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
)
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 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
156 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
158 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
159 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
161 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
162 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
165 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
169 void wxAuiDefaultTabArt::DrawBackground(wxDC
* dc
,
173 dc
->SetBrush(m_bkbrush
);
174 dc
->SetPen(*wxTRANSPARENT_PEN
);
175 dc
->DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
178 dc
->SetPen(*wxGREY_PEN
);
179 dc
->DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
183 // DrawTab() draws an individual tab.
186 // in_rect - rectangle the tab should be confined to
187 // caption - tab's caption
188 // active - whether or not the tab is active
189 // out_rect - actual output rectangle
190 // x_extent - the advance x; where the next tab should start
192 void wxAuiDefaultTabArt::DrawTab(wxDC
* dc
,
193 const wxRect
& in_rect
,
194 const wxString
& caption_text
,
196 int close_button_state
,
197 wxRect
* out_tab_rect
,
198 wxRect
* out_button_rect
,
201 wxCoord normal_textx
, normal_texty
;
202 wxCoord selected_textx
, selected_texty
;
203 wxCoord textx
, texty
;
205 // if the caption is empty, measure some temporary text
206 wxString caption
= caption_text
;
207 if (caption_text
.empty())
210 dc
->SetFont(m_selected_font
);
211 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
213 dc
->SetFont(m_normal_font
);
214 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
216 // figure out the size of the tab
217 wxSize tab_size
= GetTabSize(dc
, caption
, active
, close_button_state
, x_extent
);
219 wxCoord tab_height
= tab_size
.y
;
220 wxCoord tab_width
= tab_size
.x
;
221 wxCoord tab_x
= in_rect
.x
;
222 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
224 // select pen, brush and font for the tab to be drawn
228 dc
->SetPen(m_selected_bkpen
);
229 dc
->SetBrush(m_selected_bkbrush
);
230 dc
->SetFont(m_selected_font
);
231 textx
= selected_textx
;
232 texty
= selected_texty
;
236 dc
->SetPen(m_normal_bkpen
);
237 dc
->SetBrush(m_normal_bkbrush
);
238 dc
->SetFont(m_normal_font
);
239 textx
= normal_textx
;
240 texty
= normal_texty
;
248 points
[0].y
= tab_y
+ tab_height
- 1;
249 points
[1].x
= tab_x
+ tab_height
- 3;
250 points
[1].y
= tab_y
+ 2;
251 points
[2].x
= tab_x
+ tab_height
+ 3;
253 points
[3].x
= tab_x
+ tab_width
- 2;
255 points
[4].x
= tab_x
+ tab_width
;
256 points
[4].y
= tab_y
+ 2;
257 points
[5].x
= tab_x
+ tab_width
;
258 points
[5].y
= tab_y
+ tab_height
- 1;
259 points
[6] = points
[0];
262 dc
->DrawPolygon(6, points
);
264 dc
->SetPen(*wxGREY_PEN
);
266 //dc->DrawLines(active ? 6 : 7, points);
267 dc
->DrawLines(7, points
);
272 int close_button_width
= 0;
273 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
275 close_button_width
= m_active_close_bmp
.GetWidth();
276 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
280 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
285 dc
->DrawText(caption
,
287 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
290 // draw close button if necessary
291 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
295 bmp
= m_active_close_bmp
;
297 bmp
= m_disabled_close_bmp
;
299 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
300 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
303 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
305 *out_button_rect
= rect
;
309 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
313 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
* dc
,
314 const wxString
& caption
,
315 bool WXUNUSED(active
),
316 int close_button_state
,
319 wxCoord measured_textx
, measured_texty
;
321 dc
->SetFont(m_measuring_font
);
322 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
324 wxCoord tab_height
= measured_texty
+ 4;
325 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
327 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
328 tab_width
+= m_active_close_bmp
.GetWidth();
330 *x_extent
= tab_width
- (tab_height
/2) - 1;
332 return wxSize(tab_width
, tab_height
);
336 void wxAuiDefaultTabArt::DrawButton(
338 const wxRect
& in_rect
,
342 const wxBitmap
& bitmap_override
,
348 if (bitmap_override
.IsOk())
350 bmp
= bitmap_override
;
356 case wxAUI_BUTTON_CLOSE
:
357 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
358 bmp
= m_disabled_close_bmp
;
360 bmp
= m_active_close_bmp
;
362 case wxAUI_BUTTON_LEFT
:
363 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
364 bmp
= m_disabled_left_bmp
;
366 bmp
= m_active_left_bmp
;
368 case wxAUI_BUTTON_RIGHT
:
369 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
370 bmp
= m_disabled_right_bmp
;
372 bmp
= m_active_right_bmp
;
382 if (orientation
== wxLEFT
)
384 rect
.SetX(in_rect
.x
);
385 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
386 rect
.SetWidth(bmp
.GetWidth());
387 rect
.SetHeight(bmp
.GetHeight());
391 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
392 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
393 bmp
.GetWidth(), bmp
.GetHeight());
397 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
404 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
407 dc
.SetFont(m_measuring_font
);
409 wxSize s
= GetTabSize(&dc
, wxT("ABCDEFGHIj"), true, wxAUI_BUTTON_STATE_HIDDEN
, &x_ext
);
413 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
415 m_normal_font
= font
;
418 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
420 m_selected_font
= font
;
423 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
425 m_measuring_font
= font
;
433 // -- wxAuiTabContainer class implementation --
436 // wxAuiTabContainer is a class which contains information about each
437 // tab. It also can render an entire tab control to a specified DC.
438 // It's not a window class itself, because this code will be used by
439 // the wxFrameMananger, where it is disadvantageous to have separate
440 // windows for each tab control in the case of "docked tabs"
442 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
443 // which can be used as a tab control in the normal sense.
446 wxAuiTabContainer::wxAuiTabContainer()
450 m_art
= new wxAuiDefaultTabArt
;
452 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
453 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
454 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
457 wxAuiTabContainer::~wxAuiTabContainer()
462 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
468 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
473 void wxAuiTabContainer::SetFlags(unsigned int flags
)
477 // check for new close button settings
478 RemoveButton(wxAUI_BUTTON_CLOSE
);
479 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
481 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
485 unsigned int wxAuiTabContainer::GetFlags() const
491 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
493 m_art
->SetNormalFont(font
);
496 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
498 m_art
->SetSelectedFont(font
);
501 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
503 m_art
->SetMeasuringFont(font
);
506 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
511 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
512 const wxAuiNotebookPage
& info
)
514 wxAuiNotebookPage page_info
;
516 page_info
.window
= page
;
518 m_pages
.Add(page_info
);
523 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
524 const wxAuiNotebookPage
& info
,
527 wxAuiNotebookPage page_info
;
529 page_info
.window
= page
;
531 if (idx
>= m_pages
.GetCount())
532 m_pages
.Add(page_info
);
534 m_pages
.Insert(page_info
, idx
);
539 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
542 int idx
= GetIdxFromWindow(page
);
546 // get page entry, make a copy of it
547 wxAuiNotebookPage p
= GetPage(idx
);
549 // remove old page entry
552 // insert page where it should be
553 InsertPage(page
, p
, new_idx
);
558 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
560 size_t i
, page_count
= m_pages
.GetCount();
561 for (i
= 0; i
< page_count
; ++i
)
563 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
564 if (page
.window
== wnd
)
574 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
578 size_t i
, page_count
= m_pages
.GetCount();
579 for (i
= 0; i
< page_count
; ++i
)
581 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
582 if (page
.window
== wnd
)
596 void wxAuiTabContainer::SetNoneActive()
598 size_t i
, page_count
= m_pages
.GetCount();
599 for (i
= 0; i
< page_count
; ++i
)
601 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
606 bool wxAuiTabContainer::SetActivePage(size_t page
)
608 if (page
>= m_pages
.GetCount())
611 return SetActivePage(m_pages
.Item(page
).window
);
614 int wxAuiTabContainer::GetActivePage() const
616 size_t i
, page_count
= m_pages
.GetCount();
617 for (i
= 0; i
< page_count
; ++i
)
619 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
627 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
629 if (idx
>= m_pages
.GetCount())
632 return m_pages
[idx
].window
;
635 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
637 size_t i
, page_count
= m_pages
.GetCount();
638 for (i
= 0; i
< page_count
; ++i
)
640 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
641 if (page
.window
== wnd
)
647 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
649 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
654 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
659 size_t wxAuiTabContainer::GetPageCount() const
661 return m_pages
.GetCount();
664 void wxAuiTabContainer::AddButton(int id
,
666 const wxBitmap
& normal_bitmap
,
667 const wxBitmap
& disabled_bitmap
)
669 wxAuiTabContainerButton button
;
671 button
.bitmap
= normal_bitmap
;
672 button
.dis_bitmap
= disabled_bitmap
;
673 button
.location
= location
;
674 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
676 m_buttons
.Add(button
);
679 void wxAuiTabContainer::RemoveButton(int id
)
681 size_t i
, button_count
= m_buttons
.GetCount();
683 for (i
= 0; i
< button_count
; ++i
)
685 if (m_buttons
.Item(i
).id
== id
)
687 m_buttons
.RemoveAt(i
);
695 size_t wxAuiTabContainer::GetTabOffset() const
700 void wxAuiTabContainer::SetTabOffset(size_t offset
)
702 m_tab_offset
= offset
;
705 // Render() renders the tab catalog to the specified DC
706 // It is a virtual function and can be overridden to
707 // provide custom drawing capabilities
708 void wxAuiTabContainer::Render(wxDC
* raw_dc
)
713 size_t page_count
= m_pages
.GetCount();
714 size_t button_count
= m_buttons
.GetCount();
716 // create off-screen bitmap
717 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
718 dc
.SelectObject(bmp
);
721 // find out if size of tabs is larger than can be
722 // afforded on screen
724 int visible_width
= 0;
725 for (i
= 0; i
< page_count
; ++i
)
727 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
729 // determine if a close button is on this tab
730 bool close_button
= false;
731 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
732 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
739 wxSize size
= m_art
->GetTabSize(&dc
,
743 wxAUI_BUTTON_STATE_NORMAL
:
744 wxAUI_BUTTON_STATE_HIDDEN
,
747 if (i
+1 < page_count
)
748 total_width
+= x_extent
;
750 total_width
+= size
.x
;
752 if (i
>= m_tab_offset
)
754 if (i
+1 < page_count
)
755 visible_width
+= x_extent
;
757 visible_width
+= size
.x
;
761 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
763 // show left/right buttons
764 for (i
= 0; i
< button_count
; ++i
)
766 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
767 if (button
.id
== wxAUI_BUTTON_LEFT
||
768 button
.id
== wxAUI_BUTTON_RIGHT
)
770 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
776 // hide left/right buttons
777 for (i
= 0; i
< button_count
; ++i
)
779 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
780 if (button
.id
== wxAUI_BUTTON_LEFT
||
781 button
.id
== wxAUI_BUTTON_RIGHT
)
783 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
788 // determine whether left button should be enabled
789 for (i
= 0; i
< button_count
; ++i
)
791 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
792 if (button
.id
== wxAUI_BUTTON_LEFT
)
794 if (m_tab_offset
== 0)
795 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
797 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
799 if (button
.id
== wxAUI_BUTTON_RIGHT
)
801 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
802 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
804 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
811 m_art
->DrawBackground(&dc
, m_rect
);
814 int left_buttons_width
= 0;
815 int right_buttons_width
= 0;
819 // draw the buttons on the right side
820 offset
= m_rect
.x
+ m_rect
.width
;
821 for (i
= 0; i
< button_count
; ++i
)
823 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
825 if (button
.location
!= wxRIGHT
)
827 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
830 wxRect button_rect
= m_rect
;
832 button_rect
.SetWidth(offset
);
834 m_art
->DrawButton(&dc
,
842 offset
-= button
.rect
.GetWidth();
843 right_buttons_width
+= button
.rect
.GetWidth();
850 // draw the buttons on the left side
852 for (i
= 0; i
< button_count
; ++i
)
854 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
856 if (button
.location
!= wxLEFT
)
858 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
861 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
863 m_art
->DrawButton(&dc
,
871 offset
+= button
.rect
.GetWidth();
872 left_buttons_width
+= button
.rect
.GetWidth();
875 offset
= left_buttons_width
;
877 // set a clipping region to the tabs don't draw over the buttons
878 dc
.SetClippingRegion(left_buttons_width
, 0,
879 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
884 // prepare the tab-close-button array
885 while (m_tab_close_buttons
.GetCount() < page_count
)
887 wxAuiTabContainerButton tempbtn
;
888 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
889 tempbtn
.location
= wxCENTER
;
890 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
891 m_tab_close_buttons
.Add(tempbtn
);
894 for (i
= 0; i
< m_tab_offset
; ++i
)
896 // buttons before the tab offset must be set to hidden
897 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
904 int active_offset
= 0;
907 wxRect rect
= m_rect
;
910 rect
.height
= m_rect
.height
;
912 for (i
= m_tab_offset
; i
< page_count
; ++i
)
914 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
915 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
917 // determine if a close button is on this tab
918 bool close_button
= false;
919 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
920 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
923 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
925 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
926 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
927 tab_button
.location
= wxCENTER
;
932 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
941 tab_button
.cur_state
,
949 active_offset
= offset
;
955 // draw the active tab again so it stands in the foreground
956 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
958 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
960 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
962 // determine if a close button is on this tab
963 bool close_button
= false;
964 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
965 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
970 rect
.x
= active_offset
;
975 tab_button
.cur_state
,
981 dc
.DestroyClippingRegion();
983 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
984 m_rect
.GetWidth(), m_rect
.GetHeight(),
989 // TabHitTest() tests if a tab was hit, passing the window pointer
990 // back if that condition was fulfilled. The function returns
991 // true if a tab was hit, otherwise false
992 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
994 if (!m_rect
.Contains(x
,y
))
997 wxAuiTabContainerButton
* btn
= NULL
;
998 if (ButtonHitTest(x
, y
, &btn
))
1000 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1004 size_t i
, page_count
= m_pages
.GetCount();
1006 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1008 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1009 if (page
.rect
.Contains(x
,y
))
1020 // ButtonHitTest() tests if a button was hit. The function returns
1021 // true if a button was hit, otherwise false
1022 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1023 wxAuiTabContainerButton
** hit
) const
1025 if (!m_rect
.Contains(x
,y
))
1028 size_t i
, button_count
;
1031 button_count
= m_buttons
.GetCount();
1032 for (i
= 0; i
< button_count
; ++i
)
1034 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1035 if (button
.rect
.Contains(x
,y
))
1043 button_count
= m_tab_close_buttons
.GetCount();
1044 for (i
= 0; i
< button_count
; ++i
)
1046 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1047 if (button
.rect
.Contains(x
,y
))
1060 // the utility function ShowWnd() is the same as show,
1061 // except it handles wxAuiMDIChildFrame windows as well,
1062 // as the Show() method on this class is "unplugged"
1063 static void ShowWnd(wxWindow
* wnd
, bool show
)
1065 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1067 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1077 // DoShowHide() this function shows the active window, then
1078 // hides all of the other windows (in that order)
1079 void wxAuiTabContainer::DoShowHide()
1081 wxAuiNotebookPageArray
& pages
= GetPages();
1082 size_t i
, page_count
= pages
.GetCount();
1084 // show new active page first
1085 for (i
= 0; i
< page_count
; ++i
)
1087 wxAuiNotebookPage
& page
= pages
.Item(i
);
1090 ShowWnd(page
.window
, true);
1095 // hide all other pages
1096 for (i
= 0; i
< page_count
; ++i
)
1098 wxAuiNotebookPage
& page
= pages
.Item(i
);
1099 ShowWnd(page
.window
, page
.active
);
1108 // -- wxAuiTabCtrl class implementation --
1112 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1113 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1114 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1115 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1116 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1117 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1118 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1119 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1120 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1124 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1128 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1130 m_click_pt
= wxDefaultPosition
;
1131 m_is_dragging
= false;
1132 m_hover_button
= NULL
;
1135 wxAuiTabCtrl::~wxAuiTabCtrl()
1139 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1143 dc
.SetFont(GetFont());
1145 if (GetPageCount() > 0)
1149 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1153 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1155 wxSize s
= evt
.GetSize();
1156 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1160 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1163 m_click_pt
= wxDefaultPosition
;
1164 m_is_dragging
= false;
1168 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1170 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1171 e
.SetSelection(GetIdxFromWindow(wnd
));
1172 e
.SetOldSelection(GetActivePage());
1173 e
.SetEventObject(this);
1174 GetEventHandler()->ProcessEvent(e
);
1176 m_click_pt
.x
= evt
.m_x
;
1177 m_click_pt
.y
= evt
.m_y
;
1183 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1189 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1191 if (GetCapture() == this)
1196 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1197 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1198 evt
.SetOldSelection(evt
.GetSelection());
1199 evt
.SetEventObject(this);
1200 GetEventHandler()->ProcessEvent(evt
);
1206 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1210 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1212 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1213 evt
.SetInt(m_hover_button
->id
);
1214 evt
.SetEventObject(this);
1215 GetEventHandler()->ProcessEvent(evt
);
1219 m_click_pt
= wxDefaultPosition
;
1220 m_is_dragging
= false;
1224 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1226 wxPoint pos
= evt
.GetPosition();
1228 // check if the mouse is hovering above a button
1229 wxAuiTabContainerButton
* button
;
1230 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1232 if (m_hover_button
&& button
!= m_hover_button
)
1234 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1235 m_hover_button
= NULL
;
1240 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1242 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1245 m_hover_button
= button
;
1253 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1254 m_hover_button
= NULL
;
1261 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1266 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1267 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1268 evt
.SetOldSelection(evt
.GetSelection());
1269 evt
.SetEventObject(this);
1270 GetEventHandler()->ProcessEvent(evt
);
1275 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1276 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1278 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1279 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1281 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1282 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1283 evt
.SetOldSelection(evt
.GetSelection());
1284 evt
.SetEventObject(this);
1285 GetEventHandler()->ProcessEvent(evt
);
1287 m_is_dragging
= true;
1291 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1295 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1296 m_hover_button
= NULL
;
1302 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1304 int button
= event
.GetInt();
1306 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1308 if (button
== wxAUI_BUTTON_LEFT
)
1310 if (GetTabOffset() > 0)
1312 SetTabOffset(GetTabOffset()-1);
1319 SetTabOffset(GetTabOffset()+1);
1330 // wxTabFrame is an interesting case. It's important that all child pages
1331 // of the multi-notebook control are all actually children of that control
1332 // (and not grandchildren). wxTabFrame facilitates this. There is one
1333 // instance of wxTabFrame for each tab control inside the multi-notebook.
1334 // It's important to know that wxTabFrame is not a real window, but it merely
1335 // used to capture the dimensions/positioning of the internal tab control and
1336 // it's managed page windows
1338 class wxTabFrame
: public wxWindow
1345 m_rect
= wxRect(0,0,200,200);
1346 m_tab_ctrl_height
= 20;
1349 void SetTabCtrlHeight(int h
)
1351 m_tab_ctrl_height
= h
;
1354 void DoSetSize(int x
, int y
,
1355 int width
, int height
,
1356 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1358 m_rect
= wxRect(x
, y
, width
, height
);
1362 void DoGetClientSize(int* x
, int* y
) const
1368 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1375 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1376 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1377 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1378 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1382 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1383 size_t i
, page_count
= pages
.GetCount();
1385 for (i
= 0; i
< page_count
; ++i
)
1387 wxAuiNotebookPage
& page
= pages
.Item(i
);
1388 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
, m_rect
.width
, m_rect
.height
-tab_height
);
1390 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1392 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
1393 wnd
->ApplyMDIChildFrameRect();
1398 void DoGetSize(int* x
, int* y
) const
1401 *x
= m_rect
.GetWidth();
1403 *y
= m_rect
.GetHeight();
1415 wxAuiTabCtrl
* m_tabs
;
1416 int m_tab_ctrl_height
;
1423 // -- wxAuiNotebook class implementation --
1425 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
1426 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1427 //EVT_SIZE(wxAuiNotebook::OnSize)
1428 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1429 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
1430 EVT_COMMAND_RANGE(10000, 10100,
1431 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1432 wxAuiNotebook::OnTabClicked
)
1433 EVT_COMMAND_RANGE(10000, 10100,
1434 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1435 wxAuiNotebook::OnTabBeginDrag
)
1436 EVT_COMMAND_RANGE(10000, 10100,
1437 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1438 wxAuiNotebook::OnTabEndDrag
)
1439 EVT_COMMAND_RANGE(10000, 10100,
1440 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1441 wxAuiNotebook::OnTabDragMotion
)
1442 EVT_COMMAND_RANGE(10000, 10100,
1443 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1444 wxAuiNotebook::OnTabButton
)
1447 wxAuiNotebook::wxAuiNotebook()
1450 m_tab_id_counter
= 10000;
1452 m_tab_ctrl_height
= 20;
1455 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
1459 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1461 InitNotebook(style
);
1464 bool wxAuiNotebook::Create(wxWindow
* parent
,
1470 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1473 InitNotebook(style
);
1478 // InitNotebook() contains common initialization
1479 // code called by all constructors
1480 void wxAuiNotebook::InitNotebook(long style
)
1483 m_tab_id_counter
= 10000;
1485 m_tab_ctrl_height
= 20;
1486 m_flags
= (unsigned int)style
;
1488 m_normal_font
= *wxNORMAL_FONT
;
1489 m_selected_font
= *wxNORMAL_FONT
;
1490 m_selected_font
.SetWeight(wxBOLD
);
1492 // choose a default for the tab height
1493 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1495 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1496 m_dummy_wnd
->SetSize(200, 200);
1497 m_dummy_wnd
->Show(false);
1499 m_mgr
.SetManagedWindow(this);
1501 m_mgr
.AddPane(m_dummy_wnd
,
1502 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1507 wxAuiNotebook::~wxAuiNotebook()
1512 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
1514 m_tabs
.SetArtProvider(art
);
1517 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
1519 return m_tabs
.GetArtProvider();
1522 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1523 const wxString
& caption
,
1525 const wxBitmap
& bitmap
)
1527 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1530 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1532 const wxString
& caption
,
1534 const wxBitmap
& bitmap
)
1536 wxAuiNotebookPage info
;
1538 info
.caption
= caption
;
1539 info
.bitmap
= bitmap
;
1540 info
.active
= false;
1542 // if there are currently no tabs, the first added
1543 // tab must be active
1544 if (m_tabs
.GetPageCount() == 0)
1547 m_tabs
.InsertPage(page
, info
, page_idx
);
1549 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1550 if (page_idx
>= active_tabctrl
->GetPageCount())
1551 active_tabctrl
->AddPage(page
, info
);
1553 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1556 active_tabctrl
->DoShowHide();
1560 int idx
= m_tabs
.GetIdxFromWindow(page
);
1561 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1570 // DeletePage() removes a tab from the multi-notebook,
1571 // and destroys the window as well
1572 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1574 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1575 wxWindow
* new_active
= NULL
;
1577 // find out which onscreen tab ctrl owns this tab
1580 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1583 // find a new page and set it as active
1584 int new_idx
= ctrl_idx
+1;
1585 if (new_idx
>= (int)ctrl
->GetPageCount())
1586 new_idx
= ctrl_idx
-1;
1588 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1590 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1594 // set the active page to the first page that
1595 // isn't the one being deleted
1596 size_t i
, page_count
= m_tabs
.GetPageCount();
1597 for (i
= 0; i
< page_count
; ++i
)
1599 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1602 new_active
= m_tabs
.GetWindowFromIdx(i
);
1608 // remove the tab from main catalog
1609 if (!m_tabs
.RemovePage(wnd
))
1612 // remove the tab from the onscreen tab ctrl
1613 ctrl
->RemovePage(wnd
);
1615 // actually destroy the window now
1616 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1618 // delete the child frame with pending delete, as is
1619 // customary with frame windows
1620 if (!wxPendingDelete
.Member(wnd
))
1621 wxPendingDelete
.Append(wnd
);
1628 RemoveEmptyTabFrames();
1630 // set new active pane
1634 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1642 // RemovePage() removes a tab from the multi-notebook,
1643 // but does not destroy the window
1644 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1646 // remove the tab from our own catalog
1647 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1648 if (!m_tabs
.RemovePage(wnd
))
1651 // remove the tab from the onscreen tab ctrl
1654 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1656 ctrl
->RemovePage(wnd
);
1663 // SetPageText() changes the tab caption of the specified page
1664 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1666 if (page_idx
>= m_tabs
.GetPageCount())
1669 // update our own tab catalog
1670 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1671 page_info
.caption
= text
;
1673 // update what's on screen
1676 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1678 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1679 info
.caption
= text
;
1687 // GetSelection() returns the index of the currently active page
1688 int wxAuiNotebook::GetSelection() const
1693 // SetSelection() sets the currently active page
1694 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1696 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1700 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1701 evt
.SetSelection(new_page
);
1702 evt
.SetOldSelection(m_curpage
);
1703 evt
.SetEventObject(this);
1704 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1706 // program allows the page change
1707 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1708 (void)GetEventHandler()->ProcessEvent(evt
);
1714 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1716 m_tabs
.SetActivePage(wnd
);
1718 ctrl
->SetActivePage(ctrl_idx
);
1722 int old_curpage
= m_curpage
;
1723 m_curpage
= new_page
;
1727 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1728 size_t i
, pane_count
= all_panes
.GetCount();
1729 for (i
= 0; i
< pane_count
; ++i
)
1731 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1732 if (pane
.name
== wxT("dummy"))
1734 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1735 if (tabctrl
!= ctrl
)
1736 tabctrl
->SetSelectedFont(m_normal_font
);
1738 tabctrl
->SetSelectedFont(m_selected_font
);
1751 // GetPageCount() returns the total number of
1752 // pages managed by the multi-notebook
1753 size_t wxAuiNotebook::GetPageCount() const
1755 return m_tabs
.GetPageCount();
1758 // GetPage() returns the wxWindow pointer of the
1760 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1762 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1764 return m_tabs
.GetWindowFromIdx(page_idx
);
1767 // DoSizing() performs all sizing operations in each tab control
1768 void wxAuiNotebook::DoSizing()
1770 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1771 size_t i
, pane_count
= all_panes
.GetCount();
1772 for (i
= 0; i
< pane_count
; ++i
)
1774 if (all_panes
.Item(i
).name
== wxT("dummy"))
1777 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1778 tabframe
->DoSizing();
1782 // GetActiveTabCtrl() returns the active tab control. It is
1783 // called to determine which control gets new windows being added
1784 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1786 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1791 // find the tab ctrl with the current page
1792 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1799 // no current page, just find the first tab ctrl
1800 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1801 size_t i
, pane_count
= all_panes
.GetCount();
1802 for (i
= 0; i
< pane_count
; ++i
)
1804 if (all_panes
.Item(i
).name
== wxT("dummy"))
1807 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1808 return tabframe
->m_tabs
;
1811 // If there is no tabframe at all, create one
1812 wxTabFrame
* tabframe
= new wxTabFrame
;
1813 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1814 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1819 tabframe
->m_tabs
->SetFlags(m_flags
);
1820 m_mgr
.AddPane(tabframe
,
1821 wxAuiPaneInfo().Center().CaptionVisible(false));
1825 return tabframe
->m_tabs
;
1828 // FindTab() finds the tab control that currently contains the window as well
1829 // as the index of the window in the tab control. It returns true if the
1830 // window was found, otherwise false.
1831 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1833 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1834 size_t i
, pane_count
= all_panes
.GetCount();
1835 for (i
= 0; i
< pane_count
; ++i
)
1837 if (all_panes
.Item(i
).name
== wxT("dummy"))
1840 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1842 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1845 *ctrl
= tabframe
->m_tabs
;
1855 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
1859 void wxAuiNotebook::OnSize(wxSizeEvent
&)
1863 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1865 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1867 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1868 wxASSERT(ctrl
!= NULL
);
1870 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1871 wxASSERT(wnd
!= NULL
);
1873 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1874 wxASSERT(idx
!= -1);
1879 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1884 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1886 wxPoint screen_pt
= ::wxGetMousePosition();
1887 wxPoint client_pt
= ScreenToClient(screen_pt
);
1890 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1892 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
1893 if (dest_tabs
== src_tabs
)
1895 // always hide the hint for inner-tabctrl drag
1898 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
1899 wxWindow
* dest_location_tab
;
1901 // this is an inner-tab drag/reposition
1902 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
1904 int src_idx
= evt
.GetSelection();
1905 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
1907 // prevent jumpy drag
1908 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
1909 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
1910 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
1912 m_last_drag_x
= pt
.x
;
1917 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
1918 dest_tabs
->MovePage(src_tab
, dest_idx
);
1919 dest_tabs
->SetActivePage((size_t)dest_idx
);
1920 dest_tabs
->DoShowHide();
1921 dest_tabs
->Refresh();
1922 m_last_drag_x
= pt
.x
;
1931 wxRect hint_rect
= dest_tabs
->GetRect();
1932 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1933 m_mgr
.ShowHint(hint_rect
);
1937 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1943 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1945 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1950 // get the mouse position, which will be used to determine the drop point
1951 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1952 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1955 // the src tab control is the control that fired this event
1956 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1957 wxAuiTabCtrl
* dest_tabs
= NULL
;
1960 // If the pointer is in an existing tab frame, do a tab insert
1961 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1962 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1963 int insert_idx
= -1;
1966 dest_tabs
= tab_frame
->m_tabs
;
1968 if (dest_tabs
== src_tabs
)
1972 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
1973 wxWindow
* target
= NULL
;
1974 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
1977 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
1982 // If there is no tabframe at all, create one
1983 wxTabFrame
* new_tabs
= new wxTabFrame
;
1984 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1985 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1990 new_tabs
->m_tabs
->SetFlags(m_flags
);
1992 m_mgr
.AddPane(new_tabs
,
1993 wxAuiPaneInfo().Bottom().CaptionVisible(false),
1996 dest_tabs
= new_tabs
->m_tabs
;
2001 // remove the page from the source tabs
2002 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2003 page_info
.active
= false;
2004 src_tabs
->RemovePage(page_info
.window
);
2005 if (src_tabs
->GetPageCount() > 0)
2007 src_tabs
->SetActivePage((size_t)0);
2008 src_tabs
->DoShowHide();
2009 src_tabs
->Refresh();
2014 // add the page to the destination tabs
2015 if (insert_idx
== -1)
2016 insert_idx
= dest_tabs
->GetPageCount();
2017 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2019 if (src_tabs
->GetPageCount() == 0)
2021 RemoveEmptyTabFrames();
2025 dest_tabs
->DoShowHide();
2026 dest_tabs
->Refresh();
2028 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2031 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2033 // if we've just removed the last tab from the source
2034 // tab set, the remove the tab control completely
2035 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2036 size_t i
, pane_count
= all_panes
.GetCount();
2037 for (i
= 0; i
< pane_count
; ++i
)
2039 if (all_panes
.Item(i
).name
== wxT("dummy"))
2042 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2043 if (tabframe
->m_tab_rect
.Contains(pt
))
2044 return tabframe
->m_tabs
;
2050 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2052 // if we've just removed the last tab from the source
2053 // tab set, the remove the tab control completely
2054 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2055 size_t i
, pane_count
= all_panes
.GetCount();
2056 for (i
= 0; i
< pane_count
; ++i
)
2058 if (all_panes
.Item(i
).name
== wxT("dummy"))
2061 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2062 if (tabframe
->m_tabs
== tab_ctrl
)
2071 void wxAuiNotebook::RemoveEmptyTabFrames()
2073 // if we've just removed the last tab from the source
2074 // tab set, the remove the tab control completely
2075 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2076 size_t i
, pane_count
= all_panes
.GetCount();
2077 for (i
= 0; i
< pane_count
; ++i
)
2079 if (all_panes
.Item(i
).name
== wxT("dummy"))
2082 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2083 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2085 m_mgr
.DetachPane(tab_frame
);
2087 // use pending delete because sometimes during
2088 // window closing, refreshs are pending
2089 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2090 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2091 //tab_frame->m_tabs->Destroy();
2098 // check to see if there is still a center pane;
2099 // if there isn't, make a frame the center pane
2100 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2101 pane_count
= panes
.GetCount();
2102 wxWindow
* first_good
= NULL
;
2103 bool center_found
= false;
2104 for (i
= 0; i
< pane_count
; ++i
)
2106 if (panes
.Item(i
).name
== wxT("dummy"))
2108 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2109 center_found
= true;
2111 first_good
= panes
.Item(i
).window
;
2114 if (!center_found
&& first_good
)
2116 m_mgr
.GetPane(first_good
).Centre();
2122 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2124 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2125 if (idx
!= -1 && idx
!= m_curpage
)
2132 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2134 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2135 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2137 int button_id
= evt
.GetInt();
2139 if (button_id
== wxAUI_BUTTON_CLOSE
)
2141 int selection
= tabs
->GetActivePage();
2143 if (selection
!= -1)
2145 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2147 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2153 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2154 DeletePage(main_idx
);