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 // the base_colour is too pale to use as our base colour,
197 // so darken it a bit --
198 if ((255-base_colour
.Red()) +
199 (255-base_colour
.Green()) +
200 (255-base_colour
.Blue()) < 60)
202 base_colour
= wxAuiStepColour(base_colour
, 92);
205 m_base_colour
= base_colour
;
206 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
208 m_border_pen
= wxPen(border_colour
);
209 m_base_colour_pen
= wxPen(m_base_colour
);
210 m_base_colour_brush
= wxBrush(m_base_colour
);
212 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
213 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
215 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
216 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
218 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
219 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
221 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
222 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
227 wxAuiDefaultTabArt
::~wxAuiDefaultTabArt()
231 wxAuiTabArt
* wxAuiDefaultTabArt
::Clone()
233 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
236 void wxAuiDefaultTabArt
::SetFlags(unsigned int flags
)
241 void wxAuiDefaultTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
244 m_fixed_tab_width
= 100;
246 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
248 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
249 tot_width
-= m_active_close_bmp
.GetWidth();
250 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
251 tot_width
-= m_active_windowlist_bmp
.GetWidth();
255 m_fixed_tab_width
= tot_width
/(int)tab_count
;
259 if (m_fixed_tab_width
< 100)
260 m_fixed_tab_width
= 100;
262 if (m_fixed_tab_width
> tot_width
/2)
263 m_fixed_tab_width
= tot_width
/2;
265 if (m_fixed_tab_width
> 220)
266 m_fixed_tab_width
= 220;
268 m_tab_ctrl_height
= tab_ctrl_size
.y
;
272 void wxAuiDefaultTabArt
::DrawBackground(wxDC
& dc
,
273 wxWindow
* WXUNUSED(wnd
),
277 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
278 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
279 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
280 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
283 int y
= rect
.GetHeight();
284 int w
= rect
.GetWidth();
285 dc
.SetPen(m_border_pen
);
286 dc
.SetBrush(m_base_colour_brush
);
287 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
291 // DrawTab() draws an individual tab.
294 // in_rect - rectangle the tab should be confined to
295 // caption - tab's caption
296 // active - whether or not the tab is active
297 // out_rect - actual output rectangle
298 // x_extent - the advance x; where the next tab should start
300 void wxAuiDefaultTabArt
::DrawTab(wxDC
& dc
,
302 const wxRect
& in_rect
,
303 const wxString
& caption_text
,
304 const wxBitmap
& bitmap
,
306 int close_button_state
,
307 wxRect
* out_tab_rect
,
308 wxRect
* out_button_rect
,
311 wxCoord normal_textx
, normal_texty
;
312 wxCoord selected_textx
, selected_texty
;
313 wxCoord textx
, texty
;
315 // if the caption is empty, measure some temporary text
316 wxString caption
= caption_text
;
317 if (caption_text
.empty())
320 dc
.SetFont(m_selected_font
);
321 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
323 dc
.SetFont(m_normal_font
);
324 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
326 // figure out the size of the tab
327 wxSize tab_size
= GetTabSize(dc
,
335 wxCoord tab_height
= m_tab_ctrl_height
- 3;
336 wxCoord tab_width
= tab_size
.x
;
337 wxCoord tab_x
= in_rect
.x
;
338 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
341 caption
= caption_text
;
344 // select pen, brush and font for the tab to be drawn
348 dc
.SetFont(m_selected_font
);
349 textx
= selected_textx
;
350 texty
= selected_texty
;
354 dc
.SetFont(m_normal_font
);
355 textx
= normal_textx
;
356 texty
= normal_texty
;
360 // create points that will make the tab outline
362 int clip_width
= tab_width
;
363 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
364 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
367 wxPoint clip_points[6];
368 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
369 clip_points[1] = wxPoint(tab_x, tab_y+2);
370 clip_points[2] = wxPoint(tab_x+2, tab_y);
371 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
372 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
373 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
375 // FIXME: these ports don't provide wxRegion ctor from array of points
376 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
377 // set the clipping region for the tab --
378 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
379 dc.SetClippingRegion(clipping_region);
380 #endif // !wxDFB && !wxCocoa
382 // since the above code above doesn't play well with WXDFB or WXCOCOA,
383 // we'll just use a rectangle for the clipping region for now --
384 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
387 wxPoint border_points
[6];
388 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
389 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
390 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
391 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
392 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
393 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
396 int drawn_tab_yoff
= border_points
[1].y
;
397 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
404 // draw base background color
405 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
406 dc
.SetPen(m_base_colour_pen
);
407 dc
.SetBrush(m_base_colour_brush
);
408 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
410 // this white helps fill out the gradient at the top of the tab
411 dc
.SetPen(*wxWHITE_PEN
);
412 dc
.SetBrush(*wxWHITE_BRUSH
);
413 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
415 // these two points help the rounded corners appear more antialiased
416 dc
.SetPen(m_base_colour_pen
);
417 dc
.DrawPoint(r
.x
+2, r
.y
+1);
418 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
420 // set rectangle down a bit for gradient drawing
421 r
.SetHeight(r
.GetHeight()/2);
427 // draw gradient background
428 wxColor top_color
= *wxWHITE
;
429 wxColor bottom_color
= m_base_colour
;
430 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
436 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
438 // start the gradent up a bit and leave the inside border inset
439 // by a pixel for a 3D look. Only the top half of the inactive
440 // tab will have a slight gradient
447 // -- draw top gradient fill for glossy look
448 wxColor top_color
= m_base_colour
;
449 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
450 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
455 // -- draw bottom fill for glossy look
456 top_color
= m_base_colour
;
457 bottom_color
= m_base_colour
;
458 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
462 dc
.SetPen(m_border_pen
);
463 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
464 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
466 // there are two horizontal grey lines at the bottom of the tab control,
467 // this gets rid of the top one of those lines in the tab control
470 wxColor start_color
= m_base_colour
;
471 dc
.SetPen(m_base_colour_pen
);
472 dc
.DrawLine(border_points
[0].x
+1,
479 int text_offset
= tab_x
+ 8;
480 int close_button_width
= 0;
481 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
483 close_button_width
= m_active_close_bmp
.GetWidth();
489 int bitmap_offset
= tab_x
+ 8;
492 dc
.DrawBitmap(bitmap
,
494 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2),
497 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
498 text_offset
+= 3; // bitmap padding
502 text_offset
= tab_x
+ 8;
506 wxString draw_text
= wxAuiChopText(dc
,
508 tab_width
- (text_offset
-tab_x
) - close_button_width
);
511 dc
.DrawText(draw_text
,
513 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
518 // draw close button if necessary
519 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
521 wxBitmap bmp
= m_disabled_close_bmp
;
523 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
524 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
526 bmp
= m_active_close_bmp
;
529 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
530 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
533 IndentPressedBitmap(&rect
, close_button_state
);
534 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
536 *out_button_rect
= rect
;
539 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
541 dc
.DestroyClippingRegion();
544 int wxAuiDefaultTabArt
::GetIndentSize()
549 wxSize wxAuiDefaultTabArt
::GetTabSize(wxDC
& dc
,
550 wxWindow
* WXUNUSED(wnd
),
551 const wxString
& caption
,
552 const wxBitmap
& bitmap
,
553 bool WXUNUSED(active
),
554 int close_button_state
,
557 wxCoord measured_textx
, measured_texty
, tmp
;
559 dc
.SetFont(m_measuring_font
);
560 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
562 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
564 // add padding around the text
565 wxCoord tab_width
= measured_textx
;
566 wxCoord tab_height
= measured_texty
;
568 // if the close button is showing, add space for it
569 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
570 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
572 // if there's a bitmap, add space for it
575 tab_width
+= bitmap
.GetWidth();
576 tab_width
+= 3; // right side bitmap padding
577 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
584 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
586 tab_width
= m_fixed_tab_width
;
589 *x_extent
= tab_width
;
591 return wxSize(tab_width
, tab_height
);
595 void wxAuiDefaultTabArt
::DrawButton(wxDC
& dc
,
596 wxWindow
* WXUNUSED(wnd
),
597 const wxRect
& in_rect
,
601 const wxBitmap
& bitmap_override
,
607 if (bitmap_override
.IsOk())
609 bmp
= bitmap_override
;
615 case wxAUI_BUTTON_CLOSE
:
616 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
617 bmp
= m_disabled_close_bmp
;
619 bmp
= m_active_close_bmp
;
621 case wxAUI_BUTTON_LEFT
:
622 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
623 bmp
= m_disabled_left_bmp
;
625 bmp
= m_active_left_bmp
;
627 case wxAUI_BUTTON_RIGHT
:
628 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
629 bmp
= m_disabled_right_bmp
;
631 bmp
= m_active_right_bmp
;
633 case wxAUI_BUTTON_WINDOWLIST
:
634 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
635 bmp
= m_disabled_windowlist_bmp
;
637 bmp
= m_active_windowlist_bmp
;
647 if (orientation
== wxLEFT
)
649 rect
.SetX(in_rect
.x
);
650 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
651 rect
.SetWidth(bmp
.GetWidth());
652 rect
.SetHeight(bmp
.GetHeight());
656 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
657 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
658 bmp
.GetWidth(), bmp
.GetHeight());
661 IndentPressedBitmap(&rect
, button_state
);
662 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
668 int wxAuiDefaultTabArt
::ShowWindowList(wxWindow
* wnd
,
669 const wxArrayString
& items
,
674 size_t i
, count
= items
.GetCount();
675 for (i
= 0; i
< count
; ++i
)
677 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
680 if (active_idx
!= -1)
682 menuPopup
.Check(1000+active_idx
, true);
685 // find out where to put the popup menu of window items
686 wxPoint pt
= ::wxGetMousePosition();
687 pt
= wnd
->ScreenToClient(pt
);
689 // find out the screen coordinate at the bottom of the tab ctrl
690 wxRect cli_rect
= wnd
->GetClientRect();
691 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
693 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
694 wnd
->PushEventHandler(cc
);
695 wnd
->PopupMenu(&menuPopup
, pt
);
696 int command
= cc
->GetCommandId();
697 wnd
->PopEventHandler(true);
705 int wxAuiDefaultTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
706 wxAuiNotebookPageArray
& pages
,
707 const wxSize
& required_bmp_size
)
710 dc
.SetFont(m_measuring_font
);
712 // sometimes a standard bitmap size needs to be enforced, especially
713 // if some tabs have bitmaps and others don't. This is important because
714 // it prevents the tab control from resizing when tabs are added.
715 wxBitmap measure_bmp
;
716 if (required_bmp_size
.IsFullySpecified())
718 measure_bmp
.Create(required_bmp_size
.x
,
719 required_bmp_size
.y
);
724 size_t i
, page_count
= pages
.GetCount();
725 for (i
= 0; i
< page_count
; ++i
)
727 wxAuiNotebookPage
& page
= pages
.Item(i
);
730 if (measure_bmp
.IsOk())
735 // we don't use the caption text because we don't
736 // want tab heights to be different in the case
737 // of a very short piece of text on one tab and a very
738 // tall piece of text on another tab
740 wxSize s
= GetTabSize(dc
,
745 wxAUI_BUTTON_STATE_HIDDEN
,
748 max_y
= wxMax(max_y
, s
.y
);
754 void wxAuiDefaultTabArt
::SetNormalFont(const wxFont
& font
)
756 m_normal_font
= font
;
759 void wxAuiDefaultTabArt
::SetSelectedFont(const wxFont
& font
)
761 m_selected_font
= font
;
764 void wxAuiDefaultTabArt
::SetMeasuringFont(const wxFont
& font
)
766 m_measuring_font
= font
;
770 // -- wxAuiSimpleTabArt class implementation --
772 wxAuiSimpleTabArt
::wxAuiSimpleTabArt()
774 m_normal_font
= *wxNORMAL_FONT
;
775 m_selected_font
= *wxNORMAL_FONT
;
776 m_selected_font
.SetWeight(wxBOLD
);
777 m_measuring_font
= m_selected_font
;
780 m_fixed_tab_width
= 100;
782 wxColour base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
784 wxColour background_colour
= base_colour
;
785 wxColour normaltab_colour
= base_colour
;
786 wxColour selectedtab_colour
= *wxWHITE
;
788 m_bkbrush
= wxBrush(background_colour
);
789 m_normal_bkbrush
= wxBrush(normaltab_colour
);
790 m_normal_bkpen
= wxPen(normaltab_colour
);
791 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
792 m_selected_bkpen
= wxPen(selectedtab_colour
);
794 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
795 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
797 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
798 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
800 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
801 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
803 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
804 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
808 wxAuiSimpleTabArt
::~wxAuiSimpleTabArt()
812 wxAuiTabArt
* wxAuiSimpleTabArt
::Clone()
814 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
818 void wxAuiSimpleTabArt
::SetFlags(unsigned int flags
)
823 void wxAuiSimpleTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
826 m_fixed_tab_width
= 100;
828 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
830 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
831 tot_width
-= m_active_close_bmp
.GetWidth();
832 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
833 tot_width
-= m_active_windowlist_bmp
.GetWidth();
837 m_fixed_tab_width
= tot_width
/(int)tab_count
;
841 if (m_fixed_tab_width
< 100)
842 m_fixed_tab_width
= 100;
844 if (m_fixed_tab_width
> tot_width
/2)
845 m_fixed_tab_width
= tot_width
/2;
847 if (m_fixed_tab_width
> 220)
848 m_fixed_tab_width
= 220;
851 void wxAuiSimpleTabArt
::DrawBackground(wxDC
& dc
,
852 wxWindow
* WXUNUSED(wnd
),
856 dc
.SetBrush(m_bkbrush
);
857 dc
.SetPen(*wxTRANSPARENT_PEN
);
858 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
861 dc
.SetPen(*wxGREY_PEN
);
862 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
866 // DrawTab() draws an individual tab.
869 // in_rect - rectangle the tab should be confined to
870 // caption - tab's caption
871 // active - whether or not the tab is active
872 // out_rect - actual output rectangle
873 // x_extent - the advance x; where the next tab should start
875 void wxAuiSimpleTabArt
::DrawTab(wxDC
& dc
,
877 const wxRect
& in_rect
,
878 const wxString
& caption_text
,
879 const wxBitmap
& bitmap
,
881 int close_button_state
,
882 wxRect
* out_tab_rect
,
883 wxRect
* out_button_rect
,
886 wxCoord normal_textx
, normal_texty
;
887 wxCoord selected_textx
, selected_texty
;
888 wxCoord textx
, texty
;
890 // if the caption is empty, measure some temporary text
891 wxString caption
= caption_text
;
892 if (caption_text
.empty())
895 dc
.SetFont(m_selected_font
);
896 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
898 dc
.SetFont(m_normal_font
);
899 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
901 // figure out the size of the tab
902 wxSize tab_size
= GetTabSize(dc
,
910 wxCoord tab_height
= tab_size
.y
;
911 wxCoord tab_width
= tab_size
.x
;
912 wxCoord tab_x
= in_rect
.x
;
913 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
915 caption
= caption_text
;
917 // select pen, brush and font for the tab to be drawn
921 dc
.SetPen(m_selected_bkpen
);
922 dc
.SetBrush(m_selected_bkbrush
);
923 dc
.SetFont(m_selected_font
);
924 textx
= selected_textx
;
925 texty
= selected_texty
;
929 dc
.SetPen(m_normal_bkpen
);
930 dc
.SetBrush(m_normal_bkbrush
);
931 dc
.SetFont(m_normal_font
);
932 textx
= normal_textx
;
933 texty
= normal_texty
;
941 points
[0].y
= tab_y
+ tab_height
- 1;
942 points
[1].x
= tab_x
+ tab_height
- 3;
943 points
[1].y
= tab_y
+ 2;
944 points
[2].x
= tab_x
+ tab_height
+ 3;
946 points
[3].x
= tab_x
+ tab_width
- 2;
948 points
[4].x
= tab_x
+ tab_width
;
949 points
[4].y
= tab_y
+ 2;
950 points
[5].x
= tab_x
+ tab_width
;
951 points
[5].y
= tab_y
+ tab_height
- 1;
952 points
[6] = points
[0];
954 dc
.SetClippingRegion(in_rect
);
956 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
958 dc
.SetPen(*wxGREY_PEN
);
960 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
961 dc
.DrawLines(WXSIZEOF(points
), points
);
966 int close_button_width
= 0;
967 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
969 close_button_width
= m_active_close_bmp
.GetWidth();
970 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
974 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
977 // set minimum text offset
978 if (text_offset
< tab_x
+ tab_height
)
979 text_offset
= tab_x
+ tab_height
;
981 // chop text if necessary
982 wxString draw_text
= wxAuiChopText(dc
,
984 tab_width
- (text_offset
-tab_x
) - close_button_width
);
987 dc
.DrawText(draw_text
,
989 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
992 // draw close button if necessary
993 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
997 bmp
= m_active_close_bmp
;
999 bmp
= m_disabled_close_bmp
;
1001 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1002 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1005 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1007 *out_button_rect
= rect
;
1011 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1013 dc
.DestroyClippingRegion();
1016 int wxAuiSimpleTabArt
::GetIndentSize()
1021 wxSize wxAuiSimpleTabArt
::GetTabSize(wxDC
& dc
,
1022 wxWindow
* WXUNUSED(wnd
),
1023 const wxString
& caption
,
1024 const wxBitmap
& WXUNUSED(bitmap
),
1025 bool WXUNUSED(active
),
1026 int close_button_state
,
1029 wxCoord measured_textx
, measured_texty
;
1031 dc
.SetFont(m_measuring_font
);
1032 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1034 wxCoord tab_height
= measured_texty
+ 4;
1035 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1037 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1038 tab_width
+= m_active_close_bmp
.GetWidth();
1040 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1042 tab_width
= m_fixed_tab_width
;
1045 *x_extent
= tab_width
- (tab_height
/2) - 1;
1047 return wxSize(tab_width
, tab_height
);
1051 void wxAuiSimpleTabArt
::DrawButton(wxDC
& dc
,
1052 wxWindow
* WXUNUSED(wnd
),
1053 const wxRect
& in_rect
,
1057 const wxBitmap
& bitmap_override
,
1063 if (bitmap_override
.IsOk())
1065 bmp
= bitmap_override
;
1071 case wxAUI_BUTTON_CLOSE
:
1072 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1073 bmp
= m_disabled_close_bmp
;
1075 bmp
= m_active_close_bmp
;
1077 case wxAUI_BUTTON_LEFT
:
1078 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1079 bmp
= m_disabled_left_bmp
;
1081 bmp
= m_active_left_bmp
;
1083 case wxAUI_BUTTON_RIGHT
:
1084 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1085 bmp
= m_disabled_right_bmp
;
1087 bmp
= m_active_right_bmp
;
1089 case wxAUI_BUTTON_WINDOWLIST
:
1090 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1091 bmp
= m_disabled_windowlist_bmp
;
1093 bmp
= m_active_windowlist_bmp
;
1103 if (orientation
== wxLEFT
)
1105 rect
.SetX(in_rect
.x
);
1106 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1107 rect
.SetWidth(bmp
.GetWidth());
1108 rect
.SetHeight(bmp
.GetHeight());
1112 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1113 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1114 bmp
.GetWidth(), bmp
.GetHeight());
1118 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1124 int wxAuiSimpleTabArt
::ShowWindowList(wxWindow
* wnd
,
1125 const wxArrayString
& items
,
1130 size_t i
, count
= items
.GetCount();
1131 for (i
= 0; i
< count
; ++i
)
1133 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1136 if (active_idx
!= -1)
1138 menuPopup
.Check(1000+active_idx
, true);
1141 // find out where to put the popup menu of window
1142 // items. Subtract 100 for now to center the menu
1143 // a bit, until a better mechanism can be implemented
1144 wxPoint pt
= ::wxGetMousePosition();
1145 pt
= wnd
->ScreenToClient(pt
);
1151 // find out the screen coordinate at the bottom of the tab ctrl
1152 wxRect cli_rect
= wnd
->GetClientRect();
1153 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1155 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1156 wnd
->PushEventHandler(cc
);
1157 wnd
->PopupMenu(&menuPopup
, pt
);
1158 int command
= cc
->GetCommandId();
1159 wnd
->PopEventHandler(true);
1161 if (command
>= 1000)
1162 return command
-1000;
1167 int wxAuiSimpleTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
1168 wxAuiNotebookPageArray
& WXUNUSED(pages
),
1169 const wxSize
& WXUNUSED(required_bmp_size
))
1172 dc
.SetFont(m_measuring_font
);
1174 wxSize s
= GetTabSize(dc
,
1179 wxAUI_BUTTON_STATE_HIDDEN
,
1184 void wxAuiSimpleTabArt
::SetNormalFont(const wxFont
& font
)
1186 m_normal_font
= font
;
1189 void wxAuiSimpleTabArt
::SetSelectedFont(const wxFont
& font
)
1191 m_selected_font
= font
;
1194 void wxAuiSimpleTabArt
::SetMeasuringFont(const wxFont
& font
)
1196 m_measuring_font
= font
;
1202 // -- wxAuiTabContainer class implementation --
1205 // wxAuiTabContainer is a class which contains information about each
1206 // tab. It also can render an entire tab control to a specified DC.
1207 // It's not a window class itself, because this code will be used by
1208 // the wxFrameMananger, where it is disadvantageous to have separate
1209 // windows for each tab control in the case of "docked tabs"
1211 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1212 // which can be used as a tab control in the normal sense.
1215 wxAuiTabContainer
::wxAuiTabContainer()
1219 m_art
= new wxAuiDefaultTabArt
;
1221 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1222 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1223 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1224 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1227 wxAuiTabContainer
::~wxAuiTabContainer()
1232 void wxAuiTabContainer
::SetArtProvider(wxAuiTabArt
* art
)
1239 m_art
->SetFlags(m_flags
);
1243 wxAuiTabArt
* wxAuiTabContainer
::GetArtProvider() const
1248 void wxAuiTabContainer
::SetFlags(unsigned int flags
)
1252 // check for new close button settings
1253 RemoveButton(wxAUI_BUTTON_LEFT
);
1254 RemoveButton(wxAUI_BUTTON_RIGHT
);
1255 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1256 RemoveButton(wxAUI_BUTTON_CLOSE
);
1259 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1261 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1262 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1265 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1267 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1270 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1272 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1277 m_art
->SetFlags(m_flags
);
1281 unsigned int wxAuiTabContainer
::GetFlags() const
1287 void wxAuiTabContainer
::SetNormalFont(const wxFont
& font
)
1289 m_art
->SetNormalFont(font
);
1292 void wxAuiTabContainer
::SetSelectedFont(const wxFont
& font
)
1294 m_art
->SetSelectedFont(font
);
1297 void wxAuiTabContainer
::SetMeasuringFont(const wxFont
& font
)
1299 m_art
->SetMeasuringFont(font
);
1302 void wxAuiTabContainer
::SetRect(const wxRect
& rect
)
1308 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1312 bool wxAuiTabContainer
::AddPage(wxWindow
* page
,
1313 const wxAuiNotebookPage
& info
)
1315 wxAuiNotebookPage page_info
;
1317 page_info
.window
= page
;
1319 m_pages
.Add(page_info
);
1321 // let the art provider know how many pages we have
1324 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1330 bool wxAuiTabContainer
::InsertPage(wxWindow
* page
,
1331 const wxAuiNotebookPage
& info
,
1334 wxAuiNotebookPage page_info
;
1336 page_info
.window
= page
;
1338 if (idx
>= m_pages
.GetCount())
1339 m_pages
.Add(page_info
);
1341 m_pages
.Insert(page_info
, idx
);
1343 // let the art provider know how many pages we have
1346 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1352 bool wxAuiTabContainer
::MovePage(wxWindow
* page
,
1355 int idx
= GetIdxFromWindow(page
);
1359 // get page entry, make a copy of it
1360 wxAuiNotebookPage p
= GetPage(idx
);
1362 // remove old page entry
1365 // insert page where it should be
1366 InsertPage(page
, p
, new_idx
);
1371 bool wxAuiTabContainer
::RemovePage(wxWindow
* wnd
)
1373 size_t i
, page_count
= m_pages
.GetCount();
1374 for (i
= 0; i
< page_count
; ++i
)
1376 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1377 if (page
.window
== wnd
)
1379 m_pages
.RemoveAt(i
);
1381 // let the art provider know how many pages we have
1384 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1394 bool wxAuiTabContainer
::SetActivePage(wxWindow
* wnd
)
1398 size_t i
, page_count
= m_pages
.GetCount();
1399 for (i
= 0; i
< page_count
; ++i
)
1401 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1402 if (page
.window
== wnd
)
1409 page
.active
= false;
1416 void wxAuiTabContainer
::SetNoneActive()
1418 size_t i
, page_count
= m_pages
.GetCount();
1419 for (i
= 0; i
< page_count
; ++i
)
1421 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1422 page
.active
= false;
1426 bool wxAuiTabContainer
::SetActivePage(size_t page
)
1428 if (page
>= m_pages
.GetCount())
1431 return SetActivePage(m_pages
.Item(page
).window
);
1434 int wxAuiTabContainer
::GetActivePage() const
1436 size_t i
, page_count
= m_pages
.GetCount();
1437 for (i
= 0; i
< page_count
; ++i
)
1439 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1447 wxWindow
* wxAuiTabContainer
::GetWindowFromIdx(size_t idx
) const
1449 if (idx
>= m_pages
.GetCount())
1452 return m_pages
[idx
].window
;
1455 int wxAuiTabContainer
::GetIdxFromWindow(wxWindow
* wnd
) const
1457 size_t i
, page_count
= m_pages
.GetCount();
1458 for (i
= 0; i
< page_count
; ++i
)
1460 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1461 if (page
.window
== wnd
)
1467 wxAuiNotebookPage
& wxAuiTabContainer
::GetPage(size_t idx
)
1469 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1471 return m_pages
[idx
];
1474 wxAuiNotebookPageArray
& wxAuiTabContainer
::GetPages()
1479 size_t wxAuiTabContainer
::GetPageCount() const
1481 return m_pages
.GetCount();
1484 void wxAuiTabContainer
::AddButton(int id
,
1486 const wxBitmap
& normal_bitmap
,
1487 const wxBitmap
& disabled_bitmap
)
1489 wxAuiTabContainerButton button
;
1491 button
.bitmap
= normal_bitmap
;
1492 button
.dis_bitmap
= disabled_bitmap
;
1493 button
.location
= location
;
1494 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1496 m_buttons
.Add(button
);
1499 void wxAuiTabContainer
::RemoveButton(int id
)
1501 size_t i
, button_count
= m_buttons
.GetCount();
1503 for (i
= 0; i
< button_count
; ++i
)
1505 if (m_buttons
.Item(i
).id
== id
)
1507 m_buttons
.RemoveAt(i
);
1515 size_t wxAuiTabContainer
::GetTabOffset() const
1517 return m_tab_offset
;
1520 void wxAuiTabContainer
::SetTabOffset(size_t offset
)
1522 m_tab_offset
= offset
;
1528 // Render() renders the tab catalog to the specified DC
1529 // It is a virtual function and can be overridden to
1530 // provide custom drawing capabilities
1531 void wxAuiTabContainer
::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1533 if (!raw_dc
|| !raw_dc
->IsOk())
1539 size_t page_count
= m_pages
.GetCount();
1540 size_t button_count
= m_buttons
.GetCount();
1542 // create off-screen bitmap
1543 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1544 dc
.SelectObject(bmp
);
1549 // find out if size of tabs is larger than can be
1550 // afforded on screen
1551 int total_width
= 0;
1552 int visible_width
= 0;
1553 for (i
= 0; i
< page_count
; ++i
)
1555 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1557 // determine if a close button is on this tab
1558 bool close_button
= false;
1559 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1560 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1562 close_button
= true;
1567 wxSize size
= m_art
->GetTabSize(dc
,
1573 wxAUI_BUTTON_STATE_NORMAL
:
1574 wxAUI_BUTTON_STATE_HIDDEN
,
1577 if (i
+1 < page_count
)
1578 total_width
+= x_extent
;
1580 total_width
+= size
.x
;
1582 if (i
>= m_tab_offset
)
1584 if (i
+1 < page_count
)
1585 visible_width
+= x_extent
;
1587 visible_width
+= size
.x
;
1591 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1593 // show 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
;
1606 // hide left/right buttons
1607 for (i
= 0; i
< button_count
; ++i
)
1609 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1610 if (button
.id
== wxAUI_BUTTON_LEFT
||
1611 button
.id
== wxAUI_BUTTON_RIGHT
)
1613 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1618 // determine whether left button should be enabled
1619 for (i
= 0; i
< button_count
; ++i
)
1621 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1622 if (button
.id
== wxAUI_BUTTON_LEFT
)
1624 if (m_tab_offset
== 0)
1625 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1627 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1629 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1631 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1632 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1634 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1641 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1644 int left_buttons_width
= 0;
1645 int right_buttons_width
= 0;
1649 // draw the buttons on the right side
1650 offset
= m_rect
.x
+ m_rect
.width
;
1651 for (i
= 0; i
< button_count
; ++i
)
1653 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1655 if (button
.location
!= wxRIGHT
)
1657 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1660 wxRect button_rect
= m_rect
;
1661 button_rect
.SetY(1);
1662 button_rect
.SetWidth(offset
);
1664 m_art
->DrawButton(dc
,
1673 offset
-= button
.rect
.GetWidth();
1674 right_buttons_width
+= button
.rect
.GetWidth();
1681 // draw the buttons on the left side
1683 for (i
= 0; i
< button_count
; ++i
)
1685 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1687 if (button
.location
!= wxLEFT
)
1689 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1692 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1694 m_art
->DrawButton(dc
,
1703 offset
+= button
.rect
.GetWidth();
1704 left_buttons_width
+= button
.rect
.GetWidth();
1707 offset
= left_buttons_width
;
1710 offset
+= m_art
->GetIndentSize();
1713 // prepare the tab-close-button array
1714 // make sure tab button entries which aren't used are marked as hidden
1715 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1716 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1718 // make sure there are enough tab button entries to accommodate all tabs
1719 while (m_tab_close_buttons
.GetCount() < page_count
)
1721 wxAuiTabContainerButton tempbtn
;
1722 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1723 tempbtn
.location
= wxCENTER
;
1724 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1725 m_tab_close_buttons
.Add(tempbtn
);
1729 // buttons before the tab offset must be set to hidden
1730 for (i
= 0; i
< m_tab_offset
; ++i
)
1732 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1738 size_t active
= 999;
1739 int active_offset
= 0;
1743 wxRect rect
= m_rect
;
1745 rect
.height
= m_rect
.height
;
1747 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1749 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1750 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1752 // determine if a close button is on this tab
1753 bool close_button
= false;
1754 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1755 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1757 close_button
= true;
1758 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1760 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1761 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1762 tab_button
.location
= wxCENTER
;
1767 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1771 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1773 if (rect
.width
<= 0)
1782 tab_button
.cur_state
,
1790 active_offset
= offset
;
1798 // make sure to deactivate buttons which are off the screen to the right
1799 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1801 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1805 // draw the active tab again so it stands in the foreground
1806 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1808 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1810 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1812 // determine if a close button is on this tab
1813 bool close_button
= false;
1814 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1815 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1817 close_button
= true;
1820 rect
.x
= active_offset
;
1827 tab_button
.cur_state
,
1834 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1835 m_rect
.GetWidth(), m_rect
.GetHeight(),
1840 // TabHitTest() tests if a tab was hit, passing the window pointer
1841 // back if that condition was fulfilled. The function returns
1842 // true if a tab was hit, otherwise false
1843 bool wxAuiTabContainer
::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1845 if (!m_rect
.Contains(x
,y
))
1848 wxAuiTabContainerButton
* btn
= NULL
;
1849 if (ButtonHitTest(x
, y
, &btn
))
1851 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1855 size_t i
, page_count
= m_pages
.GetCount();
1857 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1859 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1860 if (page
.rect
.Contains(x
,y
))
1871 // ButtonHitTest() tests if a button was hit. The function returns
1872 // true if a button was hit, otherwise false
1873 bool wxAuiTabContainer
::ButtonHitTest(int x
, int y
,
1874 wxAuiTabContainerButton
** hit
) const
1876 if (!m_rect
.Contains(x
,y
))
1879 size_t i
, button_count
;
1882 button_count
= m_buttons
.GetCount();
1883 for (i
= 0; i
< button_count
; ++i
)
1885 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1886 if (button
.rect
.Contains(x
,y
) &&
1887 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1888 wxAUI_BUTTON_STATE_DISABLED
)))
1896 button_count
= m_tab_close_buttons
.GetCount();
1897 for (i
= 0; i
< button_count
; ++i
)
1899 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1900 if (button
.rect
.Contains(x
,y
) &&
1901 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1902 wxAUI_BUTTON_STATE_DISABLED
)))
1915 // the utility function ShowWnd() is the same as show,
1916 // except it handles wxAuiMDIChildFrame windows as well,
1917 // as the Show() method on this class is "unplugged"
1918 static void ShowWnd(wxWindow
* wnd
, bool show
)
1920 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1922 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1932 // DoShowHide() this function shows the active window, then
1933 // hides all of the other windows (in that order)
1934 void wxAuiTabContainer
::DoShowHide()
1936 wxAuiNotebookPageArray
& pages
= GetPages();
1937 size_t i
, page_count
= pages
.GetCount();
1939 // show new active page first
1940 for (i
= 0; i
< page_count
; ++i
)
1942 wxAuiNotebookPage
& page
= pages
.Item(i
);
1945 ShowWnd(page
.window
, true);
1950 // hide all other pages
1951 for (i
= 0; i
< page_count
; ++i
)
1953 wxAuiNotebookPage
& page
= pages
.Item(i
);
1954 ShowWnd(page
.window
, page
.active
);
1963 // -- wxAuiTabCtrl class implementation --
1967 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1968 EVT_PAINT(wxAuiTabCtrl
::OnPaint
)
1969 EVT_ERASE_BACKGROUND(wxAuiTabCtrl
::OnEraseBackground
)
1970 EVT_SIZE(wxAuiTabCtrl
::OnSize
)
1971 EVT_LEFT_DOWN(wxAuiTabCtrl
::OnLeftDown
)
1972 EVT_LEFT_DCLICK(wxAuiTabCtrl
::OnLeftDown
)
1973 EVT_LEFT_UP(wxAuiTabCtrl
::OnLeftUp
)
1974 EVT_MOTION(wxAuiTabCtrl
::OnMotion
)
1975 EVT_LEAVE_WINDOW(wxAuiTabCtrl
::OnLeaveWindow
)
1976 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl
::OnButton
)
1980 wxAuiTabCtrl
::wxAuiTabCtrl(wxWindow
* parent
,
1984 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1986 m_click_pt
= wxDefaultPosition
;
1987 m_is_dragging
= false;
1988 m_hover_button
= NULL
;
1989 m_pressed_button
= NULL
;
1992 wxAuiTabCtrl
::~wxAuiTabCtrl()
1996 void wxAuiTabCtrl
::OnPaint(wxPaintEvent
&)
2000 dc
.SetFont(GetFont());
2002 if (GetPageCount() > 0)
2006 void wxAuiTabCtrl
::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2010 void wxAuiTabCtrl
::OnSize(wxSizeEvent
& evt
)
2012 wxSize s
= evt
.GetSize();
2013 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2017 void wxAuiTabCtrl
::OnLeftDown(wxMouseEvent
& evt
)
2020 m_click_pt
= wxDefaultPosition
;
2021 m_is_dragging
= false;
2023 m_pressed_button
= NULL
;
2027 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2029 int new_selection
= GetIdxFromWindow(wnd
);
2031 if (new_selection
!= GetActivePage())
2033 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2034 e
.SetSelection(new_selection
);
2035 e
.SetOldSelection(GetActivePage());
2036 e
.SetEventObject(this);
2037 GetEventHandler()->ProcessEvent(e
);
2040 m_click_pt
.x
= evt
.m_x
;
2041 m_click_pt
.y
= evt
.m_y
;
2047 m_pressed_button
= m_hover_button
;
2048 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2054 void wxAuiTabCtrl
::OnLeftUp(wxMouseEvent
& evt
)
2056 if (GetCapture() == this)
2061 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2062 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2063 evt
.SetOldSelection(evt
.GetSelection());
2064 evt
.SetEventObject(this);
2065 GetEventHandler()->ProcessEvent(evt
);
2069 if (m_pressed_button
)
2071 // make sure we're still clicking the button
2072 wxAuiTabContainerButton
* button
= NULL
;
2073 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2076 if (button
!= m_pressed_button
)
2078 m_pressed_button
= NULL
;
2085 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2087 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2088 evt
.SetInt(m_pressed_button
->id
);
2089 evt
.SetEventObject(this);
2090 GetEventHandler()->ProcessEvent(evt
);
2093 m_pressed_button
= NULL
;
2096 m_click_pt
= wxDefaultPosition
;
2097 m_is_dragging
= false;
2101 void wxAuiTabCtrl
::OnMotion(wxMouseEvent
& evt
)
2103 wxPoint pos
= evt
.GetPosition();
2105 // check if the mouse is hovering above a button
2106 wxAuiTabContainerButton
* button
;
2107 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2109 if (m_hover_button
&& button
!= m_hover_button
)
2111 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2112 m_hover_button
= NULL
;
2117 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2119 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2122 m_hover_button
= button
;
2130 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2131 m_hover_button
= NULL
;
2138 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2143 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2144 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2145 evt
.SetOldSelection(evt
.GetSelection());
2146 evt
.SetEventObject(this);
2147 GetEventHandler()->ProcessEvent(evt
);
2152 int drag_x_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_X
);
2153 int drag_y_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_Y
);
2155 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2156 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2158 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2159 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2160 evt
.SetOldSelection(evt
.GetSelection());
2161 evt
.SetEventObject(this);
2162 GetEventHandler()->ProcessEvent(evt
);
2164 m_is_dragging
= true;
2168 void wxAuiTabCtrl
::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2172 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2173 m_hover_button
= NULL
;
2179 void wxAuiTabCtrl
::OnButton(wxAuiNotebookEvent
& event
)
2181 int button
= event
.GetInt();
2183 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2185 if (button
== wxAUI_BUTTON_LEFT
)
2187 if (GetTabOffset() > 0)
2189 SetTabOffset(GetTabOffset()-1);
2196 SetTabOffset(GetTabOffset()+1);
2201 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2205 size_t i
, page_count
= m_pages
.GetCount();
2206 for (i
= 0; i
< page_count
; ++i
)
2208 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2209 as
.Add(page
.caption
);
2212 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2216 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2217 e
.SetSelection(idx
);
2218 e
.SetOldSelection(GetActivePage());
2219 e
.SetEventObject(this);
2220 GetEventHandler()->ProcessEvent(e
);
2229 // wxTabFrame is an interesting case. It's important that all child pages
2230 // of the multi-notebook control are all actually children of that control
2231 // (and not grandchildren). wxTabFrame facilitates this. There is one
2232 // instance of wxTabFrame for each tab control inside the multi-notebook.
2233 // It's important to know that wxTabFrame is not a real window, but it merely
2234 // used to capture the dimensions/positioning of the internal tab control and
2235 // it's managed page windows
2237 class wxTabFrame
: public wxWindow
2244 m_rect
= wxRect(0,0,200,200);
2245 m_tab_ctrl_height
= 20;
2248 void SetTabCtrlHeight(int h
)
2250 m_tab_ctrl_height
= h
;
2253 void DoSetSize(int x
, int y
,
2254 int width
, int height
,
2255 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2257 m_rect
= wxRect(x
, y
, width
, height
);
2261 void DoGetClientSize(int* x
, int* y
) const
2267 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2274 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2275 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2276 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2280 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2281 size_t i
, page_count
= pages
.GetCount();
2283 for (i
= 0; i
< page_count
; ++i
)
2285 wxAuiNotebookPage
& page
= pages
.Item(i
);
2286 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2287 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2289 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2291 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2292 wnd
->ApplyMDIChildFrameRect();
2297 void DoGetSize(int* x
, int* y
) const
2300 *x
= m_rect
.GetWidth();
2302 *y
= m_rect
.GetHeight();
2314 wxAuiTabCtrl
* m_tabs
;
2315 int m_tab_ctrl_height
;
2322 // -- wxAuiNotebook class implementation --
2324 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2325 EVT_SIZE(wxAuiNotebook
::OnSize
)
2326 EVT_CHILD_FOCUS(wxAuiNotebook
::OnChildFocus
)
2327 EVT_COMMAND_RANGE(10000, 10100,
2328 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2329 wxAuiNotebook
::OnTabClicked
)
2330 EVT_COMMAND_RANGE(10000, 10100,
2331 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2332 wxAuiNotebook
::OnTabBeginDrag
)
2333 EVT_COMMAND_RANGE(10000, 10100,
2334 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2335 wxAuiNotebook
::OnTabEndDrag
)
2336 EVT_COMMAND_RANGE(10000, 10100,
2337 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2338 wxAuiNotebook
::OnTabDragMotion
)
2339 EVT_COMMAND_RANGE(10000, 10100,
2340 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2341 wxAuiNotebook
::OnTabButton
)
2344 wxAuiNotebook
::wxAuiNotebook()
2347 m_tab_id_counter
= 10000;
2349 m_tab_ctrl_height
= 20;
2350 m_requested_bmp_size
= wxDefaultSize
;
2351 m_requested_tabctrl_height
= -1;
2354 wxAuiNotebook
::wxAuiNotebook(wxWindow
*parent
,
2358 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2361 m_requested_bmp_size
= wxDefaultSize
;
2362 m_requested_tabctrl_height
= -1;
2363 InitNotebook(style
);
2366 bool wxAuiNotebook
::Create(wxWindow
* parent
,
2372 if (!wxControl
::Create(parent
, id
, pos
, size
, style
))
2375 InitNotebook(style
);
2380 // InitNotebook() contains common initialization
2381 // code called by all constructors
2382 void wxAuiNotebook
::InitNotebook(long style
)
2385 m_tab_id_counter
= 10000;
2387 m_flags
= (unsigned int)style
;
2388 m_tab_ctrl_height
= 20;
2390 m_normal_font
= *wxNORMAL_FONT
;
2391 m_selected_font
= *wxNORMAL_FONT
;
2392 m_selected_font
.SetWeight(wxBOLD
);
2394 SetArtProvider(new wxAuiDefaultTabArt
);
2396 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2397 m_dummy_wnd
->SetSize(200, 200);
2398 m_dummy_wnd
->Show(false);
2400 m_mgr
.SetManagedWindow(this);
2401 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2402 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2404 m_mgr
.AddPane(m_dummy_wnd
,
2405 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2410 wxAuiNotebook
::~wxAuiNotebook()
2415 void wxAuiNotebook
::SetArtProvider(wxAuiTabArt
* art
)
2417 m_tabs
.SetArtProvider(art
);
2419 UpdateTabCtrlHeight();
2422 // SetTabCtrlHeight() is the highest-level override of the
2423 // tab height. A call to this function effectively enforces a
2424 // specified tab ctrl height, overriding all other considerations,
2425 // such as text or bitmap height. It overrides any call to
2426 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2427 // any previous call and returns to the default behavior
2429 void wxAuiNotebook
::SetTabCtrlHeight(int height
)
2431 m_requested_tabctrl_height
= height
;
2433 // if window is already initialized, recalculate the tab height
2436 UpdateTabCtrlHeight();
2441 // SetUniformBitmapSize() ensures that all tabs will have
2442 // the same height, even if some tabs don't have bitmaps
2443 // Passing wxDefaultSize to this function will instruct
2444 // the control to use dynamic tab height-- so when a tab
2445 // with a large bitmap is added, the tab ctrl's height will
2446 // automatically increase to accommodate the bitmap
2448 void wxAuiNotebook
::SetUniformBitmapSize(const wxSize
& size
)
2450 m_requested_bmp_size
= size
;
2452 // if window is already initialized, recalculate the tab height
2455 UpdateTabCtrlHeight();
2459 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2460 // to be used interally
2461 void wxAuiNotebook
::UpdateTabCtrlHeight()
2463 // get the tab ctrl height we will use
2464 int height
= CalculateTabCtrlHeight();
2466 // if the tab control height needs to change, update
2467 // all of our tab controls with the new height
2468 if (m_tab_ctrl_height
!= height
)
2470 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2472 m_tab_ctrl_height
= height
;
2474 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2475 size_t i
, pane_count
= all_panes
.GetCount();
2476 for (i
= 0; i
< pane_count
; ++i
)
2478 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2479 if (pane
.name
== wxT("dummy"))
2481 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2482 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2483 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2484 tabctrl
->SetArtProvider(art
->Clone());
2485 tab_frame
->DoSizing();
2490 void wxAuiNotebook
::UpdateHintWindowSize()
2492 wxSize size
= CalculateNewSplitSize();
2494 // the placeholder hint window should be set to this size
2495 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2499 info
.BestSize(size
);
2500 m_dummy_wnd
->SetSize(size
);
2505 // calculates the size of the new split
2506 wxSize wxAuiNotebook
::CalculateNewSplitSize()
2508 // count number of tab controls
2509 int tab_ctrl_count
= 0;
2510 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2511 size_t i
, pane_count
= all_panes
.GetCount();
2512 for (i
= 0; i
< pane_count
; ++i
)
2514 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2515 if (pane
.name
== wxT("dummy"))
2520 wxSize new_split_size
;
2522 // if there is only one tab control, the first split
2523 // should happen around the middle
2524 if (tab_ctrl_count
< 2)
2526 new_split_size
= GetClientSize();
2527 new_split_size
.x
/= 2;
2528 new_split_size
.y
/= 2;
2532 // this is in place of a more complicated calculation
2533 // that needs to be implemented
2534 new_split_size
= wxSize(180,180);
2537 return new_split_size
;
2540 int wxAuiNotebook
::CalculateTabCtrlHeight()
2542 // if a fixed tab ctrl height is specified,
2543 // just return that instead of calculating a
2545 if (m_requested_tabctrl_height
!= -1)
2546 return m_requested_tabctrl_height
;
2548 // find out new best tab height
2549 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2551 return art
->GetBestTabCtrlSize(this,
2553 m_requested_bmp_size
);
2557 wxAuiTabArt
* wxAuiNotebook
::GetArtProvider() const
2559 return m_tabs
.GetArtProvider();
2562 void wxAuiNotebook
::SetWindowStyleFlag(long style
)
2564 wxControl
::SetWindowStyleFlag(style
);
2566 m_flags
= (unsigned int)style
;
2568 // if the control is already initialized
2569 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2571 // let all of the tab children know about the new style
2573 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2574 size_t i
, pane_count
= all_panes
.GetCount();
2575 for (i
= 0; i
< pane_count
; ++i
)
2577 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2578 if (pane
.name
== wxT("dummy"))
2580 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2581 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2582 tabctrl
->SetFlags(m_flags
);
2583 tabframe
->DoSizing();
2591 bool wxAuiNotebook
::AddPage(wxWindow
* page
,
2592 const wxString
& caption
,
2594 const wxBitmap
& bitmap
)
2596 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2599 bool wxAuiNotebook
::InsertPage(size_t page_idx
,
2601 const wxString
& caption
,
2603 const wxBitmap
& bitmap
)
2605 wxAuiNotebookPage info
;
2607 info
.caption
= caption
;
2608 info
.bitmap
= bitmap
;
2609 info
.active
= false;
2611 // if there are currently no tabs, the first added
2612 // tab must be active
2613 if (m_tabs
.GetPageCount() == 0)
2616 m_tabs
.InsertPage(page
, info
, page_idx
);
2618 // if that was the first page added, even if
2619 // select is false, it must become the "current page"
2620 // (though no select events will be fired)
2621 if (!select
&& m_tabs
.GetPageCount() == 1)
2622 m_curpage
= GetPageIndex(page
);
2624 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2625 if (page_idx
>= active_tabctrl
->GetPageCount())
2626 active_tabctrl
->AddPage(page
, info
);
2628 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2630 UpdateTabCtrlHeight();
2632 active_tabctrl
->DoShowHide();
2636 int idx
= m_tabs
.GetIdxFromWindow(page
);
2637 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2646 // DeletePage() removes a tab from the multi-notebook,
2647 // and destroys the window as well
2648 bool wxAuiNotebook
::DeletePage(size_t page_idx
)
2650 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2652 if (!RemovePage(page_idx
))
2655 // actually destroy the window now
2656 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2658 // delete the child frame with pending delete, as is
2659 // customary with frame windows
2660 if (!wxPendingDelete
.Member(wnd
))
2661 wxPendingDelete
.Append(wnd
);
2673 // RemovePage() removes a tab from the multi-notebook,
2674 // but does not destroy the window
2675 bool wxAuiNotebook
::RemovePage(size_t page_idx
)
2677 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2678 wxWindow
* new_active
= NULL
;
2680 // find out which onscreen tab ctrl owns this tab
2683 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2686 // find a new page and set it as active
2687 int new_idx
= ctrl_idx
+1;
2688 if (new_idx
>= (int)ctrl
->GetPageCount())
2689 new_idx
= ctrl_idx
-1;
2691 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2693 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2697 // set the active page to the first page that
2698 // isn't the one being deleted
2699 size_t i
, page_count
= m_tabs
.GetPageCount();
2700 for (i
= 0; i
< page_count
; ++i
)
2702 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2705 new_active
= m_tabs
.GetWindowFromIdx(i
);
2711 // remove the tab from main catalog
2712 if (!m_tabs
.RemovePage(wnd
))
2715 // remove the tab from the onscreen tab ctrl
2716 ctrl
->RemovePage(wnd
);
2719 RemoveEmptyTabFrames();
2721 // set new active pane
2725 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2731 // GetPageIndex() returns the index of the page, or -1 if the
2732 // page could not be located in the notebook
2733 int wxAuiNotebook
::GetPageIndex(wxWindow
* page_wnd
) const
2735 return m_tabs
.GetIdxFromWindow(page_wnd
);
2740 // SetPageText() changes the tab caption of the specified page
2741 bool wxAuiNotebook
::SetPageText(size_t page_idx
, const wxString
& text
)
2743 if (page_idx
>= m_tabs
.GetPageCount())
2746 // update our own tab catalog
2747 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2748 page_info
.caption
= text
;
2750 // update what's on screen
2753 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2755 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2756 info
.caption
= text
;
2765 bool wxAuiNotebook
::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2767 if (page_idx
>= m_tabs
.GetPageCount())
2770 // update our own tab catalog
2771 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2772 page_info
.bitmap
= bitmap
;
2774 // tab height might have changed
2775 UpdateTabCtrlHeight();
2777 // update what's on screen
2780 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2782 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2783 info
.bitmap
= bitmap
;
2792 // GetSelection() returns the index of the currently active page
2793 int wxAuiNotebook
::GetSelection() const
2798 // SetSelection() sets the currently active page
2799 size_t wxAuiNotebook
::SetSelection(size_t new_page
)
2801 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2805 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2806 evt
.SetSelection(new_page
);
2807 evt
.SetOldSelection(m_curpage
);
2808 evt
.SetEventObject(this);
2809 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2811 int old_curpage
= m_curpage
;
2812 m_curpage
= new_page
;
2814 // program allows the page change
2815 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2816 (void)GetEventHandler()->ProcessEvent(evt
);
2821 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2823 m_tabs
.SetActivePage(wnd
);
2825 ctrl
->SetActivePage(ctrl_idx
);
2832 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2833 size_t i
, pane_count
= all_panes
.GetCount();
2834 for (i
= 0; i
< pane_count
; ++i
)
2836 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2837 if (pane
.name
== wxT("dummy"))
2839 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2840 if (tabctrl
!= ctrl
)
2841 tabctrl
->SetSelectedFont(m_normal_font
);
2843 tabctrl
->SetSelectedFont(m_selected_font
);
2856 // GetPageCount() returns the total number of
2857 // pages managed by the multi-notebook
2858 size_t wxAuiNotebook
::GetPageCount() const
2860 return m_tabs
.GetPageCount();
2863 // GetPage() returns the wxWindow pointer of the
2865 wxWindow
* wxAuiNotebook
::GetPage(size_t page_idx
) const
2867 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2869 return m_tabs
.GetWindowFromIdx(page_idx
);
2872 // DoSizing() performs all sizing operations in each tab control
2873 void wxAuiNotebook
::DoSizing()
2875 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2876 size_t i
, pane_count
= all_panes
.GetCount();
2877 for (i
= 0; i
< pane_count
; ++i
)
2879 if (all_panes
.Item(i
).name
== wxT("dummy"))
2882 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2883 tabframe
->DoSizing();
2887 // GetActiveTabCtrl() returns the active tab control. It is
2888 // called to determine which control gets new windows being added
2889 wxAuiTabCtrl
* wxAuiNotebook
::GetActiveTabCtrl()
2891 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2896 // find the tab ctrl with the current page
2897 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2904 // no current page, just find the first tab ctrl
2905 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2906 size_t i
, pane_count
= all_panes
.GetCount();
2907 for (i
= 0; i
< pane_count
; ++i
)
2909 if (all_panes
.Item(i
).name
== wxT("dummy"))
2912 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2913 return tabframe
->m_tabs
;
2916 // If there is no tabframe at all, create one
2917 wxTabFrame
* tabframe
= new wxTabFrame
;
2918 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2919 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2924 tabframe
->m_tabs
->SetFlags(m_flags
);
2925 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2926 m_mgr
.AddPane(tabframe
,
2927 wxAuiPaneInfo().Center().CaptionVisible(false));
2931 return tabframe
->m_tabs
;
2934 // FindTab() finds the tab control that currently contains the window as well
2935 // as the index of the window in the tab control. It returns true if the
2936 // window was found, otherwise false.
2937 bool wxAuiNotebook
::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2939 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2940 size_t i
, pane_count
= all_panes
.GetCount();
2941 for (i
= 0; i
< pane_count
; ++i
)
2943 if (all_panes
.Item(i
).name
== wxT("dummy"))
2946 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2948 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2951 *ctrl
= tabframe
->m_tabs
;
2960 void wxAuiNotebook
::OnSize(wxSizeEvent
& evt
)
2962 UpdateHintWindowSize();
2967 void wxAuiNotebook
::OnTabClicked(wxCommandEvent
& command_evt
)
2969 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2971 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2972 wxASSERT(ctrl
!= NULL
);
2974 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2975 wxASSERT(wnd
!= NULL
);
2977 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2978 wxASSERT(idx
!= -1);
2983 void wxAuiNotebook
::OnTabBeginDrag(wxCommandEvent
&)
2988 void wxAuiNotebook
::OnTabDragMotion(wxCommandEvent
& evt
)
2990 wxPoint screen_pt
= ::wxGetMousePosition();
2991 wxPoint client_pt
= ScreenToClient(screen_pt
);
2994 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2995 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2997 if (dest_tabs
== src_tabs
)
3001 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3004 // always hide the hint for inner-tabctrl drag
3007 // if tab moving is not allowed, leave
3008 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3013 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3014 wxWindow
* dest_location_tab
;
3016 // this is an inner-tab drag/reposition
3017 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3019 int src_idx
= evt
.GetSelection();
3020 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3022 // prevent jumpy drag
3023 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3024 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3025 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3027 m_last_drag_x
= pt
.x
;
3032 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3033 dest_tabs
->MovePage(src_tab
, dest_idx
);
3034 dest_tabs
->SetActivePage((size_t)dest_idx
);
3035 dest_tabs
->DoShowHide();
3036 dest_tabs
->Refresh();
3037 m_last_drag_x
= pt
.x
;
3045 // if external drag is allowed, check if the tab is being dragged
3046 // over a different wxAuiNotebook control
3047 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3049 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3051 // if we aren't over any window, stop here
3055 // make sure we are not over the hint window
3056 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3060 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3062 tab_ctrl
= tab_ctrl
->GetParent();
3067 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3071 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3072 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3073 m_mgr
.ShowHint(hint_rect
);
3082 // we are either over a hint window, or not over a tab
3083 // window, and there is no where to drag to, so exit
3090 // if there are less than two panes, split can't happen, so leave
3091 if (m_tabs
.GetPageCount() < 2)
3094 // if tab moving is not allowed, leave
3095 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3101 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3107 wxRect hint_rect
= dest_tabs
->GetRect();
3108 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3109 m_mgr
.ShowHint(hint_rect
);
3113 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3119 void wxAuiNotebook
::OnTabEndDrag(wxCommandEvent
& command_evt
)
3121 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3126 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3127 wxAuiTabCtrl
* dest_tabs
= NULL
;
3130 // set cursor back to an arrow
3131 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3134 // get the mouse position, which will be used to determine the drop point
3135 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3136 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3140 // check for an external move
3141 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3143 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3147 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3149 tab_ctrl
= tab_ctrl
->GetParent();
3154 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3158 // find out from the destination control
3159 // if it's ok to drop this tab here
3160 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3161 e
.SetSelection(evt
.GetSelection());
3162 e
.SetOldSelection(evt
.GetSelection());
3163 e
.SetEventObject(this);
3164 e
.SetDragSource(this);
3165 e
.Veto(); // dropping must be explicitly approved by control owner
3167 nb
->GetEventHandler()->ProcessEvent(e
);
3171 // no answer or negative answer
3177 int src_idx
= evt
.GetSelection();
3178 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3180 // get main index of the page
3181 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3183 // make a copy of the page info
3184 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3186 // remove the page from the source notebook
3187 RemovePage(main_idx
);
3189 // reparent the page
3190 src_page
->Reparent(nb
);
3193 // found out the insert idx
3194 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3195 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3197 wxWindow
* target
= NULL
;
3198 int insert_idx
= -1;
3199 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3202 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3206 // add the page to the new notebook
3207 if (insert_idx
== -1)
3208 insert_idx
= dest_tabs
->GetPageCount();
3209 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3210 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3213 dest_tabs
->DoShowHide();
3214 dest_tabs
->Refresh();
3216 // set the selection in the destination tab control
3217 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3227 // only perform a tab split if it's allowed
3228 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3230 // If the pointer is in an existing tab frame, do a tab insert
3231 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3232 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3233 int insert_idx
= -1;
3236 dest_tabs
= tab_frame
->m_tabs
;
3238 if (dest_tabs
== src_tabs
)
3242 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3243 wxWindow
* target
= NULL
;
3244 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3247 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3253 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3258 // there is no suitable drop location here, exit out
3262 // If there is no tabframe at all, create one
3263 wxTabFrame
* new_tabs
= new wxTabFrame
;
3264 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3265 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3266 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3271 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3272 new_tabs
->m_tabs
->SetFlags(m_flags
);
3274 m_mgr
.AddPane(new_tabs
,
3275 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3278 dest_tabs
= new_tabs
->m_tabs
;
3283 // remove the page from the source tabs
3284 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3285 page_info
.active
= false;
3286 src_tabs
->RemovePage(page_info
.window
);
3287 if (src_tabs
->GetPageCount() > 0)
3289 src_tabs
->SetActivePage((size_t)0);
3290 src_tabs
->DoShowHide();
3291 src_tabs
->Refresh();
3296 // add the page to the destination tabs
3297 if (insert_idx
== -1)
3298 insert_idx
= dest_tabs
->GetPageCount();
3299 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3301 if (src_tabs
->GetPageCount() == 0)
3303 RemoveEmptyTabFrames();
3307 dest_tabs
->DoShowHide();
3308 dest_tabs
->Refresh();
3310 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3312 UpdateHintWindowSize();
3318 wxAuiTabCtrl
* wxAuiNotebook
::GetTabCtrlFromPoint(const wxPoint
& pt
)
3320 // if we've just removed the last tab from the source
3321 // tab set, the remove the tab control completely
3322 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3323 size_t i
, pane_count
= all_panes
.GetCount();
3324 for (i
= 0; i
< pane_count
; ++i
)
3326 if (all_panes
.Item(i
).name
== wxT("dummy"))
3329 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3330 if (tabframe
->m_tab_rect
.Contains(pt
))
3331 return tabframe
->m_tabs
;
3337 wxWindow
* wxAuiNotebook
::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3339 // if we've just removed the last tab from the source
3340 // tab set, the remove the tab control completely
3341 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3342 size_t i
, pane_count
= all_panes
.GetCount();
3343 for (i
= 0; i
< pane_count
; ++i
)
3345 if (all_panes
.Item(i
).name
== wxT("dummy"))
3348 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3349 if (tabframe
->m_tabs
== tab_ctrl
)
3358 void wxAuiNotebook
::RemoveEmptyTabFrames()
3360 // if we've just removed the last tab from the source
3361 // tab set, the remove the tab control completely
3362 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3363 size_t i
, pane_count
= all_panes
.GetCount();
3364 for (i
= 0; i
< pane_count
; ++i
)
3366 if (all_panes
.Item(i
).name
== wxT("dummy"))
3369 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3370 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3372 m_mgr
.DetachPane(tab_frame
);
3374 // use pending delete because sometimes during
3375 // window closing, refreshs are pending
3376 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3377 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3378 //tab_frame->m_tabs->Destroy();
3385 // check to see if there is still a center pane;
3386 // if there isn't, make a frame the center pane
3387 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3388 pane_count
= panes
.GetCount();
3389 wxWindow
* first_good
= NULL
;
3390 bool center_found
= false;
3391 for (i
= 0; i
< pane_count
; ++i
)
3393 if (panes
.Item(i
).name
== wxT("dummy"))
3395 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3396 center_found
= true;
3398 first_good
= panes
.Item(i
).window
;
3401 if (!center_found
&& first_good
)
3403 m_mgr
.GetPane(first_good
).Centre();
3409 void wxAuiNotebook
::OnChildFocus(wxChildFocusEvent
& evt
)
3411 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3412 if (idx
!= -1 && idx
!= m_curpage
)
3419 void wxAuiNotebook
::OnTabButton(wxCommandEvent
& command_evt
)
3421 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3422 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3424 int button_id
= evt
.GetInt();
3426 if (button_id
== wxAUI_BUTTON_CLOSE
)
3428 int selection
= tabs
->GetActivePage();
3430 if (selection
!= -1)
3432 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3435 // ask owner if it's ok to close the tab
3436 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3437 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3438 e
.SetOldSelection(evt
.GetSelection());
3439 e
.SetEventObject(this);
3440 GetEventHandler()->ProcessEvent(e
);
3445 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3451 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3452 DeletePage(main_idx
);