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, tab_y
+ 1,
300 close_button_width
, tab_height
- 1);
301 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
303 *out_button_rect
= rect
;
307 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
311 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
* dc
,
312 const wxString
& caption
,
313 bool WXUNUSED(active
),
314 int close_button_state
,
317 wxCoord measured_textx
, measured_texty
;
319 dc
->SetFont(m_measuring_font
);
320 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
322 wxCoord tab_height
= measured_texty
+ 4;
323 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
325 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
326 tab_width
+= m_active_close_bmp
.GetWidth();
328 *x_extent
= tab_width
- (tab_height
/2) - 1;
330 return wxSize(tab_width
, tab_height
);
334 void wxAuiDefaultTabArt::DrawButton(
336 const wxRect
& in_rect
,
340 const wxBitmap
& bitmap_override
,
346 if (bitmap_override
.IsOk())
348 bmp
= bitmap_override
;
354 case wxAUI_BUTTON_CLOSE
:
355 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
356 bmp
= m_disabled_close_bmp
;
358 bmp
= m_active_close_bmp
;
360 case wxAUI_BUTTON_LEFT
:
361 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
362 bmp
= m_disabled_left_bmp
;
364 bmp
= m_active_left_bmp
;
366 case wxAUI_BUTTON_RIGHT
:
367 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
368 bmp
= m_disabled_right_bmp
;
370 bmp
= m_active_right_bmp
;
380 if (orientation
== wxLEFT
)
382 rect
.SetX(in_rect
.x
);
383 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
384 rect
.SetWidth(bmp
.GetWidth());
385 rect
.SetHeight(bmp
.GetHeight());
389 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
390 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
391 bmp
.GetWidth(), bmp
.GetHeight());
395 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
402 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
405 dc
.SetFont(m_measuring_font
);
407 wxSize s
= GetTabSize(&dc
, wxT("ABCDEFGHIj"), true, wxAUI_BUTTON_STATE_HIDDEN
, &x_ext
);
411 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
413 m_normal_font
= font
;
416 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
418 m_selected_font
= font
;
421 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
423 m_measuring_font
= font
;
431 // -- wxAuiTabContainer class implementation --
434 // wxAuiTabContainer is a class which contains information about each
435 // tab. It also can render an entire tab control to a specified DC.
436 // It's not a window class itself, because this code will be used by
437 // the wxFrameMananger, where it is disadvantageous to have separate
438 // windows for each tab control in the case of "docked tabs"
440 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
441 // which can be used as a tab control in the normal sense.
444 wxAuiTabContainer::wxAuiTabContainer()
448 m_art
= new wxAuiDefaultTabArt
;
450 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
451 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
452 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
455 wxAuiTabContainer::~wxAuiTabContainer()
460 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
466 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
471 void wxAuiTabContainer::SetFlags(unsigned int flags
)
475 // check for new close button settings
476 RemoveButton(wxAUI_BUTTON_CLOSE
);
477 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
479 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
483 unsigned int wxAuiTabContainer::GetFlags() const
489 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
491 m_art
->SetNormalFont(font
);
494 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
496 m_art
->SetSelectedFont(font
);
499 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
501 m_art
->SetMeasuringFont(font
);
504 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
509 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
510 const wxAuiNotebookPage
& info
)
512 wxAuiNotebookPage page_info
;
514 page_info
.window
= page
;
516 m_pages
.Add(page_info
);
521 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
522 const wxAuiNotebookPage
& info
,
525 wxAuiNotebookPage page_info
;
527 page_info
.window
= page
;
529 if (idx
>= m_pages
.GetCount())
530 m_pages
.Add(page_info
);
532 m_pages
.Insert(page_info
, idx
);
537 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
540 int idx
= GetIdxFromWindow(page
);
544 // get page entry, make a copy of it
545 wxAuiNotebookPage p
= GetPage(idx
);
547 // remove old page entry
550 // insert page where it should be
551 InsertPage(page
, p
, new_idx
);
556 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
558 size_t i
, page_count
= m_pages
.GetCount();
559 for (i
= 0; i
< page_count
; ++i
)
561 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
562 if (page
.window
== wnd
)
572 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
576 size_t i
, page_count
= m_pages
.GetCount();
577 for (i
= 0; i
< page_count
; ++i
)
579 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
580 if (page
.window
== wnd
)
594 void wxAuiTabContainer::SetNoneActive()
596 size_t i
, page_count
= m_pages
.GetCount();
597 for (i
= 0; i
< page_count
; ++i
)
599 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
604 bool wxAuiTabContainer::SetActivePage(size_t page
)
606 if (page
>= m_pages
.GetCount())
609 return SetActivePage(m_pages
.Item(page
).window
);
612 int wxAuiTabContainer::GetActivePage() const
614 size_t i
, page_count
= m_pages
.GetCount();
615 for (i
= 0; i
< page_count
; ++i
)
617 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
625 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
627 if (idx
>= m_pages
.GetCount())
630 return m_pages
[idx
].window
;
633 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
635 size_t i
, page_count
= m_pages
.GetCount();
636 for (i
= 0; i
< page_count
; ++i
)
638 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
639 if (page
.window
== wnd
)
645 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
647 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
652 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
657 size_t wxAuiTabContainer::GetPageCount() const
659 return m_pages
.GetCount();
662 void wxAuiTabContainer::AddButton(int id
,
664 const wxBitmap
& normal_bitmap
,
665 const wxBitmap
& disabled_bitmap
)
667 wxAuiTabContainerButton button
;
669 button
.bitmap
= normal_bitmap
;
670 button
.dis_bitmap
= disabled_bitmap
;
671 button
.location
= location
;
672 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
674 m_buttons
.Add(button
);
677 void wxAuiTabContainer::RemoveButton(int id
)
679 size_t i
, button_count
= m_buttons
.GetCount();
681 for (i
= 0; i
< button_count
; ++i
)
683 if (m_buttons
.Item(i
).id
== id
)
685 m_buttons
.RemoveAt(i
);
693 size_t wxAuiTabContainer::GetTabOffset() const
698 void wxAuiTabContainer::SetTabOffset(size_t offset
)
700 m_tab_offset
= offset
;
703 // Render() renders the tab catalog to the specified DC
704 // It is a virtual function and can be overridden to
705 // provide custom drawing capabilities
706 void wxAuiTabContainer::Render(wxDC
* raw_dc
)
711 size_t page_count
= m_pages
.GetCount();
712 size_t button_count
= m_buttons
.GetCount();
714 // create off-screen bitmap
715 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
716 dc
.SelectObject(bmp
);
719 // find out if size of tabs is larger than can be
720 // afforded on screen
722 int visible_width
= 0;
723 for (i
= 0; i
< page_count
; ++i
)
725 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
727 // determine if a close button is on this tab
728 bool close_button
= false;
729 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
730 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
737 wxSize size
= m_art
->GetTabSize(&dc
,
741 wxAUI_BUTTON_STATE_NORMAL
:
742 wxAUI_BUTTON_STATE_HIDDEN
,
745 if (i
+1 < page_count
)
746 total_width
+= x_extent
;
748 total_width
+= size
.x
;
750 if (i
>= m_tab_offset
)
752 if (i
+1 < page_count
)
753 visible_width
+= x_extent
;
755 visible_width
+= size
.x
;
759 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
761 // show left/right buttons
762 for (i
= 0; i
< button_count
; ++i
)
764 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
765 if (button
.id
== wxAUI_BUTTON_LEFT
||
766 button
.id
== wxAUI_BUTTON_RIGHT
)
768 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
774 // hide left/right buttons
775 for (i
= 0; i
< button_count
; ++i
)
777 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
778 if (button
.id
== wxAUI_BUTTON_LEFT
||
779 button
.id
== wxAUI_BUTTON_RIGHT
)
781 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
786 // determine whether left button should be enabled
787 for (i
= 0; i
< button_count
; ++i
)
789 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
790 if (button
.id
== wxAUI_BUTTON_LEFT
)
792 if (m_tab_offset
== 0)
793 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
795 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
797 if (button
.id
== wxAUI_BUTTON_RIGHT
)
799 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
800 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
802 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
809 m_art
->DrawBackground(&dc
, m_rect
);
812 int left_buttons_width
= 0;
813 int right_buttons_width
= 0;
817 // draw the buttons on the right side
818 offset
= m_rect
.x
+ m_rect
.width
;
819 for (i
= 0; i
< button_count
; ++i
)
821 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
823 if (button
.location
!= wxRIGHT
)
825 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
828 wxRect button_rect
= m_rect
;
830 button_rect
.SetWidth(offset
);
832 m_art
->DrawButton(&dc
,
840 offset
-= button
.rect
.GetWidth();
841 right_buttons_width
+= button
.rect
.GetWidth();
848 // draw the buttons on the left side
850 for (i
= 0; i
< button_count
; ++i
)
852 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
854 if (button
.location
!= wxLEFT
)
856 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
859 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
861 m_art
->DrawButton(&dc
,
869 offset
+= button
.rect
.GetWidth();
870 left_buttons_width
+= button
.rect
.GetWidth();
873 offset
= left_buttons_width
;
875 // set a clipping region to the tabs don't draw over the buttons
876 dc
.SetClippingRegion(left_buttons_width
, 0,
877 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
882 // prepare the tab-close-button array
883 while (m_tab_close_buttons
.GetCount() < page_count
)
885 wxAuiTabContainerButton tempbtn
;
886 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
887 tempbtn
.location
= wxCENTER
;
888 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
889 m_tab_close_buttons
.Add(tempbtn
);
892 for (i
= 0; i
< m_tab_offset
; ++i
)
894 // buttons before the tab offset must be set to hidden
895 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
902 int active_offset
= 0;
905 wxRect rect
= m_rect
;
908 rect
.height
= m_rect
.height
;
910 for (i
= m_tab_offset
; i
< page_count
; ++i
)
912 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
913 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
915 // determine if a close button is on this tab
916 bool close_button
= false;
917 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
918 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
921 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
923 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
924 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
925 tab_button
.location
= wxCENTER
;
930 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
939 tab_button
.cur_state
,
947 active_offset
= offset
;
953 // draw the active tab again so it stands in the foreground
954 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
956 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
958 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
960 // determine if a close button is on this tab
961 bool close_button
= false;
962 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
963 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
968 rect
.x
= active_offset
;
973 tab_button
.cur_state
,
979 dc
.DestroyClippingRegion();
981 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
982 m_rect
.GetWidth(), m_rect
.GetHeight(),
987 // TabHitTest() tests if a tab was hit, passing the window pointer
988 // back if that condition was fulfilled. The function returns
989 // true if a tab was hit, otherwise false
990 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
992 if (!m_rect
.Contains(x
,y
))
995 wxAuiTabContainerButton
* btn
= NULL
;
996 if (ButtonHitTest(x
, y
, &btn
))
998 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1002 size_t i
, page_count
= m_pages
.GetCount();
1004 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1006 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1007 if (page
.rect
.Contains(x
,y
))
1018 // ButtonHitTest() tests if a button was hit. The function returns
1019 // true if a button was hit, otherwise false
1020 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1021 wxAuiTabContainerButton
** hit
) const
1023 if (!m_rect
.Contains(x
,y
))
1026 size_t i
, button_count
;
1029 button_count
= m_buttons
.GetCount();
1030 for (i
= 0; i
< button_count
; ++i
)
1032 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1033 if (button
.rect
.Contains(x
,y
))
1041 button_count
= m_tab_close_buttons
.GetCount();
1042 for (i
= 0; i
< button_count
; ++i
)
1044 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1045 if (button
.rect
.Contains(x
,y
))
1058 // the utility function ShowWnd() is the same as show,
1059 // except it handles wxAuiMDIChildFrame windows as well,
1060 // as the Show() method on this class is "unplugged"
1061 static void ShowWnd(wxWindow
* wnd
, bool show
)
1063 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1065 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1075 // DoShowHide() this function shows the active window, then
1076 // hides all of the other windows (in that order)
1077 void wxAuiTabContainer::DoShowHide()
1079 wxAuiNotebookPageArray
& pages
= GetPages();
1080 size_t i
, page_count
= pages
.GetCount();
1082 // show new active page first
1083 for (i
= 0; i
< page_count
; ++i
)
1085 wxAuiNotebookPage
& page
= pages
.Item(i
);
1088 ShowWnd(page
.window
, true);
1093 // hide all other pages
1094 for (i
= 0; i
< page_count
; ++i
)
1096 wxAuiNotebookPage
& page
= pages
.Item(i
);
1097 ShowWnd(page
.window
, page
.active
);
1106 // -- wxAuiTabCtrl class implementation --
1110 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1111 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1112 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1113 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1114 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1115 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1116 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1117 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1118 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1122 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1126 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1128 m_click_pt
= wxDefaultPosition
;
1129 m_is_dragging
= false;
1130 m_hover_button
= NULL
;
1133 wxAuiTabCtrl::~wxAuiTabCtrl()
1137 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1141 dc
.SetFont(GetFont());
1143 if (GetPageCount() > 0)
1147 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1151 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1153 wxSize s
= evt
.GetSize();
1154 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1158 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1161 m_click_pt
= wxDefaultPosition
;
1162 m_is_dragging
= false;
1166 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1168 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1169 e
.SetSelection(GetIdxFromWindow(wnd
));
1170 e
.SetOldSelection(GetActivePage());
1171 e
.SetEventObject(this);
1172 GetEventHandler()->ProcessEvent(e
);
1174 m_click_pt
.x
= evt
.m_x
;
1175 m_click_pt
.y
= evt
.m_y
;
1181 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1187 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1189 if (GetCapture() == this)
1194 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1195 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1196 evt
.SetOldSelection(evt
.GetSelection());
1197 evt
.SetEventObject(this);
1198 GetEventHandler()->ProcessEvent(evt
);
1204 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1208 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1210 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1211 evt
.SetInt(m_hover_button
->id
);
1212 evt
.SetEventObject(this);
1213 GetEventHandler()->ProcessEvent(evt
);
1217 m_click_pt
= wxDefaultPosition
;
1218 m_is_dragging
= false;
1222 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1224 wxPoint pos
= evt
.GetPosition();
1226 // check if the mouse is hovering above a button
1227 wxAuiTabContainerButton
* button
;
1228 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1230 if (m_hover_button
&& button
!= m_hover_button
)
1232 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1233 m_hover_button
= NULL
;
1238 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1240 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1243 m_hover_button
= button
;
1251 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1252 m_hover_button
= NULL
;
1259 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1264 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1265 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1266 evt
.SetOldSelection(evt
.GetSelection());
1267 evt
.SetEventObject(this);
1268 GetEventHandler()->ProcessEvent(evt
);
1273 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1274 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1276 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1277 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1279 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1280 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1281 evt
.SetOldSelection(evt
.GetSelection());
1282 evt
.SetEventObject(this);
1283 GetEventHandler()->ProcessEvent(evt
);
1285 m_is_dragging
= true;
1289 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1293 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1294 m_hover_button
= NULL
;
1300 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1302 int button
= event
.GetInt();
1304 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1306 if (button
== wxAUI_BUTTON_LEFT
)
1308 if (GetTabOffset() > 0)
1310 SetTabOffset(GetTabOffset()-1);
1317 SetTabOffset(GetTabOffset()+1);
1328 // wxTabFrame is an interesting case. It's important that all child pages
1329 // of the multi-notebook control are all actually children of that control
1330 // (and not grandchildren). wxTabFrame facilitates this. There is one
1331 // instance of wxTabFrame for each tab control inside the multi-notebook.
1332 // It's important to know that wxTabFrame is not a real window, but it merely
1333 // used to capture the dimensions/positioning of the internal tab control and
1334 // it's managed page windows
1336 class wxTabFrame
: public wxWindow
1343 m_rect
= wxRect(0,0,200,200);
1344 m_tab_ctrl_height
= 20;
1347 void SetTabCtrlHeight(int h
)
1349 m_tab_ctrl_height
= h
;
1352 void DoSetSize(int x
, int y
,
1353 int width
, int height
,
1354 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1356 m_rect
= wxRect(x
, y
, width
, height
);
1360 void DoGetClientSize(int* x
, int* y
) const
1366 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1373 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1374 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1375 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1376 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1380 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1381 size_t i
, page_count
= pages
.GetCount();
1383 for (i
= 0; i
< page_count
; ++i
)
1385 wxAuiNotebookPage
& page
= pages
.Item(i
);
1386 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
, m_rect
.width
, m_rect
.height
-tab_height
);
1388 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1390 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
1391 wnd
->ApplyMDIChildFrameRect();
1396 void DoGetSize(int* x
, int* y
) const
1399 *x
= m_rect
.GetWidth();
1401 *y
= m_rect
.GetHeight();
1413 wxAuiTabCtrl
* m_tabs
;
1414 int m_tab_ctrl_height
;
1421 // -- wxAuiNotebook class implementation --
1423 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
1424 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1425 //EVT_SIZE(wxAuiNotebook::OnSize)
1426 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1427 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
1428 EVT_COMMAND_RANGE(10000, 10100,
1429 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1430 wxAuiNotebook::OnTabClicked
)
1431 EVT_COMMAND_RANGE(10000, 10100,
1432 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1433 wxAuiNotebook::OnTabBeginDrag
)
1434 EVT_COMMAND_RANGE(10000, 10100,
1435 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1436 wxAuiNotebook::OnTabEndDrag
)
1437 EVT_COMMAND_RANGE(10000, 10100,
1438 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1439 wxAuiNotebook::OnTabDragMotion
)
1440 EVT_COMMAND_RANGE(10000, 10100,
1441 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1442 wxAuiNotebook::OnTabButton
)
1445 wxAuiNotebook::wxAuiNotebook()
1448 m_tab_id_counter
= 10000;
1450 m_tab_ctrl_height
= 20;
1453 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
1457 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1459 InitNotebook(style
);
1462 bool wxAuiNotebook::Create(wxWindow
* parent
,
1468 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1471 InitNotebook(style
);
1476 // InitNotebook() contains common initialization
1477 // code called by all constructors
1478 void wxAuiNotebook::InitNotebook(long style
)
1481 m_tab_id_counter
= 10000;
1483 m_tab_ctrl_height
= 20;
1484 m_flags
= (unsigned int)style
;
1486 m_normal_font
= *wxNORMAL_FONT
;
1487 m_selected_font
= *wxNORMAL_FONT
;
1488 m_selected_font
.SetWeight(wxBOLD
);
1490 // choose a default for the tab height
1491 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1493 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1494 m_dummy_wnd
->SetSize(200, 200);
1495 m_dummy_wnd
->Show(false);
1497 m_mgr
.SetManagedWindow(this);
1499 m_mgr
.AddPane(m_dummy_wnd
,
1500 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1505 wxAuiNotebook::~wxAuiNotebook()
1510 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
1512 m_tabs
.SetArtProvider(art
);
1515 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
1517 return m_tabs
.GetArtProvider();
1520 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1521 const wxString
& caption
,
1523 const wxBitmap
& bitmap
)
1525 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1528 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1530 const wxString
& caption
,
1532 const wxBitmap
& bitmap
)
1534 wxAuiNotebookPage info
;
1536 info
.caption
= caption
;
1537 info
.bitmap
= bitmap
;
1538 info
.active
= false;
1540 // if there are currently no tabs, the first added
1541 // tab must be active
1542 if (m_tabs
.GetPageCount() == 0)
1545 m_tabs
.InsertPage(page
, info
, page_idx
);
1547 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1548 if (page_idx
>= active_tabctrl
->GetPageCount())
1549 active_tabctrl
->AddPage(page
, info
);
1551 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1554 active_tabctrl
->DoShowHide();
1558 int idx
= m_tabs
.GetIdxFromWindow(page
);
1559 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1568 // DeletePage() removes a tab from the multi-notebook,
1569 // and destroys the window as well
1570 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1572 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1573 wxWindow
* new_active
= NULL
;
1575 // find out which onscreen tab ctrl owns this tab
1578 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1581 // find a new page and set it as active
1582 int new_idx
= ctrl_idx
+1;
1583 if (new_idx
>= (int)ctrl
->GetPageCount())
1584 new_idx
= ctrl_idx
-1;
1586 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1588 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1592 // set the active page to the first page that
1593 // isn't the one being deleted
1594 size_t i
, page_count
= m_tabs
.GetPageCount();
1595 for (i
= 0; i
< page_count
; ++i
)
1597 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1600 new_active
= m_tabs
.GetWindowFromIdx(i
);
1606 // remove the tab from main catalog
1607 if (!m_tabs
.RemovePage(wnd
))
1610 // remove the tab from the onscreen tab ctrl
1611 ctrl
->RemovePage(wnd
);
1613 // actually destroy the window now
1614 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1616 // delete the child frame with pending delete, as is
1617 // customary with frame windows
1618 if (!wxPendingDelete
.Member(wnd
))
1619 wxPendingDelete
.Append(wnd
);
1626 RemoveEmptyTabFrames();
1628 // set new active pane
1632 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1640 // RemovePage() removes a tab from the multi-notebook,
1641 // but does not destroy the window
1642 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1644 // remove the tab from our own catalog
1645 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1646 if (!m_tabs
.RemovePage(wnd
))
1649 // remove the tab from the onscreen tab ctrl
1652 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1654 ctrl
->RemovePage(wnd
);
1661 // SetPageText() changes the tab caption of the specified page
1662 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1664 if (page_idx
>= m_tabs
.GetPageCount())
1667 // update our own tab catalog
1668 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1669 page_info
.caption
= text
;
1671 // update what's on screen
1674 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1676 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1677 info
.caption
= text
;
1685 // GetSelection() returns the index of the currently active page
1686 int wxAuiNotebook::GetSelection() const
1691 // SetSelection() sets the currently active page
1692 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1694 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1698 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1699 evt
.SetSelection(new_page
);
1700 evt
.SetOldSelection(m_curpage
);
1701 evt
.SetEventObject(this);
1702 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1704 // program allows the page change
1705 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1706 (void)GetEventHandler()->ProcessEvent(evt
);
1712 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1714 m_tabs
.SetActivePage(wnd
);
1716 ctrl
->SetActivePage(ctrl_idx
);
1720 int old_curpage
= m_curpage
;
1721 m_curpage
= new_page
;
1725 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1726 size_t i
, pane_count
= all_panes
.GetCount();
1727 for (i
= 0; i
< pane_count
; ++i
)
1729 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1730 if (pane
.name
== wxT("dummy"))
1732 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1733 if (tabctrl
!= ctrl
)
1734 tabctrl
->SetSelectedFont(m_normal_font
);
1736 tabctrl
->SetSelectedFont(m_selected_font
);
1749 // GetPageCount() returns the total number of
1750 // pages managed by the multi-notebook
1751 size_t wxAuiNotebook::GetPageCount() const
1753 return m_tabs
.GetPageCount();
1756 // GetPage() returns the wxWindow pointer of the
1758 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1760 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1762 return m_tabs
.GetWindowFromIdx(page_idx
);
1765 // DoSizing() performs all sizing operations in each tab control
1766 void wxAuiNotebook::DoSizing()
1768 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1769 size_t i
, pane_count
= all_panes
.GetCount();
1770 for (i
= 0; i
< pane_count
; ++i
)
1772 if (all_panes
.Item(i
).name
== wxT("dummy"))
1775 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1776 tabframe
->DoSizing();
1780 // GetActiveTabCtrl() returns the active tab control. It is
1781 // called to determine which control gets new windows being added
1782 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1784 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1789 // find the tab ctrl with the current page
1790 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1797 // no current page, just find the first tab ctrl
1798 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1799 size_t i
, pane_count
= all_panes
.GetCount();
1800 for (i
= 0; i
< pane_count
; ++i
)
1802 if (all_panes
.Item(i
).name
== wxT("dummy"))
1805 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1806 return tabframe
->m_tabs
;
1809 // If there is no tabframe at all, create one
1810 wxTabFrame
* tabframe
= new wxTabFrame
;
1811 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1812 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1817 tabframe
->m_tabs
->SetFlags(m_flags
);
1818 m_mgr
.AddPane(tabframe
,
1819 wxAuiPaneInfo().Center().CaptionVisible(false));
1823 return tabframe
->m_tabs
;
1826 // FindTab() finds the tab control that currently contains the window as well
1827 // as the index of the window in the tab control. It returns true if the
1828 // window was found, otherwise false.
1829 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1831 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1832 size_t i
, pane_count
= all_panes
.GetCount();
1833 for (i
= 0; i
< pane_count
; ++i
)
1835 if (all_panes
.Item(i
).name
== wxT("dummy"))
1838 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1840 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1843 *ctrl
= tabframe
->m_tabs
;
1853 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
1857 void wxAuiNotebook::OnSize(wxSizeEvent
&)
1861 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1863 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1865 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1866 wxASSERT(ctrl
!= NULL
);
1868 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1869 wxASSERT(wnd
!= NULL
);
1871 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1872 wxASSERT(idx
!= -1);
1877 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1882 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1884 wxPoint screen_pt
= ::wxGetMousePosition();
1885 wxPoint client_pt
= ScreenToClient(screen_pt
);
1888 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1890 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
1891 if (dest_tabs
== src_tabs
)
1893 // always hide the hint for inner-tabctrl drag
1896 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
1897 wxWindow
* dest_location_tab
;
1899 // this is an inner-tab drag/reposition
1900 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
1902 int src_idx
= evt
.GetSelection();
1903 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
1905 // prevent jumpy drag
1906 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
1907 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
1908 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
1910 m_last_drag_x
= pt
.x
;
1915 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
1916 dest_tabs
->MovePage(src_tab
, dest_idx
);
1917 dest_tabs
->SetActivePage((size_t)dest_idx
);
1918 dest_tabs
->DoShowHide();
1919 dest_tabs
->Refresh();
1920 m_last_drag_x
= pt
.x
;
1929 wxRect hint_rect
= dest_tabs
->GetRect();
1930 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1931 m_mgr
.ShowHint(hint_rect
);
1935 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1941 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1943 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1948 // get the mouse position, which will be used to determine the drop point
1949 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1950 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1953 // the src tab control is the control that fired this event
1954 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1955 wxAuiTabCtrl
* dest_tabs
= NULL
;
1958 // If the pointer is in an existing tab frame, do a tab insert
1959 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1960 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1961 int insert_idx
= -1;
1964 dest_tabs
= tab_frame
->m_tabs
;
1966 if (dest_tabs
== src_tabs
)
1970 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
1971 wxWindow
* target
= NULL
;
1972 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
1975 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
1980 // If there is no tabframe at all, create one
1981 wxTabFrame
* new_tabs
= new wxTabFrame
;
1982 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1983 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1988 new_tabs
->m_tabs
->SetFlags(m_flags
);
1990 m_mgr
.AddPane(new_tabs
,
1991 wxAuiPaneInfo().Bottom().CaptionVisible(false),
1994 dest_tabs
= new_tabs
->m_tabs
;
1999 // remove the page from the source tabs
2000 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2001 page_info
.active
= false;
2002 src_tabs
->RemovePage(page_info
.window
);
2003 if (src_tabs
->GetPageCount() > 0)
2005 src_tabs
->SetActivePage((size_t)0);
2006 src_tabs
->DoShowHide();
2007 src_tabs
->Refresh();
2012 // add the page to the destination tabs
2013 if (insert_idx
== -1)
2014 insert_idx
= dest_tabs
->GetPageCount();
2015 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2017 if (src_tabs
->GetPageCount() == 0)
2019 RemoveEmptyTabFrames();
2023 dest_tabs
->DoShowHide();
2024 dest_tabs
->Refresh();
2026 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2029 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2031 // if we've just removed the last tab from the source
2032 // tab set, the remove the tab control completely
2033 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2034 size_t i
, pane_count
= all_panes
.GetCount();
2035 for (i
= 0; i
< pane_count
; ++i
)
2037 if (all_panes
.Item(i
).name
== wxT("dummy"))
2040 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2041 if (tabframe
->m_tab_rect
.Contains(pt
))
2042 return tabframe
->m_tabs
;
2048 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2050 // if we've just removed the last tab from the source
2051 // tab set, the remove the tab control completely
2052 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2053 size_t i
, pane_count
= all_panes
.GetCount();
2054 for (i
= 0; i
< pane_count
; ++i
)
2056 if (all_panes
.Item(i
).name
== wxT("dummy"))
2059 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2060 if (tabframe
->m_tabs
== tab_ctrl
)
2069 void wxAuiNotebook::RemoveEmptyTabFrames()
2071 // if we've just removed the last tab from the source
2072 // tab set, the remove the tab control completely
2073 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2074 size_t i
, pane_count
= all_panes
.GetCount();
2075 for (i
= 0; i
< pane_count
; ++i
)
2077 if (all_panes
.Item(i
).name
== wxT("dummy"))
2080 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2081 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2083 m_mgr
.DetachPane(tab_frame
);
2085 // use pending delete because sometimes during
2086 // window closing, refreshs are pending
2087 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2088 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2089 //tab_frame->m_tabs->Destroy();
2096 // check to see if there is still a center pane;
2097 // if there isn't, make a frame the center pane
2098 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2099 pane_count
= panes
.GetCount();
2100 wxWindow
* first_good
= NULL
;
2101 bool center_found
= false;
2102 for (i
= 0; i
< pane_count
; ++i
)
2104 if (panes
.Item(i
).name
== wxT("dummy"))
2106 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2107 center_found
= true;
2109 first_good
= panes
.Item(i
).window
;
2112 if (!center_found
&& first_good
)
2114 m_mgr
.GetPane(first_good
).Centre();
2120 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2122 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2123 if (idx
!= -1 && idx
!= m_curpage
)
2130 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2132 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2133 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2135 int button_id
= evt
.GetInt();
2137 if (button_id
== wxAUI_BUTTON_CLOSE
)
2139 int selection
= tabs
->GetActivePage();
2141 if (selection
!= -1)
2143 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2145 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2151 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2152 DeletePage(main_idx
);