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 // This functions are here for this proof of concept
61 // and will be factored out later. See dockart.cpp
62 static wxColor
StepColour(const wxColor
& c
, int percent
)
64 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
65 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
66 (unsigned char)wxMin((g
*percent
)/100,255),
67 (unsigned char)wxMin((b
*percent
)/100,255));
70 // This functions are here for this proof of concept
71 // and will be factored out later. See dockart.cpp
72 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
73 const wxColour
& color
)
75 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
76 img
.Replace(0,0,0,123,123,123);
77 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
78 img
.SetMaskColour(123,123,123);
82 static void DrawButtons(wxDC
& dc
,
85 const wxColour
& bkcolour
,
90 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
96 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
97 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
99 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
100 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
102 // draw the background behind the button
103 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
106 // draw the button itself
107 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
110 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
112 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
119 // chops the text so that it fits within |max_size| pixels.
120 // Also adds an elipsis if necessary
122 static wxString
ChopText(wxDC
& dc
, const wxString
& text
, int max_size
)
126 // first check if the text fits with no problems
127 dc
.GetTextExtent(text
, &x
, &y
);
131 size_t i
, len
= text
.Length();
132 size_t last_good_length
= 0;
133 for (i
= 0; i
< len
; ++i
)
135 wxString s
= text
.Left(i
);
138 dc
.GetTextExtent(s
, &x
, &y
);
142 last_good_length
= i
;
145 wxString ret
= text
.Left(last_good_length
);
151 // -- GUI helper classes and functions --
153 class wxAuiCommandCapture
: public wxEvtHandler
157 wxAuiCommandCapture() { m_last_id
= 0; }
158 int GetCommandId() const { return m_last_id
; }
160 bool ProcessEvent(wxEvent
& evt
)
162 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
164 m_last_id
= evt
.GetId();
168 if (GetNextHandler())
169 return GetNextHandler()->ProcessEvent(evt
);
181 #if defined( __WXMAC__ )
182 static unsigned char close_bits
[]={
183 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
184 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
185 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
186 #elif defined( __WXGTK__)
187 static unsigned char close_bits
[]={
188 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
189 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
190 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
192 static unsigned char close_bits
[]={
193 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
194 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
198 static unsigned char left_bits
[] = {
199 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
200 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
201 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
203 static unsigned char right_bits
[] = {
204 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
205 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
208 static unsigned char list_bits
[] = {
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
218 // -- wxAuiDefaultTabArt class implementation --
220 wxAuiDefaultTabArt
::wxAuiDefaultTabArt()
222 m_normal_font
= *wxNORMAL_FONT
;
223 m_selected_font
= *wxNORMAL_FONT
;
224 m_selected_font
.SetWeight(wxBOLD
);
225 m_measuring_font
= m_selected_font
;
227 m_fixed_tab_width
= 100;
228 m_tab_ctrl_height
= 0;
231 wxBrush toolbarbrush
;
232 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
233 wxColor base_colour
= toolbarbrush
.GetColour();
235 wxColor base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
238 m_base_colour
= base_colour
;
239 wxColor darker2_colour
= StepColour(base_colour
, 70);
241 m_border_pen
= wxPen(darker2_colour
);
242 m_base_colour_pen
= wxPen(m_base_colour
);
243 m_base_colour_brush
= wxBrush(m_base_colour
);
245 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
246 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
248 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
249 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
251 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
252 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
254 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
255 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
260 wxAuiDefaultTabArt
::~wxAuiDefaultTabArt()
264 wxAuiTabArt
* wxAuiDefaultTabArt
::Clone()
266 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
269 void wxAuiDefaultTabArt
::SetFlags(unsigned int flags
)
274 void wxAuiDefaultTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
277 m_fixed_tab_width
= 100;
279 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
281 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
282 tot_width
-= m_active_close_bmp
.GetWidth();
283 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
284 tot_width
-= m_active_windowlist_bmp
.GetWidth();
288 m_fixed_tab_width
= tot_width
/(int)tab_count
;
292 if (m_fixed_tab_width
< 100)
293 m_fixed_tab_width
= 100;
295 if (m_fixed_tab_width
> tot_width
/2)
296 m_fixed_tab_width
= tot_width
/2;
298 if (m_fixed_tab_width
> 220)
299 m_fixed_tab_width
= 220;
301 m_tab_ctrl_height
= tab_ctrl_size
.y
;
305 void wxAuiDefaultTabArt
::DrawBackground(wxDC
& dc
,
306 wxWindow
* WXUNUSED(wnd
),
310 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
311 wxColor top_color
= StepColour(m_base_colour
, 90);
312 wxColor bottom_color
= StepColour(m_base_colour
, 110);
313 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
316 int y
= rect
.GetHeight();
317 int w
= rect
.GetWidth();
318 dc
.SetPen(m_border_pen
);
319 dc
.SetBrush(m_base_colour_brush
);
320 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
324 // DrawTab() draws an individual tab.
327 // in_rect - rectangle the tab should be confined to
328 // caption - tab's caption
329 // active - whether or not the tab is active
330 // out_rect - actual output rectangle
331 // x_extent - the advance x; where the next tab should start
333 void wxAuiDefaultTabArt
::DrawTab(wxDC
& dc
,
335 const wxRect
& in_rect
,
336 const wxString
& caption_text
,
337 const wxBitmap
& bitmap
,
339 int close_button_state
,
340 wxRect
* out_tab_rect
,
341 wxRect
* out_button_rect
,
344 wxCoord normal_textx
, normal_texty
;
345 wxCoord selected_textx
, selected_texty
;
346 wxCoord textx
, texty
;
348 // if the caption is empty, measure some temporary text
349 wxString caption
= caption_text
;
350 if (caption_text
.empty())
353 dc
.SetFont(m_selected_font
);
354 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
356 dc
.SetFont(m_normal_font
);
357 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
359 // figure out the size of the tab
360 wxSize tab_size
= GetTabSize(dc
,
368 wxCoord tab_height
= m_tab_ctrl_height
- 3;
369 wxCoord tab_width
= tab_size
.x
;
370 wxCoord tab_x
= in_rect
.x
;
371 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
374 caption
= caption_text
;
377 // select pen, brush and font for the tab to be drawn
381 dc
.SetFont(m_selected_font
);
382 textx
= selected_textx
;
383 texty
= selected_texty
;
387 dc
.SetFont(m_normal_font
);
388 textx
= normal_textx
;
389 texty
= normal_texty
;
393 // create points that will make the tab outline
395 int clip_width
= tab_width
;
396 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
397 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
399 wxPoint clip_points
[6];
400 clip_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-3);
401 clip_points
[1] = wxPoint(tab_x
, tab_y
+2);
402 clip_points
[2] = wxPoint(tab_x
+2, tab_y
);
403 clip_points
[3] = wxPoint(tab_x
+clip_width
-1, tab_y
);
404 clip_points
[4] = wxPoint(tab_x
+clip_width
+1, tab_y
+2);
405 clip_points
[5] = wxPoint(tab_x
+clip_width
+1, tab_y
+tab_height
-3);
407 // FIXME: these ports don't provide wxRegion ctor from array of points
408 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
409 // set the clipping region for the tab --
410 wxRegion
clipping_region(WXSIZEOF(clip_points
), clip_points
);
411 dc
.SetClippingRegion(clipping_region
);
412 #endif // !wxDFB && !wxCocoa
414 wxPoint border_points
[6];
415 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
416 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
417 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
418 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
419 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
420 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
423 int drawn_tab_yoff
= border_points
[1].y
;
424 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
431 // draw base background color
432 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
433 dc
.SetPen(m_base_colour_pen
);
434 dc
.SetBrush(m_base_colour_brush
);
435 dc
.DrawRectangle(r
.x
, r
.y
, r
.width
, r
.height
);
437 // this white helps fill out the gradient at the top of the tab
438 dc
.SetPen(*wxWHITE_PEN
);
439 dc
.SetBrush(*wxWHITE_BRUSH
);
440 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
);
442 // these two points help the rounded corners appear more antialiased
443 dc
.SetPen(m_base_colour_pen
);
444 dc
.DrawPoint(r
.x
+2, r
.y
+1);
445 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
447 // set rectangle down a bit for gradient drawing
448 r
.SetHeight(r
.GetHeight()/2);
454 // draw gradient background
455 wxColor top_color
= *wxWHITE
;
456 wxColor bottom_color
= m_base_colour
;
457 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
463 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
465 // start the gradent up a bit and leave the inside border inset
466 // by a pixel for a 3D look. Only the top half of the inactive
467 // tab will have a slight gradient
474 // -- draw top gradient fill for glossy look
475 wxColor top_color
= m_base_colour
;
476 wxColor bottom_color
= StepColour(top_color
, 106);
477 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
482 // -- draw bottom fill for glossy look
483 top_color
= m_base_colour
;
484 bottom_color
= m_base_colour
;
485 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
489 dc
.SetPen(m_border_pen
);
490 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
491 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
493 // there are two horizontal grey lines at the bottom of the tab control,
494 // this gets rid of the top one of those lines in the tab control
497 wxColor start_color
= m_base_colour
;
498 dc
.SetPen(m_base_colour_pen
);
499 dc
.DrawLine(border_points
[0].x
+1,
506 int text_offset
= tab_x
+ 8;
507 int close_button_width
= 0;
508 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
510 close_button_width
= m_active_close_bmp
.GetWidth();
516 int bitmap_offset
= tab_x
+ 8;
519 dc
.DrawBitmap(bitmap
,
521 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2) + 1,
524 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
525 text_offset
+= 3; // bitmap padding
529 text_offset
= tab_x
+ 8;
533 wxString draw_text
= ChopText(dc
,
535 tab_width
- (text_offset
-tab_x
) - close_button_width
);
538 dc
.DrawText(draw_text
,
540 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
545 // draw close button if necessary
546 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
548 wxBitmap bmp
= m_disabled_close_bmp
;
550 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
551 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
553 bmp
= m_active_close_bmp
;
556 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
557 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
560 IndentPressedBitmap(&rect
, close_button_state
);
561 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
563 *out_button_rect
= rect
;
566 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
568 dc
.DestroyClippingRegion();
571 int wxAuiDefaultTabArt
::GetIndentSize()
576 wxSize wxAuiDefaultTabArt
::GetTabSize(wxDC
& dc
,
577 wxWindow
* WXUNUSED(wnd
),
578 const wxString
& caption
,
579 const wxBitmap
& bitmap
,
580 bool WXUNUSED(active
),
581 int close_button_state
,
584 wxCoord measured_textx
, measured_texty
, tmp
;
586 dc
.SetFont(m_measuring_font
);
587 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
589 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
591 // add padding around the text
592 wxCoord tab_width
= measured_textx
;
593 wxCoord tab_height
= measured_texty
;
595 // if the close button is showing, add space for it
596 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
597 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
599 // if there's a bitmap, add space for it
602 tab_width
+= bitmap
.GetWidth();
603 tab_width
+= 3; // right side bitmap padding
604 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
611 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
613 tab_width
= m_fixed_tab_width
;
616 *x_extent
= tab_width
;
618 return wxSize(tab_width
, tab_height
);
622 void wxAuiDefaultTabArt
::DrawButton(wxDC
& dc
,
623 wxWindow
* WXUNUSED(wnd
),
624 const wxRect
& in_rect
,
628 const wxBitmap
& bitmap_override
,
634 if (bitmap_override
.IsOk())
636 bmp
= bitmap_override
;
642 case wxAUI_BUTTON_CLOSE
:
643 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
644 bmp
= m_disabled_close_bmp
;
646 bmp
= m_active_close_bmp
;
648 case wxAUI_BUTTON_LEFT
:
649 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
650 bmp
= m_disabled_left_bmp
;
652 bmp
= m_active_left_bmp
;
654 case wxAUI_BUTTON_RIGHT
:
655 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
656 bmp
= m_disabled_right_bmp
;
658 bmp
= m_active_right_bmp
;
660 case wxAUI_BUTTON_WINDOWLIST
:
661 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
662 bmp
= m_disabled_windowlist_bmp
;
664 bmp
= m_active_windowlist_bmp
;
674 if (orientation
== wxLEFT
)
676 rect
.SetX(in_rect
.x
);
677 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
678 rect
.SetWidth(bmp
.GetWidth());
679 rect
.SetHeight(bmp
.GetHeight());
683 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
684 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
685 bmp
.GetWidth(), bmp
.GetHeight());
688 IndentPressedBitmap(&rect
, button_state
);
689 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
695 int wxAuiDefaultTabArt
::ShowWindowList(wxWindow
* wnd
,
696 const wxArrayString
& items
,
701 size_t i
, count
= items
.GetCount();
702 for (i
= 0; i
< count
; ++i
)
704 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
707 if (active_idx
!= -1)
709 menuPopup
.Check(1000+active_idx
, true);
712 // find out where to put the popup menu of window
713 // items. Subtract 100 for now to center the menu
714 // a bit, until a better mechanism can be implemented
715 wxPoint pt
= ::wxGetMousePosition();
716 pt
= wnd
->ScreenToClient(pt
);
722 // find out the screen coordinate at the bottom of the tab ctrl
723 wxRect cli_rect
= wnd
->GetClientRect();
724 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
726 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
727 wnd
->PushEventHandler(cc
);
728 wnd
->PopupMenu(&menuPopup
, pt
);
729 int command
= cc
->GetCommandId();
730 wnd
->PopEventHandler(true);
738 int wxAuiDefaultTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
739 wxAuiNotebookPageArray
& pages
,
740 const wxSize
& required_bmp_size
)
743 dc
.SetFont(m_measuring_font
);
745 // sometimes a standard bitmap size needs to be enforced, especially
746 // if some tabs have bitmaps and others don't. This is important because
747 // it prevents the tab control from resizing when tabs are added.
748 wxBitmap measure_bmp
;
749 if (required_bmp_size
.IsFullySpecified())
751 measure_bmp
.Create(required_bmp_size
.x
,
752 required_bmp_size
.y
);
757 size_t i
, page_count
= pages
.GetCount();
758 for (i
= 0; i
< page_count
; ++i
)
760 wxAuiNotebookPage
& page
= pages
.Item(i
);
763 if (measure_bmp
.IsOk())
768 // we don't use the caption text because we don't
769 // want tab heights to be different in the case
770 // of a very short piece of text on one tab and a very
771 // tall piece of text on another tab
773 wxSize s
= GetTabSize(dc
,
778 wxAUI_BUTTON_STATE_HIDDEN
,
781 max_y
= wxMax(max_y
, s
.y
);
787 void wxAuiDefaultTabArt
::SetNormalFont(const wxFont
& font
)
789 m_normal_font
= font
;
792 void wxAuiDefaultTabArt
::SetSelectedFont(const wxFont
& font
)
794 m_selected_font
= font
;
797 void wxAuiDefaultTabArt
::SetMeasuringFont(const wxFont
& font
)
799 m_measuring_font
= font
;
803 // -- wxAuiSimpleTabArt class implementation --
805 wxAuiSimpleTabArt
::wxAuiSimpleTabArt()
807 m_normal_font
= *wxNORMAL_FONT
;
808 m_selected_font
= *wxNORMAL_FONT
;
809 m_selected_font
.SetWeight(wxBOLD
);
810 m_measuring_font
= m_selected_font
;
813 m_fixed_tab_width
= 100;
815 wxColour base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
817 wxColour background_colour
= StepColour(base_colour
, 95);
818 wxColour normaltab_colour
= base_colour
;
819 wxColour selectedtab_colour
= *wxWHITE
;
821 m_bkbrush
= wxBrush(background_colour
);
822 m_normal_bkbrush
= wxBrush(normaltab_colour
);
823 m_normal_bkpen
= wxPen(normaltab_colour
);
824 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
825 m_selected_bkpen
= wxPen(selectedtab_colour
);
827 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
828 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
830 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
831 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
833 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
834 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
836 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
837 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
841 wxAuiSimpleTabArt
::~wxAuiSimpleTabArt()
845 wxAuiTabArt
* wxAuiSimpleTabArt
::Clone()
847 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
851 void wxAuiSimpleTabArt
::SetFlags(unsigned int flags
)
856 void wxAuiSimpleTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
859 m_fixed_tab_width
= 100;
861 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
863 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
864 tot_width
-= m_active_close_bmp
.GetWidth();
865 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
866 tot_width
-= m_active_windowlist_bmp
.GetWidth();
870 m_fixed_tab_width
= tot_width
/(int)tab_count
;
874 if (m_fixed_tab_width
< 100)
875 m_fixed_tab_width
= 100;
877 if (m_fixed_tab_width
> tot_width
/2)
878 m_fixed_tab_width
= tot_width
/2;
880 if (m_fixed_tab_width
> 220)
881 m_fixed_tab_width
= 220;
884 void wxAuiSimpleTabArt
::DrawBackground(wxDC
& dc
,
885 wxWindow
* WXUNUSED(wnd
),
889 dc
.SetBrush(m_bkbrush
);
890 dc
.SetPen(*wxTRANSPARENT_PEN
);
891 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
894 dc
.SetPen(*wxGREY_PEN
);
895 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
899 // DrawTab() draws an individual tab.
902 // in_rect - rectangle the tab should be confined to
903 // caption - tab's caption
904 // active - whether or not the tab is active
905 // out_rect - actual output rectangle
906 // x_extent - the advance x; where the next tab should start
908 void wxAuiSimpleTabArt
::DrawTab(wxDC
& dc
,
910 const wxRect
& in_rect
,
911 const wxString
& caption_text
,
912 const wxBitmap
& bitmap
,
914 int close_button_state
,
915 wxRect
* out_tab_rect
,
916 wxRect
* out_button_rect
,
919 wxCoord normal_textx
, normal_texty
;
920 wxCoord selected_textx
, selected_texty
;
921 wxCoord textx
, texty
;
923 // if the caption is empty, measure some temporary text
924 wxString caption
= caption_text
;
925 if (caption_text
.empty())
928 dc
.SetFont(m_selected_font
);
929 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
931 dc
.SetFont(m_normal_font
);
932 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
934 // figure out the size of the tab
935 wxSize tab_size
= GetTabSize(dc
,
943 wxCoord tab_height
= tab_size
.y
;
944 wxCoord tab_width
= tab_size
.x
;
945 wxCoord tab_x
= in_rect
.x
;
946 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
948 caption
= caption_text
;
950 // select pen, brush and font for the tab to be drawn
954 dc
.SetPen(m_selected_bkpen
);
955 dc
.SetBrush(m_selected_bkbrush
);
956 dc
.SetFont(m_selected_font
);
957 textx
= selected_textx
;
958 texty
= selected_texty
;
962 dc
.SetPen(m_normal_bkpen
);
963 dc
.SetBrush(m_normal_bkbrush
);
964 dc
.SetFont(m_normal_font
);
965 textx
= normal_textx
;
966 texty
= normal_texty
;
974 points
[0].y
= tab_y
+ tab_height
- 1;
975 points
[1].x
= tab_x
+ tab_height
- 3;
976 points
[1].y
= tab_y
+ 2;
977 points
[2].x
= tab_x
+ tab_height
+ 3;
979 points
[3].x
= tab_x
+ tab_width
- 2;
981 points
[4].x
= tab_x
+ tab_width
;
982 points
[4].y
= tab_y
+ 2;
983 points
[5].x
= tab_x
+ tab_width
;
984 points
[5].y
= tab_y
+ tab_height
- 1;
985 points
[6] = points
[0];
987 dc
.SetClippingRegion(in_rect
);
989 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
991 dc
.SetPen(*wxGREY_PEN
);
993 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
994 dc
.DrawLines(WXSIZEOF(points
), points
);
999 int close_button_width
= 0;
1000 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1002 close_button_width
= m_active_close_bmp
.GetWidth();
1003 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1007 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1010 // set minimum text offset
1011 if (text_offset
< tab_x
+ tab_height
)
1012 text_offset
= tab_x
+ tab_height
;
1014 // chop text if necessary
1015 wxString draw_text
= ChopText(dc
,
1017 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1020 dc
.DrawText(draw_text
,
1022 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1025 // draw close button if necessary
1026 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1030 bmp
= m_active_close_bmp
;
1032 bmp
= m_disabled_close_bmp
;
1034 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1035 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1038 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1040 *out_button_rect
= rect
;
1044 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1046 dc
.DestroyClippingRegion();
1049 int wxAuiSimpleTabArt
::GetIndentSize()
1054 wxSize wxAuiSimpleTabArt
::GetTabSize(wxDC
& dc
,
1055 wxWindow
* WXUNUSED(wnd
),
1056 const wxString
& caption
,
1057 const wxBitmap
& WXUNUSED(bitmap
),
1058 bool WXUNUSED(active
),
1059 int close_button_state
,
1062 wxCoord measured_textx
, measured_texty
;
1064 dc
.SetFont(m_measuring_font
);
1065 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1067 wxCoord tab_height
= measured_texty
+ 4;
1068 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1070 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1071 tab_width
+= m_active_close_bmp
.GetWidth();
1073 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1075 tab_width
= m_fixed_tab_width
;
1078 *x_extent
= tab_width
- (tab_height
/2) - 1;
1080 return wxSize(tab_width
, tab_height
);
1084 void wxAuiSimpleTabArt
::DrawButton(wxDC
& dc
,
1085 wxWindow
* WXUNUSED(wnd
),
1086 const wxRect
& in_rect
,
1090 const wxBitmap
& bitmap_override
,
1096 if (bitmap_override
.IsOk())
1098 bmp
= bitmap_override
;
1104 case wxAUI_BUTTON_CLOSE
:
1105 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1106 bmp
= m_disabled_close_bmp
;
1108 bmp
= m_active_close_bmp
;
1110 case wxAUI_BUTTON_LEFT
:
1111 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1112 bmp
= m_disabled_left_bmp
;
1114 bmp
= m_active_left_bmp
;
1116 case wxAUI_BUTTON_RIGHT
:
1117 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1118 bmp
= m_disabled_right_bmp
;
1120 bmp
= m_active_right_bmp
;
1122 case wxAUI_BUTTON_WINDOWLIST
:
1123 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1124 bmp
= m_disabled_windowlist_bmp
;
1126 bmp
= m_active_windowlist_bmp
;
1136 if (orientation
== wxLEFT
)
1138 rect
.SetX(in_rect
.x
);
1139 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1140 rect
.SetWidth(bmp
.GetWidth());
1141 rect
.SetHeight(bmp
.GetHeight());
1145 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1146 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1147 bmp
.GetWidth(), bmp
.GetHeight());
1151 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1157 int wxAuiSimpleTabArt
::ShowWindowList(wxWindow
* wnd
,
1158 const wxArrayString
& items
,
1163 size_t i
, count
= items
.GetCount();
1164 for (i
= 0; i
< count
; ++i
)
1166 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1169 if (active_idx
!= -1)
1171 menuPopup
.Check(1000+active_idx
, true);
1174 // find out where to put the popup menu of window
1175 // items. Subtract 100 for now to center the menu
1176 // a bit, until a better mechanism can be implemented
1177 wxPoint pt
= ::wxGetMousePosition();
1178 pt
= wnd
->ScreenToClient(pt
);
1184 // find out the screen coordinate at the bottom of the tab ctrl
1185 wxRect cli_rect
= wnd
->GetClientRect();
1186 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1188 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1189 wnd
->PushEventHandler(cc
);
1190 wnd
->PopupMenu(&menuPopup
, pt
);
1191 int command
= cc
->GetCommandId();
1192 wnd
->PopEventHandler(true);
1194 if (command
>= 1000)
1195 return command
-1000;
1200 int wxAuiSimpleTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
1201 wxAuiNotebookPageArray
& WXUNUSED(pages
),
1202 const wxSize
& WXUNUSED(required_bmp_size
))
1205 dc
.SetFont(m_measuring_font
);
1207 wxSize s
= GetTabSize(dc
,
1212 wxAUI_BUTTON_STATE_HIDDEN
,
1217 void wxAuiSimpleTabArt
::SetNormalFont(const wxFont
& font
)
1219 m_normal_font
= font
;
1222 void wxAuiSimpleTabArt
::SetSelectedFont(const wxFont
& font
)
1224 m_selected_font
= font
;
1227 void wxAuiSimpleTabArt
::SetMeasuringFont(const wxFont
& font
)
1229 m_measuring_font
= font
;
1235 // -- wxAuiTabContainer class implementation --
1238 // wxAuiTabContainer is a class which contains information about each
1239 // tab. It also can render an entire tab control to a specified DC.
1240 // It's not a window class itself, because this code will be used by
1241 // the wxFrameMananger, where it is disadvantageous to have separate
1242 // windows for each tab control in the case of "docked tabs"
1244 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1245 // which can be used as a tab control in the normal sense.
1248 wxAuiTabContainer
::wxAuiTabContainer()
1252 m_art
= new wxAuiDefaultTabArt
;
1254 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1255 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1256 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1257 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1260 wxAuiTabContainer
::~wxAuiTabContainer()
1265 void wxAuiTabContainer
::SetArtProvider(wxAuiTabArt
* art
)
1272 m_art
->SetFlags(m_flags
);
1276 wxAuiTabArt
* wxAuiTabContainer
::GetArtProvider() const
1281 void wxAuiTabContainer
::SetFlags(unsigned int flags
)
1285 // check for new close button settings
1286 RemoveButton(wxAUI_BUTTON_LEFT
);
1287 RemoveButton(wxAUI_BUTTON_RIGHT
);
1288 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1289 RemoveButton(wxAUI_BUTTON_CLOSE
);
1292 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1294 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1295 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1298 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1300 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1303 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1305 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1310 m_art
->SetFlags(m_flags
);
1314 unsigned int wxAuiTabContainer
::GetFlags() const
1320 void wxAuiTabContainer
::SetNormalFont(const wxFont
& font
)
1322 m_art
->SetNormalFont(font
);
1325 void wxAuiTabContainer
::SetSelectedFont(const wxFont
& font
)
1327 m_art
->SetSelectedFont(font
);
1330 void wxAuiTabContainer
::SetMeasuringFont(const wxFont
& font
)
1332 m_art
->SetMeasuringFont(font
);
1335 void wxAuiTabContainer
::SetRect(const wxRect
& rect
)
1341 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1345 bool wxAuiTabContainer
::AddPage(wxWindow
* page
,
1346 const wxAuiNotebookPage
& info
)
1348 wxAuiNotebookPage page_info
;
1350 page_info
.window
= page
;
1352 m_pages
.Add(page_info
);
1354 // let the art provider know how many pages we have
1357 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1363 bool wxAuiTabContainer
::InsertPage(wxWindow
* page
,
1364 const wxAuiNotebookPage
& info
,
1367 wxAuiNotebookPage page_info
;
1369 page_info
.window
= page
;
1371 if (idx
>= m_pages
.GetCount())
1372 m_pages
.Add(page_info
);
1374 m_pages
.Insert(page_info
, idx
);
1376 // let the art provider know how many pages we have
1379 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1385 bool wxAuiTabContainer
::MovePage(wxWindow
* page
,
1388 int idx
= GetIdxFromWindow(page
);
1392 // get page entry, make a copy of it
1393 wxAuiNotebookPage p
= GetPage(idx
);
1395 // remove old page entry
1398 // insert page where it should be
1399 InsertPage(page
, p
, new_idx
);
1404 bool wxAuiTabContainer
::RemovePage(wxWindow
* wnd
)
1406 size_t i
, page_count
= m_pages
.GetCount();
1407 for (i
= 0; i
< page_count
; ++i
)
1409 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1410 if (page
.window
== wnd
)
1412 m_pages
.RemoveAt(i
);
1414 // let the art provider know how many pages we have
1417 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1427 bool wxAuiTabContainer
::SetActivePage(wxWindow
* wnd
)
1431 size_t i
, page_count
= m_pages
.GetCount();
1432 for (i
= 0; i
< page_count
; ++i
)
1434 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1435 if (page
.window
== wnd
)
1442 page
.active
= false;
1449 void wxAuiTabContainer
::SetNoneActive()
1451 size_t i
, page_count
= m_pages
.GetCount();
1452 for (i
= 0; i
< page_count
; ++i
)
1454 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1455 page
.active
= false;
1459 bool wxAuiTabContainer
::SetActivePage(size_t page
)
1461 if (page
>= m_pages
.GetCount())
1464 return SetActivePage(m_pages
.Item(page
).window
);
1467 int wxAuiTabContainer
::GetActivePage() const
1469 size_t i
, page_count
= m_pages
.GetCount();
1470 for (i
= 0; i
< page_count
; ++i
)
1472 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1480 wxWindow
* wxAuiTabContainer
::GetWindowFromIdx(size_t idx
) const
1482 if (idx
>= m_pages
.GetCount())
1485 return m_pages
[idx
].window
;
1488 int wxAuiTabContainer
::GetIdxFromWindow(wxWindow
* wnd
) const
1490 size_t i
, page_count
= m_pages
.GetCount();
1491 for (i
= 0; i
< page_count
; ++i
)
1493 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1494 if (page
.window
== wnd
)
1500 wxAuiNotebookPage
& wxAuiTabContainer
::GetPage(size_t idx
)
1502 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1504 return m_pages
[idx
];
1507 wxAuiNotebookPageArray
& wxAuiTabContainer
::GetPages()
1512 size_t wxAuiTabContainer
::GetPageCount() const
1514 return m_pages
.GetCount();
1517 void wxAuiTabContainer
::AddButton(int id
,
1519 const wxBitmap
& normal_bitmap
,
1520 const wxBitmap
& disabled_bitmap
)
1522 wxAuiTabContainerButton button
;
1524 button
.bitmap
= normal_bitmap
;
1525 button
.dis_bitmap
= disabled_bitmap
;
1526 button
.location
= location
;
1527 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1529 m_buttons
.Add(button
);
1532 void wxAuiTabContainer
::RemoveButton(int id
)
1534 size_t i
, button_count
= m_buttons
.GetCount();
1536 for (i
= 0; i
< button_count
; ++i
)
1538 if (m_buttons
.Item(i
).id
== id
)
1540 m_buttons
.RemoveAt(i
);
1548 size_t wxAuiTabContainer
::GetTabOffset() const
1550 return m_tab_offset
;
1553 void wxAuiTabContainer
::SetTabOffset(size_t offset
)
1555 m_tab_offset
= offset
;
1561 // Render() renders the tab catalog to the specified DC
1562 // It is a virtual function and can be overridden to
1563 // provide custom drawing capabilities
1564 void wxAuiTabContainer
::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1566 if (!raw_dc
|| !raw_dc
->IsOk())
1572 size_t page_count
= m_pages
.GetCount();
1573 size_t button_count
= m_buttons
.GetCount();
1575 // create off-screen bitmap
1576 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1577 dc
.SelectObject(bmp
);
1582 // find out if size of tabs is larger than can be
1583 // afforded on screen
1584 int total_width
= 0;
1585 int visible_width
= 0;
1586 for (i
= 0; i
< page_count
; ++i
)
1588 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1590 // determine if a close button is on this tab
1591 bool close_button
= false;
1592 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1593 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1595 close_button
= true;
1600 wxSize size
= m_art
->GetTabSize(dc
,
1606 wxAUI_BUTTON_STATE_NORMAL
:
1607 wxAUI_BUTTON_STATE_HIDDEN
,
1610 if (i
+1 < page_count
)
1611 total_width
+= x_extent
;
1613 total_width
+= size
.x
;
1615 if (i
>= m_tab_offset
)
1617 if (i
+1 < page_count
)
1618 visible_width
+= x_extent
;
1620 visible_width
+= size
.x
;
1624 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1626 // show left/right buttons
1627 for (i
= 0; i
< button_count
; ++i
)
1629 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1630 if (button
.id
== wxAUI_BUTTON_LEFT
||
1631 button
.id
== wxAUI_BUTTON_RIGHT
)
1633 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1639 // hide left/right buttons
1640 for (i
= 0; i
< button_count
; ++i
)
1642 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1643 if (button
.id
== wxAUI_BUTTON_LEFT
||
1644 button
.id
== wxAUI_BUTTON_RIGHT
)
1646 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1651 // determine whether left button should be enabled
1652 for (i
= 0; i
< button_count
; ++i
)
1654 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1655 if (button
.id
== wxAUI_BUTTON_LEFT
)
1657 if (m_tab_offset
== 0)
1658 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1660 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1662 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1664 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1665 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1667 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1674 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1677 int left_buttons_width
= 0;
1678 int right_buttons_width
= 0;
1682 // draw the buttons on the right side
1683 offset
= m_rect
.x
+ m_rect
.width
;
1684 for (i
= 0; i
< button_count
; ++i
)
1686 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1688 if (button
.location
!= wxRIGHT
)
1690 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1693 wxRect button_rect
= m_rect
;
1694 button_rect
.SetY(1);
1695 button_rect
.SetWidth(offset
);
1697 m_art
->DrawButton(dc
,
1706 offset
-= button
.rect
.GetWidth();
1707 right_buttons_width
+= button
.rect
.GetWidth();
1714 // draw the buttons on the left side
1716 for (i
= 0; i
< button_count
; ++i
)
1718 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1720 if (button
.location
!= wxLEFT
)
1722 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1725 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1727 m_art
->DrawButton(dc
,
1736 offset
+= button
.rect
.GetWidth();
1737 left_buttons_width
+= button
.rect
.GetWidth();
1740 offset
= left_buttons_width
;
1743 offset
+= m_art
->GetIndentSize();
1746 // prepare the tab-close-button array
1747 // make sure tab button entries which aren't used are marked as hidden
1748 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1749 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1751 // make sure there are enough tab button entries to accommodate all tabs
1752 while (m_tab_close_buttons
.GetCount() < page_count
)
1754 wxAuiTabContainerButton tempbtn
;
1755 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1756 tempbtn
.location
= wxCENTER
;
1757 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1758 m_tab_close_buttons
.Add(tempbtn
);
1762 // buttons before the tab offset must be set to hidden
1763 for (i
= 0; i
< m_tab_offset
; ++i
)
1765 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1771 size_t active
= 999;
1772 int active_offset
= 0;
1776 wxRect rect
= m_rect
;
1778 rect
.height
= m_rect
.height
;
1780 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1782 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1783 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1785 // determine if a close button is on this tab
1786 bool close_button
= false;
1787 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1788 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1790 close_button
= true;
1791 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1793 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1794 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1795 tab_button
.location
= wxCENTER
;
1800 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1804 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1806 if (rect
.width
<= 0)
1815 tab_button
.cur_state
,
1823 active_offset
= offset
;
1831 // make sure to deactivate buttons which are off the screen to the right
1832 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1834 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1838 // draw the active tab again so it stands in the foreground
1839 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1841 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1843 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1845 // determine if a close button is on this tab
1846 bool close_button
= false;
1847 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1848 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1850 close_button
= true;
1853 rect
.x
= active_offset
;
1860 tab_button
.cur_state
,
1867 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1868 m_rect
.GetWidth(), m_rect
.GetHeight(),
1873 // TabHitTest() tests if a tab was hit, passing the window pointer
1874 // back if that condition was fulfilled. The function returns
1875 // true if a tab was hit, otherwise false
1876 bool wxAuiTabContainer
::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1878 if (!m_rect
.Contains(x
,y
))
1881 wxAuiTabContainerButton
* btn
= NULL
;
1882 if (ButtonHitTest(x
, y
, &btn
))
1884 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1888 size_t i
, page_count
= m_pages
.GetCount();
1890 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1892 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1893 if (page
.rect
.Contains(x
,y
))
1904 // ButtonHitTest() tests if a button was hit. The function returns
1905 // true if a button was hit, otherwise false
1906 bool wxAuiTabContainer
::ButtonHitTest(int x
, int y
,
1907 wxAuiTabContainerButton
** hit
) const
1909 if (!m_rect
.Contains(x
,y
))
1912 size_t i
, button_count
;
1915 button_count
= m_buttons
.GetCount();
1916 for (i
= 0; i
< button_count
; ++i
)
1918 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1919 if (button
.rect
.Contains(x
,y
) &&
1920 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1921 wxAUI_BUTTON_STATE_DISABLED
)))
1929 button_count
= m_tab_close_buttons
.GetCount();
1930 for (i
= 0; i
< button_count
; ++i
)
1932 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1933 if (button
.rect
.Contains(x
,y
) &&
1934 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1935 wxAUI_BUTTON_STATE_DISABLED
)))
1948 // the utility function ShowWnd() is the same as show,
1949 // except it handles wxAuiMDIChildFrame windows as well,
1950 // as the Show() method on this class is "unplugged"
1951 static void ShowWnd(wxWindow
* wnd
, bool show
)
1953 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1955 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1965 // DoShowHide() this function shows the active window, then
1966 // hides all of the other windows (in that order)
1967 void wxAuiTabContainer
::DoShowHide()
1969 wxAuiNotebookPageArray
& pages
= GetPages();
1970 size_t i
, page_count
= pages
.GetCount();
1972 // show new active page first
1973 for (i
= 0; i
< page_count
; ++i
)
1975 wxAuiNotebookPage
& page
= pages
.Item(i
);
1978 ShowWnd(page
.window
, true);
1983 // hide all other pages
1984 for (i
= 0; i
< page_count
; ++i
)
1986 wxAuiNotebookPage
& page
= pages
.Item(i
);
1987 ShowWnd(page
.window
, page
.active
);
1996 // -- wxAuiTabCtrl class implementation --
2000 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2001 EVT_PAINT(wxAuiTabCtrl
::OnPaint
)
2002 EVT_ERASE_BACKGROUND(wxAuiTabCtrl
::OnEraseBackground
)
2003 EVT_SIZE(wxAuiTabCtrl
::OnSize
)
2004 EVT_LEFT_DOWN(wxAuiTabCtrl
::OnLeftDown
)
2005 EVT_LEFT_UP(wxAuiTabCtrl
::OnLeftUp
)
2006 EVT_MOTION(wxAuiTabCtrl
::OnMotion
)
2007 EVT_LEAVE_WINDOW(wxAuiTabCtrl
::OnLeaveWindow
)
2008 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl
::OnButton
)
2012 wxAuiTabCtrl
::wxAuiTabCtrl(wxWindow
* parent
,
2016 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2018 m_click_pt
= wxDefaultPosition
;
2019 m_is_dragging
= false;
2020 m_hover_button
= NULL
;
2021 m_pressed_button
= NULL
;
2024 wxAuiTabCtrl
::~wxAuiTabCtrl()
2028 void wxAuiTabCtrl
::OnPaint(wxPaintEvent
&)
2032 dc
.SetFont(GetFont());
2034 if (GetPageCount() > 0)
2038 void wxAuiTabCtrl
::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2042 void wxAuiTabCtrl
::OnSize(wxSizeEvent
& evt
)
2044 wxSize s
= evt
.GetSize();
2045 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2049 void wxAuiTabCtrl
::OnLeftDown(wxMouseEvent
& evt
)
2052 m_click_pt
= wxDefaultPosition
;
2053 m_is_dragging
= false;
2055 m_pressed_button
= NULL
;
2059 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2061 int new_selection
= GetIdxFromWindow(wnd
);
2063 if (new_selection
!= GetActivePage())
2065 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2066 e
.SetSelection(new_selection
);
2067 e
.SetOldSelection(GetActivePage());
2068 e
.SetEventObject(this);
2069 GetEventHandler()->ProcessEvent(e
);
2072 m_click_pt
.x
= evt
.m_x
;
2073 m_click_pt
.y
= evt
.m_y
;
2079 m_pressed_button
= m_hover_button
;
2080 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2086 void wxAuiTabCtrl
::OnLeftUp(wxMouseEvent
& evt
)
2088 if (GetCapture() == this)
2093 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2094 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2095 evt
.SetOldSelection(evt
.GetSelection());
2096 evt
.SetEventObject(this);
2097 GetEventHandler()->ProcessEvent(evt
);
2101 if (m_pressed_button
)
2103 // make sure we're still clicking the button
2104 wxAuiTabContainerButton
* button
= NULL
;
2105 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2108 if (button
!= m_pressed_button
)
2110 m_pressed_button
= NULL
;
2117 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2119 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2120 evt
.SetInt(m_pressed_button
->id
);
2121 evt
.SetEventObject(this);
2122 GetEventHandler()->ProcessEvent(evt
);
2125 m_pressed_button
= NULL
;
2128 m_click_pt
= wxDefaultPosition
;
2129 m_is_dragging
= false;
2133 void wxAuiTabCtrl
::OnMotion(wxMouseEvent
& evt
)
2135 wxPoint pos
= evt
.GetPosition();
2137 // check if the mouse is hovering above a button
2138 wxAuiTabContainerButton
* button
;
2139 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2141 if (m_hover_button
&& button
!= m_hover_button
)
2143 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2144 m_hover_button
= NULL
;
2149 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2151 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2154 m_hover_button
= button
;
2162 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2163 m_hover_button
= NULL
;
2170 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2175 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2176 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2177 evt
.SetOldSelection(evt
.GetSelection());
2178 evt
.SetEventObject(this);
2179 GetEventHandler()->ProcessEvent(evt
);
2184 int drag_x_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_X
);
2185 int drag_y_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_Y
);
2187 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2188 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2190 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2191 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2192 evt
.SetOldSelection(evt
.GetSelection());
2193 evt
.SetEventObject(this);
2194 GetEventHandler()->ProcessEvent(evt
);
2196 m_is_dragging
= true;
2200 void wxAuiTabCtrl
::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2204 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2205 m_hover_button
= NULL
;
2211 void wxAuiTabCtrl
::OnButton(wxAuiNotebookEvent
& event
)
2213 int button
= event
.GetInt();
2215 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2217 if (button
== wxAUI_BUTTON_LEFT
)
2219 if (GetTabOffset() > 0)
2221 SetTabOffset(GetTabOffset()-1);
2228 SetTabOffset(GetTabOffset()+1);
2233 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2237 size_t i
, page_count
= m_pages
.GetCount();
2238 for (i
= 0; i
< page_count
; ++i
)
2240 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2241 as
.Add(page
.caption
);
2244 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2248 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2249 e
.SetSelection(idx
);
2250 e
.SetOldSelection(GetActivePage());
2251 e
.SetEventObject(this);
2252 GetEventHandler()->ProcessEvent(e
);
2261 // wxTabFrame is an interesting case. It's important that all child pages
2262 // of the multi-notebook control are all actually children of that control
2263 // (and not grandchildren). wxTabFrame facilitates this. There is one
2264 // instance of wxTabFrame for each tab control inside the multi-notebook.
2265 // It's important to know that wxTabFrame is not a real window, but it merely
2266 // used to capture the dimensions/positioning of the internal tab control and
2267 // it's managed page windows
2269 class wxTabFrame
: public wxWindow
2276 m_rect
= wxRect(0,0,200,200);
2277 m_tab_ctrl_height
= 20;
2280 void SetTabCtrlHeight(int h
)
2282 m_tab_ctrl_height
= h
;
2285 void DoSetSize(int x
, int y
,
2286 int width
, int height
,
2287 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2289 m_rect
= wxRect(x
, y
, width
, height
);
2293 void DoGetClientSize(int* x
, int* y
) const
2299 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2306 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2307 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2308 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2312 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2313 size_t i
, page_count
= pages
.GetCount();
2315 for (i
= 0; i
< page_count
; ++i
)
2317 wxAuiNotebookPage
& page
= pages
.Item(i
);
2318 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2319 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2321 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2323 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2324 wnd
->ApplyMDIChildFrameRect();
2329 void DoGetSize(int* x
, int* y
) const
2332 *x
= m_rect
.GetWidth();
2334 *y
= m_rect
.GetHeight();
2346 wxAuiTabCtrl
* m_tabs
;
2347 int m_tab_ctrl_height
;
2354 // -- wxAuiNotebook class implementation --
2356 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2357 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2358 EVT_SIZE(wxAuiNotebook
::OnSize
)
2359 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2360 EVT_CHILD_FOCUS(wxAuiNotebook
::OnChildFocus
)
2361 EVT_COMMAND_RANGE(10000, 10100,
2362 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2363 wxAuiNotebook
::OnTabClicked
)
2364 EVT_COMMAND_RANGE(10000, 10100,
2365 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2366 wxAuiNotebook
::OnTabBeginDrag
)
2367 EVT_COMMAND_RANGE(10000, 10100,
2368 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2369 wxAuiNotebook
::OnTabEndDrag
)
2370 EVT_COMMAND_RANGE(10000, 10100,
2371 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2372 wxAuiNotebook
::OnTabDragMotion
)
2373 EVT_COMMAND_RANGE(10000, 10100,
2374 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2375 wxAuiNotebook
::OnTabButton
)
2378 wxAuiNotebook
::wxAuiNotebook()
2381 m_tab_id_counter
= 10000;
2383 m_tab_ctrl_height
= 20;
2384 m_requested_bmp_size
= wxDefaultSize
;
2385 m_requested_tabctrl_height
= -1;
2388 wxAuiNotebook
::wxAuiNotebook(wxWindow
*parent
,
2392 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2395 m_requested_bmp_size
= wxDefaultSize
;
2396 m_requested_tabctrl_height
= -1;
2397 InitNotebook(style
);
2400 bool wxAuiNotebook
::Create(wxWindow
* parent
,
2406 if (!wxControl
::Create(parent
, id
, pos
, size
, style
))
2409 InitNotebook(style
);
2414 // InitNotebook() contains common initialization
2415 // code called by all constructors
2416 void wxAuiNotebook
::InitNotebook(long style
)
2419 m_tab_id_counter
= 10000;
2421 m_flags
= (unsigned int)style
;
2422 m_tab_ctrl_height
= 20;
2424 m_normal_font
= *wxNORMAL_FONT
;
2425 m_selected_font
= *wxNORMAL_FONT
;
2426 m_selected_font
.SetWeight(wxBOLD
);
2428 SetArtProvider(new wxAuiDefaultTabArt
);
2430 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2431 m_dummy_wnd
->SetSize(200, 200);
2432 m_dummy_wnd
->Show(false);
2434 m_mgr
.SetManagedWindow(this);
2435 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
| (1 << 28) /*wxAUI_MGR_NO_DOCK_SIZE_LIMIT*/);
2437 m_mgr
.AddPane(m_dummy_wnd
,
2438 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2443 wxAuiNotebook
::~wxAuiNotebook()
2448 void wxAuiNotebook
::SetArtProvider(wxAuiTabArt
* art
)
2450 m_tabs
.SetArtProvider(art
);
2452 UpdateTabCtrlHeight();
2455 // SetTabCtrlHeight() is the highest-level override of the
2456 // tab height. A call to this function effectively enforces a
2457 // specified tab ctrl height, overriding all other considerations,
2458 // such as text or bitmap height. It overrides any call to
2459 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2460 // any previous call and returns to the default behavior
2462 void wxAuiNotebook
::SetTabCtrlHeight(int height
)
2464 m_requested_tabctrl_height
= height
;
2466 // if window is already initialized, recalculate the tab height
2469 UpdateTabCtrlHeight();
2474 // SetUniformBitmapSize() ensures that all tabs will have
2475 // the same height, even if some tabs don't have bitmaps
2476 // Passing wxDefaultSize to this function will instruct
2477 // the control to use dynamic tab height-- so when a tab
2478 // with a large bitmap is added, the tab ctrl's height will
2479 // automatically increase to accommodate the bitmap
2481 void wxAuiNotebook
::SetUniformBitmapSize(const wxSize
& size
)
2483 m_requested_bmp_size
= size
;
2485 // if window is already initialized, recalculate the tab height
2488 UpdateTabCtrlHeight();
2492 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2493 // to be used interally
2494 void wxAuiNotebook
::UpdateTabCtrlHeight()
2496 // get the tab ctrl height we will use
2497 int height
= CalculateTabCtrlHeight();
2499 // if the tab control height needs to change, update
2500 // all of our tab controls with the new height
2501 if (m_tab_ctrl_height
!= height
)
2503 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2505 m_tab_ctrl_height
= height
;
2507 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2508 size_t i
, pane_count
= all_panes
.GetCount();
2509 for (i
= 0; i
< pane_count
; ++i
)
2511 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2512 if (pane
.name
== wxT("dummy"))
2514 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2515 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2516 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2517 tabctrl
->SetArtProvider(art
->Clone());
2518 tab_frame
->DoSizing();
2523 void wxAuiNotebook
::UpdateHintWindowSize()
2525 wxSize size
= CalculateNewSplitSize();
2527 // the placeholder hint window should be set to this size
2528 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2532 info
.BestSize(size
);
2533 m_dummy_wnd
->SetSize(size
);
2538 // calculates the size of the new split
2539 wxSize wxAuiNotebook
::CalculateNewSplitSize()
2541 // count number of tab controls
2542 int tab_ctrl_count
= 0;
2543 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2544 size_t i
, pane_count
= all_panes
.GetCount();
2545 for (i
= 0; i
< pane_count
; ++i
)
2547 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2548 if (pane
.name
== wxT("dummy"))
2553 wxSize new_split_size
;
2555 // if there is only one tab control, the first split
2556 // should happen around the middle
2557 if (tab_ctrl_count
< 2)
2559 new_split_size
= GetClientSize();
2560 new_split_size
.x
/= 2;
2561 new_split_size
.y
/= 2;
2565 // this is in place of a more complicated calculation
2566 // that needs to be implemented
2567 new_split_size
= wxSize(180,180);
2570 return new_split_size
;
2573 int wxAuiNotebook
::CalculateTabCtrlHeight()
2575 // if a fixed tab ctrl height is specified,
2576 // just return that instead of calculating a
2578 if (m_requested_tabctrl_height
!= -1)
2579 return m_requested_tabctrl_height
;
2581 // find out new best tab height
2582 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2584 return art
->GetBestTabCtrlSize(this,
2586 m_requested_bmp_size
);
2590 wxAuiTabArt
* wxAuiNotebook
::GetArtProvider() const
2592 return m_tabs
.GetArtProvider();
2595 void wxAuiNotebook
::SetWindowStyleFlag(long style
)
2597 wxControl
::SetWindowStyleFlag(style
);
2599 m_flags
= (unsigned int)style
;
2601 // if the control is already initialized
2602 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2604 // let all of the tab children know about the new style
2606 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2607 size_t i
, pane_count
= all_panes
.GetCount();
2608 for (i
= 0; i
< pane_count
; ++i
)
2610 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2611 if (pane
.name
== wxT("dummy"))
2613 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2614 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2615 tabctrl
->SetFlags(m_flags
);
2616 tabframe
->DoSizing();
2624 bool wxAuiNotebook
::AddPage(wxWindow
* page
,
2625 const wxString
& caption
,
2627 const wxBitmap
& bitmap
)
2629 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2632 bool wxAuiNotebook
::InsertPage(size_t page_idx
,
2634 const wxString
& caption
,
2636 const wxBitmap
& bitmap
)
2638 wxAuiNotebookPage info
;
2640 info
.caption
= caption
;
2641 info
.bitmap
= bitmap
;
2642 info
.active
= false;
2644 // if there are currently no tabs, the first added
2645 // tab must be active
2646 if (m_tabs
.GetPageCount() == 0)
2649 m_tabs
.InsertPage(page
, info
, page_idx
);
2651 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2652 if (page_idx
>= active_tabctrl
->GetPageCount())
2653 active_tabctrl
->AddPage(page
, info
);
2655 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2657 UpdateTabCtrlHeight();
2659 active_tabctrl
->DoShowHide();
2663 int idx
= m_tabs
.GetIdxFromWindow(page
);
2664 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2673 // DeletePage() removes a tab from the multi-notebook,
2674 // and destroys the window as well
2675 bool wxAuiNotebook
::DeletePage(size_t page_idx
)
2677 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2679 if (!RemovePage(page_idx
))
2682 // actually destroy the window now
2683 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2685 // delete the child frame with pending delete, as is
2686 // customary with frame windows
2687 if (!wxPendingDelete
.Member(wnd
))
2688 wxPendingDelete
.Append(wnd
);
2700 // RemovePage() removes a tab from the multi-notebook,
2701 // but does not destroy the window
2702 bool wxAuiNotebook
::RemovePage(size_t page_idx
)
2704 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2705 wxWindow
* new_active
= NULL
;
2707 // find out which onscreen tab ctrl owns this tab
2710 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2713 // find a new page and set it as active
2714 int new_idx
= ctrl_idx
+1;
2715 if (new_idx
>= (int)ctrl
->GetPageCount())
2716 new_idx
= ctrl_idx
-1;
2718 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2720 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2724 // set the active page to the first page that
2725 // isn't the one being deleted
2726 size_t i
, page_count
= m_tabs
.GetPageCount();
2727 for (i
= 0; i
< page_count
; ++i
)
2729 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2732 new_active
= m_tabs
.GetWindowFromIdx(i
);
2738 // remove the tab from main catalog
2739 if (!m_tabs
.RemovePage(wnd
))
2742 // remove the tab from the onscreen tab ctrl
2743 ctrl
->RemovePage(wnd
);
2746 RemoveEmptyTabFrames();
2748 // set new active pane
2752 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2758 // GetPageIndex() returns the index of the page, or -1 if the
2759 // page could not be located in the notebook
2760 int wxAuiNotebook
::GetPageIndex(wxWindow
* page_wnd
) const
2762 return m_tabs
.GetIdxFromWindow(page_wnd
);
2767 // SetPageText() changes the tab caption of the specified page
2768 bool wxAuiNotebook
::SetPageText(size_t page_idx
, const wxString
& text
)
2770 if (page_idx
>= m_tabs
.GetPageCount())
2773 // update our own tab catalog
2774 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2775 page_info
.caption
= text
;
2777 // update what's on screen
2780 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2782 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2783 info
.caption
= text
;
2792 bool wxAuiNotebook
::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2794 if (page_idx
>= m_tabs
.GetPageCount())
2797 // update our own tab catalog
2798 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2799 page_info
.bitmap
= bitmap
;
2801 // tab height might have changed
2802 UpdateTabCtrlHeight();
2804 // update what's on screen
2807 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2809 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2810 info
.bitmap
= bitmap
;
2819 // GetSelection() returns the index of the currently active page
2820 int wxAuiNotebook
::GetSelection() const
2825 // SetSelection() sets the currently active page
2826 size_t wxAuiNotebook
::SetSelection(size_t new_page
)
2828 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2832 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2833 evt
.SetSelection(new_page
);
2834 evt
.SetOldSelection(m_curpage
);
2835 evt
.SetEventObject(this);
2836 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2838 int old_curpage
= m_curpage
;
2839 m_curpage
= new_page
;
2841 // program allows the page change
2842 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2843 (void)GetEventHandler()->ProcessEvent(evt
);
2848 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2850 m_tabs
.SetActivePage(wnd
);
2852 ctrl
->SetActivePage(ctrl_idx
);
2859 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2860 size_t i
, pane_count
= all_panes
.GetCount();
2861 for (i
= 0; i
< pane_count
; ++i
)
2863 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2864 if (pane
.name
== wxT("dummy"))
2866 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2867 if (tabctrl
!= ctrl
)
2868 tabctrl
->SetSelectedFont(m_normal_font
);
2870 tabctrl
->SetSelectedFont(m_selected_font
);
2883 // GetPageCount() returns the total number of
2884 // pages managed by the multi-notebook
2885 size_t wxAuiNotebook
::GetPageCount() const
2887 return m_tabs
.GetPageCount();
2890 // GetPage() returns the wxWindow pointer of the
2892 wxWindow
* wxAuiNotebook
::GetPage(size_t page_idx
) const
2894 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2896 return m_tabs
.GetWindowFromIdx(page_idx
);
2899 // DoSizing() performs all sizing operations in each tab control
2900 void wxAuiNotebook
::DoSizing()
2902 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2903 size_t i
, pane_count
= all_panes
.GetCount();
2904 for (i
= 0; i
< pane_count
; ++i
)
2906 if (all_panes
.Item(i
).name
== wxT("dummy"))
2909 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2910 tabframe
->DoSizing();
2914 // GetActiveTabCtrl() returns the active tab control. It is
2915 // called to determine which control gets new windows being added
2916 wxAuiTabCtrl
* wxAuiNotebook
::GetActiveTabCtrl()
2918 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2923 // find the tab ctrl with the current page
2924 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2931 // no current page, just find the first tab ctrl
2932 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2933 size_t i
, pane_count
= all_panes
.GetCount();
2934 for (i
= 0; i
< pane_count
; ++i
)
2936 if (all_panes
.Item(i
).name
== wxT("dummy"))
2939 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2940 return tabframe
->m_tabs
;
2943 // If there is no tabframe at all, create one
2944 wxTabFrame
* tabframe
= new wxTabFrame
;
2945 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2946 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2951 tabframe
->m_tabs
->SetFlags(m_flags
);
2952 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2953 m_mgr
.AddPane(tabframe
,
2954 wxAuiPaneInfo().Center().CaptionVisible(false));
2958 return tabframe
->m_tabs
;
2961 // FindTab() finds the tab control that currently contains the window as well
2962 // as the index of the window in the tab control. It returns true if the
2963 // window was found, otherwise false.
2964 bool wxAuiNotebook
::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2966 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2967 size_t i
, pane_count
= all_panes
.GetCount();
2968 for (i
= 0; i
< pane_count
; ++i
)
2970 if (all_panes
.Item(i
).name
== wxT("dummy"))
2973 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2975 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2978 *ctrl
= tabframe
->m_tabs
;
2988 void wxAuiNotebook
::OnEraseBackground(wxEraseEvent
&)
2992 void wxAuiNotebook
::OnSize(wxSizeEvent
& evt
)
2994 UpdateHintWindowSize();
2999 void wxAuiNotebook
::OnTabClicked(wxCommandEvent
& command_evt
)
3001 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3003 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3004 wxASSERT(ctrl
!= NULL
);
3006 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3007 wxASSERT(wnd
!= NULL
);
3009 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
3010 wxASSERT(idx
!= -1);
3015 void wxAuiNotebook
::OnTabBeginDrag(wxCommandEvent
&)
3020 void wxAuiNotebook
::OnTabDragMotion(wxCommandEvent
& evt
)
3022 wxPoint screen_pt
= ::wxGetMousePosition();
3023 wxPoint client_pt
= ScreenToClient(screen_pt
);
3026 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3027 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3029 if (dest_tabs
== src_tabs
)
3033 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3036 // always hide the hint for inner-tabctrl drag
3039 // if tab moving is not allowed, leave
3040 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3045 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3046 wxWindow
* dest_location_tab
;
3048 // this is an inner-tab drag/reposition
3049 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3051 int src_idx
= evt
.GetSelection();
3052 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3054 // prevent jumpy drag
3055 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3056 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3057 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3059 m_last_drag_x
= pt
.x
;
3064 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3065 dest_tabs
->MovePage(src_tab
, dest_idx
);
3066 dest_tabs
->SetActivePage((size_t)dest_idx
);
3067 dest_tabs
->DoShowHide();
3068 dest_tabs
->Refresh();
3069 m_last_drag_x
= pt
.x
;
3077 // if external drag is allowed, check if the tab is being dragged
3078 // over a different wxAuiNotebook control
3079 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3081 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3083 // if we aren't over any window, stop here
3087 // make sure we are not over the hint window
3088 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3092 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3094 tab_ctrl
= tab_ctrl
->GetParent();
3099 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3103 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3104 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3105 m_mgr
.ShowHint(hint_rect
);
3114 // we are either over a hint window, or not over a tab
3115 // window, and there is no where to drag to, so exit
3122 // if there are less than two panes, split can't happen, so leave
3123 if (m_tabs
.GetPageCount() < 2)
3126 // if tab moving is not allowed, leave
3127 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3133 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3139 wxRect hint_rect
= dest_tabs
->GetRect();
3140 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3141 m_mgr
.ShowHint(hint_rect
);
3145 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3151 void wxAuiNotebook
::OnTabEndDrag(wxCommandEvent
& command_evt
)
3153 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3158 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3159 wxAuiTabCtrl
* dest_tabs
= NULL
;
3162 // set cursor back to an arrow
3163 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3166 // get the mouse position, which will be used to determine the drop point
3167 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3168 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3172 // check for an external move
3173 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3175 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3179 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3181 tab_ctrl
= tab_ctrl
->GetParent();
3186 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3190 // find out from the destination control
3191 // if it's ok to drop this tab here
3192 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3193 e
.SetSelection(evt
.GetSelection());
3194 e
.SetOldSelection(evt
.GetSelection());
3195 e
.SetEventObject(this);
3196 e
.SetDragSource(this);
3197 e
.Veto(); // dropping must be explicitly approved by control owner
3199 nb
->GetEventHandler()->ProcessEvent(e
);
3203 // no answer or negative answer
3209 int src_idx
= evt
.GetSelection();
3210 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3212 // get main index of the page
3213 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3215 // make a copy of the page info
3216 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3218 // remove the page from the source notebook
3219 RemovePage(main_idx
);
3221 // reparent the page
3222 src_page
->Reparent(nb
);
3225 // found out the insert idx
3226 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3227 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3229 wxWindow
* target
= NULL
;
3230 int insert_idx
= -1;
3231 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3234 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3238 // add the page to the new notebook
3239 if (insert_idx
== -1)
3240 insert_idx
= dest_tabs
->GetPageCount();
3241 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3242 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3245 dest_tabs
->DoShowHide();
3246 dest_tabs
->Refresh();
3248 // set the selection in the destination tab control
3249 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3259 // only perform a tab split if it's allowed
3260 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3262 // If the pointer is in an existing tab frame, do a tab insert
3263 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3264 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3265 int insert_idx
= -1;
3268 dest_tabs
= tab_frame
->m_tabs
;
3270 if (dest_tabs
== src_tabs
)
3274 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3275 wxWindow
* target
= NULL
;
3276 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3279 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3285 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3290 // there is no suitable drop location here, exit out
3294 // If there is no tabframe at all, create one
3295 wxTabFrame
* new_tabs
= new wxTabFrame
;
3296 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3297 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3298 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3303 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3304 new_tabs
->m_tabs
->SetFlags(m_flags
);
3306 m_mgr
.AddPane(new_tabs
,
3307 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3310 dest_tabs
= new_tabs
->m_tabs
;
3315 // remove the page from the source tabs
3316 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3317 page_info
.active
= false;
3318 src_tabs
->RemovePage(page_info
.window
);
3319 if (src_tabs
->GetPageCount() > 0)
3321 src_tabs
->SetActivePage((size_t)0);
3322 src_tabs
->DoShowHide();
3323 src_tabs
->Refresh();
3328 // add the page to the destination tabs
3329 if (insert_idx
== -1)
3330 insert_idx
= dest_tabs
->GetPageCount();
3331 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3333 if (src_tabs
->GetPageCount() == 0)
3335 RemoveEmptyTabFrames();
3339 dest_tabs
->DoShowHide();
3340 dest_tabs
->Refresh();
3342 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3344 UpdateHintWindowSize();
3350 wxAuiTabCtrl
* wxAuiNotebook
::GetTabCtrlFromPoint(const wxPoint
& pt
)
3352 // if we've just removed the last tab from the source
3353 // tab set, the remove the tab control completely
3354 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3355 size_t i
, pane_count
= all_panes
.GetCount();
3356 for (i
= 0; i
< pane_count
; ++i
)
3358 if (all_panes
.Item(i
).name
== wxT("dummy"))
3361 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3362 if (tabframe
->m_tab_rect
.Contains(pt
))
3363 return tabframe
->m_tabs
;
3369 wxWindow
* wxAuiNotebook
::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3371 // if we've just removed the last tab from the source
3372 // tab set, the remove the tab control completely
3373 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3374 size_t i
, pane_count
= all_panes
.GetCount();
3375 for (i
= 0; i
< pane_count
; ++i
)
3377 if (all_panes
.Item(i
).name
== wxT("dummy"))
3380 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3381 if (tabframe
->m_tabs
== tab_ctrl
)
3390 void wxAuiNotebook
::RemoveEmptyTabFrames()
3392 // if we've just removed the last tab from the source
3393 // tab set, the remove the tab control completely
3394 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3395 size_t i
, pane_count
= all_panes
.GetCount();
3396 for (i
= 0; i
< pane_count
; ++i
)
3398 if (all_panes
.Item(i
).name
== wxT("dummy"))
3401 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3402 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3404 m_mgr
.DetachPane(tab_frame
);
3406 // use pending delete because sometimes during
3407 // window closing, refreshs are pending
3408 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3409 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3410 //tab_frame->m_tabs->Destroy();
3417 // check to see if there is still a center pane;
3418 // if there isn't, make a frame the center pane
3419 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3420 pane_count
= panes
.GetCount();
3421 wxWindow
* first_good
= NULL
;
3422 bool center_found
= false;
3423 for (i
= 0; i
< pane_count
; ++i
)
3425 if (panes
.Item(i
).name
== wxT("dummy"))
3427 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3428 center_found
= true;
3430 first_good
= panes
.Item(i
).window
;
3433 if (!center_found
&& first_good
)
3435 m_mgr
.GetPane(first_good
).Centre();
3441 void wxAuiNotebook
::OnChildFocus(wxChildFocusEvent
& evt
)
3443 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3444 if (idx
!= -1 && idx
!= m_curpage
)
3451 void wxAuiNotebook
::OnTabButton(wxCommandEvent
& command_evt
)
3453 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3454 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3456 int button_id
= evt
.GetInt();
3458 if (button_id
== wxAUI_BUTTON_CLOSE
)
3460 int selection
= tabs
->GetActivePage();
3462 if (selection
!= -1)
3464 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3467 // ask owner if it's ok to close the tab
3468 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3469 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3470 e
.SetOldSelection(evt
.GetSelection());
3471 e
.SetEventObject(this);
3472 GetEventHandler()->ProcessEvent(e
);
3477 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3483 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3484 DeletePage(main_idx
);