1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/auibook.cpp
3 // Purpose: wxaui: wx advanced user interface - notebook
4 // Author: Benjamin I. Williams
7 // Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
8 // Licence: wxWindows Library Licence, Version 3.1
9 ///////////////////////////////////////////////////////////////////////////////
11 // ----------------------------------------------------------------------------
13 // ----------------------------------------------------------------------------
15 #include "wx/wxprec.h"
23 #include "wx/aui/auibook.h"
26 #include "wx/settings.h"
30 #include "wx/aui/tabmdi.h"
31 #include "wx/dcbuffer.h"
35 #include "wx/mac/carbon/private.h"
38 #include "wx/arrimpl.cpp"
39 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
40 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
52 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
53 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
54 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
60 // This functions are here for this proof of concept
61 // and will be factored out later. See dockart.cpp
62 static wxColor
StepColour(const wxColor
& c
, int percent
)
64 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
65 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
66 (unsigned char)wxMin((g
*percent
)/100,255),
67 (unsigned char)wxMin((b
*percent
)/100,255));
70 // This functions are here for this proof of concept
71 // and will be factored out later. See dockart.cpp
72 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
73 const wxColour
& color
)
75 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
76 img
.Replace(0,0,0,123,123,123);
77 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
78 img
.SetMaskColour(123,123,123);
82 static void DrawButtons(wxDC
& dc
,
85 const wxColour
& bkcolour
,
90 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
96 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
97 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
99 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
100 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
102 // draw the background behind the button
103 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
106 // draw the button itself
107 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
110 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
112 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
119 // chops the text so that it fits within |max_size| pixels.
120 // Also adds an elipsis if necessary
122 static wxString
ChopText(wxDC
& dc
, const wxString
& text
, int max_size
)
126 // first check if the text fits with no problems
127 dc
.GetTextExtent(text
, &x
, &y
);
131 size_t i
, len
= text
.Length();
132 size_t last_good_length
= 0;
133 for (i
= 0; i
< len
; ++i
)
135 wxString s
= text
.Left(i
);
138 dc
.GetTextExtent(s
, &x
, &y
);
142 last_good_length
= i
;
145 wxString ret
= text
.Left(last_good_length
);
151 // -- GUI helper classes and functions --
153 class wxAuiCommandCapture
: public wxEvtHandler
157 wxAuiCommandCapture() { m_last_id
= 0; }
158 int GetCommandId() const { return m_last_id
; }
160 bool ProcessEvent(wxEvent
& evt
)
162 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
164 m_last_id
= evt
.GetId();
168 if (GetNextHandler())
169 return GetNextHandler()->ProcessEvent(evt
);
181 #if defined( __WXMAC__ )
182 static unsigned char close_bits
[]={
183 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
184 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
185 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
186 #elif defined( __WXGTK__)
187 static unsigned char close_bits
[]={
188 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
189 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
190 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
192 static unsigned char close_bits
[]={
193 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
194 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
198 static unsigned char left_bits
[] = {
199 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
200 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
201 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
203 static unsigned char right_bits
[] = {
204 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
205 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
208 static unsigned char list_bits
[] = {
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
218 // -- wxAuiDefaultTabArt class implementation --
220 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
222 m_normal_font
= *wxNORMAL_FONT
;
223 m_selected_font
= *wxNORMAL_FONT
;
224 m_selected_font
.SetWeight(wxBOLD
);
225 m_measuring_font
= m_selected_font
;
227 m_fixed_tab_width
= 100;
228 m_tab_ctrl_height
= 0;
231 wxBrush toolbarbrush
;
232 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
233 wxColor base_colour
= toolbarbrush
.GetColour();
235 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
238 m_base_colour
= base_colour
;
239 wxColor darker2_colour
= StepColour(base_colour
, 70);
241 m_border_pen
= wxPen(darker2_colour
);
242 m_base_colour_pen
= wxPen(m_base_colour
);
243 m_base_colour_brush
= wxBrush(m_base_colour
);
245 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
246 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
248 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
249 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
251 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
252 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
254 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
255 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
260 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
264 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
266 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
269 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
274 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
277 m_fixed_tab_width
= 100;
279 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
282 m_fixed_tab_width
= tot_width
/(int)tab_count
;
286 if (m_fixed_tab_width
< 100)
287 m_fixed_tab_width
= 100;
289 if (m_fixed_tab_width
> tot_width
/2)
290 m_fixed_tab_width
= tot_width
/2;
292 if (m_fixed_tab_width
> 220)
293 m_fixed_tab_width
= 220;
295 m_tab_ctrl_height
= tab_ctrl_size
.y
;
299 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
300 wxWindow
* WXUNUSED(wnd
),
304 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
305 wxColor start_colour
= StepColour(m_base_colour
, 90);
306 wxColor end_colour
= StepColour(m_base_colour
, 110);
307 dc
.GradientFillLinear(r
, start_colour
, end_colour
, wxSOUTH
);
310 int y
= rect
.GetHeight();
311 int w
= rect
.GetWidth();
312 dc
.SetPen(m_border_pen
);
313 dc
.DrawLine(0, y
-4, w
, y
-4);
314 dc
.DrawLine(0, y
-1, w
, y
-1);
315 dc
.SetPen(wxPen(start_colour
));
316 dc
.DrawLine(0, y
-3, w
, y
-3);
317 dc
.DrawLine(0, y
-2, w
, y
-2);
321 // DrawTab() draws an individual tab.
324 // in_rect - rectangle the tab should be confined to
325 // caption - tab's caption
326 // active - whether or not the tab is active
327 // out_rect - actual output rectangle
328 // x_extent - the advance x; where the next tab should start
330 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
332 const wxRect
& in_rect
,
333 const wxString
& caption_text
,
334 const wxBitmap
& bitmap
,
336 int close_button_state
,
337 wxRect
* out_tab_rect
,
338 wxRect
* out_button_rect
,
341 wxCoord normal_textx
, normal_texty
;
342 wxCoord selected_textx
, selected_texty
;
343 wxCoord textx
, texty
;
345 // if the caption is empty, measure some temporary text
346 wxString caption
= caption_text
;
347 if (caption_text
.empty())
350 dc
.SetFont(m_selected_font
);
351 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
353 dc
.SetFont(m_normal_font
);
354 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
356 // figure out the size of the tab
357 wxSize tab_size
= GetTabSize(dc
,
365 wxCoord tab_height
= m_tab_ctrl_height
- 3;
366 wxCoord tab_width
= tab_size
.x
;
367 wxCoord tab_x
= in_rect
.x
;
368 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
371 caption
= caption_text
;
374 // select pen, brush and font for the tab to be drawn
378 dc
.SetFont(m_selected_font
);
379 textx
= selected_textx
;
380 texty
= selected_texty
;
384 dc
.SetFont(m_normal_font
);
385 textx
= normal_textx
;
386 texty
= normal_texty
;
390 // create points that will make the tab outline
392 wxPoint clip_points
[6];
393 clip_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-3);
394 clip_points
[1] = wxPoint(tab_x
, tab_y
+2);
395 clip_points
[2] = wxPoint(tab_x
+2, tab_y
);
396 clip_points
[3] = wxPoint(tab_x
+tab_width
-1, tab_y
);
397 clip_points
[4] = wxPoint(tab_x
+tab_width
+1, tab_y
+2);
398 clip_points
[5] = wxPoint(tab_x
+tab_width
+1, tab_y
+tab_height
-3);
400 // set the clipping region for the tab --
401 wxRegion
clipping_region(6, clip_points
);
402 dc
.SetClippingRegion(clipping_region
);
404 wxPoint border_points
[6];
405 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
406 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
407 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
408 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
409 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
410 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
413 int drawn_tab_yoff
= border_points
[1].y
;
414 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
421 // draw base background color
422 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
423 dc
.SetPen(m_base_colour_pen
);
424 dc
.SetBrush(m_base_colour_brush
);
425 dc
.DrawRectangle(r
.x
, r
.y
, r
.width
, r
.height
);
427 // this white helps fill out the gradient at the top of the tab
428 dc
.SetPen(*wxWHITE_PEN
);
429 dc
.SetBrush(*wxWHITE_BRUSH
);
430 dc
.DrawRectangle(r
.x
+2, r
.y
+2, r
.width
-3, r
.height
);
432 // these two points help the rounded corners appear more antialiased
433 dc
.SetPen(m_base_colour_pen
);
434 dc
.DrawPoint(r
.x
+2, r
.y
+2);
435 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+2);
437 // set rectangle down a bit for gradient drawing
438 r
.SetHeight(r
.GetHeight()/2);
443 // draw gradient background
444 wxColor start_color
= StepColour(m_base_colour
, 95);
445 wxColor end_color
= *wxWHITE
;
446 dc
.GradientFillLinear(r
, start_color
, end_color
, wxNORTH
);
452 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
454 // draw base background color for inactive tabs
455 dc
.SetPen(m_base_colour_pen
);
456 dc
.SetBrush(m_base_colour_brush
);
457 dc
.DrawRectangle(r
.x
, r
.y
, r
.width
, r
.height
);
459 // start the gradent up a bit and leave the inside border inset
460 // by a pixel for a 3D look. Only the top half of the inactive
461 // tab will have a slight gradient
466 // -- draw bottom gradient fill for glossy look
467 wxColor top_color
= m_base_colour
;
468 wxColor bottom_color
= StepColour(top_color
, 106);
469 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
473 dc
.SetPen(m_border_pen
);
474 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
475 dc
.DrawPolygon(6, border_points
);
477 // there are two horizontal grey lines at the bottom of the tab control,
478 // this gets rid of the top one of those lines in the tab control
481 wxColor start_color
= StepColour(m_base_colour
, 93);
482 dc
.SetPen(wxPen(start_color
));
483 dc
.DrawLine(border_points
[0].x
,
485 border_points
[5].x
+1,
490 int text_offset
= tab_x
+ 8;
491 int close_button_width
= 0;
492 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
494 close_button_width
= m_active_close_bmp
.GetWidth();
500 int bitmap_offset
= tab_x
+ 8;
503 dc
.DrawBitmap(bitmap
,
505 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2) + 1,
508 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
509 text_offset
+= 3; // bitmap padding
513 text_offset
= tab_x
+ 8;
517 wxString draw_text
= ChopText(dc
,
519 tab_width
- (text_offset
-tab_x
) - close_button_width
);
522 dc
.DrawText(draw_text
,
524 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
529 // draw close button if necessary
530 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
532 wxBitmap bmp
= m_disabled_close_bmp
;
534 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
535 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
537 bmp
= m_active_close_bmp
;
540 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
541 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
544 IndentPressedBitmap(&rect
, close_button_state
);
545 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
547 *out_button_rect
= rect
;
550 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
552 dc
.DestroyClippingRegion();
555 int wxAuiDefaultTabArt::GetIndentSize()
560 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
561 wxWindow
* WXUNUSED(wnd
),
562 const wxString
& caption
,
563 const wxBitmap
& bitmap
,
564 bool WXUNUSED(active
),
565 int close_button_state
,
568 wxCoord measured_textx
, measured_texty
, tmp
;
570 dc
.SetFont(m_measuring_font
);
571 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
573 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
575 // add padding around the text
576 wxCoord tab_width
= measured_textx
;
577 wxCoord tab_height
= measured_texty
;
579 // if the close button is showing, add space for it
580 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
581 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
583 // if there's a bitmap, add space for it
586 tab_width
+= bitmap
.GetWidth();
587 tab_width
+= 3; // right side bitmap padding
588 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
595 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
597 tab_width
= m_fixed_tab_width
;
600 *x_extent
= tab_width
;
602 return wxSize(tab_width
, tab_height
);
606 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
607 wxWindow
* WXUNUSED(wnd
),
608 const wxRect
& in_rect
,
612 const wxBitmap
& bitmap_override
,
618 if (bitmap_override
.IsOk())
620 bmp
= bitmap_override
;
626 case wxAUI_BUTTON_CLOSE
:
627 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
628 bmp
= m_disabled_close_bmp
;
630 bmp
= m_active_close_bmp
;
632 case wxAUI_BUTTON_LEFT
:
633 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
634 bmp
= m_disabled_left_bmp
;
636 bmp
= m_active_left_bmp
;
638 case wxAUI_BUTTON_RIGHT
:
639 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
640 bmp
= m_disabled_right_bmp
;
642 bmp
= m_active_right_bmp
;
644 case wxAUI_BUTTON_WINDOWLIST
:
645 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
646 bmp
= m_disabled_windowlist_bmp
;
648 bmp
= m_active_windowlist_bmp
;
658 if (orientation
== wxLEFT
)
660 rect
.SetX(in_rect
.x
);
661 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
662 rect
.SetWidth(bmp
.GetWidth());
663 rect
.SetHeight(bmp
.GetHeight());
667 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
668 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
669 bmp
.GetWidth(), bmp
.GetHeight());
672 IndentPressedBitmap(&rect
, button_state
);
673 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
679 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
680 const wxArrayString
& items
,
685 size_t i
, count
= items
.GetCount();
686 for (i
= 0; i
< count
; ++i
)
688 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
691 if (active_idx
!= -1)
693 menuPopup
.Check(1000+active_idx
, true);
696 // find out where to put the popup menu of window
697 // items. Subtract 100 for now to center the menu
698 // a bit, until a better mechanism can be implemented
699 wxPoint pt
= ::wxGetMousePosition();
700 pt
= wnd
->ScreenToClient(pt
);
706 // find out the screen coordinate at the bottom of the tab ctrl
707 wxRect cli_rect
= wnd
->GetClientRect();
708 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
710 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
711 wnd
->PushEventHandler(cc
);
712 wnd
->PopupMenu(&menuPopup
, pt
);
713 int command
= cc
->GetCommandId();
714 wnd
->PopEventHandler(true);
722 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
723 wxAuiNotebookPageArray
& pages
)
726 dc
.SetFont(m_measuring_font
);
729 size_t i
, page_count
= pages
.GetCount();
730 for (i
= 0; i
< page_count
; ++i
)
732 wxAuiNotebookPage
& page
= pages
.Item(i
);
734 // we don't use the caption text because we don't
735 // want tab heights to be different in the case
736 // of a very short piece of text on one tab and a very
737 // tall piece of text on another tab
739 wxSize s
= GetTabSize(dc
,
744 wxAUI_BUTTON_STATE_HIDDEN
,
746 max_y
= wxMax(max_y
, s
.y
);
752 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
754 m_normal_font
= font
;
757 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
759 m_selected_font
= font
;
762 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
764 m_measuring_font
= font
;
768 // -- wxAuiSimpleTabArt class implementation --
770 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
772 m_normal_font
= *wxNORMAL_FONT
;
773 m_selected_font
= *wxNORMAL_FONT
;
774 m_selected_font
.SetWeight(wxBOLD
);
775 m_measuring_font
= m_selected_font
;
778 m_fixed_tab_width
= 100;
780 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
782 wxColour background_colour
= StepColour(base_colour
, 95);
783 wxColour normaltab_colour
= base_colour
;
784 wxColour selectedtab_colour
= *wxWHITE
;
786 m_bkbrush
= wxBrush(background_colour
);
787 m_normal_bkbrush
= wxBrush(normaltab_colour
);
788 m_normal_bkpen
= wxPen(normaltab_colour
);
789 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
790 m_selected_bkpen
= wxPen(selectedtab_colour
);
792 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
793 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
795 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
796 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
798 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
799 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
801 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
802 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
806 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
810 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
812 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
816 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
821 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
824 m_fixed_tab_width
= 100;
826 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
829 m_fixed_tab_width
= tot_width
/(int)tab_count
;
833 if (m_fixed_tab_width
< 100)
834 m_fixed_tab_width
= 100;
836 if (m_fixed_tab_width
> tot_width
/2)
837 m_fixed_tab_width
= tot_width
/2;
839 if (m_fixed_tab_width
> 220)
840 m_fixed_tab_width
= 220;
843 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
844 wxWindow
* WXUNUSED(wnd
),
848 dc
.SetBrush(m_bkbrush
);
849 dc
.SetPen(*wxTRANSPARENT_PEN
);
850 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
853 dc
.SetPen(*wxGREY_PEN
);
854 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
858 // DrawTab() draws an individual tab.
861 // in_rect - rectangle the tab should be confined to
862 // caption - tab's caption
863 // active - whether or not the tab is active
864 // out_rect - actual output rectangle
865 // x_extent - the advance x; where the next tab should start
867 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
869 const wxRect
& in_rect
,
870 const wxString
& caption_text
,
871 const wxBitmap
& bitmap
,
873 int close_button_state
,
874 wxRect
* out_tab_rect
,
875 wxRect
* out_button_rect
,
878 wxCoord normal_textx
, normal_texty
;
879 wxCoord selected_textx
, selected_texty
;
880 wxCoord textx
, texty
;
882 // if the caption is empty, measure some temporary text
883 wxString caption
= caption_text
;
884 if (caption_text
.empty())
887 dc
.SetFont(m_selected_font
);
888 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
890 dc
.SetFont(m_normal_font
);
891 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
893 // figure out the size of the tab
894 wxSize tab_size
= GetTabSize(dc
,
902 wxCoord tab_height
= tab_size
.y
;
903 wxCoord tab_width
= tab_size
.x
;
904 wxCoord tab_x
= in_rect
.x
;
905 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
907 caption
= caption_text
;
909 // select pen, brush and font for the tab to be drawn
913 dc
.SetPen(m_selected_bkpen
);
914 dc
.SetBrush(m_selected_bkbrush
);
915 dc
.SetFont(m_selected_font
);
916 textx
= selected_textx
;
917 texty
= selected_texty
;
921 dc
.SetPen(m_normal_bkpen
);
922 dc
.SetBrush(m_normal_bkbrush
);
923 dc
.SetFont(m_normal_font
);
924 textx
= normal_textx
;
925 texty
= normal_texty
;
933 points
[0].y
= tab_y
+ tab_height
- 1;
934 points
[1].x
= tab_x
+ tab_height
- 3;
935 points
[1].y
= tab_y
+ 2;
936 points
[2].x
= tab_x
+ tab_height
+ 3;
938 points
[3].x
= tab_x
+ tab_width
- 2;
940 points
[4].x
= tab_x
+ tab_width
;
941 points
[4].y
= tab_y
+ 2;
942 points
[5].x
= tab_x
+ tab_width
;
943 points
[5].y
= tab_y
+ tab_height
- 1;
944 points
[6] = points
[0];
946 dc
.SetClippingRegion(in_rect
);
948 dc
.DrawPolygon(6, points
);
950 dc
.SetPen(*wxGREY_PEN
);
952 //dc.DrawLines(active ? 6 : 7, points);
953 dc
.DrawLines(7, points
);
958 int close_button_width
= 0;
959 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
961 close_button_width
= m_active_close_bmp
.GetWidth();
962 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
966 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
969 // set minimum text offset
970 if (text_offset
< tab_x
+ tab_height
)
971 text_offset
= tab_x
+ tab_height
;
973 // chop text if necessary
974 wxString draw_text
= ChopText(dc
,
976 tab_width
- (text_offset
-tab_x
) - close_button_width
);
979 dc
.DrawText(draw_text
,
981 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
984 // draw close button if necessary
985 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
989 bmp
= m_active_close_bmp
;
991 bmp
= m_disabled_close_bmp
;
993 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
994 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
997 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
999 *out_button_rect
= rect
;
1003 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1005 dc
.DestroyClippingRegion();
1008 int wxAuiSimpleTabArt::GetIndentSize()
1013 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1014 wxWindow
* WXUNUSED(wnd
),
1015 const wxString
& caption
,
1016 const wxBitmap
& WXUNUSED(bitmap
),
1017 bool WXUNUSED(active
),
1018 int close_button_state
,
1021 wxCoord measured_textx
, measured_texty
;
1023 dc
.SetFont(m_measuring_font
);
1024 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1026 wxCoord tab_height
= measured_texty
+ 4;
1027 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1029 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1030 tab_width
+= m_active_close_bmp
.GetWidth();
1032 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1034 tab_width
= m_fixed_tab_width
;
1037 *x_extent
= tab_width
- (tab_height
/2) - 1;
1039 return wxSize(tab_width
, tab_height
);
1043 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1044 wxWindow
* WXUNUSED(wnd
),
1045 const wxRect
& in_rect
,
1049 const wxBitmap
& bitmap_override
,
1055 if (bitmap_override
.IsOk())
1057 bmp
= bitmap_override
;
1063 case wxAUI_BUTTON_CLOSE
:
1064 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1065 bmp
= m_disabled_close_bmp
;
1067 bmp
= m_active_close_bmp
;
1069 case wxAUI_BUTTON_LEFT
:
1070 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1071 bmp
= m_disabled_left_bmp
;
1073 bmp
= m_active_left_bmp
;
1075 case wxAUI_BUTTON_RIGHT
:
1076 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1077 bmp
= m_disabled_right_bmp
;
1079 bmp
= m_active_right_bmp
;
1081 case wxAUI_BUTTON_WINDOWLIST
:
1082 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1083 bmp
= m_disabled_windowlist_bmp
;
1085 bmp
= m_active_windowlist_bmp
;
1095 if (orientation
== wxLEFT
)
1097 rect
.SetX(in_rect
.x
);
1098 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1099 rect
.SetWidth(bmp
.GetWidth());
1100 rect
.SetHeight(bmp
.GetHeight());
1104 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1105 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1106 bmp
.GetWidth(), bmp
.GetHeight());
1110 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1116 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1117 const wxArrayString
& items
,
1122 size_t i
, count
= items
.GetCount();
1123 for (i
= 0; i
< count
; ++i
)
1125 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1128 if (active_idx
!= -1)
1130 menuPopup
.Check(1000+active_idx
, true);
1133 // find out where to put the popup menu of window
1134 // items. Subtract 100 for now to center the menu
1135 // a bit, until a better mechanism can be implemented
1136 wxPoint pt
= ::wxGetMousePosition();
1137 pt
= wnd
->ScreenToClient(pt
);
1143 // find out the screen coordinate at the bottom of the tab ctrl
1144 wxRect cli_rect
= wnd
->GetClientRect();
1145 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1147 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1148 wnd
->PushEventHandler(cc
);
1149 wnd
->PopupMenu(&menuPopup
, pt
);
1150 int command
= cc
->GetCommandId();
1151 wnd
->PopEventHandler(true);
1153 if (command
>= 1000)
1154 return command
-1000;
1159 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1160 wxAuiNotebookPageArray
& WXUNUSED(pages
))
1163 dc
.SetFont(m_measuring_font
);
1165 wxSize s
= GetTabSize(dc
,
1170 wxAUI_BUTTON_STATE_HIDDEN
,
1175 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1177 m_normal_font
= font
;
1180 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1182 m_selected_font
= font
;
1185 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1187 m_measuring_font
= font
;
1193 // -- wxAuiTabContainer class implementation --
1196 // wxAuiTabContainer is a class which contains information about each
1197 // tab. It also can render an entire tab control to a specified DC.
1198 // It's not a window class itself, because this code will be used by
1199 // the wxFrameMananger, where it is disadvantageous to have separate
1200 // windows for each tab control in the case of "docked tabs"
1202 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1203 // which can be used as a tab control in the normal sense.
1206 wxAuiTabContainer::wxAuiTabContainer()
1210 m_art
= new wxAuiDefaultTabArt
;
1212 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1213 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1214 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1215 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1218 wxAuiTabContainer::~wxAuiTabContainer()
1223 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1230 m_art
->SetFlags(m_flags
);
1234 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1239 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1243 // check for new close button settings
1244 RemoveButton(wxAUI_BUTTON_LEFT
);
1245 RemoveButton(wxAUI_BUTTON_RIGHT
);
1246 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1247 RemoveButton(wxAUI_BUTTON_CLOSE
);
1250 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1252 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1253 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1256 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1258 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1261 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1263 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1268 m_art
->SetFlags(m_flags
);
1272 unsigned int wxAuiTabContainer::GetFlags() const
1278 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1280 m_art
->SetNormalFont(font
);
1283 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1285 m_art
->SetSelectedFont(font
);
1288 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1290 m_art
->SetMeasuringFont(font
);
1293 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1299 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1303 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1304 const wxAuiNotebookPage
& info
)
1306 wxAuiNotebookPage page_info
;
1308 page_info
.window
= page
;
1310 m_pages
.Add(page_info
);
1312 // let the art provider know how many pages we have
1315 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1321 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1322 const wxAuiNotebookPage
& info
,
1325 wxAuiNotebookPage page_info
;
1327 page_info
.window
= page
;
1329 if (idx
>= m_pages
.GetCount())
1330 m_pages
.Add(page_info
);
1332 m_pages
.Insert(page_info
, idx
);
1334 // let the art provider know how many pages we have
1337 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1343 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1346 int idx
= GetIdxFromWindow(page
);
1350 // get page entry, make a copy of it
1351 wxAuiNotebookPage p
= GetPage(idx
);
1353 // remove old page entry
1356 // insert page where it should be
1357 InsertPage(page
, p
, new_idx
);
1362 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1364 size_t i
, page_count
= m_pages
.GetCount();
1365 for (i
= 0; i
< page_count
; ++i
)
1367 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1368 if (page
.window
== wnd
)
1370 m_pages
.RemoveAt(i
);
1372 // let the art provider know how many pages we have
1375 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1385 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1389 size_t i
, page_count
= m_pages
.GetCount();
1390 for (i
= 0; i
< page_count
; ++i
)
1392 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1393 if (page
.window
== wnd
)
1400 page
.active
= false;
1407 void wxAuiTabContainer::SetNoneActive()
1409 size_t i
, page_count
= m_pages
.GetCount();
1410 for (i
= 0; i
< page_count
; ++i
)
1412 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1413 page
.active
= false;
1417 bool wxAuiTabContainer::SetActivePage(size_t page
)
1419 if (page
>= m_pages
.GetCount())
1422 return SetActivePage(m_pages
.Item(page
).window
);
1425 int wxAuiTabContainer::GetActivePage() const
1427 size_t i
, page_count
= m_pages
.GetCount();
1428 for (i
= 0; i
< page_count
; ++i
)
1430 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1438 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1440 if (idx
>= m_pages
.GetCount())
1443 return m_pages
[idx
].window
;
1446 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1448 size_t i
, page_count
= m_pages
.GetCount();
1449 for (i
= 0; i
< page_count
; ++i
)
1451 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1452 if (page
.window
== wnd
)
1458 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1460 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1462 return m_pages
[idx
];
1465 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1470 size_t wxAuiTabContainer::GetPageCount() const
1472 return m_pages
.GetCount();
1475 void wxAuiTabContainer::AddButton(int id
,
1477 const wxBitmap
& normal_bitmap
,
1478 const wxBitmap
& disabled_bitmap
)
1480 wxAuiTabContainerButton button
;
1482 button
.bitmap
= normal_bitmap
;
1483 button
.dis_bitmap
= disabled_bitmap
;
1484 button
.location
= location
;
1485 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1487 m_buttons
.Add(button
);
1490 void wxAuiTabContainer::RemoveButton(int id
)
1492 size_t i
, button_count
= m_buttons
.GetCount();
1494 for (i
= 0; i
< button_count
; ++i
)
1496 if (m_buttons
.Item(i
).id
== id
)
1498 m_buttons
.RemoveAt(i
);
1506 size_t wxAuiTabContainer::GetTabOffset() const
1508 return m_tab_offset
;
1511 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1513 m_tab_offset
= offset
;
1519 // Render() renders the tab catalog to the specified DC
1520 // It is a virtual function and can be overridden to
1521 // provide custom drawing capabilities
1522 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1524 if (!raw_dc
|| !raw_dc
->IsOk())
1530 size_t page_count
= m_pages
.GetCount();
1531 size_t button_count
= m_buttons
.GetCount();
1533 // create off-screen bitmap
1534 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1535 dc
.SelectObject(bmp
);
1540 // find out if size of tabs is larger than can be
1541 // afforded on screen
1542 int total_width
= 0;
1543 int visible_width
= 0;
1544 for (i
= 0; i
< page_count
; ++i
)
1546 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1548 // determine if a close button is on this tab
1549 bool close_button
= false;
1550 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1551 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1553 close_button
= true;
1558 wxSize size
= m_art
->GetTabSize(dc
,
1564 wxAUI_BUTTON_STATE_NORMAL
:
1565 wxAUI_BUTTON_STATE_HIDDEN
,
1568 if (i
+1 < page_count
)
1569 total_width
+= x_extent
;
1571 total_width
+= size
.x
;
1573 if (i
>= m_tab_offset
)
1575 if (i
+1 < page_count
)
1576 visible_width
+= x_extent
;
1578 visible_width
+= size
.x
;
1582 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1584 // show left/right buttons
1585 for (i
= 0; i
< button_count
; ++i
)
1587 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1588 if (button
.id
== wxAUI_BUTTON_LEFT
||
1589 button
.id
== wxAUI_BUTTON_RIGHT
)
1591 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1597 // hide left/right buttons
1598 for (i
= 0; i
< button_count
; ++i
)
1600 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1601 if (button
.id
== wxAUI_BUTTON_LEFT
||
1602 button
.id
== wxAUI_BUTTON_RIGHT
)
1604 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1609 // determine whether left button should be enabled
1610 for (i
= 0; i
< button_count
; ++i
)
1612 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1613 if (button
.id
== wxAUI_BUTTON_LEFT
)
1615 if (m_tab_offset
== 0)
1616 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1618 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1620 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1622 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1623 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1625 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1632 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1635 int left_buttons_width
= 0;
1636 int right_buttons_width
= 0;
1640 // draw the buttons on the right side
1641 offset
= m_rect
.x
+ m_rect
.width
;
1642 for (i
= 0; i
< button_count
; ++i
)
1644 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1646 if (button
.location
!= wxRIGHT
)
1648 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1651 wxRect button_rect
= m_rect
;
1652 button_rect
.SetY(1);
1653 button_rect
.SetWidth(offset
);
1655 m_art
->DrawButton(dc
,
1664 offset
-= button
.rect
.GetWidth();
1665 right_buttons_width
+= button
.rect
.GetWidth();
1672 // draw the buttons on the left side
1674 for (i
= 0; i
< button_count
; ++i
)
1676 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1678 if (button
.location
!= wxLEFT
)
1680 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1683 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1685 m_art
->DrawButton(dc
,
1694 offset
+= button
.rect
.GetWidth();
1695 left_buttons_width
+= button
.rect
.GetWidth();
1698 offset
= left_buttons_width
;
1701 offset
+= m_art
->GetIndentSize();
1704 // prepare the tab-close-button array
1705 // make sure tab button entries which aren't used are marked as hidden
1706 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1707 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1709 // make sure there are enough tab button entries to accommodate all tabs
1710 while (m_tab_close_buttons
.GetCount() < page_count
)
1712 wxAuiTabContainerButton tempbtn
;
1713 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1714 tempbtn
.location
= wxCENTER
;
1715 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1716 m_tab_close_buttons
.Add(tempbtn
);
1720 // buttons before the tab offset must be set to hidden
1721 for (i
= 0; i
< m_tab_offset
; ++i
)
1723 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1729 size_t active
= 999;
1730 int active_offset
= 0;
1734 wxRect rect
= m_rect
;
1736 rect
.height
= m_rect
.height
;
1738 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1740 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1741 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1743 // determine if a close button is on this tab
1744 bool close_button
= false;
1745 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1746 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1748 close_button
= true;
1749 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1751 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1752 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1753 tab_button
.location
= wxCENTER
;
1758 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1762 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1764 if (rect
.width
<= 0)
1773 tab_button
.cur_state
,
1781 active_offset
= offset
;
1789 // make sure to deactivate buttons which are off the screen to the right
1790 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1792 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1796 // draw the active tab again so it stands in the foreground
1797 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1799 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1801 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1803 // determine if a close button is on this tab
1804 bool close_button
= false;
1805 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1806 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1808 close_button
= true;
1811 rect
.x
= active_offset
;
1818 tab_button
.cur_state
,
1825 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1826 m_rect
.GetWidth(), m_rect
.GetHeight(),
1831 // TabHitTest() tests if a tab was hit, passing the window pointer
1832 // back if that condition was fulfilled. The function returns
1833 // true if a tab was hit, otherwise false
1834 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1836 if (!m_rect
.Contains(x
,y
))
1839 wxAuiTabContainerButton
* btn
= NULL
;
1840 if (ButtonHitTest(x
, y
, &btn
))
1842 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1846 size_t i
, page_count
= m_pages
.GetCount();
1848 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1850 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1851 if (page
.rect
.Contains(x
,y
))
1862 // ButtonHitTest() tests if a button was hit. The function returns
1863 // true if a button was hit, otherwise false
1864 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1865 wxAuiTabContainerButton
** hit
) const
1867 if (!m_rect
.Contains(x
,y
))
1870 size_t i
, button_count
;
1873 button_count
= m_buttons
.GetCount();
1874 for (i
= 0; i
< button_count
; ++i
)
1876 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1877 if (button
.rect
.Contains(x
,y
) &&
1878 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1879 wxAUI_BUTTON_STATE_DISABLED
)))
1887 button_count
= m_tab_close_buttons
.GetCount();
1888 for (i
= 0; i
< button_count
; ++i
)
1890 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1891 if (button
.rect
.Contains(x
,y
) &&
1892 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1893 wxAUI_BUTTON_STATE_DISABLED
)))
1906 // the utility function ShowWnd() is the same as show,
1907 // except it handles wxAuiMDIChildFrame windows as well,
1908 // as the Show() method on this class is "unplugged"
1909 static void ShowWnd(wxWindow
* wnd
, bool show
)
1911 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1913 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1923 // DoShowHide() this function shows the active window, then
1924 // hides all of the other windows (in that order)
1925 void wxAuiTabContainer::DoShowHide()
1927 wxAuiNotebookPageArray
& pages
= GetPages();
1928 size_t i
, page_count
= pages
.GetCount();
1930 // show new active page first
1931 for (i
= 0; i
< page_count
; ++i
)
1933 wxAuiNotebookPage
& page
= pages
.Item(i
);
1936 ShowWnd(page
.window
, true);
1941 // hide all other pages
1942 for (i
= 0; i
< page_count
; ++i
)
1944 wxAuiNotebookPage
& page
= pages
.Item(i
);
1945 ShowWnd(page
.window
, page
.active
);
1954 // -- wxAuiTabCtrl class implementation --
1958 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1959 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1960 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1961 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1962 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1963 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1964 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1965 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1966 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1970 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1974 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1976 m_click_pt
= wxDefaultPosition
;
1977 m_is_dragging
= false;
1978 m_hover_button
= NULL
;
1979 m_pressed_button
= NULL
;
1982 wxAuiTabCtrl::~wxAuiTabCtrl()
1986 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1990 dc
.SetFont(GetFont());
1992 if (GetPageCount() > 0)
1996 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2000 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2002 wxSize s
= evt
.GetSize();
2003 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2007 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2010 m_click_pt
= wxDefaultPosition
;
2011 m_is_dragging
= false;
2013 m_pressed_button
= NULL
;
2017 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2019 int new_selection
= GetIdxFromWindow(wnd
);
2021 if (new_selection
!= GetActivePage())
2023 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2024 e
.SetSelection(new_selection
);
2025 e
.SetOldSelection(GetActivePage());
2026 e
.SetEventObject(this);
2027 GetEventHandler()->ProcessEvent(e
);
2030 m_click_pt
.x
= evt
.m_x
;
2031 m_click_pt
.y
= evt
.m_y
;
2037 m_pressed_button
= m_hover_button
;
2038 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2044 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2046 if (GetCapture() == this)
2051 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2052 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2053 evt
.SetOldSelection(evt
.GetSelection());
2054 evt
.SetEventObject(this);
2055 GetEventHandler()->ProcessEvent(evt
);
2059 if (m_pressed_button
)
2061 // make sure we're still clicking the button
2062 wxAuiTabContainerButton
* button
= NULL
;
2063 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2066 if (button
!= m_pressed_button
)
2068 m_pressed_button
= NULL
;
2075 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2077 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2078 evt
.SetInt(m_pressed_button
->id
);
2079 evt
.SetEventObject(this);
2080 GetEventHandler()->ProcessEvent(evt
);
2083 m_pressed_button
= NULL
;
2086 m_click_pt
= wxDefaultPosition
;
2087 m_is_dragging
= false;
2091 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2093 wxPoint pos
= evt
.GetPosition();
2095 // check if the mouse is hovering above a button
2096 wxAuiTabContainerButton
* button
;
2097 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2099 if (m_hover_button
&& button
!= m_hover_button
)
2101 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2102 m_hover_button
= NULL
;
2107 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2109 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2112 m_hover_button
= button
;
2120 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2121 m_hover_button
= NULL
;
2128 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2133 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2134 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2135 evt
.SetOldSelection(evt
.GetSelection());
2136 evt
.SetEventObject(this);
2137 GetEventHandler()->ProcessEvent(evt
);
2142 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2143 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2145 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2146 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2148 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2149 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2150 evt
.SetOldSelection(evt
.GetSelection());
2151 evt
.SetEventObject(this);
2152 GetEventHandler()->ProcessEvent(evt
);
2154 m_is_dragging
= true;
2158 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2162 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2163 m_hover_button
= NULL
;
2169 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2171 int button
= event
.GetInt();
2173 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2175 if (button
== wxAUI_BUTTON_LEFT
)
2177 if (GetTabOffset() > 0)
2179 SetTabOffset(GetTabOffset()-1);
2186 SetTabOffset(GetTabOffset()+1);
2191 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2195 size_t i
, page_count
= m_pages
.GetCount();
2196 for (i
= 0; i
< page_count
; ++i
)
2198 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2199 as
.Add(page
.caption
);
2202 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2206 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2207 e
.SetSelection(idx
);
2208 e
.SetOldSelection(GetActivePage());
2209 e
.SetEventObject(this);
2210 GetEventHandler()->ProcessEvent(e
);
2219 // wxTabFrame is an interesting case. It's important that all child pages
2220 // of the multi-notebook control are all actually children of that control
2221 // (and not grandchildren). wxTabFrame facilitates this. There is one
2222 // instance of wxTabFrame for each tab control inside the multi-notebook.
2223 // It's important to know that wxTabFrame is not a real window, but it merely
2224 // used to capture the dimensions/positioning of the internal tab control and
2225 // it's managed page windows
2227 class wxTabFrame
: public wxWindow
2234 m_rect
= wxRect(0,0,200,200);
2235 m_tab_ctrl_height
= 20;
2238 void SetTabCtrlHeight(int h
)
2240 m_tab_ctrl_height
= h
;
2243 void DoSetSize(int x
, int y
,
2244 int width
, int height
,
2245 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2247 m_rect
= wxRect(x
, y
, width
, height
);
2251 void DoGetClientSize(int* x
, int* y
) const
2257 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2264 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2265 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2266 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2270 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2271 size_t i
, page_count
= pages
.GetCount();
2273 for (i
= 0; i
< page_count
; ++i
)
2275 wxAuiNotebookPage
& page
= pages
.Item(i
);
2276 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2277 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2279 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2281 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2282 wnd
->ApplyMDIChildFrameRect();
2287 void DoGetSize(int* x
, int* y
) const
2290 *x
= m_rect
.GetWidth();
2292 *y
= m_rect
.GetHeight();
2304 wxAuiTabCtrl
* m_tabs
;
2305 int m_tab_ctrl_height
;
2312 // -- wxAuiNotebook class implementation --
2314 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2315 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2316 //EVT_SIZE(wxAuiNotebook::OnSize)
2317 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2318 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2319 EVT_COMMAND_RANGE(10000, 10100,
2320 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2321 wxAuiNotebook::OnTabClicked
)
2322 EVT_COMMAND_RANGE(10000, 10100,
2323 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2324 wxAuiNotebook::OnTabBeginDrag
)
2325 EVT_COMMAND_RANGE(10000, 10100,
2326 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2327 wxAuiNotebook::OnTabEndDrag
)
2328 EVT_COMMAND_RANGE(10000, 10100,
2329 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2330 wxAuiNotebook::OnTabDragMotion
)
2331 EVT_COMMAND_RANGE(10000, 10100,
2332 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2333 wxAuiNotebook::OnTabButton
)
2336 wxAuiNotebook::wxAuiNotebook()
2339 m_tab_id_counter
= 10000;
2341 m_tab_ctrl_height
= 20;
2344 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2348 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2350 InitNotebook(style
);
2353 bool wxAuiNotebook::Create(wxWindow
* parent
,
2359 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2362 InitNotebook(style
);
2367 // InitNotebook() contains common initialization
2368 // code called by all constructors
2369 void wxAuiNotebook::InitNotebook(long style
)
2372 m_tab_id_counter
= 10000;
2374 m_tab_ctrl_height
= 20;
2375 m_flags
= (unsigned int)style
;
2377 m_normal_font
= *wxNORMAL_FONT
;
2378 m_selected_font
= *wxNORMAL_FONT
;
2379 m_selected_font
.SetWeight(wxBOLD
);
2381 SetArtProvider(new wxAuiDefaultTabArt
);
2383 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2384 m_dummy_wnd
->SetSize(200, 200);
2385 m_dummy_wnd
->Show(false);
2387 m_mgr
.SetManagedWindow(this);
2389 m_mgr
.AddPane(m_dummy_wnd
,
2390 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2395 wxAuiNotebook::~wxAuiNotebook()
2400 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2402 m_tabs
.SetArtProvider(art
);
2404 SetTabCtrlHeight(CalculateTabCtrlHeight());
2407 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2409 // if the tab control height needs to change, update
2410 // all of our tab controls with the new height
2411 if (m_tab_ctrl_height
!= height
)
2413 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2415 m_tab_ctrl_height
= height
;
2417 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2418 size_t i
, pane_count
= all_panes
.GetCount();
2419 for (i
= 0; i
< pane_count
; ++i
)
2421 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2422 if (pane
.name
== wxT("dummy"))
2424 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2425 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2426 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2427 tabctrl
->SetArtProvider(art
->Clone());
2428 tab_frame
->DoSizing();
2433 int wxAuiNotebook::CalculateTabCtrlHeight()
2435 // find out new best tab height
2436 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2438 return art
->GetBestTabCtrlSize(this, m_tabs
.GetPages());
2442 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2444 return m_tabs
.GetArtProvider();
2447 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2449 wxControl::SetWindowStyleFlag(style
);
2451 m_flags
= (unsigned int)style
;
2453 // if the control is already initialized
2454 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2456 // let all of the tab children know about the new style
2458 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2459 size_t i
, pane_count
= all_panes
.GetCount();
2460 for (i
= 0; i
< pane_count
; ++i
)
2462 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2463 if (pane
.name
== wxT("dummy"))
2465 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2466 tabctrl
->SetFlags(m_flags
);
2474 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2475 const wxString
& caption
,
2477 const wxBitmap
& bitmap
)
2479 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2482 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2484 const wxString
& caption
,
2486 const wxBitmap
& bitmap
)
2488 wxAuiNotebookPage info
;
2490 info
.caption
= caption
;
2491 info
.bitmap
= bitmap
;
2492 info
.active
= false;
2494 // if there are currently no tabs, the first added
2495 // tab must be active
2496 if (m_tabs
.GetPageCount() == 0)
2499 m_tabs
.InsertPage(page
, info
, page_idx
);
2501 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2502 if (page_idx
>= active_tabctrl
->GetPageCount())
2503 active_tabctrl
->AddPage(page
, info
);
2505 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2507 SetTabCtrlHeight(CalculateTabCtrlHeight());
2509 active_tabctrl
->DoShowHide();
2513 int idx
= m_tabs
.GetIdxFromWindow(page
);
2514 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2523 // DeletePage() removes a tab from the multi-notebook,
2524 // and destroys the window as well
2525 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2527 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2529 if (!RemovePage(page_idx
))
2532 // actually destroy the window now
2533 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2535 // delete the child frame with pending delete, as is
2536 // customary with frame windows
2537 if (!wxPendingDelete
.Member(wnd
))
2538 wxPendingDelete
.Append(wnd
);
2550 // RemovePage() removes a tab from the multi-notebook,
2551 // but does not destroy the window
2552 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2554 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2555 wxWindow
* new_active
= NULL
;
2557 // find out which onscreen tab ctrl owns this tab
2560 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2563 // find a new page and set it as active
2564 int new_idx
= ctrl_idx
+1;
2565 if (new_idx
>= (int)ctrl
->GetPageCount())
2566 new_idx
= ctrl_idx
-1;
2568 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2570 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2574 // set the active page to the first page that
2575 // isn't the one being deleted
2576 size_t i
, page_count
= m_tabs
.GetPageCount();
2577 for (i
= 0; i
< page_count
; ++i
)
2579 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2582 new_active
= m_tabs
.GetWindowFromIdx(i
);
2588 // remove the tab from main catalog
2589 if (!m_tabs
.RemovePage(wnd
))
2592 // remove the tab from the onscreen tab ctrl
2593 ctrl
->RemovePage(wnd
);
2596 RemoveEmptyTabFrames();
2598 // set new active pane
2602 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2608 // GetPageIndex() returns the index of the page, or -1 if the
2609 // page could not be located in the notebook
2610 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2612 return m_tabs
.GetIdxFromWindow(page_wnd
);
2617 // SetPageText() changes the tab caption of the specified page
2618 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2620 if (page_idx
>= m_tabs
.GetPageCount())
2623 // update our own tab catalog
2624 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2625 page_info
.caption
= text
;
2627 // update what's on screen
2630 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2632 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2633 info
.caption
= text
;
2642 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2644 if (page_idx
>= m_tabs
.GetPageCount())
2647 // update our own tab catalog
2648 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2649 page_info
.bitmap
= bitmap
;
2651 // tab height might have changed
2652 SetTabCtrlHeight(CalculateTabCtrlHeight());
2654 // update what's on screen
2657 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2659 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2660 info
.bitmap
= bitmap
;
2669 // GetSelection() returns the index of the currently active page
2670 int wxAuiNotebook::GetSelection() const
2675 // SetSelection() sets the currently active page
2676 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2678 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2682 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2683 evt
.SetSelection(new_page
);
2684 evt
.SetOldSelection(m_curpage
);
2685 evt
.SetEventObject(this);
2686 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2688 int old_curpage
= m_curpage
;
2689 m_curpage
= new_page
;
2691 // program allows the page change
2692 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2693 (void)GetEventHandler()->ProcessEvent(evt
);
2698 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2700 m_tabs
.SetActivePage(wnd
);
2702 ctrl
->SetActivePage(ctrl_idx
);
2709 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2710 size_t i
, pane_count
= all_panes
.GetCount();
2711 for (i
= 0; i
< pane_count
; ++i
)
2713 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2714 if (pane
.name
== wxT("dummy"))
2716 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2717 if (tabctrl
!= ctrl
)
2718 tabctrl
->SetSelectedFont(m_normal_font
);
2720 tabctrl
->SetSelectedFont(m_selected_font
);
2733 // GetPageCount() returns the total number of
2734 // pages managed by the multi-notebook
2735 size_t wxAuiNotebook::GetPageCount() const
2737 return m_tabs
.GetPageCount();
2740 // GetPage() returns the wxWindow pointer of the
2742 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2744 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2746 return m_tabs
.GetWindowFromIdx(page_idx
);
2749 // DoSizing() performs all sizing operations in each tab control
2750 void wxAuiNotebook::DoSizing()
2752 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2753 size_t i
, pane_count
= all_panes
.GetCount();
2754 for (i
= 0; i
< pane_count
; ++i
)
2756 if (all_panes
.Item(i
).name
== wxT("dummy"))
2759 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2760 tabframe
->DoSizing();
2764 // GetActiveTabCtrl() returns the active tab control. It is
2765 // called to determine which control gets new windows being added
2766 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2768 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2773 // find the tab ctrl with the current page
2774 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2781 // no current page, just find the first tab ctrl
2782 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2783 size_t i
, pane_count
= all_panes
.GetCount();
2784 for (i
= 0; i
< pane_count
; ++i
)
2786 if (all_panes
.Item(i
).name
== wxT("dummy"))
2789 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2790 return tabframe
->m_tabs
;
2793 // If there is no tabframe at all, create one
2794 wxTabFrame
* tabframe
= new wxTabFrame
;
2795 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2796 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2801 tabframe
->m_tabs
->SetFlags(m_flags
);
2802 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2803 m_mgr
.AddPane(tabframe
,
2804 wxAuiPaneInfo().Center().CaptionVisible(false));
2808 return tabframe
->m_tabs
;
2811 // FindTab() finds the tab control that currently contains the window as well
2812 // as the index of the window in the tab control. It returns true if the
2813 // window was found, otherwise false.
2814 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2816 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2817 size_t i
, pane_count
= all_panes
.GetCount();
2818 for (i
= 0; i
< pane_count
; ++i
)
2820 if (all_panes
.Item(i
).name
== wxT("dummy"))
2823 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2825 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2828 *ctrl
= tabframe
->m_tabs
;
2838 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2842 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2846 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2848 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2850 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2851 wxASSERT(ctrl
!= NULL
);
2853 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2854 wxASSERT(wnd
!= NULL
);
2856 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2857 wxASSERT(idx
!= -1);
2862 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2867 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2869 wxPoint screen_pt
= ::wxGetMousePosition();
2870 wxPoint client_pt
= ScreenToClient(screen_pt
);
2873 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2874 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2876 if (dest_tabs
== src_tabs
)
2880 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2883 // always hide the hint for inner-tabctrl drag
2886 // if tab moving is not allowed, leave
2887 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2892 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2893 wxWindow
* dest_location_tab
;
2895 // this is an inner-tab drag/reposition
2896 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2898 int src_idx
= evt
.GetSelection();
2899 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2901 // prevent jumpy drag
2902 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2903 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2904 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2906 m_last_drag_x
= pt
.x
;
2911 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2912 dest_tabs
->MovePage(src_tab
, dest_idx
);
2913 dest_tabs
->SetActivePage((size_t)dest_idx
);
2914 dest_tabs
->DoShowHide();
2915 dest_tabs
->Refresh();
2916 m_last_drag_x
= pt
.x
;
2924 // if external drag is allowed, check if the tab is being dragged
2925 // over a different wxAuiNotebook control
2926 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2928 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2930 // if we aren't over any window, stop here
2934 // make sure we are not over the hint window
2935 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2939 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2941 tab_ctrl
= tab_ctrl
->GetParent();
2946 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2950 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2951 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2952 m_mgr
.ShowHint(hint_rect
);
2961 // we are either over a hint window, or not over a tab
2962 // window, and there is no where to drag to, so exit
2969 // if there are less than two panes, split can't happen, so leave
2970 if (m_tabs
.GetPageCount() < 2)
2973 // if tab moving is not allowed, leave
2974 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2980 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2986 wxRect hint_rect
= dest_tabs
->GetRect();
2987 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2988 m_mgr
.ShowHint(hint_rect
);
2992 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2998 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3000 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3005 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3006 wxAuiTabCtrl
* dest_tabs
= NULL
;
3009 // set cursor back to an arrow
3010 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3013 // get the mouse position, which will be used to determine the drop point
3014 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3015 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3019 // check for an external move
3020 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3022 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3026 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3028 tab_ctrl
= tab_ctrl
->GetParent();
3033 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3037 // find out from the destination control
3038 // if it's ok to drop this tab here
3039 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3040 e
.SetSelection(evt
.GetSelection());
3041 e
.SetOldSelection(evt
.GetSelection());
3042 e
.SetEventObject(this);
3043 e
.SetDragSource(this);
3044 e
.Veto(); // dropping must be explicitly approved by control owner
3046 nb
->GetEventHandler()->ProcessEvent(e
);
3050 // no answer or negative answer
3056 int src_idx
= evt
.GetSelection();
3057 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3059 // get main index of the page
3060 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3062 // make a copy of the page info
3063 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3065 // remove the page from the source notebook
3066 RemovePage(main_idx
);
3068 // reparent the page
3069 src_page
->Reparent(nb
);
3072 // found out the insert idx
3073 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3074 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3076 wxWindow
* target
= NULL
;
3077 int insert_idx
= -1;
3078 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3081 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3085 // add the page to the new notebook
3086 if (insert_idx
== -1)
3087 insert_idx
= dest_tabs
->GetPageCount();
3088 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3089 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3092 dest_tabs
->DoShowHide();
3093 dest_tabs
->Refresh();
3095 // set the selection in the destination tab control
3096 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3106 // only perform a tab split if it's allowed
3107 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3109 // If the pointer is in an existing tab frame, do a tab insert
3110 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3111 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3112 int insert_idx
= -1;
3115 dest_tabs
= tab_frame
->m_tabs
;
3117 if (dest_tabs
== src_tabs
)
3121 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3122 wxWindow
* target
= NULL
;
3123 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3126 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3131 // If there is no tabframe at all, create one
3132 wxTabFrame
* new_tabs
= new wxTabFrame
;
3133 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3134 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3139 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3140 new_tabs
->m_tabs
->SetFlags(m_flags
);
3142 m_mgr
.AddPane(new_tabs
,
3143 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3146 dest_tabs
= new_tabs
->m_tabs
;
3151 // remove the page from the source tabs
3152 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3153 page_info
.active
= false;
3154 src_tabs
->RemovePage(page_info
.window
);
3155 if (src_tabs
->GetPageCount() > 0)
3157 src_tabs
->SetActivePage((size_t)0);
3158 src_tabs
->DoShowHide();
3159 src_tabs
->Refresh();
3164 // add the page to the destination tabs
3165 if (insert_idx
== -1)
3166 insert_idx
= dest_tabs
->GetPageCount();
3167 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3169 if (src_tabs
->GetPageCount() == 0)
3171 RemoveEmptyTabFrames();
3175 dest_tabs
->DoShowHide();
3176 dest_tabs
->Refresh();
3178 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3184 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3186 // if we've just removed the last tab from the source
3187 // tab set, the remove the tab control completely
3188 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3189 size_t i
, pane_count
= all_panes
.GetCount();
3190 for (i
= 0; i
< pane_count
; ++i
)
3192 if (all_panes
.Item(i
).name
== wxT("dummy"))
3195 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3196 if (tabframe
->m_tab_rect
.Contains(pt
))
3197 return tabframe
->m_tabs
;
3203 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3205 // if we've just removed the last tab from the source
3206 // tab set, the remove the tab control completely
3207 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3208 size_t i
, pane_count
= all_panes
.GetCount();
3209 for (i
= 0; i
< pane_count
; ++i
)
3211 if (all_panes
.Item(i
).name
== wxT("dummy"))
3214 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3215 if (tabframe
->m_tabs
== tab_ctrl
)
3224 void wxAuiNotebook::RemoveEmptyTabFrames()
3226 // if we've just removed the last tab from the source
3227 // tab set, the remove the tab control completely
3228 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3229 size_t i
, pane_count
= all_panes
.GetCount();
3230 for (i
= 0; i
< pane_count
; ++i
)
3232 if (all_panes
.Item(i
).name
== wxT("dummy"))
3235 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3236 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3238 m_mgr
.DetachPane(tab_frame
);
3240 // use pending delete because sometimes during
3241 // window closing, refreshs are pending
3242 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3243 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3244 //tab_frame->m_tabs->Destroy();
3251 // check to see if there is still a center pane;
3252 // if there isn't, make a frame the center pane
3253 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3254 pane_count
= panes
.GetCount();
3255 wxWindow
* first_good
= NULL
;
3256 bool center_found
= false;
3257 for (i
= 0; i
< pane_count
; ++i
)
3259 if (panes
.Item(i
).name
== wxT("dummy"))
3261 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3262 center_found
= true;
3264 first_good
= panes
.Item(i
).window
;
3267 if (!center_found
&& first_good
)
3269 m_mgr
.GetPane(first_good
).Centre();
3275 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3277 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3278 if (idx
!= -1 && idx
!= m_curpage
)
3285 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3287 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3288 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3290 int button_id
= evt
.GetInt();
3292 if (button_id
== wxAUI_BUTTON_CLOSE
)
3294 int selection
= tabs
->GetActivePage();
3296 if (selection
!= -1)
3298 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3301 // ask owner if it's ok to close the tab
3302 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3303 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3304 e
.SetOldSelection(evt
.GetSelection());
3305 e
.SetEventObject(this);
3306 GetEventHandler()->ProcessEvent(e
);
3311 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3317 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3318 DeletePage(main_idx
);