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"
34 #include "wx/arrimpl.cpp"
35 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
36 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
48 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
49 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
50 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
56 // This functions are here for this proof of concept
57 // and will be factored out later. See dockart.cpp
58 static wxColor
StepColour(const wxColor
& c
, int percent
)
60 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
61 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
62 (unsigned char)wxMin((g
*percent
)/100,255),
63 (unsigned char)wxMin((b
*percent
)/100,255));
66 // This functions are here for this proof of concept
67 // and will be factored out later. See dockart.cpp
68 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
69 const wxColour
& color
)
71 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
72 img
.Replace(0,0,0,123,123,123);
73 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
74 img
.SetMaskColour(123,123,123);
78 static void DrawButtons(wxDC
& dc
,
81 const wxColour
& bkcolour
,
86 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
93 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
95 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
96 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
98 // draw the background behind the button
99 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
102 // draw the button itself
103 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
106 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
108 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
115 // chops the text so that it fits within |max_size| pixels.
116 // Also adds an elipsis if necessary
118 static wxString
ChopText(wxDC
& dc
, const wxString
& text
, int max_size
)
122 // first check if the text fits with no problems
123 dc
.GetTextExtent(text
, &x
, &y
);
127 size_t i
, len
= text
.Length();
128 size_t last_good_length
= 0;
129 for (i
= 0; i
< len
; ++i
)
131 wxString s
= text
.Left(i
);
134 dc
.GetTextExtent(s
, &x
, &y
);
138 last_good_length
= i
;
141 wxString ret
= text
.Left(last_good_length
);
147 // -- GUI helper classes and functions --
149 class wxAuiCommandCapture
: public wxEvtHandler
153 wxAuiCommandCapture() { m_last_id
= 0; }
154 int GetCommandId() const { return m_last_id
; }
156 bool ProcessEvent(wxEvent
& evt
)
158 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
160 m_last_id
= evt
.GetId();
164 if (GetNextHandler())
165 return GetNextHandler()->ProcessEvent(evt
);
177 #if defined( __WXMAC__ )
178 static unsigned char close_bits
[]={
179 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
180 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
181 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
182 #elif defined( __WXGTK__)
183 static unsigned char close_bits
[]={
184 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
185 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
186 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
188 static unsigned char close_bits
[]={
189 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
190 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
191 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
194 static unsigned char left_bits
[] = {
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
196 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
199 static unsigned char right_bits
[] = {
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
201 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
204 static unsigned char list_bits
[] = {
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
214 // -- wxAuiDefaultTabArt class implementation --
216 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
218 m_normal_font
= *wxNORMAL_FONT
;
219 m_selected_font
= *wxNORMAL_FONT
;
220 m_selected_font
.SetWeight(wxBOLD
);
221 m_measuring_font
= m_selected_font
;
223 m_fixed_tab_width
= 100;
224 m_tab_ctrl_height
= 0;
227 wxBrush toolbarbrush
;
228 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
229 wxColor base_colour
= toolbarbrush
.GetColour();
231 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
234 m_base_colour
= base_colour
;
235 wxColor darker2_colour
= StepColour(base_colour
, 70);
237 m_border_pen
= wxPen(darker2_colour
);
238 m_base_colour_pen
= wxPen(m_base_colour
);
239 m_base_colour_brush
= wxBrush(m_base_colour
);
241 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
242 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
244 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
245 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
247 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
248 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
250 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
251 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
256 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
260 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
262 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
265 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
270 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
273 m_fixed_tab_width
= 100;
275 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
278 m_fixed_tab_width
= tot_width
/(int)tab_count
;
282 if (m_fixed_tab_width
< 100)
283 m_fixed_tab_width
= 100;
285 if (m_fixed_tab_width
> tot_width
/2)
286 m_fixed_tab_width
= tot_width
/2;
288 if (m_fixed_tab_width
> 220)
289 m_fixed_tab_width
= 220;
291 m_tab_ctrl_height
= tab_ctrl_size
.y
;
295 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
296 wxWindow
* WXUNUSED(wnd
),
300 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
301 wxColor start_colour
= StepColour(m_base_colour
, 90);
302 wxColor end_colour
= StepColour(m_base_colour
, 110);
303 dc
.GradientFillLinear(r
, start_colour
, end_colour
, wxSOUTH
);
306 int y
= rect
.GetHeight();
307 int w
= rect
.GetWidth();
308 dc
.SetPen(m_border_pen
);
309 dc
.DrawLine(0, y
-4, w
, y
-4);
310 dc
.DrawLine(0, y
-1, w
, y
-1);
311 dc
.SetPen(wxPen(start_colour
));
312 dc
.DrawLine(0, y
-3, w
, y
-3);
313 dc
.DrawLine(0, y
-2, w
, y
-2);
317 // DrawTab() draws an individual tab.
320 // in_rect - rectangle the tab should be confined to
321 // caption - tab's caption
322 // active - whether or not the tab is active
323 // out_rect - actual output rectangle
324 // x_extent - the advance x; where the next tab should start
326 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
328 const wxRect
& in_rect
,
329 const wxString
& caption_text
,
330 const wxBitmap
& bitmap
,
332 int close_button_state
,
333 wxRect
* out_tab_rect
,
334 wxRect
* out_button_rect
,
337 wxCoord normal_textx
, normal_texty
;
338 wxCoord selected_textx
, selected_texty
;
339 wxCoord textx
, texty
;
341 // if the caption is empty, measure some temporary text
342 wxString caption
= caption_text
;
343 if (caption_text
.empty())
346 dc
.SetFont(m_selected_font
);
347 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
349 dc
.SetFont(m_normal_font
);
350 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
352 // figure out the size of the tab
353 wxSize tab_size
= GetTabSize(dc
,
361 wxCoord tab_height
= m_tab_ctrl_height
- 3;
362 wxCoord tab_width
= tab_size
.x
;
363 wxCoord tab_x
= in_rect
.x
;
364 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
367 caption
= caption_text
;
370 // select pen, brush and font for the tab to be drawn
374 dc
.SetFont(m_selected_font
);
375 textx
= selected_textx
;
376 texty
= selected_texty
;
380 dc
.SetFont(m_normal_font
);
381 textx
= normal_textx
;
382 texty
= normal_texty
;
386 // create points that will make the tab outline
388 wxPoint clip_points
[6];
389 clip_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-3);
390 clip_points
[1] = wxPoint(tab_x
, tab_y
+2);
391 clip_points
[2] = wxPoint(tab_x
+2, tab_y
);
392 clip_points
[3] = wxPoint(tab_x
+tab_width
-1, tab_y
);
393 clip_points
[4] = wxPoint(tab_x
+tab_width
+1, tab_y
+2);
394 clip_points
[5] = wxPoint(tab_x
+tab_width
+1, tab_y
+tab_height
-3);
396 // set the clipping region for the tab --
397 wxRegion
clipping_region(6, clip_points
);
398 dc
.SetClippingRegion(clipping_region
);
400 wxPoint border_points
[6];
401 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
402 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
403 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
404 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
405 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
406 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
409 int drawn_tab_yoff
= border_points
[1].y
;
410 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
417 // draw base background color
418 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
419 dc
.SetPen(m_base_colour_pen
);
420 dc
.SetBrush(m_base_colour_brush
);
421 dc
.DrawRectangle(r
.x
, r
.y
, r
.width
, r
.height
);
423 // this white helps fill out the gradient at the top of the tab
424 dc
.SetPen(*wxWHITE_PEN
);
425 dc
.SetBrush(*wxWHITE_BRUSH
);
426 dc
.DrawRectangle(r
.x
+2, r
.y
+2, r
.width
-3, r
.height
);
428 // these two points help the rounded corners appear more antialiased
429 dc
.SetPen(m_base_colour_pen
);
430 dc
.DrawPoint(r
.x
+2, r
.y
+2);
431 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+2);
433 // set rectangle down a bit for gradient drawing
434 r
.SetHeight(r
.GetHeight()/2);
439 // draw gradient background
440 wxColor start_color
= StepColour(m_base_colour
, 95);
441 wxColor end_color
= *wxWHITE
;
442 dc
.GradientFillLinear(r
, start_color
, end_color
, wxNORTH
);
448 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
450 // draw base background color for inactive tabs
451 dc
.SetPen(m_base_colour_pen
);
452 dc
.SetBrush(m_base_colour_brush
);
453 dc
.DrawRectangle(r
.x
, r
.y
, r
.width
, r
.height
);
455 // start the gradent up a bit and leave the inside border inset
456 // by a pixel for a 3D look. Only the top half of the inactive
457 // tab will have a slight gradient
462 // -- draw bottom gradient fill for glossy look
463 wxColor top_color
= m_base_colour
;
464 wxColor bottom_color
= StepColour(top_color
, 106);
465 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
469 dc
.SetPen(m_border_pen
);
470 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
471 dc
.DrawPolygon(6, border_points
);
473 // there are two horizontal grey lines at the bottom of the tab control,
474 // this gets rid of the top one of those lines in the tab control
477 wxColor start_color
= StepColour(m_base_colour
, 93);
478 dc
.SetPen(wxPen(start_color
));
479 dc
.DrawLine(border_points
[0].x
,
481 border_points
[5].x
+1,
486 int text_offset
= tab_x
+ 8;
487 int close_button_width
= 0;
488 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
490 close_button_width
= m_active_close_bmp
.GetWidth();
496 int bitmap_offset
= tab_x
+ 8;
499 dc
.DrawBitmap(bitmap
,
501 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2) + 1,
504 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
505 text_offset
+= 3; // bitmap padding
509 text_offset
= tab_x
+ 8;
513 wxString draw_text
= ChopText(dc
,
515 tab_width
- (text_offset
-tab_x
) - close_button_width
);
518 dc
.DrawText(draw_text
,
520 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
525 // draw close button if necessary
526 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
528 wxBitmap bmp
= m_disabled_close_bmp
;
530 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
531 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
533 bmp
= m_active_close_bmp
;
536 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
537 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
540 IndentPressedBitmap(&rect
, close_button_state
);
541 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
543 *out_button_rect
= rect
;
546 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
548 dc
.DestroyClippingRegion();
551 int wxAuiDefaultTabArt::GetIndentSize()
556 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
557 wxWindow
* WXUNUSED(wnd
),
558 const wxString
& caption
,
559 const wxBitmap
& bitmap
,
560 bool WXUNUSED(active
),
561 int close_button_state
,
564 wxCoord measured_textx
, measured_texty
, tmp
;
566 dc
.SetFont(m_measuring_font
);
567 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
569 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
571 // add padding around the text
572 wxCoord tab_width
= measured_textx
;
573 wxCoord tab_height
= measured_texty
;
575 // if the close button is showing, add space for it
576 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
577 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
579 // if there's a bitmap, add space for it
582 tab_width
+= bitmap
.GetWidth();
583 tab_width
+= 3; // right side bitmap padding
584 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
591 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
593 tab_width
= m_fixed_tab_width
;
596 *x_extent
= tab_width
;
598 return wxSize(tab_width
, tab_height
);
602 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
603 wxWindow
* WXUNUSED(wnd
),
604 const wxRect
& in_rect
,
608 const wxBitmap
& bitmap_override
,
614 if (bitmap_override
.IsOk())
616 bmp
= bitmap_override
;
622 case wxAUI_BUTTON_CLOSE
:
623 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
624 bmp
= m_disabled_close_bmp
;
626 bmp
= m_active_close_bmp
;
628 case wxAUI_BUTTON_LEFT
:
629 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
630 bmp
= m_disabled_left_bmp
;
632 bmp
= m_active_left_bmp
;
634 case wxAUI_BUTTON_RIGHT
:
635 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
636 bmp
= m_disabled_right_bmp
;
638 bmp
= m_active_right_bmp
;
640 case wxAUI_BUTTON_WINDOWLIST
:
641 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
642 bmp
= m_disabled_windowlist_bmp
;
644 bmp
= m_active_windowlist_bmp
;
654 if (orientation
== wxLEFT
)
656 rect
.SetX(in_rect
.x
);
657 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
658 rect
.SetWidth(bmp
.GetWidth());
659 rect
.SetHeight(bmp
.GetHeight());
663 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
664 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
665 bmp
.GetWidth(), bmp
.GetHeight());
668 IndentPressedBitmap(&rect
, button_state
);
669 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
675 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
676 const wxArrayString
& items
,
681 size_t i
, count
= items
.GetCount();
682 for (i
= 0; i
< count
; ++i
)
684 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
687 if (active_idx
!= -1)
689 menuPopup
.Check(1000+active_idx
, true);
692 // find out where to put the popup menu of window
693 // items. Subtract 100 for now to center the menu
694 // a bit, until a better mechanism can be implemented
695 wxPoint pt
= ::wxGetMousePosition();
696 pt
= wnd
->ScreenToClient(pt
);
702 // find out the screen coordinate at the bottom of the tab ctrl
703 wxRect cli_rect
= wnd
->GetClientRect();
704 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
706 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
707 wnd
->PushEventHandler(cc
);
708 wnd
->PopupMenu(&menuPopup
, pt
);
709 int command
= cc
->GetCommandId();
710 wnd
->PopEventHandler(true);
718 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
719 wxAuiNotebookPageArray
& pages
)
722 dc
.SetFont(m_measuring_font
);
725 size_t i
, page_count
= pages
.GetCount();
726 for (i
= 0; i
< page_count
; ++i
)
728 wxAuiNotebookPage
& page
= pages
.Item(i
);
730 // we don't use the caption text because we don't
731 // want tab heights to be different in the case
732 // of a very short piece of text on one tab and a very
733 // tall piece of text on another tab
735 wxSize s
= GetTabSize(dc
,
740 wxAUI_BUTTON_STATE_HIDDEN
,
742 max_y
= wxMax(max_y
, s
.y
);
748 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
750 m_normal_font
= font
;
753 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
755 m_selected_font
= font
;
758 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
760 m_measuring_font
= font
;
764 // -- wxAuiSimpleTabArt class implementation --
766 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
768 m_normal_font
= *wxNORMAL_FONT
;
769 m_selected_font
= *wxNORMAL_FONT
;
770 m_selected_font
.SetWeight(wxBOLD
);
771 m_measuring_font
= m_selected_font
;
774 m_fixed_tab_width
= 100;
776 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
778 wxColour background_colour
= StepColour(base_colour
, 95);
779 wxColour normaltab_colour
= base_colour
;
780 wxColour selectedtab_colour
= *wxWHITE
;
782 m_bkbrush
= wxBrush(background_colour
);
783 m_normal_bkbrush
= wxBrush(normaltab_colour
);
784 m_normal_bkpen
= wxPen(normaltab_colour
);
785 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
786 m_selected_bkpen
= wxPen(selectedtab_colour
);
788 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
789 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
791 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
792 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
794 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
795 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
797 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
798 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
802 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
806 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
808 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
812 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
817 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
820 m_fixed_tab_width
= 100;
822 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
825 m_fixed_tab_width
= tot_width
/(int)tab_count
;
829 if (m_fixed_tab_width
< 100)
830 m_fixed_tab_width
= 100;
832 if (m_fixed_tab_width
> tot_width
/2)
833 m_fixed_tab_width
= tot_width
/2;
835 if (m_fixed_tab_width
> 220)
836 m_fixed_tab_width
= 220;
839 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
840 wxWindow
* WXUNUSED(wnd
),
844 dc
.SetBrush(m_bkbrush
);
845 dc
.SetPen(*wxTRANSPARENT_PEN
);
846 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
849 dc
.SetPen(*wxGREY_PEN
);
850 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
854 // DrawTab() draws an individual tab.
857 // in_rect - rectangle the tab should be confined to
858 // caption - tab's caption
859 // active - whether or not the tab is active
860 // out_rect - actual output rectangle
861 // x_extent - the advance x; where the next tab should start
863 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
865 const wxRect
& in_rect
,
866 const wxString
& caption_text
,
867 const wxBitmap
& bitmap
,
869 int close_button_state
,
870 wxRect
* out_tab_rect
,
871 wxRect
* out_button_rect
,
874 wxCoord normal_textx
, normal_texty
;
875 wxCoord selected_textx
, selected_texty
;
876 wxCoord textx
, texty
;
878 // if the caption is empty, measure some temporary text
879 wxString caption
= caption_text
;
880 if (caption_text
.empty())
883 dc
.SetFont(m_selected_font
);
884 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
886 dc
.SetFont(m_normal_font
);
887 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
889 // figure out the size of the tab
890 wxSize tab_size
= GetTabSize(dc
,
898 wxCoord tab_height
= tab_size
.y
;
899 wxCoord tab_width
= tab_size
.x
;
900 wxCoord tab_x
= in_rect
.x
;
901 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
903 caption
= caption_text
;
905 // select pen, brush and font for the tab to be drawn
909 dc
.SetPen(m_selected_bkpen
);
910 dc
.SetBrush(m_selected_bkbrush
);
911 dc
.SetFont(m_selected_font
);
912 textx
= selected_textx
;
913 texty
= selected_texty
;
917 dc
.SetPen(m_normal_bkpen
);
918 dc
.SetBrush(m_normal_bkbrush
);
919 dc
.SetFont(m_normal_font
);
920 textx
= normal_textx
;
921 texty
= normal_texty
;
929 points
[0].y
= tab_y
+ tab_height
- 1;
930 points
[1].x
= tab_x
+ tab_height
- 3;
931 points
[1].y
= tab_y
+ 2;
932 points
[2].x
= tab_x
+ tab_height
+ 3;
934 points
[3].x
= tab_x
+ tab_width
- 2;
936 points
[4].x
= tab_x
+ tab_width
;
937 points
[4].y
= tab_y
+ 2;
938 points
[5].x
= tab_x
+ tab_width
;
939 points
[5].y
= tab_y
+ tab_height
- 1;
940 points
[6] = points
[0];
942 dc
.SetClippingRegion(in_rect
);
944 dc
.DrawPolygon(6, points
);
946 dc
.SetPen(*wxGREY_PEN
);
948 //dc.DrawLines(active ? 6 : 7, points);
949 dc
.DrawLines(7, points
);
954 int close_button_width
= 0;
955 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
957 close_button_width
= m_active_close_bmp
.GetWidth();
958 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
962 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
965 // set minimum text offset
966 if (text_offset
< tab_x
+ tab_height
)
967 text_offset
= tab_x
+ tab_height
;
969 // chop text if necessary
970 wxString draw_text
= ChopText(dc
,
972 tab_width
- (text_offset
-tab_x
) - close_button_width
);
975 dc
.DrawText(draw_text
,
977 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
980 // draw close button if necessary
981 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
985 bmp
= m_active_close_bmp
;
987 bmp
= m_disabled_close_bmp
;
989 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
990 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
993 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
995 *out_button_rect
= rect
;
999 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1001 dc
.DestroyClippingRegion();
1004 int wxAuiSimpleTabArt::GetIndentSize()
1009 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1010 wxWindow
* WXUNUSED(wnd
),
1011 const wxString
& caption
,
1012 const wxBitmap
& WXUNUSED(bitmap
),
1013 bool WXUNUSED(active
),
1014 int close_button_state
,
1017 wxCoord measured_textx
, measured_texty
;
1019 dc
.SetFont(m_measuring_font
);
1020 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1022 wxCoord tab_height
= measured_texty
+ 4;
1023 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1025 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1026 tab_width
+= m_active_close_bmp
.GetWidth();
1028 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1030 tab_width
= m_fixed_tab_width
;
1033 *x_extent
= tab_width
- (tab_height
/2) - 1;
1035 return wxSize(tab_width
, tab_height
);
1039 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1040 wxWindow
* WXUNUSED(wnd
),
1041 const wxRect
& in_rect
,
1045 const wxBitmap
& bitmap_override
,
1051 if (bitmap_override
.IsOk())
1053 bmp
= bitmap_override
;
1059 case wxAUI_BUTTON_CLOSE
:
1060 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1061 bmp
= m_disabled_close_bmp
;
1063 bmp
= m_active_close_bmp
;
1065 case wxAUI_BUTTON_LEFT
:
1066 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1067 bmp
= m_disabled_left_bmp
;
1069 bmp
= m_active_left_bmp
;
1071 case wxAUI_BUTTON_RIGHT
:
1072 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1073 bmp
= m_disabled_right_bmp
;
1075 bmp
= m_active_right_bmp
;
1077 case wxAUI_BUTTON_WINDOWLIST
:
1078 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1079 bmp
= m_disabled_windowlist_bmp
;
1081 bmp
= m_active_windowlist_bmp
;
1091 if (orientation
== wxLEFT
)
1093 rect
.SetX(in_rect
.x
);
1094 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1095 rect
.SetWidth(bmp
.GetWidth());
1096 rect
.SetHeight(bmp
.GetHeight());
1100 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1101 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1102 bmp
.GetWidth(), bmp
.GetHeight());
1106 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1112 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1113 const wxArrayString
& items
,
1118 size_t i
, count
= items
.GetCount();
1119 for (i
= 0; i
< count
; ++i
)
1121 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1124 if (active_idx
!= -1)
1126 menuPopup
.Check(1000+active_idx
, true);
1129 // find out where to put the popup menu of window
1130 // items. Subtract 100 for now to center the menu
1131 // a bit, until a better mechanism can be implemented
1132 wxPoint pt
= ::wxGetMousePosition();
1133 pt
= wnd
->ScreenToClient(pt
);
1139 // find out the screen coordinate at the bottom of the tab ctrl
1140 wxRect cli_rect
= wnd
->GetClientRect();
1141 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1143 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1144 wnd
->PushEventHandler(cc
);
1145 wnd
->PopupMenu(&menuPopup
, pt
);
1146 int command
= cc
->GetCommandId();
1147 wnd
->PopEventHandler(true);
1149 if (command
>= 1000)
1150 return command
-1000;
1155 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1156 wxAuiNotebookPageArray
& WXUNUSED(pages
))
1159 dc
.SetFont(m_measuring_font
);
1161 wxSize s
= GetTabSize(dc
,
1166 wxAUI_BUTTON_STATE_HIDDEN
,
1171 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1173 m_normal_font
= font
;
1176 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1178 m_selected_font
= font
;
1181 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1183 m_measuring_font
= font
;
1189 // -- wxAuiTabContainer class implementation --
1192 // wxAuiTabContainer is a class which contains information about each
1193 // tab. It also can render an entire tab control to a specified DC.
1194 // It's not a window class itself, because this code will be used by
1195 // the wxFrameMananger, where it is disadvantageous to have separate
1196 // windows for each tab control in the case of "docked tabs"
1198 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1199 // which can be used as a tab control in the normal sense.
1202 wxAuiTabContainer::wxAuiTabContainer()
1206 m_art
= new wxAuiDefaultTabArt
;
1208 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1209 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1210 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1211 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1214 wxAuiTabContainer::~wxAuiTabContainer()
1219 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1226 m_art
->SetFlags(m_flags
);
1230 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1235 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1239 // check for new close button settings
1240 RemoveButton(wxAUI_BUTTON_LEFT
);
1241 RemoveButton(wxAUI_BUTTON_RIGHT
);
1242 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1243 RemoveButton(wxAUI_BUTTON_CLOSE
);
1246 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1248 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1249 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1252 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1254 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1257 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1259 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1264 m_art
->SetFlags(m_flags
);
1268 unsigned int wxAuiTabContainer::GetFlags() const
1274 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1276 m_art
->SetNormalFont(font
);
1279 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1281 m_art
->SetSelectedFont(font
);
1284 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1286 m_art
->SetMeasuringFont(font
);
1289 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1295 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1299 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1300 const wxAuiNotebookPage
& info
)
1302 wxAuiNotebookPage page_info
;
1304 page_info
.window
= page
;
1306 m_pages
.Add(page_info
);
1308 // let the art provider know how many pages we have
1311 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1317 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1318 const wxAuiNotebookPage
& info
,
1321 wxAuiNotebookPage page_info
;
1323 page_info
.window
= page
;
1325 if (idx
>= m_pages
.GetCount())
1326 m_pages
.Add(page_info
);
1328 m_pages
.Insert(page_info
, idx
);
1330 // let the art provider know how many pages we have
1333 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1339 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1342 int idx
= GetIdxFromWindow(page
);
1346 // get page entry, make a copy of it
1347 wxAuiNotebookPage p
= GetPage(idx
);
1349 // remove old page entry
1352 // insert page where it should be
1353 InsertPage(page
, p
, new_idx
);
1358 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1360 size_t i
, page_count
= m_pages
.GetCount();
1361 for (i
= 0; i
< page_count
; ++i
)
1363 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1364 if (page
.window
== wnd
)
1366 m_pages
.RemoveAt(i
);
1368 // let the art provider know how many pages we have
1371 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1381 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1385 size_t i
, page_count
= m_pages
.GetCount();
1386 for (i
= 0; i
< page_count
; ++i
)
1388 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1389 if (page
.window
== wnd
)
1396 page
.active
= false;
1403 void wxAuiTabContainer::SetNoneActive()
1405 size_t i
, page_count
= m_pages
.GetCount();
1406 for (i
= 0; i
< page_count
; ++i
)
1408 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1409 page
.active
= false;
1413 bool wxAuiTabContainer::SetActivePage(size_t page
)
1415 if (page
>= m_pages
.GetCount())
1418 return SetActivePage(m_pages
.Item(page
).window
);
1421 int wxAuiTabContainer::GetActivePage() const
1423 size_t i
, page_count
= m_pages
.GetCount();
1424 for (i
= 0; i
< page_count
; ++i
)
1426 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1434 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1436 if (idx
>= m_pages
.GetCount())
1439 return m_pages
[idx
].window
;
1442 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1444 size_t i
, page_count
= m_pages
.GetCount();
1445 for (i
= 0; i
< page_count
; ++i
)
1447 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1448 if (page
.window
== wnd
)
1454 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1456 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1458 return m_pages
[idx
];
1461 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1466 size_t wxAuiTabContainer::GetPageCount() const
1468 return m_pages
.GetCount();
1471 void wxAuiTabContainer::AddButton(int id
,
1473 const wxBitmap
& normal_bitmap
,
1474 const wxBitmap
& disabled_bitmap
)
1476 wxAuiTabContainerButton button
;
1478 button
.bitmap
= normal_bitmap
;
1479 button
.dis_bitmap
= disabled_bitmap
;
1480 button
.location
= location
;
1481 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1483 m_buttons
.Add(button
);
1486 void wxAuiTabContainer::RemoveButton(int id
)
1488 size_t i
, button_count
= m_buttons
.GetCount();
1490 for (i
= 0; i
< button_count
; ++i
)
1492 if (m_buttons
.Item(i
).id
== id
)
1494 m_buttons
.RemoveAt(i
);
1502 size_t wxAuiTabContainer::GetTabOffset() const
1504 return m_tab_offset
;
1507 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1509 m_tab_offset
= offset
;
1515 // Render() renders the tab catalog to the specified DC
1516 // It is a virtual function and can be overridden to
1517 // provide custom drawing capabilities
1518 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1520 if (!raw_dc
|| !raw_dc
->IsOk())
1526 size_t page_count
= m_pages
.GetCount();
1527 size_t button_count
= m_buttons
.GetCount();
1529 // create off-screen bitmap
1530 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1531 dc
.SelectObject(bmp
);
1536 // find out if size of tabs is larger than can be
1537 // afforded on screen
1538 int total_width
= 0;
1539 int visible_width
= 0;
1540 for (i
= 0; i
< page_count
; ++i
)
1542 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1544 // determine if a close button is on this tab
1545 bool close_button
= false;
1546 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1547 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1549 close_button
= true;
1554 wxSize size
= m_art
->GetTabSize(dc
,
1560 wxAUI_BUTTON_STATE_NORMAL
:
1561 wxAUI_BUTTON_STATE_HIDDEN
,
1564 if (i
+1 < page_count
)
1565 total_width
+= x_extent
;
1567 total_width
+= size
.x
;
1569 if (i
>= m_tab_offset
)
1571 if (i
+1 < page_count
)
1572 visible_width
+= x_extent
;
1574 visible_width
+= size
.x
;
1578 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1580 // show left/right buttons
1581 for (i
= 0; i
< button_count
; ++i
)
1583 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1584 if (button
.id
== wxAUI_BUTTON_LEFT
||
1585 button
.id
== wxAUI_BUTTON_RIGHT
)
1587 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1593 // hide left/right buttons
1594 for (i
= 0; i
< button_count
; ++i
)
1596 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1597 if (button
.id
== wxAUI_BUTTON_LEFT
||
1598 button
.id
== wxAUI_BUTTON_RIGHT
)
1600 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1605 // determine whether left button should be enabled
1606 for (i
= 0; i
< button_count
; ++i
)
1608 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1609 if (button
.id
== wxAUI_BUTTON_LEFT
)
1611 if (m_tab_offset
== 0)
1612 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1614 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1616 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1618 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1619 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1621 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1628 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1631 int left_buttons_width
= 0;
1632 int right_buttons_width
= 0;
1636 // draw the buttons on the right side
1637 offset
= m_rect
.x
+ m_rect
.width
;
1638 for (i
= 0; i
< button_count
; ++i
)
1640 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1642 if (button
.location
!= wxRIGHT
)
1644 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1647 wxRect button_rect
= m_rect
;
1648 button_rect
.SetY(1);
1649 button_rect
.SetWidth(offset
);
1651 m_art
->DrawButton(dc
,
1660 offset
-= button
.rect
.GetWidth();
1661 right_buttons_width
+= button
.rect
.GetWidth();
1668 // draw the buttons on the left side
1670 for (i
= 0; i
< button_count
; ++i
)
1672 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1674 if (button
.location
!= wxLEFT
)
1676 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1679 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1681 m_art
->DrawButton(dc
,
1690 offset
+= button
.rect
.GetWidth();
1691 left_buttons_width
+= button
.rect
.GetWidth();
1694 offset
= left_buttons_width
;
1697 offset
+= m_art
->GetIndentSize();
1700 // prepare the tab-close-button array
1701 // make sure tab button entries which aren't used are marked as hidden
1702 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1703 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1705 // make sure there are enough tab button entries to accommodate all tabs
1706 while (m_tab_close_buttons
.GetCount() < page_count
)
1708 wxAuiTabContainerButton tempbtn
;
1709 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1710 tempbtn
.location
= wxCENTER
;
1711 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1712 m_tab_close_buttons
.Add(tempbtn
);
1716 // buttons before the tab offset must be set to hidden
1717 for (i
= 0; i
< m_tab_offset
; ++i
)
1719 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1725 size_t active
= 999;
1726 int active_offset
= 0;
1730 wxRect rect
= m_rect
;
1732 rect
.height
= m_rect
.height
;
1734 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1736 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1737 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1739 // determine if a close button is on this tab
1740 bool close_button
= false;
1741 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1742 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1744 close_button
= true;
1745 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1747 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1748 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1749 tab_button
.location
= wxCENTER
;
1754 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1758 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1760 if (rect
.width
<= 0)
1769 tab_button
.cur_state
,
1777 active_offset
= offset
;
1785 // make sure to deactivate buttons which are off the screen to the right
1786 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1788 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1792 // draw the active tab again so it stands in the foreground
1793 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1795 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1797 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1799 // determine if a close button is on this tab
1800 bool close_button
= false;
1801 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1802 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1804 close_button
= true;
1807 rect
.x
= active_offset
;
1814 tab_button
.cur_state
,
1821 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1822 m_rect
.GetWidth(), m_rect
.GetHeight(),
1827 // TabHitTest() tests if a tab was hit, passing the window pointer
1828 // back if that condition was fulfilled. The function returns
1829 // true if a tab was hit, otherwise false
1830 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1832 if (!m_rect
.Contains(x
,y
))
1835 wxAuiTabContainerButton
* btn
= NULL
;
1836 if (ButtonHitTest(x
, y
, &btn
))
1838 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1842 size_t i
, page_count
= m_pages
.GetCount();
1844 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1846 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1847 if (page
.rect
.Contains(x
,y
))
1858 // ButtonHitTest() tests if a button was hit. The function returns
1859 // true if a button was hit, otherwise false
1860 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1861 wxAuiTabContainerButton
** hit
) const
1863 if (!m_rect
.Contains(x
,y
))
1866 size_t i
, button_count
;
1869 button_count
= m_buttons
.GetCount();
1870 for (i
= 0; i
< button_count
; ++i
)
1872 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1873 if (button
.rect
.Contains(x
,y
) &&
1874 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1875 wxAUI_BUTTON_STATE_DISABLED
)))
1883 button_count
= m_tab_close_buttons
.GetCount();
1884 for (i
= 0; i
< button_count
; ++i
)
1886 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1887 if (button
.rect
.Contains(x
,y
) &&
1888 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1889 wxAUI_BUTTON_STATE_DISABLED
)))
1902 // the utility function ShowWnd() is the same as show,
1903 // except it handles wxAuiMDIChildFrame windows as well,
1904 // as the Show() method on this class is "unplugged"
1905 static void ShowWnd(wxWindow
* wnd
, bool show
)
1907 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1909 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1919 // DoShowHide() this function shows the active window, then
1920 // hides all of the other windows (in that order)
1921 void wxAuiTabContainer::DoShowHide()
1923 wxAuiNotebookPageArray
& pages
= GetPages();
1924 size_t i
, page_count
= pages
.GetCount();
1926 // show new active page first
1927 for (i
= 0; i
< page_count
; ++i
)
1929 wxAuiNotebookPage
& page
= pages
.Item(i
);
1932 ShowWnd(page
.window
, true);
1937 // hide all other pages
1938 for (i
= 0; i
< page_count
; ++i
)
1940 wxAuiNotebookPage
& page
= pages
.Item(i
);
1941 ShowWnd(page
.window
, page
.active
);
1950 // -- wxAuiTabCtrl class implementation --
1954 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1955 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1956 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1957 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1958 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1959 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1960 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1961 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1962 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1966 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1970 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1972 m_click_pt
= wxDefaultPosition
;
1973 m_is_dragging
= false;
1974 m_hover_button
= NULL
;
1975 m_pressed_button
= NULL
;
1978 wxAuiTabCtrl::~wxAuiTabCtrl()
1982 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1986 dc
.SetFont(GetFont());
1988 if (GetPageCount() > 0)
1992 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1996 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1998 wxSize s
= evt
.GetSize();
1999 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2003 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2006 m_click_pt
= wxDefaultPosition
;
2007 m_is_dragging
= false;
2009 m_pressed_button
= NULL
;
2013 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2015 int new_selection
= GetIdxFromWindow(wnd
);
2017 if (new_selection
!= GetActivePage())
2019 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2020 e
.SetSelection(new_selection
);
2021 e
.SetOldSelection(GetActivePage());
2022 e
.SetEventObject(this);
2023 GetEventHandler()->ProcessEvent(e
);
2026 m_click_pt
.x
= evt
.m_x
;
2027 m_click_pt
.y
= evt
.m_y
;
2033 m_pressed_button
= m_hover_button
;
2034 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2040 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2042 if (GetCapture() == this)
2047 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2048 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2049 evt
.SetOldSelection(evt
.GetSelection());
2050 evt
.SetEventObject(this);
2051 GetEventHandler()->ProcessEvent(evt
);
2055 if (m_pressed_button
)
2057 // make sure we're still clicking the button
2058 wxAuiTabContainerButton
* button
= NULL
;
2059 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2062 if (button
!= m_pressed_button
)
2064 m_pressed_button
= NULL
;
2071 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2073 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2074 evt
.SetInt(m_pressed_button
->id
);
2075 evt
.SetEventObject(this);
2076 GetEventHandler()->ProcessEvent(evt
);
2079 m_pressed_button
= NULL
;
2082 m_click_pt
= wxDefaultPosition
;
2083 m_is_dragging
= false;
2087 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2089 wxPoint pos
= evt
.GetPosition();
2091 // check if the mouse is hovering above a button
2092 wxAuiTabContainerButton
* button
;
2093 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2095 if (m_hover_button
&& button
!= m_hover_button
)
2097 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2098 m_hover_button
= NULL
;
2103 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2105 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2108 m_hover_button
= button
;
2116 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2117 m_hover_button
= NULL
;
2124 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2129 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2130 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2131 evt
.SetOldSelection(evt
.GetSelection());
2132 evt
.SetEventObject(this);
2133 GetEventHandler()->ProcessEvent(evt
);
2138 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2139 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2141 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2142 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2144 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2145 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2146 evt
.SetOldSelection(evt
.GetSelection());
2147 evt
.SetEventObject(this);
2148 GetEventHandler()->ProcessEvent(evt
);
2150 m_is_dragging
= true;
2154 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2158 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2159 m_hover_button
= NULL
;
2165 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2167 int button
= event
.GetInt();
2169 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2171 if (button
== wxAUI_BUTTON_LEFT
)
2173 if (GetTabOffset() > 0)
2175 SetTabOffset(GetTabOffset()-1);
2182 SetTabOffset(GetTabOffset()+1);
2187 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2191 size_t i
, page_count
= m_pages
.GetCount();
2192 for (i
= 0; i
< page_count
; ++i
)
2194 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2195 as
.Add(page
.caption
);
2198 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2202 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2203 e
.SetSelection(idx
);
2204 e
.SetOldSelection(GetActivePage());
2205 e
.SetEventObject(this);
2206 GetEventHandler()->ProcessEvent(e
);
2215 // wxTabFrame is an interesting case. It's important that all child pages
2216 // of the multi-notebook control are all actually children of that control
2217 // (and not grandchildren). wxTabFrame facilitates this. There is one
2218 // instance of wxTabFrame for each tab control inside the multi-notebook.
2219 // It's important to know that wxTabFrame is not a real window, but it merely
2220 // used to capture the dimensions/positioning of the internal tab control and
2221 // it's managed page windows
2223 class wxTabFrame
: public wxWindow
2230 m_rect
= wxRect(0,0,200,200);
2231 m_tab_ctrl_height
= 20;
2234 void SetTabCtrlHeight(int h
)
2236 m_tab_ctrl_height
= h
;
2239 void DoSetSize(int x
, int y
,
2240 int width
, int height
,
2241 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2243 m_rect
= wxRect(x
, y
, width
, height
);
2247 void DoGetClientSize(int* x
, int* y
) const
2253 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2260 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2261 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2262 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2266 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2267 size_t i
, page_count
= pages
.GetCount();
2269 for (i
= 0; i
< page_count
; ++i
)
2271 wxAuiNotebookPage
& page
= pages
.Item(i
);
2272 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2273 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2275 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2277 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2278 wnd
->ApplyMDIChildFrameRect();
2283 void DoGetSize(int* x
, int* y
) const
2286 *x
= m_rect
.GetWidth();
2288 *y
= m_rect
.GetHeight();
2300 wxAuiTabCtrl
* m_tabs
;
2301 int m_tab_ctrl_height
;
2308 // -- wxAuiNotebook class implementation --
2310 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2311 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2312 //EVT_SIZE(wxAuiNotebook::OnSize)
2313 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2314 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2315 EVT_COMMAND_RANGE(10000, 10100,
2316 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2317 wxAuiNotebook::OnTabClicked
)
2318 EVT_COMMAND_RANGE(10000, 10100,
2319 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2320 wxAuiNotebook::OnTabBeginDrag
)
2321 EVT_COMMAND_RANGE(10000, 10100,
2322 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2323 wxAuiNotebook::OnTabEndDrag
)
2324 EVT_COMMAND_RANGE(10000, 10100,
2325 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2326 wxAuiNotebook::OnTabDragMotion
)
2327 EVT_COMMAND_RANGE(10000, 10100,
2328 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2329 wxAuiNotebook::OnTabButton
)
2332 wxAuiNotebook::wxAuiNotebook()
2335 m_tab_id_counter
= 10000;
2337 m_tab_ctrl_height
= 20;
2340 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2344 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2346 InitNotebook(style
);
2349 bool wxAuiNotebook::Create(wxWindow
* parent
,
2355 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2358 InitNotebook(style
);
2363 // InitNotebook() contains common initialization
2364 // code called by all constructors
2365 void wxAuiNotebook::InitNotebook(long style
)
2368 m_tab_id_counter
= 10000;
2370 m_tab_ctrl_height
= 20;
2371 m_flags
= (unsigned int)style
;
2373 m_normal_font
= *wxNORMAL_FONT
;
2374 m_selected_font
= *wxNORMAL_FONT
;
2375 m_selected_font
.SetWeight(wxBOLD
);
2377 SetArtProvider(new wxAuiDefaultTabArt
);
2379 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2380 m_dummy_wnd
->SetSize(200, 200);
2381 m_dummy_wnd
->Show(false);
2383 m_mgr
.SetManagedWindow(this);
2385 m_mgr
.AddPane(m_dummy_wnd
,
2386 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2391 wxAuiNotebook::~wxAuiNotebook()
2396 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2398 m_tabs
.SetArtProvider(art
);
2400 SetTabCtrlHeight(CalculateTabCtrlHeight());
2403 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2405 // if the tab control height needs to change, update
2406 // all of our tab controls with the new height
2407 if (m_tab_ctrl_height
!= height
)
2409 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2411 m_tab_ctrl_height
= height
;
2413 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2414 size_t i
, pane_count
= all_panes
.GetCount();
2415 for (i
= 0; i
< pane_count
; ++i
)
2417 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2418 if (pane
.name
== wxT("dummy"))
2420 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2421 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2422 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2423 tabctrl
->SetArtProvider(art
->Clone());
2424 tab_frame
->DoSizing();
2429 int wxAuiNotebook::CalculateTabCtrlHeight()
2431 // find out new best tab height
2432 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2434 return art
->GetBestTabCtrlSize(this, m_tabs
.GetPages());
2438 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2440 return m_tabs
.GetArtProvider();
2443 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2445 wxControl::SetWindowStyleFlag(style
);
2447 m_flags
= (unsigned int)style
;
2449 // if the control is already initialized
2450 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2452 // let all of the tab children know about the new style
2454 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2455 size_t i
, pane_count
= all_panes
.GetCount();
2456 for (i
= 0; i
< pane_count
; ++i
)
2458 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2459 if (pane
.name
== wxT("dummy"))
2461 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2462 tabctrl
->SetFlags(m_flags
);
2470 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2471 const wxString
& caption
,
2473 const wxBitmap
& bitmap
)
2475 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2478 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2480 const wxString
& caption
,
2482 const wxBitmap
& bitmap
)
2484 wxAuiNotebookPage info
;
2486 info
.caption
= caption
;
2487 info
.bitmap
= bitmap
;
2488 info
.active
= false;
2490 // if there are currently no tabs, the first added
2491 // tab must be active
2492 if (m_tabs
.GetPageCount() == 0)
2495 m_tabs
.InsertPage(page
, info
, page_idx
);
2497 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2498 if (page_idx
>= active_tabctrl
->GetPageCount())
2499 active_tabctrl
->AddPage(page
, info
);
2501 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2503 SetTabCtrlHeight(CalculateTabCtrlHeight());
2505 active_tabctrl
->DoShowHide();
2509 int idx
= m_tabs
.GetIdxFromWindow(page
);
2510 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2519 // DeletePage() removes a tab from the multi-notebook,
2520 // and destroys the window as well
2521 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2523 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2525 if (!RemovePage(page_idx
))
2528 // actually destroy the window now
2529 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2531 // delete the child frame with pending delete, as is
2532 // customary with frame windows
2533 if (!wxPendingDelete
.Member(wnd
))
2534 wxPendingDelete
.Append(wnd
);
2546 // RemovePage() removes a tab from the multi-notebook,
2547 // but does not destroy the window
2548 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2550 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2551 wxWindow
* new_active
= NULL
;
2553 // find out which onscreen tab ctrl owns this tab
2556 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2559 // find a new page and set it as active
2560 int new_idx
= ctrl_idx
+1;
2561 if (new_idx
>= (int)ctrl
->GetPageCount())
2562 new_idx
= ctrl_idx
-1;
2564 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2566 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2570 // set the active page to the first page that
2571 // isn't the one being deleted
2572 size_t i
, page_count
= m_tabs
.GetPageCount();
2573 for (i
= 0; i
< page_count
; ++i
)
2575 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2578 new_active
= m_tabs
.GetWindowFromIdx(i
);
2584 // remove the tab from main catalog
2585 if (!m_tabs
.RemovePage(wnd
))
2588 // remove the tab from the onscreen tab ctrl
2589 ctrl
->RemovePage(wnd
);
2592 RemoveEmptyTabFrames();
2594 // set new active pane
2598 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2604 // GetPageIndex() returns the index of the page, or -1 if the
2605 // page could not be located in the notebook
2606 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2608 return m_tabs
.GetIdxFromWindow(page_wnd
);
2613 // SetPageText() changes the tab caption of the specified page
2614 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2616 if (page_idx
>= m_tabs
.GetPageCount())
2619 // update our own tab catalog
2620 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2621 page_info
.caption
= text
;
2623 // update what's on screen
2626 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2628 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2629 info
.caption
= text
;
2638 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2640 if (page_idx
>= m_tabs
.GetPageCount())
2643 // update our own tab catalog
2644 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2645 page_info
.bitmap
= bitmap
;
2647 // tab height might have changed
2648 SetTabCtrlHeight(CalculateTabCtrlHeight());
2650 // update what's on screen
2653 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2655 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2656 info
.bitmap
= bitmap
;
2665 // GetSelection() returns the index of the currently active page
2666 int wxAuiNotebook::GetSelection() const
2671 // SetSelection() sets the currently active page
2672 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2674 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2678 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2679 evt
.SetSelection(new_page
);
2680 evt
.SetOldSelection(m_curpage
);
2681 evt
.SetEventObject(this);
2682 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2684 int old_curpage
= m_curpage
;
2685 m_curpage
= new_page
;
2687 // program allows the page change
2688 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2689 (void)GetEventHandler()->ProcessEvent(evt
);
2694 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2696 m_tabs
.SetActivePage(wnd
);
2698 ctrl
->SetActivePage(ctrl_idx
);
2705 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2706 size_t i
, pane_count
= all_panes
.GetCount();
2707 for (i
= 0; i
< pane_count
; ++i
)
2709 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2710 if (pane
.name
== wxT("dummy"))
2712 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2713 if (tabctrl
!= ctrl
)
2714 tabctrl
->SetSelectedFont(m_normal_font
);
2716 tabctrl
->SetSelectedFont(m_selected_font
);
2729 // GetPageCount() returns the total number of
2730 // pages managed by the multi-notebook
2731 size_t wxAuiNotebook::GetPageCount() const
2733 return m_tabs
.GetPageCount();
2736 // GetPage() returns the wxWindow pointer of the
2738 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2740 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2742 return m_tabs
.GetWindowFromIdx(page_idx
);
2745 // DoSizing() performs all sizing operations in each tab control
2746 void wxAuiNotebook::DoSizing()
2748 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2749 size_t i
, pane_count
= all_panes
.GetCount();
2750 for (i
= 0; i
< pane_count
; ++i
)
2752 if (all_panes
.Item(i
).name
== wxT("dummy"))
2755 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2756 tabframe
->DoSizing();
2760 // GetActiveTabCtrl() returns the active tab control. It is
2761 // called to determine which control gets new windows being added
2762 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2764 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2769 // find the tab ctrl with the current page
2770 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2777 // no current page, just find the first tab ctrl
2778 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2779 size_t i
, pane_count
= all_panes
.GetCount();
2780 for (i
= 0; i
< pane_count
; ++i
)
2782 if (all_panes
.Item(i
).name
== wxT("dummy"))
2785 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2786 return tabframe
->m_tabs
;
2789 // If there is no tabframe at all, create one
2790 wxTabFrame
* tabframe
= new wxTabFrame
;
2791 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2792 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2797 tabframe
->m_tabs
->SetFlags(m_flags
);
2798 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2799 m_mgr
.AddPane(tabframe
,
2800 wxAuiPaneInfo().Center().CaptionVisible(false));
2804 return tabframe
->m_tabs
;
2807 // FindTab() finds the tab control that currently contains the window as well
2808 // as the index of the window in the tab control. It returns true if the
2809 // window was found, otherwise false.
2810 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2812 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2813 size_t i
, pane_count
= all_panes
.GetCount();
2814 for (i
= 0; i
< pane_count
; ++i
)
2816 if (all_panes
.Item(i
).name
== wxT("dummy"))
2819 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2821 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2824 *ctrl
= tabframe
->m_tabs
;
2834 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2838 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2842 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2844 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2846 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2847 wxASSERT(ctrl
!= NULL
);
2849 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2850 wxASSERT(wnd
!= NULL
);
2852 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2853 wxASSERT(idx
!= -1);
2858 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2863 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2865 wxPoint screen_pt
= ::wxGetMousePosition();
2866 wxPoint client_pt
= ScreenToClient(screen_pt
);
2869 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2870 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2872 if (dest_tabs
== src_tabs
)
2876 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2879 // always hide the hint for inner-tabctrl drag
2882 // if tab moving is not allowed, leave
2883 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2888 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2889 wxWindow
* dest_location_tab
;
2891 // this is an inner-tab drag/reposition
2892 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2894 int src_idx
= evt
.GetSelection();
2895 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2897 // prevent jumpy drag
2898 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2899 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2900 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2902 m_last_drag_x
= pt
.x
;
2907 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2908 dest_tabs
->MovePage(src_tab
, dest_idx
);
2909 dest_tabs
->SetActivePage((size_t)dest_idx
);
2910 dest_tabs
->DoShowHide();
2911 dest_tabs
->Refresh();
2912 m_last_drag_x
= pt
.x
;
2920 // if external drag is allowed, check if the tab is being dragged
2921 // over a different wxAuiNotebook control
2922 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2924 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2926 // if we aren't over any window, stop here
2930 // make sure we are not over the hint window
2931 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2935 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2937 tab_ctrl
= tab_ctrl
->GetParent();
2942 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2946 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2947 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2948 m_mgr
.ShowHint(hint_rect
);
2957 // we are either over a hint window, or not over a tab
2958 // window, and there is no where to drag to, so exit
2965 // if there are less than two panes, split can't happen, so leave
2966 if (m_tabs
.GetPageCount() < 2)
2969 // if tab moving is not allowed, leave
2970 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2976 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2982 wxRect hint_rect
= dest_tabs
->GetRect();
2983 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2984 m_mgr
.ShowHint(hint_rect
);
2988 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2994 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2996 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3001 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3002 wxAuiTabCtrl
* dest_tabs
= NULL
;
3005 // set cursor back to an arrow
3006 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3009 // get the mouse position, which will be used to determine the drop point
3010 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3011 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3015 // check for an external move
3016 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3018 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3022 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3024 tab_ctrl
= tab_ctrl
->GetParent();
3029 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3033 // find out from the destination control
3034 // if it's ok to drop this tab here
3035 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3036 e
.SetSelection(evt
.GetSelection());
3037 e
.SetOldSelection(evt
.GetSelection());
3038 e
.SetEventObject(this);
3039 e
.SetDragSource(this);
3040 e
.Veto(); // dropping must be explicitly approved by control owner
3042 nb
->GetEventHandler()->ProcessEvent(e
);
3046 // no answer or negative answer
3052 int src_idx
= evt
.GetSelection();
3053 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3055 // get main index of the page
3056 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3058 // make a copy of the page info
3059 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3061 // remove the page from the source notebook
3062 RemovePage(main_idx
);
3064 // reparent the page
3065 src_page
->Reparent(nb
);
3068 // found out the insert idx
3069 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3070 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3072 wxWindow
* target
= NULL
;
3073 int insert_idx
= -1;
3074 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3077 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3081 // add the page to the new notebook
3082 if (insert_idx
== -1)
3083 insert_idx
= dest_tabs
->GetPageCount();
3084 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3085 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3088 dest_tabs
->DoShowHide();
3089 dest_tabs
->Refresh();
3091 // set the selection in the destination tab control
3092 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3102 // only perform a tab split if it's allowed
3103 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3105 // If the pointer is in an existing tab frame, do a tab insert
3106 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3107 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3108 int insert_idx
= -1;
3111 dest_tabs
= tab_frame
->m_tabs
;
3113 if (dest_tabs
== src_tabs
)
3117 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3118 wxWindow
* target
= NULL
;
3119 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3122 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3127 // If there is no tabframe at all, create one
3128 wxTabFrame
* new_tabs
= new wxTabFrame
;
3129 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3130 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3135 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3136 new_tabs
->m_tabs
->SetFlags(m_flags
);
3138 m_mgr
.AddPane(new_tabs
,
3139 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3142 dest_tabs
= new_tabs
->m_tabs
;
3147 // remove the page from the source tabs
3148 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3149 page_info
.active
= false;
3150 src_tabs
->RemovePage(page_info
.window
);
3151 if (src_tabs
->GetPageCount() > 0)
3153 src_tabs
->SetActivePage((size_t)0);
3154 src_tabs
->DoShowHide();
3155 src_tabs
->Refresh();
3160 // add the page to the destination tabs
3161 if (insert_idx
== -1)
3162 insert_idx
= dest_tabs
->GetPageCount();
3163 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3165 if (src_tabs
->GetPageCount() == 0)
3167 RemoveEmptyTabFrames();
3171 dest_tabs
->DoShowHide();
3172 dest_tabs
->Refresh();
3174 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3180 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3182 // if we've just removed the last tab from the source
3183 // tab set, the remove the tab control completely
3184 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3185 size_t i
, pane_count
= all_panes
.GetCount();
3186 for (i
= 0; i
< pane_count
; ++i
)
3188 if (all_panes
.Item(i
).name
== wxT("dummy"))
3191 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3192 if (tabframe
->m_tab_rect
.Contains(pt
))
3193 return tabframe
->m_tabs
;
3199 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3201 // if we've just removed the last tab from the source
3202 // tab set, the remove the tab control completely
3203 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3204 size_t i
, pane_count
= all_panes
.GetCount();
3205 for (i
= 0; i
< pane_count
; ++i
)
3207 if (all_panes
.Item(i
).name
== wxT("dummy"))
3210 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3211 if (tabframe
->m_tabs
== tab_ctrl
)
3220 void wxAuiNotebook::RemoveEmptyTabFrames()
3222 // if we've just removed the last tab from the source
3223 // tab set, the remove the tab control completely
3224 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3225 size_t i
, pane_count
= all_panes
.GetCount();
3226 for (i
= 0; i
< pane_count
; ++i
)
3228 if (all_panes
.Item(i
).name
== wxT("dummy"))
3231 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3232 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3234 m_mgr
.DetachPane(tab_frame
);
3236 // use pending delete because sometimes during
3237 // window closing, refreshs are pending
3238 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3239 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3240 //tab_frame->m_tabs->Destroy();
3247 // check to see if there is still a center pane;
3248 // if there isn't, make a frame the center pane
3249 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3250 pane_count
= panes
.GetCount();
3251 wxWindow
* first_good
= NULL
;
3252 bool center_found
= false;
3253 for (i
= 0; i
< pane_count
; ++i
)
3255 if (panes
.Item(i
).name
== wxT("dummy"))
3257 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3258 center_found
= true;
3260 first_good
= panes
.Item(i
).window
;
3263 if (!center_found
&& first_good
)
3265 m_mgr
.GetPane(first_good
).Centre();
3271 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3273 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3274 if (idx
!= -1 && idx
!= m_curpage
)
3281 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3283 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3284 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3286 int button_id
= evt
.GetInt();
3288 if (button_id
== wxAUI_BUTTON_CLOSE
)
3290 int selection
= tabs
->GetActivePage();
3292 if (selection
!= -1)
3294 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3297 // ask owner if it's ok to close the tab
3298 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3299 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3300 e
.SetOldSelection(evt
.GetSelection());
3301 e
.SetEventObject(this);
3302 GetEventHandler()->ProcessEvent(e
);
3307 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3313 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3314 DeletePage(main_idx
);