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 // these functions live in dockart.cpp -- they'll eventually
61 // be moved to a new utility cpp file
63 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
65 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
66 const wxColour
& color
);
68 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
70 static void DrawButtons(wxDC
& dc
,
73 const wxColour
& bkcolour
,
78 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
84 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
85 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
87 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
88 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
90 // draw the background behind the button
91 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
94 // draw the button itself
95 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
98 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
100 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
109 // -- GUI helper classes and functions --
111 class wxAuiCommandCapture
: public wxEvtHandler
115 wxAuiCommandCapture() { m_last_id
= 0; }
116 int GetCommandId() const { return m_last_id
; }
118 bool ProcessEvent(wxEvent
& evt
)
120 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
122 m_last_id
= evt
.GetId();
126 if (GetNextHandler())
127 return GetNextHandler()->ProcessEvent(evt
);
139 #if defined( __WXMAC__ )
140 static unsigned char close_bits
[]={
141 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
142 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
143 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
144 #elif defined( __WXGTK__)
145 static unsigned char close_bits
[]={
146 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
147 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
148 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
150 static unsigned char close_bits
[]={
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
152 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156 static unsigned char left_bits
[] = {
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
158 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
161 static unsigned char right_bits
[] = {
162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
163 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
166 static unsigned char list_bits
[] = {
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
168 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
176 // -- wxAuiDefaultTabArt class implementation --
178 wxAuiDefaultTabArt
::wxAuiDefaultTabArt()
180 m_normal_font
= *wxNORMAL_FONT
;
181 m_selected_font
= *wxNORMAL_FONT
;
182 m_selected_font
.SetWeight(wxBOLD
);
183 m_measuring_font
= m_selected_font
;
185 m_fixed_tab_width
= 100;
186 m_tab_ctrl_height
= 0;
189 wxBrush toolbarbrush
;
190 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
191 wxColor base_colour
= toolbarbrush
.GetColour();
193 wxColor base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
196 m_base_colour
= base_colour
;
197 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
199 m_border_pen
= wxPen(border_colour
);
200 m_base_colour_pen
= wxPen(m_base_colour
);
201 m_base_colour_brush
= wxBrush(m_base_colour
);
203 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
204 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
206 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
207 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
209 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
210 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
212 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
213 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
218 wxAuiDefaultTabArt
::~wxAuiDefaultTabArt()
222 wxAuiTabArt
* wxAuiDefaultTabArt
::Clone()
224 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
227 void wxAuiDefaultTabArt
::SetFlags(unsigned int flags
)
232 void wxAuiDefaultTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
235 m_fixed_tab_width
= 100;
237 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
239 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
240 tot_width
-= m_active_close_bmp
.GetWidth();
241 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
242 tot_width
-= m_active_windowlist_bmp
.GetWidth();
246 m_fixed_tab_width
= tot_width
/(int)tab_count
;
250 if (m_fixed_tab_width
< 100)
251 m_fixed_tab_width
= 100;
253 if (m_fixed_tab_width
> tot_width
/2)
254 m_fixed_tab_width
= tot_width
/2;
256 if (m_fixed_tab_width
> 220)
257 m_fixed_tab_width
= 220;
259 m_tab_ctrl_height
= tab_ctrl_size
.y
;
263 void wxAuiDefaultTabArt
::DrawBackground(wxDC
& dc
,
264 wxWindow
* WXUNUSED(wnd
),
268 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
269 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
270 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
271 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
274 int y
= rect
.GetHeight();
275 int w
= rect
.GetWidth();
276 dc
.SetPen(m_border_pen
);
277 dc
.SetBrush(m_base_colour_brush
);
278 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
282 // DrawTab() draws an individual tab.
285 // in_rect - rectangle the tab should be confined to
286 // caption - tab's caption
287 // active - whether or not the tab is active
288 // out_rect - actual output rectangle
289 // x_extent - the advance x; where the next tab should start
291 void wxAuiDefaultTabArt
::DrawTab(wxDC
& dc
,
293 const wxRect
& in_rect
,
294 const wxString
& caption_text
,
295 const wxBitmap
& bitmap
,
297 int close_button_state
,
298 wxRect
* out_tab_rect
,
299 wxRect
* out_button_rect
,
302 wxCoord normal_textx
, normal_texty
;
303 wxCoord selected_textx
, selected_texty
;
304 wxCoord textx
, texty
;
306 // if the caption is empty, measure some temporary text
307 wxString caption
= caption_text
;
308 if (caption_text
.empty())
311 dc
.SetFont(m_selected_font
);
312 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
314 dc
.SetFont(m_normal_font
);
315 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
317 // figure out the size of the tab
318 wxSize tab_size
= GetTabSize(dc
,
326 wxCoord tab_height
= m_tab_ctrl_height
- 3;
327 wxCoord tab_width
= tab_size
.x
;
328 wxCoord tab_x
= in_rect
.x
;
329 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
332 caption
= caption_text
;
335 // select pen, brush and font for the tab to be drawn
339 dc
.SetFont(m_selected_font
);
340 textx
= selected_textx
;
341 texty
= selected_texty
;
345 dc
.SetFont(m_normal_font
);
346 textx
= normal_textx
;
347 texty
= normal_texty
;
351 // create points that will make the tab outline
353 int clip_width
= tab_width
;
354 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
355 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
358 wxPoint clip_points[6];
359 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
360 clip_points[1] = wxPoint(tab_x, tab_y+2);
361 clip_points[2] = wxPoint(tab_x+2, tab_y);
362 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
363 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
364 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
366 // FIXME: these ports don't provide wxRegion ctor from array of points
367 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
368 // set the clipping region for the tab --
369 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
370 dc.SetClippingRegion(clipping_region);
371 #endif // !wxDFB && !wxCocoa
373 // since the above code above doesn't play well with WXDFB or WXCOCOA,
374 // we'll just use a rectangle for the clipping region for now --
375 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
378 wxPoint border_points
[6];
379 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
380 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
381 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
382 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
383 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
384 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
387 int drawn_tab_yoff
= border_points
[1].y
;
388 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
395 // draw base background color
396 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
397 dc
.SetPen(m_base_colour_pen
);
398 dc
.SetBrush(m_base_colour_brush
);
399 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
401 // this white helps fill out the gradient at the top of the tab
402 dc
.SetPen(*wxWHITE_PEN
);
403 dc
.SetBrush(*wxWHITE_BRUSH
);
404 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
406 // these two points help the rounded corners appear more antialiased
407 dc
.SetPen(m_base_colour_pen
);
408 dc
.DrawPoint(r
.x
+2, r
.y
+1);
409 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
411 // set rectangle down a bit for gradient drawing
412 r
.SetHeight(r
.GetHeight()/2);
418 // draw gradient background
419 wxColor top_color
= *wxWHITE
;
420 wxColor bottom_color
= m_base_colour
;
421 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
427 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
429 // start the gradent up a bit and leave the inside border inset
430 // by a pixel for a 3D look. Only the top half of the inactive
431 // tab will have a slight gradient
438 // -- draw top gradient fill for glossy look
439 wxColor top_color
= m_base_colour
;
440 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
441 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
446 // -- draw bottom fill for glossy look
447 top_color
= m_base_colour
;
448 bottom_color
= m_base_colour
;
449 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
453 dc
.SetPen(m_border_pen
);
454 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
455 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
457 // there are two horizontal grey lines at the bottom of the tab control,
458 // this gets rid of the top one of those lines in the tab control
461 wxColor start_color
= m_base_colour
;
462 dc
.SetPen(m_base_colour_pen
);
463 dc
.DrawLine(border_points
[0].x
+1,
470 int text_offset
= tab_x
+ 8;
471 int close_button_width
= 0;
472 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
474 close_button_width
= m_active_close_bmp
.GetWidth();
480 int bitmap_offset
= tab_x
+ 8;
483 dc
.DrawBitmap(bitmap
,
485 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2),
488 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
489 text_offset
+= 3; // bitmap padding
493 text_offset
= tab_x
+ 8;
497 wxString draw_text
= wxAuiChopText(dc
,
499 tab_width
- (text_offset
-tab_x
) - close_button_width
);
502 dc
.DrawText(draw_text
,
504 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
509 // draw close button if necessary
510 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
512 wxBitmap bmp
= m_disabled_close_bmp
;
514 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
515 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
517 bmp
= m_active_close_bmp
;
520 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
521 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
524 IndentPressedBitmap(&rect
, close_button_state
);
525 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
527 *out_button_rect
= rect
;
530 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
532 dc
.DestroyClippingRegion();
535 int wxAuiDefaultTabArt
::GetIndentSize()
540 wxSize wxAuiDefaultTabArt
::GetTabSize(wxDC
& dc
,
541 wxWindow
* WXUNUSED(wnd
),
542 const wxString
& caption
,
543 const wxBitmap
& bitmap
,
544 bool WXUNUSED(active
),
545 int close_button_state
,
548 wxCoord measured_textx
, measured_texty
, tmp
;
550 dc
.SetFont(m_measuring_font
);
551 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
553 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
555 // add padding around the text
556 wxCoord tab_width
= measured_textx
;
557 wxCoord tab_height
= measured_texty
;
559 // if the close button is showing, add space for it
560 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
561 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
563 // if there's a bitmap, add space for it
566 tab_width
+= bitmap
.GetWidth();
567 tab_width
+= 3; // right side bitmap padding
568 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
575 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
577 tab_width
= m_fixed_tab_width
;
580 *x_extent
= tab_width
;
582 return wxSize(tab_width
, tab_height
);
586 void wxAuiDefaultTabArt
::DrawButton(wxDC
& dc
,
587 wxWindow
* WXUNUSED(wnd
),
588 const wxRect
& in_rect
,
592 const wxBitmap
& bitmap_override
,
598 if (bitmap_override
.IsOk())
600 bmp
= bitmap_override
;
606 case wxAUI_BUTTON_CLOSE
:
607 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
608 bmp
= m_disabled_close_bmp
;
610 bmp
= m_active_close_bmp
;
612 case wxAUI_BUTTON_LEFT
:
613 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
614 bmp
= m_disabled_left_bmp
;
616 bmp
= m_active_left_bmp
;
618 case wxAUI_BUTTON_RIGHT
:
619 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
620 bmp
= m_disabled_right_bmp
;
622 bmp
= m_active_right_bmp
;
624 case wxAUI_BUTTON_WINDOWLIST
:
625 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
626 bmp
= m_disabled_windowlist_bmp
;
628 bmp
= m_active_windowlist_bmp
;
638 if (orientation
== wxLEFT
)
640 rect
.SetX(in_rect
.x
);
641 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
642 rect
.SetWidth(bmp
.GetWidth());
643 rect
.SetHeight(bmp
.GetHeight());
647 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
648 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
649 bmp
.GetWidth(), bmp
.GetHeight());
652 IndentPressedBitmap(&rect
, button_state
);
653 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
659 int wxAuiDefaultTabArt
::ShowWindowList(wxWindow
* wnd
,
660 const wxArrayString
& items
,
665 size_t i
, count
= items
.GetCount();
666 for (i
= 0; i
< count
; ++i
)
668 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
671 if (active_idx
!= -1)
673 menuPopup
.Check(1000+active_idx
, true);
676 // find out where to put the popup menu of window
677 // items. Subtract 100 for now to center the menu
678 // a bit, until a better mechanism can be implemented
679 wxPoint pt
= ::wxGetMousePosition();
680 pt
= wnd
->ScreenToClient(pt
);
686 // find out the screen coordinate at the bottom of the tab ctrl
687 wxRect cli_rect
= wnd
->GetClientRect();
688 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
690 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
691 wnd
->PushEventHandler(cc
);
692 wnd
->PopupMenu(&menuPopup
, pt
);
693 int command
= cc
->GetCommandId();
694 wnd
->PopEventHandler(true);
702 int wxAuiDefaultTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
703 wxAuiNotebookPageArray
& pages
,
704 const wxSize
& required_bmp_size
)
707 dc
.SetFont(m_measuring_font
);
709 // sometimes a standard bitmap size needs to be enforced, especially
710 // if some tabs have bitmaps and others don't. This is important because
711 // it prevents the tab control from resizing when tabs are added.
712 wxBitmap measure_bmp
;
713 if (required_bmp_size
.IsFullySpecified())
715 measure_bmp
.Create(required_bmp_size
.x
,
716 required_bmp_size
.y
);
721 size_t i
, page_count
= pages
.GetCount();
722 for (i
= 0; i
< page_count
; ++i
)
724 wxAuiNotebookPage
& page
= pages
.Item(i
);
727 if (measure_bmp
.IsOk())
732 // we don't use the caption text because we don't
733 // want tab heights to be different in the case
734 // of a very short piece of text on one tab and a very
735 // tall piece of text on another tab
737 wxSize s
= GetTabSize(dc
,
742 wxAUI_BUTTON_STATE_HIDDEN
,
745 max_y
= wxMax(max_y
, s
.y
);
751 void wxAuiDefaultTabArt
::SetNormalFont(const wxFont
& font
)
753 m_normal_font
= font
;
756 void wxAuiDefaultTabArt
::SetSelectedFont(const wxFont
& font
)
758 m_selected_font
= font
;
761 void wxAuiDefaultTabArt
::SetMeasuringFont(const wxFont
& font
)
763 m_measuring_font
= font
;
767 // -- wxAuiSimpleTabArt class implementation --
769 wxAuiSimpleTabArt
::wxAuiSimpleTabArt()
771 m_normal_font
= *wxNORMAL_FONT
;
772 m_selected_font
= *wxNORMAL_FONT
;
773 m_selected_font
.SetWeight(wxBOLD
);
774 m_measuring_font
= m_selected_font
;
777 m_fixed_tab_width
= 100;
779 wxColour base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
781 wxColour background_colour
= base_colour
;
782 wxColour normaltab_colour
= base_colour
;
783 wxColour selectedtab_colour
= *wxWHITE
;
785 m_bkbrush
= wxBrush(background_colour
);
786 m_normal_bkbrush
= wxBrush(normaltab_colour
);
787 m_normal_bkpen
= wxPen(normaltab_colour
);
788 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
789 m_selected_bkpen
= wxPen(selectedtab_colour
);
791 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
792 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
794 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
795 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
797 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
798 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
800 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
801 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
805 wxAuiSimpleTabArt
::~wxAuiSimpleTabArt()
809 wxAuiTabArt
* wxAuiSimpleTabArt
::Clone()
811 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
815 void wxAuiSimpleTabArt
::SetFlags(unsigned int flags
)
820 void wxAuiSimpleTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
823 m_fixed_tab_width
= 100;
825 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
827 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
828 tot_width
-= m_active_close_bmp
.GetWidth();
829 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
830 tot_width
-= m_active_windowlist_bmp
.GetWidth();
834 m_fixed_tab_width
= tot_width
/(int)tab_count
;
838 if (m_fixed_tab_width
< 100)
839 m_fixed_tab_width
= 100;
841 if (m_fixed_tab_width
> tot_width
/2)
842 m_fixed_tab_width
= tot_width
/2;
844 if (m_fixed_tab_width
> 220)
845 m_fixed_tab_width
= 220;
848 void wxAuiSimpleTabArt
::DrawBackground(wxDC
& dc
,
849 wxWindow
* WXUNUSED(wnd
),
853 dc
.SetBrush(m_bkbrush
);
854 dc
.SetPen(*wxTRANSPARENT_PEN
);
855 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
858 dc
.SetPen(*wxGREY_PEN
);
859 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
863 // DrawTab() draws an individual tab.
866 // in_rect - rectangle the tab should be confined to
867 // caption - tab's caption
868 // active - whether or not the tab is active
869 // out_rect - actual output rectangle
870 // x_extent - the advance x; where the next tab should start
872 void wxAuiSimpleTabArt
::DrawTab(wxDC
& dc
,
874 const wxRect
& in_rect
,
875 const wxString
& caption_text
,
876 const wxBitmap
& bitmap
,
878 int close_button_state
,
879 wxRect
* out_tab_rect
,
880 wxRect
* out_button_rect
,
883 wxCoord normal_textx
, normal_texty
;
884 wxCoord selected_textx
, selected_texty
;
885 wxCoord textx
, texty
;
887 // if the caption is empty, measure some temporary text
888 wxString caption
= caption_text
;
889 if (caption_text
.empty())
892 dc
.SetFont(m_selected_font
);
893 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
895 dc
.SetFont(m_normal_font
);
896 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
898 // figure out the size of the tab
899 wxSize tab_size
= GetTabSize(dc
,
907 wxCoord tab_height
= tab_size
.y
;
908 wxCoord tab_width
= tab_size
.x
;
909 wxCoord tab_x
= in_rect
.x
;
910 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
912 caption
= caption_text
;
914 // select pen, brush and font for the tab to be drawn
918 dc
.SetPen(m_selected_bkpen
);
919 dc
.SetBrush(m_selected_bkbrush
);
920 dc
.SetFont(m_selected_font
);
921 textx
= selected_textx
;
922 texty
= selected_texty
;
926 dc
.SetPen(m_normal_bkpen
);
927 dc
.SetBrush(m_normal_bkbrush
);
928 dc
.SetFont(m_normal_font
);
929 textx
= normal_textx
;
930 texty
= normal_texty
;
938 points
[0].y
= tab_y
+ tab_height
- 1;
939 points
[1].x
= tab_x
+ tab_height
- 3;
940 points
[1].y
= tab_y
+ 2;
941 points
[2].x
= tab_x
+ tab_height
+ 3;
943 points
[3].x
= tab_x
+ tab_width
- 2;
945 points
[4].x
= tab_x
+ tab_width
;
946 points
[4].y
= tab_y
+ 2;
947 points
[5].x
= tab_x
+ tab_width
;
948 points
[5].y
= tab_y
+ tab_height
- 1;
949 points
[6] = points
[0];
951 dc
.SetClippingRegion(in_rect
);
953 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
955 dc
.SetPen(*wxGREY_PEN
);
957 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
958 dc
.DrawLines(WXSIZEOF(points
), points
);
963 int close_button_width
= 0;
964 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
966 close_button_width
= m_active_close_bmp
.GetWidth();
967 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
971 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
974 // set minimum text offset
975 if (text_offset
< tab_x
+ tab_height
)
976 text_offset
= tab_x
+ tab_height
;
978 // chop text if necessary
979 wxString draw_text
= wxAuiChopText(dc
,
981 tab_width
- (text_offset
-tab_x
) - close_button_width
);
984 dc
.DrawText(draw_text
,
986 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
989 // draw close button if necessary
990 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
994 bmp
= m_active_close_bmp
;
996 bmp
= m_disabled_close_bmp
;
998 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
999 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1002 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1004 *out_button_rect
= rect
;
1008 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1010 dc
.DestroyClippingRegion();
1013 int wxAuiSimpleTabArt
::GetIndentSize()
1018 wxSize wxAuiSimpleTabArt
::GetTabSize(wxDC
& dc
,
1019 wxWindow
* WXUNUSED(wnd
),
1020 const wxString
& caption
,
1021 const wxBitmap
& WXUNUSED(bitmap
),
1022 bool WXUNUSED(active
),
1023 int close_button_state
,
1026 wxCoord measured_textx
, measured_texty
;
1028 dc
.SetFont(m_measuring_font
);
1029 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1031 wxCoord tab_height
= measured_texty
+ 4;
1032 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1034 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1035 tab_width
+= m_active_close_bmp
.GetWidth();
1037 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1039 tab_width
= m_fixed_tab_width
;
1042 *x_extent
= tab_width
- (tab_height
/2) - 1;
1044 return wxSize(tab_width
, tab_height
);
1048 void wxAuiSimpleTabArt
::DrawButton(wxDC
& dc
,
1049 wxWindow
* WXUNUSED(wnd
),
1050 const wxRect
& in_rect
,
1054 const wxBitmap
& bitmap_override
,
1060 if (bitmap_override
.IsOk())
1062 bmp
= bitmap_override
;
1068 case wxAUI_BUTTON_CLOSE
:
1069 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1070 bmp
= m_disabled_close_bmp
;
1072 bmp
= m_active_close_bmp
;
1074 case wxAUI_BUTTON_LEFT
:
1075 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1076 bmp
= m_disabled_left_bmp
;
1078 bmp
= m_active_left_bmp
;
1080 case wxAUI_BUTTON_RIGHT
:
1081 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1082 bmp
= m_disabled_right_bmp
;
1084 bmp
= m_active_right_bmp
;
1086 case wxAUI_BUTTON_WINDOWLIST
:
1087 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1088 bmp
= m_disabled_windowlist_bmp
;
1090 bmp
= m_active_windowlist_bmp
;
1100 if (orientation
== wxLEFT
)
1102 rect
.SetX(in_rect
.x
);
1103 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1104 rect
.SetWidth(bmp
.GetWidth());
1105 rect
.SetHeight(bmp
.GetHeight());
1109 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1110 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1111 bmp
.GetWidth(), bmp
.GetHeight());
1115 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1121 int wxAuiSimpleTabArt
::ShowWindowList(wxWindow
* wnd
,
1122 const wxArrayString
& items
,
1127 size_t i
, count
= items
.GetCount();
1128 for (i
= 0; i
< count
; ++i
)
1130 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1133 if (active_idx
!= -1)
1135 menuPopup
.Check(1000+active_idx
, true);
1138 // find out where to put the popup menu of window
1139 // items. Subtract 100 for now to center the menu
1140 // a bit, until a better mechanism can be implemented
1141 wxPoint pt
= ::wxGetMousePosition();
1142 pt
= wnd
->ScreenToClient(pt
);
1148 // find out the screen coordinate at the bottom of the tab ctrl
1149 wxRect cli_rect
= wnd
->GetClientRect();
1150 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1152 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1153 wnd
->PushEventHandler(cc
);
1154 wnd
->PopupMenu(&menuPopup
, pt
);
1155 int command
= cc
->GetCommandId();
1156 wnd
->PopEventHandler(true);
1158 if (command
>= 1000)
1159 return command
-1000;
1164 int wxAuiSimpleTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
1165 wxAuiNotebookPageArray
& WXUNUSED(pages
),
1166 const wxSize
& WXUNUSED(required_bmp_size
))
1169 dc
.SetFont(m_measuring_font
);
1171 wxSize s
= GetTabSize(dc
,
1176 wxAUI_BUTTON_STATE_HIDDEN
,
1181 void wxAuiSimpleTabArt
::SetNormalFont(const wxFont
& font
)
1183 m_normal_font
= font
;
1186 void wxAuiSimpleTabArt
::SetSelectedFont(const wxFont
& font
)
1188 m_selected_font
= font
;
1191 void wxAuiSimpleTabArt
::SetMeasuringFont(const wxFont
& font
)
1193 m_measuring_font
= font
;
1199 // -- wxAuiTabContainer class implementation --
1202 // wxAuiTabContainer is a class which contains information about each
1203 // tab. It also can render an entire tab control to a specified DC.
1204 // It's not a window class itself, because this code will be used by
1205 // the wxFrameMananger, where it is disadvantageous to have separate
1206 // windows for each tab control in the case of "docked tabs"
1208 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1209 // which can be used as a tab control in the normal sense.
1212 wxAuiTabContainer
::wxAuiTabContainer()
1216 m_art
= new wxAuiDefaultTabArt
;
1218 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1219 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1220 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1221 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1224 wxAuiTabContainer
::~wxAuiTabContainer()
1229 void wxAuiTabContainer
::SetArtProvider(wxAuiTabArt
* art
)
1236 m_art
->SetFlags(m_flags
);
1240 wxAuiTabArt
* wxAuiTabContainer
::GetArtProvider() const
1245 void wxAuiTabContainer
::SetFlags(unsigned int flags
)
1249 // check for new close button settings
1250 RemoveButton(wxAUI_BUTTON_LEFT
);
1251 RemoveButton(wxAUI_BUTTON_RIGHT
);
1252 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1253 RemoveButton(wxAUI_BUTTON_CLOSE
);
1256 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1258 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1259 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1262 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1264 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1267 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1269 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1274 m_art
->SetFlags(m_flags
);
1278 unsigned int wxAuiTabContainer
::GetFlags() const
1284 void wxAuiTabContainer
::SetNormalFont(const wxFont
& font
)
1286 m_art
->SetNormalFont(font
);
1289 void wxAuiTabContainer
::SetSelectedFont(const wxFont
& font
)
1291 m_art
->SetSelectedFont(font
);
1294 void wxAuiTabContainer
::SetMeasuringFont(const wxFont
& font
)
1296 m_art
->SetMeasuringFont(font
);
1299 void wxAuiTabContainer
::SetRect(const wxRect
& rect
)
1305 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1309 bool wxAuiTabContainer
::AddPage(wxWindow
* page
,
1310 const wxAuiNotebookPage
& info
)
1312 wxAuiNotebookPage page_info
;
1314 page_info
.window
= page
;
1316 m_pages
.Add(page_info
);
1318 // let the art provider know how many pages we have
1321 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1327 bool wxAuiTabContainer
::InsertPage(wxWindow
* page
,
1328 const wxAuiNotebookPage
& info
,
1331 wxAuiNotebookPage page_info
;
1333 page_info
.window
= page
;
1335 if (idx
>= m_pages
.GetCount())
1336 m_pages
.Add(page_info
);
1338 m_pages
.Insert(page_info
, idx
);
1340 // let the art provider know how many pages we have
1343 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1349 bool wxAuiTabContainer
::MovePage(wxWindow
* page
,
1352 int idx
= GetIdxFromWindow(page
);
1356 // get page entry, make a copy of it
1357 wxAuiNotebookPage p
= GetPage(idx
);
1359 // remove old page entry
1362 // insert page where it should be
1363 InsertPage(page
, p
, new_idx
);
1368 bool wxAuiTabContainer
::RemovePage(wxWindow
* wnd
)
1370 size_t i
, page_count
= m_pages
.GetCount();
1371 for (i
= 0; i
< page_count
; ++i
)
1373 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1374 if (page
.window
== wnd
)
1376 m_pages
.RemoveAt(i
);
1378 // let the art provider know how many pages we have
1381 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1391 bool wxAuiTabContainer
::SetActivePage(wxWindow
* wnd
)
1395 size_t i
, page_count
= m_pages
.GetCount();
1396 for (i
= 0; i
< page_count
; ++i
)
1398 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1399 if (page
.window
== wnd
)
1406 page
.active
= false;
1413 void wxAuiTabContainer
::SetNoneActive()
1415 size_t i
, page_count
= m_pages
.GetCount();
1416 for (i
= 0; i
< page_count
; ++i
)
1418 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1419 page
.active
= false;
1423 bool wxAuiTabContainer
::SetActivePage(size_t page
)
1425 if (page
>= m_pages
.GetCount())
1428 return SetActivePage(m_pages
.Item(page
).window
);
1431 int wxAuiTabContainer
::GetActivePage() const
1433 size_t i
, page_count
= m_pages
.GetCount();
1434 for (i
= 0; i
< page_count
; ++i
)
1436 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1444 wxWindow
* wxAuiTabContainer
::GetWindowFromIdx(size_t idx
) const
1446 if (idx
>= m_pages
.GetCount())
1449 return m_pages
[idx
].window
;
1452 int wxAuiTabContainer
::GetIdxFromWindow(wxWindow
* wnd
) const
1454 size_t i
, page_count
= m_pages
.GetCount();
1455 for (i
= 0; i
< page_count
; ++i
)
1457 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1458 if (page
.window
== wnd
)
1464 wxAuiNotebookPage
& wxAuiTabContainer
::GetPage(size_t idx
)
1466 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1468 return m_pages
[idx
];
1471 wxAuiNotebookPageArray
& wxAuiTabContainer
::GetPages()
1476 size_t wxAuiTabContainer
::GetPageCount() const
1478 return m_pages
.GetCount();
1481 void wxAuiTabContainer
::AddButton(int id
,
1483 const wxBitmap
& normal_bitmap
,
1484 const wxBitmap
& disabled_bitmap
)
1486 wxAuiTabContainerButton button
;
1488 button
.bitmap
= normal_bitmap
;
1489 button
.dis_bitmap
= disabled_bitmap
;
1490 button
.location
= location
;
1491 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1493 m_buttons
.Add(button
);
1496 void wxAuiTabContainer
::RemoveButton(int id
)
1498 size_t i
, button_count
= m_buttons
.GetCount();
1500 for (i
= 0; i
< button_count
; ++i
)
1502 if (m_buttons
.Item(i
).id
== id
)
1504 m_buttons
.RemoveAt(i
);
1512 size_t wxAuiTabContainer
::GetTabOffset() const
1514 return m_tab_offset
;
1517 void wxAuiTabContainer
::SetTabOffset(size_t offset
)
1519 m_tab_offset
= offset
;
1525 // Render() renders the tab catalog to the specified DC
1526 // It is a virtual function and can be overridden to
1527 // provide custom drawing capabilities
1528 void wxAuiTabContainer
::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1530 if (!raw_dc
|| !raw_dc
->IsOk())
1536 size_t page_count
= m_pages
.GetCount();
1537 size_t button_count
= m_buttons
.GetCount();
1539 // create off-screen bitmap
1540 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1541 dc
.SelectObject(bmp
);
1546 // find out if size of tabs is larger than can be
1547 // afforded on screen
1548 int total_width
= 0;
1549 int visible_width
= 0;
1550 for (i
= 0; i
< page_count
; ++i
)
1552 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1554 // determine if a close button is on this tab
1555 bool close_button
= false;
1556 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1557 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1559 close_button
= true;
1564 wxSize size
= m_art
->GetTabSize(dc
,
1570 wxAUI_BUTTON_STATE_NORMAL
:
1571 wxAUI_BUTTON_STATE_HIDDEN
,
1574 if (i
+1 < page_count
)
1575 total_width
+= x_extent
;
1577 total_width
+= size
.x
;
1579 if (i
>= m_tab_offset
)
1581 if (i
+1 < page_count
)
1582 visible_width
+= x_extent
;
1584 visible_width
+= size
.x
;
1588 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1590 // show left/right buttons
1591 for (i
= 0; i
< button_count
; ++i
)
1593 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1594 if (button
.id
== wxAUI_BUTTON_LEFT
||
1595 button
.id
== wxAUI_BUTTON_RIGHT
)
1597 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1603 // hide left/right buttons
1604 for (i
= 0; i
< button_count
; ++i
)
1606 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1607 if (button
.id
== wxAUI_BUTTON_LEFT
||
1608 button
.id
== wxAUI_BUTTON_RIGHT
)
1610 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1615 // determine whether left button should be enabled
1616 for (i
= 0; i
< button_count
; ++i
)
1618 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1619 if (button
.id
== wxAUI_BUTTON_LEFT
)
1621 if (m_tab_offset
== 0)
1622 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1624 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1626 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1628 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1629 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1631 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1638 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1641 int left_buttons_width
= 0;
1642 int right_buttons_width
= 0;
1646 // draw the buttons on the right side
1647 offset
= m_rect
.x
+ m_rect
.width
;
1648 for (i
= 0; i
< button_count
; ++i
)
1650 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1652 if (button
.location
!= wxRIGHT
)
1654 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1657 wxRect button_rect
= m_rect
;
1658 button_rect
.SetY(1);
1659 button_rect
.SetWidth(offset
);
1661 m_art
->DrawButton(dc
,
1670 offset
-= button
.rect
.GetWidth();
1671 right_buttons_width
+= button
.rect
.GetWidth();
1678 // draw the buttons on the left side
1680 for (i
= 0; i
< button_count
; ++i
)
1682 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1684 if (button
.location
!= wxLEFT
)
1686 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1689 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1691 m_art
->DrawButton(dc
,
1700 offset
+= button
.rect
.GetWidth();
1701 left_buttons_width
+= button
.rect
.GetWidth();
1704 offset
= left_buttons_width
;
1707 offset
+= m_art
->GetIndentSize();
1710 // prepare the tab-close-button array
1711 // make sure tab button entries which aren't used are marked as hidden
1712 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1713 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1715 // make sure there are enough tab button entries to accommodate all tabs
1716 while (m_tab_close_buttons
.GetCount() < page_count
)
1718 wxAuiTabContainerButton tempbtn
;
1719 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1720 tempbtn
.location
= wxCENTER
;
1721 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1722 m_tab_close_buttons
.Add(tempbtn
);
1726 // buttons before the tab offset must be set to hidden
1727 for (i
= 0; i
< m_tab_offset
; ++i
)
1729 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1735 size_t active
= 999;
1736 int active_offset
= 0;
1740 wxRect rect
= m_rect
;
1742 rect
.height
= m_rect
.height
;
1744 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1746 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1747 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1749 // determine if a close button is on this tab
1750 bool close_button
= false;
1751 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1752 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1754 close_button
= true;
1755 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1757 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1758 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1759 tab_button
.location
= wxCENTER
;
1764 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1768 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1770 if (rect
.width
<= 0)
1779 tab_button
.cur_state
,
1787 active_offset
= offset
;
1795 // make sure to deactivate buttons which are off the screen to the right
1796 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1798 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1802 // draw the active tab again so it stands in the foreground
1803 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1805 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1807 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1809 // determine if a close button is on this tab
1810 bool close_button
= false;
1811 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1812 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1814 close_button
= true;
1817 rect
.x
= active_offset
;
1824 tab_button
.cur_state
,
1831 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1832 m_rect
.GetWidth(), m_rect
.GetHeight(),
1837 // TabHitTest() tests if a tab was hit, passing the window pointer
1838 // back if that condition was fulfilled. The function returns
1839 // true if a tab was hit, otherwise false
1840 bool wxAuiTabContainer
::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1842 if (!m_rect
.Contains(x
,y
))
1845 wxAuiTabContainerButton
* btn
= NULL
;
1846 if (ButtonHitTest(x
, y
, &btn
))
1848 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1852 size_t i
, page_count
= m_pages
.GetCount();
1854 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1856 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1857 if (page
.rect
.Contains(x
,y
))
1868 // ButtonHitTest() tests if a button was hit. The function returns
1869 // true if a button was hit, otherwise false
1870 bool wxAuiTabContainer
::ButtonHitTest(int x
, int y
,
1871 wxAuiTabContainerButton
** hit
) const
1873 if (!m_rect
.Contains(x
,y
))
1876 size_t i
, button_count
;
1879 button_count
= m_buttons
.GetCount();
1880 for (i
= 0; i
< button_count
; ++i
)
1882 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1883 if (button
.rect
.Contains(x
,y
) &&
1884 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1885 wxAUI_BUTTON_STATE_DISABLED
)))
1893 button_count
= m_tab_close_buttons
.GetCount();
1894 for (i
= 0; i
< button_count
; ++i
)
1896 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1897 if (button
.rect
.Contains(x
,y
) &&
1898 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1899 wxAUI_BUTTON_STATE_DISABLED
)))
1912 // the utility function ShowWnd() is the same as show,
1913 // except it handles wxAuiMDIChildFrame windows as well,
1914 // as the Show() method on this class is "unplugged"
1915 static void ShowWnd(wxWindow
* wnd
, bool show
)
1917 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1919 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1929 // DoShowHide() this function shows the active window, then
1930 // hides all of the other windows (in that order)
1931 void wxAuiTabContainer
::DoShowHide()
1933 wxAuiNotebookPageArray
& pages
= GetPages();
1934 size_t i
, page_count
= pages
.GetCount();
1936 // show new active page first
1937 for (i
= 0; i
< page_count
; ++i
)
1939 wxAuiNotebookPage
& page
= pages
.Item(i
);
1942 ShowWnd(page
.window
, true);
1947 // hide all other pages
1948 for (i
= 0; i
< page_count
; ++i
)
1950 wxAuiNotebookPage
& page
= pages
.Item(i
);
1951 ShowWnd(page
.window
, page
.active
);
1960 // -- wxAuiTabCtrl class implementation --
1964 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1965 EVT_PAINT(wxAuiTabCtrl
::OnPaint
)
1966 EVT_ERASE_BACKGROUND(wxAuiTabCtrl
::OnEraseBackground
)
1967 EVT_SIZE(wxAuiTabCtrl
::OnSize
)
1968 EVT_LEFT_DOWN(wxAuiTabCtrl
::OnLeftDown
)
1969 EVT_LEFT_UP(wxAuiTabCtrl
::OnLeftUp
)
1970 EVT_MOTION(wxAuiTabCtrl
::OnMotion
)
1971 EVT_LEAVE_WINDOW(wxAuiTabCtrl
::OnLeaveWindow
)
1972 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl
::OnButton
)
1976 wxAuiTabCtrl
::wxAuiTabCtrl(wxWindow
* parent
,
1980 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1982 m_click_pt
= wxDefaultPosition
;
1983 m_is_dragging
= false;
1984 m_hover_button
= NULL
;
1985 m_pressed_button
= NULL
;
1988 wxAuiTabCtrl
::~wxAuiTabCtrl()
1992 void wxAuiTabCtrl
::OnPaint(wxPaintEvent
&)
1996 dc
.SetFont(GetFont());
1998 if (GetPageCount() > 0)
2002 void wxAuiTabCtrl
::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2006 void wxAuiTabCtrl
::OnSize(wxSizeEvent
& evt
)
2008 wxSize s
= evt
.GetSize();
2009 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2013 void wxAuiTabCtrl
::OnLeftDown(wxMouseEvent
& evt
)
2016 m_click_pt
= wxDefaultPosition
;
2017 m_is_dragging
= false;
2019 m_pressed_button
= NULL
;
2023 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2025 int new_selection
= GetIdxFromWindow(wnd
);
2027 if (new_selection
!= GetActivePage())
2029 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2030 e
.SetSelection(new_selection
);
2031 e
.SetOldSelection(GetActivePage());
2032 e
.SetEventObject(this);
2033 GetEventHandler()->ProcessEvent(e
);
2036 m_click_pt
.x
= evt
.m_x
;
2037 m_click_pt
.y
= evt
.m_y
;
2043 m_pressed_button
= m_hover_button
;
2044 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2050 void wxAuiTabCtrl
::OnLeftUp(wxMouseEvent
& evt
)
2052 if (GetCapture() == this)
2057 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2058 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2059 evt
.SetOldSelection(evt
.GetSelection());
2060 evt
.SetEventObject(this);
2061 GetEventHandler()->ProcessEvent(evt
);
2065 if (m_pressed_button
)
2067 // make sure we're still clicking the button
2068 wxAuiTabContainerButton
* button
= NULL
;
2069 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2072 if (button
!= m_pressed_button
)
2074 m_pressed_button
= NULL
;
2081 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2083 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2084 evt
.SetInt(m_pressed_button
->id
);
2085 evt
.SetEventObject(this);
2086 GetEventHandler()->ProcessEvent(evt
);
2089 m_pressed_button
= NULL
;
2092 m_click_pt
= wxDefaultPosition
;
2093 m_is_dragging
= false;
2097 void wxAuiTabCtrl
::OnMotion(wxMouseEvent
& evt
)
2099 wxPoint pos
= evt
.GetPosition();
2101 // check if the mouse is hovering above a button
2102 wxAuiTabContainerButton
* button
;
2103 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2105 if (m_hover_button
&& button
!= m_hover_button
)
2107 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2108 m_hover_button
= NULL
;
2113 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2115 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2118 m_hover_button
= button
;
2126 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2127 m_hover_button
= NULL
;
2134 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2139 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2140 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2141 evt
.SetOldSelection(evt
.GetSelection());
2142 evt
.SetEventObject(this);
2143 GetEventHandler()->ProcessEvent(evt
);
2148 int drag_x_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_X
);
2149 int drag_y_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_Y
);
2151 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2152 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2154 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2155 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2156 evt
.SetOldSelection(evt
.GetSelection());
2157 evt
.SetEventObject(this);
2158 GetEventHandler()->ProcessEvent(evt
);
2160 m_is_dragging
= true;
2164 void wxAuiTabCtrl
::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2168 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2169 m_hover_button
= NULL
;
2175 void wxAuiTabCtrl
::OnButton(wxAuiNotebookEvent
& event
)
2177 int button
= event
.GetInt();
2179 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2181 if (button
== wxAUI_BUTTON_LEFT
)
2183 if (GetTabOffset() > 0)
2185 SetTabOffset(GetTabOffset()-1);
2192 SetTabOffset(GetTabOffset()+1);
2197 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2201 size_t i
, page_count
= m_pages
.GetCount();
2202 for (i
= 0; i
< page_count
; ++i
)
2204 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2205 as
.Add(page
.caption
);
2208 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2212 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2213 e
.SetSelection(idx
);
2214 e
.SetOldSelection(GetActivePage());
2215 e
.SetEventObject(this);
2216 GetEventHandler()->ProcessEvent(e
);
2225 // wxTabFrame is an interesting case. It's important that all child pages
2226 // of the multi-notebook control are all actually children of that control
2227 // (and not grandchildren). wxTabFrame facilitates this. There is one
2228 // instance of wxTabFrame for each tab control inside the multi-notebook.
2229 // It's important to know that wxTabFrame is not a real window, but it merely
2230 // used to capture the dimensions/positioning of the internal tab control and
2231 // it's managed page windows
2233 class wxTabFrame
: public wxWindow
2240 m_rect
= wxRect(0,0,200,200);
2241 m_tab_ctrl_height
= 20;
2244 void SetTabCtrlHeight(int h
)
2246 m_tab_ctrl_height
= h
;
2249 void DoSetSize(int x
, int y
,
2250 int width
, int height
,
2251 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2253 m_rect
= wxRect(x
, y
, width
, height
);
2257 void DoGetClientSize(int* x
, int* y
) const
2263 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2270 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2271 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2272 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2276 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2277 size_t i
, page_count
= pages
.GetCount();
2279 for (i
= 0; i
< page_count
; ++i
)
2281 wxAuiNotebookPage
& page
= pages
.Item(i
);
2282 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2283 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2285 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2287 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2288 wnd
->ApplyMDIChildFrameRect();
2293 void DoGetSize(int* x
, int* y
) const
2296 *x
= m_rect
.GetWidth();
2298 *y
= m_rect
.GetHeight();
2310 wxAuiTabCtrl
* m_tabs
;
2311 int m_tab_ctrl_height
;
2318 // -- wxAuiNotebook class implementation --
2320 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2321 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2322 EVT_SIZE(wxAuiNotebook
::OnSize
)
2323 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2324 EVT_CHILD_FOCUS(wxAuiNotebook
::OnChildFocus
)
2325 EVT_COMMAND_RANGE(10000, 10100,
2326 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2327 wxAuiNotebook
::OnTabClicked
)
2328 EVT_COMMAND_RANGE(10000, 10100,
2329 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2330 wxAuiNotebook
::OnTabBeginDrag
)
2331 EVT_COMMAND_RANGE(10000, 10100,
2332 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2333 wxAuiNotebook
::OnTabEndDrag
)
2334 EVT_COMMAND_RANGE(10000, 10100,
2335 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2336 wxAuiNotebook
::OnTabDragMotion
)
2337 EVT_COMMAND_RANGE(10000, 10100,
2338 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2339 wxAuiNotebook
::OnTabButton
)
2342 wxAuiNotebook
::wxAuiNotebook()
2345 m_tab_id_counter
= 10000;
2347 m_tab_ctrl_height
= 20;
2348 m_requested_bmp_size
= wxDefaultSize
;
2349 m_requested_tabctrl_height
= -1;
2352 wxAuiNotebook
::wxAuiNotebook(wxWindow
*parent
,
2356 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2359 m_requested_bmp_size
= wxDefaultSize
;
2360 m_requested_tabctrl_height
= -1;
2361 InitNotebook(style
);
2364 bool wxAuiNotebook
::Create(wxWindow
* parent
,
2370 if (!wxControl
::Create(parent
, id
, pos
, size
, style
))
2373 InitNotebook(style
);
2378 // InitNotebook() contains common initialization
2379 // code called by all constructors
2380 void wxAuiNotebook
::InitNotebook(long style
)
2383 m_tab_id_counter
= 10000;
2385 m_flags
= (unsigned int)style
;
2386 m_tab_ctrl_height
= 20;
2388 m_normal_font
= *wxNORMAL_FONT
;
2389 m_selected_font
= *wxNORMAL_FONT
;
2390 m_selected_font
.SetWeight(wxBOLD
);
2392 SetArtProvider(new wxAuiDefaultTabArt
);
2394 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2395 m_dummy_wnd
->SetSize(200, 200);
2396 m_dummy_wnd
->Show(false);
2398 m_mgr
.SetManagedWindow(this);
2399 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
| (1 << 28) /*wxAUI_MGR_NO_DOCK_SIZE_LIMIT*/);
2401 m_mgr
.AddPane(m_dummy_wnd
,
2402 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2407 wxAuiNotebook
::~wxAuiNotebook()
2412 void wxAuiNotebook
::SetArtProvider(wxAuiTabArt
* art
)
2414 m_tabs
.SetArtProvider(art
);
2416 UpdateTabCtrlHeight();
2419 // SetTabCtrlHeight() is the highest-level override of the
2420 // tab height. A call to this function effectively enforces a
2421 // specified tab ctrl height, overriding all other considerations,
2422 // such as text or bitmap height. It overrides any call to
2423 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2424 // any previous call and returns to the default behavior
2426 void wxAuiNotebook
::SetTabCtrlHeight(int height
)
2428 m_requested_tabctrl_height
= height
;
2430 // if window is already initialized, recalculate the tab height
2433 UpdateTabCtrlHeight();
2438 // SetUniformBitmapSize() ensures that all tabs will have
2439 // the same height, even if some tabs don't have bitmaps
2440 // Passing wxDefaultSize to this function will instruct
2441 // the control to use dynamic tab height-- so when a tab
2442 // with a large bitmap is added, the tab ctrl's height will
2443 // automatically increase to accommodate the bitmap
2445 void wxAuiNotebook
::SetUniformBitmapSize(const wxSize
& size
)
2447 m_requested_bmp_size
= size
;
2449 // if window is already initialized, recalculate the tab height
2452 UpdateTabCtrlHeight();
2456 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2457 // to be used interally
2458 void wxAuiNotebook
::UpdateTabCtrlHeight()
2460 // get the tab ctrl height we will use
2461 int height
= CalculateTabCtrlHeight();
2463 // if the tab control height needs to change, update
2464 // all of our tab controls with the new height
2465 if (m_tab_ctrl_height
!= height
)
2467 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2469 m_tab_ctrl_height
= height
;
2471 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2472 size_t i
, pane_count
= all_panes
.GetCount();
2473 for (i
= 0; i
< pane_count
; ++i
)
2475 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2476 if (pane
.name
== wxT("dummy"))
2478 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2479 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2480 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2481 tabctrl
->SetArtProvider(art
->Clone());
2482 tab_frame
->DoSizing();
2487 void wxAuiNotebook
::UpdateHintWindowSize()
2489 wxSize size
= CalculateNewSplitSize();
2491 // the placeholder hint window should be set to this size
2492 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2496 info
.BestSize(size
);
2497 m_dummy_wnd
->SetSize(size
);
2502 // calculates the size of the new split
2503 wxSize wxAuiNotebook
::CalculateNewSplitSize()
2505 // count number of tab controls
2506 int tab_ctrl_count
= 0;
2507 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2508 size_t i
, pane_count
= all_panes
.GetCount();
2509 for (i
= 0; i
< pane_count
; ++i
)
2511 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2512 if (pane
.name
== wxT("dummy"))
2517 wxSize new_split_size
;
2519 // if there is only one tab control, the first split
2520 // should happen around the middle
2521 if (tab_ctrl_count
< 2)
2523 new_split_size
= GetClientSize();
2524 new_split_size
.x
/= 2;
2525 new_split_size
.y
/= 2;
2529 // this is in place of a more complicated calculation
2530 // that needs to be implemented
2531 new_split_size
= wxSize(180,180);
2534 return new_split_size
;
2537 int wxAuiNotebook
::CalculateTabCtrlHeight()
2539 // if a fixed tab ctrl height is specified,
2540 // just return that instead of calculating a
2542 if (m_requested_tabctrl_height
!= -1)
2543 return m_requested_tabctrl_height
;
2545 // find out new best tab height
2546 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2548 return art
->GetBestTabCtrlSize(this,
2550 m_requested_bmp_size
);
2554 wxAuiTabArt
* wxAuiNotebook
::GetArtProvider() const
2556 return m_tabs
.GetArtProvider();
2559 void wxAuiNotebook
::SetWindowStyleFlag(long style
)
2561 wxControl
::SetWindowStyleFlag(style
);
2563 m_flags
= (unsigned int)style
;
2565 // if the control is already initialized
2566 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2568 // let all of the tab children know about the new style
2570 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2571 size_t i
, pane_count
= all_panes
.GetCount();
2572 for (i
= 0; i
< pane_count
; ++i
)
2574 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2575 if (pane
.name
== wxT("dummy"))
2577 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2578 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2579 tabctrl
->SetFlags(m_flags
);
2580 tabframe
->DoSizing();
2588 bool wxAuiNotebook
::AddPage(wxWindow
* page
,
2589 const wxString
& caption
,
2591 const wxBitmap
& bitmap
)
2593 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2596 bool wxAuiNotebook
::InsertPage(size_t page_idx
,
2598 const wxString
& caption
,
2600 const wxBitmap
& bitmap
)
2602 wxAuiNotebookPage info
;
2604 info
.caption
= caption
;
2605 info
.bitmap
= bitmap
;
2606 info
.active
= false;
2608 // if there are currently no tabs, the first added
2609 // tab must be active
2610 if (m_tabs
.GetPageCount() == 0)
2613 m_tabs
.InsertPage(page
, info
, page_idx
);
2615 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2616 if (page_idx
>= active_tabctrl
->GetPageCount())
2617 active_tabctrl
->AddPage(page
, info
);
2619 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2621 UpdateTabCtrlHeight();
2623 active_tabctrl
->DoShowHide();
2627 int idx
= m_tabs
.GetIdxFromWindow(page
);
2628 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2637 // DeletePage() removes a tab from the multi-notebook,
2638 // and destroys the window as well
2639 bool wxAuiNotebook
::DeletePage(size_t page_idx
)
2641 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2643 if (!RemovePage(page_idx
))
2646 // actually destroy the window now
2647 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2649 // delete the child frame with pending delete, as is
2650 // customary with frame windows
2651 if (!wxPendingDelete
.Member(wnd
))
2652 wxPendingDelete
.Append(wnd
);
2664 // RemovePage() removes a tab from the multi-notebook,
2665 // but does not destroy the window
2666 bool wxAuiNotebook
::RemovePage(size_t page_idx
)
2668 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2669 wxWindow
* new_active
= NULL
;
2671 // find out which onscreen tab ctrl owns this tab
2674 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2677 // find a new page and set it as active
2678 int new_idx
= ctrl_idx
+1;
2679 if (new_idx
>= (int)ctrl
->GetPageCount())
2680 new_idx
= ctrl_idx
-1;
2682 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2684 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2688 // set the active page to the first page that
2689 // isn't the one being deleted
2690 size_t i
, page_count
= m_tabs
.GetPageCount();
2691 for (i
= 0; i
< page_count
; ++i
)
2693 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2696 new_active
= m_tabs
.GetWindowFromIdx(i
);
2702 // remove the tab from main catalog
2703 if (!m_tabs
.RemovePage(wnd
))
2706 // remove the tab from the onscreen tab ctrl
2707 ctrl
->RemovePage(wnd
);
2710 RemoveEmptyTabFrames();
2712 // set new active pane
2716 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2722 // GetPageIndex() returns the index of the page, or -1 if the
2723 // page could not be located in the notebook
2724 int wxAuiNotebook
::GetPageIndex(wxWindow
* page_wnd
) const
2726 return m_tabs
.GetIdxFromWindow(page_wnd
);
2731 // SetPageText() changes the tab caption of the specified page
2732 bool wxAuiNotebook
::SetPageText(size_t page_idx
, const wxString
& text
)
2734 if (page_idx
>= m_tabs
.GetPageCount())
2737 // update our own tab catalog
2738 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2739 page_info
.caption
= text
;
2741 // update what's on screen
2744 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2746 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2747 info
.caption
= text
;
2756 bool wxAuiNotebook
::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2758 if (page_idx
>= m_tabs
.GetPageCount())
2761 // update our own tab catalog
2762 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2763 page_info
.bitmap
= bitmap
;
2765 // tab height might have changed
2766 UpdateTabCtrlHeight();
2768 // update what's on screen
2771 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2773 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2774 info
.bitmap
= bitmap
;
2783 // GetSelection() returns the index of the currently active page
2784 int wxAuiNotebook
::GetSelection() const
2789 // SetSelection() sets the currently active page
2790 size_t wxAuiNotebook
::SetSelection(size_t new_page
)
2792 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2796 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2797 evt
.SetSelection(new_page
);
2798 evt
.SetOldSelection(m_curpage
);
2799 evt
.SetEventObject(this);
2800 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2802 int old_curpage
= m_curpage
;
2803 m_curpage
= new_page
;
2805 // program allows the page change
2806 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2807 (void)GetEventHandler()->ProcessEvent(evt
);
2812 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2814 m_tabs
.SetActivePage(wnd
);
2816 ctrl
->SetActivePage(ctrl_idx
);
2823 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2824 size_t i
, pane_count
= all_panes
.GetCount();
2825 for (i
= 0; i
< pane_count
; ++i
)
2827 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2828 if (pane
.name
== wxT("dummy"))
2830 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2831 if (tabctrl
!= ctrl
)
2832 tabctrl
->SetSelectedFont(m_normal_font
);
2834 tabctrl
->SetSelectedFont(m_selected_font
);
2847 // GetPageCount() returns the total number of
2848 // pages managed by the multi-notebook
2849 size_t wxAuiNotebook
::GetPageCount() const
2851 return m_tabs
.GetPageCount();
2854 // GetPage() returns the wxWindow pointer of the
2856 wxWindow
* wxAuiNotebook
::GetPage(size_t page_idx
) const
2858 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2860 return m_tabs
.GetWindowFromIdx(page_idx
);
2863 // DoSizing() performs all sizing operations in each tab control
2864 void wxAuiNotebook
::DoSizing()
2866 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2867 size_t i
, pane_count
= all_panes
.GetCount();
2868 for (i
= 0; i
< pane_count
; ++i
)
2870 if (all_panes
.Item(i
).name
== wxT("dummy"))
2873 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2874 tabframe
->DoSizing();
2878 // GetActiveTabCtrl() returns the active tab control. It is
2879 // called to determine which control gets new windows being added
2880 wxAuiTabCtrl
* wxAuiNotebook
::GetActiveTabCtrl()
2882 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2887 // find the tab ctrl with the current page
2888 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2895 // no current page, just find the first tab ctrl
2896 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2897 size_t i
, pane_count
= all_panes
.GetCount();
2898 for (i
= 0; i
< pane_count
; ++i
)
2900 if (all_panes
.Item(i
).name
== wxT("dummy"))
2903 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2904 return tabframe
->m_tabs
;
2907 // If there is no tabframe at all, create one
2908 wxTabFrame
* tabframe
= new wxTabFrame
;
2909 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2910 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2915 tabframe
->m_tabs
->SetFlags(m_flags
);
2916 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2917 m_mgr
.AddPane(tabframe
,
2918 wxAuiPaneInfo().Center().CaptionVisible(false));
2922 return tabframe
->m_tabs
;
2925 // FindTab() finds the tab control that currently contains the window as well
2926 // as the index of the window in the tab control. It returns true if the
2927 // window was found, otherwise false.
2928 bool wxAuiNotebook
::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2930 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2931 size_t i
, pane_count
= all_panes
.GetCount();
2932 for (i
= 0; i
< pane_count
; ++i
)
2934 if (all_panes
.Item(i
).name
== wxT("dummy"))
2937 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2939 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2942 *ctrl
= tabframe
->m_tabs
;
2952 void wxAuiNotebook
::OnEraseBackground(wxEraseEvent
&)
2956 void wxAuiNotebook
::OnSize(wxSizeEvent
& evt
)
2958 UpdateHintWindowSize();
2963 void wxAuiNotebook
::OnTabClicked(wxCommandEvent
& command_evt
)
2965 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2967 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2968 wxASSERT(ctrl
!= NULL
);
2970 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2971 wxASSERT(wnd
!= NULL
);
2973 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2974 wxASSERT(idx
!= -1);
2979 void wxAuiNotebook
::OnTabBeginDrag(wxCommandEvent
&)
2984 void wxAuiNotebook
::OnTabDragMotion(wxCommandEvent
& evt
)
2986 wxPoint screen_pt
= ::wxGetMousePosition();
2987 wxPoint client_pt
= ScreenToClient(screen_pt
);
2990 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2991 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2993 if (dest_tabs
== src_tabs
)
2997 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3000 // always hide the hint for inner-tabctrl drag
3003 // if tab moving is not allowed, leave
3004 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3009 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3010 wxWindow
* dest_location_tab
;
3012 // this is an inner-tab drag/reposition
3013 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3015 int src_idx
= evt
.GetSelection();
3016 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3018 // prevent jumpy drag
3019 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3020 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3021 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3023 m_last_drag_x
= pt
.x
;
3028 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3029 dest_tabs
->MovePage(src_tab
, dest_idx
);
3030 dest_tabs
->SetActivePage((size_t)dest_idx
);
3031 dest_tabs
->DoShowHide();
3032 dest_tabs
->Refresh();
3033 m_last_drag_x
= pt
.x
;
3041 // if external drag is allowed, check if the tab is being dragged
3042 // over a different wxAuiNotebook control
3043 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3045 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3047 // if we aren't over any window, stop here
3051 // make sure we are not over the hint window
3052 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3056 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3058 tab_ctrl
= tab_ctrl
->GetParent();
3063 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3067 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3068 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3069 m_mgr
.ShowHint(hint_rect
);
3078 // we are either over a hint window, or not over a tab
3079 // window, and there is no where to drag to, so exit
3086 // if there are less than two panes, split can't happen, so leave
3087 if (m_tabs
.GetPageCount() < 2)
3090 // if tab moving is not allowed, leave
3091 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3097 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3103 wxRect hint_rect
= dest_tabs
->GetRect();
3104 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3105 m_mgr
.ShowHint(hint_rect
);
3109 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3115 void wxAuiNotebook
::OnTabEndDrag(wxCommandEvent
& command_evt
)
3117 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3122 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3123 wxAuiTabCtrl
* dest_tabs
= NULL
;
3126 // set cursor back to an arrow
3127 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3130 // get the mouse position, which will be used to determine the drop point
3131 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3132 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3136 // check for an external move
3137 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3139 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3143 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3145 tab_ctrl
= tab_ctrl
->GetParent();
3150 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3154 // find out from the destination control
3155 // if it's ok to drop this tab here
3156 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3157 e
.SetSelection(evt
.GetSelection());
3158 e
.SetOldSelection(evt
.GetSelection());
3159 e
.SetEventObject(this);
3160 e
.SetDragSource(this);
3161 e
.Veto(); // dropping must be explicitly approved by control owner
3163 nb
->GetEventHandler()->ProcessEvent(e
);
3167 // no answer or negative answer
3173 int src_idx
= evt
.GetSelection();
3174 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3176 // get main index of the page
3177 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3179 // make a copy of the page info
3180 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3182 // remove the page from the source notebook
3183 RemovePage(main_idx
);
3185 // reparent the page
3186 src_page
->Reparent(nb
);
3189 // found out the insert idx
3190 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3191 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3193 wxWindow
* target
= NULL
;
3194 int insert_idx
= -1;
3195 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3198 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3202 // add the page to the new notebook
3203 if (insert_idx
== -1)
3204 insert_idx
= dest_tabs
->GetPageCount();
3205 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3206 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3209 dest_tabs
->DoShowHide();
3210 dest_tabs
->Refresh();
3212 // set the selection in the destination tab control
3213 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3223 // only perform a tab split if it's allowed
3224 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3226 // If the pointer is in an existing tab frame, do a tab insert
3227 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3228 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3229 int insert_idx
= -1;
3232 dest_tabs
= tab_frame
->m_tabs
;
3234 if (dest_tabs
== src_tabs
)
3238 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3239 wxWindow
* target
= NULL
;
3240 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3243 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3249 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3254 // there is no suitable drop location here, exit out
3258 // If there is no tabframe at all, create one
3259 wxTabFrame
* new_tabs
= new wxTabFrame
;
3260 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3261 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3262 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3267 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3268 new_tabs
->m_tabs
->SetFlags(m_flags
);
3270 m_mgr
.AddPane(new_tabs
,
3271 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3274 dest_tabs
= new_tabs
->m_tabs
;
3279 // remove the page from the source tabs
3280 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3281 page_info
.active
= false;
3282 src_tabs
->RemovePage(page_info
.window
);
3283 if (src_tabs
->GetPageCount() > 0)
3285 src_tabs
->SetActivePage((size_t)0);
3286 src_tabs
->DoShowHide();
3287 src_tabs
->Refresh();
3292 // add the page to the destination tabs
3293 if (insert_idx
== -1)
3294 insert_idx
= dest_tabs
->GetPageCount();
3295 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3297 if (src_tabs
->GetPageCount() == 0)
3299 RemoveEmptyTabFrames();
3303 dest_tabs
->DoShowHide();
3304 dest_tabs
->Refresh();
3306 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3308 UpdateHintWindowSize();
3314 wxAuiTabCtrl
* wxAuiNotebook
::GetTabCtrlFromPoint(const wxPoint
& pt
)
3316 // if we've just removed the last tab from the source
3317 // tab set, the remove the tab control completely
3318 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3319 size_t i
, pane_count
= all_panes
.GetCount();
3320 for (i
= 0; i
< pane_count
; ++i
)
3322 if (all_panes
.Item(i
).name
== wxT("dummy"))
3325 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3326 if (tabframe
->m_tab_rect
.Contains(pt
))
3327 return tabframe
->m_tabs
;
3333 wxWindow
* wxAuiNotebook
::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3335 // if we've just removed the last tab from the source
3336 // tab set, the remove the tab control completely
3337 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3338 size_t i
, pane_count
= all_panes
.GetCount();
3339 for (i
= 0; i
< pane_count
; ++i
)
3341 if (all_panes
.Item(i
).name
== wxT("dummy"))
3344 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3345 if (tabframe
->m_tabs
== tab_ctrl
)
3354 void wxAuiNotebook
::RemoveEmptyTabFrames()
3356 // if we've just removed the last tab from the source
3357 // tab set, the remove the tab control completely
3358 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3359 size_t i
, pane_count
= all_panes
.GetCount();
3360 for (i
= 0; i
< pane_count
; ++i
)
3362 if (all_panes
.Item(i
).name
== wxT("dummy"))
3365 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3366 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3368 m_mgr
.DetachPane(tab_frame
);
3370 // use pending delete because sometimes during
3371 // window closing, refreshs are pending
3372 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3373 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3374 //tab_frame->m_tabs->Destroy();
3381 // check to see if there is still a center pane;
3382 // if there isn't, make a frame the center pane
3383 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3384 pane_count
= panes
.GetCount();
3385 wxWindow
* first_good
= NULL
;
3386 bool center_found
= false;
3387 for (i
= 0; i
< pane_count
; ++i
)
3389 if (panes
.Item(i
).name
== wxT("dummy"))
3391 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3392 center_found
= true;
3394 first_good
= panes
.Item(i
).window
;
3397 if (!center_found
&& first_good
)
3399 m_mgr
.GetPane(first_good
).Centre();
3405 void wxAuiNotebook
::OnChildFocus(wxChildFocusEvent
& evt
)
3407 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3408 if (idx
!= -1 && idx
!= m_curpage
)
3415 void wxAuiNotebook
::OnTabButton(wxCommandEvent
& command_evt
)
3417 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3418 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3420 int button_id
= evt
.GetInt();
3422 if (button_id
== wxAUI_BUTTON_CLOSE
)
3424 int selection
= tabs
->GetActivePage();
3426 if (selection
!= -1)
3428 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3431 // ask owner if it's ok to close the tab
3432 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3433 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3434 e
.SetOldSelection(evt
.GetSelection());
3435 e
.SetEventObject(this);
3436 GetEventHandler()->ProcessEvent(e
);
3441 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3447 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3448 DeletePage(main_idx
);