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"
34 #include "wx/arrimpl.cpp"
35 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
36 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
48 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
49 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
50 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
56 // This functions are here for this proof of concept
57 // and will be factored out later. See dockart.cpp
58 static wxColor
StepColour(const wxColor
& c
, int percent
)
60 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
61 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
62 (unsigned char)wxMin((g
*percent
)/100,255),
63 (unsigned char)wxMin((b
*percent
)/100,255));
66 // This functions are here for this proof of concept
67 // and will be factored out later. See dockart.cpp
68 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
69 const wxColour
& color
)
71 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
72 img
.Replace(0,0,0,123,123,123);
73 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
74 img
.SetMaskColour(123,123,123);
78 static void DrawButtons(wxDC
& dc
,
81 const wxColour
& bkcolour
,
86 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
93 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
95 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
96 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
98 // draw the background behind the button
99 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
102 // draw the button itself
103 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
106 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
108 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
115 // chops the text so that it fits within |max_size| pixels.
116 // Also adds an elipsis if necessary
118 static wxString
ChopText(wxDC
& dc
, const wxString
& text
, int max_size
)
122 // first check if the text fits with no problems
123 dc
.GetTextExtent(text
, &x
, &y
);
127 size_t i
, len
= text
.Length();
128 size_t last_good_length
= 0;
129 for (i
= 0; i
< len
; ++i
)
131 wxString s
= text
.Left(i
);
134 dc
.GetTextExtent(s
, &x
, &y
);
138 last_good_length
= i
;
141 wxString ret
= text
.Left(last_good_length
);
147 // -- GUI helper classes and functions --
149 class wxAuiCommandCapture
: public wxEvtHandler
153 wxAuiCommandCapture() { m_last_id
= 0; }
154 int GetCommandId() const { return m_last_id
; }
156 bool ProcessEvent(wxEvent
& evt
)
158 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
160 m_last_id
= evt
.GetId();
164 if (GetNextHandler())
165 return GetNextHandler()->ProcessEvent(evt
);
177 #if defined( __WXMAC__ )
178 static unsigned char close_bits
[]={
179 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
180 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
181 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
182 #elif defined( __WXGTK__)
183 static unsigned char close_bits
[]={
184 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
185 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
186 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
188 static unsigned char close_bits
[]={
189 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
190 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
191 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
194 static unsigned char left_bits
[] = {
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
196 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
199 static unsigned char right_bits
[] = {
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
201 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
204 static unsigned char list_bits
[] = {
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
214 // -- wxAuiDefaultTabArt class implementation --
216 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
218 m_normal_font
= *wxNORMAL_FONT
;
219 m_selected_font
= *wxNORMAL_FONT
;
220 m_selected_font
.SetWeight(wxBOLD
);
221 m_measuring_font
= m_selected_font
;
223 m_fixed_tab_width
= 100;
225 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
227 wxColour background_colour
= base_colour
;
228 wxColour normaltab_colour
= base_colour
;
229 wxColour selectedtab_colour
= base_colour
;
231 m_bkbrush
= wxBrush(background_colour
);
232 m_normal_bkbrush
= wxBrush(normaltab_colour
);
233 m_normal_bkpen
= wxPen(normaltab_colour
);
234 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
235 m_selected_bkpen
= wxPen(selectedtab_colour
);
238 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
239 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
241 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
242 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
244 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
245 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
247 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
248 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
253 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
257 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
259 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
262 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
267 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
270 m_fixed_tab_width
= 100;
272 int tot_width
= tab_ctrl_size
.x
;
275 m_fixed_tab_width
= tot_width
/(int)tab_count
;
279 if (m_fixed_tab_width
< 100)
280 m_fixed_tab_width
= 100;
282 if (m_fixed_tab_width
> tot_width
/2)
283 m_fixed_tab_width
= tot_width
/2;
285 if (m_fixed_tab_width
> 220)
286 m_fixed_tab_width
= 220;
290 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
291 wxWindow
* WXUNUSED(wnd
),
295 dc
.SetBrush(m_bkbrush
);
296 dc
.SetPen(*wxTRANSPARENT_PEN
);
297 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
300 dc
.SetPen(*wxGREY_PEN
);
301 dc
.DrawLine(0, rect
.GetHeight()-4, rect
.GetWidth(), rect
.GetHeight()-4);
302 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
306 // DrawTab() draws an individual tab.
309 // in_rect - rectangle the tab should be confined to
310 // caption - tab's caption
311 // active - whether or not the tab is active
312 // out_rect - actual output rectangle
313 // x_extent - the advance x; where the next tab should start
315 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
317 const wxRect
& in_rect
,
318 const wxString
& caption_text
,
320 int close_button_state
,
321 wxRect
* out_tab_rect
,
322 wxRect
* out_button_rect
,
325 wxCoord normal_textx
, normal_texty
;
326 wxCoord selected_textx
, selected_texty
;
327 wxCoord textx
, texty
;
329 // if the caption is empty, measure some temporary text
330 wxString caption
= caption_text
;
331 if (caption_text
.empty())
334 dc
.SetFont(m_selected_font
);
335 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
337 dc
.SetFont(m_normal_font
);
338 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
340 // figure out the size of the tab
341 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
343 wxCoord tab_height
= tab_size
.y
;
344 wxCoord tab_width
= tab_size
.x
;
345 wxCoord tab_x
= in_rect
.x
;
346 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
349 caption
= caption_text
;
351 dc
.SetClippingRegion(in_rect
);
355 // select pen, brush and font for the tab to be drawn
359 dc
.SetPen(m_selected_bkpen
);
360 dc
.SetBrush(m_selected_bkbrush
);
361 dc
.SetFont(m_selected_font
);
362 textx
= selected_textx
;
363 texty
= selected_texty
;
367 dc
.SetPen(m_normal_bkpen
);
368 dc
.SetBrush(m_normal_bkbrush
);
369 dc
.SetFont(m_normal_font
);
370 textx
= normal_textx
;
371 texty
= normal_texty
;
375 // create points that will make the tab outline
379 points
[0].y
= tab_y
+ tab_height
- 4;
381 points
[1].y
= tab_y
+ 2;
382 points
[2].x
= tab_x
+ 2;
384 points
[3].x
= tab_x
+ tab_width
- 2;
386 points
[4].x
= tab_x
+ tab_width
;
387 points
[4].y
= tab_y
+ 2;
388 points
[5].x
= tab_x
+ tab_width
;
389 points
[5].y
= tab_y
+ tab_height
- 4;
392 // draw gradient background
395 wxColour c
= m_bkbrush
.GetColour();
399 for (y
= points
[0].y
; y
> points
[2].y
; --y
)
401 if (y
< tab_y
+(tab_height
*3/5) && y
!= last_y
)
404 c
= StepColour(c
, 102);
408 dc
.DrawLine(points
[0].x
+1, y
, points
[5].x
, y
);
413 dc
.SetPen(*wxGREY_PEN
);
414 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
415 dc
.DrawPolygon(6, points
);
417 // there are two horizontal grey lines at the bottom of the tab control,
418 // this gets rid of the top one of those lines in the tab control
421 wxColour c
= m_bkbrush
.GetColour();
423 dc
.DrawLine(points
[0].x
+1, points
[0].y
, points
[5].x
, points
[5].y
);
428 int close_button_width
= 0;
430 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
432 close_button_width
= m_active_close_bmp
.GetWidth();
435 text_offset
= tab_x
+ 8;
438 wxString draw_text
= ChopText(dc
,
440 tab_width
- (text_offset
-tab_x
) - close_button_width
);
443 dc
.DrawText(draw_text
,
445 (tab_y
+ tab_height
)/2 - (texty
/2));
450 // draw close button if necessary
451 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
453 wxBitmap bmp
= m_disabled_close_bmp
;
455 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
456 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
458 bmp
= m_active_close_bmp
;
461 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
462 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
465 IndentPressedBitmap(&rect
, close_button_state
);
466 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
468 *out_button_rect
= rect
;
471 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
473 dc
.DestroyClippingRegion();
476 int wxAuiDefaultTabArt::GetIndentSize()
481 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
482 wxWindow
* WXUNUSED(wnd
),
483 const wxString
& caption
,
484 bool WXUNUSED(active
),
485 int close_button_state
,
488 wxCoord measured_textx
, measured_texty
, tmp
;
490 dc
.SetFont(m_measuring_font
);
491 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
493 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
495 wxCoord tab_width
= measured_textx
+ 5;
496 wxCoord tab_height
= measured_texty
+ 10;
498 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
499 tab_width
+= m_active_close_bmp
.GetWidth() + 8;
502 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
504 tab_width
= m_fixed_tab_width
;
507 *x_extent
= tab_width
;
509 return wxSize(tab_width
, tab_height
);
513 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
514 wxWindow
* WXUNUSED(wnd
),
515 const wxRect
& in_rect
,
519 const wxBitmap
& bitmap_override
,
525 if (bitmap_override
.IsOk())
527 bmp
= bitmap_override
;
533 case wxAUI_BUTTON_CLOSE
:
534 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
535 bmp
= m_disabled_close_bmp
;
537 bmp
= m_active_close_bmp
;
539 case wxAUI_BUTTON_LEFT
:
540 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
541 bmp
= m_disabled_left_bmp
;
543 bmp
= m_active_left_bmp
;
545 case wxAUI_BUTTON_RIGHT
:
546 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
547 bmp
= m_disabled_right_bmp
;
549 bmp
= m_active_right_bmp
;
551 case wxAUI_BUTTON_WINDOWLIST
:
552 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
553 bmp
= m_disabled_windowlist_bmp
;
555 bmp
= m_active_windowlist_bmp
;
565 if (orientation
== wxLEFT
)
567 rect
.SetX(in_rect
.x
);
568 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
569 rect
.SetWidth(bmp
.GetWidth());
570 rect
.SetHeight(bmp
.GetHeight());
574 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
575 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
576 bmp
.GetWidth(), bmp
.GetHeight());
579 IndentPressedBitmap(&rect
, button_state
);
580 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
586 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
587 const wxArrayString
& items
,
592 size_t i
, count
= items
.GetCount();
593 for (i
= 0; i
< count
; ++i
)
595 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
598 if (active_idx
!= -1)
600 menuPopup
.Check(1000+active_idx
, true);
603 // find out where to put the popup menu of window
604 // items. Subtract 100 for now to center the menu
605 // a bit, until a better mechanism can be implemented
606 wxPoint pt
= ::wxGetMousePosition();
607 pt
= wnd
->ScreenToClient(pt
);
613 // find out the screen coordinate at the bottom of the tab ctrl
614 wxRect cli_rect
= wnd
->GetClientRect();
615 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
617 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
618 wnd
->PushEventHandler(cc
);
619 wnd
->PopupMenu(&menuPopup
, pt
);
620 int command
= cc
->GetCommandId();
621 wnd
->PopEventHandler(true);
629 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
632 dc
.SetFont(m_measuring_font
);
634 wxSize s
= GetTabSize(dc
,
638 wxAUI_BUTTON_STATE_HIDDEN
,
643 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
645 m_normal_font
= font
;
648 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
650 m_selected_font
= font
;
653 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
655 m_measuring_font
= font
;
659 // -- wxAuiSimpleTabArt class implementation --
661 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
663 m_normal_font
= *wxNORMAL_FONT
;
664 m_selected_font
= *wxNORMAL_FONT
;
665 m_selected_font
.SetWeight(wxBOLD
);
666 m_measuring_font
= m_selected_font
;
669 m_fixed_tab_width
= 100;
671 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
673 wxColour background_colour
= StepColour(base_colour
, 95);
674 wxColour normaltab_colour
= base_colour
;
675 wxColour selectedtab_colour
= *wxWHITE
;
677 m_bkbrush
= wxBrush(background_colour
);
678 m_normal_bkbrush
= wxBrush(normaltab_colour
);
679 m_normal_bkpen
= wxPen(normaltab_colour
);
680 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
681 m_selected_bkpen
= wxPen(selectedtab_colour
);
683 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
684 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
686 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
687 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
689 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
690 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
692 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
693 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
697 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
701 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
703 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
707 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
712 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
715 m_fixed_tab_width
= 100;
717 int tot_width
= tab_ctrl_size
.x
;
720 m_fixed_tab_width
= tot_width
/(int)tab_count
;
724 if (m_fixed_tab_width
< 100)
725 m_fixed_tab_width
= 100;
727 if (m_fixed_tab_width
> tot_width
/2)
728 m_fixed_tab_width
= tot_width
/2;
730 if (m_fixed_tab_width
> 220)
731 m_fixed_tab_width
= 220;
734 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
735 wxWindow
* WXUNUSED(wnd
),
739 dc
.SetBrush(m_bkbrush
);
740 dc
.SetPen(*wxTRANSPARENT_PEN
);
741 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
744 dc
.SetPen(*wxGREY_PEN
);
745 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
749 // DrawTab() draws an individual tab.
752 // in_rect - rectangle the tab should be confined to
753 // caption - tab's caption
754 // active - whether or not the tab is active
755 // out_rect - actual output rectangle
756 // x_extent - the advance x; where the next tab should start
758 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
760 const wxRect
& in_rect
,
761 const wxString
& caption_text
,
763 int close_button_state
,
764 wxRect
* out_tab_rect
,
765 wxRect
* out_button_rect
,
768 wxCoord normal_textx
, normal_texty
;
769 wxCoord selected_textx
, selected_texty
;
770 wxCoord textx
, texty
;
772 // if the caption is empty, measure some temporary text
773 wxString caption
= caption_text
;
774 if (caption_text
.empty())
777 dc
.SetFont(m_selected_font
);
778 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
780 dc
.SetFont(m_normal_font
);
781 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
783 // figure out the size of the tab
784 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
786 wxCoord tab_height
= tab_size
.y
;
787 wxCoord tab_width
= tab_size
.x
;
788 wxCoord tab_x
= in_rect
.x
;
789 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
791 caption
= caption_text
;
793 // select pen, brush and font for the tab to be drawn
797 dc
.SetPen(m_selected_bkpen
);
798 dc
.SetBrush(m_selected_bkbrush
);
799 dc
.SetFont(m_selected_font
);
800 textx
= selected_textx
;
801 texty
= selected_texty
;
805 dc
.SetPen(m_normal_bkpen
);
806 dc
.SetBrush(m_normal_bkbrush
);
807 dc
.SetFont(m_normal_font
);
808 textx
= normal_textx
;
809 texty
= normal_texty
;
817 points
[0].y
= tab_y
+ tab_height
- 1;
818 points
[1].x
= tab_x
+ tab_height
- 3;
819 points
[1].y
= tab_y
+ 2;
820 points
[2].x
= tab_x
+ tab_height
+ 3;
822 points
[3].x
= tab_x
+ tab_width
- 2;
824 points
[4].x
= tab_x
+ tab_width
;
825 points
[4].y
= tab_y
+ 2;
826 points
[5].x
= tab_x
+ tab_width
;
827 points
[5].y
= tab_y
+ tab_height
- 1;
828 points
[6] = points
[0];
830 dc
.SetClippingRegion(in_rect
);
832 dc
.DrawPolygon(6, points
);
834 dc
.SetPen(*wxGREY_PEN
);
836 //dc.DrawLines(active ? 6 : 7, points);
837 dc
.DrawLines(7, points
);
842 int close_button_width
= 0;
843 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
845 close_button_width
= m_active_close_bmp
.GetWidth();
846 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
850 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
853 // set minimum text offset
854 if (text_offset
< tab_x
+ tab_height
)
855 text_offset
= tab_x
+ tab_height
;
857 // chop text if necessary
858 wxString draw_text
= ChopText(dc
,
860 tab_width
- (text_offset
-tab_x
) - close_button_width
);
863 dc
.DrawText(draw_text
,
865 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
868 // draw close button if necessary
869 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
873 bmp
= m_active_close_bmp
;
875 bmp
= m_disabled_close_bmp
;
877 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
878 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
881 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
883 *out_button_rect
= rect
;
887 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
889 dc
.DestroyClippingRegion();
892 int wxAuiSimpleTabArt::GetIndentSize()
897 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
898 wxWindow
* WXUNUSED(wnd
),
899 const wxString
& caption
,
900 bool WXUNUSED(active
),
901 int close_button_state
,
904 wxCoord measured_textx
, measured_texty
;
906 dc
.SetFont(m_measuring_font
);
907 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
909 wxCoord tab_height
= measured_texty
+ 4;
910 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
912 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
913 tab_width
+= m_active_close_bmp
.GetWidth();
915 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
917 tab_width
= m_fixed_tab_width
;
920 *x_extent
= tab_width
- (tab_height
/2) - 1;
922 return wxSize(tab_width
, tab_height
);
926 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
927 wxWindow
* WXUNUSED(wnd
),
928 const wxRect
& in_rect
,
932 const wxBitmap
& bitmap_override
,
938 if (bitmap_override
.IsOk())
940 bmp
= bitmap_override
;
946 case wxAUI_BUTTON_CLOSE
:
947 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
948 bmp
= m_disabled_close_bmp
;
950 bmp
= m_active_close_bmp
;
952 case wxAUI_BUTTON_LEFT
:
953 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
954 bmp
= m_disabled_left_bmp
;
956 bmp
= m_active_left_bmp
;
958 case wxAUI_BUTTON_RIGHT
:
959 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
960 bmp
= m_disabled_right_bmp
;
962 bmp
= m_active_right_bmp
;
964 case wxAUI_BUTTON_WINDOWLIST
:
965 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
966 bmp
= m_disabled_windowlist_bmp
;
968 bmp
= m_active_windowlist_bmp
;
978 if (orientation
== wxLEFT
)
980 rect
.SetX(in_rect
.x
);
981 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
982 rect
.SetWidth(bmp
.GetWidth());
983 rect
.SetHeight(bmp
.GetHeight());
987 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
988 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
989 bmp
.GetWidth(), bmp
.GetHeight());
993 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
999 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1000 const wxArrayString
& items
,
1005 size_t i
, count
= items
.GetCount();
1006 for (i
= 0; i
< count
; ++i
)
1008 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1011 if (active_idx
!= -1)
1013 menuPopup
.Check(1000+active_idx
, true);
1016 // find out where to put the popup menu of window
1017 // items. Subtract 100 for now to center the menu
1018 // a bit, until a better mechanism can be implemented
1019 wxPoint pt
= ::wxGetMousePosition();
1020 pt
= wnd
->ScreenToClient(pt
);
1026 // find out the screen coordinate at the bottom of the tab ctrl
1027 wxRect cli_rect
= wnd
->GetClientRect();
1028 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1030 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1031 wnd
->PushEventHandler(cc
);
1032 wnd
->PopupMenu(&menuPopup
, pt
);
1033 int command
= cc
->GetCommandId();
1034 wnd
->PopEventHandler(true);
1036 if (command
>= 1000)
1037 return command
-1000;
1042 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
1045 dc
.SetFont(m_measuring_font
);
1047 wxSize s
= GetTabSize(dc
,
1051 wxAUI_BUTTON_STATE_HIDDEN
,
1056 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1058 m_normal_font
= font
;
1061 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1063 m_selected_font
= font
;
1066 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1068 m_measuring_font
= font
;
1074 // -- wxAuiTabContainer class implementation --
1077 // wxAuiTabContainer is a class which contains information about each
1078 // tab. It also can render an entire tab control to a specified DC.
1079 // It's not a window class itself, because this code will be used by
1080 // the wxFrameMananger, where it is disadvantageous to have separate
1081 // windows for each tab control in the case of "docked tabs"
1083 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1084 // which can be used as a tab control in the normal sense.
1087 wxAuiTabContainer::wxAuiTabContainer()
1091 m_art
= new wxAuiDefaultTabArt
;
1093 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1094 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1095 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1096 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1099 wxAuiTabContainer::~wxAuiTabContainer()
1104 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1111 m_art
->SetFlags(m_flags
);
1115 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1120 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1124 // check for new close button settings
1125 RemoveButton(wxAUI_BUTTON_LEFT
);
1126 RemoveButton(wxAUI_BUTTON_RIGHT
);
1127 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1128 RemoveButton(wxAUI_BUTTON_CLOSE
);
1131 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1133 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1134 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1137 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1139 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1142 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1144 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1149 m_art
->SetFlags(m_flags
);
1153 unsigned int wxAuiTabContainer::GetFlags() const
1159 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1161 m_art
->SetNormalFont(font
);
1164 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1166 m_art
->SetSelectedFont(font
);
1169 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1171 m_art
->SetMeasuringFont(font
);
1174 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1180 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1184 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1185 const wxAuiNotebookPage
& info
)
1187 wxAuiNotebookPage page_info
;
1189 page_info
.window
= page
;
1191 m_pages
.Add(page_info
);
1193 // let the art provider know how many pages we have
1196 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1202 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1203 const wxAuiNotebookPage
& info
,
1206 wxAuiNotebookPage page_info
;
1208 page_info
.window
= page
;
1210 if (idx
>= m_pages
.GetCount())
1211 m_pages
.Add(page_info
);
1213 m_pages
.Insert(page_info
, idx
);
1215 // let the art provider know how many pages we have
1218 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1224 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1227 int idx
= GetIdxFromWindow(page
);
1231 // get page entry, make a copy of it
1232 wxAuiNotebookPage p
= GetPage(idx
);
1234 // remove old page entry
1237 // insert page where it should be
1238 InsertPage(page
, p
, new_idx
);
1243 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1245 size_t i
, page_count
= m_pages
.GetCount();
1246 for (i
= 0; i
< page_count
; ++i
)
1248 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1249 if (page
.window
== wnd
)
1251 m_pages
.RemoveAt(i
);
1253 // let the art provider know how many pages we have
1256 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1266 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1270 size_t i
, page_count
= m_pages
.GetCount();
1271 for (i
= 0; i
< page_count
; ++i
)
1273 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1274 if (page
.window
== wnd
)
1281 page
.active
= false;
1288 void wxAuiTabContainer::SetNoneActive()
1290 size_t i
, page_count
= m_pages
.GetCount();
1291 for (i
= 0; i
< page_count
; ++i
)
1293 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1294 page
.active
= false;
1298 bool wxAuiTabContainer::SetActivePage(size_t page
)
1300 if (page
>= m_pages
.GetCount())
1303 return SetActivePage(m_pages
.Item(page
).window
);
1306 int wxAuiTabContainer::GetActivePage() const
1308 size_t i
, page_count
= m_pages
.GetCount();
1309 for (i
= 0; i
< page_count
; ++i
)
1311 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1319 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1321 if (idx
>= m_pages
.GetCount())
1324 return m_pages
[idx
].window
;
1327 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1329 size_t i
, page_count
= m_pages
.GetCount();
1330 for (i
= 0; i
< page_count
; ++i
)
1332 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1333 if (page
.window
== wnd
)
1339 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1341 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1343 return m_pages
[idx
];
1346 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1351 size_t wxAuiTabContainer::GetPageCount() const
1353 return m_pages
.GetCount();
1356 void wxAuiTabContainer::AddButton(int id
,
1358 const wxBitmap
& normal_bitmap
,
1359 const wxBitmap
& disabled_bitmap
)
1361 wxAuiTabContainerButton button
;
1363 button
.bitmap
= normal_bitmap
;
1364 button
.dis_bitmap
= disabled_bitmap
;
1365 button
.location
= location
;
1366 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1368 m_buttons
.Add(button
);
1371 void wxAuiTabContainer::RemoveButton(int id
)
1373 size_t i
, button_count
= m_buttons
.GetCount();
1375 for (i
= 0; i
< button_count
; ++i
)
1377 if (m_buttons
.Item(i
).id
== id
)
1379 m_buttons
.RemoveAt(i
);
1387 size_t wxAuiTabContainer::GetTabOffset() const
1389 return m_tab_offset
;
1392 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1394 m_tab_offset
= offset
;
1400 // Render() renders the tab catalog to the specified DC
1401 // It is a virtual function and can be overridden to
1402 // provide custom drawing capabilities
1403 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1408 size_t page_count
= m_pages
.GetCount();
1409 size_t button_count
= m_buttons
.GetCount();
1411 // create off-screen bitmap
1412 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1413 dc
.SelectObject(bmp
);
1416 // find out if size of tabs is larger than can be
1417 // afforded on screen
1418 int total_width
= 0;
1419 int visible_width
= 0;
1420 for (i
= 0; i
< page_count
; ++i
)
1422 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1424 // determine if a close button is on this tab
1425 bool close_button
= false;
1426 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1427 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1429 close_button
= true;
1434 wxSize size
= m_art
->GetTabSize(dc
,
1439 wxAUI_BUTTON_STATE_NORMAL
:
1440 wxAUI_BUTTON_STATE_HIDDEN
,
1443 if (i
+1 < page_count
)
1444 total_width
+= x_extent
;
1446 total_width
+= size
.x
;
1448 if (i
>= m_tab_offset
)
1450 if (i
+1 < page_count
)
1451 visible_width
+= x_extent
;
1453 visible_width
+= size
.x
;
1457 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1459 // show left/right buttons
1460 for (i
= 0; i
< button_count
; ++i
)
1462 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1463 if (button
.id
== wxAUI_BUTTON_LEFT
||
1464 button
.id
== wxAUI_BUTTON_RIGHT
)
1466 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1472 // hide left/right buttons
1473 for (i
= 0; i
< button_count
; ++i
)
1475 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1476 if (button
.id
== wxAUI_BUTTON_LEFT
||
1477 button
.id
== wxAUI_BUTTON_RIGHT
)
1479 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1484 // determine whether left button should be enabled
1485 for (i
= 0; i
< button_count
; ++i
)
1487 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1488 if (button
.id
== wxAUI_BUTTON_LEFT
)
1490 if (m_tab_offset
== 0)
1491 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1493 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1495 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1497 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1498 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1500 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1507 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1510 int left_buttons_width
= 0;
1511 int right_buttons_width
= 0;
1515 // draw the buttons on the right side
1516 offset
= m_rect
.x
+ m_rect
.width
;
1517 for (i
= 0; i
< button_count
; ++i
)
1519 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1521 if (button
.location
!= wxRIGHT
)
1523 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1526 wxRect button_rect
= m_rect
;
1527 button_rect
.SetY(1);
1528 button_rect
.SetWidth(offset
);
1530 m_art
->DrawButton(dc
,
1539 offset
-= button
.rect
.GetWidth();
1540 right_buttons_width
+= button
.rect
.GetWidth();
1547 // draw the buttons on the left side
1549 for (i
= 0; i
< button_count
; ++i
)
1551 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1553 if (button
.location
!= wxLEFT
)
1555 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1558 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1560 m_art
->DrawButton(dc
,
1569 offset
+= button
.rect
.GetWidth();
1570 left_buttons_width
+= button
.rect
.GetWidth();
1573 offset
= left_buttons_width
;
1576 offset
+= m_art
->GetIndentSize();
1578 // prepare the tab-close-button array
1579 while (m_tab_close_buttons
.GetCount() < page_count
)
1581 wxAuiTabContainerButton tempbtn
;
1582 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1583 tempbtn
.location
= wxCENTER
;
1584 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1585 m_tab_close_buttons
.Add(tempbtn
);
1588 for (i
= 0; i
< m_tab_offset
; ++i
)
1590 // buttons before the tab offset must be set to hidden
1591 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1597 size_t active
= 999;
1598 int active_offset
= 0;
1602 wxRect rect
= m_rect
;
1604 rect
.height
= m_rect
.height
;
1606 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1608 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1609 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1611 // determine if a close button is on this tab
1612 bool close_button
= false;
1613 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1614 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1616 close_button
= true;
1617 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1619 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1620 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1621 tab_button
.location
= wxCENTER
;
1626 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1630 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1639 tab_button
.cur_state
,
1647 active_offset
= offset
;
1654 // draw the active tab again so it stands in the foreground
1655 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1657 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1659 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1661 // determine if a close button is on this tab
1662 bool close_button
= false;
1663 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1664 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1666 close_button
= true;
1669 rect
.x
= active_offset
;
1675 tab_button
.cur_state
,
1682 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1683 m_rect
.GetWidth(), m_rect
.GetHeight(),
1688 // TabHitTest() tests if a tab was hit, passing the window pointer
1689 // back if that condition was fulfilled. The function returns
1690 // true if a tab was hit, otherwise false
1691 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1693 if (!m_rect
.Contains(x
,y
))
1696 wxAuiTabContainerButton
* btn
= NULL
;
1697 if (ButtonHitTest(x
, y
, &btn
))
1699 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1703 size_t i
, page_count
= m_pages
.GetCount();
1705 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1707 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1708 if (page
.rect
.Contains(x
,y
))
1719 // ButtonHitTest() tests if a button was hit. The function returns
1720 // true if a button was hit, otherwise false
1721 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1722 wxAuiTabContainerButton
** hit
) const
1724 if (!m_rect
.Contains(x
,y
))
1727 size_t i
, button_count
;
1730 button_count
= m_buttons
.GetCount();
1731 for (i
= 0; i
< button_count
; ++i
)
1733 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1734 if (button
.rect
.Contains(x
,y
))
1742 button_count
= m_tab_close_buttons
.GetCount();
1743 for (i
= 0; i
< button_count
; ++i
)
1745 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1746 if (button
.rect
.Contains(x
,y
))
1759 // the utility function ShowWnd() is the same as show,
1760 // except it handles wxAuiMDIChildFrame windows as well,
1761 // as the Show() method on this class is "unplugged"
1762 static void ShowWnd(wxWindow
* wnd
, bool show
)
1764 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1766 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1776 // DoShowHide() this function shows the active window, then
1777 // hides all of the other windows (in that order)
1778 void wxAuiTabContainer::DoShowHide()
1780 wxAuiNotebookPageArray
& pages
= GetPages();
1781 size_t i
, page_count
= pages
.GetCount();
1783 // show new active page first
1784 for (i
= 0; i
< page_count
; ++i
)
1786 wxAuiNotebookPage
& page
= pages
.Item(i
);
1789 ShowWnd(page
.window
, true);
1794 // hide all other pages
1795 for (i
= 0; i
< page_count
; ++i
)
1797 wxAuiNotebookPage
& page
= pages
.Item(i
);
1798 ShowWnd(page
.window
, page
.active
);
1807 // -- wxAuiTabCtrl class implementation --
1811 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1812 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1813 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1814 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1815 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1816 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1817 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1818 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1819 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1823 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1827 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1829 m_click_pt
= wxDefaultPosition
;
1830 m_is_dragging
= false;
1831 m_hover_button
= NULL
;
1834 wxAuiTabCtrl::~wxAuiTabCtrl()
1838 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1842 dc
.SetFont(GetFont());
1844 if (GetPageCount() > 0)
1848 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1852 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1854 wxSize s
= evt
.GetSize();
1855 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1859 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1862 m_click_pt
= wxDefaultPosition
;
1863 m_is_dragging
= false;
1867 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1869 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1870 e
.SetSelection(GetIdxFromWindow(wnd
));
1871 e
.SetOldSelection(GetActivePage());
1872 e
.SetEventObject(this);
1873 GetEventHandler()->ProcessEvent(e
);
1875 m_click_pt
.x
= evt
.m_x
;
1876 m_click_pt
.y
= evt
.m_y
;
1882 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1888 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1890 if (GetCapture() == this)
1895 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1896 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1897 evt
.SetOldSelection(evt
.GetSelection());
1898 evt
.SetEventObject(this);
1899 GetEventHandler()->ProcessEvent(evt
);
1905 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1909 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1911 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1912 evt
.SetInt(m_hover_button
->id
);
1913 evt
.SetEventObject(this);
1914 GetEventHandler()->ProcessEvent(evt
);
1918 m_click_pt
= wxDefaultPosition
;
1919 m_is_dragging
= false;
1923 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1925 wxPoint pos
= evt
.GetPosition();
1927 // check if the mouse is hovering above a button
1928 wxAuiTabContainerButton
* button
;
1929 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1931 if (m_hover_button
&& button
!= m_hover_button
)
1933 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1934 m_hover_button
= NULL
;
1939 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1941 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1944 m_hover_button
= button
;
1952 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1953 m_hover_button
= NULL
;
1960 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1965 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1966 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1967 evt
.SetOldSelection(evt
.GetSelection());
1968 evt
.SetEventObject(this);
1969 GetEventHandler()->ProcessEvent(evt
);
1974 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1975 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1977 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1978 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1980 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1981 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1982 evt
.SetOldSelection(evt
.GetSelection());
1983 evt
.SetEventObject(this);
1984 GetEventHandler()->ProcessEvent(evt
);
1986 m_is_dragging
= true;
1990 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1994 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1995 m_hover_button
= NULL
;
2001 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2003 int button
= event
.GetInt();
2005 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2007 if (button
== wxAUI_BUTTON_LEFT
)
2009 if (GetTabOffset() > 0)
2011 SetTabOffset(GetTabOffset()-1);
2018 SetTabOffset(GetTabOffset()+1);
2023 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2027 size_t i
, page_count
= m_pages
.GetCount();
2028 for (i
= 0; i
< page_count
; ++i
)
2030 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2031 as
.Add(page
.caption
);
2034 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2038 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2039 e
.SetSelection(idx
);
2040 e
.SetOldSelection(GetActivePage());
2041 e
.SetEventObject(this);
2042 GetEventHandler()->ProcessEvent(e
);
2051 // wxTabFrame is an interesting case. It's important that all child pages
2052 // of the multi-notebook control are all actually children of that control
2053 // (and not grandchildren). wxTabFrame facilitates this. There is one
2054 // instance of wxTabFrame for each tab control inside the multi-notebook.
2055 // It's important to know that wxTabFrame is not a real window, but it merely
2056 // used to capture the dimensions/positioning of the internal tab control and
2057 // it's managed page windows
2059 class wxTabFrame
: public wxWindow
2066 m_rect
= wxRect(0,0,200,200);
2067 m_tab_ctrl_height
= 20;
2070 void SetTabCtrlHeight(int h
)
2072 m_tab_ctrl_height
= h
;
2075 void DoSetSize(int x
, int y
,
2076 int width
, int height
,
2077 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2079 m_rect
= wxRect(x
, y
, width
, height
);
2083 void DoGetClientSize(int* x
, int* y
) const
2089 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2096 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2097 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2098 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2102 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2103 size_t i
, page_count
= pages
.GetCount();
2105 for (i
= 0; i
< page_count
; ++i
)
2107 wxAuiNotebookPage
& page
= pages
.Item(i
);
2108 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2109 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2111 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2113 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2114 wnd
->ApplyMDIChildFrameRect();
2119 void DoGetSize(int* x
, int* y
) const
2122 *x
= m_rect
.GetWidth();
2124 *y
= m_rect
.GetHeight();
2136 wxAuiTabCtrl
* m_tabs
;
2137 int m_tab_ctrl_height
;
2144 // -- wxAuiNotebook class implementation --
2146 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2147 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2148 //EVT_SIZE(wxAuiNotebook::OnSize)
2149 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2150 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2151 EVT_COMMAND_RANGE(10000, 10100,
2152 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2153 wxAuiNotebook::OnTabClicked
)
2154 EVT_COMMAND_RANGE(10000, 10100,
2155 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2156 wxAuiNotebook::OnTabBeginDrag
)
2157 EVT_COMMAND_RANGE(10000, 10100,
2158 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2159 wxAuiNotebook::OnTabEndDrag
)
2160 EVT_COMMAND_RANGE(10000, 10100,
2161 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2162 wxAuiNotebook::OnTabDragMotion
)
2163 EVT_COMMAND_RANGE(10000, 10100,
2164 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2165 wxAuiNotebook::OnTabButton
)
2168 wxAuiNotebook::wxAuiNotebook()
2171 m_tab_id_counter
= 10000;
2173 m_tab_ctrl_height
= 20;
2176 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2180 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2182 InitNotebook(style
);
2185 bool wxAuiNotebook::Create(wxWindow
* parent
,
2191 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2194 InitNotebook(style
);
2199 // InitNotebook() contains common initialization
2200 // code called by all constructors
2201 void wxAuiNotebook::InitNotebook(long style
)
2204 m_tab_id_counter
= 10000;
2206 m_tab_ctrl_height
= 20;
2207 m_flags
= (unsigned int)style
;
2209 m_normal_font
= *wxNORMAL_FONT
;
2210 m_selected_font
= *wxNORMAL_FONT
;
2211 m_selected_font
.SetWeight(wxBOLD
);
2213 SetArtProvider(new wxAuiDefaultTabArt
);
2215 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2216 m_dummy_wnd
->SetSize(200, 200);
2217 m_dummy_wnd
->Show(false);
2219 m_mgr
.SetManagedWindow(this);
2221 m_mgr
.AddPane(m_dummy_wnd
,
2222 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2227 wxAuiNotebook::~wxAuiNotebook()
2232 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2234 m_tabs
.SetArtProvider(art
);
2236 // choose a default for the tab height
2237 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2239 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2240 size_t i
, pane_count
= all_panes
.GetCount();
2241 for (i
= 0; i
< pane_count
; ++i
)
2243 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2244 if (pane
.name
== wxT("dummy"))
2246 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2247 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2248 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2249 tabctrl
->SetArtProvider(art
->Clone());
2250 tab_frame
->DoSizing();
2255 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2257 return m_tabs
.GetArtProvider();
2260 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2262 wxControl::SetWindowStyleFlag(style
);
2264 m_flags
= (unsigned int)style
;
2266 // if the control is already initialized
2267 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2269 // let all of the tab children know about the new style
2271 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2272 size_t i
, pane_count
= all_panes
.GetCount();
2273 for (i
= 0; i
< pane_count
; ++i
)
2275 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2276 if (pane
.name
== wxT("dummy"))
2278 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2279 tabctrl
->SetFlags(m_flags
);
2287 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2288 const wxString
& caption
,
2290 const wxBitmap
& bitmap
)
2292 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2295 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2297 const wxString
& caption
,
2299 const wxBitmap
& bitmap
)
2301 wxAuiNotebookPage info
;
2303 info
.caption
= caption
;
2304 info
.bitmap
= bitmap
;
2305 info
.active
= false;
2307 // if there are currently no tabs, the first added
2308 // tab must be active
2309 if (m_tabs
.GetPageCount() == 0)
2312 m_tabs
.InsertPage(page
, info
, page_idx
);
2314 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2315 if (page_idx
>= active_tabctrl
->GetPageCount())
2316 active_tabctrl
->AddPage(page
, info
);
2318 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2321 active_tabctrl
->DoShowHide();
2325 int idx
= m_tabs
.GetIdxFromWindow(page
);
2326 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2335 // DeletePage() removes a tab from the multi-notebook,
2336 // and destroys the window as well
2337 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2339 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2341 if (!RemovePage(page_idx
))
2345 // actually destroy the window now
2346 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2348 // delete the child frame with pending delete, as is
2349 // customary with frame windows
2350 if (!wxPendingDelete
.Member(wnd
))
2351 wxPendingDelete
.Append(wnd
);
2363 // RemovePage() removes a tab from the multi-notebook,
2364 // but does not destroy the window
2365 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2367 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2368 wxWindow
* new_active
= NULL
;
2370 // find out which onscreen tab ctrl owns this tab
2373 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2376 // find a new page and set it as active
2377 int new_idx
= ctrl_idx
+1;
2378 if (new_idx
>= (int)ctrl
->GetPageCount())
2379 new_idx
= ctrl_idx
-1;
2381 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2383 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2387 // set the active page to the first page that
2388 // isn't the one being deleted
2389 size_t i
, page_count
= m_tabs
.GetPageCount();
2390 for (i
= 0; i
< page_count
; ++i
)
2392 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2395 new_active
= m_tabs
.GetWindowFromIdx(i
);
2401 // remove the tab from main catalog
2402 if (!m_tabs
.RemovePage(wnd
))
2405 // remove the tab from the onscreen tab ctrl
2406 ctrl
->RemovePage(wnd
);
2409 RemoveEmptyTabFrames();
2411 // set new active pane
2415 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2421 // SetPageText() changes the tab caption of the specified page
2422 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2424 if (page_idx
>= m_tabs
.GetPageCount())
2427 // update our own tab catalog
2428 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2429 page_info
.caption
= text
;
2431 // update what's on screen
2434 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2436 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2437 info
.caption
= text
;
2445 // GetSelection() returns the index of the currently active page
2446 int wxAuiNotebook::GetSelection() const
2451 // SetSelection() sets the currently active page
2452 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2454 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2458 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2459 evt
.SetSelection(new_page
);
2460 evt
.SetOldSelection(m_curpage
);
2461 evt
.SetEventObject(this);
2462 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2464 // program allows the page change
2465 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2466 (void)GetEventHandler()->ProcessEvent(evt
);
2472 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2474 m_tabs
.SetActivePage(wnd
);
2476 ctrl
->SetActivePage(ctrl_idx
);
2480 int old_curpage
= m_curpage
;
2481 m_curpage
= new_page
;
2485 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2486 size_t i
, pane_count
= all_panes
.GetCount();
2487 for (i
= 0; i
< pane_count
; ++i
)
2489 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2490 if (pane
.name
== wxT("dummy"))
2492 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2493 if (tabctrl
!= ctrl
)
2494 tabctrl
->SetSelectedFont(m_normal_font
);
2496 tabctrl
->SetSelectedFont(m_selected_font
);
2509 // GetPageCount() returns the total number of
2510 // pages managed by the multi-notebook
2511 size_t wxAuiNotebook::GetPageCount() const
2513 return m_tabs
.GetPageCount();
2516 // GetPage() returns the wxWindow pointer of the
2518 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2520 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2522 return m_tabs
.GetWindowFromIdx(page_idx
);
2525 // DoSizing() performs all sizing operations in each tab control
2526 void wxAuiNotebook::DoSizing()
2528 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2529 size_t i
, pane_count
= all_panes
.GetCount();
2530 for (i
= 0; i
< pane_count
; ++i
)
2532 if (all_panes
.Item(i
).name
== wxT("dummy"))
2535 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2536 tabframe
->DoSizing();
2540 // GetActiveTabCtrl() returns the active tab control. It is
2541 // called to determine which control gets new windows being added
2542 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2544 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2549 // find the tab ctrl with the current page
2550 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2557 // no current page, just find the first tab ctrl
2558 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2559 size_t i
, pane_count
= all_panes
.GetCount();
2560 for (i
= 0; i
< pane_count
; ++i
)
2562 if (all_panes
.Item(i
).name
== wxT("dummy"))
2565 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2566 return tabframe
->m_tabs
;
2569 // If there is no tabframe at all, create one
2570 wxTabFrame
* tabframe
= new wxTabFrame
;
2571 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2572 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2577 tabframe
->m_tabs
->SetFlags(m_flags
);
2578 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2579 m_mgr
.AddPane(tabframe
,
2580 wxAuiPaneInfo().Center().CaptionVisible(false));
2584 return tabframe
->m_tabs
;
2587 // FindTab() finds the tab control that currently contains the window as well
2588 // as the index of the window in the tab control. It returns true if the
2589 // window was found, otherwise false.
2590 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2592 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2593 size_t i
, pane_count
= all_panes
.GetCount();
2594 for (i
= 0; i
< pane_count
; ++i
)
2596 if (all_panes
.Item(i
).name
== wxT("dummy"))
2599 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2601 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2604 *ctrl
= tabframe
->m_tabs
;
2614 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2618 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2622 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2624 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2626 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2627 wxASSERT(ctrl
!= NULL
);
2629 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2630 wxASSERT(wnd
!= NULL
);
2632 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2633 wxASSERT(idx
!= -1);
2638 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2643 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2645 wxPoint screen_pt
= ::wxGetMousePosition();
2646 wxPoint client_pt
= ScreenToClient(screen_pt
);
2649 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2650 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2652 if (dest_tabs
== src_tabs
)
2656 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2659 // always hide the hint for inner-tabctrl drag
2662 // if tab moving is not allowed, leave
2663 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2668 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2669 wxWindow
* dest_location_tab
;
2671 // this is an inner-tab drag/reposition
2672 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2674 int src_idx
= evt
.GetSelection();
2675 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2677 // prevent jumpy drag
2678 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2679 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2680 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2682 m_last_drag_x
= pt
.x
;
2687 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2688 dest_tabs
->MovePage(src_tab
, dest_idx
);
2689 dest_tabs
->SetActivePage((size_t)dest_idx
);
2690 dest_tabs
->DoShowHide();
2691 dest_tabs
->Refresh();
2692 m_last_drag_x
= pt
.x
;
2700 // if external drag is allowed, check if the tab is being dragged
2701 // over a different wxAuiNotebook control
2702 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2704 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2706 // make sure we are not over the hint window
2707 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2711 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2713 tab_ctrl
= tab_ctrl
->GetParent();
2718 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2722 wxRect hint_rect
= tab_ctrl
->GetRect();
2723 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2724 m_mgr
.ShowHint(hint_rect
);
2733 // if tab moving is not allowed, leave
2734 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2742 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2748 wxRect hint_rect
= dest_tabs
->GetRect();
2749 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2750 m_mgr
.ShowHint(hint_rect
);
2754 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2760 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2762 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2767 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2768 wxAuiTabCtrl
* dest_tabs
= NULL
;
2771 // set cursor back to an arrow
2772 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2775 // get the mouse position, which will be used to determine the drop point
2776 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2777 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2781 // check for an external move
2782 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2784 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2788 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2790 tab_ctrl
= tab_ctrl
->GetParent();
2795 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2799 // find out from the destination control
2800 // if it's ok to drop this tab here
2801 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2802 e
.SetSelection(evt
.GetSelection());
2803 e
.SetOldSelection(evt
.GetSelection());
2804 e
.SetEventObject(this);
2805 e
.SetDragSource(this);
2806 e
.Veto(); // dropping must be explicitly approved by control owner
2808 nb
->GetEventHandler()->ProcessEvent(e
);
2812 // no answer or negative answer
2818 int src_idx
= evt
.GetSelection();
2819 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2821 // get main index of the page
2822 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2824 // make a copy of the page info
2825 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2827 // remove the page from the source notebook
2828 RemovePage(main_idx
);
2830 // reparent the page
2831 src_page
->Reparent(nb
);
2834 // found out the insert idx
2835 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2836 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2838 wxWindow
* target
= NULL
;
2839 int insert_idx
= -1;
2840 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2843 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2847 // add the page to the new notebook
2848 if (insert_idx
== -1)
2849 insert_idx
= dest_tabs
->GetPageCount();
2850 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2851 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2854 dest_tabs
->DoShowHide();
2855 dest_tabs
->Refresh();
2857 // set the selection in the destination tab control
2858 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2868 // only perform a tab split if it's allowed
2869 if (m_flags
& wxAUI_NB_TAB_SPLIT
)
2871 // If the pointer is in an existing tab frame, do a tab insert
2872 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2873 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2874 int insert_idx
= -1;
2877 dest_tabs
= tab_frame
->m_tabs
;
2879 if (dest_tabs
== src_tabs
)
2883 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2884 wxWindow
* target
= NULL
;
2885 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2888 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2893 // If there is no tabframe at all, create one
2894 wxTabFrame
* new_tabs
= new wxTabFrame
;
2895 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2896 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2901 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2902 new_tabs
->m_tabs
->SetFlags(m_flags
);
2904 m_mgr
.AddPane(new_tabs
,
2905 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2908 dest_tabs
= new_tabs
->m_tabs
;
2913 // remove the page from the source tabs
2914 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2915 page_info
.active
= false;
2916 src_tabs
->RemovePage(page_info
.window
);
2917 if (src_tabs
->GetPageCount() > 0)
2919 src_tabs
->SetActivePage((size_t)0);
2920 src_tabs
->DoShowHide();
2921 src_tabs
->Refresh();
2926 // add the page to the destination tabs
2927 if (insert_idx
== -1)
2928 insert_idx
= dest_tabs
->GetPageCount();
2929 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2931 if (src_tabs
->GetPageCount() == 0)
2933 RemoveEmptyTabFrames();
2937 dest_tabs
->DoShowHide();
2938 dest_tabs
->Refresh();
2940 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2946 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2948 // if we've just removed the last tab from the source
2949 // tab set, the remove the tab control completely
2950 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2951 size_t i
, pane_count
= all_panes
.GetCount();
2952 for (i
= 0; i
< pane_count
; ++i
)
2954 if (all_panes
.Item(i
).name
== wxT("dummy"))
2957 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2958 if (tabframe
->m_tab_rect
.Contains(pt
))
2959 return tabframe
->m_tabs
;
2965 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2967 // if we've just removed the last tab from the source
2968 // tab set, the remove the tab control completely
2969 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2970 size_t i
, pane_count
= all_panes
.GetCount();
2971 for (i
= 0; i
< pane_count
; ++i
)
2973 if (all_panes
.Item(i
).name
== wxT("dummy"))
2976 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2977 if (tabframe
->m_tabs
== tab_ctrl
)
2986 void wxAuiNotebook::RemoveEmptyTabFrames()
2988 // if we've just removed the last tab from the source
2989 // tab set, the remove the tab control completely
2990 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2991 size_t i
, pane_count
= all_panes
.GetCount();
2992 for (i
= 0; i
< pane_count
; ++i
)
2994 if (all_panes
.Item(i
).name
== wxT("dummy"))
2997 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2998 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3000 m_mgr
.DetachPane(tab_frame
);
3002 // use pending delete because sometimes during
3003 // window closing, refreshs are pending
3004 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3005 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3006 //tab_frame->m_tabs->Destroy();
3013 // check to see if there is still a center pane;
3014 // if there isn't, make a frame the center pane
3015 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3016 pane_count
= panes
.GetCount();
3017 wxWindow
* first_good
= NULL
;
3018 bool center_found
= false;
3019 for (i
= 0; i
< pane_count
; ++i
)
3021 if (panes
.Item(i
).name
== wxT("dummy"))
3023 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3024 center_found
= true;
3026 first_good
= panes
.Item(i
).window
;
3029 if (!center_found
&& first_good
)
3031 m_mgr
.GetPane(first_good
).Centre();
3037 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3039 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3040 if (idx
!= -1 && idx
!= m_curpage
)
3047 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3049 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3050 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3052 int button_id
= evt
.GetInt();
3054 if (button_id
== wxAUI_BUTTON_CLOSE
)
3056 int selection
= tabs
->GetActivePage();
3058 if (selection
!= -1)
3060 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3063 // ask owner if it's ok to close the tab
3064 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3065 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3066 e
.SetOldSelection(evt
.GetSelection());
3067 e
.SetEventObject(this);
3068 GetEventHandler()->ProcessEvent(e
);
3073 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3079 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3080 DeletePage(main_idx
);