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"
33 #include "wx/arrimpl.cpp"
34 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
35 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
37 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
45 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
46 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
52 // This functions are here for this proof of concept
53 // and will be factored out later. See dockart.cpp
54 static wxColor
StepColour(const wxColor
& c
, int percent
)
56 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
57 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
58 (unsigned char)wxMin((g
*percent
)/100,255),
59 (unsigned char)wxMin((b
*percent
)/100,255));
62 // This functions are here for this proof of concept
63 // and will be factored out later. See dockart.cpp
64 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
65 const wxColour
& color
)
67 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
68 img
.Replace(0,0,0,123,123,123);
69 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
70 img
.SetMaskColour(123,123,123);
74 static void DrawButtonS(wxDC
& dc
,
77 const wxColour
& bkcolour
,
82 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
88 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
89 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
91 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
92 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
94 // draw the background behind the button
95 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
98 // draw the button itself
99 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
106 // -- wxAuiDefaultTabArt class implementation --
108 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
110 m_normal_font
= *wxNORMAL_FONT
;
111 m_selected_font
= *wxNORMAL_FONT
;
112 m_selected_font
.SetWeight(wxBOLD
);
113 m_measuring_font
= m_selected_font
;
115 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
117 wxColour background_colour
= StepColour(base_colour
, 95);
118 wxColour normaltab_colour
= base_colour
;
119 wxColour selectedtab_colour
= *wxWHITE
;
121 m_bkbrush
= wxBrush(background_colour
);
122 m_normal_bkbrush
= wxBrush(normaltab_colour
);
123 m_normal_bkpen
= wxPen(normaltab_colour
);
124 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
125 m_selected_bkpen
= wxPen(selectedtab_colour
);
128 #if defined( __WXMAC__ )
129 static unsigned char close_bits
[]={
130 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
131 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
132 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
133 #elif defined( __WXGTK__)
134 static unsigned char close_bits
[]={
135 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
136 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
137 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
139 static unsigned char close_bits
[]={
140 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
141 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
142 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
145 static unsigned char left_bits
[] = {
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
147 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
150 static unsigned char right_bits
[] = {
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
152 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
155 static unsigned char list_bits
[] = {
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
161 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
162 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
164 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
165 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
167 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
168 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
170 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
171 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
175 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
179 void wxAuiDefaultTabArt::DrawBackground(wxDC
* dc
,
180 wxWindow
* WXUNUSED(wnd
),
184 dc
->SetBrush(m_bkbrush
);
185 dc
->SetPen(*wxTRANSPARENT_PEN
);
186 dc
->DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
189 dc
->SetPen(*wxGREY_PEN
);
190 dc
->DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
194 // DrawTab() draws an individual tab.
197 // in_rect - rectangle the tab should be confined to
198 // caption - tab's caption
199 // active - whether or not the tab is active
200 // out_rect - actual output rectangle
201 // x_extent - the advance x; where the next tab should start
203 void wxAuiDefaultTabArt::DrawTab(wxDC
* dc
,
205 const wxRect
& in_rect
,
206 const wxString
& caption_text
,
208 int close_button_state
,
209 wxRect
* out_tab_rect
,
210 wxRect
* out_button_rect
,
213 wxCoord normal_textx
, normal_texty
;
214 wxCoord selected_textx
, selected_texty
;
215 wxCoord textx
, texty
;
217 // if the caption is empty, measure some temporary text
218 wxString caption
= caption_text
;
219 if (caption_text
.empty())
222 dc
->SetFont(m_selected_font
);
223 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
225 dc
->SetFont(m_normal_font
);
226 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
228 // figure out the size of the tab
229 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
231 wxCoord tab_height
= tab_size
.y
;
232 wxCoord tab_width
= tab_size
.x
;
233 wxCoord tab_x
= in_rect
.x
;
234 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
236 // select pen, brush and font for the tab to be drawn
240 dc
->SetPen(m_selected_bkpen
);
241 dc
->SetBrush(m_selected_bkbrush
);
242 dc
->SetFont(m_selected_font
);
243 textx
= selected_textx
;
244 texty
= selected_texty
;
248 dc
->SetPen(m_normal_bkpen
);
249 dc
->SetBrush(m_normal_bkbrush
);
250 dc
->SetFont(m_normal_font
);
251 textx
= normal_textx
;
252 texty
= normal_texty
;
260 points
[0].y
= tab_y
+ tab_height
- 1;
261 points
[1].x
= tab_x
+ tab_height
- 3;
262 points
[1].y
= tab_y
+ 2;
263 points
[2].x
= tab_x
+ tab_height
+ 3;
265 points
[3].x
= tab_x
+ tab_width
- 2;
267 points
[4].x
= tab_x
+ tab_width
;
268 points
[4].y
= tab_y
+ 2;
269 points
[5].x
= tab_x
+ tab_width
;
270 points
[5].y
= tab_y
+ tab_height
- 1;
271 points
[6] = points
[0];
274 dc
->DrawPolygon(6, points
);
276 dc
->SetPen(*wxGREY_PEN
);
278 //dc->DrawLines(active ? 6 : 7, points);
279 dc
->DrawLines(7, points
);
284 int close_button_width
= 0;
285 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
287 close_button_width
= m_active_close_bmp
.GetWidth();
288 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
292 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
297 dc
->DrawText(caption
,
299 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
302 // draw close button if necessary
303 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
307 bmp
= m_active_close_bmp
;
309 bmp
= m_disabled_close_bmp
;
311 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
312 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
315 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
317 *out_button_rect
= rect
;
321 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
325 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
* dc
,
326 wxWindow
* WXUNUSED(wnd
),
327 const wxString
& caption
,
328 bool WXUNUSED(active
),
329 int close_button_state
,
332 wxCoord measured_textx
, measured_texty
;
334 dc
->SetFont(m_measuring_font
);
335 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
337 wxCoord tab_height
= measured_texty
+ 4;
338 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
340 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
341 tab_width
+= m_active_close_bmp
.GetWidth();
343 *x_extent
= tab_width
- (tab_height
/2) - 1;
345 return wxSize(tab_width
, tab_height
);
349 void wxAuiDefaultTabArt::DrawButton(
351 wxWindow
* WXUNUSED(wnd
),
352 const wxRect
& in_rect
,
356 const wxBitmap
& bitmap_override
,
362 if (bitmap_override
.IsOk())
364 bmp
= bitmap_override
;
370 case wxAUI_BUTTON_CLOSE
:
371 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
372 bmp
= m_disabled_close_bmp
;
374 bmp
= m_active_close_bmp
;
376 case wxAUI_BUTTON_LEFT
:
377 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
378 bmp
= m_disabled_left_bmp
;
380 bmp
= m_active_left_bmp
;
382 case wxAUI_BUTTON_RIGHT
:
383 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
384 bmp
= m_disabled_right_bmp
;
386 bmp
= m_active_right_bmp
;
388 case wxAUI_BUTTON_WINDOWLIST
:
389 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
390 bmp
= m_disabled_windowlist_bmp
;
392 bmp
= m_active_windowlist_bmp
;
402 if (orientation
== wxLEFT
)
404 rect
.SetX(in_rect
.x
);
405 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
406 rect
.SetWidth(bmp
.GetWidth());
407 rect
.SetHeight(bmp
.GetHeight());
411 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
412 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
413 bmp
.GetWidth(), bmp
.GetHeight());
417 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
425 // -- GUI helper classes and functions --
427 class wxAuiCommandCapture
: public wxEvtHandler
431 wxAuiCommandCapture() { m_last_id
= 0; }
432 int GetCommandId() const { return m_last_id
; }
434 bool ProcessEvent(wxEvent
& evt
)
436 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
438 m_last_id
= evt
.GetId();
442 if (GetNextHandler())
443 return GetNextHandler()->ProcessEvent(evt
);
454 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
455 const wxArrayString
& items
,
460 size_t i
, count
= items
.GetCount();
461 for (i
= 0; i
< count
; ++i
)
463 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
466 if (active_idx
!= -1)
468 menuPopup
.Check(1000+active_idx
, true);
471 // find out where to put the popup menu of window
472 // items. Subtract 100 for now to center the menu
473 // a bit, until a better mechanism can be implemented
474 wxPoint pt
= ::wxGetMousePosition();
475 pt
= wnd
->ScreenToClient(pt
);
481 // find out the screen coordinate at the bottom of the tab ctrl
482 wxRect cli_rect
= wnd
->GetClientRect();
483 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
485 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
486 wnd
->PushEventHandler(cc
);
487 wnd
->PopupMenu(&menuPopup
, pt
);
488 int command
= cc
->GetCommandId();
489 wnd
->PopEventHandler(true);
497 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
500 dc
.SetFont(m_measuring_font
);
502 wxSize s
= GetTabSize(&dc
,
506 wxAUI_BUTTON_STATE_HIDDEN
,
511 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
513 m_normal_font
= font
;
516 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
518 m_selected_font
= font
;
521 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
523 m_measuring_font
= font
;
531 // -- wxAuiTabContainer class implementation --
534 // wxAuiTabContainer is a class which contains information about each
535 // tab. It also can render an entire tab control to a specified DC.
536 // It's not a window class itself, because this code will be used by
537 // the wxFrameMananger, where it is disadvantageous to have separate
538 // windows for each tab control in the case of "docked tabs"
540 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
541 // which can be used as a tab control in the normal sense.
544 wxAuiTabContainer::wxAuiTabContainer()
548 m_art
= new wxAuiDefaultTabArt
;
550 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
551 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
552 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
553 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
556 wxAuiTabContainer::~wxAuiTabContainer()
561 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
567 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
572 void wxAuiTabContainer::SetFlags(unsigned int flags
)
576 // check for new close button settings
577 RemoveButton(wxAUI_BUTTON_LEFT
);
578 RemoveButton(wxAUI_BUTTON_RIGHT
);
579 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
580 RemoveButton(wxAUI_BUTTON_CLOSE
);
583 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
585 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
586 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
589 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
591 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
594 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
596 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
600 unsigned int wxAuiTabContainer::GetFlags() const
606 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
608 m_art
->SetNormalFont(font
);
611 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
613 m_art
->SetSelectedFont(font
);
616 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
618 m_art
->SetMeasuringFont(font
);
621 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
626 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
627 const wxAuiNotebookPage
& info
)
629 wxAuiNotebookPage page_info
;
631 page_info
.window
= page
;
633 m_pages
.Add(page_info
);
638 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
639 const wxAuiNotebookPage
& info
,
642 wxAuiNotebookPage page_info
;
644 page_info
.window
= page
;
646 if (idx
>= m_pages
.GetCount())
647 m_pages
.Add(page_info
);
649 m_pages
.Insert(page_info
, idx
);
654 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
657 int idx
= GetIdxFromWindow(page
);
661 // get page entry, make a copy of it
662 wxAuiNotebookPage p
= GetPage(idx
);
664 // remove old page entry
667 // insert page where it should be
668 InsertPage(page
, p
, new_idx
);
673 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
675 size_t i
, page_count
= m_pages
.GetCount();
676 for (i
= 0; i
< page_count
; ++i
)
678 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
679 if (page
.window
== wnd
)
689 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
693 size_t i
, page_count
= m_pages
.GetCount();
694 for (i
= 0; i
< page_count
; ++i
)
696 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
697 if (page
.window
== wnd
)
711 void wxAuiTabContainer::SetNoneActive()
713 size_t i
, page_count
= m_pages
.GetCount();
714 for (i
= 0; i
< page_count
; ++i
)
716 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
721 bool wxAuiTabContainer::SetActivePage(size_t page
)
723 if (page
>= m_pages
.GetCount())
726 return SetActivePage(m_pages
.Item(page
).window
);
729 int wxAuiTabContainer::GetActivePage() const
731 size_t i
, page_count
= m_pages
.GetCount();
732 for (i
= 0; i
< page_count
; ++i
)
734 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
742 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
744 if (idx
>= m_pages
.GetCount())
747 return m_pages
[idx
].window
;
750 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
752 size_t i
, page_count
= m_pages
.GetCount();
753 for (i
= 0; i
< page_count
; ++i
)
755 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
756 if (page
.window
== wnd
)
762 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
764 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
769 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
774 size_t wxAuiTabContainer::GetPageCount() const
776 return m_pages
.GetCount();
779 void wxAuiTabContainer::AddButton(int id
,
781 const wxBitmap
& normal_bitmap
,
782 const wxBitmap
& disabled_bitmap
)
784 wxAuiTabContainerButton button
;
786 button
.bitmap
= normal_bitmap
;
787 button
.dis_bitmap
= disabled_bitmap
;
788 button
.location
= location
;
789 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
791 m_buttons
.Add(button
);
794 void wxAuiTabContainer::RemoveButton(int id
)
796 size_t i
, button_count
= m_buttons
.GetCount();
798 for (i
= 0; i
< button_count
; ++i
)
800 if (m_buttons
.Item(i
).id
== id
)
802 m_buttons
.RemoveAt(i
);
810 size_t wxAuiTabContainer::GetTabOffset() const
815 void wxAuiTabContainer::SetTabOffset(size_t offset
)
817 m_tab_offset
= offset
;
820 // Render() renders the tab catalog to the specified DC
821 // It is a virtual function and can be overridden to
822 // provide custom drawing capabilities
823 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
828 size_t page_count
= m_pages
.GetCount();
829 size_t button_count
= m_buttons
.GetCount();
831 // create off-screen bitmap
832 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
833 dc
.SelectObject(bmp
);
836 // find out if size of tabs is larger than can be
837 // afforded on screen
839 int visible_width
= 0;
840 for (i
= 0; i
< page_count
; ++i
)
842 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
844 // determine if a close button is on this tab
845 bool close_button
= false;
846 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
847 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
854 wxSize size
= m_art
->GetTabSize(&dc
,
859 wxAUI_BUTTON_STATE_NORMAL
:
860 wxAUI_BUTTON_STATE_HIDDEN
,
863 if (i
+1 < page_count
)
864 total_width
+= x_extent
;
866 total_width
+= size
.x
;
868 if (i
>= m_tab_offset
)
870 if (i
+1 < page_count
)
871 visible_width
+= x_extent
;
873 visible_width
+= size
.x
;
877 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
879 // show left/right buttons
880 for (i
= 0; i
< button_count
; ++i
)
882 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
883 if (button
.id
== wxAUI_BUTTON_LEFT
||
884 button
.id
== wxAUI_BUTTON_RIGHT
)
886 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
892 // hide left/right buttons
893 for (i
= 0; i
< button_count
; ++i
)
895 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
896 if (button
.id
== wxAUI_BUTTON_LEFT
||
897 button
.id
== wxAUI_BUTTON_RIGHT
)
899 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
904 // determine whether left button should be enabled
905 for (i
= 0; i
< button_count
; ++i
)
907 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
908 if (button
.id
== wxAUI_BUTTON_LEFT
)
910 if (m_tab_offset
== 0)
911 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
913 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
915 if (button
.id
== wxAUI_BUTTON_RIGHT
)
917 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
918 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
920 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
927 m_art
->DrawBackground(&dc
, wnd
, m_rect
);
930 int left_buttons_width
= 0;
931 int right_buttons_width
= 0;
935 // draw the buttons on the right side
936 offset
= m_rect
.x
+ m_rect
.width
;
937 for (i
= 0; i
< button_count
; ++i
)
939 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
941 if (button
.location
!= wxRIGHT
)
943 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
946 wxRect button_rect
= m_rect
;
948 button_rect
.SetWidth(offset
);
950 m_art
->DrawButton(&dc
,
959 offset
-= button
.rect
.GetWidth();
960 right_buttons_width
+= button
.rect
.GetWidth();
967 // draw the buttons on the left side
969 for (i
= 0; i
< button_count
; ++i
)
971 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
973 if (button
.location
!= wxLEFT
)
975 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
978 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
980 m_art
->DrawButton(&dc
,
989 offset
+= button
.rect
.GetWidth();
990 left_buttons_width
+= button
.rect
.GetWidth();
993 offset
= left_buttons_width
;
995 // set a clipping region to the tabs don't draw over the buttons
996 dc
.SetClippingRegion(left_buttons_width
, 0,
997 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
1002 // prepare the tab-close-button array
1003 while (m_tab_close_buttons
.GetCount() < page_count
)
1005 wxAuiTabContainerButton tempbtn
;
1006 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1007 tempbtn
.location
= wxCENTER
;
1008 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1009 m_tab_close_buttons
.Add(tempbtn
);
1012 for (i
= 0; i
< m_tab_offset
; ++i
)
1014 // buttons before the tab offset must be set to hidden
1015 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1021 size_t active
= 999;
1022 int active_offset
= 0;
1025 wxRect rect
= m_rect
;
1028 rect
.height
= m_rect
.height
;
1030 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1032 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1033 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1035 // determine if a close button is on this tab
1036 bool close_button
= false;
1037 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1038 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1040 close_button
= true;
1041 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1043 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1044 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1045 tab_button
.location
= wxCENTER
;
1050 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1060 tab_button
.cur_state
,
1068 active_offset
= offset
;
1074 // draw the active tab again so it stands in the foreground
1075 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1077 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1079 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1081 // determine if a close button is on this tab
1082 bool close_button
= false;
1083 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1084 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1086 close_button
= true;
1089 rect
.x
= active_offset
;
1095 tab_button
.cur_state
,
1101 dc
.DestroyClippingRegion();
1103 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1104 m_rect
.GetWidth(), m_rect
.GetHeight(),
1109 // TabHitTest() tests if a tab was hit, passing the window pointer
1110 // back if that condition was fulfilled. The function returns
1111 // true if a tab was hit, otherwise false
1112 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1114 if (!m_rect
.Contains(x
,y
))
1117 wxAuiTabContainerButton
* btn
= NULL
;
1118 if (ButtonHitTest(x
, y
, &btn
))
1120 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1124 size_t i
, page_count
= m_pages
.GetCount();
1126 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1128 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1129 if (page
.rect
.Contains(x
,y
))
1140 // ButtonHitTest() tests if a button was hit. The function returns
1141 // true if a button was hit, otherwise false
1142 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1143 wxAuiTabContainerButton
** hit
) const
1145 if (!m_rect
.Contains(x
,y
))
1148 size_t i
, button_count
;
1151 button_count
= m_buttons
.GetCount();
1152 for (i
= 0; i
< button_count
; ++i
)
1154 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1155 if (button
.rect
.Contains(x
,y
))
1163 button_count
= m_tab_close_buttons
.GetCount();
1164 for (i
= 0; i
< button_count
; ++i
)
1166 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1167 if (button
.rect
.Contains(x
,y
))
1180 // the utility function ShowWnd() is the same as show,
1181 // except it handles wxAuiMDIChildFrame windows as well,
1182 // as the Show() method on this class is "unplugged"
1183 static void ShowWnd(wxWindow
* wnd
, bool show
)
1185 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1187 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1197 // DoShowHide() this function shows the active window, then
1198 // hides all of the other windows (in that order)
1199 void wxAuiTabContainer::DoShowHide()
1201 wxAuiNotebookPageArray
& pages
= GetPages();
1202 size_t i
, page_count
= pages
.GetCount();
1204 // show new active page first
1205 for (i
= 0; i
< page_count
; ++i
)
1207 wxAuiNotebookPage
& page
= pages
.Item(i
);
1210 ShowWnd(page
.window
, true);
1215 // hide all other pages
1216 for (i
= 0; i
< page_count
; ++i
)
1218 wxAuiNotebookPage
& page
= pages
.Item(i
);
1219 ShowWnd(page
.window
, page
.active
);
1228 // -- wxAuiTabCtrl class implementation --
1232 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1233 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1234 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1235 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1236 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1237 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1238 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1239 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1240 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1244 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1248 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1250 m_click_pt
= wxDefaultPosition
;
1251 m_is_dragging
= false;
1252 m_hover_button
= NULL
;
1255 wxAuiTabCtrl::~wxAuiTabCtrl()
1259 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1263 dc
.SetFont(GetFont());
1265 if (GetPageCount() > 0)
1269 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1273 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1275 wxSize s
= evt
.GetSize();
1276 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1280 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1283 m_click_pt
= wxDefaultPosition
;
1284 m_is_dragging
= false;
1288 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1290 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1291 e
.SetSelection(GetIdxFromWindow(wnd
));
1292 e
.SetOldSelection(GetActivePage());
1293 e
.SetEventObject(this);
1294 GetEventHandler()->ProcessEvent(e
);
1296 m_click_pt
.x
= evt
.m_x
;
1297 m_click_pt
.y
= evt
.m_y
;
1303 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1309 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1311 if (GetCapture() == this)
1316 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1317 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1318 evt
.SetOldSelection(evt
.GetSelection());
1319 evt
.SetEventObject(this);
1320 GetEventHandler()->ProcessEvent(evt
);
1326 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1330 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1332 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1333 evt
.SetInt(m_hover_button
->id
);
1334 evt
.SetEventObject(this);
1335 GetEventHandler()->ProcessEvent(evt
);
1339 m_click_pt
= wxDefaultPosition
;
1340 m_is_dragging
= false;
1344 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1346 wxPoint pos
= evt
.GetPosition();
1348 // check if the mouse is hovering above a button
1349 wxAuiTabContainerButton
* button
;
1350 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1352 if (m_hover_button
&& button
!= m_hover_button
)
1354 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1355 m_hover_button
= NULL
;
1360 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1362 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1365 m_hover_button
= button
;
1373 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1374 m_hover_button
= NULL
;
1381 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1386 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1387 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1388 evt
.SetOldSelection(evt
.GetSelection());
1389 evt
.SetEventObject(this);
1390 GetEventHandler()->ProcessEvent(evt
);
1395 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1396 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1398 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1399 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1401 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1402 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1403 evt
.SetOldSelection(evt
.GetSelection());
1404 evt
.SetEventObject(this);
1405 GetEventHandler()->ProcessEvent(evt
);
1407 m_is_dragging
= true;
1411 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1415 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1416 m_hover_button
= NULL
;
1422 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1424 int button
= event
.GetInt();
1426 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1428 if (button
== wxAUI_BUTTON_LEFT
)
1430 if (GetTabOffset() > 0)
1432 SetTabOffset(GetTabOffset()-1);
1439 SetTabOffset(GetTabOffset()+1);
1444 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
1448 size_t i
, page_count
= m_pages
.GetCount();
1449 for (i
= 0; i
< page_count
; ++i
)
1451 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1452 as
.Add(page
.caption
);
1455 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
1459 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1460 e
.SetSelection(idx
);
1461 e
.SetOldSelection(GetActivePage());
1462 e
.SetEventObject(this);
1463 GetEventHandler()->ProcessEvent(e
);
1472 // wxTabFrame is an interesting case. It's important that all child pages
1473 // of the multi-notebook control are all actually children of that control
1474 // (and not grandchildren). wxTabFrame facilitates this. There is one
1475 // instance of wxTabFrame for each tab control inside the multi-notebook.
1476 // It's important to know that wxTabFrame is not a real window, but it merely
1477 // used to capture the dimensions/positioning of the internal tab control and
1478 // it's managed page windows
1480 class wxTabFrame
: public wxWindow
1487 m_rect
= wxRect(0,0,200,200);
1488 m_tab_ctrl_height
= 20;
1491 void SetTabCtrlHeight(int h
)
1493 m_tab_ctrl_height
= h
;
1496 void DoSetSize(int x
, int y
,
1497 int width
, int height
,
1498 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1500 m_rect
= wxRect(x
, y
, width
, height
);
1504 void DoGetClientSize(int* x
, int* y
) const
1510 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1517 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1518 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1519 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1520 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1524 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1525 size_t i
, page_count
= pages
.GetCount();
1527 for (i
= 0; i
< page_count
; ++i
)
1529 wxAuiNotebookPage
& page
= pages
.Item(i
);
1530 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
,
1531 m_rect
.width
, m_rect
.height
-tab_height
);
1533 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1535 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
1536 wnd
->ApplyMDIChildFrameRect();
1541 void DoGetSize(int* x
, int* y
) const
1544 *x
= m_rect
.GetWidth();
1546 *y
= m_rect
.GetHeight();
1558 wxAuiTabCtrl
* m_tabs
;
1559 int m_tab_ctrl_height
;
1566 // -- wxAuiNotebook class implementation --
1568 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
1569 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1570 //EVT_SIZE(wxAuiNotebook::OnSize)
1571 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1572 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
1573 EVT_COMMAND_RANGE(10000, 10100,
1574 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1575 wxAuiNotebook::OnTabClicked
)
1576 EVT_COMMAND_RANGE(10000, 10100,
1577 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1578 wxAuiNotebook::OnTabBeginDrag
)
1579 EVT_COMMAND_RANGE(10000, 10100,
1580 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1581 wxAuiNotebook::OnTabEndDrag
)
1582 EVT_COMMAND_RANGE(10000, 10100,
1583 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1584 wxAuiNotebook::OnTabDragMotion
)
1585 EVT_COMMAND_RANGE(10000, 10100,
1586 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1587 wxAuiNotebook::OnTabButton
)
1590 wxAuiNotebook::wxAuiNotebook()
1593 m_tab_id_counter
= 10000;
1595 m_tab_ctrl_height
= 20;
1598 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
1602 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1604 InitNotebook(style
);
1607 bool wxAuiNotebook::Create(wxWindow
* parent
,
1613 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1616 InitNotebook(style
);
1621 // InitNotebook() contains common initialization
1622 // code called by all constructors
1623 void wxAuiNotebook::InitNotebook(long style
)
1626 m_tab_id_counter
= 10000;
1628 m_tab_ctrl_height
= 20;
1629 m_flags
= (unsigned int)style
;
1631 m_normal_font
= *wxNORMAL_FONT
;
1632 m_selected_font
= *wxNORMAL_FONT
;
1633 m_selected_font
.SetWeight(wxBOLD
);
1635 // choose a default for the tab height
1636 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1638 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1639 m_dummy_wnd
->SetSize(200, 200);
1640 m_dummy_wnd
->Show(false);
1642 m_mgr
.SetManagedWindow(this);
1644 m_mgr
.AddPane(m_dummy_wnd
,
1645 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1650 wxAuiNotebook::~wxAuiNotebook()
1655 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
1657 m_tabs
.SetArtProvider(art
);
1660 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
1662 return m_tabs
.GetArtProvider();
1665 void wxAuiNotebook::SetWindowStyleFlag(long style
)
1667 wxControl::SetWindowStyleFlag(style
);
1669 m_flags
= (unsigned int)style
;
1671 // if the control is already initialized
1672 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
1674 // let all of the tab children know about the new style
1676 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1677 size_t i
, pane_count
= all_panes
.GetCount();
1678 for (i
= 0; i
< pane_count
; ++i
)
1680 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1681 if (pane
.name
== wxT("dummy"))
1683 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1684 tabctrl
->SetFlags(m_flags
);
1692 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1693 const wxString
& caption
,
1695 const wxBitmap
& bitmap
)
1697 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1700 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1702 const wxString
& caption
,
1704 const wxBitmap
& bitmap
)
1706 wxAuiNotebookPage info
;
1708 info
.caption
= caption
;
1709 info
.bitmap
= bitmap
;
1710 info
.active
= false;
1712 // if there are currently no tabs, the first added
1713 // tab must be active
1714 if (m_tabs
.GetPageCount() == 0)
1717 m_tabs
.InsertPage(page
, info
, page_idx
);
1719 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1720 if (page_idx
>= active_tabctrl
->GetPageCount())
1721 active_tabctrl
->AddPage(page
, info
);
1723 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1726 active_tabctrl
->DoShowHide();
1730 int idx
= m_tabs
.GetIdxFromWindow(page
);
1731 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1740 // DeletePage() removes a tab from the multi-notebook,
1741 // and destroys the window as well
1742 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1744 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1745 wxWindow
* new_active
= NULL
;
1747 // find out which onscreen tab ctrl owns this tab
1750 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1753 // find a new page and set it as active
1754 int new_idx
= ctrl_idx
+1;
1755 if (new_idx
>= (int)ctrl
->GetPageCount())
1756 new_idx
= ctrl_idx
-1;
1758 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1760 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1764 // set the active page to the first page that
1765 // isn't the one being deleted
1766 size_t i
, page_count
= m_tabs
.GetPageCount();
1767 for (i
= 0; i
< page_count
; ++i
)
1769 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1772 new_active
= m_tabs
.GetWindowFromIdx(i
);
1778 // remove the tab from main catalog
1779 if (!m_tabs
.RemovePage(wnd
))
1782 // remove the tab from the onscreen tab ctrl
1783 ctrl
->RemovePage(wnd
);
1785 // actually destroy the window now
1786 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1788 // delete the child frame with pending delete, as is
1789 // customary with frame windows
1790 if (!wxPendingDelete
.Member(wnd
))
1791 wxPendingDelete
.Append(wnd
);
1798 RemoveEmptyTabFrames();
1800 // set new active pane
1804 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1812 // RemovePage() removes a tab from the multi-notebook,
1813 // but does not destroy the window
1814 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1816 // remove the tab from our own catalog
1817 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1818 if (!m_tabs
.RemovePage(wnd
))
1821 // remove the tab from the onscreen tab ctrl
1824 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1826 ctrl
->RemovePage(wnd
);
1833 // SetPageText() changes the tab caption of the specified page
1834 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1836 if (page_idx
>= m_tabs
.GetPageCount())
1839 // update our own tab catalog
1840 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1841 page_info
.caption
= text
;
1843 // update what's on screen
1846 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1848 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1849 info
.caption
= text
;
1857 // GetSelection() returns the index of the currently active page
1858 int wxAuiNotebook::GetSelection() const
1863 // SetSelection() sets the currently active page
1864 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1866 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1870 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1871 evt
.SetSelection(new_page
);
1872 evt
.SetOldSelection(m_curpage
);
1873 evt
.SetEventObject(this);
1874 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1876 // program allows the page change
1877 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1878 (void)GetEventHandler()->ProcessEvent(evt
);
1884 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1886 m_tabs
.SetActivePage(wnd
);
1888 ctrl
->SetActivePage(ctrl_idx
);
1892 int old_curpage
= m_curpage
;
1893 m_curpage
= new_page
;
1897 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1898 size_t i
, pane_count
= all_panes
.GetCount();
1899 for (i
= 0; i
< pane_count
; ++i
)
1901 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1902 if (pane
.name
== wxT("dummy"))
1904 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1905 if (tabctrl
!= ctrl
)
1906 tabctrl
->SetSelectedFont(m_normal_font
);
1908 tabctrl
->SetSelectedFont(m_selected_font
);
1921 // GetPageCount() returns the total number of
1922 // pages managed by the multi-notebook
1923 size_t wxAuiNotebook::GetPageCount() const
1925 return m_tabs
.GetPageCount();
1928 // GetPage() returns the wxWindow pointer of the
1930 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1932 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1934 return m_tabs
.GetWindowFromIdx(page_idx
);
1937 // DoSizing() performs all sizing operations in each tab control
1938 void wxAuiNotebook::DoSizing()
1940 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1941 size_t i
, pane_count
= all_panes
.GetCount();
1942 for (i
= 0; i
< pane_count
; ++i
)
1944 if (all_panes
.Item(i
).name
== wxT("dummy"))
1947 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1948 tabframe
->DoSizing();
1952 // GetActiveTabCtrl() returns the active tab control. It is
1953 // called to determine which control gets new windows being added
1954 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1956 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1961 // find the tab ctrl with the current page
1962 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1969 // no current page, just find the first tab ctrl
1970 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1971 size_t i
, pane_count
= all_panes
.GetCount();
1972 for (i
= 0; i
< pane_count
; ++i
)
1974 if (all_panes
.Item(i
).name
== wxT("dummy"))
1977 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1978 return tabframe
->m_tabs
;
1981 // If there is no tabframe at all, create one
1982 wxTabFrame
* tabframe
= new wxTabFrame
;
1983 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1984 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1989 tabframe
->m_tabs
->SetFlags(m_flags
);
1990 m_mgr
.AddPane(tabframe
,
1991 wxAuiPaneInfo().Center().CaptionVisible(false));
1995 return tabframe
->m_tabs
;
1998 // FindTab() finds the tab control that currently contains the window as well
1999 // as the index of the window in the tab control. It returns true if the
2000 // window was found, otherwise false.
2001 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2003 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2004 size_t i
, pane_count
= all_panes
.GetCount();
2005 for (i
= 0; i
< pane_count
; ++i
)
2007 if (all_panes
.Item(i
).name
== wxT("dummy"))
2010 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2012 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2015 *ctrl
= tabframe
->m_tabs
;
2025 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2029 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2033 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2035 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2037 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2038 wxASSERT(ctrl
!= NULL
);
2040 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2041 wxASSERT(wnd
!= NULL
);
2043 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2044 wxASSERT(idx
!= -1);
2049 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2054 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2056 wxPoint screen_pt
= ::wxGetMousePosition();
2057 wxPoint client_pt
= ScreenToClient(screen_pt
);
2060 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2062 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2063 if (dest_tabs
== src_tabs
)
2067 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2070 // always hide the hint for inner-tabctrl drag
2073 // if tab moving is not allowed, leave
2074 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2079 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2080 wxWindow
* dest_location_tab
;
2082 // this is an inner-tab drag/reposition
2083 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2085 int src_idx
= evt
.GetSelection();
2086 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2088 // prevent jumpy drag
2089 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2090 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2091 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2093 m_last_drag_x
= pt
.x
;
2098 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2099 dest_tabs
->MovePage(src_tab
, dest_idx
);
2100 dest_tabs
->SetActivePage((size_t)dest_idx
);
2101 dest_tabs
->DoShowHide();
2102 dest_tabs
->Refresh();
2103 m_last_drag_x
= pt
.x
;
2111 // if tab moving is not allowed, leave
2112 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2120 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2126 wxRect hint_rect
= dest_tabs
->GetRect();
2127 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2128 m_mgr
.ShowHint(hint_rect
);
2132 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2138 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2140 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2144 // if tab moving is not allowed, leave
2145 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2150 // set cursor back to an arrow
2151 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2154 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2157 // get the mouse position, which will be used to determine the drop point
2158 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2159 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2162 // the src tab control is the control that fired this event
2163 wxAuiTabCtrl
* dest_tabs
= NULL
;
2166 // If the pointer is in an existing tab frame, do a tab insert
2167 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2168 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2169 int insert_idx
= -1;
2172 dest_tabs
= tab_frame
->m_tabs
;
2174 if (dest_tabs
== src_tabs
)
2178 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2179 wxWindow
* target
= NULL
;
2180 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2183 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2188 // If there is no tabframe at all, create one
2189 wxTabFrame
* new_tabs
= new wxTabFrame
;
2190 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2191 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2196 new_tabs
->m_tabs
->SetFlags(m_flags
);
2198 m_mgr
.AddPane(new_tabs
,
2199 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2202 dest_tabs
= new_tabs
->m_tabs
;
2207 // remove the page from the source tabs
2208 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2209 page_info
.active
= false;
2210 src_tabs
->RemovePage(page_info
.window
);
2211 if (src_tabs
->GetPageCount() > 0)
2213 src_tabs
->SetActivePage((size_t)0);
2214 src_tabs
->DoShowHide();
2215 src_tabs
->Refresh();
2220 // add the page to the destination tabs
2221 if (insert_idx
== -1)
2222 insert_idx
= dest_tabs
->GetPageCount();
2223 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2225 if (src_tabs
->GetPageCount() == 0)
2227 RemoveEmptyTabFrames();
2231 dest_tabs
->DoShowHide();
2232 dest_tabs
->Refresh();
2234 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2239 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2241 // if we've just removed the last tab from the source
2242 // tab set, the remove the tab control completely
2243 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2244 size_t i
, pane_count
= all_panes
.GetCount();
2245 for (i
= 0; i
< pane_count
; ++i
)
2247 if (all_panes
.Item(i
).name
== wxT("dummy"))
2250 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2251 if (tabframe
->m_tab_rect
.Contains(pt
))
2252 return tabframe
->m_tabs
;
2258 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2260 // if we've just removed the last tab from the source
2261 // tab set, the remove the tab control completely
2262 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2263 size_t i
, pane_count
= all_panes
.GetCount();
2264 for (i
= 0; i
< pane_count
; ++i
)
2266 if (all_panes
.Item(i
).name
== wxT("dummy"))
2269 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2270 if (tabframe
->m_tabs
== tab_ctrl
)
2279 void wxAuiNotebook::RemoveEmptyTabFrames()
2281 // if we've just removed the last tab from the source
2282 // tab set, the remove the tab control completely
2283 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2284 size_t i
, pane_count
= all_panes
.GetCount();
2285 for (i
= 0; i
< pane_count
; ++i
)
2287 if (all_panes
.Item(i
).name
== wxT("dummy"))
2290 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2291 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2293 m_mgr
.DetachPane(tab_frame
);
2295 // use pending delete because sometimes during
2296 // window closing, refreshs are pending
2297 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2298 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2299 //tab_frame->m_tabs->Destroy();
2306 // check to see if there is still a center pane;
2307 // if there isn't, make a frame the center pane
2308 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2309 pane_count
= panes
.GetCount();
2310 wxWindow
* first_good
= NULL
;
2311 bool center_found
= false;
2312 for (i
= 0; i
< pane_count
; ++i
)
2314 if (panes
.Item(i
).name
== wxT("dummy"))
2316 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2317 center_found
= true;
2319 first_good
= panes
.Item(i
).window
;
2322 if (!center_found
&& first_good
)
2324 m_mgr
.GetPane(first_good
).Centre();
2330 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2332 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2333 if (idx
!= -1 && idx
!= m_curpage
)
2340 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2342 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2343 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2345 int button_id
= evt
.GetInt();
2347 if (button_id
== wxAUI_BUTTON_CLOSE
)
2349 int selection
= tabs
->GetActivePage();
2351 if (selection
!= -1)
2353 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2355 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2361 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2362 DeletePage(main_idx
);