]> git.saurik.com Git - wxWidgets.git/blob - src/aui/tabart.cpp
9a30baf76c720906b5b877c742f86a2d3c31fdfa
[wxWidgets.git] / src / aui / tabart.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/tabart.cpp
3 // Purpose: wxaui: wx advanced user interface - notebook-art
4 // Author: Benjamin I. Williams
5 // Modified by: Jens Lody (moved from auibook.cpp in extra file)
6 // Created: 2012-03-21
7 // RCS-ID: $Id:$
8 // Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
9 // Licence: wxWindows Library Licence, Version 3.1
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ----------------------------------------------------------------------------
13 // headers
14 // ----------------------------------------------------------------------------
15
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #if wxUSE_AUI
23
24 #ifndef WX_PRECOMP
25 #include "wx/dc.h"
26 #include "wx/dcclient.h"
27 #include "wx/settings.h"
28 #include "wx/bitmap.h"
29 #include "wx/menu.h"
30 #endif
31
32 #include "wx/renderer.h"
33 #include "wx/aui/auibook.h"
34 #include "wx/aui/framemanager.h"
35 #include "wx/aui/dockart.h"
36
37 #ifdef __WXMAC__
38 #include "wx/osx/private.h"
39 #endif
40
41
42 // -- GUI helper classes and functions --
43
44 class wxAuiCommandCapture : public wxEvtHandler
45 {
46 public:
47
48 wxAuiCommandCapture() { m_lastId = 0; }
49 int GetCommandId() const { return m_lastId; }
50
51 bool ProcessEvent(wxEvent& evt)
52 {
53 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
54 {
55 m_lastId = evt.GetId();
56 return true;
57 }
58
59 if (GetNextHandler())
60 return GetNextHandler()->ProcessEvent(evt);
61
62 return false;
63 }
64
65 private:
66 int m_lastId;
67 };
68
69
70 // these functions live in dockart.cpp -- they'll eventually
71 // be moved to a new utility cpp file
72
73 wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
74 const wxColour& color);
75
76 wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size);
77
78 static void DrawButtons(wxDC& dc,
79 const wxRect& _rect,
80 const wxBitmap& bmp,
81 const wxColour& bkcolour,
82 int button_state)
83 {
84 wxRect rect = _rect;
85
86 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
87 {
88 rect.x++;
89 rect.y++;
90 }
91
92 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
93 button_state == wxAUI_BUTTON_STATE_PRESSED)
94 {
95 dc.SetBrush(wxBrush(bkcolour.ChangeLightness(120)));
96 dc.SetPen(wxPen(bkcolour.ChangeLightness(75)));
97
98 // draw the background behind the button
99 dc.DrawRectangle(rect.x, rect.y, 15, 15);
100 }
101
102 // draw the button itself
103 dc.DrawBitmap(bmp, rect.x, rect.y, true);
104 }
105
106 static void IndentPressedBitmap(wxRect* rect, int button_state)
107 {
108 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
109 {
110 rect->x++;
111 rect->y++;
112 }
113 }
114
115 // -- bitmaps --
116
117 #if defined( __WXMAC__ )
118 static const unsigned char close_bits[]={
119 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
120 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
121 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
122 #elif defined( __WXGTK__)
123 static const unsigned char close_bits[]={
124 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
125 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
126 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
127 #else
128 static const unsigned char close_bits[]={
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
130 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
132 #endif
133
134 static const unsigned char left_bits[] = {
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
136 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
138
139 static const unsigned char right_bits[] = {
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
141 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
143
144 static const unsigned char list_bits[] = {
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
148
149
150
151
152
153
154 // -- wxAuiGenericTabArt class implementation --
155
156 wxAuiGenericTabArt::wxAuiGenericTabArt()
157 {
158 m_normalFont = *wxNORMAL_FONT;
159 m_selectedFont = *wxNORMAL_FONT;
160 m_selectedFont.SetWeight(wxBOLD);
161 m_measuringFont = m_selectedFont;
162
163 m_fixedTabWidth = 100;
164 m_tabCtrlHeight = 0;
165
166 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
167 wxColor baseColour = wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground));
168 #else
169 wxColor baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
170 #endif
171
172 // the baseColour is too pale to use as our base colour,
173 // so darken it a bit --
174 if ((255-baseColour.Red()) +
175 (255-baseColour.Green()) +
176 (255-baseColour.Blue()) < 60)
177 {
178 baseColour = baseColour.ChangeLightness(92);
179 }
180
181 m_activeColour = baseColour;
182 m_baseColour = baseColour;
183 wxColor borderColour = baseColour.ChangeLightness(75);
184
185 m_borderPen = wxPen(borderColour);
186 m_baseColourPen = wxPen(m_baseColour);
187 m_baseColourBrush = wxBrush(m_baseColour);
188
189 m_activeCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
190 m_disabledCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
191
192 m_activeLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
193 m_disabledLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
194
195 m_activeRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
196 m_disabledRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
197
198 m_activeWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
199 m_disabledWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
200
201 m_flags = 0;
202 }
203
204 wxAuiGenericTabArt::~wxAuiGenericTabArt()
205 {
206 }
207
208 wxAuiTabArt* wxAuiGenericTabArt::Clone()
209 {
210 return new wxAuiGenericTabArt(*this);
211 }
212
213 void wxAuiGenericTabArt::SetFlags(unsigned int flags)
214 {
215 m_flags = flags;
216 }
217
218 void wxAuiGenericTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
219 size_t tab_count)
220 {
221 m_fixedTabWidth = 100;
222
223 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
224
225 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
226 tot_width -= m_activeCloseBmp.GetWidth();
227 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
228 tot_width -= m_activeWindowListBmp.GetWidth();
229
230 if (tab_count > 0)
231 {
232 m_fixedTabWidth = tot_width/(int)tab_count;
233 }
234
235
236 if (m_fixedTabWidth < 100)
237 m_fixedTabWidth = 100;
238
239 if (m_fixedTabWidth > tot_width/2)
240 m_fixedTabWidth = tot_width/2;
241
242 if (m_fixedTabWidth > 220)
243 m_fixedTabWidth = 220;
244
245 m_tabCtrlHeight = tab_ctrl_size.y;
246 }
247
248
249 void wxAuiGenericTabArt::DrawBorder(wxDC& dc, wxWindow* wnd, const wxRect& rect)
250 {
251 int i, border_width = GetBorderWidth(wnd);
252
253 wxRect theRect(rect);
254 for (i = 0; i < border_width; ++i)
255 {
256 dc.DrawRectangle(theRect.x, theRect.y, theRect.width, theRect.height);
257 theRect.Deflate(1);
258 }
259 }
260
261 void wxAuiGenericTabArt::DrawBackground(wxDC& dc,
262 wxWindow* WXUNUSED(wnd),
263 const wxRect& rect)
264 {
265 // draw background
266
267 wxColor top_color = m_baseColour.ChangeLightness(90);
268 wxColor bottom_color = m_baseColour.ChangeLightness(170);
269 wxRect r;
270
271 if (m_flags &wxAUI_NB_BOTTOM)
272 r = wxRect(rect.x, rect.y, rect.width+2, rect.height);
273 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
274 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
275 else //for wxAUI_NB_TOP
276 r = wxRect(rect.x, rect.y, rect.width+2, rect.height-3);
277
278 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
279
280
281 // draw base lines
282
283 dc.SetPen(m_borderPen);
284 int y = rect.GetHeight();
285 int w = rect.GetWidth();
286
287 if (m_flags &wxAUI_NB_BOTTOM)
288 {
289 dc.SetBrush(wxBrush(bottom_color));
290 dc.DrawRectangle(-1, 0, w+2, 4);
291 }
292 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
293 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
294 else //for wxAUI_NB_TOP
295 {
296 dc.SetBrush(m_baseColourBrush);
297 dc.DrawRectangle(-1, y-4, w+2, 4);
298 }
299 }
300
301
302 // DrawTab() draws an individual tab.
303 //
304 // dc - output dc
305 // in_rect - rectangle the tab should be confined to
306 // caption - tab's caption
307 // active - whether or not the tab is active
308 // out_rect - actual output rectangle
309 // x_extent - the advance x; where the next tab should start
310
311 void wxAuiGenericTabArt::DrawTab(wxDC& dc,
312 wxWindow* wnd,
313 const wxAuiNotebookPage& page,
314 const wxRect& in_rect,
315 int close_button_state,
316 wxRect* out_tab_rect,
317 wxRect* out_button_rect,
318 int* x_extent)
319 {
320 wxCoord normal_textx, normal_texty;
321 wxCoord selected_textx, selected_texty;
322 wxCoord texty;
323
324 // if the caption is empty, measure some temporary text
325 wxString caption = page.caption;
326 if (caption.empty())
327 caption = wxT("Xj");
328
329 dc.SetFont(m_selectedFont);
330 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
331
332 dc.SetFont(m_normalFont);
333 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
334
335 // figure out the size of the tab
336 wxSize tab_size = GetTabSize(dc,
337 wnd,
338 page.caption,
339 page.bitmap,
340 page.active,
341 close_button_state,
342 x_extent);
343
344 wxCoord tab_height = m_tabCtrlHeight - 3;
345 wxCoord tab_width = tab_size.x;
346 wxCoord tab_x = in_rect.x;
347 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
348
349
350 caption = page.caption;
351
352
353 // select pen, brush and font for the tab to be drawn
354
355 if (page.active)
356 {
357 dc.SetFont(m_selectedFont);
358 texty = selected_texty;
359 }
360 else
361 {
362 dc.SetFont(m_normalFont);
363 texty = normal_texty;
364 }
365
366
367 // create points that will make the tab outline
368
369 int clip_width = tab_width;
370 if (tab_x + clip_width > in_rect.x + in_rect.width)
371 clip_width = (in_rect.x + in_rect.width) - tab_x;
372
373 /*
374 wxPoint clip_points[6];
375 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
376 clip_points[1] = wxPoint(tab_x, tab_y+2);
377 clip_points[2] = wxPoint(tab_x+2, tab_y);
378 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
379 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
380 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
381
382 // FIXME: these ports don't provide wxRegion ctor from array of points
383 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
384 // set the clipping region for the tab --
385 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
386 dc.SetClippingRegion(clipping_region);
387 #endif // !wxDFB && !wxCocoa
388 */
389 // since the above code above doesn't play well with WXDFB or WXCOCOA,
390 // we'll just use a rectangle for the clipping region for now --
391 dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3);
392
393
394 wxPoint border_points[6];
395 if (m_flags &wxAUI_NB_BOTTOM)
396 {
397 border_points[0] = wxPoint(tab_x, tab_y);
398 border_points[1] = wxPoint(tab_x, tab_y+tab_height-6);
399 border_points[2] = wxPoint(tab_x+2, tab_y+tab_height-4);
400 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y+tab_height-4);
401 border_points[4] = wxPoint(tab_x+tab_width, tab_y+tab_height-6);
402 border_points[5] = wxPoint(tab_x+tab_width, tab_y);
403 }
404 else //if (m_flags & wxAUI_NB_TOP) {}
405 {
406 border_points[0] = wxPoint(tab_x, tab_y+tab_height-4);
407 border_points[1] = wxPoint(tab_x, tab_y+2);
408 border_points[2] = wxPoint(tab_x+2, tab_y);
409 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y);
410 border_points[4] = wxPoint(tab_x+tab_width, tab_y+2);
411 border_points[5] = wxPoint(tab_x+tab_width, tab_y+tab_height-4);
412 }
413 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
414 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
415
416 int drawn_tab_yoff = border_points[1].y;
417 int drawn_tab_height = border_points[0].y - border_points[1].y;
418
419
420 if (page.active)
421 {
422 // draw active tab
423
424 // draw base background color
425 wxRect r(tab_x, tab_y, tab_width, tab_height);
426 dc.SetPen(wxPen(m_activeColour));
427 dc.SetBrush(wxBrush(m_activeColour));
428 dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4);
429
430 // this white helps fill out the gradient at the top of the tab
431 dc.SetPen(*wxWHITE_PEN);
432 dc.SetBrush(*wxWHITE_BRUSH);
433 dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4);
434
435 // these two points help the rounded corners appear more antialiased
436 dc.SetPen(wxPen(m_activeColour));
437 dc.DrawPoint(r.x+2, r.y+1);
438 dc.DrawPoint(r.x+r.width-2, r.y+1);
439
440 // set rectangle down a bit for gradient drawing
441 r.SetHeight(r.GetHeight()/2);
442 r.x += 2;
443 r.width -= 3;
444 r.y += r.height;
445 r.y -= 2;
446
447 // draw gradient background
448 wxColor top_color = *wxWHITE;
449 wxColor bottom_color = m_activeColour;
450 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
451 }
452 else
453 {
454 // draw inactive tab
455
456 wxRect r(tab_x, tab_y+1, tab_width, tab_height-3);
457
458 // start the gradent up a bit and leave the inside border inset
459 // by a pixel for a 3D look. Only the top half of the inactive
460 // tab will have a slight gradient
461 r.x += 3;
462 r.y++;
463 r.width -= 4;
464 r.height /= 2;
465 r.height--;
466
467 // -- draw top gradient fill for glossy look
468 wxColor top_color = m_baseColour;
469 wxColor bottom_color = top_color.ChangeLightness(160);
470 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
471
472 r.y += r.height;
473 r.y--;
474
475 // -- draw bottom fill for glossy look
476 top_color = m_baseColour;
477 bottom_color = m_baseColour;
478 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
479 }
480
481 // draw tab outline
482 dc.SetPen(m_borderPen);
483 dc.SetBrush(*wxTRANSPARENT_BRUSH);
484 dc.DrawPolygon(WXSIZEOF(border_points), border_points);
485
486 // there are two horizontal grey lines at the bottom of the tab control,
487 // this gets rid of the top one of those lines in the tab control
488 if (page.active)
489 {
490 if (m_flags &wxAUI_NB_BOTTOM)
491 dc.SetPen(wxPen(m_baseColour.ChangeLightness(170)));
492 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
493 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
494 else //for wxAUI_NB_TOP
495 dc.SetPen(m_baseColourPen);
496 dc.DrawLine(border_points[0].x+1,
497 border_points[0].y,
498 border_points[5].x,
499 border_points[5].y);
500 }
501
502
503 int text_offset = tab_x + 8;
504 int close_button_width = 0;
505 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
506 {
507 close_button_width = m_activeCloseBmp.GetWidth();
508 }
509
510 int bitmap_offset = 0;
511 if (page.bitmap.IsOk())
512 {
513 bitmap_offset = tab_x + 8;
514
515 // draw bitmap
516 dc.DrawBitmap(page.bitmap,
517 bitmap_offset,
518 drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
519 true);
520
521 text_offset = bitmap_offset + page.bitmap.GetWidth();
522 text_offset += 3; // bitmap padding
523
524 }
525 else
526 {
527 text_offset = tab_x + 8;
528 }
529
530
531 wxString draw_text = wxAuiChopText(dc,
532 caption,
533 tab_width - (text_offset-tab_x) - close_button_width);
534
535 // draw tab text
536 dc.DrawText(draw_text,
537 text_offset,
538 drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);
539
540 // draw focus rectangle
541 if (page.active && (wnd->FindFocus() == wnd))
542 {
543 wxRect focusRectText(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1),
544 selected_textx, selected_texty);
545
546 wxRect focusRect;
547 wxRect focusRectBitmap;
548
549 if (page.bitmap.IsOk())
550 focusRectBitmap = wxRect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
551 page.bitmap.GetWidth(), page.bitmap.GetHeight());
552
553 if (page.bitmap.IsOk() && draw_text.IsEmpty())
554 focusRect = focusRectBitmap;
555 else if (!page.bitmap.IsOk() && !draw_text.IsEmpty())
556 focusRect = focusRectText;
557 else if (page.bitmap.IsOk() && !draw_text.IsEmpty())
558 focusRect = focusRectText.Union(focusRectBitmap);
559
560 focusRect.Inflate(2, 2);
561
562 wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
563 }
564
565 // draw close button if necessary
566 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
567 {
568 wxBitmap bmp = m_disabledCloseBmp;
569
570 if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
571 close_button_state == wxAUI_BUTTON_STATE_PRESSED)
572 {
573 bmp = m_activeCloseBmp;
574 }
575
576 int offsetY = tab_y-1;
577 if (m_flags & wxAUI_NB_BOTTOM)
578 offsetY = 1;
579
580 wxRect rect(tab_x + tab_width - close_button_width - 1,
581 offsetY + (tab_height/2) - (bmp.GetHeight()/2),
582 close_button_width,
583 tab_height);
584
585 IndentPressedBitmap(&rect, close_button_state);
586 dc.DrawBitmap(bmp, rect.x, rect.y, true);
587
588 *out_button_rect = rect;
589 }
590
591 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
592
593 dc.DestroyClippingRegion();
594 }
595
596 int wxAuiGenericTabArt::GetIndentSize()
597 {
598 return 5;
599 }
600
601 int wxAuiGenericTabArt::GetBorderWidth(wxWindow* wnd)
602 {
603 wxAuiManager* mgr = wxAuiManager::GetManager(wnd);
604 if (mgr)
605 {
606 wxAuiDockArt* art = mgr->GetArtProvider();
607 if (art)
608 return art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
609 }
610 return 1;
611 }
612
613 int wxAuiGenericTabArt::GetAdditionalBorderSpace(wxWindow* WXUNUSED(wnd))
614 {
615 return 0;
616 }
617
618 wxSize wxAuiGenericTabArt::GetTabSize(wxDC& dc,
619 wxWindow* WXUNUSED(wnd),
620 const wxString& caption,
621 const wxBitmap& bitmap,
622 bool WXUNUSED(active),
623 int close_button_state,
624 int* x_extent)
625 {
626 wxCoord measured_textx, measured_texty, tmp;
627
628 dc.SetFont(m_measuringFont);
629 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
630
631 dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
632
633 // add padding around the text
634 wxCoord tab_width = measured_textx;
635 wxCoord tab_height = measured_texty;
636
637 // if the close button is showing, add space for it
638 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
639 tab_width += m_activeCloseBmp.GetWidth() + 3;
640
641 // if there's a bitmap, add space for it
642 if (bitmap.IsOk())
643 {
644 tab_width += bitmap.GetWidth();
645 tab_width += 3; // right side bitmap padding
646 tab_height = wxMax(tab_height, bitmap.GetHeight());
647 }
648
649 // add padding
650 tab_width += 16;
651 tab_height += 10;
652
653 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
654 {
655 tab_width = m_fixedTabWidth;
656 }
657
658 *x_extent = tab_width;
659
660 return wxSize(tab_width, tab_height);
661 }
662
663
664 void wxAuiGenericTabArt::DrawButton(wxDC& dc,
665 wxWindow* WXUNUSED(wnd),
666 const wxRect& in_rect,
667 int bitmap_id,
668 int button_state,
669 int orientation,
670 wxRect* out_rect)
671 {
672 wxBitmap bmp;
673 wxRect rect;
674
675 switch (bitmap_id)
676 {
677 case wxAUI_BUTTON_CLOSE:
678 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
679 bmp = m_disabledCloseBmp;
680 else
681 bmp = m_activeCloseBmp;
682 break;
683 case wxAUI_BUTTON_LEFT:
684 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
685 bmp = m_disabledLeftBmp;
686 else
687 bmp = m_activeLeftBmp;
688 break;
689 case wxAUI_BUTTON_RIGHT:
690 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
691 bmp = m_disabledRightBmp;
692 else
693 bmp = m_activeRightBmp;
694 break;
695 case wxAUI_BUTTON_WINDOWLIST:
696 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
697 bmp = m_disabledWindowListBmp;
698 else
699 bmp = m_activeWindowListBmp;
700 break;
701 }
702
703
704 if (!bmp.IsOk())
705 return;
706
707 rect = in_rect;
708
709 if (orientation == wxLEFT)
710 {
711 rect.SetX(in_rect.x);
712 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
713 rect.SetWidth(bmp.GetWidth());
714 rect.SetHeight(bmp.GetHeight());
715 }
716 else
717 {
718 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
719 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
720 bmp.GetWidth(), bmp.GetHeight());
721 }
722
723 IndentPressedBitmap(&rect, button_state);
724 dc.DrawBitmap(bmp, rect.x, rect.y, true);
725
726 *out_rect = rect;
727 }
728
729 int wxAuiGenericTabArt::ShowDropDown(wxWindow* wnd,
730 const wxAuiNotebookPageArray& pages,
731 int /*active_idx*/)
732 {
733 wxMenu menuPopup;
734
735 size_t i, count = pages.GetCount();
736 for (i = 0; i < count; ++i)
737 {
738 const wxAuiNotebookPage& page = pages.Item(i);
739 wxString caption = page.caption;
740
741 // if there is no caption, make it a space. This will prevent
742 // an assert in the menu code.
743 if (caption.IsEmpty())
744 caption = wxT(" ");
745
746 wxMenuItem* item = new wxMenuItem(NULL, 1000+i, caption);
747 if (page.bitmap.IsOk())
748 item->SetBitmap(page.bitmap);
749 menuPopup.Append(item);
750 }
751
752 // find out where to put the popup menu of window items
753 wxPoint pt = ::wxGetMousePosition();
754 pt = wnd->ScreenToClient(pt);
755
756 // find out the screen coordinate at the bottom of the tab ctrl
757 wxRect cli_rect = wnd->GetClientRect();
758 pt.y = cli_rect.y + cli_rect.height;
759
760 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
761 wnd->PushEventHandler(cc);
762 wnd->PopupMenu(&menuPopup, pt);
763 int command = cc->GetCommandId();
764 wnd->PopEventHandler(true);
765
766 if (command >= 1000)
767 return command-1000;
768
769 return -1;
770 }
771
772 int wxAuiGenericTabArt::GetBestTabCtrlSize(wxWindow* wnd,
773 const wxAuiNotebookPageArray& pages,
774 const wxSize& requiredBmp_size)
775 {
776 wxClientDC dc(wnd);
777 dc.SetFont(m_measuringFont);
778
779 // sometimes a standard bitmap size needs to be enforced, especially
780 // if some tabs have bitmaps and others don't. This is important because
781 // it prevents the tab control from resizing when tabs are added.
782 wxBitmap measureBmp;
783 if (requiredBmp_size.IsFullySpecified())
784 {
785 measureBmp.Create(requiredBmp_size.x,
786 requiredBmp_size.y);
787 }
788
789
790 int max_y = 0;
791 size_t i, page_count = pages.GetCount();
792 for (i = 0; i < page_count; ++i)
793 {
794 wxAuiNotebookPage& page = pages.Item(i);
795
796 wxBitmap bmp;
797 if (measureBmp.IsOk())
798 bmp = measureBmp;
799 else
800 bmp = page.bitmap;
801
802 // we don't use the caption text because we don't
803 // want tab heights to be different in the case
804 // of a very short piece of text on one tab and a very
805 // tall piece of text on another tab
806 int x_ext = 0;
807 wxSize s = GetTabSize(dc,
808 wnd,
809 wxT("ABCDEFGHIj"),
810 bmp,
811 true,
812 wxAUI_BUTTON_STATE_HIDDEN,
813 &x_ext);
814
815 max_y = wxMax(max_y, s.y);
816 }
817
818 return max_y+2;
819 }
820
821 void wxAuiGenericTabArt::SetNormalFont(const wxFont& font)
822 {
823 m_normalFont = font;
824 }
825
826 void wxAuiGenericTabArt::SetSelectedFont(const wxFont& font)
827 {
828 m_selectedFont = font;
829 }
830
831 void wxAuiGenericTabArt::SetMeasuringFont(const wxFont& font)
832 {
833 m_measuringFont = font;
834 }
835
836 void wxAuiGenericTabArt::SetColour(const wxColour& colour)
837 {
838 m_baseColour = colour;
839 m_borderPen = wxPen(m_baseColour.ChangeLightness(75));
840 m_baseColourPen = wxPen(m_baseColour);
841 m_baseColourBrush = wxBrush(m_baseColour);
842 }
843
844 void wxAuiGenericTabArt::SetActiveColour(const wxColour& colour)
845 {
846 m_activeColour = colour;
847 }
848
849 // -- wxAuiSimpleTabArt class implementation --
850
851 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
852 {
853 m_normalFont = *wxNORMAL_FONT;
854 m_selectedFont = *wxNORMAL_FONT;
855 m_selectedFont.SetWeight(wxBOLD);
856 m_measuringFont = m_selectedFont;
857
858 m_flags = 0;
859 m_fixedTabWidth = 100;
860
861 wxColour baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
862
863 wxColour backgroundColour = baseColour;
864 wxColour normaltabColour = baseColour;
865 wxColour selectedtabColour = *wxWHITE;
866
867 m_bkBrush = wxBrush(backgroundColour);
868 m_normalBkBrush = wxBrush(normaltabColour);
869 m_normalBkPen = wxPen(normaltabColour);
870 m_selectedBkBrush = wxBrush(selectedtabColour);
871 m_selectedBkPen = wxPen(selectedtabColour);
872
873 m_activeCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
874 m_disabledCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
875
876 m_activeLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
877 m_disabledLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
878
879 m_activeRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
880 m_disabledRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
881
882 m_activeWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
883 m_disabledWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
884
885 }
886
887 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
888 {
889 }
890
891 wxAuiTabArt* wxAuiSimpleTabArt::Clone()
892 {
893 return new wxAuiSimpleTabArt(*this);
894 }
895
896 void wxAuiSimpleTabArt::SetFlags(unsigned int flags)
897 {
898 m_flags = flags;
899 }
900
901 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
902 size_t tab_count)
903 {
904 m_fixedTabWidth = 100;
905
906 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
907
908 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
909 tot_width -= m_activeCloseBmp.GetWidth();
910 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
911 tot_width -= m_activeWindowListBmp.GetWidth();
912
913 if (tab_count > 0)
914 {
915 m_fixedTabWidth = tot_width/(int)tab_count;
916 }
917
918
919 if (m_fixedTabWidth < 100)
920 m_fixedTabWidth = 100;
921
922 if (m_fixedTabWidth > tot_width/2)
923 m_fixedTabWidth = tot_width/2;
924
925 if (m_fixedTabWidth > 220)
926 m_fixedTabWidth = 220;
927 }
928
929 void wxAuiSimpleTabArt::SetColour(const wxColour& colour)
930 {
931 m_bkBrush = wxBrush(colour);
932 m_normalBkBrush = wxBrush(colour);
933 m_normalBkPen = wxPen(colour);
934 }
935
936 void wxAuiSimpleTabArt::SetActiveColour(const wxColour& colour)
937 {
938 m_selectedBkBrush = wxBrush(colour);
939 m_selectedBkPen = wxPen(colour);
940 }
941
942 void wxAuiSimpleTabArt::DrawBorder(wxDC& dc, wxWindow* wnd, const wxRect& rect)
943 {
944 int i, border_width = GetBorderWidth(wnd);
945
946 wxRect theRect(rect);
947 for (i = 0; i < border_width; ++i)
948 {
949 dc.DrawRectangle(theRect.x, theRect.y, theRect.width, theRect.height);
950 theRect.Deflate(1);
951 }
952 }
953
954 void wxAuiSimpleTabArt::DrawBackground(wxDC& dc,
955 wxWindow* WXUNUSED(wnd),
956 const wxRect& rect)
957 {
958 // draw background
959 dc.SetBrush(m_bkBrush);
960 dc.SetPen(*wxTRANSPARENT_PEN);
961 dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
962
963 // draw base line
964 dc.SetPen(*wxGREY_PEN);
965 dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
966 }
967
968
969 // DrawTab() draws an individual tab.
970 //
971 // dc - output dc
972 // in_rect - rectangle the tab should be confined to
973 // caption - tab's caption
974 // active - whether or not the tab is active
975 // out_rect - actual output rectangle
976 // x_extent - the advance x; where the next tab should start
977
978 void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
979 wxWindow* wnd,
980 const wxAuiNotebookPage& page,
981 const wxRect& in_rect,
982 int close_button_state,
983 wxRect* out_tab_rect,
984 wxRect* out_button_rect,
985 int* x_extent)
986 {
987 wxCoord normal_textx, normal_texty;
988 wxCoord selected_textx, selected_texty;
989 wxCoord textx, texty;
990
991 // if the caption is empty, measure some temporary text
992 wxString caption = page.caption;
993 if (caption.empty())
994 caption = wxT("Xj");
995
996 dc.SetFont(m_selectedFont);
997 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
998
999 dc.SetFont(m_normalFont);
1000 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
1001
1002 // figure out the size of the tab
1003 wxSize tab_size = GetTabSize(dc,
1004 wnd,
1005 page.caption,
1006 page.bitmap,
1007 page.active,
1008 close_button_state,
1009 x_extent);
1010
1011 wxCoord tab_height = tab_size.y;
1012 wxCoord tab_width = tab_size.x;
1013 wxCoord tab_x = in_rect.x;
1014 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
1015
1016 caption = page.caption;
1017
1018 // select pen, brush and font for the tab to be drawn
1019
1020 if (page.active)
1021 {
1022 dc.SetPen(m_selectedBkPen);
1023 dc.SetBrush(m_selectedBkBrush);
1024 dc.SetFont(m_selectedFont);
1025 textx = selected_textx;
1026 texty = selected_texty;
1027 }
1028 else
1029 {
1030 dc.SetPen(m_normalBkPen);
1031 dc.SetBrush(m_normalBkBrush);
1032 dc.SetFont(m_normalFont);
1033 textx = normal_textx;
1034 texty = normal_texty;
1035 }
1036
1037
1038 // -- draw line --
1039
1040 wxPoint points[7];
1041 points[0].x = tab_x;
1042 points[0].y = tab_y + tab_height - 1;
1043 points[1].x = tab_x + tab_height - 3;
1044 points[1].y = tab_y + 2;
1045 points[2].x = tab_x + tab_height + 3;
1046 points[2].y = tab_y;
1047 points[3].x = tab_x + tab_width - 2;
1048 points[3].y = tab_y;
1049 points[4].x = tab_x + tab_width;
1050 points[4].y = tab_y + 2;
1051 points[5].x = tab_x + tab_width;
1052 points[5].y = tab_y + tab_height - 1;
1053 points[6] = points[0];
1054
1055 dc.SetClippingRegion(in_rect);
1056
1057 dc.DrawPolygon(WXSIZEOF(points) - 1, points);
1058
1059 dc.SetPen(*wxGREY_PEN);
1060
1061 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1062 dc.DrawLines(WXSIZEOF(points), points);
1063
1064
1065 int text_offset;
1066
1067 int close_button_width = 0;
1068 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1069 {
1070 close_button_width = m_activeCloseBmp.GetWidth();
1071 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
1072 }
1073 else
1074 {
1075 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
1076 }
1077
1078 // set minimum text offset
1079 if (text_offset < tab_x + tab_height)
1080 text_offset = tab_x + tab_height;
1081
1082 // chop text if necessary
1083 wxString draw_text = wxAuiChopText(dc,
1084 caption,
1085 tab_width - (text_offset-tab_x) - close_button_width);
1086
1087 // draw tab text
1088 dc.DrawText(draw_text,
1089 text_offset,
1090 (tab_y + tab_height)/2 - (texty/2) + 1);
1091
1092
1093 // draw focus rectangle
1094 if (page.active && (wnd->FindFocus() == wnd))
1095 {
1096 wxRect focusRect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1),
1097 selected_textx, selected_texty);
1098
1099 focusRect.Inflate(2, 2);
1100
1101 wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
1102 }
1103
1104 // draw close button if necessary
1105 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1106 {
1107 wxBitmap bmp;
1108 if (page.active)
1109 bmp = m_activeCloseBmp;
1110 else
1111 bmp = m_disabledCloseBmp;
1112
1113 wxRect rect(tab_x + tab_width - close_button_width - 1,
1114 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
1115 close_button_width,
1116 tab_height - 1);
1117 DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state);
1118
1119 *out_button_rect = rect;
1120 }
1121
1122
1123 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
1124
1125 dc.DestroyClippingRegion();
1126 }
1127
1128 int wxAuiSimpleTabArt::GetIndentSize()
1129 {
1130 return 0;
1131 }
1132
1133 int wxAuiSimpleTabArt::GetBorderWidth(wxWindow* wnd)
1134 {
1135 wxAuiManager* mgr = wxAuiManager::GetManager(wnd);
1136 if (mgr)
1137 {
1138 wxAuiDockArt* art = mgr->GetArtProvider();
1139 if (art)
1140 return art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
1141 }
1142 return 1;
1143 }
1144
1145 int wxAuiSimpleTabArt::GetAdditionalBorderSpace(wxWindow* WXUNUSED(wnd))
1146 {
1147 return 0;
1148 }
1149
1150 wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
1151 wxWindow* WXUNUSED(wnd),
1152 const wxString& caption,
1153 const wxBitmap& WXUNUSED(bitmap),
1154 bool WXUNUSED(active),
1155 int close_button_state,
1156 int* x_extent)
1157 {
1158 wxCoord measured_textx, measured_texty;
1159
1160 dc.SetFont(m_measuringFont);
1161 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
1162
1163 wxCoord tab_height = measured_texty + 4;
1164 wxCoord tab_width = measured_textx + tab_height + 5;
1165
1166 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1167 tab_width += m_activeCloseBmp.GetWidth();
1168
1169 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
1170 {
1171 tab_width = m_fixedTabWidth;
1172 }
1173
1174 *x_extent = tab_width - (tab_height/2) - 1;
1175
1176 return wxSize(tab_width, tab_height);
1177 }
1178
1179
1180 void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
1181 wxWindow* WXUNUSED(wnd),
1182 const wxRect& in_rect,
1183 int bitmap_id,
1184 int button_state,
1185 int orientation,
1186 wxRect* out_rect)
1187 {
1188 wxBitmap bmp;
1189 wxRect rect;
1190
1191 switch (bitmap_id)
1192 {
1193 case wxAUI_BUTTON_CLOSE:
1194 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1195 bmp = m_disabledCloseBmp;
1196 else
1197 bmp = m_activeCloseBmp;
1198 break;
1199 case wxAUI_BUTTON_LEFT:
1200 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1201 bmp = m_disabledLeftBmp;
1202 else
1203 bmp = m_activeLeftBmp;
1204 break;
1205 case wxAUI_BUTTON_RIGHT:
1206 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1207 bmp = m_disabledRightBmp;
1208 else
1209 bmp = m_activeRightBmp;
1210 break;
1211 case wxAUI_BUTTON_WINDOWLIST:
1212 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1213 bmp = m_disabledWindowListBmp;
1214 else
1215 bmp = m_activeWindowListBmp;
1216 break;
1217 }
1218
1219 if (!bmp.IsOk())
1220 return;
1221
1222 rect = in_rect;
1223
1224 if (orientation == wxLEFT)
1225 {
1226 rect.SetX(in_rect.x);
1227 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
1228 rect.SetWidth(bmp.GetWidth());
1229 rect.SetHeight(bmp.GetHeight());
1230 }
1231 else
1232 {
1233 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
1234 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
1235 bmp.GetWidth(), bmp.GetHeight());
1236 }
1237
1238
1239 DrawButtons(dc, rect, bmp, *wxWHITE, button_state);
1240
1241 *out_rect = rect;
1242 }
1243
1244 int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd,
1245 const wxAuiNotebookPageArray& pages,
1246 int active_idx)
1247 {
1248 wxMenu menuPopup;
1249
1250 size_t i, count = pages.GetCount();
1251 for (i = 0; i < count; ++i)
1252 {
1253 const wxAuiNotebookPage& page = pages.Item(i);
1254 menuPopup.AppendCheckItem(1000+i, page.caption);
1255 }
1256
1257 if (active_idx != -1)
1258 {
1259 menuPopup.Check(1000+active_idx, true);
1260 }
1261
1262 // find out where to put the popup menu of window
1263 // items. Subtract 100 for now to center the menu
1264 // a bit, until a better mechanism can be implemented
1265 wxPoint pt = ::wxGetMousePosition();
1266 pt = wnd->ScreenToClient(pt);
1267 if (pt.x < 100)
1268 pt.x = 0;
1269 else
1270 pt.x -= 100;
1271
1272 // find out the screen coordinate at the bottom of the tab ctrl
1273 wxRect cli_rect = wnd->GetClientRect();
1274 pt.y = cli_rect.y + cli_rect.height;
1275
1276 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
1277 wnd->PushEventHandler(cc);
1278 wnd->PopupMenu(&menuPopup, pt);
1279 int command = cc->GetCommandId();
1280 wnd->PopEventHandler(true);
1281
1282 if (command >= 1000)
1283 return command-1000;
1284
1285 return -1;
1286 }
1287
1288 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd,
1289 const wxAuiNotebookPageArray& WXUNUSED(pages),
1290 const wxSize& WXUNUSED(requiredBmp_size))
1291 {
1292 wxClientDC dc(wnd);
1293 dc.SetFont(m_measuringFont);
1294 int x_ext = 0;
1295 wxSize s = GetTabSize(dc,
1296 wnd,
1297 wxT("ABCDEFGHIj"),
1298 wxNullBitmap,
1299 true,
1300 wxAUI_BUTTON_STATE_HIDDEN,
1301 &x_ext);
1302 return s.y+3;
1303 }
1304
1305 void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font)
1306 {
1307 m_normalFont = font;
1308 }
1309
1310 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font)
1311 {
1312 m_selectedFont = font;
1313 }
1314
1315 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font)
1316 {
1317 m_measuringFont = font;
1318 }
1319
1320 #endif // wxUSE_AUI