1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/auibook.cpp
3 // Purpose: wxaui: wx advanced user interface - notebook
4 // Author: Benjamin I. Williams
5 // Modified by:
6 // Created: 2006-06-28
7 // Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
8 // Licence: wxWindows Library Licence, Version 3.1
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ----------------------------------------------------------------------------
12 // headers
13 // ----------------------------------------------------------------------------
14
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #if wxUSE_AUI
22
23 #include "wx/aui/auibook.h"
24
25 #ifndef WX_PRECOMP
26 #include "wx/settings.h"
27 #include "wx/image.h"
28 #include "wx/menu.h"
29 #endif
30
31 #include "wx/aui/tabmdi.h"
32 #include "wx/dcbuffer.h"
33 #include "wx/log.h"
34
35 #ifdef __WXMSW__
36 #include "wx/msw/private.h"
37 #endif
38
39 #ifdef __WXMAC__
40 #include "wx/mac/carbon/private.h"
41 #endif
42
43 #ifdef __WXGTK__
44 #include <gtk/gtk.h>
45 #include "wx/gtk/win_gtk.h"
46 #endif
47
48 #include "wx/arrimpl.cpp"
49 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
50 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
51
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
57 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
58 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
59 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
60 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND)
61 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK)
62 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE)
63 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP)
64 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN)
65 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP)
66 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN)
67
68
69 IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
70 IMPLEMENT_CLASS(wxAuiTabCtrl, wxControl)
71 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
72
73
74
75
76 // these functions live in dockart.cpp -- they'll eventually
77 // be moved to a new utility cpp file
78
79 wxColor wxAuiStepColour(const wxColor& c, int percent);
80
81 wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
82 const wxColour& color);
83
84 wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size);
85
DrawButtons(wxDC & dc,const wxRect & _rect,const wxBitmap & bmp,const wxColour & bkcolour,int button_state)86 static void DrawButtons(wxDC& dc,
87 const wxRect& _rect,
88 const wxBitmap& bmp,
89 const wxColour& bkcolour,
90 int button_state)
91 {
92 wxRect rect = _rect;
93
94 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
95 {
96 rect.x++;
97 rect.y++;
98 }
99
100 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
101 button_state == wxAUI_BUTTON_STATE_PRESSED)
102 {
103 dc.SetBrush(wxBrush(wxAuiStepColour(bkcolour, 120)));
104 dc.SetPen(wxPen(wxAuiStepColour(bkcolour, 75)));
105
106 // draw the background behind the button
107 dc.DrawRectangle(rect.x, rect.y, 15, 15);
108 }
109
110 // draw the button itself
111 dc.DrawBitmap(bmp, rect.x, rect.y, true);
112 }
113
IndentPressedBitmap(wxRect * rect,int button_state)114 static void IndentPressedBitmap(wxRect* rect, int button_state)
115 {
116 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
117 {
118 rect->x++;
119 rect->y++;
120 }
121 }
122
DrawFocusRect(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)123 static void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
124 {
125 #ifdef __WXMSW__
126 wxUnusedVar(win);
127 wxUnusedVar(flags);
128
129 RECT rc;
130 wxCopyRectToRECT(rect, rc);
131
132 ::DrawFocusRect(GetHdcOf(dc), &rc);
133
134 #elif defined(__WXGTK20__)
135 GdkWindow* gdk_window = dc.GetGDKWindow();
136 wxASSERT_MSG( gdk_window,
137 wxT("cannot draw focus rectangle on wxDC of this type") );
138
139 GtkStateType state;
140 //if (flags & wxCONTROL_SELECTED)
141 // state = GTK_STATE_SELECTED;
142 //else
143 state = GTK_STATE_NORMAL;
144
145 gtk_paint_focus( win->m_widget->style,
146 gdk_window,
147 state,
148 NULL,
149 win->m_wxwindow,
150 NULL,
151 dc.LogicalToDeviceX(rect.x),
152 dc.LogicalToDeviceY(rect.y),
153 rect.width,
154 rect.height );
155 #elif (defined(__WXMAC__))
156
157 #if wxMAC_USE_CORE_GRAPHICS
158 {
159 CGRect cgrect = CGRectMake( rect.x , rect.y , rect.width, rect.height ) ;
160
161 #if 0
162 Rect bounds ;
163 win->GetPeer()->GetRect( &bounds ) ;
164
165 wxLogDebug(wxT("Focus rect %d, %d, %d, %d"), rect.x, rect.y, rect.width, rect.height);
166 wxLogDebug(wxT("Peer rect %d, %d, %d, %d"), bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
167 #endif
168
169 HIThemeFrameDrawInfo info ;
170 memset( &info, 0 , sizeof(info) ) ;
171
172 info.version = 0 ;
173 info.kind = 0 ;
174 info.state = kThemeStateActive;
175 info.isFocused = true ;
176
177 CGContextRef cgContext = (CGContextRef) win->MacGetCGContextRef() ;
178 wxASSERT( cgContext ) ;
179
180 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
181 }
182 #else
183 {
184 Rect r;
185 r.left = rect.x; r.top = rect.y; r.right = rect.GetRight(); r.bottom = rect.GetBottom();
186 wxTopLevelWindowMac* top = win->MacGetTopLevelWindow();
187 if ( top )
188 {
189 wxPoint pt(0, 0) ;
190 wxMacControl::Convert( &pt , win->GetPeer() , top->GetPeer() ) ;
191 OffsetRect( &r , pt.x , pt.y ) ;
192 }
193
194 DrawThemeFocusRect( &r , true ) ;
195 }
196 #endif
197 #else
198 wxUnusedVar(win);
199 wxUnusedVar(flags);
200
201 // draw the pixels manually because the "dots" in wxPen with wxDOT style
202 // may be short traits and not really dots
203 //
204 // note that to behave in the same manner as DrawRect(), we must exclude
205 // the bottom and right borders from the rectangle
206 wxCoord x1 = rect.GetLeft(),
207 y1 = rect.GetTop(),
208 x2 = rect.GetRight(),
209 y2 = rect.GetBottom();
210
211 dc.SetPen(*wxBLACK_PEN);
212
213 #ifdef __WXMAC__
214 dc.SetLogicalFunction(wxCOPY);
215 #else
216 // this seems to be closer than what Windows does than wxINVERT although
217 // I'm still not sure if it's correct
218 dc.SetLogicalFunction(wxAND_REVERSE);
219 #endif
220
221 wxCoord z;
222 for ( z = x1 + 1; z < x2; z += 2 )
223 dc.DrawPoint(z, rect.GetTop());
224
225 wxCoord shift = z == x2 ? 0 : 1;
226 for ( z = y1 + shift; z < y2; z += 2 )
227 dc.DrawPoint(x2, z);
228
229 shift = z == y2 ? 0 : 1;
230 for ( z = x2 - shift; z > x1; z -= 2 )
231 dc.DrawPoint(z, y2);
232
233 shift = z == x1 ? 0 : 1;
234 for ( z = y2 - shift; z > y1; z -= 2 )
235 dc.DrawPoint(x1, z);
236
237 dc.SetLogicalFunction(wxCOPY);
238 #endif
239 }
240
241
242 // -- GUI helper classes and functions --
243
244 class wxAuiCommandCapture : public wxEvtHandler
245 {
246 public:
247
wxAuiCommandCapture()248 wxAuiCommandCapture() { m_last_id = 0; }
GetCommandId() const249 int GetCommandId() const { return m_last_id; }
250
ProcessEvent(wxEvent & evt)251 bool ProcessEvent(wxEvent& evt)
252 {
253 if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED)
254 {
255 m_last_id = evt.GetId();
256 return true;
257 }
258
259 if (GetNextHandler())
260 return GetNextHandler()->ProcessEvent(evt);
261
262 return false;
263 }
264
265 private:
266 int m_last_id;
267 };
268
269
270 // -- bitmaps --
271
272 #if defined( __WXMAC__ )
273 static unsigned char close_bits[]={
274 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
275 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
276 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
277 #elif defined( __WXGTK__)
278 static unsigned char close_bits[]={
279 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
280 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
281 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
282 #else
283 static unsigned char close_bits[]={
284 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
285 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
286 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
287 #endif
288
289 static unsigned char left_bits[] = {
290 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
291 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
292 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
293
294 static unsigned char right_bits[] = {
295 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
296 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
297 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
298
299 static unsigned char list_bits[] = {
300 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
301 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
302 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
303
304
305
306
307
308
309 // -- wxAuiDefaultTabArt class implementation --
310
wxAuiDefaultTabArt()311 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
312 {
313 m_normal_font = *wxNORMAL_FONT;
314 m_selected_font = *wxNORMAL_FONT;
315 m_selected_font.SetWeight(wxBOLD);
316 m_measuring_font = m_selected_font;
317
318 m_fixed_tab_width = 100;
319 m_tab_ctrl_height = 0;
320
321 #ifdef __WXMAC__
322 wxBrush toolbarbrush;
323 toolbarbrush.MacSetTheme( kThemeBrushToolbarBackground );
324 wxColor base_colour = toolbarbrush.GetColour();
325 #else
326 wxColor base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
327 #endif
328
329 // the base_colour is too pale to use as our base colour,
330 // so darken it a bit --
331 if ((255-base_colour.Red()) +
332 (255-base_colour.Green()) +
333 (255-base_colour.Blue()) < 60)
334 {
335 base_colour = wxAuiStepColour(base_colour, 92);
336 }
337
338 m_base_colour = base_colour;
339 wxColor border_colour = wxAuiStepColour(base_colour, 75);
340
341 m_border_pen = wxPen(border_colour);
342 m_base_colour_pen = wxPen(m_base_colour);
343 m_base_colour_brush = wxBrush(m_base_colour);
344
345 m_active_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
346 m_disabled_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
347
348 m_active_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
349 m_disabled_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
350
351 m_active_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
352 m_disabled_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
353
354 m_active_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
355 m_disabled_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
356
357 m_flags = 0;
358 }
359
~wxAuiDefaultTabArt()360 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
361 {
362 }
363
Clone()364 wxAuiTabArt* wxAuiDefaultTabArt::Clone()
365 {
366 wxAuiDefaultTabArt* art = new wxAuiDefaultTabArt;
367 art->SetNormalFont(m_normal_font);
368 art->SetSelectedFont(m_selected_font);
369 art->SetMeasuringFont(m_measuring_font);
370
371 return art;
372 }
373
SetFlags(unsigned int flags)374 void wxAuiDefaultTabArt::SetFlags(unsigned int flags)
375 {
376 m_flags = flags;
377 }
378
SetSizingInfo(const wxSize & tab_ctrl_size,size_t tab_count)379 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
380 size_t tab_count)
381 {
382 m_fixed_tab_width = 100;
383
384 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
385
386 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
387 tot_width -= m_active_close_bmp.GetWidth();
388 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
389 tot_width -= m_active_windowlist_bmp.GetWidth();
390
391 if (tab_count > 0)
392 {
393 m_fixed_tab_width = tot_width/(int)tab_count;
394 }
395
396
397 if (m_fixed_tab_width < 100)
398 m_fixed_tab_width = 100;
399
400 if (m_fixed_tab_width > tot_width/2)
401 m_fixed_tab_width = tot_width/2;
402
403 if (m_fixed_tab_width > 220)
404 m_fixed_tab_width = 220;
405
406 m_tab_ctrl_height = tab_ctrl_size.y;
407 }
408
409
DrawBackground(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect)410 void wxAuiDefaultTabArt::DrawBackground(wxDC& dc,
411 wxWindow* WXUNUSED(wnd),
412 const wxRect& rect)
413 {
414 // draw background
415 wxColor top_color = wxAuiStepColour(m_base_colour, 90);
416 wxColor bottom_color = wxAuiStepColour(m_base_colour, 170);
417 wxRect r;
418
419 if (m_flags &wxAUI_NB_BOTTOM)
420 r = wxRect(rect.x, rect.y, rect.width+2, rect.height);
421 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
422 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
423 else //for wxAUI_NB_TOP
424 r = wxRect(rect.x, rect.y, rect.width+2, rect.height-3);
425 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
426
427 // draw base lines
428 dc.SetPen(m_border_pen);
429 int y = rect.GetHeight();
430 int w = rect.GetWidth();
431
432 if (m_flags &wxAUI_NB_BOTTOM)
433 {
434 dc.SetBrush(wxBrush(bottom_color));
435 dc.DrawRectangle(-1, 0, w+2, 4);
436 }
437 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
438 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
439 else //for wxAUI_NB_TOP
440 {
441 dc.SetBrush(m_base_colour_brush);
442 dc.DrawRectangle(-1, y-4, w+2, 4);
443 }
444 }
445
446
447 // DrawTab() draws an individual tab.
448 //
449 // dc - output dc
450 // in_rect - rectangle the tab should be confined to
451 // caption - tab's caption
452 // active - whether or not the tab is active
453 // out_rect - actual output rectangle
454 // x_extent - the advance x; where the next tab should start
455
DrawTab(wxDC & dc,wxWindow * wnd,const wxAuiNotebookPage & page,const wxRect & in_rect,int close_button_state,wxRect * out_tab_rect,wxRect * out_button_rect,int * x_extent)456 void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
457 wxWindow* wnd,
458 const wxAuiNotebookPage& page,
459 const wxRect& in_rect,
460 int close_button_state,
461 wxRect* out_tab_rect,
462 wxRect* out_button_rect,
463 int* x_extent)
464 {
465 wxCoord normal_textx, normal_texty;
466 wxCoord selected_textx, selected_texty;
467 wxCoord texty;
468
469 // if the caption is empty, measure some temporary text
470 wxString caption = page.caption;
471 if (caption.empty())
472 caption = wxT("Xj");
473
474 dc.SetFont(m_selected_font);
475 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
476
477 dc.SetFont(m_normal_font);
478 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
479
480 // figure out the size of the tab
481 wxSize tab_size = GetTabSize(dc,
482 wnd,
483 page.caption,
484 page.bitmap,
485 page.active,
486 close_button_state,
487 x_extent);
488
489 wxCoord tab_height = m_tab_ctrl_height - 3;
490 wxCoord tab_width = tab_size.x;
491 wxCoord tab_x = in_rect.x;
492 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
493
494
495 caption = page.caption;
496
497
498 // select pen, brush and font for the tab to be drawn
499
500 if (page.active)
501 {
502 dc.SetFont(m_selected_font);
503 texty = selected_texty;
504 }
505 else
506 {
507 dc.SetFont(m_normal_font);
508 texty = normal_texty;
509 }
510
511
512 // create points that will make the tab outline
513
514 int clip_width = tab_width;
515 if (tab_x + clip_width > in_rect.x + in_rect.width)
516 clip_width = (in_rect.x + in_rect.width) - tab_x;
517
518 /*
519 wxPoint clip_points[6];
520 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
521 clip_points[1] = wxPoint(tab_x, tab_y+2);
522 clip_points[2] = wxPoint(tab_x+2, tab_y);
523 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
524 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
525 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
526
527 // FIXME: these ports don't provide wxRegion ctor from array of points
528 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
529 // set the clipping region for the tab --
530 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
531 dc.SetClippingRegion(clipping_region);
532 #endif // !wxDFB && !wxCocoa
533 */
534 // since the above code above doesn't play well with WXDFB or WXCOCOA,
535 // we'll just use a rectangle for the clipping region for now --
536 dc.SetClippingRegion(tab_x, tab_y, clip_width+1, tab_height-3);
537
538
539 wxPoint border_points[6];
540 if (m_flags &wxAUI_NB_BOTTOM)
541 {
542 border_points[0] = wxPoint(tab_x, tab_y);
543 border_points[1] = wxPoint(tab_x, tab_y+tab_height-6);
544 border_points[2] = wxPoint(tab_x+2, tab_y+tab_height-4);
545 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y+tab_height-4);
546 border_points[4] = wxPoint(tab_x+tab_width, tab_y+tab_height-6);
547 border_points[5] = wxPoint(tab_x+tab_width, tab_y);
548 }
549 else //if (m_flags & wxAUI_NB_TOP) {}
550 {
551 border_points[0] = wxPoint(tab_x, tab_y+tab_height-4);
552 border_points[1] = wxPoint(tab_x, tab_y+2);
553 border_points[2] = wxPoint(tab_x+2, tab_y);
554 border_points[3] = wxPoint(tab_x+tab_width-2, tab_y);
555 border_points[4] = wxPoint(tab_x+tab_width, tab_y+2);
556 border_points[5] = wxPoint(tab_x+tab_width, tab_y+tab_height-4);
557 }
558 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
559 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
560
561 int drawn_tab_yoff = border_points[1].y;
562 int drawn_tab_height = border_points[0].y - border_points[1].y;
563
564
565 if (page.active)
566 {
567 // draw active tab
568
569 // draw base background color
570 wxRect r(tab_x, tab_y, tab_width, tab_height);
571 dc.SetPen(m_base_colour_pen);
572 dc.SetBrush(m_base_colour_brush);
573 dc.DrawRectangle(r.x+1, r.y+1, r.width-1, r.height-4);
574
575 // this white helps fill out the gradient at the top of the tab
576 dc.SetPen(*wxWHITE_PEN);
577 dc.SetBrush(*wxWHITE_BRUSH);
578 dc.DrawRectangle(r.x+2, r.y+1, r.width-3, r.height-4);
579
580 // these two points help the rounded corners appear more antialiased
581 dc.SetPen(m_base_colour_pen);
582 dc.DrawPoint(r.x+2, r.y+1);
583 dc.DrawPoint(r.x+r.width-2, r.y+1);
584
585 // set rectangle down a bit for gradient drawing
586 r.SetHeight(r.GetHeight()/2);
587 r.x += 2;
588 r.width -= 2;
589 r.y += r.height;
590 r.y -= 2;
591
592 // draw gradient background
593 wxColor top_color = *wxWHITE;
594 wxColor bottom_color = m_base_colour;
595 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
596 }
597 else
598 {
599 // draw inactive tab
600
601 wxRect r(tab_x, tab_y+1, tab_width, tab_height-3);
602
603 // start the gradent up a bit and leave the inside border inset
604 // by a pixel for a 3D look. Only the top half of the inactive
605 // tab will have a slight gradient
606 r.x += 3;
607 r.y++;
608 r.width -= 4;
609 r.height /= 2;
610 r.height--;
611
612 // -- draw top gradient fill for glossy look
613 wxColor top_color = m_base_colour;
614 wxColor bottom_color = wxAuiStepColour(top_color, 160);
615 dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
616
617 r.y += r.height;
618 r.y--;
619
620 // -- draw bottom fill for glossy look
621 top_color = m_base_colour;
622 bottom_color = m_base_colour;
623 dc.GradientFillLinear(r, top_color, bottom_color, wxSOUTH);
624 }
625
626 // draw tab outline
627 dc.SetPen(m_border_pen);
628 dc.SetBrush(*wxTRANSPARENT_BRUSH);
629 dc.DrawPolygon(WXSIZEOF(border_points), border_points);
630
631 // there are two horizontal grey lines at the bottom of the tab control,
632 // this gets rid of the top one of those lines in the tab control
633 if (page.active)
634 {
635 if (m_flags &wxAUI_NB_BOTTOM)
636 dc.SetPen(wxPen(wxColour(wxAuiStepColour(m_base_colour, 170))));
637 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
638 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
639 else //for wxAUI_NB_TOP
640 dc.SetPen(m_base_colour_pen);
641 dc.DrawLine(border_points[0].x+1,
642 border_points[0].y,
643 border_points[5].x,
644 border_points[5].y);
645 }
646
647
648 int text_offset = tab_x + 8;
649 int close_button_width = 0;
650 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
651 {
652 close_button_width = m_active_close_bmp.GetWidth();
653 }
654
655
656 int bitmap_offset = 0;
657 if (page.bitmap.IsOk())
658 {
659 bitmap_offset = tab_x + 8;
660
661 // draw bitmap
662 dc.DrawBitmap(page.bitmap,
663 bitmap_offset,
664 drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
665 true);
666
667 text_offset = bitmap_offset + page.bitmap.GetWidth();
668 text_offset += 3; // bitmap padding
669 }
670 else
671 {
672 text_offset = tab_x + 8;
673 }
674
675
676 wxString draw_text = wxAuiChopText(dc,
677 caption,
678 tab_width - (text_offset-tab_x) - close_button_width);
679
680 // draw tab text
681 dc.DrawText(draw_text,
682 text_offset,
683 drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);
684
685 // draw close button if necessary
686 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
687 {
688 wxBitmap bmp = m_disabled_close_bmp;
689
690 if (close_button_state == wxAUI_BUTTON_STATE_HOVER ||
691 close_button_state == wxAUI_BUTTON_STATE_PRESSED)
692 {
693 bmp = m_active_close_bmp;
694 }
695
696 int offsetY = tab_y-1;
697 if (m_flags & wxAUI_NB_BOTTOM)
698 offsetY = 1;
699
700 wxRect rect(tab_x + tab_width - close_button_width - 1,
701 offsetY + (tab_height/2) - (bmp.GetHeight()/2),
702 close_button_width,
703 tab_height);
704
705 IndentPressedBitmap(&rect, close_button_state);
706 dc.DrawBitmap(bmp, rect.x, rect.y, true);
707
708 *out_button_rect = rect;
709 }
710
711 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
712
713 #ifndef __WXMAC__
714 // draw focus rectangle
715 if (page.active && (wnd->FindFocus() == wnd))
716 {
717 wxRect focusRectText(text_offset, (drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1),
718 selected_textx, selected_texty);
719
720 wxRect focusRect;
721 wxRect focusRectBitmap;
722
723 if (page.bitmap.IsOk())
724 focusRectBitmap = wxRect(bitmap_offset, drawn_tab_yoff + (drawn_tab_height/2) - (page.bitmap.GetHeight()/2),
725 page.bitmap.GetWidth(), page.bitmap.GetHeight());
726
727 if (page.bitmap.IsOk() && draw_text.IsEmpty())
728 focusRect = focusRectBitmap;
729 else if (!page.bitmap.IsOk() && !draw_text.IsEmpty())
730 focusRect = focusRectText;
731 else if (page.bitmap.IsOk() && !draw_text.IsEmpty())
732 focusRect = focusRectText.Union(focusRectBitmap);
733
734 focusRect.Inflate(2, 2);
735
736 DrawFocusRect(wnd, dc, focusRect, 0);
737 }
738 #endif
739
740 dc.DestroyClippingRegion();
741 }
742
GetIndentSize()743 int wxAuiDefaultTabArt::GetIndentSize()
744 {
745 return 5;
746 }
747
GetTabSize(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxString & caption,const wxBitmap & bitmap,bool WXUNUSED (active),int close_button_state,int * x_extent)748 wxSize wxAuiDefaultTabArt::GetTabSize(wxDC& dc,
749 wxWindow* WXUNUSED(wnd),
750 const wxString& caption,
751 const wxBitmap& bitmap,
752 bool WXUNUSED(active),
753 int close_button_state,
754 int* x_extent)
755 {
756 wxCoord measured_textx, measured_texty, tmp;
757
758 dc.SetFont(m_measuring_font);
759 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
760
761 dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
762
763 // add padding around the text
764 wxCoord tab_width = measured_textx;
765 wxCoord tab_height = measured_texty;
766
767 // if the close button is showing, add space for it
768 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
769 tab_width += m_active_close_bmp.GetWidth() + 3;
770
771 // if there's a bitmap, add space for it
772 if (bitmap.IsOk())
773 {
774 tab_width += bitmap.GetWidth();
775 tab_width += 3; // right side bitmap padding
776 tab_height = wxMax(tab_height, bitmap.GetHeight());
777 }
778
779 // add padding
780 tab_width += 16;
781 tab_height += 10;
782
783 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
784 {
785 tab_width = m_fixed_tab_width;
786 }
787
788 *x_extent = tab_width;
789
790 return wxSize(tab_width, tab_height);
791 }
792
793
DrawButton(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & in_rect,int bitmap_id,int button_state,int orientation,wxRect * out_rect)794 void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
795 wxWindow* WXUNUSED(wnd),
796 const wxRect& in_rect,
797 int bitmap_id,
798 int button_state,
799 int orientation,
800 wxRect* out_rect)
801 {
802 wxBitmap bmp;
803 wxRect rect;
804
805 switch (bitmap_id)
806 {
807 case wxAUI_BUTTON_CLOSE:
808 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
809 bmp = m_disabled_close_bmp;
810 else
811 bmp = m_active_close_bmp;
812 break;
813 case wxAUI_BUTTON_LEFT:
814 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
815 bmp = m_disabled_left_bmp;
816 else
817 bmp = m_active_left_bmp;
818 break;
819 case wxAUI_BUTTON_RIGHT:
820 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
821 bmp = m_disabled_right_bmp;
822 else
823 bmp = m_active_right_bmp;
824 break;
825 case wxAUI_BUTTON_WINDOWLIST:
826 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
827 bmp = m_disabled_windowlist_bmp;
828 else
829 bmp = m_active_windowlist_bmp;
830 break;
831 }
832
833
834 if (!bmp.IsOk())
835 return;
836
837 rect = in_rect;
838
839 if (orientation == wxLEFT)
840 {
841 rect.SetX(in_rect.x);
842 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
843 rect.SetWidth(bmp.GetWidth());
844 rect.SetHeight(bmp.GetHeight());
845 }
846 else
847 {
848 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
849 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
850 bmp.GetWidth(), bmp.GetHeight());
851 }
852
853 IndentPressedBitmap(&rect, button_state);
854 dc.DrawBitmap(bmp, rect.x, rect.y, true);
855
856 *out_rect = rect;
857 }
858
859
ShowDropDown(wxWindow * wnd,const wxAuiNotebookPageArray & pages,int active_idx)860 int wxAuiDefaultTabArt::ShowDropDown(wxWindow* wnd,
861 const wxAuiNotebookPageArray& pages,
862 int active_idx)
863 {
864 wxMenu menuPopup;
865
866 size_t i, count = pages.GetCount();
867 for (i = 0; i < count; ++i)
868 {
869 const wxAuiNotebookPage& page = pages.Item(i);
870 wxString caption = page.caption;
871
872 // if there is no caption, make it a space. This will prevent
873 // an assert in the menu code.
874 if (caption.IsEmpty())
875 caption = wxT(" ");
876
877 menuPopup.AppendCheckItem(1000+i, caption);
878 }
879
880 if (active_idx != -1)
881 {
882 menuPopup.Check(1000+active_idx, true);
883 }
884
885 // find out where to put the popup menu of window items
886 wxPoint pt = ::wxGetMousePosition();
887 pt = wnd->ScreenToClient(pt);
888
889 // find out the screen coordinate at the bottom of the tab ctrl
890 wxRect cli_rect = wnd->GetClientRect();
891 pt.y = cli_rect.y + cli_rect.height;
892
893 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
894 wnd->PushEventHandler(cc);
895 wnd->PopupMenu(&menuPopup, pt);
896 int command = cc->GetCommandId();
897 wnd->PopEventHandler(true);
898
899 if (command >= 1000)
900 return command-1000;
901
902 return -1;
903 }
904
GetBestTabCtrlSize(wxWindow * wnd,const wxAuiNotebookPageArray & pages,const wxSize & required_bmp_size)905 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd,
906 const wxAuiNotebookPageArray& pages,
907 const wxSize& required_bmp_size)
908 {
909 wxClientDC dc(wnd);
910 dc.SetFont(m_measuring_font);
911
912 // sometimes a standard bitmap size needs to be enforced, especially
913 // if some tabs have bitmaps and others don't. This is important because
914 // it prevents the tab control from resizing when tabs are added.
915 wxBitmap measure_bmp;
916 if (required_bmp_size.IsFullySpecified())
917 {
918 measure_bmp.Create(required_bmp_size.x,
919 required_bmp_size.y);
920 }
921
922
923 int max_y = 0;
924 size_t i, page_count = pages.GetCount();
925 for (i = 0; i < page_count; ++i)
926 {
927 wxAuiNotebookPage& page = pages.Item(i);
928
929 wxBitmap bmp;
930 if (measure_bmp.IsOk())
931 bmp = measure_bmp;
932 else
933 bmp = page.bitmap;
934
935 // we don't use the caption text because we don't
936 // want tab heights to be different in the case
937 // of a very short piece of text on one tab and a very
938 // tall piece of text on another tab
939 int x_ext = 0;
940 wxSize s = GetTabSize(dc,
941 wnd,
942 wxT("ABCDEFGHIj"),
943 bmp,
944 true,
945 wxAUI_BUTTON_STATE_HIDDEN,
946 &x_ext);
947
948 max_y = wxMax(max_y, s.y);
949 }
950
951 return max_y+2;
952 }
953
SetNormalFont(const wxFont & font)954 void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
955 {
956 m_normal_font = font;
957 }
958
SetSelectedFont(const wxFont & font)959 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
960 {
961 m_selected_font = font;
962 }
963
SetMeasuringFont(const wxFont & font)964 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
965 {
966 m_measuring_font = font;
967 }
968
969
970 // -- wxAuiSimpleTabArt class implementation --
971
wxAuiSimpleTabArt()972 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
973 {
974 m_normal_font = *wxNORMAL_FONT;
975 m_selected_font = *wxNORMAL_FONT;
976 m_selected_font.SetWeight(wxBOLD);
977 m_measuring_font = m_selected_font;
978
979 m_flags = 0;
980 m_fixed_tab_width = 100;
981
982 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
983
984 wxColour background_colour = base_colour;
985 wxColour normaltab_colour = base_colour;
986 wxColour selectedtab_colour = *wxWHITE;
987
988 m_bkbrush = wxBrush(background_colour);
989 m_normal_bkbrush = wxBrush(normaltab_colour);
990 m_normal_bkpen = wxPen(normaltab_colour);
991 m_selected_bkbrush = wxBrush(selectedtab_colour);
992 m_selected_bkpen = wxPen(selectedtab_colour);
993
994 m_active_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
995 m_disabled_close_bmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
996
997 m_active_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
998 m_disabled_left_bmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
999
1000 m_active_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
1001 m_disabled_right_bmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
1002
1003 m_active_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
1004 m_disabled_windowlist_bmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
1005
1006 }
1007
~wxAuiSimpleTabArt()1008 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
1009 {
1010 }
1011
Clone()1012 wxAuiTabArt* wxAuiSimpleTabArt::Clone()
1013 {
1014 return wx_static_cast(wxAuiTabArt*, new wxAuiSimpleTabArt);
1015 }
1016
1017
SetFlags(unsigned int flags)1018 void wxAuiSimpleTabArt::SetFlags(unsigned int flags)
1019 {
1020 m_flags = flags;
1021 }
1022
SetSizingInfo(const wxSize & tab_ctrl_size,size_t tab_count)1023 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
1024 size_t tab_count)
1025 {
1026 m_fixed_tab_width = 100;
1027
1028 int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
1029
1030 if (m_flags & wxAUI_NB_CLOSE_BUTTON)
1031 tot_width -= m_active_close_bmp.GetWidth();
1032 if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
1033 tot_width -= m_active_windowlist_bmp.GetWidth();
1034
1035 if (tab_count > 0)
1036 {
1037 m_fixed_tab_width = tot_width/(int)tab_count;
1038 }
1039
1040
1041 if (m_fixed_tab_width < 100)
1042 m_fixed_tab_width = 100;
1043
1044 if (m_fixed_tab_width > tot_width/2)
1045 m_fixed_tab_width = tot_width/2;
1046
1047 if (m_fixed_tab_width > 220)
1048 m_fixed_tab_width = 220;
1049 }
1050
DrawBackground(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & rect)1051 void wxAuiSimpleTabArt::DrawBackground(wxDC& dc,
1052 wxWindow* WXUNUSED(wnd),
1053 const wxRect& rect)
1054 {
1055 // draw background
1056 dc.SetBrush(m_bkbrush);
1057 dc.SetPen(*wxTRANSPARENT_PEN);
1058 dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
1059
1060 // draw base line
1061 dc.SetPen(*wxGREY_PEN);
1062 dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
1063 }
1064
1065
1066 // DrawTab() draws an individual tab.
1067 //
1068 // dc - output dc
1069 // in_rect - rectangle the tab should be confined to
1070 // caption - tab's caption
1071 // active - whether or not the tab is active
1072 // out_rect - actual output rectangle
1073 // x_extent - the advance x; where the next tab should start
1074
DrawTab(wxDC & dc,wxWindow * wnd,const wxAuiNotebookPage & page,const wxRect & in_rect,int close_button_state,wxRect * out_tab_rect,wxRect * out_button_rect,int * x_extent)1075 void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
1076 wxWindow* wnd,
1077 const wxAuiNotebookPage& page,
1078 const wxRect& in_rect,
1079 int close_button_state,
1080 wxRect* out_tab_rect,
1081 wxRect* out_button_rect,
1082 int* x_extent)
1083 {
1084 wxCoord normal_textx, normal_texty;
1085 wxCoord selected_textx, selected_texty;
1086 wxCoord textx, texty;
1087
1088 // if the caption is empty, measure some temporary text
1089 wxString caption = page.caption;
1090 if (caption.empty())
1091 caption = wxT("Xj");
1092
1093 dc.SetFont(m_selected_font);
1094 dc.GetTextExtent(caption, &selected_textx, &selected_texty);
1095
1096 dc.SetFont(m_normal_font);
1097 dc.GetTextExtent(caption, &normal_textx, &normal_texty);
1098
1099 // figure out the size of the tab
1100 wxSize tab_size = GetTabSize(dc,
1101 wnd,
1102 page.caption,
1103 page.bitmap,
1104 page.active,
1105 close_button_state,
1106 x_extent);
1107
1108 wxCoord tab_height = tab_size.y;
1109 wxCoord tab_width = tab_size.x;
1110 wxCoord tab_x = in_rect.x;
1111 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
1112
1113 caption = page.caption;
1114
1115 // select pen, brush and font for the tab to be drawn
1116
1117 if (page.active)
1118 {
1119 dc.SetPen(m_selected_bkpen);
1120 dc.SetBrush(m_selected_bkbrush);
1121 dc.SetFont(m_selected_font);
1122 textx = selected_textx;
1123 texty = selected_texty;
1124 }
1125 else
1126 {
1127 dc.SetPen(m_normal_bkpen);
1128 dc.SetBrush(m_normal_bkbrush);
1129 dc.SetFont(m_normal_font);
1130 textx = normal_textx;
1131 texty = normal_texty;
1132 }
1133
1134
1135 // -- draw line --
1136
1137 wxPoint points[7];
1138 points[0].x = tab_x;
1139 points[0].y = tab_y + tab_height - 1;
1140 points[1].x = tab_x + tab_height - 3;
1141 points[1].y = tab_y + 2;
1142 points[2].x = tab_x + tab_height + 3;
1143 points[2].y = tab_y;
1144 points[3].x = tab_x + tab_width - 2;
1145 points[3].y = tab_y;
1146 points[4].x = tab_x + tab_width;
1147 points[4].y = tab_y + 2;
1148 points[5].x = tab_x + tab_width;
1149 points[5].y = tab_y + tab_height - 1;
1150 points[6] = points[0];
1151
1152 dc.SetClippingRegion(in_rect);
1153
1154 dc.DrawPolygon(WXSIZEOF(points) - 1, points);
1155
1156 dc.SetPen(*wxGREY_PEN);
1157
1158 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1159 dc.DrawLines(WXSIZEOF(points), points);
1160
1161
1162 int text_offset;
1163
1164 int close_button_width = 0;
1165 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1166 {
1167 close_button_width = m_active_close_bmp.GetWidth();
1168 text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
1169 }
1170 else
1171 {
1172 text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
1173 }
1174
1175 // set minimum text offset
1176 if (text_offset < tab_x + tab_height)
1177 text_offset = tab_x + tab_height;
1178
1179 // chop text if necessary
1180 wxString draw_text = wxAuiChopText(dc,
1181 caption,
1182 tab_width - (text_offset-tab_x) - close_button_width);
1183
1184 // draw tab text
1185 dc.DrawText(draw_text,
1186 text_offset,
1187 (tab_y + tab_height)/2 - (texty/2) + 1);
1188
1189
1190 #ifndef __WXMAC__
1191 // draw focus rectangle
1192 if (page.active && (wnd->FindFocus() == wnd))
1193 {
1194 wxRect focusRect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1),
1195 selected_textx, selected_texty);
1196
1197 focusRect.Inflate(2, 2);
1198
1199 DrawFocusRect(wnd, dc, focusRect, 0);
1200 }
1201 #endif
1202
1203 // draw close button if necessary
1204 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1205 {
1206 wxBitmap bmp;
1207 if (page.active)
1208 bmp = m_active_close_bmp;
1209 else
1210 bmp = m_disabled_close_bmp;
1211
1212 wxRect rect(tab_x + tab_width - close_button_width - 1,
1213 tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
1214 close_button_width,
1215 tab_height - 1);
1216 DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state);
1217
1218 *out_button_rect = rect;
1219 }
1220
1221
1222 *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
1223
1224 dc.DestroyClippingRegion();
1225 }
1226
GetIndentSize()1227 int wxAuiSimpleTabArt::GetIndentSize()
1228 {
1229 return 0;
1230 }
1231
GetTabSize(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxString & caption,const wxBitmap & WXUNUSED (bitmap),bool WXUNUSED (active),int close_button_state,int * x_extent)1232 wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
1233 wxWindow* WXUNUSED(wnd),
1234 const wxString& caption,
1235 const wxBitmap& WXUNUSED(bitmap),
1236 bool WXUNUSED(active),
1237 int close_button_state,
1238 int* x_extent)
1239 {
1240 wxCoord measured_textx, measured_texty;
1241
1242 dc.SetFont(m_measuring_font);
1243 dc.GetTextExtent(caption, &measured_textx, &measured_texty);
1244
1245 wxCoord tab_height = measured_texty + 4;
1246 wxCoord tab_width = measured_textx + tab_height + 5;
1247
1248 if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
1249 tab_width += m_active_close_bmp.GetWidth();
1250
1251 if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
1252 {
1253 tab_width = m_fixed_tab_width;
1254 }
1255
1256 *x_extent = tab_width - (tab_height/2) - 1;
1257
1258 return wxSize(tab_width, tab_height);
1259 }
1260
1261
DrawButton(wxDC & dc,wxWindow * WXUNUSED (wnd),const wxRect & in_rect,int bitmap_id,int button_state,int orientation,wxRect * out_rect)1262 void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
1263 wxWindow* WXUNUSED(wnd),
1264 const wxRect& in_rect,
1265 int bitmap_id,
1266 int button_state,
1267 int orientation,
1268 wxRect* out_rect)
1269 {
1270 wxBitmap bmp;
1271 wxRect rect;
1272
1273 switch (bitmap_id)
1274 {
1275 case wxAUI_BUTTON_CLOSE:
1276 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1277 bmp = m_disabled_close_bmp;
1278 else
1279 bmp = m_active_close_bmp;
1280 break;
1281 case wxAUI_BUTTON_LEFT:
1282 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1283 bmp = m_disabled_left_bmp;
1284 else
1285 bmp = m_active_left_bmp;
1286 break;
1287 case wxAUI_BUTTON_RIGHT:
1288 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1289 bmp = m_disabled_right_bmp;
1290 else
1291 bmp = m_active_right_bmp;
1292 break;
1293 case wxAUI_BUTTON_WINDOWLIST:
1294 if (button_state & wxAUI_BUTTON_STATE_DISABLED)
1295 bmp = m_disabled_windowlist_bmp;
1296 else
1297 bmp = m_active_windowlist_bmp;
1298 break;
1299 }
1300
1301 if (!bmp.IsOk())
1302 return;
1303
1304 rect = in_rect;
1305
1306 if (orientation == wxLEFT)
1307 {
1308 rect.SetX(in_rect.x);
1309 rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
1310 rect.SetWidth(bmp.GetWidth());
1311 rect.SetHeight(bmp.GetHeight());
1312 }
1313 else
1314 {
1315 rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
1316 ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
1317 bmp.GetWidth(), bmp.GetHeight());
1318 }
1319
1320
1321 DrawButtons(dc, rect, bmp, *wxWHITE, button_state);
1322
1323 *out_rect = rect;
1324 }
1325
1326
ShowDropDown(wxWindow * wnd,const wxAuiNotebookPageArray & pages,int active_idx)1327 int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd,
1328 const wxAuiNotebookPageArray& pages,
1329 int active_idx)
1330 {
1331 wxMenu menuPopup;
1332
1333 size_t i, count = pages.GetCount();
1334 for (i = 0; i < count; ++i)
1335 {
1336 const wxAuiNotebookPage& page = pages.Item(i);
1337 menuPopup.AppendCheckItem(1000+i, page.caption);
1338 }
1339
1340 if (active_idx != -1)
1341 {
1342 menuPopup.Check(1000+active_idx, true);
1343 }
1344
1345 // find out where to put the popup menu of window
1346 // items. Subtract 100 for now to center the menu
1347 // a bit, until a better mechanism can be implemented
1348 wxPoint pt = ::wxGetMousePosition();
1349 pt = wnd->ScreenToClient(pt);
1350 if (pt.x < 100)
1351 pt.x = 0;
1352 else
1353 pt.x -= 100;
1354
1355 // find out the screen coordinate at the bottom of the tab ctrl
1356 wxRect cli_rect = wnd->GetClientRect();
1357 pt.y = cli_rect.y + cli_rect.height;
1358
1359 wxAuiCommandCapture* cc = new wxAuiCommandCapture;
1360 wnd->PushEventHandler(cc);
1361 wnd->PopupMenu(&menuPopup, pt);
1362 int command = cc->GetCommandId();
1363 wnd->PopEventHandler(true);
1364
1365 if (command >= 1000)
1366 return command-1000;
1367
1368 return -1;
1369 }
1370
GetBestTabCtrlSize(wxWindow * wnd,const wxAuiNotebookPageArray & WXUNUSED (pages),const wxSize & WXUNUSED (required_bmp_size))1371 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd,
1372 const wxAuiNotebookPageArray& WXUNUSED(pages),
1373 const wxSize& WXUNUSED(required_bmp_size))
1374 {
1375 wxClientDC dc(wnd);
1376 dc.SetFont(m_measuring_font);
1377 int x_ext = 0;
1378 wxSize s = GetTabSize(dc,
1379 wnd,
1380 wxT("ABCDEFGHIj"),
1381 wxNullBitmap,
1382 true,
1383 wxAUI_BUTTON_STATE_HIDDEN,
1384 &x_ext);
1385 return s.y+3;
1386 }
1387
SetNormalFont(const wxFont & font)1388 void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font)
1389 {
1390 m_normal_font = font;
1391 }
1392
SetSelectedFont(const wxFont & font)1393 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font)
1394 {
1395 m_selected_font = font;
1396 }
1397
SetMeasuringFont(const wxFont & font)1398 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font)
1399 {
1400 m_measuring_font = font;
1401 }
1402
1403
1404
1405
1406 // -- wxAuiTabContainer class implementation --
1407
1408
1409 // wxAuiTabContainer is a class which contains information about each
1410 // tab. It also can render an entire tab control to a specified DC.
1411 // It's not a window class itself, because this code will be used by
1412 // the wxFrameMananger, where it is disadvantageous to have separate
1413 // windows for each tab control in the case of "docked tabs"
1414
1415 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1416 // which can be used as a tab control in the normal sense.
1417
1418
wxAuiTabContainer()1419 wxAuiTabContainer::wxAuiTabContainer()
1420 {
1421 m_tab_offset = 0;
1422 m_flags = 0;
1423 m_art = new wxAuiDefaultTabArt;
1424
1425 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
1426 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1427 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
1428 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
1429 }
1430
~wxAuiTabContainer()1431 wxAuiTabContainer::~wxAuiTabContainer()
1432 {
1433 delete m_art;
1434 }
1435
SetArtProvider(wxAuiTabArt * art)1436 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
1437 {
1438 delete m_art;
1439 m_art = art;
1440
1441 if (m_art)
1442 {
1443 m_art->SetFlags(m_flags);
1444 }
1445 }
1446
GetArtProvider() const1447 wxAuiTabArt* wxAuiTabContainer::GetArtProvider() const
1448 {
1449 return m_art;
1450 }
1451
SetFlags(unsigned int flags)1452 void wxAuiTabContainer::SetFlags(unsigned int flags)
1453 {
1454 m_flags = flags;
1455
1456 // check for new close button settings
1457 RemoveButton(wxAUI_BUTTON_LEFT);
1458 RemoveButton(wxAUI_BUTTON_RIGHT);
1459 RemoveButton(wxAUI_BUTTON_WINDOWLIST);
1460 RemoveButton(wxAUI_BUTTON_CLOSE);
1461
1462
1463 if (flags & wxAUI_NB_SCROLL_BUTTONS)
1464 {
1465 AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
1466 AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
1467 }
1468
1469 if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
1470 {
1471 AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
1472 }
1473
1474 if (flags & wxAUI_NB_CLOSE_BUTTON)
1475 {
1476 AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
1477 }
1478
1479 if (m_art)
1480 {
1481 m_art->SetFlags(m_flags);
1482 }
1483 }
1484
GetFlags() const1485 unsigned int wxAuiTabContainer::GetFlags() const
1486 {
1487 return m_flags;
1488 }
1489
1490
SetNormalFont(const wxFont & font)1491 void wxAuiTabContainer::SetNormalFont(const wxFont& font)
1492 {
1493 m_art->SetNormalFont(font);
1494 }
1495
SetSelectedFont(const wxFont & font)1496 void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
1497 {
1498 m_art->SetSelectedFont(font);
1499 }
1500
SetMeasuringFont(const wxFont & font)1501 void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
1502 {
1503 m_art->SetMeasuringFont(font);
1504 }
1505
SetRect(const wxRect & rect)1506 void wxAuiTabContainer::SetRect(const wxRect& rect)
1507 {
1508 m_rect = rect;
1509
1510 if (m_art)
1511 {
1512 m_art->SetSizingInfo(rect.GetSize(), m_pages.GetCount());
1513 }
1514 }
1515
AddPage(wxWindow * page,const wxAuiNotebookPage & info)1516 bool wxAuiTabContainer::AddPage(wxWindow* page,
1517 const wxAuiNotebookPage& info)
1518 {
1519 wxAuiNotebookPage page_info;
1520 page_info = info;
1521 page_info.window = page;
1522
1523 m_pages.Add(page_info);
1524
1525 // let the art provider know how many pages we have
1526 if (m_art)
1527 {
1528 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1529 }
1530
1531 return true;
1532 }
1533
InsertPage(wxWindow * page,const wxAuiNotebookPage & info,size_t idx)1534 bool wxAuiTabContainer::InsertPage(wxWindow* page,
1535 const wxAuiNotebookPage& info,
1536 size_t idx)
1537 {
1538 wxAuiNotebookPage page_info;
1539 page_info = info;
1540 page_info.window = page;
1541
1542 if (idx >= m_pages.GetCount())
1543 m_pages.Add(page_info);
1544 else
1545 m_pages.Insert(page_info, idx);
1546
1547 // let the art provider know how many pages we have
1548 if (m_art)
1549 {
1550 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1551 }
1552
1553 return true;
1554 }
1555
MovePage(wxWindow * page,size_t new_idx)1556 bool wxAuiTabContainer::MovePage(wxWindow* page,
1557 size_t new_idx)
1558 {
1559 int idx = GetIdxFromWindow(page);
1560 if (idx == -1)
1561 return false;
1562
1563 // get page entry, make a copy of it
1564 wxAuiNotebookPage p = GetPage(idx);
1565
1566 // remove old page entry
1567 RemovePage(page);
1568
1569 // insert page where it should be
1570 InsertPage(page, p, new_idx);
1571
1572 return true;
1573 }
1574
RemovePage(wxWindow * wnd)1575 bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
1576 {
1577 size_t i, page_count = m_pages.GetCount();
1578 for (i = 0; i < page_count; ++i)
1579 {
1580 wxAuiNotebookPage& page = m_pages.Item(i);
1581 if (page.window == wnd)
1582 {
1583 m_pages.RemoveAt(i);
1584
1585 // let the art provider know how many pages we have
1586 if (m_art)
1587 {
1588 m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
1589 }
1590
1591 return true;
1592 }
1593 }
1594
1595 return false;
1596 }
1597
SetActivePage(wxWindow * wnd)1598 bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
1599 {
1600 bool found = false;
1601
1602 size_t i, page_count = m_pages.GetCount();
1603 for (i = 0; i < page_count; ++i)
1604 {
1605 wxAuiNotebookPage& page = m_pages.Item(i);
1606 if (page.window == wnd)
1607 {
1608 page.active = true;
1609 found = true;
1610 }
1611 else
1612 {
1613 page.active = false;
1614 }
1615 }
1616
1617 return found;
1618 }
1619
SetNoneActive()1620 void wxAuiTabContainer::SetNoneActive()
1621 {
1622 size_t i, page_count = m_pages.GetCount();
1623 for (i = 0; i < page_count; ++i)
1624 {
1625 wxAuiNotebookPage& page = m_pages.Item(i);
1626 page.active = false;
1627 }
1628 }
1629
SetActivePage(size_t page)1630 bool wxAuiTabContainer::SetActivePage(size_t page)
1631 {
1632 if (page >= m_pages.GetCount())
1633 return false;
1634
1635 return SetActivePage(m_pages.Item(page).window);
1636 }
1637
GetActivePage() const1638 int wxAuiTabContainer::GetActivePage() const
1639 {
1640 size_t i, page_count = m_pages.GetCount();
1641 for (i = 0; i < page_count; ++i)
1642 {
1643 wxAuiNotebookPage& page = m_pages.Item(i);
1644 if (page.active)
1645 return i;
1646 }
1647
1648 return -1;
1649 }
1650
GetWindowFromIdx(size_t idx) const1651 wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
1652 {
1653 if (idx >= m_pages.GetCount())
1654 return NULL;
1655
1656 return m_pages[idx].window;
1657 }
1658
GetIdxFromWindow(wxWindow * wnd) const1659 int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
1660 {
1661 size_t i, page_count = m_pages.GetCount();
1662 for (i = 0; i < page_count; ++i)
1663 {
1664 wxAuiNotebookPage& page = m_pages.Item(i);
1665 if (page.window == wnd)
1666 return i;
1667 }
1668 return -1;
1669 }
1670
GetPage(size_t idx)1671 wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
1672 {
1673 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
1674
1675 return m_pages[idx];
1676 }
1677
GetPage(size_t idx) const1678 const wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx) const
1679 {
1680 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
1681
1682 return m_pages[idx];
1683 }
1684
GetPages()1685 wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
1686 {
1687 return m_pages;
1688 }
1689
GetPageCount() const1690 size_t wxAuiTabContainer::GetPageCount() const
1691 {
1692 return m_pages.GetCount();
1693 }
1694
AddButton(int id,int location,const wxBitmap & normal_bitmap,const wxBitmap & disabled_bitmap)1695 void wxAuiTabContainer::AddButton(int id,
1696 int location,
1697 const wxBitmap& normal_bitmap,
1698 const wxBitmap& disabled_bitmap)
1699 {
1700 wxAuiTabContainerButton button;
1701 button.id = id;
1702 button.bitmap = normal_bitmap;
1703 button.dis_bitmap = disabled_bitmap;
1704 button.location = location;
1705 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
1706
1707 m_buttons.Add(button);
1708 }
1709
RemoveButton(int id)1710 void wxAuiTabContainer::RemoveButton(int id)
1711 {
1712 size_t i, button_count = m_buttons.GetCount();
1713
1714 for (i = 0; i < button_count; ++i)
1715 {
1716 if (m_buttons.Item(i).id == id)
1717 {
1718 m_buttons.RemoveAt(i);
1719 return;
1720 }
1721 }
1722 }
1723
1724
1725
GetTabOffset() const1726 size_t wxAuiTabContainer::GetTabOffset() const
1727 {
1728 return m_tab_offset;
1729 }
1730
SetTabOffset(size_t offset)1731 void wxAuiTabContainer::SetTabOffset(size_t offset)
1732 {
1733 m_tab_offset = offset;
1734 }
1735
1736
1737
1738
1739 // Render() renders the tab catalog to the specified DC
1740 // It is a virtual function and can be overridden to
1741 // provide custom drawing capabilities
Render(wxDC * raw_dc,wxWindow * wnd)1742 void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
1743 {
1744 if (!raw_dc || !raw_dc->IsOk())
1745 return;
1746
1747 wxMemoryDC dc;
1748
1749 // use the same layout direction as the window DC uses to ensure that the
1750 // text is rendered correctly
1751 dc.SetLayoutDirection(raw_dc->GetLayoutDirection());
1752
1753 wxBitmap bmp;
1754 size_t i;
1755 size_t page_count = m_pages.GetCount();
1756 size_t button_count = m_buttons.GetCount();
1757
1758 // create off-screen bitmap
1759 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
1760 dc.SelectObject(bmp);
1761
1762 if (!dc.IsOk())
1763 return;
1764
1765 // find out if size of tabs is larger than can be
1766 // afforded on screen
1767 int total_width = 0;
1768 int visible_width = 0;
1769
1770 for (i = 0; i < page_count; ++i)
1771 {
1772 wxAuiNotebookPage& page = m_pages.Item(i);
1773
1774 // determine if a close button is on this tab
1775 bool close_button = false;
1776 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1777 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1778 {
1779 close_button = true;
1780 }
1781
1782
1783 int x_extent = 0;
1784 wxSize size = m_art->GetTabSize(dc,
1785 wnd,
1786 page.caption,
1787 page.bitmap,
1788 page.active,
1789 close_button ?
1790 wxAUI_BUTTON_STATE_NORMAL :
1791 wxAUI_BUTTON_STATE_HIDDEN,
1792 &x_extent);
1793
1794 if (i+1 < page_count)
1795 total_width += x_extent;
1796 else
1797 total_width += size.x;
1798
1799 if (i >= m_tab_offset)
1800 {
1801 if (i+1 < page_count)
1802 visible_width += x_extent;
1803 else
1804 visible_width += size.x;
1805 }
1806 }
1807
1808 if (total_width > m_rect.GetWidth() || m_tab_offset != 0)
1809 {
1810 // show left/right buttons
1811 for (i = 0; i < button_count; ++i)
1812 {
1813 wxAuiTabContainerButton& button = m_buttons.Item(i);
1814 if (button.id == wxAUI_BUTTON_LEFT ||
1815 button.id == wxAUI_BUTTON_RIGHT)
1816 {
1817 button.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN;
1818 }
1819 }
1820 }
1821 else
1822 {
1823 // hide left/right buttons
1824 for (i = 0; i < button_count; ++i)
1825 {
1826 wxAuiTabContainerButton& button = m_buttons.Item(i);
1827 if (button.id == wxAUI_BUTTON_LEFT ||
1828 button.id == wxAUI_BUTTON_RIGHT)
1829 {
1830 button.cur_state |= wxAUI_BUTTON_STATE_HIDDEN;
1831 }
1832 }
1833 }
1834
1835 // determine whether left button should be enabled
1836 for (i = 0; i < button_count; ++i)
1837 {
1838 wxAuiTabContainerButton& button = m_buttons.Item(i);
1839 if (button.id == wxAUI_BUTTON_LEFT)
1840 {
1841 if (m_tab_offset == 0)
1842 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
1843 else
1844 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1845 }
1846 if (button.id == wxAUI_BUTTON_RIGHT)
1847 {
1848 if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
1849 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
1850 else
1851 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
1852 }
1853 }
1854
1855
1856
1857 // draw background
1858 m_art->DrawBackground(dc, wnd, m_rect);
1859
1860 // draw buttons
1861 int left_buttons_width = 0;
1862 int right_buttons_width = 0;
1863
1864 int offset = 0;
1865
1866 // draw the buttons on the right side
1867 offset = m_rect.x + m_rect.width;
1868 for (i = 0; i < button_count; ++i)
1869 {
1870 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1871
1872 if (button.location != wxRIGHT)
1873 continue;
1874 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1875 continue;
1876
1877 wxRect button_rect = m_rect;
1878 button_rect.SetY(1);
1879 button_rect.SetWidth(offset);
1880
1881 m_art->DrawButton(dc,
1882 wnd,
1883 button_rect,
1884 button.id,
1885 button.cur_state,
1886 wxRIGHT,
1887 &button.rect);
1888
1889 offset -= button.rect.GetWidth();
1890 right_buttons_width += button.rect.GetWidth();
1891 }
1892
1893
1894
1895 offset = 0;
1896
1897 // draw the buttons on the left side
1898
1899 for (i = 0; i < button_count; ++i)
1900 {
1901 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
1902
1903 if (button.location != wxLEFT)
1904 continue;
1905 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
1906 continue;
1907
1908 wxRect button_rect(offset, 1, 1000, m_rect.height);
1909
1910 m_art->DrawButton(dc,
1911 wnd,
1912 button_rect,
1913 button.id,
1914 button.cur_state,
1915 wxLEFT,
1916 &button.rect);
1917
1918 offset += button.rect.GetWidth();
1919 left_buttons_width += button.rect.GetWidth();
1920 }
1921
1922 offset = left_buttons_width;
1923
1924 if (offset == 0)
1925 offset += m_art->GetIndentSize();
1926
1927
1928 // prepare the tab-close-button array
1929 // make sure tab button entries which aren't used are marked as hidden
1930 for (i = page_count; i < m_tab_close_buttons.GetCount(); ++i)
1931 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1932
1933 // make sure there are enough tab button entries to accommodate all tabs
1934 while (m_tab_close_buttons.GetCount() < page_count)
1935 {
1936 wxAuiTabContainerButton tempbtn;
1937 tempbtn.id = wxAUI_BUTTON_CLOSE;
1938 tempbtn.location = wxCENTER;
1939 tempbtn.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1940 m_tab_close_buttons.Add(tempbtn);
1941 }
1942
1943
1944 // buttons before the tab offset must be set to hidden
1945 for (i = 0; i < m_tab_offset; ++i)
1946 {
1947 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1948 }
1949
1950
1951 // draw the tabs
1952
1953 size_t active = 999;
1954 int active_offset = 0;
1955 wxRect active_rect;
1956 wxRect active_focus_rect;
1957
1958 int x_extent = 0;
1959 wxRect rect = m_rect;
1960 rect.y = 0;
1961 rect.height = m_rect.height;
1962
1963 for (i = m_tab_offset; i < page_count; ++i)
1964 {
1965 wxAuiNotebookPage& page = m_pages.Item(i);
1966 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
1967
1968 // determine if a close button is on this tab
1969 if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
1970 ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
1971 {
1972 if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
1973 {
1974 tab_button.id = wxAUI_BUTTON_CLOSE;
1975 tab_button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
1976 tab_button.location = wxCENTER;
1977 }
1978 }
1979 else
1980 {
1981 tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
1982 }
1983
1984 rect.x = offset;
1985 rect.width = m_rect.width - right_buttons_width - offset - 2;
1986
1987 if (rect.width <= 0)
1988 break;
1989
1990 m_art->DrawTab(dc,
1991 wnd,
1992 page,
1993 rect,
1994 tab_button.cur_state,
1995 &page.rect,
1996 &tab_button.rect,
1997 &x_extent);
1998
1999 if (page.active)
2000 {
2001 active = i;
2002 active_offset = offset;
2003 active_rect = rect;
2004 active_focus_rect = rect;
2005 active_focus_rect.width = x_extent;
2006 }
2007
2008 offset += x_extent;
2009 }
2010
2011
2012 // make sure to deactivate buttons which are off the screen to the right
2013 for (++i; i < m_tab_close_buttons.GetCount(); ++i)
2014 {
2015 m_tab_close_buttons.Item(i).cur_state = wxAUI_BUTTON_STATE_HIDDEN;
2016 }
2017
2018
2019 // draw the active tab again so it stands in the foreground
2020 if (active >= m_tab_offset && active < m_pages.GetCount())
2021 {
2022 wxAuiNotebookPage& page = m_pages.Item(active);
2023
2024 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
2025
2026 rect.x = active_offset;
2027 m_art->DrawTab(dc,
2028 wnd,
2029 page,
2030 active_rect,
2031 tab_button.cur_state,
2032 &page.rect,
2033 &tab_button.rect,
2034 &x_extent);
2035 }
2036
2037
2038 raw_dc->Blit(m_rect.x, m_rect.y,
2039 m_rect.GetWidth(), m_rect.GetHeight(),
2040 &dc, 0, 0);
2041
2042 #ifdef __WXMAC__
2043 // On Mac, need to draw the focus rect directly to the window
2044 if (wnd && (wnd->FindFocus() == wnd) && (active >= m_tab_offset && active < m_pages.GetCount()))
2045 {
2046 wxRect focusRect(active_focus_rect);
2047 focusRect.Inflate(-6, -6);
2048 DrawFocusRect(wnd, * raw_dc, focusRect, 0);
2049 }
2050 #endif
2051 }
2052
2053 // Is the tab visible?
IsTabVisible(int tabPage,int tabOffset,wxDC * dc,wxWindow * wnd)2054 bool wxAuiTabContainer::IsTabVisible(int tabPage, int tabOffset, wxDC* dc, wxWindow* wnd)
2055 {
2056 if (!dc || !dc->IsOk())
2057 return false;
2058
2059 size_t i;
2060 size_t page_count = m_pages.GetCount();
2061 size_t button_count = m_buttons.GetCount();
2062
2063 // Hasn't been rendered yet; assume it's visible
2064 if (m_tab_close_buttons.GetCount() < page_count)
2065 return true;
2066
2067 // First check if both buttons are disabled - if so, there's no need to
2068 // check further for visibility.
2069 int arrowButtonVisibleCount = 0;
2070 for (i = 0; i < button_count; ++i)
2071 {
2072 wxAuiTabContainerButton& button = m_buttons.Item(i);
2073 if (button.id == wxAUI_BUTTON_LEFT ||
2074 button.id == wxAUI_BUTTON_RIGHT)
2075 {
2076 if ((button.cur_state & wxAUI_BUTTON_STATE_HIDDEN) == 0)
2077 arrowButtonVisibleCount ++;
2078 }
2079 }
2080
2081 // Tab must be visible
2082 if (arrowButtonVisibleCount == 0)
2083 return true;
2084
2085 // If tab is less than the given offset, it must be invisible by definition
2086 if (tabPage < tabOffset)
2087 return false;
2088
2089 // draw buttons
2090 int left_buttons_width = 0;
2091 int right_buttons_width = 0;
2092
2093 int offset = 0;
2094
2095 // calculate size of the buttons on the right side
2096 offset = m_rect.x + m_rect.width;
2097 for (i = 0; i < button_count; ++i)
2098 {
2099 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
2100
2101 if (button.location != wxRIGHT)
2102 continue;
2103 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
2104 continue;
2105
2106 offset -= button.rect.GetWidth();
2107 right_buttons_width += button.rect.GetWidth();
2108 }
2109
2110 offset = 0;
2111
2112 // calculate size of the buttons on the left side
2113 for (i = 0; i < button_count; ++i)
2114 {
2115 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
2116
2117 if (button.location != wxLEFT)
2118 continue;
2119 if (button.cur_state & wxAUI_BUTTON_STATE_HIDDEN)
2120 continue;
2121
2122 offset += button.rect.GetWidth();
2123 left_buttons_width += button.rect.GetWidth();
2124 }
2125
2126 offset = left_buttons_width;
2127
2128 if (offset == 0)
2129 offset += m_art->GetIndentSize();
2130
2131 wxRect active_rect;
2132
2133 wxRect rect = m_rect;
2134 rect.y = 0;
2135 rect.height = m_rect.height;
2136
2137 // See if the given page is visible at the given tab offset (effectively scroll position)
2138 for (i = tabOffset; i < page_count; ++i)
2139 {
2140 wxAuiNotebookPage& page = m_pages.Item(i);
2141 wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(i);
2142
2143 rect.x = offset;
2144 rect.width = m_rect.width - right_buttons_width - offset - 2;
2145
2146 if (rect.width <= 0)
2147 return false; // haven't found the tab, and we've run out of space, so return false
2148
2149 int x_extent = 0;
2150 wxSize size = m_art->GetTabSize(*dc,
2151 wnd,
2152 page.caption,
2153 page.bitmap,
2154 page.active,
2155 tab_button.cur_state,
2156 &x_extent);
2157
2158 offset += x_extent;
2159
2160 if (i == (size_t) tabPage)
2161 {
2162 // If not all of the tab is visible, and supposing there's space to display it all,
2163 // we could do better so we return false.
2164 if (((m_rect.width - right_buttons_width - offset - 2) <= 0) && ((m_rect.width - right_buttons_width - left_buttons_width) > x_extent))
2165 return false;
2166 else
2167 return true;
2168 }
2169 }
2170
2171 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2172 // further looping in calling code.
2173 return true;
2174 }
2175
2176 // Make the tab visible if it wasn't already
MakeTabVisible(int tabPage,wxWindow * win)2177 void wxAuiTabContainer::MakeTabVisible(int tabPage, wxWindow* win)
2178 {
2179 wxClientDC dc(win);
2180 if (!IsTabVisible(tabPage, GetTabOffset(), & dc, win))
2181 {
2182 int i;
2183 for (i = 0; i < (int) m_pages.GetCount(); i++)
2184 {
2185 if (IsTabVisible(tabPage, i, & dc, win))
2186 {
2187 SetTabOffset(i);
2188 win->Refresh();
2189 return;
2190 }
2191 }
2192 }
2193 }
2194
2195 // TabHitTest() tests if a tab was hit, passing the window pointer
2196 // back if that condition was fulfilled. The function returns
2197 // true if a tab was hit, otherwise false
TabHitTest(int x,int y,wxWindow ** hit) const2198 bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
2199 {
2200 if (!m_rect.Contains(x,y))
2201 return false;
2202
2203 wxAuiTabContainerButton* btn = NULL;
2204 if (ButtonHitTest(x, y, &btn) && !(btn->cur_state & wxAUI_BUTTON_STATE_DISABLED))
2205 {
2206 if (m_buttons.Index(*btn) != wxNOT_FOUND)
2207 return false;
2208 }
2209
2210 size_t i, page_count = m_pages.GetCount();
2211
2212 for (i = m_tab_offset; i < page_count; ++i)
2213 {
2214 wxAuiNotebookPage& page = m_pages.Item(i);
2215 if (page.rect.Contains(x,y))
2216 {
2217 if (hit)
2218 *hit = page.window;
2219 return true;
2220 }
2221 }
2222
2223 return false;
2224 }
2225
2226 // ButtonHitTest() tests if a button was hit. The function returns
2227 // true if a button was hit, otherwise false
ButtonHitTest(int x,int y,wxAuiTabContainerButton ** hit) const2228 bool wxAuiTabContainer::ButtonHitTest(int x, int y,
2229 wxAuiTabContainerButton** hit) const
2230 {
2231 if (!m_rect.Contains(x,y))
2232 return false;
2233
2234 size_t i, button_count;
2235
2236
2237 button_count = m_buttons.GetCount();
2238 for (i = 0; i < button_count; ++i)
2239 {
2240 wxAuiTabContainerButton& button = m_buttons.Item(i);
2241 if (button.rect.Contains(x,y) &&
2242 !(button.cur_state & wxAUI_BUTTON_STATE_HIDDEN ))
2243 {
2244 if (hit)
2245 *hit = &button;
2246 return true;
2247 }
2248 }
2249
2250 button_count = m_tab_close_buttons.GetCount();
2251 for (i = 0; i < button_count; ++i)
2252 {
2253 wxAuiTabContainerButton& button = m_tab_close_buttons.Item(i);
2254 if (button.rect.Contains(x,y) &&
2255 !(button.cur_state & (wxAUI_BUTTON_STATE_HIDDEN |
2256 wxAUI_BUTTON_STATE_DISABLED)))
2257 {
2258 if (hit)
2259 *hit = &button;
2260 return true;
2261 }
2262 }
2263
2264 return false;
2265 }
2266
2267
2268
2269 // the utility function ShowWnd() is the same as show,
2270 // except it handles wxAuiMDIChildFrame windows as well,
2271 // as the Show() method on this class is "unplugged"
ShowWnd(wxWindow * wnd,bool show)2272 static void ShowWnd(wxWindow* wnd, bool show)
2273 {
2274 #if wxUSE_MDI
2275 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
2276 {
2277 wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
2278 cf->DoShow(show);
2279 }
2280 else
2281 #endif
2282 {
2283 wnd->Show(show);
2284 }
2285 }
2286
2287
2288 // DoShowHide() this function shows the active window, then
2289 // hides all of the other windows (in that order)
DoShowHide()2290 void wxAuiTabContainer::DoShowHide()
2291 {
2292 wxAuiNotebookPageArray& pages = GetPages();
2293 size_t i, page_count = pages.GetCount();
2294
2295 // show new active page first
2296 for (i = 0; i < page_count; ++i)
2297 {
2298 wxAuiNotebookPage& page = pages.Item(i);
2299 if (page.active)
2300 {
2301 ShowWnd(page.window, true);
2302 break;
2303 }
2304 }
2305
2306 // hide all other pages
2307 for (i = 0; i < page_count; ++i)
2308 {
2309 wxAuiNotebookPage& page = pages.Item(i);
2310 if (!page.active)
2311 ShowWnd(page.window, false);
2312 }
2313 }
2314
2315
2316
2317
2318
2319
2320 // -- wxAuiTabCtrl class implementation --
2321
2322
2323
BEGIN_EVENT_TABLE(wxAuiTabCtrl,wxControl)2324 BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
2325 EVT_PAINT(wxAuiTabCtrl::OnPaint)
2326 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
2327 EVT_SIZE(wxAuiTabCtrl::OnSize)
2328 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
2329 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick)
2330 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
2331 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown)
2332 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp)
2333 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown)
2334 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp)
2335 EVT_MOTION(wxAuiTabCtrl::OnMotion)
2336 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
2337 EVT_AUINOTEBOOK_BUTTON(wxID_ANY, wxAuiTabCtrl::OnButton)
2338 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus)
2339 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus)
2340 EVT_CHAR(wxAuiTabCtrl::OnChar)
2341 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost)
2342 END_EVENT_TABLE()
2343
2344
2345 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
2346 wxWindowID id,
2347 const wxPoint& pos,
2348 const wxSize& size,
2349 long style) : wxControl(parent, id, pos, size, style)
2350 {
2351 m_click_pt = wxDefaultPosition;
2352 m_is_dragging = false;
2353 m_hover_button = NULL;
2354 m_pressed_button = NULL;
2355 }
2356
~wxAuiTabCtrl()2357 wxAuiTabCtrl::~wxAuiTabCtrl()
2358 {
2359 }
2360
OnPaint(wxPaintEvent &)2361 void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
2362 {
2363 wxPaintDC dc(this);
2364
2365 dc.SetFont(GetFont());
2366
2367 if (GetPageCount() > 0)
2368 Render(&dc, this);
2369 }
2370
OnEraseBackground(wxEraseEvent & WXUNUSED (evt))2371 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
2372 {
2373 }
2374
OnSize(wxSizeEvent & evt)2375 void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
2376 {
2377 wxSize s = evt.GetSize();
2378 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
2379 SetRect(r);
2380 }
2381
OnLeftDown(wxMouseEvent & evt)2382 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
2383 {
2384 CaptureMouse();
2385 m_click_pt = wxDefaultPosition;
2386 m_is_dragging = false;
2387 m_click_tab = NULL;
2388 m_pressed_button = NULL;
2389
2390
2391 wxWindow* wnd;
2392 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
2393 {
2394 int new_selection = GetIdxFromWindow(wnd);
2395
2396 // wxAuiNotebooks always want to receive this event
2397 // even if the tab is already active, because they may
2398 // have multiple tab controls
2399 if (new_selection != GetActivePage() ||
2400 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook)))
2401 {
2402 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2403 e.SetSelection(new_selection);
2404 e.SetOldSelection(GetActivePage());
2405 e.SetEventObject(this);
2406 GetEventHandler()->ProcessEvent(e);
2407 }
2408
2409 m_click_pt.x = evt.m_x;
2410 m_click_pt.y = evt.m_y;
2411 m_click_tab = wnd;
2412 }
2413
2414 if (m_hover_button)
2415 {
2416 m_pressed_button = m_hover_button;
2417 m_pressed_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
2418 Refresh();
2419 Update();
2420 }
2421 }
2422
OnCaptureLost(wxMouseCaptureLostEvent & WXUNUSED (event))2423 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
2424 {
2425 }
2426
OnLeftUp(wxMouseEvent & evt)2427 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
2428 {
2429 if (GetCapture() == this)
2430 ReleaseMouse();
2431
2432 if (m_is_dragging)
2433 {
2434 m_is_dragging = false;
2435
2436 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
2437 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2438 evt.SetOldSelection(evt.GetSelection());
2439 evt.SetEventObject(this);
2440 GetEventHandler()->ProcessEvent(evt);
2441
2442 return;
2443 }
2444
2445 if (m_pressed_button)
2446 {
2447 // make sure we're still clicking the button
2448 wxAuiTabContainerButton* button = NULL;
2449 if (!ButtonHitTest(evt.m_x, evt.m_y, &button) ||
2450 button->cur_state & wxAUI_BUTTON_STATE_DISABLED)
2451 return;
2452
2453 if (button != m_pressed_button)
2454 {
2455 m_pressed_button = NULL;
2456 return;
2457 }
2458
2459 Refresh();
2460 Update();
2461
2462 if (!(m_pressed_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
2463 {
2464 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
2465 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2466 evt.SetInt(m_pressed_button->id);
2467 evt.SetEventObject(this);
2468 GetEventHandler()->ProcessEvent(evt);
2469 }
2470
2471 m_pressed_button = NULL;
2472 }
2473
2474 m_click_pt = wxDefaultPosition;
2475 m_is_dragging = false;
2476 m_click_tab = NULL;
2477 }
2478
OnMiddleUp(wxMouseEvent & evt)2479 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent& evt)
2480 {
2481 wxWindow* wnd = NULL;
2482 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2483 return;
2484
2485 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
2486 e.SetEventObject(this);
2487 e.SetSelection(GetIdxFromWindow(wnd));
2488 GetEventHandler()->ProcessEvent(e);
2489 }
2490
OnMiddleDown(wxMouseEvent & evt)2491 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt)
2492 {
2493 wxWindow* wnd = NULL;
2494 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2495 return;
2496
2497 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
2498 e.SetEventObject(this);
2499 e.SetSelection(GetIdxFromWindow(wnd));
2500 GetEventHandler()->ProcessEvent(e);
2501 }
2502
OnRightUp(wxMouseEvent & evt)2503 void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt)
2504 {
2505 wxWindow* wnd = NULL;
2506 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2507 return;
2508
2509 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
2510 e.SetEventObject(this);
2511 e.SetSelection(GetIdxFromWindow(wnd));
2512 GetEventHandler()->ProcessEvent(e);
2513 }
2514
OnRightDown(wxMouseEvent & evt)2515 void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt)
2516 {
2517 wxWindow* wnd = NULL;
2518 if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
2519 return;
2520
2521 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
2522 e.SetEventObject(this);
2523 e.SetSelection(GetIdxFromWindow(wnd));
2524 GetEventHandler()->ProcessEvent(e);
2525 }
2526
OnLeftDClick(wxMouseEvent & evt)2527 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent& evt)
2528 {
2529 wxWindow* wnd;
2530 wxAuiTabContainerButton* button;
2531 if (!TabHitTest(evt.m_x, evt.m_y, &wnd) && !ButtonHitTest(evt.m_x, evt.m_y, &button))
2532 {
2533 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, m_windowId);
2534 e.SetEventObject(this);
2535 GetEventHandler()->ProcessEvent(e);
2536 }
2537 }
2538
OnMotion(wxMouseEvent & evt)2539 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
2540 {
2541 wxPoint pos = evt.GetPosition();
2542
2543 // check if the mouse is hovering above a button
2544 wxAuiTabContainerButton* button;
2545 if (ButtonHitTest(pos.x, pos.y, &button) && !(button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
2546 {
2547 if (m_hover_button && button != m_hover_button)
2548 {
2549 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2550 m_hover_button = NULL;
2551 Refresh();
2552 Update();
2553 }
2554
2555 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
2556 {
2557 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
2558 Refresh();
2559 Update();
2560 m_hover_button = button;
2561 return;
2562 }
2563 }
2564 else
2565 {
2566 if (m_hover_button)
2567 {
2568 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2569 m_hover_button = NULL;
2570 Refresh();
2571 Update();
2572 }
2573 }
2574
2575
2576 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
2577 return;
2578
2579 if (m_is_dragging)
2580 {
2581 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
2582 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2583 evt.SetOldSelection(evt.GetSelection());
2584 evt.SetEventObject(this);
2585 GetEventHandler()->ProcessEvent(evt);
2586 return;
2587 }
2588
2589
2590 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
2591 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
2592
2593 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
2594 abs(pos.y - m_click_pt.y) > drag_y_threshold)
2595 {
2596 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
2597 evt.SetSelection(GetIdxFromWindow(m_click_tab));
2598 evt.SetOldSelection(evt.GetSelection());
2599 evt.SetEventObject(this);
2600 GetEventHandler()->ProcessEvent(evt);
2601
2602 m_is_dragging = true;
2603 }
2604 }
2605
OnLeaveWindow(wxMouseEvent & WXUNUSED (event))2606 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
2607 {
2608 if (m_hover_button)
2609 {
2610 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
2611 m_hover_button = NULL;
2612 Refresh();
2613 Update();
2614 }
2615 }
2616
OnButton(wxAuiNotebookEvent & event)2617 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
2618 {
2619 int button = event.GetInt();
2620
2621 if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT)
2622 {
2623 if (button == wxAUI_BUTTON_LEFT)
2624 {
2625 if (GetTabOffset() > 0)
2626 {
2627 SetTabOffset(GetTabOffset()-1);
2628 Refresh();
2629 Update();
2630 }
2631 }
2632 else
2633 {
2634 SetTabOffset(GetTabOffset()+1);
2635 Refresh();
2636 Update();
2637 }
2638 }
2639 else if (button == wxAUI_BUTTON_WINDOWLIST)
2640 {
2641 int idx = GetArtProvider()->ShowDropDown(this, m_pages, GetActivePage());
2642
2643 if (idx != -1)
2644 {
2645 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2646 e.SetSelection(idx);
2647 e.SetOldSelection(GetActivePage());
2648 e.SetEventObject(this);
2649 GetEventHandler()->ProcessEvent(e);
2650 }
2651 }
2652 else
2653 {
2654 event.Skip();
2655 }
2656 }
2657
OnSetFocus(wxFocusEvent & WXUNUSED (event))2658 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event))
2659 {
2660 Refresh();
2661 }
2662
OnKillFocus(wxFocusEvent & WXUNUSED (event))2663 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event))
2664 {
2665 Refresh();
2666 }
2667
OnChar(wxKeyEvent & event)2668 void wxAuiTabCtrl::OnChar(wxKeyEvent& event)
2669 {
2670 if (GetActivePage() == -1)
2671 {
2672 event.Skip();
2673 return;
2674 }
2675
2676 // We can't leave tab processing to the system; on Windows, tabs and keys
2677 // get eaten by the system and not processed properly if we specify both
2678 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2679 // we don't key arrow key events.
2680
2681 int key = event.GetKeyCode();
2682
2683 if (key == WXK_NUMPAD_PAGEUP)
2684 key = WXK_PAGEUP;
2685 if (key == WXK_NUMPAD_PAGEDOWN)
2686 key = WXK_PAGEDOWN;
2687 if (key == WXK_NUMPAD_HOME)
2688 key = WXK_HOME;
2689 if (key == WXK_NUMPAD_END)
2690 key = WXK_END;
2691 if (key == WXK_NUMPAD_LEFT)
2692 key = WXK_LEFT;
2693 if (key == WXK_NUMPAD_RIGHT)
2694 key = WXK_RIGHT;
2695
2696 if (key == WXK_TAB || key == WXK_PAGEUP || key == WXK_PAGEDOWN)
2697 {
2698 bool bCtrlDown = event.ControlDown();
2699 bool bShiftDown = event.ShiftDown();
2700
2701 bool bForward = (key == WXK_TAB && !bShiftDown) || (key == WXK_PAGEDOWN);
2702 bool bWindowChange = (key == WXK_PAGEUP) || (key == WXK_PAGEDOWN) || bCtrlDown;
2703 bool bFromTab = (key == WXK_TAB);
2704
2705 wxAuiNotebook* nb = wxDynamicCast(GetParent(), wxAuiNotebook);
2706 if (!nb)
2707 {
2708 event.Skip();
2709 return;
2710 }
2711
2712 wxNavigationKeyEvent keyEvent;
2713 keyEvent.SetDirection(bForward);
2714 keyEvent.SetWindowChange(bWindowChange);
2715 keyEvent.SetFromTab(bFromTab);
2716 keyEvent.SetEventObject(nb);
2717
2718 if (!nb->GetEventHandler()->ProcessEvent(keyEvent))
2719 {
2720 // Not processed? Do an explicit tab into the page.
2721 wxWindow* win = GetWindowFromIdx(GetActivePage());
2722 if (win)
2723 win->SetFocus();
2724 }
2725 return;
2726 }
2727
2728 if (m_pages.GetCount() < 2)
2729 {
2730 event.Skip();
2731 return;
2732 }
2733
2734 int newPage = -1;
2735
2736 int forwardKey, backwardKey;
2737 if (GetLayoutDirection() == wxLayout_RightToLeft)
2738 {
2739 forwardKey = WXK_LEFT;
2740 backwardKey = WXK_RIGHT;
2741 }
2742 else
2743 {
2744 forwardKey = WXK_RIGHT;
2745 backwardKey = WXK_LEFT;
2746 }
2747
2748 if (key == forwardKey)
2749 {
2750 if (m_pages.GetCount() > 1)
2751 {
2752 if (GetActivePage() == -1)
2753 newPage = 0;
2754 else if (GetActivePage() < (int) (m_pages.GetCount() - 1))
2755 newPage = GetActivePage() + 1;
2756 }
2757 }
2758 else if (key == backwardKey)
2759 {
2760 if (m_pages.GetCount() > 1)
2761 {
2762 if (GetActivePage() == -1)
2763 newPage = (int) (m_pages.GetCount() - 1);
2764 else if (GetActivePage() > 0)
2765 newPage = GetActivePage() - 1;
2766 }
2767 }
2768 else if (key == WXK_HOME)
2769 {
2770 newPage = 0;
2771 }
2772 else if (key == WXK_END)
2773 {
2774 newPage = (int) (m_pages.GetCount() - 1);
2775 }
2776 else
2777 event.Skip();
2778
2779 if (newPage != -1)
2780 {
2781 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
2782 e.SetSelection(newPage);
2783 e.SetOldSelection(newPage);
2784 e.SetEventObject(this);
2785 this->GetEventHandler()->ProcessEvent(e);
2786 }
2787 else
2788 event.Skip();
2789 }
2790
2791 // wxTabFrame is an interesting case. It's important that all child pages
2792 // of the multi-notebook control are all actually children of that control
2793 // (and not grandchildren). wxTabFrame facilitates this. There is one
2794 // instance of wxTabFrame for each tab control inside the multi-notebook.
2795 // It's important to know that wxTabFrame is not a real window, but it merely
2796 // used to capture the dimensions/positioning of the internal tab control and
2797 // it's managed page windows
2798
2799 class wxTabFrame : public wxWindow
2800 {
2801 public:
2802
wxTabFrame()2803 wxTabFrame()
2804 {
2805 m_tabs = NULL;
2806 m_rect = wxRect(0,0,200,200);
2807 m_tab_ctrl_height = 20;
2808 }
2809
~wxTabFrame()2810 ~wxTabFrame()
2811 {
2812 wxDELETE(m_tabs);
2813 }
2814
SetTabCtrlHeight(int h)2815 void SetTabCtrlHeight(int h)
2816 {
2817 m_tab_ctrl_height = h;
2818 }
2819
DoSetSize(int x,int y,int width,int height,int WXUNUSED (sizeFlags=wxSIZE_AUTO))2820 void DoSetSize(int x, int y,
2821 int width, int height,
2822 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
2823 {
2824 m_rect = wxRect(x, y, width, height);
2825 DoSizing();
2826 }
2827
DoGetClientSize(int * x,int * y) const2828 void DoGetClientSize(int* x, int* y) const
2829 {
2830 *x = m_rect.width;
2831 *y = m_rect.height;
2832 }
2833
Show(bool WXUNUSED (show=true))2834 bool Show( bool WXUNUSED(show = true) ) { return false; }
2835
DoSizing()2836 void DoSizing()
2837 {
2838 if (!m_tabs)
2839 return;
2840
2841 if (m_tabs->IsFrozen() || m_tabs->GetParent()->IsFrozen())
2842 return;
2843
2844 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
2845 {
2846 m_tab_rect = wxRect (m_rect.x, m_rect.y + m_rect.height - m_tab_ctrl_height, m_rect.width, m_tab_ctrl_height);
2847 m_tabs->SetSize (m_rect.x, m_rect.y + m_rect.height - m_tab_ctrl_height, m_rect.width, m_tab_ctrl_height);
2848 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tab_ctrl_height));
2849 }
2850 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2851 {
2852 m_tab_rect = wxRect (m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2853 m_tabs->SetSize (m_rect.x, m_rect.y, m_rect.width, m_tab_ctrl_height);
2854 m_tabs->SetRect (wxRect(0, 0, m_rect.width, m_tab_ctrl_height));
2855 }
2856 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2857 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2858
2859 m_tabs->Refresh();
2860 m_tabs->Update();
2861
2862 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
2863 size_t i, page_count = pages.GetCount();
2864
2865 for (i = 0; i < page_count; ++i)
2866 {
2867 wxAuiNotebookPage& page = pages.Item(i);
2868 if (m_tabs->GetFlags() & wxAUI_NB_BOTTOM)
2869 {
2870 page.window->SetSize(m_rect.x, m_rect.y,
2871 m_rect.width, m_rect.height - m_tab_ctrl_height);
2872 }
2873 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2874 {
2875 page.window->SetSize(m_rect.x, m_rect.y + m_tab_ctrl_height,
2876 m_rect.width, m_rect.height - m_tab_ctrl_height);
2877 }
2878 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2879 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2880
2881 #if wxUSE_MDI
2882 if (page.window->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
2883 {
2884 wxAuiMDIChildFrame* wnd = (wxAuiMDIChildFrame*)page.window;
2885 wnd->ApplyMDIChildFrameRect();
2886 }
2887 #endif
2888 }
2889 }
2890
DoGetSize(int * x,int * y) const2891 void DoGetSize(int* x, int* y) const
2892 {
2893 if (x)
2894 *x = m_rect.GetWidth();
2895 if (y)
2896 *y = m_rect.GetHeight();
2897 }
2898
Update()2899 void Update()
2900 {
2901 // does nothing
2902 }
2903
2904 public:
2905
2906 wxRect m_rect;
2907 wxRect m_tab_rect;
2908 wxAuiTabCtrl* m_tabs;
2909 int m_tab_ctrl_height;
2910 };
2911
2912
2913 const int wxAuiBaseTabCtrlId = 5380;
2914
2915
2916 // -- wxAuiNotebook class implementation --
2917
BEGIN_EVENT_TABLE(wxAuiNotebook,wxControl)2918 BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
2919 EVT_SIZE(wxAuiNotebook::OnSize)
2920 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus)
2921 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2922 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
2923 wxAuiNotebook::OnTabClicked)
2924 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2925 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
2926 wxAuiNotebook::OnTabBeginDrag)
2927 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2928 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
2929 wxAuiNotebook::OnTabEndDrag)
2930 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2931 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
2932 wxAuiNotebook::OnTabDragMotion)
2933 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2934 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
2935 wxAuiNotebook::OnTabButton)
2936 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2937 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN,
2938 wxAuiNotebook::OnTabMiddleDown)
2939 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2940 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP,
2941 wxAuiNotebook::OnTabMiddleUp)
2942 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2943 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN,
2944 wxAuiNotebook::OnTabRightDown)
2945 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2946 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP,
2947 wxAuiNotebook::OnTabRightUp)
2948 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
2949 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK,
2950 wxAuiNotebook::OnTabBgDClick)
2951 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKey)
2952 END_EVENT_TABLE()
2953
2954 wxAuiNotebook::wxAuiNotebook()
2955 {
2956 m_curpage = -1;
2957 m_tab_id_counter = wxAuiBaseTabCtrlId;
2958 m_dummy_wnd = NULL;
2959 m_tab_ctrl_height = 20;
2960 m_requested_bmp_size = wxDefaultSize;
2961 m_requested_tabctrl_height = -1;
2962 }
2963
wxAuiNotebook(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style)2964 wxAuiNotebook::wxAuiNotebook(wxWindow *parent,
2965 wxWindowID id,
2966 const wxPoint& pos,
2967 const wxSize& size,
2968 long style) : wxControl(parent, id, pos, size, style)
2969 {
2970 m_dummy_wnd = NULL;
2971 m_requested_bmp_size = wxDefaultSize;
2972 m_requested_tabctrl_height = -1;
2973 InitNotebook(style);
2974 }
2975
Create(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style)2976 bool wxAuiNotebook::Create(wxWindow* parent,
2977 wxWindowID id,
2978 const wxPoint& pos,
2979 const wxSize& size,
2980 long style)
2981 {
2982 if (!wxControl::Create(parent, id, pos, size, style))
2983 return false;
2984
2985 InitNotebook(style);
2986
2987 return true;
2988 }
2989
2990 // InitNotebook() contains common initialization
2991 // code called by all constructors
InitNotebook(long style)2992 void wxAuiNotebook::InitNotebook(long style)
2993 {
2994 m_curpage = -1;
2995 m_tab_id_counter = wxAuiBaseTabCtrlId;
2996 m_dummy_wnd = NULL;
2997 m_flags = (unsigned int)style;
2998 m_tab_ctrl_height = 20;
2999
3000 m_normal_font = *wxNORMAL_FONT;
3001 m_selected_font = *wxNORMAL_FONT;
3002 m_selected_font.SetWeight(wxBOLD);
3003
3004 SetArtProvider(new wxAuiDefaultTabArt);
3005
3006 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
3007 m_dummy_wnd->SetSize(200, 200);
3008 m_dummy_wnd->Show(false);
3009
3010 m_mgr.SetManagedWindow(this);
3011 m_mgr.SetFlags(wxAUI_MGR_DEFAULT);
3012 m_mgr.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
3013
3014 m_mgr.AddPane(m_dummy_wnd,
3015 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
3016
3017 m_mgr.Update();
3018 }
3019
~wxAuiNotebook()3020 wxAuiNotebook::~wxAuiNotebook()
3021 {
3022 // Indicate we're deleting pages
3023 m_isBeingDeleted = true;
3024
3025 while ( GetPageCount() > 0 )
3026 DeletePage(0);
3027
3028 m_mgr.UnInit();
3029 }
3030
SetArtProvider(wxAuiTabArt * art)3031 void wxAuiNotebook::SetArtProvider(wxAuiTabArt* art)
3032 {
3033 m_tabs.SetArtProvider(art);
3034
3035 UpdateTabCtrlHeight();
3036 }
3037
3038 // SetTabCtrlHeight() is the highest-level override of the
3039 // tab height. A call to this function effectively enforces a
3040 // specified tab ctrl height, overriding all other considerations,
3041 // such as text or bitmap height. It overrides any call to
3042 // SetUniformBitmapSize(). Specifying a height of -1 reverts
3043 // any previous call and returns to the default behavior
3044
SetTabCtrlHeight(int height)3045 void wxAuiNotebook::SetTabCtrlHeight(int height)
3046 {
3047 m_requested_tabctrl_height = height;
3048
3049 // if window is already initialized, recalculate the tab height
3050 if (m_dummy_wnd)
3051 {
3052 UpdateTabCtrlHeight();
3053 }
3054 }
3055
3056
3057 // SetUniformBitmapSize() ensures that all tabs will have
3058 // the same height, even if some tabs don't have bitmaps
3059 // Passing wxDefaultSize to this function will instruct
3060 // the control to use dynamic tab height-- so when a tab
3061 // with a large bitmap is added, the tab ctrl's height will
3062 // automatically increase to accommodate the bitmap
3063
SetUniformBitmapSize(const wxSize & size)3064 void wxAuiNotebook::SetUniformBitmapSize(const wxSize& size)
3065 {
3066 m_requested_bmp_size = size;
3067
3068 // if window is already initialized, recalculate the tab height
3069 if (m_dummy_wnd)
3070 {
3071 UpdateTabCtrlHeight();
3072 }
3073 }
3074
3075 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
3076 // to be used interally
UpdateTabCtrlHeight()3077 void wxAuiNotebook::UpdateTabCtrlHeight()
3078 {
3079 // get the tab ctrl height we will use
3080 int height = CalculateTabCtrlHeight();
3081
3082 // if the tab control height needs to change, update
3083 // all of our tab controls with the new height
3084 if (m_tab_ctrl_height != height)
3085 {
3086 wxAuiTabArt* art = m_tabs.GetArtProvider();
3087
3088 m_tab_ctrl_height = height;
3089
3090 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3091 size_t i, pane_count = all_panes.GetCount();
3092 for (i = 0; i < pane_count; ++i)
3093 {
3094 wxAuiPaneInfo& pane = all_panes.Item(i);
3095 if (pane.name == wxT("dummy"))
3096 continue;
3097 wxTabFrame* tab_frame = (wxTabFrame*)pane.window;
3098 wxAuiTabCtrl* tabctrl = tab_frame->m_tabs;
3099 tab_frame->SetTabCtrlHeight(m_tab_ctrl_height);
3100 tabctrl->SetArtProvider(art->Clone());
3101 tab_frame->DoSizing();
3102 }
3103 }
3104 }
3105
UpdateHintWindowSize()3106 void wxAuiNotebook::UpdateHintWindowSize()
3107 {
3108 wxSize size = CalculateNewSplitSize();
3109
3110 // the placeholder hint window should be set to this size
3111 wxAuiPaneInfo& info = m_mgr.GetPane(wxT("dummy"));
3112 if (info.IsOk())
3113 {
3114 info.MinSize(size);
3115 info.BestSize(size);
3116 m_dummy_wnd->SetSize(size);
3117 }
3118 }
3119
3120
3121 // calculates the size of the new split
CalculateNewSplitSize()3122 wxSize wxAuiNotebook::CalculateNewSplitSize()
3123 {
3124 // count number of tab controls
3125 int tab_ctrl_count = 0;
3126 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3127 size_t i, pane_count = all_panes.GetCount();
3128 for (i = 0; i < pane_count; ++i)
3129 {
3130 wxAuiPaneInfo& pane = all_panes.Item(i);
3131 if (pane.name == wxT("dummy"))
3132 continue;
3133 tab_ctrl_count++;
3134 }
3135
3136 wxSize new_split_size;
3137
3138 // if there is only one tab control, the first split
3139 // should happen around the middle
3140 if (tab_ctrl_count < 2)
3141 {
3142 new_split_size = GetClientSize();
3143 new_split_size.x /= 2;
3144 new_split_size.y /= 2;
3145 }
3146 else
3147 {
3148 // this is in place of a more complicated calculation
3149 // that needs to be implemented
3150 new_split_size = wxSize(180,180);
3151 }
3152
3153 return new_split_size;
3154 }
3155
CalculateTabCtrlHeight()3156 int wxAuiNotebook::CalculateTabCtrlHeight()
3157 {
3158 // if a fixed tab ctrl height is specified,
3159 // just return that instead of calculating a
3160 // tab height
3161 if (m_requested_tabctrl_height != -1)
3162 return m_requested_tabctrl_height;
3163
3164 // find out new best tab height
3165 wxAuiTabArt* art = m_tabs.GetArtProvider();
3166
3167 return art->GetBestTabCtrlSize(this,
3168 m_tabs.GetPages(),
3169 m_requested_bmp_size);
3170 }
3171
3172
GetArtProvider() const3173 wxAuiTabArt* wxAuiNotebook::GetArtProvider() const
3174 {
3175 return m_tabs.GetArtProvider();
3176 }
3177
SetWindowStyleFlag(long style)3178 void wxAuiNotebook::SetWindowStyleFlag(long style)
3179 {
3180 wxControl::SetWindowStyleFlag(style);
3181
3182 m_flags = (unsigned int)style;
3183
3184 // if the control is already initialized
3185 if (m_mgr.GetManagedWindow() == (wxWindow*)this)
3186 {
3187 // let all of the tab children know about the new style
3188
3189 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3190 size_t i, pane_count = all_panes.GetCount();
3191 for (i = 0; i < pane_count; ++i)
3192 {
3193 wxAuiPaneInfo& pane = all_panes.Item(i);
3194 if (pane.name == wxT("dummy"))
3195 continue;
3196 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
3197 wxAuiTabCtrl* tabctrl = tabframe->m_tabs;
3198 tabctrl->SetFlags(m_flags);
3199 tabframe->DoSizing();
3200 tabctrl->Refresh();
3201 tabctrl->Update();
3202 }
3203 }
3204 }
3205
3206
AddPage(wxWindow * page,const wxString & caption,bool select,const wxBitmap & bitmap)3207 bool wxAuiNotebook::AddPage(wxWindow* page,
3208 const wxString& caption,
3209 bool select,
3210 const wxBitmap& bitmap)
3211 {
3212 return InsertPage(GetPageCount(), page, caption, select, bitmap);
3213 }
3214
InsertPage(size_t page_idx,wxWindow * page,const wxString & caption,bool select,const wxBitmap & bitmap)3215 bool wxAuiNotebook::InsertPage(size_t page_idx,
3216 wxWindow* page,
3217 const wxString& caption,
3218 bool select,
3219 const wxBitmap& bitmap)
3220 {
3221 wxASSERT_MSG(page, wxT("page pointer must be non-NULL"));
3222 if (!page)
3223 return false;
3224
3225 page->Reparent(this);
3226
3227 wxAuiNotebookPage info;
3228 info.window = page;
3229 info.caption = caption;
3230 info.bitmap = bitmap;
3231 info.active = false;
3232
3233 // if there are currently no tabs, the first added
3234 // tab must be active
3235 if (m_tabs.GetPageCount() == 0)
3236 info.active = true;
3237
3238 m_tabs.InsertPage(page, info, page_idx);
3239
3240 // if that was the first page added, even if
3241 // select is false, it must become the "current page"
3242 // (though no select events will be fired)
3243 if (!select && m_tabs.GetPageCount() == 1)
3244 select = true;
3245 //m_curpage = GetPageIndex(page);
3246
3247 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
3248 if (page_idx >= active_tabctrl->GetPageCount())
3249 active_tabctrl->AddPage(page, info);
3250 else
3251 active_tabctrl->InsertPage(page, info, page_idx);
3252
3253 UpdateTabCtrlHeight();
3254 DoSizing();
3255 active_tabctrl->DoShowHide();
3256
3257 // adjust selected index
3258 if(m_curpage >= (int) page_idx)
3259 m_curpage++;
3260
3261 if (select)
3262 {
3263 int idx = m_tabs.GetIdxFromWindow(page);
3264 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
3265
3266 SetSelection(idx);
3267 }
3268
3269 return true;
3270 }
3271
3272
3273 // DeletePage() removes a tab from the multi-notebook,
3274 // and destroys the window as well
DeletePage(size_t page_idx)3275 bool wxAuiNotebook::DeletePage(size_t page_idx)
3276 {
3277 if (page_idx >= m_tabs.GetPageCount())
3278 return false;
3279
3280 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
3281
3282 // hide the window in advance, as this will
3283 // prevent flicker
3284 if ( !IsBeingDeleted() )
3285 ShowWnd(wnd, false);
3286
3287 if (!RemovePage(page_idx))
3288 return false;
3289
3290 // actually destroy the window now
3291 #if wxUSE_MDI
3292 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
3293 {
3294 // delete the child frame with pending delete, as is
3295 // customary with frame windows
3296 if (!wxPendingDelete.Member(wnd))
3297 wxPendingDelete.Append(wnd);
3298 }
3299 else
3300 #endif
3301 {
3302 wnd->Destroy();
3303 }
3304
3305 return true;
3306 }
3307
3308
3309
3310 // RemovePage() removes a tab from the multi-notebook,
3311 // but does not destroy the window
RemovePage(size_t page_idx)3312 bool wxAuiNotebook::RemovePage(size_t page_idx)
3313 {
3314 // save active window pointer
3315 wxWindow* active_wnd = NULL;
3316 if (m_curpage >= 0)
3317 active_wnd = m_tabs.GetWindowFromIdx(m_curpage);
3318
3319 // save pointer of window being deleted
3320 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
3321 wxWindow* new_active = NULL;
3322
3323 // make sure we found the page
3324 if (!wnd)
3325 return false;
3326
3327 // find out which onscreen tab ctrl owns this tab
3328 wxAuiTabCtrl* ctrl;
3329 int ctrl_idx;
3330 if (!FindTab(wnd, &ctrl, &ctrl_idx))
3331 return false;
3332
3333 bool is_curpage = (m_curpage == (int)page_idx);
3334 bool is_active_in_split = ctrl->GetPage(ctrl_idx).active;
3335
3336
3337 // remove the tab from main catalog
3338 if (!m_tabs.RemovePage(wnd))
3339 return false;
3340
3341 // remove the tab from the onscreen tab ctrl
3342 ctrl->RemovePage(wnd);
3343
3344 if (is_active_in_split)
3345 {
3346 int ctrl_new_page_count = (int)ctrl->GetPageCount();
3347
3348 if (ctrl_idx >= ctrl_new_page_count)
3349 ctrl_idx = ctrl_new_page_count-1;
3350
3351 if (ctrl_idx >= 0 && ctrl_idx < (int)ctrl->GetPageCount())
3352 {
3353 // set new page as active in the tab split
3354 ctrl->SetActivePage(ctrl_idx);
3355
3356 // if the page deleted was the current page for the
3357 // entire tab control, then record the window
3358 // pointer of the new active page for activation
3359 if (is_curpage)
3360 {
3361 new_active = ctrl->GetWindowFromIdx(ctrl_idx);
3362 }
3363 }
3364 }
3365 else
3366 {
3367 // we are not deleting the active page, so keep it the same
3368 new_active = active_wnd;
3369 }
3370
3371
3372 if (!new_active)
3373 {
3374 // we haven't yet found a new page to active,
3375 // so select the next page from the main tab
3376 // catalogue
3377
3378 if (page_idx < m_tabs.GetPageCount())
3379 {
3380 new_active = m_tabs.GetPage(page_idx).window;
3381 }
3382
3383 if (!new_active && m_tabs.GetPageCount() > 0)
3384 {
3385 new_active = m_tabs.GetPage(0).window;
3386 }
3387 }
3388
3389
3390 RemoveEmptyTabFrames();
3391
3392 // set new active pane
3393 m_curpage = -1;
3394 if (new_active && !m_isBeingDeleted)
3395 {
3396 SetSelection(m_tabs.GetIdxFromWindow(new_active));
3397 }
3398
3399 return true;
3400 }
3401
3402 // GetPageIndex() returns the index of the page, or -1 if the
3403 // page could not be located in the notebook
GetPageIndex(wxWindow * page_wnd) const3404 int wxAuiNotebook::GetPageIndex(wxWindow* page_wnd) const
3405 {
3406 return m_tabs.GetIdxFromWindow(page_wnd);
3407 }
3408
3409
3410
3411 // SetPageText() changes the tab caption of the specified page
SetPageText(size_t page_idx,const wxString & text)3412 bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
3413 {
3414 if (page_idx >= m_tabs.GetPageCount())
3415 return false;
3416
3417 // update our own tab catalog
3418 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3419 page_info.caption = text;
3420
3421 // update what's on screen
3422 wxAuiTabCtrl* ctrl;
3423 int ctrl_idx;
3424 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
3425 {
3426 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
3427 info.caption = text;
3428 ctrl->Refresh();
3429 ctrl->Update();
3430 }
3431
3432 return true;
3433 }
3434
3435 // returns the page caption
GetPageText(size_t page_idx) const3436 wxString wxAuiNotebook::GetPageText(size_t page_idx) const
3437 {
3438 if (page_idx >= m_tabs.GetPageCount())
3439 return wxEmptyString;
3440
3441 // update our own tab catalog
3442 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3443 return page_info.caption;
3444 }
3445
SetPageBitmap(size_t page_idx,const wxBitmap & bitmap)3446 bool wxAuiNotebook::SetPageBitmap(size_t page_idx, const wxBitmap& bitmap)
3447 {
3448 if (page_idx >= m_tabs.GetPageCount())
3449 return false;
3450
3451 // update our own tab catalog
3452 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3453 page_info.bitmap = bitmap;
3454
3455 // tab height might have changed
3456 UpdateTabCtrlHeight();
3457
3458 // update what's on screen
3459 wxAuiTabCtrl* ctrl;
3460 int ctrl_idx;
3461 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
3462 {
3463 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
3464 info.bitmap = bitmap;
3465 ctrl->Refresh();
3466 ctrl->Update();
3467 }
3468
3469 return true;
3470 }
3471
3472 // returns the page bitmap
GetPageBitmap(size_t page_idx) const3473 wxBitmap wxAuiNotebook::GetPageBitmap(size_t page_idx) const
3474 {
3475 if (page_idx >= m_tabs.GetPageCount())
3476 return wxBitmap();
3477
3478 // update our own tab catalog
3479 const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
3480 return page_info.bitmap;
3481 }
3482
3483 // GetSelection() returns the index of the currently active page
GetSelection() const3484 int wxAuiNotebook::GetSelection() const
3485 {
3486 return m_curpage;
3487 }
3488
3489 // SetSelection() sets the currently active page
SetSelection(size_t new_page)3490 size_t wxAuiNotebook::SetSelection(size_t new_page)
3491 {
3492 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
3493 if (!wnd)
3494 return m_curpage;
3495
3496 // don't change the page unless necessary;
3497 // however, clicking again on a tab should give it the focus.
3498 if ((int)new_page == m_curpage)
3499 {
3500 wxAuiTabCtrl* ctrl;
3501 int ctrl_idx;
3502 if (FindTab(wnd, &ctrl, &ctrl_idx))
3503 {
3504 if (FindFocus() != ctrl)
3505 ctrl->SetFocus();
3506 }
3507 return m_curpage;
3508 }
3509
3510 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
3511 evt.SetSelection(new_page);
3512 evt.SetOldSelection(m_curpage);
3513 evt.SetEventObject(this);
3514 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
3515 {
3516 int old_curpage = m_curpage;
3517 m_curpage = new_page;
3518
3519 // program allows the page change
3520 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
3521 (void)GetEventHandler()->ProcessEvent(evt);
3522
3523
3524 wxAuiTabCtrl* ctrl;
3525 int ctrl_idx;
3526 if (FindTab(wnd, &ctrl, &ctrl_idx))
3527 {
3528 m_tabs.SetActivePage(wnd);
3529
3530 ctrl->SetActivePage(ctrl_idx);
3531 DoSizing();
3532 ctrl->DoShowHide();
3533
3534 ctrl->MakeTabVisible(ctrl_idx, ctrl);
3535
3536 // set fonts
3537 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3538 size_t i, pane_count = all_panes.GetCount();
3539 for (i = 0; i < pane_count; ++i)
3540 {
3541 wxAuiPaneInfo& pane = all_panes.Item(i);
3542 if (pane.name == wxT("dummy"))
3543 continue;
3544 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
3545 if (tabctrl != ctrl)
3546 tabctrl->SetSelectedFont(m_normal_font);
3547 else
3548 tabctrl->SetSelectedFont(m_selected_font);
3549 tabctrl->Refresh();
3550 }
3551
3552 // Set the focus to the page if we're not currently focused on the tab.
3553 // This is Firefox-like behaviour.
3554 if (wnd->IsShownOnScreen() && FindFocus() != ctrl)
3555 wnd->SetFocus();
3556
3557 return old_curpage;
3558 }
3559 }
3560
3561 return m_curpage;
3562 }
3563
3564 // GetPageCount() returns the total number of
3565 // pages managed by the multi-notebook
GetPageCount() const3566 size_t wxAuiNotebook::GetPageCount() const
3567 {
3568 return m_tabs.GetPageCount();
3569 }
3570
3571 // GetPage() returns the wxWindow pointer of the
3572 // specified page
GetPage(size_t page_idx) const3573 wxWindow* wxAuiNotebook::GetPage(size_t page_idx) const
3574 {
3575 wxASSERT(page_idx < m_tabs.GetPageCount());
3576
3577 return m_tabs.GetWindowFromIdx(page_idx);
3578 }
3579
3580 // DoSizing() performs all sizing operations in each tab control
DoSizing()3581 void wxAuiNotebook::DoSizing()
3582 {
3583 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3584 size_t i, pane_count = all_panes.GetCount();
3585 for (i = 0; i < pane_count; ++i)
3586 {
3587 if (all_panes.Item(i).name == wxT("dummy"))
3588 continue;
3589
3590 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3591 tabframe->DoSizing();
3592 }
3593 }
3594
3595 // GetActiveTabCtrl() returns the active tab control. It is
3596 // called to determine which control gets new windows being added
GetActiveTabCtrl()3597 wxAuiTabCtrl* wxAuiNotebook::GetActiveTabCtrl()
3598 {
3599 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
3600 {
3601 wxAuiTabCtrl* ctrl;
3602 int idx;
3603
3604 // find the tab ctrl with the current page
3605 if (FindTab(m_tabs.GetPage(m_curpage).window,
3606 &ctrl, &idx))
3607 {
3608 return ctrl;
3609 }
3610 }
3611
3612 // no current page, just find the first tab ctrl
3613 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3614 size_t i, pane_count = all_panes.GetCount();
3615 for (i = 0; i < pane_count; ++i)
3616 {
3617 if (all_panes.Item(i).name == wxT("dummy"))
3618 continue;
3619
3620 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3621 return tabframe->m_tabs;
3622 }
3623
3624 // If there is no tabframe at all, create one
3625 wxTabFrame* tabframe = new wxTabFrame;
3626 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
3627 tabframe->m_tabs = new wxAuiTabCtrl(this,
3628 m_tab_id_counter++,
3629 wxDefaultPosition,
3630 wxDefaultSize,
3631 wxNO_BORDER|wxWANTS_CHARS);
3632 tabframe->m_tabs->SetFlags(m_flags);
3633 tabframe->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
3634 m_mgr.AddPane(tabframe,
3635 wxAuiPaneInfo().Center().CaptionVisible(false));
3636
3637 m_mgr.Update();
3638
3639 return tabframe->m_tabs;
3640 }
3641
3642 // FindTab() finds the tab control that currently contains the window as well
3643 // as the index of the window in the tab control. It returns true if the
3644 // window was found, otherwise false.
FindTab(wxWindow * page,wxAuiTabCtrl ** ctrl,int * idx)3645 bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
3646 {
3647 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
3648 size_t i, pane_count = all_panes.GetCount();
3649 for (i = 0; i < pane_count; ++i)
3650 {
3651 if (all_panes.Item(i).name == wxT("dummy"))
3652 continue;
3653
3654 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
3655
3656 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
3657 if (page_idx != -1)
3658 {
3659 *ctrl = tabframe->m_tabs;
3660 *idx = page_idx;
3661 return true;
3662 }
3663 }
3664
3665 return false;
3666 }
3667
Split(size_t page,int direction)3668 void wxAuiNotebook::Split(size_t page, int direction)
3669 {
3670 wxSize cli_size = GetClientSize();
3671
3672 // get the page's window pointer
3673 wxWindow* wnd = GetPage(page);
3674 if (!wnd)
3675 return;
3676
3677 // notebooks with 1 or less pages can't be split
3678 if (GetPageCount() < 2)
3679 return;
3680
3681 // find out which tab control the page currently belongs to
3682 wxAuiTabCtrl *src_tabs, *dest_tabs;
3683 int src_idx = -1;
3684 src_tabs = NULL;
3685 if (!FindTab(wnd, &src_tabs, &src_idx))
3686 return;
3687 if (!src_tabs || src_idx == -1)
3688 return;
3689
3690 // choose a split size
3691 wxSize split_size;
3692 if (GetPageCount() > 2)
3693 {
3694 split_size = CalculateNewSplitSize();
3695 }
3696 else
3697 {
3698 // because there are two panes, always split them
3699 // equally
3700 split_size = GetClientSize();
3701 split_size.x /= 2;
3702 split_size.y /= 2;
3703 }
3704
3705
3706 // create a new tab frame
3707 wxTabFrame* new_tabs = new wxTabFrame;
3708 new_tabs->m_rect = wxRect(wxPoint(0,0), split_size);
3709 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
3710 new_tabs->m_tabs = new wxAuiTabCtrl(this,
3711 m_tab_id_counter++,
3712 wxDefaultPosition,
3713 wxDefaultSize,
3714 wxNO_BORDER|wxWANTS_CHARS);
3715 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
3716 new_tabs->m_tabs->SetFlags(m_flags);
3717 dest_tabs = new_tabs->m_tabs;
3718
3719 // create a pane info structure with the information
3720 // about where the pane should be added
3721 wxAuiPaneInfo pane_info = wxAuiPaneInfo().Bottom().CaptionVisible(false);
3722 wxPoint mouse_pt;
3723
3724 if (direction == wxLEFT)
3725 {
3726 pane_info.Left();
3727 mouse_pt = wxPoint(0, cli_size.y/2);
3728 }
3729 else if (direction == wxRIGHT)
3730 {
3731 pane_info.Right();
3732 mouse_pt = wxPoint(cli_size.x, cli_size.y/2);
3733 }
3734 else if (direction == wxTOP)
3735 {
3736 pane_info.Top();
3737 mouse_pt = wxPoint(cli_size.x/2, 0);
3738 }
3739 else if (direction == wxBOTTOM)
3740 {
3741 pane_info.Bottom();
3742 mouse_pt = wxPoint(cli_size.x/2, cli_size.y);
3743 }
3744
3745 m_mgr.AddPane(new_tabs, pane_info, mouse_pt);
3746 m_mgr.Update();
3747
3748 // remove the page from the source tabs
3749 wxAuiNotebookPage page_info = src_tabs->GetPage(src_idx);
3750 page_info.active = false;
3751 src_tabs->RemovePage(page_info.window);
3752 if (src_tabs->GetPageCount() > 0)
3753 {
3754 src_tabs->SetActivePage((size_t)0);
3755 src_tabs->DoShowHide();
3756 src_tabs->Refresh();
3757 }
3758
3759
3760 // add the page to the destination tabs
3761 dest_tabs->InsertPage(page_info.window, page_info, 0);
3762
3763 if (src_tabs->GetPageCount() == 0)
3764 {
3765 RemoveEmptyTabFrames();
3766 }
3767
3768 DoSizing();
3769 dest_tabs->DoShowHide();
3770 dest_tabs->Refresh();
3771
3772 // force the set selection function reset the selection
3773 m_curpage = -1;
3774
3775 // set the active page to the one we just split off
3776 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
3777
3778 UpdateHintWindowSize();
3779 }
3780
3781
OnSize(wxSizeEvent & evt)3782 void wxAuiNotebook::OnSize(wxSizeEvent& evt)
3783 {
3784 UpdateHintWindowSize();
3785
3786 evt.Skip();
3787 }
3788
OnTabClicked(wxCommandEvent & command_evt)3789 void wxAuiNotebook::OnTabClicked(wxCommandEvent& command_evt)
3790 {
3791 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
3792
3793 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
3794 wxASSERT(ctrl != NULL);
3795
3796 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
3797 wxASSERT(wnd != NULL);
3798
3799 int idx = m_tabs.GetIdxFromWindow(wnd);
3800 wxASSERT(idx != -1);
3801
3802
3803 // since a tab was clicked, let the parent know that we received
3804 // the focus, even if we will assign that focus immediately
3805 // to the child tab in the SetSelection call below
3806 // (the child focus event will also let wxAuiManager, if any,
3807 // know that the notebook control has been activated)
3808
3809 wxWindow* parent = GetParent();
3810 if (parent)
3811 {
3812 wxChildFocusEvent eventFocus(this);
3813 parent->GetEventHandler()->ProcessEvent(eventFocus);
3814 }
3815
3816
3817 SetSelection(idx);
3818 }
3819
OnTabBgDClick(wxCommandEvent & WXUNUSED (evt))3820 void wxAuiNotebook::OnTabBgDClick(wxCommandEvent& WXUNUSED(evt))
3821 {
3822 // notify owner that the tabbar background has been double-clicked
3823 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, m_windowId);
3824 e.SetEventObject(this);
3825 GetEventHandler()->ProcessEvent(e);
3826 }
3827
OnTabBeginDrag(wxCommandEvent &)3828 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent&)
3829 {
3830 m_last_drag_x = 0;
3831 }
3832
OnTabDragMotion(wxCommandEvent & evt)3833 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
3834 {
3835 wxPoint screen_pt = ::wxGetMousePosition();
3836 wxPoint client_pt = ScreenToClient(screen_pt);
3837 wxPoint zero(0,0);
3838
3839 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3840 wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
3841
3842 if (dest_tabs == src_tabs)
3843 {
3844 if (src_tabs)
3845 {
3846 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
3847 }
3848
3849 // always hide the hint for inner-tabctrl drag
3850 m_mgr.HideHint();
3851
3852 // if tab moving is not allowed, leave
3853 if (!(m_flags & wxAUI_NB_TAB_MOVE))
3854 {
3855 return;
3856 }
3857
3858 wxPoint pt = dest_tabs->ScreenToClient(screen_pt);
3859 wxWindow* dest_location_tab;
3860
3861 // this is an inner-tab drag/reposition
3862 if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab))
3863 {
3864 int src_idx = evt.GetSelection();
3865 int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab);
3866
3867 // prevent jumpy drag
3868 if ((src_idx == dest_idx) || dest_idx == -1 ||
3869 (src_idx > dest_idx && m_last_drag_x <= pt.x) ||
3870 (src_idx < dest_idx && m_last_drag_x >= pt.x))
3871 {
3872 m_last_drag_x = pt.x;
3873 return;
3874 }
3875
3876
3877 wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx);
3878 dest_tabs->MovePage(src_tab, dest_idx);
3879 dest_tabs->SetActivePage((size_t)dest_idx);
3880 dest_tabs->DoShowHide();
3881 dest_tabs->Refresh();
3882 m_last_drag_x = pt.x;
3883
3884 }
3885
3886 return;
3887 }
3888
3889
3890 // if external drag is allowed, check if the tab is being dragged
3891 // over a different wxAuiNotebook control
3892 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
3893 {
3894 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(screen_pt);
3895
3896 // if we aren't over any window, stop here
3897 if (!tab_ctrl)
3898 return;
3899
3900 // make sure we are not over the hint window
3901 if (!tab_ctrl->IsKindOf(CLASSINFO(wxFrame)))
3902 {
3903 while (tab_ctrl)
3904 {
3905 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
3906 break;
3907 tab_ctrl = tab_ctrl->GetParent();
3908 }
3909
3910 if (tab_ctrl)
3911 {
3912 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
3913
3914 if (nb != this)
3915 {
3916 wxRect hint_rect = tab_ctrl->GetClientRect();
3917 tab_ctrl->ClientToScreen(&hint_rect.x, &hint_rect.y);
3918 m_mgr.ShowHint(hint_rect);
3919 return;
3920 }
3921 }
3922 }
3923 else
3924 {
3925 if (!dest_tabs)
3926 {
3927 // we are either over a hint window, or not over a tab
3928 // window, and there is no where to drag to, so exit
3929 return;
3930 }
3931 }
3932 }
3933
3934
3935 // if there are less than two panes, split can't happen, so leave
3936 if (m_tabs.GetPageCount() < 2)
3937 return;
3938
3939 // if tab moving is not allowed, leave
3940 if (!(m_flags & wxAUI_NB_TAB_SPLIT))
3941 return;
3942
3943
3944 if (src_tabs)
3945 {
3946 src_tabs->SetCursor(wxCursor(wxCURSOR_SIZING));
3947 }
3948
3949
3950 if (dest_tabs)
3951 {
3952 wxRect hint_rect = dest_tabs->GetRect();
3953 ClientToScreen(&hint_rect.x, &hint_rect.y);
3954 m_mgr.ShowHint(hint_rect);
3955 }
3956 else
3957 {
3958 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
3959 }
3960 }
3961
3962
3963
OnTabEndDrag(wxCommandEvent & command_evt)3964 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
3965 {
3966 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
3967
3968 m_mgr.HideHint();
3969
3970
3971 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
3972 wxAuiTabCtrl* dest_tabs = NULL;
3973 if (src_tabs)
3974 {
3975 // set cursor back to an arrow
3976 src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
3977 }
3978
3979 // get the mouse position, which will be used to determine the drop point
3980 wxPoint mouse_screen_pt = ::wxGetMousePosition();
3981 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
3982
3983
3984
3985 // check for an external move
3986 if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
3987 {
3988 wxWindow* tab_ctrl = ::wxFindWindowAtPoint(mouse_screen_pt);
3989
3990 while (tab_ctrl)
3991 {
3992 if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
3993 break;
3994 tab_ctrl = tab_ctrl->GetParent();
3995 }
3996
3997 if (tab_ctrl)
3998 {
3999 wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
4000
4001 if (nb != this)
4002 {
4003 // find out from the destination control
4004 // if it's ok to drop this tab here
4005 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, m_windowId);
4006 e.SetSelection(evt.GetSelection());
4007 e.SetOldSelection(evt.GetSelection());
4008 e.SetEventObject(this);
4009 e.SetDragSource(this);
4010 e.Veto(); // dropping must be explicitly approved by control owner
4011
4012 nb->GetEventHandler()->ProcessEvent(e);
4013
4014 if (!e.IsAllowed())
4015 {
4016 // no answer or negative answer
4017 m_mgr.HideHint();
4018 return;
4019 }
4020
4021 // drop was allowed
4022 int src_idx = evt.GetSelection();
4023 wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx);
4024
4025 // Check that it's not an impossible parent relationship
4026 wxWindow* p = nb;
4027 while (p && !p->IsTopLevel())
4028 {
4029 if (p == src_page)
4030 {
4031 return;
4032 }
4033 p = p->GetParent();
4034 }
4035
4036 // get main index of the page
4037 int main_idx = m_tabs.GetIdxFromWindow(src_page);
4038
4039 // make a copy of the page info
4040 wxAuiNotebookPage page_info = m_tabs.GetPage((size_t)main_idx);
4041
4042 // remove the page from the source notebook
4043 RemovePage(main_idx);
4044
4045 // reparent the page
4046 src_page->Reparent(nb);
4047
4048
4049 // found out the insert idx
4050 wxAuiTabCtrl* dest_tabs = (wxAuiTabCtrl*)tab_ctrl;
4051 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
4052
4053 wxWindow* target = NULL;
4054 int insert_idx = -1;
4055 dest_tabs->TabHitTest(pt.x, pt.y, &target);
4056 if (target)
4057 {
4058 insert_idx = dest_tabs->GetIdxFromWindow(target);
4059 }
4060
4061
4062 // add the page to the new notebook
4063 if (insert_idx == -1)
4064 insert_idx = dest_tabs->GetPageCount();
4065 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
4066 nb->m_tabs.AddPage(page_info.window, page_info);
4067
4068 nb->DoSizing();
4069 dest_tabs->DoShowHide();
4070 dest_tabs->Refresh();
4071
4072 // set the selection in the destination tab control
4073 nb->SetSelection(nb->m_tabs.GetIdxFromWindow(page_info.window));
4074
4075 // notify owner that the tab has been dragged
4076 wxAuiNotebookEvent e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, m_windowId);
4077 e2.SetSelection(evt.GetSelection());
4078 e2.SetOldSelection(evt.GetSelection());
4079 e2.SetEventObject(this);
4080 GetEventHandler()->ProcessEvent(e2);
4081
4082 return;
4083 }
4084 }
4085 }
4086
4087
4088
4089
4090 // only perform a tab split if it's allowed
4091 if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2)
4092 {
4093 // If the pointer is in an existing tab frame, do a tab insert
4094 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
4095 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
4096 int insert_idx = -1;
4097 if (tab_frame)
4098 {
4099 dest_tabs = tab_frame->m_tabs;
4100
4101 if (dest_tabs == src_tabs)
4102 return;
4103
4104
4105 wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
4106 wxWindow* target = NULL;
4107 dest_tabs->TabHitTest(pt.x, pt.y, &target);
4108 if (target)
4109 {
4110 insert_idx = dest_tabs->GetIdxFromWindow(target);
4111 }
4112 }
4113 else
4114 {
4115 wxPoint zero(0,0);
4116 wxRect rect = m_mgr.CalculateHintRect(m_dummy_wnd,
4117 mouse_client_pt,
4118 zero);
4119 if (rect.IsEmpty())
4120 {
4121 // there is no suitable drop location here, exit out
4122 return;
4123 }
4124
4125 // If there is no tabframe at all, create one
4126 wxTabFrame* new_tabs = new wxTabFrame;
4127 new_tabs->m_rect = wxRect(wxPoint(0,0), CalculateNewSplitSize());
4128 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
4129 new_tabs->m_tabs = new wxAuiTabCtrl(this,
4130 m_tab_id_counter++,
4131 wxDefaultPosition,
4132 wxDefaultSize,
4133 wxNO_BORDER|wxWANTS_CHARS);
4134 new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
4135 new_tabs->m_tabs->SetFlags(m_flags);
4136
4137 m_mgr.AddPane(new_tabs,
4138 wxAuiPaneInfo().Bottom().CaptionVisible(false),
4139 mouse_client_pt);
4140 m_mgr.Update();
4141 dest_tabs = new_tabs->m_tabs;
4142 }
4143
4144
4145
4146 // remove the page from the source tabs
4147 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
4148 page_info.active = false;
4149 src_tabs->RemovePage(page_info.window);
4150 if (src_tabs->GetPageCount() > 0)
4151 {
4152 src_tabs->SetActivePage((size_t)0);
4153 src_tabs->DoShowHide();
4154 src_tabs->Refresh();
4155 }
4156
4157
4158
4159 // add the page to the destination tabs
4160 if (insert_idx == -1)
4161 insert_idx = dest_tabs->GetPageCount();
4162 dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
4163
4164 if (src_tabs->GetPageCount() == 0)
4165 {
4166 RemoveEmptyTabFrames();
4167 }
4168
4169 DoSizing();
4170 dest_tabs->DoShowHide();
4171 dest_tabs->Refresh();
4172
4173 // force the set selection function reset the selection
4174 m_curpage = -1;
4175
4176 // set the active page to the one we just split off
4177 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
4178
4179 UpdateHintWindowSize();
4180 }
4181
4182 // notify owner that the tab has been dragged
4183 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, m_windowId);
4184 e.SetSelection(evt.GetSelection());
4185 e.SetOldSelection(evt.GetSelection());
4186 e.SetEventObject(this);
4187 GetEventHandler()->ProcessEvent(e);
4188 }
4189
4190
4191
GetTabCtrlFromPoint(const wxPoint & pt)4192 wxAuiTabCtrl* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
4193 {
4194 // if we've just removed the last tab from the source
4195 // tab set, the remove the tab control completely
4196 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
4197 size_t i, pane_count = all_panes.GetCount();
4198 for (i = 0; i < pane_count; ++i)
4199 {
4200 if (all_panes.Item(i).name == wxT("dummy"))
4201 continue;
4202
4203 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4204 if (tabframe->m_tab_rect.Contains(pt))
4205 return tabframe->m_tabs;
4206 }
4207
4208 return NULL;
4209 }
4210
GetTabFrameFromTabCtrl(wxWindow * tab_ctrl)4211 wxWindow* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
4212 {
4213 // if we've just removed the last tab from the source
4214 // tab set, the remove the tab control completely
4215 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
4216 size_t i, pane_count = all_panes.GetCount();
4217 for (i = 0; i < pane_count; ++i)
4218 {
4219 if (all_panes.Item(i).name == wxT("dummy"))
4220 continue;
4221
4222 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4223 if (tabframe->m_tabs == tab_ctrl)
4224 {
4225 return tabframe;
4226 }
4227 }
4228
4229 return NULL;
4230 }
4231
RemoveEmptyTabFrames()4232 void wxAuiNotebook::RemoveEmptyTabFrames()
4233 {
4234 // if we've just removed the last tab from the source
4235 // tab set, the remove the tab control completely
4236 wxAuiPaneInfoArray all_panes = m_mgr.GetAllPanes();
4237 size_t i, pane_count = all_panes.GetCount();
4238 for (i = 0; i < pane_count; ++i)
4239 {
4240 if (all_panes.Item(i).name == wxT("dummy"))
4241 continue;
4242
4243 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
4244 if (tab_frame->m_tabs->GetPageCount() == 0)
4245 {
4246 m_mgr.DetachPane(tab_frame);
4247
4248 // use pending delete because sometimes during
4249 // window closing, refreshs are pending
4250 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4251 wxPendingDelete.Append(tab_frame->m_tabs);
4252
4253 tab_frame->m_tabs = NULL;
4254
4255 delete tab_frame;
4256 }
4257 }
4258
4259
4260 // check to see if there is still a center pane;
4261 // if there isn't, make a frame the center pane
4262 wxAuiPaneInfoArray panes = m_mgr.GetAllPanes();
4263 pane_count = panes.GetCount();
4264 wxWindow* first_good = NULL;
4265 bool center_found = false;
4266 for (i = 0; i < pane_count; ++i)
4267 {
4268 if (panes.Item(i).name == wxT("dummy"))
4269 continue;
4270 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
4271 center_found = true;
4272 if (!first_good)
4273 first_good = panes.Item(i).window;
4274 }
4275
4276 if (!center_found && first_good)
4277 {
4278 m_mgr.GetPane(first_good).Centre();
4279 }
4280
4281 if (!m_isBeingDeleted)
4282 m_mgr.Update();
4283 }
4284
OnChildFocus(wxChildFocusEvent & evt)4285 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent& evt)
4286 {
4287 // if we're dragging a tab, don't change the current selection.
4288 // This code prevents a bug that used to happen when the hint window
4289 // was hidden. In the bug, the focus would return to the notebook
4290 // child, which would then enter this handler and call
4291 // SetSelection, which is not desired turn tab dragging.
4292
4293 wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
4294 size_t i, pane_count = all_panes.GetCount();
4295 for (i = 0; i < pane_count; ++i)
4296 {
4297 wxAuiPaneInfo& pane = all_panes.Item(i);
4298 if (pane.name == wxT("dummy"))
4299 continue;
4300 wxTabFrame* tabframe = (wxTabFrame*)pane.window;
4301 if (tabframe->m_tabs->IsDragging())
4302 return;
4303 }
4304
4305
4306 // change the tab selection to the child
4307 // which was focused
4308 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
4309 if (idx != -1 && idx != m_curpage)
4310 {
4311 SetSelection(idx);
4312 }
4313 }
4314
OnNavigationKey(wxNavigationKeyEvent & event)4315 void wxAuiNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
4316 {
4317 if ( event.IsWindowChange() ) {
4318 // change pages
4319 // FIXME: the problem with this is that if we have a split notebook,
4320 // we selection may go all over the place.
4321 AdvanceSelection(event.GetDirection());
4322 }
4323 else {
4324 // we get this event in 3 cases
4325 //
4326 // a) one of our pages might have generated it because the user TABbed
4327 // out from it in which case we should propagate the event upwards and
4328 // our parent will take care of setting the focus to prev/next sibling
4329 //
4330 // or
4331 //
4332 // b) the parent panel wants to give the focus to us so that we
4333 // forward it to our selected page. We can't deal with this in
4334 // OnSetFocus() because we don't know which direction the focus came
4335 // from in this case and so can't choose between setting the focus to
4336 // first or last panel child
4337 //
4338 // or
4339 //
4340 // c) we ourselves (see MSWTranslateMessage) generated the event
4341 //
4342 wxWindow * const parent = GetParent();
4343
4344 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4345 const bool isFromParent = event.GetEventObject() == (wxObject*) parent;
4346 const bool isFromSelf = event.GetEventObject() == (wxObject*) this;
4347
4348 if ( isFromParent || isFromSelf )
4349 {
4350 // no, it doesn't come from child, case (b) or (c): forward to a
4351 // page but only if direction is backwards (TAB) or from ourselves,
4352 if ( GetSelection() != wxNOT_FOUND &&
4353 (!event.GetDirection() || isFromSelf) )
4354 {
4355 // so that the page knows that the event comes from it's parent
4356 // and is being propagated downwards
4357 event.SetEventObject(this);
4358
4359 wxWindow *page = GetPage(GetSelection());
4360 if ( !page->GetEventHandler()->ProcessEvent(event) )
4361 {
4362 page->SetFocus();
4363 }
4364 //else: page manages focus inside it itself
4365 }
4366 else // otherwise set the focus to the notebook itself
4367 {
4368 SetFocus();
4369 }
4370 }
4371 else
4372 {
4373 // it comes from our child, case (a), pass to the parent, but only
4374 // if the direction is forwards. Otherwise set the focus to the
4375 // notebook itself. The notebook is always the 'first' control of a
4376 // page.
4377 if ( !event.GetDirection() )
4378 {
4379 SetFocus();
4380 }
4381 else if ( parent )
4382 {
4383 event.SetCurrentFocus(this);
4384 parent->GetEventHandler()->ProcessEvent(event);
4385 }
4386 }
4387 }
4388 }
4389
OnTabButton(wxCommandEvent & command_evt)4390 void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
4391 {
4392 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
4393 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4394
4395 int button_id = evt.GetInt();
4396
4397 if (button_id == wxAUI_BUTTON_CLOSE)
4398 {
4399 int selection = evt.GetSelection();
4400
4401 if (selection == -1)
4402 {
4403 // if the close button is to the right, use the active
4404 // page selection to determine which page to close
4405 selection = tabs->GetActivePage();
4406 }
4407
4408 if (selection != -1)
4409 {
4410 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4411
4412 // ask owner if it's ok to close the tab
4413 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, m_windowId);
4414 const int idx = m_tabs.GetIdxFromWindow(close_wnd);
4415 e.SetSelection(idx);
4416 e.SetOldSelection(evt.GetSelection());
4417 e.SetEventObject(this);
4418 GetEventHandler()->ProcessEvent(e);
4419 if (!e.IsAllowed())
4420 return;
4421
4422
4423 #if wxUSE_MDI
4424 if (close_wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
4425 {
4426 close_wnd->Close();
4427 }
4428 else
4429 #endif
4430 {
4431 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
4432 DeletePage(main_idx);
4433 }
4434
4435 // notify owner that the tab has been closed
4436 wxAuiNotebookEvent e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, m_windowId);
4437 e2.SetSelection(idx);
4438 e2.SetEventObject(this);
4439 GetEventHandler()->ProcessEvent(e2);
4440 }
4441 }
4442 }
4443
OnTabMiddleDown(wxCommandEvent & evt)4444 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent& evt)
4445 {
4446 // patch event through to owner
4447 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4448 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4449
4450 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
4451 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4452 e.SetEventObject(this);
4453 GetEventHandler()->ProcessEvent(e);
4454 }
4455
OnTabMiddleUp(wxCommandEvent & evt)4456 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent& evt)
4457 {
4458 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4459 // click should act like a tab close action. However, first
4460 // give the owner an opportunity to handle the middle up event
4461 // for custom action
4462
4463 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4464 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4465
4466 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
4467 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4468 e.SetEventObject(this);
4469 if (GetEventHandler()->ProcessEvent(e))
4470 return;
4471 if (!e.IsAllowed())
4472 return;
4473
4474 // check if we are supposed to close on middle-up
4475 if ((m_flags & wxAUI_NB_MIDDLE_CLICK_CLOSE) == 0)
4476 return;
4477
4478 // simulate the user pressing the close button on the tab
4479 evt.SetInt(wxAUI_BUTTON_CLOSE);
4480 OnTabButton(evt);
4481 }
4482
OnTabRightDown(wxCommandEvent & evt)4483 void wxAuiNotebook::OnTabRightDown(wxCommandEvent& evt)
4484 {
4485 // patch event through to owner
4486 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4487 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4488
4489 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
4490 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4491 e.SetEventObject(this);
4492 GetEventHandler()->ProcessEvent(e);
4493 }
4494
OnTabRightUp(wxCommandEvent & evt)4495 void wxAuiNotebook::OnTabRightUp(wxCommandEvent& evt)
4496 {
4497 // patch event through to owner
4498 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4499 wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
4500
4501 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
4502 e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
4503 e.SetEventObject(this);
4504 GetEventHandler()->ProcessEvent(e);
4505 }
4506
4507
4508
4509 // Sets the normal font
SetNormalFont(const wxFont & font)4510 void wxAuiNotebook::SetNormalFont(const wxFont& font)
4511 {
4512 m_normal_font = font;
4513 GetArtProvider()->SetNormalFont(font);
4514 }
4515
4516 // Sets the selected tab font
SetSelectedFont(const wxFont & font)4517 void wxAuiNotebook::SetSelectedFont(const wxFont& font)
4518 {
4519 m_selected_font = font;
4520 GetArtProvider()->SetSelectedFont(font);
4521 }
4522
4523 // Sets the measuring font
SetMeasuringFont(const wxFont & font)4524 void wxAuiNotebook::SetMeasuringFont(const wxFont& font)
4525 {
4526 GetArtProvider()->SetMeasuringFont(font);
4527 }
4528
4529 // Sets the tab font
SetFont(const wxFont & font)4530 bool wxAuiNotebook::SetFont(const wxFont& font)
4531 {
4532 wxControl::SetFont(font);
4533
4534 wxFont normalFont(font);
4535 wxFont selectedFont(normalFont);
4536 selectedFont.SetWeight(wxBOLD);
4537
4538 SetNormalFont(normalFont);
4539 SetSelectedFont(selectedFont);
4540 SetMeasuringFont(selectedFont);
4541
4542 return true;
4543 }
4544
4545 // Gets the tab control height
GetTabCtrlHeight() const4546 int wxAuiNotebook::GetTabCtrlHeight() const
4547 {
4548 return m_tab_ctrl_height;
4549 }
4550
4551 // Gets the height of the notebook for a given page height
GetHeightForPageHeight(int pageHeight)4552 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight)
4553 {
4554 UpdateTabCtrlHeight();
4555
4556 int tabCtrlHeight = GetTabCtrlHeight();
4557 int decorHeight = 2;
4558 return tabCtrlHeight + pageHeight + decorHeight;
4559 }
4560
4561 // Advances the selection, generation page selection events
AdvanceSelection(bool forward)4562 void wxAuiNotebook::AdvanceSelection(bool forward)
4563 {
4564 if (GetPageCount() <= 1)
4565 return;
4566
4567 int currentSelection = GetSelection();
4568
4569 if (forward)
4570 {
4571 if (currentSelection == (int) (GetPageCount() - 1))
4572 return;
4573 else if (currentSelection == -1)
4574 currentSelection = 0;
4575 else
4576 currentSelection ++;
4577 }
4578 else
4579 {
4580 if (currentSelection <= 0)
4581 return;
4582 else
4583 currentSelection --;
4584 }
4585
4586 SetSelection(currentSelection);
4587 }
4588
4589 // Shows the window menu
ShowWindowMenu()4590 bool wxAuiNotebook::ShowWindowMenu()
4591 {
4592 wxAuiTabCtrl* tabCtrl = GetActiveTabCtrl();
4593
4594 int idx = tabCtrl->GetArtProvider()->ShowDropDown(tabCtrl, tabCtrl->GetPages(), tabCtrl->GetActivePage());
4595
4596 if (idx != -1)
4597 {
4598 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, tabCtrl->GetId());
4599 e.SetSelection(idx);
4600 e.SetOldSelection(tabCtrl->GetActivePage());
4601 e.SetEventObject(tabCtrl);
4602 GetEventHandler()->ProcessEvent(e);
4603
4604 return true;
4605 }
4606 else
4607 return false;
4608 }
4609
4610 #endif // wxUSE_AUI
4611