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 wxAuiNotebookPage
& page
,
303 const wxRect
& in_rect
,
304 int close_button_state
,
305 wxRect
* out_tab_rect
,
306 wxRect
* out_button_rect
,
309 wxCoord normal_textx
, normal_texty
;
310 wxCoord selected_textx
, selected_texty
;
311 wxCoord textx
, texty
;
313 // if the caption is empty, measure some temporary text
314 wxString caption
= page
.caption
;
318 dc
.SetFont(m_selected_font
);
319 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
321 dc
.SetFont(m_normal_font
);
322 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
324 // figure out the size of the tab
325 wxSize tab_size
= GetTabSize(dc
,
333 wxCoord tab_height
= m_tab_ctrl_height
- 3;
334 wxCoord tab_width
= tab_size
.x
;
335 wxCoord tab_x
= in_rect
.x
;
336 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
339 caption
= page
.caption
;
342 // select pen, brush and font for the tab to be drawn
346 dc
.SetFont(m_selected_font
);
347 textx
= selected_textx
;
348 texty
= selected_texty
;
352 dc
.SetFont(m_normal_font
);
353 textx
= normal_textx
;
354 texty
= normal_texty
;
358 // create points that will make the tab outline
360 int clip_width
= tab_width
;
361 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
362 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
365 wxPoint clip_points[6];
366 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
367 clip_points[1] = wxPoint(tab_x, tab_y+2);
368 clip_points[2] = wxPoint(tab_x+2, tab_y);
369 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
370 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
371 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
373 // FIXME: these ports don't provide wxRegion ctor from array of points
374 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
375 // set the clipping region for the tab --
376 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
377 dc.SetClippingRegion(clipping_region);
378 #endif // !wxDFB && !wxCocoa
380 // since the above code above doesn't play well with WXDFB or WXCOCOA,
381 // we'll just use a rectangle for the clipping region for now --
382 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
385 wxPoint border_points
[6];
386 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
387 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
388 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
389 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
390 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
391 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
394 int drawn_tab_yoff
= border_points
[1].y
;
395 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
402 // draw base background color
403 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
404 dc
.SetPen(m_base_colour_pen
);
405 dc
.SetBrush(m_base_colour_brush
);
406 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
408 // this white helps fill out the gradient at the top of the tab
409 dc
.SetPen(*wxWHITE_PEN
);
410 dc
.SetBrush(*wxWHITE_BRUSH
);
411 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
413 // these two points help the rounded corners appear more antialiased
414 dc
.SetPen(m_base_colour_pen
);
415 dc
.DrawPoint(r
.x
+2, r
.y
+1);
416 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
418 // set rectangle down a bit for gradient drawing
419 r
.SetHeight(r
.GetHeight()/2);
425 // draw gradient background
426 wxColor top_color
= *wxWHITE
;
427 wxColor bottom_color
= m_base_colour
;
428 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
434 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
436 // start the gradent up a bit and leave the inside border inset
437 // by a pixel for a 3D look. Only the top half of the inactive
438 // tab will have a slight gradient
445 // -- draw top gradient fill for glossy look
446 wxColor top_color
= m_base_colour
;
447 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
448 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
453 // -- draw bottom fill for glossy look
454 top_color
= m_base_colour
;
455 bottom_color
= m_base_colour
;
456 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
460 dc
.SetPen(m_border_pen
);
461 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
462 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
464 // there are two horizontal grey lines at the bottom of the tab control,
465 // this gets rid of the top one of those lines in the tab control
468 wxColor start_color
= m_base_colour
;
469 dc
.SetPen(m_base_colour_pen
);
470 dc
.DrawLine(border_points
[0].x
+1,
477 int text_offset
= tab_x
+ 8;
478 int close_button_width
= 0;
479 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
481 close_button_width
= m_active_close_bmp
.GetWidth();
485 if (page
.bitmap
.IsOk())
487 int bitmap_offset
= tab_x
+ 8;
490 dc
.DrawBitmap(page
.bitmap
,
492 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
495 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
496 text_offset
+= 3; // bitmap padding
500 text_offset
= tab_x
+ 8;
504 wxString draw_text
= wxAuiChopText(dc
,
506 tab_width
- (text_offset
-tab_x
) - close_button_width
);
509 dc
.DrawText(draw_text
,
511 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
516 // draw close button if necessary
517 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
519 wxBitmap bmp
= m_disabled_close_bmp
;
521 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
522 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
524 bmp
= m_active_close_bmp
;
527 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
528 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
531 IndentPressedBitmap(&rect
, close_button_state
);
532 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
534 *out_button_rect
= rect
;
537 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
539 dc
.DestroyClippingRegion();
542 int wxAuiDefaultTabArt::GetIndentSize()
547 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
548 wxWindow
* WXUNUSED(wnd
),
549 const wxString
& caption
,
550 const wxBitmap
& bitmap
,
551 bool WXUNUSED(active
),
552 int close_button_state
,
555 wxCoord measured_textx
, measured_texty
, tmp
;
557 dc
.SetFont(m_measuring_font
);
558 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
560 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
562 // add padding around the text
563 wxCoord tab_width
= measured_textx
;
564 wxCoord tab_height
= measured_texty
;
566 // if the close button is showing, add space for it
567 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
568 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
570 // if there's a bitmap, add space for it
573 tab_width
+= bitmap
.GetWidth();
574 tab_width
+= 3; // right side bitmap padding
575 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
582 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
584 tab_width
= m_fixed_tab_width
;
587 *x_extent
= tab_width
;
589 return wxSize(tab_width
, tab_height
);
593 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
594 wxWindow
* WXUNUSED(wnd
),
595 const wxRect
& in_rect
,
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::ShowDropDown(wxWindow
* wnd
,
660 const wxAuiNotebookPageArray
& pages
,
665 size_t i
, count
= pages
.GetCount();
666 for (i
= 0; i
< count
; ++i
)
668 const wxAuiNotebookPage
& page
= pages
.Item(i
);
669 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
672 if (active_idx
!= -1)
674 menuPopup
.Check(1000+active_idx
, true);
677 // find out where to put the popup menu of window items
678 wxPoint pt
= ::wxGetMousePosition();
679 pt
= wnd
->ScreenToClient(pt
);
681 // find out the screen coordinate at the bottom of the tab ctrl
682 wxRect cli_rect
= wnd
->GetClientRect();
683 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
685 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
686 wnd
->PushEventHandler(cc
);
687 wnd
->PopupMenu(&menuPopup
, pt
);
688 int command
= cc
->GetCommandId();
689 wnd
->PopEventHandler(true);
697 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
698 const wxAuiNotebookPageArray
& pages
,
699 const wxSize
& required_bmp_size
)
702 dc
.SetFont(m_measuring_font
);
704 // sometimes a standard bitmap size needs to be enforced, especially
705 // if some tabs have bitmaps and others don't. This is important because
706 // it prevents the tab control from resizing when tabs are added.
707 wxBitmap measure_bmp
;
708 if (required_bmp_size
.IsFullySpecified())
710 measure_bmp
.Create(required_bmp_size
.x
,
711 required_bmp_size
.y
);
716 size_t i
, page_count
= pages
.GetCount();
717 for (i
= 0; i
< page_count
; ++i
)
719 wxAuiNotebookPage
& page
= pages
.Item(i
);
722 if (measure_bmp
.IsOk())
727 // we don't use the caption text because we don't
728 // want tab heights to be different in the case
729 // of a very short piece of text on one tab and a very
730 // tall piece of text on another tab
732 wxSize s
= GetTabSize(dc
,
737 wxAUI_BUTTON_STATE_HIDDEN
,
740 max_y
= wxMax(max_y
, s
.y
);
746 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
748 m_normal_font
= font
;
751 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
753 m_selected_font
= font
;
756 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
758 m_measuring_font
= font
;
762 // -- wxAuiSimpleTabArt class implementation --
764 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
766 m_normal_font
= *wxNORMAL_FONT
;
767 m_selected_font
= *wxNORMAL_FONT
;
768 m_selected_font
.SetWeight(wxBOLD
);
769 m_measuring_font
= m_selected_font
;
772 m_fixed_tab_width
= 100;
774 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
776 wxColour background_colour
= base_colour
;
777 wxColour normaltab_colour
= base_colour
;
778 wxColour selectedtab_colour
= *wxWHITE
;
780 m_bkbrush
= wxBrush(background_colour
);
781 m_normal_bkbrush
= wxBrush(normaltab_colour
);
782 m_normal_bkpen
= wxPen(normaltab_colour
);
783 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
784 m_selected_bkpen
= wxPen(selectedtab_colour
);
786 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
787 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
789 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
790 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
792 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
793 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
795 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
796 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
800 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
804 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
806 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
810 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
815 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
818 m_fixed_tab_width
= 100;
820 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
822 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
823 tot_width
-= m_active_close_bmp
.GetWidth();
824 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
825 tot_width
-= m_active_windowlist_bmp
.GetWidth();
829 m_fixed_tab_width
= tot_width
/(int)tab_count
;
833 if (m_fixed_tab_width
< 100)
834 m_fixed_tab_width
= 100;
836 if (m_fixed_tab_width
> tot_width
/2)
837 m_fixed_tab_width
= tot_width
/2;
839 if (m_fixed_tab_width
> 220)
840 m_fixed_tab_width
= 220;
843 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
844 wxWindow
* WXUNUSED(wnd
),
848 dc
.SetBrush(m_bkbrush
);
849 dc
.SetPen(*wxTRANSPARENT_PEN
);
850 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
853 dc
.SetPen(*wxGREY_PEN
);
854 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
858 // DrawTab() draws an individual tab.
861 // in_rect - rectangle the tab should be confined to
862 // caption - tab's caption
863 // active - whether or not the tab is active
864 // out_rect - actual output rectangle
865 // x_extent - the advance x; where the next tab should start
867 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
869 const wxAuiNotebookPage
& page
,
870 const wxRect
& in_rect
,
871 int close_button_state
,
872 wxRect
* out_tab_rect
,
873 wxRect
* out_button_rect
,
876 wxCoord normal_textx
, normal_texty
;
877 wxCoord selected_textx
, selected_texty
;
878 wxCoord textx
, texty
;
880 // if the caption is empty, measure some temporary text
881 wxString caption
= page
.caption
;
885 dc
.SetFont(m_selected_font
);
886 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
888 dc
.SetFont(m_normal_font
);
889 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
891 // figure out the size of the tab
892 wxSize tab_size
= GetTabSize(dc
,
900 wxCoord tab_height
= tab_size
.y
;
901 wxCoord tab_width
= tab_size
.x
;
902 wxCoord tab_x
= in_rect
.x
;
903 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
905 caption
= page
.caption
;
907 // select pen, brush and font for the tab to be drawn
911 dc
.SetPen(m_selected_bkpen
);
912 dc
.SetBrush(m_selected_bkbrush
);
913 dc
.SetFont(m_selected_font
);
914 textx
= selected_textx
;
915 texty
= selected_texty
;
919 dc
.SetPen(m_normal_bkpen
);
920 dc
.SetBrush(m_normal_bkbrush
);
921 dc
.SetFont(m_normal_font
);
922 textx
= normal_textx
;
923 texty
= normal_texty
;
931 points
[0].y
= tab_y
+ tab_height
- 1;
932 points
[1].x
= tab_x
+ tab_height
- 3;
933 points
[1].y
= tab_y
+ 2;
934 points
[2].x
= tab_x
+ tab_height
+ 3;
936 points
[3].x
= tab_x
+ tab_width
- 2;
938 points
[4].x
= tab_x
+ tab_width
;
939 points
[4].y
= tab_y
+ 2;
940 points
[5].x
= tab_x
+ tab_width
;
941 points
[5].y
= tab_y
+ tab_height
- 1;
942 points
[6] = points
[0];
944 dc
.SetClippingRegion(in_rect
);
946 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
948 dc
.SetPen(*wxGREY_PEN
);
950 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
951 dc
.DrawLines(WXSIZEOF(points
), points
);
956 int close_button_width
= 0;
957 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
959 close_button_width
= m_active_close_bmp
.GetWidth();
960 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
964 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
967 // set minimum text offset
968 if (text_offset
< tab_x
+ tab_height
)
969 text_offset
= tab_x
+ tab_height
;
971 // chop text if necessary
972 wxString draw_text
= wxAuiChopText(dc
,
974 tab_width
- (text_offset
-tab_x
) - close_button_width
);
977 dc
.DrawText(draw_text
,
979 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
982 // draw close button if necessary
983 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
987 bmp
= m_active_close_bmp
;
989 bmp
= m_disabled_close_bmp
;
991 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
992 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
995 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
997 *out_button_rect
= rect
;
1001 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1003 dc
.DestroyClippingRegion();
1006 int wxAuiSimpleTabArt::GetIndentSize()
1011 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1012 wxWindow
* WXUNUSED(wnd
),
1013 const wxString
& caption
,
1014 const wxBitmap
& WXUNUSED(bitmap
),
1015 bool WXUNUSED(active
),
1016 int close_button_state
,
1019 wxCoord measured_textx
, measured_texty
;
1021 dc
.SetFont(m_measuring_font
);
1022 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1024 wxCoord tab_height
= measured_texty
+ 4;
1025 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1027 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1028 tab_width
+= m_active_close_bmp
.GetWidth();
1030 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1032 tab_width
= m_fixed_tab_width
;
1035 *x_extent
= tab_width
- (tab_height
/2) - 1;
1037 return wxSize(tab_width
, tab_height
);
1041 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1042 wxWindow
* WXUNUSED(wnd
),
1043 const wxRect
& in_rect
,
1054 case wxAUI_BUTTON_CLOSE
:
1055 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1056 bmp
= m_disabled_close_bmp
;
1058 bmp
= m_active_close_bmp
;
1060 case wxAUI_BUTTON_LEFT
:
1061 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1062 bmp
= m_disabled_left_bmp
;
1064 bmp
= m_active_left_bmp
;
1066 case wxAUI_BUTTON_RIGHT
:
1067 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1068 bmp
= m_disabled_right_bmp
;
1070 bmp
= m_active_right_bmp
;
1072 case wxAUI_BUTTON_WINDOWLIST
:
1073 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1074 bmp
= m_disabled_windowlist_bmp
;
1076 bmp
= m_active_windowlist_bmp
;
1085 if (orientation
== wxLEFT
)
1087 rect
.SetX(in_rect
.x
);
1088 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1089 rect
.SetWidth(bmp
.GetWidth());
1090 rect
.SetHeight(bmp
.GetHeight());
1094 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1095 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1096 bmp
.GetWidth(), bmp
.GetHeight());
1100 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1106 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1107 const wxAuiNotebookPageArray
& pages
,
1112 size_t i
, count
= pages
.GetCount();
1113 for (i
= 0; i
< count
; ++i
)
1115 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1116 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1119 if (active_idx
!= -1)
1121 menuPopup
.Check(1000+active_idx
, true);
1124 // find out where to put the popup menu of window
1125 // items. Subtract 100 for now to center the menu
1126 // a bit, until a better mechanism can be implemented
1127 wxPoint pt
= ::wxGetMousePosition();
1128 pt
= wnd
->ScreenToClient(pt
);
1134 // find out the screen coordinate at the bottom of the tab ctrl
1135 wxRect cli_rect
= wnd
->GetClientRect();
1136 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1138 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1139 wnd
->PushEventHandler(cc
);
1140 wnd
->PopupMenu(&menuPopup
, pt
);
1141 int command
= cc
->GetCommandId();
1142 wnd
->PopEventHandler(true);
1144 if (command
>= 1000)
1145 return command
-1000;
1150 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1151 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1152 const wxSize
& WXUNUSED(required_bmp_size
))
1155 dc
.SetFont(m_measuring_font
);
1157 wxSize s
= GetTabSize(dc
,
1162 wxAUI_BUTTON_STATE_HIDDEN
,
1167 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1169 m_normal_font
= font
;
1172 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1174 m_selected_font
= font
;
1177 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1179 m_measuring_font
= font
;
1185 // -- wxAuiTabContainer class implementation --
1188 // wxAuiTabContainer is a class which contains information about each
1189 // tab. It also can render an entire tab control to a specified DC.
1190 // It's not a window class itself, because this code will be used by
1191 // the wxFrameMananger, where it is disadvantageous to have separate
1192 // windows for each tab control in the case of "docked tabs"
1194 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1195 // which can be used as a tab control in the normal sense.
1198 wxAuiTabContainer::wxAuiTabContainer()
1202 m_art
= new wxAuiDefaultTabArt
;
1204 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1205 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1206 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1207 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1210 wxAuiTabContainer::~wxAuiTabContainer()
1215 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1222 m_art
->SetFlags(m_flags
);
1226 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1231 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1235 // check for new close button settings
1236 RemoveButton(wxAUI_BUTTON_LEFT
);
1237 RemoveButton(wxAUI_BUTTON_RIGHT
);
1238 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1239 RemoveButton(wxAUI_BUTTON_CLOSE
);
1242 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1244 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1245 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1248 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1250 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1253 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1255 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1260 m_art
->SetFlags(m_flags
);
1264 unsigned int wxAuiTabContainer::GetFlags() const
1270 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1272 m_art
->SetNormalFont(font
);
1275 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1277 m_art
->SetSelectedFont(font
);
1280 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1282 m_art
->SetMeasuringFont(font
);
1285 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1291 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1295 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1296 const wxAuiNotebookPage
& info
)
1298 wxAuiNotebookPage page_info
;
1300 page_info
.window
= page
;
1302 m_pages
.Add(page_info
);
1304 // let the art provider know how many pages we have
1307 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1313 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1314 const wxAuiNotebookPage
& info
,
1317 wxAuiNotebookPage page_info
;
1319 page_info
.window
= page
;
1321 if (idx
>= m_pages
.GetCount())
1322 m_pages
.Add(page_info
);
1324 m_pages
.Insert(page_info
, idx
);
1326 // let the art provider know how many pages we have
1329 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1335 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1338 int idx
= GetIdxFromWindow(page
);
1342 // get page entry, make a copy of it
1343 wxAuiNotebookPage p
= GetPage(idx
);
1345 // remove old page entry
1348 // insert page where it should be
1349 InsertPage(page
, p
, new_idx
);
1354 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1356 size_t i
, page_count
= m_pages
.GetCount();
1357 for (i
= 0; i
< page_count
; ++i
)
1359 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1360 if (page
.window
== wnd
)
1362 m_pages
.RemoveAt(i
);
1364 // let the art provider know how many pages we have
1367 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1377 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1381 size_t i
, page_count
= m_pages
.GetCount();
1382 for (i
= 0; i
< page_count
; ++i
)
1384 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1385 if (page
.window
== wnd
)
1392 page
.active
= false;
1399 void wxAuiTabContainer::SetNoneActive()
1401 size_t i
, page_count
= m_pages
.GetCount();
1402 for (i
= 0; i
< page_count
; ++i
)
1404 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1405 page
.active
= false;
1409 bool wxAuiTabContainer::SetActivePage(size_t page
)
1411 if (page
>= m_pages
.GetCount())
1414 return SetActivePage(m_pages
.Item(page
).window
);
1417 int wxAuiTabContainer::GetActivePage() const
1419 size_t i
, page_count
= m_pages
.GetCount();
1420 for (i
= 0; i
< page_count
; ++i
)
1422 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1430 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1432 if (idx
>= m_pages
.GetCount())
1435 return m_pages
[idx
].window
;
1438 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1440 size_t i
, page_count
= m_pages
.GetCount();
1441 for (i
= 0; i
< page_count
; ++i
)
1443 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1444 if (page
.window
== wnd
)
1450 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1452 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1454 return m_pages
[idx
];
1457 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1462 size_t wxAuiTabContainer::GetPageCount() const
1464 return m_pages
.GetCount();
1467 void wxAuiTabContainer::AddButton(int id
,
1469 const wxBitmap
& normal_bitmap
,
1470 const wxBitmap
& disabled_bitmap
)
1472 wxAuiTabContainerButton button
;
1474 button
.bitmap
= normal_bitmap
;
1475 button
.dis_bitmap
= disabled_bitmap
;
1476 button
.location
= location
;
1477 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1479 m_buttons
.Add(button
);
1482 void wxAuiTabContainer::RemoveButton(int id
)
1484 size_t i
, button_count
= m_buttons
.GetCount();
1486 for (i
= 0; i
< button_count
; ++i
)
1488 if (m_buttons
.Item(i
).id
== id
)
1490 m_buttons
.RemoveAt(i
);
1498 size_t wxAuiTabContainer::GetTabOffset() const
1500 return m_tab_offset
;
1503 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1505 m_tab_offset
= offset
;
1511 // Render() renders the tab catalog to the specified DC
1512 // It is a virtual function and can be overridden to
1513 // provide custom drawing capabilities
1514 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1516 if (!raw_dc
|| !raw_dc
->IsOk())
1522 size_t page_count
= m_pages
.GetCount();
1523 size_t button_count
= m_buttons
.GetCount();
1525 // create off-screen bitmap
1526 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1527 dc
.SelectObject(bmp
);
1532 // find out if size of tabs is larger than can be
1533 // afforded on screen
1534 int total_width
= 0;
1535 int visible_width
= 0;
1536 for (i
= 0; i
< page_count
; ++i
)
1538 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1540 // determine if a close button is on this tab
1541 bool close_button
= false;
1542 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1543 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1545 close_button
= true;
1550 wxSize size
= m_art
->GetTabSize(dc
,
1556 wxAUI_BUTTON_STATE_NORMAL
:
1557 wxAUI_BUTTON_STATE_HIDDEN
,
1560 if (i
+1 < page_count
)
1561 total_width
+= x_extent
;
1563 total_width
+= size
.x
;
1565 if (i
>= m_tab_offset
)
1567 if (i
+1 < page_count
)
1568 visible_width
+= x_extent
;
1570 visible_width
+= size
.x
;
1574 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1576 // show left/right buttons
1577 for (i
= 0; i
< button_count
; ++i
)
1579 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1580 if (button
.id
== wxAUI_BUTTON_LEFT
||
1581 button
.id
== wxAUI_BUTTON_RIGHT
)
1583 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1589 // hide left/right buttons
1590 for (i
= 0; i
< button_count
; ++i
)
1592 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1593 if (button
.id
== wxAUI_BUTTON_LEFT
||
1594 button
.id
== wxAUI_BUTTON_RIGHT
)
1596 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1601 // determine whether left button should be enabled
1602 for (i
= 0; i
< button_count
; ++i
)
1604 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1605 if (button
.id
== wxAUI_BUTTON_LEFT
)
1607 if (m_tab_offset
== 0)
1608 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1610 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1612 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1614 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1615 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1617 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1624 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1627 int left_buttons_width
= 0;
1628 int right_buttons_width
= 0;
1632 // draw the buttons on the right side
1633 offset
= m_rect
.x
+ m_rect
.width
;
1634 for (i
= 0; i
< button_count
; ++i
)
1636 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1638 if (button
.location
!= wxRIGHT
)
1640 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1643 wxRect button_rect
= m_rect
;
1644 button_rect
.SetY(1);
1645 button_rect
.SetWidth(offset
);
1647 m_art
->DrawButton(dc
,
1655 offset
-= button
.rect
.GetWidth();
1656 right_buttons_width
+= button
.rect
.GetWidth();
1663 // draw the buttons on the left side
1665 for (i
= 0; i
< button_count
; ++i
)
1667 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1669 if (button
.location
!= wxLEFT
)
1671 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1674 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1676 m_art
->DrawButton(dc
,
1684 offset
+= button
.rect
.GetWidth();
1685 left_buttons_width
+= button
.rect
.GetWidth();
1688 offset
= left_buttons_width
;
1691 offset
+= m_art
->GetIndentSize();
1694 // prepare the tab-close-button array
1695 // make sure tab button entries which aren't used are marked as hidden
1696 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1697 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1699 // make sure there are enough tab button entries to accommodate all tabs
1700 while (m_tab_close_buttons
.GetCount() < page_count
)
1702 wxAuiTabContainerButton tempbtn
;
1703 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1704 tempbtn
.location
= wxCENTER
;
1705 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1706 m_tab_close_buttons
.Add(tempbtn
);
1710 // buttons before the tab offset must be set to hidden
1711 for (i
= 0; i
< m_tab_offset
; ++i
)
1713 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1719 size_t active
= 999;
1720 int active_offset
= 0;
1724 wxRect rect
= m_rect
;
1726 rect
.height
= m_rect
.height
;
1728 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1730 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1731 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1733 // determine if a close button is on this tab
1734 bool close_button
= false;
1735 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1736 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1738 close_button
= true;
1739 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1741 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1742 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1743 tab_button
.location
= wxCENTER
;
1748 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1752 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1754 if (rect
.width
<= 0)
1761 tab_button
.cur_state
,
1769 active_offset
= offset
;
1777 // make sure to deactivate buttons which are off the screen to the right
1778 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1780 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1784 // draw the active tab again so it stands in the foreground
1785 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1787 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1789 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1791 // determine if a close button is on this tab
1792 bool close_button
= false;
1793 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1794 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1796 close_button
= true;
1799 rect
.x
= active_offset
;
1804 tab_button
.cur_state
,
1811 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1812 m_rect
.GetWidth(), m_rect
.GetHeight(),
1817 // TabHitTest() tests if a tab was hit, passing the window pointer
1818 // back if that condition was fulfilled. The function returns
1819 // true if a tab was hit, otherwise false
1820 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1822 if (!m_rect
.Contains(x
,y
))
1825 wxAuiTabContainerButton
* btn
= NULL
;
1826 if (ButtonHitTest(x
, y
, &btn
))
1828 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1832 size_t i
, page_count
= m_pages
.GetCount();
1834 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1836 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1837 if (page
.rect
.Contains(x
,y
))
1848 // ButtonHitTest() tests if a button was hit. The function returns
1849 // true if a button was hit, otherwise false
1850 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1851 wxAuiTabContainerButton
** hit
) const
1853 if (!m_rect
.Contains(x
,y
))
1856 size_t i
, button_count
;
1859 button_count
= m_buttons
.GetCount();
1860 for (i
= 0; i
< button_count
; ++i
)
1862 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1863 if (button
.rect
.Contains(x
,y
) &&
1864 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1865 wxAUI_BUTTON_STATE_DISABLED
)))
1873 button_count
= m_tab_close_buttons
.GetCount();
1874 for (i
= 0; i
< button_count
; ++i
)
1876 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1877 if (button
.rect
.Contains(x
,y
) &&
1878 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1879 wxAUI_BUTTON_STATE_DISABLED
)))
1892 // the utility function ShowWnd() is the same as show,
1893 // except it handles wxAuiMDIChildFrame windows as well,
1894 // as the Show() method on this class is "unplugged"
1895 static void ShowWnd(wxWindow
* wnd
, bool show
)
1897 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1899 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1909 // DoShowHide() this function shows the active window, then
1910 // hides all of the other windows (in that order)
1911 void wxAuiTabContainer::DoShowHide()
1913 wxAuiNotebookPageArray
& pages
= GetPages();
1914 size_t i
, page_count
= pages
.GetCount();
1916 // show new active page first
1917 for (i
= 0; i
< page_count
; ++i
)
1919 wxAuiNotebookPage
& page
= pages
.Item(i
);
1922 ShowWnd(page
.window
, true);
1927 // hide all other pages
1928 for (i
= 0; i
< page_count
; ++i
)
1930 wxAuiNotebookPage
& page
= pages
.Item(i
);
1931 ShowWnd(page
.window
, page
.active
);
1940 // -- wxAuiTabCtrl class implementation --
1944 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1945 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1946 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1947 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1948 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1949 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1950 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1951 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1952 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1953 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1957 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1961 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1963 m_click_pt
= wxDefaultPosition
;
1964 m_is_dragging
= false;
1965 m_hover_button
= NULL
;
1966 m_pressed_button
= NULL
;
1969 wxAuiTabCtrl::~wxAuiTabCtrl()
1973 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1977 dc
.SetFont(GetFont());
1979 if (GetPageCount() > 0)
1983 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1987 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1989 wxSize s
= evt
.GetSize();
1990 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1994 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1997 m_click_pt
= wxDefaultPosition
;
1998 m_is_dragging
= false;
2000 m_pressed_button
= NULL
;
2004 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2006 int new_selection
= GetIdxFromWindow(wnd
);
2008 // wxAuiNotebooks always want to receive this event
2009 // even if the tab is already active, because they may
2010 // have multiple tab controls
2011 if (new_selection
!= GetActivePage() ||
2012 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2014 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2015 e
.SetSelection(new_selection
);
2016 e
.SetOldSelection(GetActivePage());
2017 e
.SetEventObject(this);
2018 GetEventHandler()->ProcessEvent(e
);
2021 m_click_pt
.x
= evt
.m_x
;
2022 m_click_pt
.y
= evt
.m_y
;
2028 m_pressed_button
= m_hover_button
;
2029 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2035 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2037 if (GetCapture() == this)
2042 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2043 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2044 evt
.SetOldSelection(evt
.GetSelection());
2045 evt
.SetEventObject(this);
2046 GetEventHandler()->ProcessEvent(evt
);
2050 if (m_pressed_button
)
2052 // make sure we're still clicking the button
2053 wxAuiTabContainerButton
* button
= NULL
;
2054 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2057 if (button
!= m_pressed_button
)
2059 m_pressed_button
= NULL
;
2066 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2068 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2069 evt
.SetInt(m_pressed_button
->id
);
2070 evt
.SetEventObject(this);
2071 GetEventHandler()->ProcessEvent(evt
);
2074 m_pressed_button
= NULL
;
2077 m_click_pt
= wxDefaultPosition
;
2078 m_is_dragging
= false;
2082 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2084 wxPoint pos
= evt
.GetPosition();
2086 // check if the mouse is hovering above a button
2087 wxAuiTabContainerButton
* button
;
2088 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2090 if (m_hover_button
&& button
!= m_hover_button
)
2092 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2093 m_hover_button
= NULL
;
2098 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2100 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2103 m_hover_button
= button
;
2111 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2112 m_hover_button
= NULL
;
2119 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2124 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2125 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2126 evt
.SetOldSelection(evt
.GetSelection());
2127 evt
.SetEventObject(this);
2128 GetEventHandler()->ProcessEvent(evt
);
2133 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2134 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2136 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2137 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2139 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2140 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2141 evt
.SetOldSelection(evt
.GetSelection());
2142 evt
.SetEventObject(this);
2143 GetEventHandler()->ProcessEvent(evt
);
2145 m_is_dragging
= true;
2149 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2153 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2154 m_hover_button
= NULL
;
2160 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2162 int button
= event
.GetInt();
2164 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2166 if (button
== wxAUI_BUTTON_LEFT
)
2168 if (GetTabOffset() > 0)
2170 SetTabOffset(GetTabOffset()-1);
2177 SetTabOffset(GetTabOffset()+1);
2182 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2184 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2188 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2189 e
.SetSelection(idx
);
2190 e
.SetOldSelection(GetActivePage());
2191 e
.SetEventObject(this);
2192 GetEventHandler()->ProcessEvent(e
);
2201 // wxTabFrame is an interesting case. It's important that all child pages
2202 // of the multi-notebook control are all actually children of that control
2203 // (and not grandchildren). wxTabFrame facilitates this. There is one
2204 // instance of wxTabFrame for each tab control inside the multi-notebook.
2205 // It's important to know that wxTabFrame is not a real window, but it merely
2206 // used to capture the dimensions/positioning of the internal tab control and
2207 // it's managed page windows
2209 class wxTabFrame
: public wxWindow
2216 m_rect
= wxRect(0,0,200,200);
2217 m_tab_ctrl_height
= 20;
2220 void SetTabCtrlHeight(int h
)
2222 m_tab_ctrl_height
= h
;
2225 void DoSetSize(int x
, int y
,
2226 int width
, int height
,
2227 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2229 m_rect
= wxRect(x
, y
, width
, height
);
2233 void DoGetClientSize(int* x
, int* y
) const
2239 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2246 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2247 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2248 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2252 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2253 size_t i
, page_count
= pages
.GetCount();
2255 for (i
= 0; i
< page_count
; ++i
)
2257 wxAuiNotebookPage
& page
= pages
.Item(i
);
2258 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2259 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2261 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2263 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2264 wnd
->ApplyMDIChildFrameRect();
2269 void DoGetSize(int* x
, int* y
) const
2272 *x
= m_rect
.GetWidth();
2274 *y
= m_rect
.GetHeight();
2286 wxAuiTabCtrl
* m_tabs
;
2287 int m_tab_ctrl_height
;
2291 const int wxAuiBaseTabCtrlId
= 5380;
2294 // -- wxAuiNotebook class implementation --
2296 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2297 EVT_SIZE(wxAuiNotebook::OnSize
)
2298 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2299 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2300 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2301 wxAuiNotebook::OnTabClicked
)
2302 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2303 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2304 wxAuiNotebook::OnTabBeginDrag
)
2305 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2306 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2307 wxAuiNotebook::OnTabEndDrag
)
2308 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2309 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2310 wxAuiNotebook::OnTabDragMotion
)
2311 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2312 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2313 wxAuiNotebook::OnTabButton
)
2316 wxAuiNotebook::wxAuiNotebook()
2319 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2321 m_tab_ctrl_height
= 20;
2322 m_requested_bmp_size
= wxDefaultSize
;
2323 m_requested_tabctrl_height
= -1;
2326 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2330 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2333 m_requested_bmp_size
= wxDefaultSize
;
2334 m_requested_tabctrl_height
= -1;
2335 InitNotebook(style
);
2338 bool wxAuiNotebook::Create(wxWindow
* parent
,
2344 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2347 InitNotebook(style
);
2352 // InitNotebook() contains common initialization
2353 // code called by all constructors
2354 void wxAuiNotebook::InitNotebook(long style
)
2357 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2359 m_flags
= (unsigned int)style
;
2360 m_tab_ctrl_height
= 20;
2362 m_normal_font
= *wxNORMAL_FONT
;
2363 m_selected_font
= *wxNORMAL_FONT
;
2364 m_selected_font
.SetWeight(wxBOLD
);
2366 SetArtProvider(new wxAuiDefaultTabArt
);
2368 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2369 m_dummy_wnd
->SetSize(200, 200);
2370 m_dummy_wnd
->Show(false);
2372 m_mgr
.SetManagedWindow(this);
2373 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2374 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2376 m_mgr
.AddPane(m_dummy_wnd
,
2377 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2382 wxAuiNotebook::~wxAuiNotebook()
2387 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2389 m_tabs
.SetArtProvider(art
);
2391 UpdateTabCtrlHeight();
2394 // SetTabCtrlHeight() is the highest-level override of the
2395 // tab height. A call to this function effectively enforces a
2396 // specified tab ctrl height, overriding all other considerations,
2397 // such as text or bitmap height. It overrides any call to
2398 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2399 // any previous call and returns to the default behavior
2401 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2403 m_requested_tabctrl_height
= height
;
2405 // if window is already initialized, recalculate the tab height
2408 UpdateTabCtrlHeight();
2413 // SetUniformBitmapSize() ensures that all tabs will have
2414 // the same height, even if some tabs don't have bitmaps
2415 // Passing wxDefaultSize to this function will instruct
2416 // the control to use dynamic tab height-- so when a tab
2417 // with a large bitmap is added, the tab ctrl's height will
2418 // automatically increase to accommodate the bitmap
2420 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2422 m_requested_bmp_size
= size
;
2424 // if window is already initialized, recalculate the tab height
2427 UpdateTabCtrlHeight();
2431 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2432 // to be used interally
2433 void wxAuiNotebook::UpdateTabCtrlHeight()
2435 // get the tab ctrl height we will use
2436 int height
= CalculateTabCtrlHeight();
2438 // if the tab control height needs to change, update
2439 // all of our tab controls with the new height
2440 if (m_tab_ctrl_height
!= height
)
2442 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2444 m_tab_ctrl_height
= height
;
2446 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2447 size_t i
, pane_count
= all_panes
.GetCount();
2448 for (i
= 0; i
< pane_count
; ++i
)
2450 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2451 if (pane
.name
== wxT("dummy"))
2453 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2454 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2455 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2456 tabctrl
->SetArtProvider(art
->Clone());
2457 tab_frame
->DoSizing();
2462 void wxAuiNotebook::UpdateHintWindowSize()
2464 wxSize size
= CalculateNewSplitSize();
2466 // the placeholder hint window should be set to this size
2467 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2471 info
.BestSize(size
);
2472 m_dummy_wnd
->SetSize(size
);
2477 // calculates the size of the new split
2478 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2480 // count number of tab controls
2481 int tab_ctrl_count
= 0;
2482 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2483 size_t i
, pane_count
= all_panes
.GetCount();
2484 for (i
= 0; i
< pane_count
; ++i
)
2486 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2487 if (pane
.name
== wxT("dummy"))
2492 wxSize new_split_size
;
2494 // if there is only one tab control, the first split
2495 // should happen around the middle
2496 if (tab_ctrl_count
< 2)
2498 new_split_size
= GetClientSize();
2499 new_split_size
.x
/= 2;
2500 new_split_size
.y
/= 2;
2504 // this is in place of a more complicated calculation
2505 // that needs to be implemented
2506 new_split_size
= wxSize(180,180);
2509 return new_split_size
;
2512 int wxAuiNotebook::CalculateTabCtrlHeight()
2514 // if a fixed tab ctrl height is specified,
2515 // just return that instead of calculating a
2517 if (m_requested_tabctrl_height
!= -1)
2518 return m_requested_tabctrl_height
;
2520 // find out new best tab height
2521 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2523 return art
->GetBestTabCtrlSize(this,
2525 m_requested_bmp_size
);
2529 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2531 return m_tabs
.GetArtProvider();
2534 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2536 wxControl::SetWindowStyleFlag(style
);
2538 m_flags
= (unsigned int)style
;
2540 // if the control is already initialized
2541 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2543 // let all of the tab children know about the new style
2545 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2546 size_t i
, pane_count
= all_panes
.GetCount();
2547 for (i
= 0; i
< pane_count
; ++i
)
2549 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2550 if (pane
.name
== wxT("dummy"))
2552 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2553 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2554 tabctrl
->SetFlags(m_flags
);
2555 tabframe
->DoSizing();
2563 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2564 const wxString
& caption
,
2566 const wxBitmap
& bitmap
)
2568 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2571 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2573 const wxString
& caption
,
2575 const wxBitmap
& bitmap
)
2577 wxAuiNotebookPage info
;
2579 info
.caption
= caption
;
2580 info
.bitmap
= bitmap
;
2581 info
.active
= false;
2583 // if there are currently no tabs, the first added
2584 // tab must be active
2585 if (m_tabs
.GetPageCount() == 0)
2588 m_tabs
.InsertPage(page
, info
, page_idx
);
2590 // if that was the first page added, even if
2591 // select is false, it must become the "current page"
2592 // (though no select events will be fired)
2593 if (!select
&& m_tabs
.GetPageCount() == 1)
2594 m_curpage
= GetPageIndex(page
);
2596 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2597 if (page_idx
>= active_tabctrl
->GetPageCount())
2598 active_tabctrl
->AddPage(page
, info
);
2600 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2602 UpdateTabCtrlHeight();
2604 active_tabctrl
->DoShowHide();
2608 int idx
= m_tabs
.GetIdxFromWindow(page
);
2609 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2618 // DeletePage() removes a tab from the multi-notebook,
2619 // and destroys the window as well
2620 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2622 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2624 if (!RemovePage(page_idx
))
2627 // actually destroy the window now
2628 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2630 // delete the child frame with pending delete, as is
2631 // customary with frame windows
2632 if (!wxPendingDelete
.Member(wnd
))
2633 wxPendingDelete
.Append(wnd
);
2645 // RemovePage() removes a tab from the multi-notebook,
2646 // but does not destroy the window
2647 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2649 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2650 wxWindow
* new_active
= NULL
;
2652 // find out which onscreen tab ctrl owns this tab
2655 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2658 // find a new page and set it as active
2659 int new_idx
= ctrl_idx
+1;
2660 if (new_idx
>= (int)ctrl
->GetPageCount())
2661 new_idx
= ctrl_idx
-1;
2663 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2665 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2669 // set the active page to the first page that
2670 // isn't the one being deleted
2671 size_t i
, page_count
= m_tabs
.GetPageCount();
2672 for (i
= 0; i
< page_count
; ++i
)
2674 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2677 new_active
= m_tabs
.GetWindowFromIdx(i
);
2683 // remove the tab from main catalog
2684 if (!m_tabs
.RemovePage(wnd
))
2687 // remove the tab from the onscreen tab ctrl
2688 ctrl
->RemovePage(wnd
);
2691 RemoveEmptyTabFrames();
2693 // set new active pane
2697 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2703 // GetPageIndex() returns the index of the page, or -1 if the
2704 // page could not be located in the notebook
2705 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2707 return m_tabs
.GetIdxFromWindow(page_wnd
);
2712 // SetPageText() changes the tab caption of the specified page
2713 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2715 if (page_idx
>= m_tabs
.GetPageCount())
2718 // update our own tab catalog
2719 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2720 page_info
.caption
= text
;
2722 // update what's on screen
2725 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2727 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2728 info
.caption
= text
;
2737 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2739 if (page_idx
>= m_tabs
.GetPageCount())
2742 // update our own tab catalog
2743 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2744 page_info
.bitmap
= bitmap
;
2746 // tab height might have changed
2747 UpdateTabCtrlHeight();
2749 // update what's on screen
2752 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2754 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2755 info
.bitmap
= bitmap
;
2764 // GetSelection() returns the index of the currently active page
2765 int wxAuiNotebook::GetSelection() const
2770 // SetSelection() sets the currently active page
2771 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2773 // don't change the page unless necessary
2774 if (new_page
== m_curpage
)
2777 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2781 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2782 evt
.SetSelection(new_page
);
2783 evt
.SetOldSelection(m_curpage
);
2784 evt
.SetEventObject(this);
2785 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2787 int old_curpage
= m_curpage
;
2788 m_curpage
= new_page
;
2790 // program allows the page change
2791 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2792 (void)GetEventHandler()->ProcessEvent(evt
);
2797 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2799 m_tabs
.SetActivePage(wnd
);
2801 ctrl
->SetActivePage(ctrl_idx
);
2808 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2809 size_t i
, pane_count
= all_panes
.GetCount();
2810 for (i
= 0; i
< pane_count
; ++i
)
2812 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2813 if (pane
.name
== wxT("dummy"))
2815 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2816 if (tabctrl
!= ctrl
)
2817 tabctrl
->SetSelectedFont(m_normal_font
);
2819 tabctrl
->SetSelectedFont(m_selected_font
);
2832 // GetPageCount() returns the total number of
2833 // pages managed by the multi-notebook
2834 size_t wxAuiNotebook::GetPageCount() const
2836 return m_tabs
.GetPageCount();
2839 // GetPage() returns the wxWindow pointer of the
2841 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2843 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2845 return m_tabs
.GetWindowFromIdx(page_idx
);
2848 // DoSizing() performs all sizing operations in each tab control
2849 void wxAuiNotebook::DoSizing()
2851 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2852 size_t i
, pane_count
= all_panes
.GetCount();
2853 for (i
= 0; i
< pane_count
; ++i
)
2855 if (all_panes
.Item(i
).name
== wxT("dummy"))
2858 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2859 tabframe
->DoSizing();
2863 // GetActiveTabCtrl() returns the active tab control. It is
2864 // called to determine which control gets new windows being added
2865 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2867 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2872 // find the tab ctrl with the current page
2873 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2880 // no current page, just find the first tab ctrl
2881 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2882 size_t i
, pane_count
= all_panes
.GetCount();
2883 for (i
= 0; i
< pane_count
; ++i
)
2885 if (all_panes
.Item(i
).name
== wxT("dummy"))
2888 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2889 return tabframe
->m_tabs
;
2892 // If there is no tabframe at all, create one
2893 wxTabFrame
* tabframe
= new wxTabFrame
;
2894 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2895 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2900 tabframe
->m_tabs
->SetFlags(m_flags
);
2901 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2902 m_mgr
.AddPane(tabframe
,
2903 wxAuiPaneInfo().Center().CaptionVisible(false));
2907 return tabframe
->m_tabs
;
2910 // FindTab() finds the tab control that currently contains the window as well
2911 // as the index of the window in the tab control. It returns true if the
2912 // window was found, otherwise false.
2913 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2915 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2916 size_t i
, pane_count
= all_panes
.GetCount();
2917 for (i
= 0; i
< pane_count
; ++i
)
2919 if (all_panes
.Item(i
).name
== wxT("dummy"))
2922 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2924 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2927 *ctrl
= tabframe
->m_tabs
;
2936 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
2938 UpdateHintWindowSize();
2943 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2945 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2947 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2948 wxASSERT(ctrl
!= NULL
);
2950 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2951 wxASSERT(wnd
!= NULL
);
2953 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2954 wxASSERT(idx
!= -1);
2959 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2964 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2966 wxPoint screen_pt
= ::wxGetMousePosition();
2967 wxPoint client_pt
= ScreenToClient(screen_pt
);
2970 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2971 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2973 if (dest_tabs
== src_tabs
)
2977 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2980 // always hide the hint for inner-tabctrl drag
2983 // if tab moving is not allowed, leave
2984 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2989 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2990 wxWindow
* dest_location_tab
;
2992 // this is an inner-tab drag/reposition
2993 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2995 int src_idx
= evt
.GetSelection();
2996 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2998 // prevent jumpy drag
2999 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3000 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3001 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3003 m_last_drag_x
= pt
.x
;
3008 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3009 dest_tabs
->MovePage(src_tab
, dest_idx
);
3010 dest_tabs
->SetActivePage((size_t)dest_idx
);
3011 dest_tabs
->DoShowHide();
3012 dest_tabs
->Refresh();
3013 m_last_drag_x
= pt
.x
;
3021 // if external drag is allowed, check if the tab is being dragged
3022 // over a different wxAuiNotebook control
3023 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3025 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3027 // if we aren't over any window, stop here
3031 // make sure we are not over the hint window
3032 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3036 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3038 tab_ctrl
= tab_ctrl
->GetParent();
3043 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3047 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3048 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3049 m_mgr
.ShowHint(hint_rect
);
3058 // we are either over a hint window, or not over a tab
3059 // window, and there is no where to drag to, so exit
3066 // if there are less than two panes, split can't happen, so leave
3067 if (m_tabs
.GetPageCount() < 2)
3070 // if tab moving is not allowed, leave
3071 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3077 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3083 wxRect hint_rect
= dest_tabs
->GetRect();
3084 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3085 m_mgr
.ShowHint(hint_rect
);
3089 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3095 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3097 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3102 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3103 wxAuiTabCtrl
* dest_tabs
= NULL
;
3106 // set cursor back to an arrow
3107 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3110 // get the mouse position, which will be used to determine the drop point
3111 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3112 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3116 // check for an external move
3117 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3119 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3123 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3125 tab_ctrl
= tab_ctrl
->GetParent();
3130 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3134 // find out from the destination control
3135 // if it's ok to drop this tab here
3136 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3137 e
.SetSelection(evt
.GetSelection());
3138 e
.SetOldSelection(evt
.GetSelection());
3139 e
.SetEventObject(this);
3140 e
.SetDragSource(this);
3141 e
.Veto(); // dropping must be explicitly approved by control owner
3143 nb
->GetEventHandler()->ProcessEvent(e
);
3147 // no answer or negative answer
3153 int src_idx
= evt
.GetSelection();
3154 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3156 // get main index of the page
3157 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3159 // make a copy of the page info
3160 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3162 // remove the page from the source notebook
3163 RemovePage(main_idx
);
3165 // reparent the page
3166 src_page
->Reparent(nb
);
3169 // found out the insert idx
3170 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3171 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3173 wxWindow
* target
= NULL
;
3174 int insert_idx
= -1;
3175 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3178 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3182 // add the page to the new notebook
3183 if (insert_idx
== -1)
3184 insert_idx
= dest_tabs
->GetPageCount();
3185 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3186 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3189 dest_tabs
->DoShowHide();
3190 dest_tabs
->Refresh();
3192 // set the selection in the destination tab control
3193 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3203 // only perform a tab split if it's allowed
3204 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3206 // If the pointer is in an existing tab frame, do a tab insert
3207 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3208 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3209 int insert_idx
= -1;
3212 dest_tabs
= tab_frame
->m_tabs
;
3214 if (dest_tabs
== src_tabs
)
3218 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3219 wxWindow
* target
= NULL
;
3220 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3223 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3229 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3234 // there is no suitable drop location here, exit out
3238 // If there is no tabframe at all, create one
3239 wxTabFrame
* new_tabs
= new wxTabFrame
;
3240 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3241 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3242 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3247 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3248 new_tabs
->m_tabs
->SetFlags(m_flags
);
3250 m_mgr
.AddPane(new_tabs
,
3251 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3254 dest_tabs
= new_tabs
->m_tabs
;
3259 // remove the page from the source tabs
3260 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3261 page_info
.active
= false;
3262 src_tabs
->RemovePage(page_info
.window
);
3263 if (src_tabs
->GetPageCount() > 0)
3265 src_tabs
->SetActivePage((size_t)0);
3266 src_tabs
->DoShowHide();
3267 src_tabs
->Refresh();
3272 // add the page to the destination tabs
3273 if (insert_idx
== -1)
3274 insert_idx
= dest_tabs
->GetPageCount();
3275 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3277 if (src_tabs
->GetPageCount() == 0)
3279 RemoveEmptyTabFrames();
3283 dest_tabs
->DoShowHide();
3284 dest_tabs
->Refresh();
3286 // force the set selection function reset the selection
3289 // set the active page to the one we just split off
3290 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3292 UpdateHintWindowSize();
3298 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3300 // if we've just removed the last tab from the source
3301 // tab set, the remove the tab control completely
3302 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3303 size_t i
, pane_count
= all_panes
.GetCount();
3304 for (i
= 0; i
< pane_count
; ++i
)
3306 if (all_panes
.Item(i
).name
== wxT("dummy"))
3309 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3310 if (tabframe
->m_tab_rect
.Contains(pt
))
3311 return tabframe
->m_tabs
;
3317 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3319 // if we've just removed the last tab from the source
3320 // tab set, the remove the tab control completely
3321 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3322 size_t i
, pane_count
= all_panes
.GetCount();
3323 for (i
= 0; i
< pane_count
; ++i
)
3325 if (all_panes
.Item(i
).name
== wxT("dummy"))
3328 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3329 if (tabframe
->m_tabs
== tab_ctrl
)
3338 void wxAuiNotebook::RemoveEmptyTabFrames()
3340 // if we've just removed the last tab from the source
3341 // tab set, the remove the tab control completely
3342 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3343 size_t i
, pane_count
= all_panes
.GetCount();
3344 for (i
= 0; i
< pane_count
; ++i
)
3346 if (all_panes
.Item(i
).name
== wxT("dummy"))
3349 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3350 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3352 m_mgr
.DetachPane(tab_frame
);
3354 // use pending delete because sometimes during
3355 // window closing, refreshs are pending
3356 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3357 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3358 //tab_frame->m_tabs->Destroy();
3365 // check to see if there is still a center pane;
3366 // if there isn't, make a frame the center pane
3367 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3368 pane_count
= panes
.GetCount();
3369 wxWindow
* first_good
= NULL
;
3370 bool center_found
= false;
3371 for (i
= 0; i
< pane_count
; ++i
)
3373 if (panes
.Item(i
).name
== wxT("dummy"))
3375 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3376 center_found
= true;
3378 first_good
= panes
.Item(i
).window
;
3381 if (!center_found
&& first_good
)
3383 m_mgr
.GetPane(first_good
).Centre();
3389 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3391 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3392 if (idx
!= -1 && idx
!= m_curpage
)
3399 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3401 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3402 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3404 int button_id
= evt
.GetInt();
3406 if (button_id
== wxAUI_BUTTON_CLOSE
)
3408 int selection
= tabs
->GetActivePage();
3410 if (selection
!= -1)
3412 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3415 // ask owner if it's ok to close the tab
3416 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3417 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3418 e
.SetOldSelection(evt
.GetSelection());
3419 e
.SetEventObject(this);
3420 GetEventHandler()->ProcessEvent(e
);
3425 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3431 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3432 DeletePage(main_idx
);