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 if (new_selection
!= GetActivePage())
2010 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2011 e
.SetSelection(new_selection
);
2012 e
.SetOldSelection(GetActivePage());
2013 e
.SetEventObject(this);
2014 GetEventHandler()->ProcessEvent(e
);
2017 m_click_pt
.x
= evt
.m_x
;
2018 m_click_pt
.y
= evt
.m_y
;
2024 m_pressed_button
= m_hover_button
;
2025 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2031 void wxAuiTabCtrl
::OnLeftUp(wxMouseEvent
& evt
)
2033 if (GetCapture() == this)
2038 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2039 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2040 evt
.SetOldSelection(evt
.GetSelection());
2041 evt
.SetEventObject(this);
2042 GetEventHandler()->ProcessEvent(evt
);
2046 if (m_pressed_button
)
2048 // make sure we're still clicking the button
2049 wxAuiTabContainerButton
* button
= NULL
;
2050 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2053 if (button
!= m_pressed_button
)
2055 m_pressed_button
= NULL
;
2062 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2064 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2065 evt
.SetInt(m_pressed_button
->id
);
2066 evt
.SetEventObject(this);
2067 GetEventHandler()->ProcessEvent(evt
);
2070 m_pressed_button
= NULL
;
2073 m_click_pt
= wxDefaultPosition
;
2074 m_is_dragging
= false;
2078 void wxAuiTabCtrl
::OnMotion(wxMouseEvent
& evt
)
2080 wxPoint pos
= evt
.GetPosition();
2082 // check if the mouse is hovering above a button
2083 wxAuiTabContainerButton
* button
;
2084 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2086 if (m_hover_button
&& button
!= m_hover_button
)
2088 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2089 m_hover_button
= NULL
;
2094 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2096 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2099 m_hover_button
= button
;
2107 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2108 m_hover_button
= NULL
;
2115 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2120 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2121 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2122 evt
.SetOldSelection(evt
.GetSelection());
2123 evt
.SetEventObject(this);
2124 GetEventHandler()->ProcessEvent(evt
);
2129 int drag_x_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_X
);
2130 int drag_y_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_Y
);
2132 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2133 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2135 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2136 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2137 evt
.SetOldSelection(evt
.GetSelection());
2138 evt
.SetEventObject(this);
2139 GetEventHandler()->ProcessEvent(evt
);
2141 m_is_dragging
= true;
2145 void wxAuiTabCtrl
::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2149 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2150 m_hover_button
= NULL
;
2156 void wxAuiTabCtrl
::OnButton(wxAuiNotebookEvent
& event
)
2158 int button
= event
.GetInt();
2160 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2162 if (button
== wxAUI_BUTTON_LEFT
)
2164 if (GetTabOffset() > 0)
2166 SetTabOffset(GetTabOffset()-1);
2173 SetTabOffset(GetTabOffset()+1);
2178 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2180 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2184 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2185 e
.SetSelection(idx
);
2186 e
.SetOldSelection(GetActivePage());
2187 e
.SetEventObject(this);
2188 GetEventHandler()->ProcessEvent(e
);
2197 // wxTabFrame is an interesting case. It's important that all child pages
2198 // of the multi-notebook control are all actually children of that control
2199 // (and not grandchildren). wxTabFrame facilitates this. There is one
2200 // instance of wxTabFrame for each tab control inside the multi-notebook.
2201 // It's important to know that wxTabFrame is not a real window, but it merely
2202 // used to capture the dimensions/positioning of the internal tab control and
2203 // it's managed page windows
2205 class wxTabFrame
: public wxWindow
2212 m_rect
= wxRect(0,0,200,200);
2213 m_tab_ctrl_height
= 20;
2216 void SetTabCtrlHeight(int h
)
2218 m_tab_ctrl_height
= h
;
2221 void DoSetSize(int x
, int y
,
2222 int width
, int height
,
2223 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2225 m_rect
= wxRect(x
, y
, width
, height
);
2229 void DoGetClientSize(int* x
, int* y
) const
2235 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2242 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2243 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2244 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2248 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2249 size_t i
, page_count
= pages
.GetCount();
2251 for (i
= 0; i
< page_count
; ++i
)
2253 wxAuiNotebookPage
& page
= pages
.Item(i
);
2254 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2255 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2257 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2259 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2260 wnd
->ApplyMDIChildFrameRect();
2265 void DoGetSize(int* x
, int* y
) const
2268 *x
= m_rect
.GetWidth();
2270 *y
= m_rect
.GetHeight();
2282 wxAuiTabCtrl
* m_tabs
;
2283 int m_tab_ctrl_height
;
2287 const int wxAuiBaseTabCtrlId
= 5380;
2290 // -- wxAuiNotebook class implementation --
2292 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2293 EVT_SIZE(wxAuiNotebook
::OnSize
)
2294 EVT_CHILD_FOCUS(wxAuiNotebook
::OnChildFocus
)
2295 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2296 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2297 wxAuiNotebook
::OnTabClicked
)
2298 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2299 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2300 wxAuiNotebook
::OnTabBeginDrag
)
2301 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2302 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2303 wxAuiNotebook
::OnTabEndDrag
)
2304 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2305 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2306 wxAuiNotebook
::OnTabDragMotion
)
2307 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2308 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2309 wxAuiNotebook
::OnTabButton
)
2312 wxAuiNotebook
::wxAuiNotebook()
2315 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2317 m_tab_ctrl_height
= 20;
2318 m_requested_bmp_size
= wxDefaultSize
;
2319 m_requested_tabctrl_height
= -1;
2322 wxAuiNotebook
::wxAuiNotebook(wxWindow
*parent
,
2326 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2329 m_requested_bmp_size
= wxDefaultSize
;
2330 m_requested_tabctrl_height
= -1;
2331 InitNotebook(style
);
2334 bool wxAuiNotebook
::Create(wxWindow
* parent
,
2340 if (!wxControl
::Create(parent
, id
, pos
, size
, style
))
2343 InitNotebook(style
);
2348 // InitNotebook() contains common initialization
2349 // code called by all constructors
2350 void wxAuiNotebook
::InitNotebook(long style
)
2353 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2355 m_flags
= (unsigned int)style
;
2356 m_tab_ctrl_height
= 20;
2358 m_normal_font
= *wxNORMAL_FONT
;
2359 m_selected_font
= *wxNORMAL_FONT
;
2360 m_selected_font
.SetWeight(wxBOLD
);
2362 SetArtProvider(new wxAuiDefaultTabArt
);
2364 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2365 m_dummy_wnd
->SetSize(200, 200);
2366 m_dummy_wnd
->Show(false);
2368 m_mgr
.SetManagedWindow(this);
2369 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2370 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2372 m_mgr
.AddPane(m_dummy_wnd
,
2373 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2378 wxAuiNotebook
::~wxAuiNotebook()
2383 void wxAuiNotebook
::SetArtProvider(wxAuiTabArt
* art
)
2385 m_tabs
.SetArtProvider(art
);
2387 UpdateTabCtrlHeight();
2390 // SetTabCtrlHeight() is the highest-level override of the
2391 // tab height. A call to this function effectively enforces a
2392 // specified tab ctrl height, overriding all other considerations,
2393 // such as text or bitmap height. It overrides any call to
2394 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2395 // any previous call and returns to the default behavior
2397 void wxAuiNotebook
::SetTabCtrlHeight(int height
)
2399 m_requested_tabctrl_height
= height
;
2401 // if window is already initialized, recalculate the tab height
2404 UpdateTabCtrlHeight();
2409 // SetUniformBitmapSize() ensures that all tabs will have
2410 // the same height, even if some tabs don't have bitmaps
2411 // Passing wxDefaultSize to this function will instruct
2412 // the control to use dynamic tab height-- so when a tab
2413 // with a large bitmap is added, the tab ctrl's height will
2414 // automatically increase to accommodate the bitmap
2416 void wxAuiNotebook
::SetUniformBitmapSize(const wxSize
& size
)
2418 m_requested_bmp_size
= size
;
2420 // if window is already initialized, recalculate the tab height
2423 UpdateTabCtrlHeight();
2427 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2428 // to be used interally
2429 void wxAuiNotebook
::UpdateTabCtrlHeight()
2431 // get the tab ctrl height we will use
2432 int height
= CalculateTabCtrlHeight();
2434 // if the tab control height needs to change, update
2435 // all of our tab controls with the new height
2436 if (m_tab_ctrl_height
!= height
)
2438 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2440 m_tab_ctrl_height
= height
;
2442 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2443 size_t i
, pane_count
= all_panes
.GetCount();
2444 for (i
= 0; i
< pane_count
; ++i
)
2446 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2447 if (pane
.name
== wxT("dummy"))
2449 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2450 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2451 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2452 tabctrl
->SetArtProvider(art
->Clone());
2453 tab_frame
->DoSizing();
2458 void wxAuiNotebook
::UpdateHintWindowSize()
2460 wxSize size
= CalculateNewSplitSize();
2462 // the placeholder hint window should be set to this size
2463 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2467 info
.BestSize(size
);
2468 m_dummy_wnd
->SetSize(size
);
2473 // calculates the size of the new split
2474 wxSize wxAuiNotebook
::CalculateNewSplitSize()
2476 // count number of tab controls
2477 int tab_ctrl_count
= 0;
2478 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2479 size_t i
, pane_count
= all_panes
.GetCount();
2480 for (i
= 0; i
< pane_count
; ++i
)
2482 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2483 if (pane
.name
== wxT("dummy"))
2488 wxSize new_split_size
;
2490 // if there is only one tab control, the first split
2491 // should happen around the middle
2492 if (tab_ctrl_count
< 2)
2494 new_split_size
= GetClientSize();
2495 new_split_size
.x
/= 2;
2496 new_split_size
.y
/= 2;
2500 // this is in place of a more complicated calculation
2501 // that needs to be implemented
2502 new_split_size
= wxSize(180,180);
2505 return new_split_size
;
2508 int wxAuiNotebook
::CalculateTabCtrlHeight()
2510 // if a fixed tab ctrl height is specified,
2511 // just return that instead of calculating a
2513 if (m_requested_tabctrl_height
!= -1)
2514 return m_requested_tabctrl_height
;
2516 // find out new best tab height
2517 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2519 return art
->GetBestTabCtrlSize(this,
2521 m_requested_bmp_size
);
2525 wxAuiTabArt
* wxAuiNotebook
::GetArtProvider() const
2527 return m_tabs
.GetArtProvider();
2530 void wxAuiNotebook
::SetWindowStyleFlag(long style
)
2532 wxControl
::SetWindowStyleFlag(style
);
2534 m_flags
= (unsigned int)style
;
2536 // if the control is already initialized
2537 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2539 // let all of the tab children know about the new style
2541 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2542 size_t i
, pane_count
= all_panes
.GetCount();
2543 for (i
= 0; i
< pane_count
; ++i
)
2545 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2546 if (pane
.name
== wxT("dummy"))
2548 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2549 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2550 tabctrl
->SetFlags(m_flags
);
2551 tabframe
->DoSizing();
2559 bool wxAuiNotebook
::AddPage(wxWindow
* page
,
2560 const wxString
& caption
,
2562 const wxBitmap
& bitmap
)
2564 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2567 bool wxAuiNotebook
::InsertPage(size_t page_idx
,
2569 const wxString
& caption
,
2571 const wxBitmap
& bitmap
)
2573 wxAuiNotebookPage info
;
2575 info
.caption
= caption
;
2576 info
.bitmap
= bitmap
;
2577 info
.active
= false;
2579 // if there are currently no tabs, the first added
2580 // tab must be active
2581 if (m_tabs
.GetPageCount() == 0)
2584 m_tabs
.InsertPage(page
, info
, page_idx
);
2586 // if that was the first page added, even if
2587 // select is false, it must become the "current page"
2588 // (though no select events will be fired)
2589 if (!select
&& m_tabs
.GetPageCount() == 1)
2590 m_curpage
= GetPageIndex(page
);
2592 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2593 if (page_idx
>= active_tabctrl
->GetPageCount())
2594 active_tabctrl
->AddPage(page
, info
);
2596 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2598 UpdateTabCtrlHeight();
2600 active_tabctrl
->DoShowHide();
2604 int idx
= m_tabs
.GetIdxFromWindow(page
);
2605 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2614 // DeletePage() removes a tab from the multi-notebook,
2615 // and destroys the window as well
2616 bool wxAuiNotebook
::DeletePage(size_t page_idx
)
2618 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2620 if (!RemovePage(page_idx
))
2623 // actually destroy the window now
2624 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2626 // delete the child frame with pending delete, as is
2627 // customary with frame windows
2628 if (!wxPendingDelete
.Member(wnd
))
2629 wxPendingDelete
.Append(wnd
);
2641 // RemovePage() removes a tab from the multi-notebook,
2642 // but does not destroy the window
2643 bool wxAuiNotebook
::RemovePage(size_t page_idx
)
2645 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2646 wxWindow
* new_active
= NULL
;
2648 // find out which onscreen tab ctrl owns this tab
2651 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2654 // find a new page and set it as active
2655 int new_idx
= ctrl_idx
+1;
2656 if (new_idx
>= (int)ctrl
->GetPageCount())
2657 new_idx
= ctrl_idx
-1;
2659 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2661 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2665 // set the active page to the first page that
2666 // isn't the one being deleted
2667 size_t i
, page_count
= m_tabs
.GetPageCount();
2668 for (i
= 0; i
< page_count
; ++i
)
2670 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2673 new_active
= m_tabs
.GetWindowFromIdx(i
);
2679 // remove the tab from main catalog
2680 if (!m_tabs
.RemovePage(wnd
))
2683 // remove the tab from the onscreen tab ctrl
2684 ctrl
->RemovePage(wnd
);
2687 RemoveEmptyTabFrames();
2689 // set new active pane
2693 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2699 // GetPageIndex() returns the index of the page, or -1 if the
2700 // page could not be located in the notebook
2701 int wxAuiNotebook
::GetPageIndex(wxWindow
* page_wnd
) const
2703 return m_tabs
.GetIdxFromWindow(page_wnd
);
2708 // SetPageText() changes the tab caption of the specified page
2709 bool wxAuiNotebook
::SetPageText(size_t page_idx
, const wxString
& text
)
2711 if (page_idx
>= m_tabs
.GetPageCount())
2714 // update our own tab catalog
2715 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2716 page_info
.caption
= text
;
2718 // update what's on screen
2721 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2723 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2724 info
.caption
= text
;
2733 bool wxAuiNotebook
::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2735 if (page_idx
>= m_tabs
.GetPageCount())
2738 // update our own tab catalog
2739 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2740 page_info
.bitmap
= bitmap
;
2742 // tab height might have changed
2743 UpdateTabCtrlHeight();
2745 // update what's on screen
2748 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2750 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2751 info
.bitmap
= bitmap
;
2760 // GetSelection() returns the index of the currently active page
2761 int wxAuiNotebook
::GetSelection() const
2766 // SetSelection() sets the currently active page
2767 size_t wxAuiNotebook
::SetSelection(size_t new_page
)
2769 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2773 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2774 evt
.SetSelection(new_page
);
2775 evt
.SetOldSelection(m_curpage
);
2776 evt
.SetEventObject(this);
2777 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2779 int old_curpage
= m_curpage
;
2780 m_curpage
= new_page
;
2782 // program allows the page change
2783 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2784 (void)GetEventHandler()->ProcessEvent(evt
);
2789 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2791 m_tabs
.SetActivePage(wnd
);
2793 ctrl
->SetActivePage(ctrl_idx
);
2800 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2801 size_t i
, pane_count
= all_panes
.GetCount();
2802 for (i
= 0; i
< pane_count
; ++i
)
2804 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2805 if (pane
.name
== wxT("dummy"))
2807 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2808 if (tabctrl
!= ctrl
)
2809 tabctrl
->SetSelectedFont(m_normal_font
);
2811 tabctrl
->SetSelectedFont(m_selected_font
);
2824 // GetPageCount() returns the total number of
2825 // pages managed by the multi-notebook
2826 size_t wxAuiNotebook
::GetPageCount() const
2828 return m_tabs
.GetPageCount();
2831 // GetPage() returns the wxWindow pointer of the
2833 wxWindow
* wxAuiNotebook
::GetPage(size_t page_idx
) const
2835 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2837 return m_tabs
.GetWindowFromIdx(page_idx
);
2840 // DoSizing() performs all sizing operations in each tab control
2841 void wxAuiNotebook
::DoSizing()
2843 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2844 size_t i
, pane_count
= all_panes
.GetCount();
2845 for (i
= 0; i
< pane_count
; ++i
)
2847 if (all_panes
.Item(i
).name
== wxT("dummy"))
2850 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2851 tabframe
->DoSizing();
2855 // GetActiveTabCtrl() returns the active tab control. It is
2856 // called to determine which control gets new windows being added
2857 wxAuiTabCtrl
* wxAuiNotebook
::GetActiveTabCtrl()
2859 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2864 // find the tab ctrl with the current page
2865 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2872 // no current page, just find the first tab ctrl
2873 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2874 size_t i
, pane_count
= all_panes
.GetCount();
2875 for (i
= 0; i
< pane_count
; ++i
)
2877 if (all_panes
.Item(i
).name
== wxT("dummy"))
2880 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2881 return tabframe
->m_tabs
;
2884 // If there is no tabframe at all, create one
2885 wxTabFrame
* tabframe
= new wxTabFrame
;
2886 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2887 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2892 tabframe
->m_tabs
->SetFlags(m_flags
);
2893 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2894 m_mgr
.AddPane(tabframe
,
2895 wxAuiPaneInfo().Center().CaptionVisible(false));
2899 return tabframe
->m_tabs
;
2902 // FindTab() finds the tab control that currently contains the window as well
2903 // as the index of the window in the tab control. It returns true if the
2904 // window was found, otherwise false.
2905 bool wxAuiNotebook
::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2907 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2908 size_t i
, pane_count
= all_panes
.GetCount();
2909 for (i
= 0; i
< pane_count
; ++i
)
2911 if (all_panes
.Item(i
).name
== wxT("dummy"))
2914 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2916 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2919 *ctrl
= tabframe
->m_tabs
;
2928 void wxAuiNotebook
::OnSize(wxSizeEvent
& evt
)
2930 UpdateHintWindowSize();
2935 void wxAuiNotebook
::OnTabClicked(wxCommandEvent
& command_evt
)
2937 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2939 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2940 wxASSERT(ctrl
!= NULL
);
2942 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2943 wxASSERT(wnd
!= NULL
);
2945 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2946 wxASSERT(idx
!= -1);
2951 void wxAuiNotebook
::OnTabBeginDrag(wxCommandEvent
&)
2956 void wxAuiNotebook
::OnTabDragMotion(wxCommandEvent
& evt
)
2958 wxPoint screen_pt
= ::wxGetMousePosition();
2959 wxPoint client_pt
= ScreenToClient(screen_pt
);
2962 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2963 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2965 if (dest_tabs
== src_tabs
)
2969 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2972 // always hide the hint for inner-tabctrl drag
2975 // if tab moving is not allowed, leave
2976 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2981 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2982 wxWindow
* dest_location_tab
;
2984 // this is an inner-tab drag/reposition
2985 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2987 int src_idx
= evt
.GetSelection();
2988 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2990 // prevent jumpy drag
2991 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2992 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2993 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2995 m_last_drag_x
= pt
.x
;
3000 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3001 dest_tabs
->MovePage(src_tab
, dest_idx
);
3002 dest_tabs
->SetActivePage((size_t)dest_idx
);
3003 dest_tabs
->DoShowHide();
3004 dest_tabs
->Refresh();
3005 m_last_drag_x
= pt
.x
;
3013 // if external drag is allowed, check if the tab is being dragged
3014 // over a different wxAuiNotebook control
3015 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3017 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3019 // if we aren't over any window, stop here
3023 // make sure we are not over the hint window
3024 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3028 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3030 tab_ctrl
= tab_ctrl
->GetParent();
3035 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3039 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3040 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3041 m_mgr
.ShowHint(hint_rect
);
3050 // we are either over a hint window, or not over a tab
3051 // window, and there is no where to drag to, so exit
3058 // if there are less than two panes, split can't happen, so leave
3059 if (m_tabs
.GetPageCount() < 2)
3062 // if tab moving is not allowed, leave
3063 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3069 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3075 wxRect hint_rect
= dest_tabs
->GetRect();
3076 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3077 m_mgr
.ShowHint(hint_rect
);
3081 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3087 void wxAuiNotebook
::OnTabEndDrag(wxCommandEvent
& command_evt
)
3089 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3094 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3095 wxAuiTabCtrl
* dest_tabs
= NULL
;
3098 // set cursor back to an arrow
3099 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3102 // get the mouse position, which will be used to determine the drop point
3103 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3104 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3108 // check for an external move
3109 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3111 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3115 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3117 tab_ctrl
= tab_ctrl
->GetParent();
3122 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3126 // find out from the destination control
3127 // if it's ok to drop this tab here
3128 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3129 e
.SetSelection(evt
.GetSelection());
3130 e
.SetOldSelection(evt
.GetSelection());
3131 e
.SetEventObject(this);
3132 e
.SetDragSource(this);
3133 e
.Veto(); // dropping must be explicitly approved by control owner
3135 nb
->GetEventHandler()->ProcessEvent(e
);
3139 // no answer or negative answer
3145 int src_idx
= evt
.GetSelection();
3146 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3148 // get main index of the page
3149 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3151 // make a copy of the page info
3152 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3154 // remove the page from the source notebook
3155 RemovePage(main_idx
);
3157 // reparent the page
3158 src_page
->Reparent(nb
);
3161 // found out the insert idx
3162 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3163 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3165 wxWindow
* target
= NULL
;
3166 int insert_idx
= -1;
3167 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3170 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3174 // add the page to the new notebook
3175 if (insert_idx
== -1)
3176 insert_idx
= dest_tabs
->GetPageCount();
3177 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3178 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3181 dest_tabs
->DoShowHide();
3182 dest_tabs
->Refresh();
3184 // set the selection in the destination tab control
3185 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3195 // only perform a tab split if it's allowed
3196 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3198 // If the pointer is in an existing tab frame, do a tab insert
3199 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3200 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3201 int insert_idx
= -1;
3204 dest_tabs
= tab_frame
->m_tabs
;
3206 if (dest_tabs
== src_tabs
)
3210 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3211 wxWindow
* target
= NULL
;
3212 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3215 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3221 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3226 // there is no suitable drop location here, exit out
3230 // If there is no tabframe at all, create one
3231 wxTabFrame
* new_tabs
= new wxTabFrame
;
3232 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3233 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3234 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3239 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3240 new_tabs
->m_tabs
->SetFlags(m_flags
);
3242 m_mgr
.AddPane(new_tabs
,
3243 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3246 dest_tabs
= new_tabs
->m_tabs
;
3251 // remove the page from the source tabs
3252 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3253 page_info
.active
= false;
3254 src_tabs
->RemovePage(page_info
.window
);
3255 if (src_tabs
->GetPageCount() > 0)
3257 src_tabs
->SetActivePage((size_t)0);
3258 src_tabs
->DoShowHide();
3259 src_tabs
->Refresh();
3264 // add the page to the destination tabs
3265 if (insert_idx
== -1)
3266 insert_idx
= dest_tabs
->GetPageCount();
3267 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3269 if (src_tabs
->GetPageCount() == 0)
3271 RemoveEmptyTabFrames();
3275 dest_tabs
->DoShowHide();
3276 dest_tabs
->Refresh();
3278 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3280 UpdateHintWindowSize();
3286 wxAuiTabCtrl
* wxAuiNotebook
::GetTabCtrlFromPoint(const wxPoint
& pt
)
3288 // if we've just removed the last tab from the source
3289 // tab set, the remove the tab control completely
3290 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3291 size_t i
, pane_count
= all_panes
.GetCount();
3292 for (i
= 0; i
< pane_count
; ++i
)
3294 if (all_panes
.Item(i
).name
== wxT("dummy"))
3297 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3298 if (tabframe
->m_tab_rect
.Contains(pt
))
3299 return tabframe
->m_tabs
;
3305 wxWindow
* wxAuiNotebook
::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3307 // if we've just removed the last tab from the source
3308 // tab set, the remove the tab control completely
3309 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3310 size_t i
, pane_count
= all_panes
.GetCount();
3311 for (i
= 0; i
< pane_count
; ++i
)
3313 if (all_panes
.Item(i
).name
== wxT("dummy"))
3316 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3317 if (tabframe
->m_tabs
== tab_ctrl
)
3326 void wxAuiNotebook
::RemoveEmptyTabFrames()
3328 // if we've just removed the last tab from the source
3329 // tab set, the remove the tab control completely
3330 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3331 size_t i
, pane_count
= all_panes
.GetCount();
3332 for (i
= 0; i
< pane_count
; ++i
)
3334 if (all_panes
.Item(i
).name
== wxT("dummy"))
3337 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3338 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3340 m_mgr
.DetachPane(tab_frame
);
3342 // use pending delete because sometimes during
3343 // window closing, refreshs are pending
3344 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3345 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3346 //tab_frame->m_tabs->Destroy();
3353 // check to see if there is still a center pane;
3354 // if there isn't, make a frame the center pane
3355 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3356 pane_count
= panes
.GetCount();
3357 wxWindow
* first_good
= NULL
;
3358 bool center_found
= false;
3359 for (i
= 0; i
< pane_count
; ++i
)
3361 if (panes
.Item(i
).name
== wxT("dummy"))
3363 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3364 center_found
= true;
3366 first_good
= panes
.Item(i
).window
;
3369 if (!center_found
&& first_good
)
3371 m_mgr
.GetPane(first_good
).Centre();
3377 void wxAuiNotebook
::OnChildFocus(wxChildFocusEvent
& evt
)
3379 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3380 if (idx
!= -1 && idx
!= m_curpage
)
3387 void wxAuiNotebook
::OnTabButton(wxCommandEvent
& command_evt
)
3389 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3390 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3392 int button_id
= evt
.GetInt();
3394 if (button_id
== wxAUI_BUTTON_CLOSE
)
3396 int selection
= tabs
->GetActivePage();
3398 if (selection
!= -1)
3400 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3403 // ask owner if it's ok to close the tab
3404 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3405 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3406 e
.SetOldSelection(evt
.GetSelection());
3407 e
.SetEventObject(this);
3408 GetEventHandler()->ProcessEvent(e
);
3413 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3419 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3420 DeletePage(main_idx
);