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_CHANGING
)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
46 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
47 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
53 // This functions are here for this proof of concept
54 // and will be factored out later. See dockart.cpp
55 static wxColor
StepColour(const wxColor
& c
, int percent
)
57 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
58 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
59 (unsigned char)wxMin((g
*percent
)/100,255),
60 (unsigned char)wxMin((b
*percent
)/100,255));
63 // This functions are here for this proof of concept
64 // and will be factored out later. See dockart.cpp
65 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
66 const wxColour
& color
)
68 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
69 img
.Replace(0,0,0,123,123,123);
70 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
71 img
.SetMaskColour(123,123,123);
75 static void DrawButtonS(wxDC
& dc
,
78 const wxColour
& bkcolour
,
83 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
89 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
90 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
93 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
95 // draw the background behind the button
96 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
99 // draw the button itself
100 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
107 // -- wxAuiDefaultTabArt class implementation --
109 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
111 m_normal_font
= *wxNORMAL_FONT
;
112 m_selected_font
= *wxNORMAL_FONT
;
113 m_selected_font
.SetWeight(wxBOLD
);
114 m_measuring_font
= m_selected_font
;
116 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
118 wxColour background_colour
= StepColour(base_colour
, 95);
119 wxColour normaltab_colour
= base_colour
;
120 wxColour selectedtab_colour
= *wxWHITE
;
122 m_bkbrush
= wxBrush(background_colour
);
123 m_normal_bkbrush
= wxBrush(normaltab_colour
);
124 m_normal_bkpen
= wxPen(normaltab_colour
);
125 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
126 m_selected_bkpen
= wxPen(selectedtab_colour
);
129 #if defined( __WXMAC__ )
130 static unsigned char close_bits
[]={
131 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
132 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
133 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
134 #elif defined( __WXGTK__)
135 static unsigned char close_bits
[]={
136 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
137 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
138 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
140 static unsigned char close_bits
[]={
141 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
142 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
143 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
146 static unsigned char left_bits
[] = {
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
148 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
151 static unsigned char right_bits
[] = {
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
153 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156 static unsigned char list_bits
[] = {
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
158 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
162 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
163 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
165 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
166 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
168 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
169 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
171 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
172 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
176 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
180 void wxAuiDefaultTabArt::DrawBackground(wxDC
* dc
,
181 wxWindow
* WXUNUSED(wnd
),
185 dc
->SetBrush(m_bkbrush
);
186 dc
->SetPen(*wxTRANSPARENT_PEN
);
187 dc
->DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
190 dc
->SetPen(*wxGREY_PEN
);
191 dc
->DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
195 // DrawTab() draws an individual tab.
198 // in_rect - rectangle the tab should be confined to
199 // caption - tab's caption
200 // active - whether or not the tab is active
201 // out_rect - actual output rectangle
202 // x_extent - the advance x; where the next tab should start
204 void wxAuiDefaultTabArt::DrawTab(wxDC
* dc
,
206 const wxRect
& in_rect
,
207 const wxString
& caption_text
,
209 int close_button_state
,
210 wxRect
* out_tab_rect
,
211 wxRect
* out_button_rect
,
214 wxCoord normal_textx
, normal_texty
;
215 wxCoord selected_textx
, selected_texty
;
216 wxCoord textx
, texty
;
218 // if the caption is empty, measure some temporary text
219 wxString caption
= caption_text
;
220 if (caption_text
.empty())
223 dc
->SetFont(m_selected_font
);
224 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
226 dc
->SetFont(m_normal_font
);
227 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
229 // figure out the size of the tab
230 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
232 wxCoord tab_height
= tab_size
.y
;
233 wxCoord tab_width
= tab_size
.x
;
234 wxCoord tab_x
= in_rect
.x
;
235 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
237 // select pen, brush and font for the tab to be drawn
241 dc
->SetPen(m_selected_bkpen
);
242 dc
->SetBrush(m_selected_bkbrush
);
243 dc
->SetFont(m_selected_font
);
244 textx
= selected_textx
;
245 texty
= selected_texty
;
249 dc
->SetPen(m_normal_bkpen
);
250 dc
->SetBrush(m_normal_bkbrush
);
251 dc
->SetFont(m_normal_font
);
252 textx
= normal_textx
;
253 texty
= normal_texty
;
261 points
[0].y
= tab_y
+ tab_height
- 1;
262 points
[1].x
= tab_x
+ tab_height
- 3;
263 points
[1].y
= tab_y
+ 2;
264 points
[2].x
= tab_x
+ tab_height
+ 3;
266 points
[3].x
= tab_x
+ tab_width
- 2;
268 points
[4].x
= tab_x
+ tab_width
;
269 points
[4].y
= tab_y
+ 2;
270 points
[5].x
= tab_x
+ tab_width
;
271 points
[5].y
= tab_y
+ tab_height
- 1;
272 points
[6] = points
[0];
275 dc
->DrawPolygon(6, points
);
277 dc
->SetPen(*wxGREY_PEN
);
279 //dc->DrawLines(active ? 6 : 7, points);
280 dc
->DrawLines(7, points
);
285 int close_button_width
= 0;
286 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
288 close_button_width
= m_active_close_bmp
.GetWidth();
289 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
293 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
298 dc
->DrawText(caption
,
300 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
303 // draw close button if necessary
304 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
308 bmp
= m_active_close_bmp
;
310 bmp
= m_disabled_close_bmp
;
312 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
313 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
316 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
318 *out_button_rect
= rect
;
322 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
326 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
* dc
,
327 wxWindow
* WXUNUSED(wnd
),
328 const wxString
& caption
,
329 bool WXUNUSED(active
),
330 int close_button_state
,
333 wxCoord measured_textx
, measured_texty
;
335 dc
->SetFont(m_measuring_font
);
336 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
338 wxCoord tab_height
= measured_texty
+ 4;
339 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
341 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
342 tab_width
+= m_active_close_bmp
.GetWidth();
344 *x_extent
= tab_width
- (tab_height
/2) - 1;
346 return wxSize(tab_width
, tab_height
);
350 void wxAuiDefaultTabArt::DrawButton(
352 wxWindow
* WXUNUSED(wnd
),
353 const wxRect
& in_rect
,
357 const wxBitmap
& bitmap_override
,
363 if (bitmap_override
.IsOk())
365 bmp
= bitmap_override
;
371 case wxAUI_BUTTON_CLOSE
:
372 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
373 bmp
= m_disabled_close_bmp
;
375 bmp
= m_active_close_bmp
;
377 case wxAUI_BUTTON_LEFT
:
378 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
379 bmp
= m_disabled_left_bmp
;
381 bmp
= m_active_left_bmp
;
383 case wxAUI_BUTTON_RIGHT
:
384 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
385 bmp
= m_disabled_right_bmp
;
387 bmp
= m_active_right_bmp
;
389 case wxAUI_BUTTON_WINDOWLIST
:
390 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
391 bmp
= m_disabled_windowlist_bmp
;
393 bmp
= m_active_windowlist_bmp
;
403 if (orientation
== wxLEFT
)
405 rect
.SetX(in_rect
.x
);
406 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
407 rect
.SetWidth(bmp
.GetWidth());
408 rect
.SetHeight(bmp
.GetHeight());
412 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
413 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
414 bmp
.GetWidth(), bmp
.GetHeight());
418 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
426 // -- GUI helper classes and functions --
428 class wxAuiCommandCapture
: public wxEvtHandler
432 wxAuiCommandCapture() { m_last_id
= 0; }
433 int GetCommandId() const { return m_last_id
; }
435 bool ProcessEvent(wxEvent
& evt
)
437 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
439 m_last_id
= evt
.GetId();
443 if (GetNextHandler())
444 return GetNextHandler()->ProcessEvent(evt
);
455 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
456 const wxArrayString
& items
,
461 size_t i
, count
= items
.GetCount();
462 for (i
= 0; i
< count
; ++i
)
464 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
467 if (active_idx
!= -1)
469 menuPopup
.Check(1000+active_idx
, true);
472 // find out where to put the popup menu of window
473 // items. Subtract 100 for now to center the menu
474 // a bit, until a better mechanism can be implemented
475 wxPoint pt
= ::wxGetMousePosition();
476 pt
= wnd
->ScreenToClient(pt
);
482 // find out the screen coordinate at the bottom of the tab ctrl
483 wxRect cli_rect
= wnd
->GetClientRect();
484 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
486 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
487 wnd
->PushEventHandler(cc
);
488 wnd
->PopupMenu(&menuPopup
, pt
);
489 int command
= cc
->GetCommandId();
490 wnd
->PopEventHandler(true);
498 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
501 dc
.SetFont(m_measuring_font
);
503 wxSize s
= GetTabSize(&dc
,
507 wxAUI_BUTTON_STATE_HIDDEN
,
512 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
514 m_normal_font
= font
;
517 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
519 m_selected_font
= font
;
522 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
524 m_measuring_font
= font
;
532 // -- wxAuiTabContainer class implementation --
535 // wxAuiTabContainer is a class which contains information about each
536 // tab. It also can render an entire tab control to a specified DC.
537 // It's not a window class itself, because this code will be used by
538 // the wxFrameMananger, where it is disadvantageous to have separate
539 // windows for each tab control in the case of "docked tabs"
541 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
542 // which can be used as a tab control in the normal sense.
545 wxAuiTabContainer::wxAuiTabContainer()
549 m_art
= new wxAuiDefaultTabArt
;
551 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
552 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
553 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
554 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
557 wxAuiTabContainer::~wxAuiTabContainer()
562 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
568 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
573 void wxAuiTabContainer::SetFlags(unsigned int flags
)
577 // check for new close button settings
578 RemoveButton(wxAUI_BUTTON_LEFT
);
579 RemoveButton(wxAUI_BUTTON_RIGHT
);
580 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
581 RemoveButton(wxAUI_BUTTON_CLOSE
);
584 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
586 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
587 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
590 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
592 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
595 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
597 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
601 unsigned int wxAuiTabContainer::GetFlags() const
607 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
609 m_art
->SetNormalFont(font
);
612 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
614 m_art
->SetSelectedFont(font
);
617 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
619 m_art
->SetMeasuringFont(font
);
622 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
627 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
628 const wxAuiNotebookPage
& info
)
630 wxAuiNotebookPage page_info
;
632 page_info
.window
= page
;
634 m_pages
.Add(page_info
);
639 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
640 const wxAuiNotebookPage
& info
,
643 wxAuiNotebookPage page_info
;
645 page_info
.window
= page
;
647 if (idx
>= m_pages
.GetCount())
648 m_pages
.Add(page_info
);
650 m_pages
.Insert(page_info
, idx
);
655 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
658 int idx
= GetIdxFromWindow(page
);
662 // get page entry, make a copy of it
663 wxAuiNotebookPage p
= GetPage(idx
);
665 // remove old page entry
668 // insert page where it should be
669 InsertPage(page
, p
, new_idx
);
674 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
676 size_t i
, page_count
= m_pages
.GetCount();
677 for (i
= 0; i
< page_count
; ++i
)
679 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
680 if (page
.window
== wnd
)
690 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
694 size_t i
, page_count
= m_pages
.GetCount();
695 for (i
= 0; i
< page_count
; ++i
)
697 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
698 if (page
.window
== wnd
)
712 void wxAuiTabContainer::SetNoneActive()
714 size_t i
, page_count
= m_pages
.GetCount();
715 for (i
= 0; i
< page_count
; ++i
)
717 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
722 bool wxAuiTabContainer::SetActivePage(size_t page
)
724 if (page
>= m_pages
.GetCount())
727 return SetActivePage(m_pages
.Item(page
).window
);
730 int wxAuiTabContainer::GetActivePage() const
732 size_t i
, page_count
= m_pages
.GetCount();
733 for (i
= 0; i
< page_count
; ++i
)
735 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
743 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
745 if (idx
>= m_pages
.GetCount())
748 return m_pages
[idx
].window
;
751 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
753 size_t i
, page_count
= m_pages
.GetCount();
754 for (i
= 0; i
< page_count
; ++i
)
756 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
757 if (page
.window
== wnd
)
763 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
765 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
770 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
775 size_t wxAuiTabContainer::GetPageCount() const
777 return m_pages
.GetCount();
780 void wxAuiTabContainer::AddButton(int id
,
782 const wxBitmap
& normal_bitmap
,
783 const wxBitmap
& disabled_bitmap
)
785 wxAuiTabContainerButton button
;
787 button
.bitmap
= normal_bitmap
;
788 button
.dis_bitmap
= disabled_bitmap
;
789 button
.location
= location
;
790 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
792 m_buttons
.Add(button
);
795 void wxAuiTabContainer::RemoveButton(int id
)
797 size_t i
, button_count
= m_buttons
.GetCount();
799 for (i
= 0; i
< button_count
; ++i
)
801 if (m_buttons
.Item(i
).id
== id
)
803 m_buttons
.RemoveAt(i
);
811 size_t wxAuiTabContainer::GetTabOffset() const
816 void wxAuiTabContainer::SetTabOffset(size_t offset
)
818 m_tab_offset
= offset
;
821 // Render() renders the tab catalog to the specified DC
822 // It is a virtual function and can be overridden to
823 // provide custom drawing capabilities
824 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
829 size_t page_count
= m_pages
.GetCount();
830 size_t button_count
= m_buttons
.GetCount();
832 // create off-screen bitmap
833 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
834 dc
.SelectObject(bmp
);
837 // find out if size of tabs is larger than can be
838 // afforded on screen
840 int visible_width
= 0;
841 for (i
= 0; i
< page_count
; ++i
)
843 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
845 // determine if a close button is on this tab
846 bool close_button
= false;
847 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
848 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
855 wxSize size
= m_art
->GetTabSize(&dc
,
860 wxAUI_BUTTON_STATE_NORMAL
:
861 wxAUI_BUTTON_STATE_HIDDEN
,
864 if (i
+1 < page_count
)
865 total_width
+= x_extent
;
867 total_width
+= size
.x
;
869 if (i
>= m_tab_offset
)
871 if (i
+1 < page_count
)
872 visible_width
+= x_extent
;
874 visible_width
+= size
.x
;
878 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
880 // show left/right buttons
881 for (i
= 0; i
< button_count
; ++i
)
883 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
884 if (button
.id
== wxAUI_BUTTON_LEFT
||
885 button
.id
== wxAUI_BUTTON_RIGHT
)
887 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
893 // hide left/right buttons
894 for (i
= 0; i
< button_count
; ++i
)
896 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
897 if (button
.id
== wxAUI_BUTTON_LEFT
||
898 button
.id
== wxAUI_BUTTON_RIGHT
)
900 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
905 // determine whether left button should be enabled
906 for (i
= 0; i
< button_count
; ++i
)
908 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
909 if (button
.id
== wxAUI_BUTTON_LEFT
)
911 if (m_tab_offset
== 0)
912 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
914 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
916 if (button
.id
== wxAUI_BUTTON_RIGHT
)
918 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
919 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
921 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
928 m_art
->DrawBackground(&dc
, wnd
, m_rect
);
931 int left_buttons_width
= 0;
932 int right_buttons_width
= 0;
936 // draw the buttons on the right side
937 offset
= m_rect
.x
+ m_rect
.width
;
938 for (i
= 0; i
< button_count
; ++i
)
940 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
942 if (button
.location
!= wxRIGHT
)
944 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
947 wxRect button_rect
= m_rect
;
949 button_rect
.SetWidth(offset
);
951 m_art
->DrawButton(&dc
,
960 offset
-= button
.rect
.GetWidth();
961 right_buttons_width
+= button
.rect
.GetWidth();
968 // draw the buttons on the left side
970 for (i
= 0; i
< button_count
; ++i
)
972 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
974 if (button
.location
!= wxLEFT
)
976 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
979 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
981 m_art
->DrawButton(&dc
,
990 offset
+= button
.rect
.GetWidth();
991 left_buttons_width
+= button
.rect
.GetWidth();
994 offset
= left_buttons_width
;
996 // set a clipping region to the tabs don't draw over the buttons
997 dc
.SetClippingRegion(left_buttons_width
, 0,
998 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
1003 // prepare the tab-close-button array
1004 while (m_tab_close_buttons
.GetCount() < page_count
)
1006 wxAuiTabContainerButton tempbtn
;
1007 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1008 tempbtn
.location
= wxCENTER
;
1009 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1010 m_tab_close_buttons
.Add(tempbtn
);
1013 for (i
= 0; i
< m_tab_offset
; ++i
)
1015 // buttons before the tab offset must be set to hidden
1016 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1022 size_t active
= 999;
1023 int active_offset
= 0;
1026 wxRect rect
= m_rect
;
1029 rect
.height
= m_rect
.height
;
1031 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1033 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1034 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1036 // determine if a close button is on this tab
1037 bool close_button
= false;
1038 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1039 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1041 close_button
= true;
1042 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1044 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1045 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1046 tab_button
.location
= wxCENTER
;
1051 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1061 tab_button
.cur_state
,
1069 active_offset
= offset
;
1075 // draw the active tab again so it stands in the foreground
1076 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1078 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1080 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1082 // determine if a close button is on this tab
1083 bool close_button
= false;
1084 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1085 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1087 close_button
= true;
1090 rect
.x
= active_offset
;
1096 tab_button
.cur_state
,
1102 dc
.DestroyClippingRegion();
1104 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1105 m_rect
.GetWidth(), m_rect
.GetHeight(),
1110 // TabHitTest() tests if a tab was hit, passing the window pointer
1111 // back if that condition was fulfilled. The function returns
1112 // true if a tab was hit, otherwise false
1113 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1115 if (!m_rect
.Contains(x
,y
))
1118 wxAuiTabContainerButton
* btn
= NULL
;
1119 if (ButtonHitTest(x
, y
, &btn
))
1121 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1125 size_t i
, page_count
= m_pages
.GetCount();
1127 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1129 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1130 if (page
.rect
.Contains(x
,y
))
1141 // ButtonHitTest() tests if a button was hit. The function returns
1142 // true if a button was hit, otherwise false
1143 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1144 wxAuiTabContainerButton
** hit
) const
1146 if (!m_rect
.Contains(x
,y
))
1149 size_t i
, button_count
;
1152 button_count
= m_buttons
.GetCount();
1153 for (i
= 0; i
< button_count
; ++i
)
1155 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1156 if (button
.rect
.Contains(x
,y
))
1164 button_count
= m_tab_close_buttons
.GetCount();
1165 for (i
= 0; i
< button_count
; ++i
)
1167 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1168 if (button
.rect
.Contains(x
,y
))
1181 // the utility function ShowWnd() is the same as show,
1182 // except it handles wxAuiMDIChildFrame windows as well,
1183 // as the Show() method on this class is "unplugged"
1184 static void ShowWnd(wxWindow
* wnd
, bool show
)
1186 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1188 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1198 // DoShowHide() this function shows the active window, then
1199 // hides all of the other windows (in that order)
1200 void wxAuiTabContainer::DoShowHide()
1202 wxAuiNotebookPageArray
& pages
= GetPages();
1203 size_t i
, page_count
= pages
.GetCount();
1205 // show new active page first
1206 for (i
= 0; i
< page_count
; ++i
)
1208 wxAuiNotebookPage
& page
= pages
.Item(i
);
1211 ShowWnd(page
.window
, true);
1216 // hide all other pages
1217 for (i
= 0; i
< page_count
; ++i
)
1219 wxAuiNotebookPage
& page
= pages
.Item(i
);
1220 ShowWnd(page
.window
, page
.active
);
1229 // -- wxAuiTabCtrl class implementation --
1233 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1234 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1235 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1236 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1237 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1238 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1239 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1240 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1241 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1245 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1249 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1251 m_click_pt
= wxDefaultPosition
;
1252 m_is_dragging
= false;
1253 m_hover_button
= NULL
;
1256 wxAuiTabCtrl::~wxAuiTabCtrl()
1260 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1264 dc
.SetFont(GetFont());
1266 if (GetPageCount() > 0)
1270 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1274 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1276 wxSize s
= evt
.GetSize();
1277 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1281 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1284 m_click_pt
= wxDefaultPosition
;
1285 m_is_dragging
= false;
1289 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1291 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1292 e
.SetSelection(GetIdxFromWindow(wnd
));
1293 e
.SetOldSelection(GetActivePage());
1294 e
.SetEventObject(this);
1295 GetEventHandler()->ProcessEvent(e
);
1297 m_click_pt
.x
= evt
.m_x
;
1298 m_click_pt
.y
= evt
.m_y
;
1304 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1310 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1312 if (GetCapture() == this)
1317 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1318 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1319 evt
.SetOldSelection(evt
.GetSelection());
1320 evt
.SetEventObject(this);
1321 GetEventHandler()->ProcessEvent(evt
);
1327 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1331 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1333 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1334 evt
.SetInt(m_hover_button
->id
);
1335 evt
.SetEventObject(this);
1336 GetEventHandler()->ProcessEvent(evt
);
1340 m_click_pt
= wxDefaultPosition
;
1341 m_is_dragging
= false;
1345 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1347 wxPoint pos
= evt
.GetPosition();
1349 // check if the mouse is hovering above a button
1350 wxAuiTabContainerButton
* button
;
1351 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1353 if (m_hover_button
&& button
!= m_hover_button
)
1355 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1356 m_hover_button
= NULL
;
1361 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1363 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1366 m_hover_button
= button
;
1374 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1375 m_hover_button
= NULL
;
1382 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1387 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1388 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1389 evt
.SetOldSelection(evt
.GetSelection());
1390 evt
.SetEventObject(this);
1391 GetEventHandler()->ProcessEvent(evt
);
1396 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1397 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1399 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1400 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1402 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1403 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1404 evt
.SetOldSelection(evt
.GetSelection());
1405 evt
.SetEventObject(this);
1406 GetEventHandler()->ProcessEvent(evt
);
1408 m_is_dragging
= true;
1412 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1416 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1417 m_hover_button
= NULL
;
1423 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1425 int button
= event
.GetInt();
1427 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1429 if (button
== wxAUI_BUTTON_LEFT
)
1431 if (GetTabOffset() > 0)
1433 SetTabOffset(GetTabOffset()-1);
1440 SetTabOffset(GetTabOffset()+1);
1445 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
1449 size_t i
, page_count
= m_pages
.GetCount();
1450 for (i
= 0; i
< page_count
; ++i
)
1452 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1453 as
.Add(page
.caption
);
1456 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
1460 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1461 e
.SetSelection(idx
);
1462 e
.SetOldSelection(GetActivePage());
1463 e
.SetEventObject(this);
1464 GetEventHandler()->ProcessEvent(e
);
1473 // wxTabFrame is an interesting case. It's important that all child pages
1474 // of the multi-notebook control are all actually children of that control
1475 // (and not grandchildren). wxTabFrame facilitates this. There is one
1476 // instance of wxTabFrame for each tab control inside the multi-notebook.
1477 // It's important to know that wxTabFrame is not a real window, but it merely
1478 // used to capture the dimensions/positioning of the internal tab control and
1479 // it's managed page windows
1481 class wxTabFrame
: public wxWindow
1488 m_rect
= wxRect(0,0,200,200);
1489 m_tab_ctrl_height
= 20;
1492 void SetTabCtrlHeight(int h
)
1494 m_tab_ctrl_height
= h
;
1497 void DoSetSize(int x
, int y
,
1498 int width
, int height
,
1499 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1501 m_rect
= wxRect(x
, y
, width
, height
);
1505 void DoGetClientSize(int* x
, int* y
) const
1511 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1518 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1519 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1520 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1521 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1525 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1526 size_t i
, page_count
= pages
.GetCount();
1528 for (i
= 0; i
< page_count
; ++i
)
1530 wxAuiNotebookPage
& page
= pages
.Item(i
);
1531 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
,
1532 m_rect
.width
, m_rect
.height
-tab_height
);
1534 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1536 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
1537 wnd
->ApplyMDIChildFrameRect();
1542 void DoGetSize(int* x
, int* y
) const
1545 *x
= m_rect
.GetWidth();
1547 *y
= m_rect
.GetHeight();
1559 wxAuiTabCtrl
* m_tabs
;
1560 int m_tab_ctrl_height
;
1567 // -- wxAuiNotebook class implementation --
1569 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
1570 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1571 //EVT_SIZE(wxAuiNotebook::OnSize)
1572 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1573 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
1574 EVT_COMMAND_RANGE(10000, 10100,
1575 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1576 wxAuiNotebook::OnTabClicked
)
1577 EVT_COMMAND_RANGE(10000, 10100,
1578 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1579 wxAuiNotebook::OnTabBeginDrag
)
1580 EVT_COMMAND_RANGE(10000, 10100,
1581 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1582 wxAuiNotebook::OnTabEndDrag
)
1583 EVT_COMMAND_RANGE(10000, 10100,
1584 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1585 wxAuiNotebook::OnTabDragMotion
)
1586 EVT_COMMAND_RANGE(10000, 10100,
1587 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1588 wxAuiNotebook::OnTabButton
)
1591 wxAuiNotebook::wxAuiNotebook()
1594 m_tab_id_counter
= 10000;
1596 m_tab_ctrl_height
= 20;
1599 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
1603 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1605 InitNotebook(style
);
1608 bool wxAuiNotebook::Create(wxWindow
* parent
,
1614 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1617 InitNotebook(style
);
1622 // InitNotebook() contains common initialization
1623 // code called by all constructors
1624 void wxAuiNotebook::InitNotebook(long style
)
1627 m_tab_id_counter
= 10000;
1629 m_tab_ctrl_height
= 20;
1630 m_flags
= (unsigned int)style
;
1632 m_normal_font
= *wxNORMAL_FONT
;
1633 m_selected_font
= *wxNORMAL_FONT
;
1634 m_selected_font
.SetWeight(wxBOLD
);
1636 // choose a default for the tab height
1637 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1639 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1640 m_dummy_wnd
->SetSize(200, 200);
1641 m_dummy_wnd
->Show(false);
1643 m_mgr
.SetManagedWindow(this);
1645 m_mgr
.AddPane(m_dummy_wnd
,
1646 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1651 wxAuiNotebook::~wxAuiNotebook()
1656 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
1658 m_tabs
.SetArtProvider(art
);
1661 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
1663 return m_tabs
.GetArtProvider();
1666 void wxAuiNotebook::SetWindowStyleFlag(long style
)
1668 wxControl::SetWindowStyleFlag(style
);
1670 m_flags
= (unsigned int)style
;
1672 // if the control is already initialized
1673 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
1675 // let all of the tab children know about the new style
1677 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1678 size_t i
, pane_count
= all_panes
.GetCount();
1679 for (i
= 0; i
< pane_count
; ++i
)
1681 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1682 if (pane
.name
== wxT("dummy"))
1684 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1685 tabctrl
->SetFlags(m_flags
);
1693 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1694 const wxString
& caption
,
1696 const wxBitmap
& bitmap
)
1698 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1701 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1703 const wxString
& caption
,
1705 const wxBitmap
& bitmap
)
1707 wxAuiNotebookPage info
;
1709 info
.caption
= caption
;
1710 info
.bitmap
= bitmap
;
1711 info
.active
= false;
1713 // if there are currently no tabs, the first added
1714 // tab must be active
1715 if (m_tabs
.GetPageCount() == 0)
1718 m_tabs
.InsertPage(page
, info
, page_idx
);
1720 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1721 if (page_idx
>= active_tabctrl
->GetPageCount())
1722 active_tabctrl
->AddPage(page
, info
);
1724 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1727 active_tabctrl
->DoShowHide();
1731 int idx
= m_tabs
.GetIdxFromWindow(page
);
1732 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1741 // DeletePage() removes a tab from the multi-notebook,
1742 // and destroys the window as well
1743 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1745 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1746 wxWindow
* new_active
= NULL
;
1748 // find out which onscreen tab ctrl owns this tab
1751 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1754 // find a new page and set it as active
1755 int new_idx
= ctrl_idx
+1;
1756 if (new_idx
>= (int)ctrl
->GetPageCount())
1757 new_idx
= ctrl_idx
-1;
1759 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1761 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1765 // set the active page to the first page that
1766 // isn't the one being deleted
1767 size_t i
, page_count
= m_tabs
.GetPageCount();
1768 for (i
= 0; i
< page_count
; ++i
)
1770 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1773 new_active
= m_tabs
.GetWindowFromIdx(i
);
1779 // remove the tab from main catalog
1780 if (!m_tabs
.RemovePage(wnd
))
1783 // remove the tab from the onscreen tab ctrl
1784 ctrl
->RemovePage(wnd
);
1786 // actually destroy the window now
1787 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1789 // delete the child frame with pending delete, as is
1790 // customary with frame windows
1791 if (!wxPendingDelete
.Member(wnd
))
1792 wxPendingDelete
.Append(wnd
);
1799 RemoveEmptyTabFrames();
1801 // set new active pane
1805 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1813 // RemovePage() removes a tab from the multi-notebook,
1814 // but does not destroy the window
1815 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1817 // remove the tab from our own catalog
1818 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1819 if (!m_tabs
.RemovePage(wnd
))
1822 // remove the tab from the onscreen tab ctrl
1825 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1827 ctrl
->RemovePage(wnd
);
1834 // SetPageText() changes the tab caption of the specified page
1835 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1837 if (page_idx
>= m_tabs
.GetPageCount())
1840 // update our own tab catalog
1841 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1842 page_info
.caption
= text
;
1844 // update what's on screen
1847 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1849 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1850 info
.caption
= text
;
1858 // GetSelection() returns the index of the currently active page
1859 int wxAuiNotebook::GetSelection() const
1864 // SetSelection() sets the currently active page
1865 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1867 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1871 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1872 evt
.SetSelection(new_page
);
1873 evt
.SetOldSelection(m_curpage
);
1874 evt
.SetEventObject(this);
1875 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1877 // program allows the page change
1878 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1879 (void)GetEventHandler()->ProcessEvent(evt
);
1885 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1887 m_tabs
.SetActivePage(wnd
);
1889 ctrl
->SetActivePage(ctrl_idx
);
1893 int old_curpage
= m_curpage
;
1894 m_curpage
= new_page
;
1898 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1899 size_t i
, pane_count
= all_panes
.GetCount();
1900 for (i
= 0; i
< pane_count
; ++i
)
1902 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1903 if (pane
.name
== wxT("dummy"))
1905 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1906 if (tabctrl
!= ctrl
)
1907 tabctrl
->SetSelectedFont(m_normal_font
);
1909 tabctrl
->SetSelectedFont(m_selected_font
);
1922 // GetPageCount() returns the total number of
1923 // pages managed by the multi-notebook
1924 size_t wxAuiNotebook::GetPageCount() const
1926 return m_tabs
.GetPageCount();
1929 // GetPage() returns the wxWindow pointer of the
1931 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1933 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1935 return m_tabs
.GetWindowFromIdx(page_idx
);
1938 // DoSizing() performs all sizing operations in each tab control
1939 void wxAuiNotebook::DoSizing()
1941 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1942 size_t i
, pane_count
= all_panes
.GetCount();
1943 for (i
= 0; i
< pane_count
; ++i
)
1945 if (all_panes
.Item(i
).name
== wxT("dummy"))
1948 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1949 tabframe
->DoSizing();
1953 // GetActiveTabCtrl() returns the active tab control. It is
1954 // called to determine which control gets new windows being added
1955 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1957 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1962 // find the tab ctrl with the current page
1963 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1970 // no current page, just find the first tab ctrl
1971 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1972 size_t i
, pane_count
= all_panes
.GetCount();
1973 for (i
= 0; i
< pane_count
; ++i
)
1975 if (all_panes
.Item(i
).name
== wxT("dummy"))
1978 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1979 return tabframe
->m_tabs
;
1982 // If there is no tabframe at all, create one
1983 wxTabFrame
* tabframe
= new wxTabFrame
;
1984 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1985 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1990 tabframe
->m_tabs
->SetFlags(m_flags
);
1991 m_mgr
.AddPane(tabframe
,
1992 wxAuiPaneInfo().Center().CaptionVisible(false));
1996 return tabframe
->m_tabs
;
1999 // FindTab() finds the tab control that currently contains the window as well
2000 // as the index of the window in the tab control. It returns true if the
2001 // window was found, otherwise false.
2002 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2004 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2005 size_t i
, pane_count
= all_panes
.GetCount();
2006 for (i
= 0; i
< pane_count
; ++i
)
2008 if (all_panes
.Item(i
).name
== wxT("dummy"))
2011 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2013 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2016 *ctrl
= tabframe
->m_tabs
;
2026 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2030 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2034 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2036 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2038 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2039 wxASSERT(ctrl
!= NULL
);
2041 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2042 wxASSERT(wnd
!= NULL
);
2044 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2045 wxASSERT(idx
!= -1);
2050 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2055 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2057 wxPoint screen_pt
= ::wxGetMousePosition();
2058 wxPoint client_pt
= ScreenToClient(screen_pt
);
2061 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2063 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2064 if (dest_tabs
== src_tabs
)
2068 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2071 // always hide the hint for inner-tabctrl drag
2074 // if tab moving is not allowed, leave
2075 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2080 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2081 wxWindow
* dest_location_tab
;
2083 // this is an inner-tab drag/reposition
2084 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2086 int src_idx
= evt
.GetSelection();
2087 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2089 // prevent jumpy drag
2090 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2091 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2092 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2094 m_last_drag_x
= pt
.x
;
2099 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2100 dest_tabs
->MovePage(src_tab
, dest_idx
);
2101 dest_tabs
->SetActivePage((size_t)dest_idx
);
2102 dest_tabs
->DoShowHide();
2103 dest_tabs
->Refresh();
2104 m_last_drag_x
= pt
.x
;
2112 // if tab moving is not allowed, leave
2113 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2121 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2127 wxRect hint_rect
= dest_tabs
->GetRect();
2128 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2129 m_mgr
.ShowHint(hint_rect
);
2133 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2139 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2141 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2145 // if tab moving is not allowed, leave
2146 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2151 // set cursor back to an arrow
2152 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2155 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2158 // get the mouse position, which will be used to determine the drop point
2159 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2160 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2163 // the src tab control is the control that fired this event
2164 wxAuiTabCtrl
* dest_tabs
= NULL
;
2167 // If the pointer is in an existing tab frame, do a tab insert
2168 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2169 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2170 int insert_idx
= -1;
2173 dest_tabs
= tab_frame
->m_tabs
;
2175 if (dest_tabs
== src_tabs
)
2179 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2180 wxWindow
* target
= NULL
;
2181 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2184 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2189 // If there is no tabframe at all, create one
2190 wxTabFrame
* new_tabs
= new wxTabFrame
;
2191 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2192 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2197 new_tabs
->m_tabs
->SetFlags(m_flags
);
2199 m_mgr
.AddPane(new_tabs
,
2200 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2203 dest_tabs
= new_tabs
->m_tabs
;
2208 // remove the page from the source tabs
2209 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2210 page_info
.active
= false;
2211 src_tabs
->RemovePage(page_info
.window
);
2212 if (src_tabs
->GetPageCount() > 0)
2214 src_tabs
->SetActivePage((size_t)0);
2215 src_tabs
->DoShowHide();
2216 src_tabs
->Refresh();
2221 // add the page to the destination tabs
2222 if (insert_idx
== -1)
2223 insert_idx
= dest_tabs
->GetPageCount();
2224 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2226 if (src_tabs
->GetPageCount() == 0)
2228 RemoveEmptyTabFrames();
2232 dest_tabs
->DoShowHide();
2233 dest_tabs
->Refresh();
2235 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2240 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2242 // if we've just removed the last tab from the source
2243 // tab set, the remove the tab control completely
2244 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2245 size_t i
, pane_count
= all_panes
.GetCount();
2246 for (i
= 0; i
< pane_count
; ++i
)
2248 if (all_panes
.Item(i
).name
== wxT("dummy"))
2251 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2252 if (tabframe
->m_tab_rect
.Contains(pt
))
2253 return tabframe
->m_tabs
;
2259 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2261 // if we've just removed the last tab from the source
2262 // tab set, the remove the tab control completely
2263 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2264 size_t i
, pane_count
= all_panes
.GetCount();
2265 for (i
= 0; i
< pane_count
; ++i
)
2267 if (all_panes
.Item(i
).name
== wxT("dummy"))
2270 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2271 if (tabframe
->m_tabs
== tab_ctrl
)
2280 void wxAuiNotebook::RemoveEmptyTabFrames()
2282 // if we've just removed the last tab from the source
2283 // tab set, the remove the tab control completely
2284 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2285 size_t i
, pane_count
= all_panes
.GetCount();
2286 for (i
= 0; i
< pane_count
; ++i
)
2288 if (all_panes
.Item(i
).name
== wxT("dummy"))
2291 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2292 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2294 m_mgr
.DetachPane(tab_frame
);
2296 // use pending delete because sometimes during
2297 // window closing, refreshs are pending
2298 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2299 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2300 //tab_frame->m_tabs->Destroy();
2307 // check to see if there is still a center pane;
2308 // if there isn't, make a frame the center pane
2309 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2310 pane_count
= panes
.GetCount();
2311 wxWindow
* first_good
= NULL
;
2312 bool center_found
= false;
2313 for (i
= 0; i
< pane_count
; ++i
)
2315 if (panes
.Item(i
).name
== wxT("dummy"))
2317 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2318 center_found
= true;
2320 first_good
= panes
.Item(i
).window
;
2323 if (!center_found
&& first_good
)
2325 m_mgr
.GetPane(first_good
).Centre();
2331 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2333 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2334 if (idx
!= -1 && idx
!= m_curpage
)
2341 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2343 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2344 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2346 int button_id
= evt
.GetInt();
2348 if (button_id
== wxAUI_BUTTON_CLOSE
)
2350 int selection
= tabs
->GetActivePage();
2352 if (selection
!= -1)
2354 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2356 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2362 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2363 DeletePage(main_idx
);