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 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 void wxAuiNotebook::SetWindowStyleFlag(long style
)
1524 wxControl::SetWindowStyleFlag(style
);
1526 m_flags
= (unsigned int)style
;
1528 // if the control is already initialized
1529 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
1531 // let all of the tab children know about the new style
1533 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1534 size_t i
, pane_count
= all_panes
.GetCount();
1535 for (i
= 0; i
< pane_count
; ++i
)
1537 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1538 if (pane
.name
== wxT("dummy"))
1540 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1541 tabctrl
->SetFlags(m_flags
);
1549 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1550 const wxString
& caption
,
1552 const wxBitmap
& bitmap
)
1554 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1557 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1559 const wxString
& caption
,
1561 const wxBitmap
& bitmap
)
1563 wxAuiNotebookPage info
;
1565 info
.caption
= caption
;
1566 info
.bitmap
= bitmap
;
1567 info
.active
= false;
1569 // if there are currently no tabs, the first added
1570 // tab must be active
1571 if (m_tabs
.GetPageCount() == 0)
1574 m_tabs
.InsertPage(page
, info
, page_idx
);
1576 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1577 if (page_idx
>= active_tabctrl
->GetPageCount())
1578 active_tabctrl
->AddPage(page
, info
);
1580 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1583 active_tabctrl
->DoShowHide();
1587 int idx
= m_tabs
.GetIdxFromWindow(page
);
1588 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1597 // DeletePage() removes a tab from the multi-notebook,
1598 // and destroys the window as well
1599 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1601 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1602 wxWindow
* new_active
= NULL
;
1604 // find out which onscreen tab ctrl owns this tab
1607 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1610 // find a new page and set it as active
1611 int new_idx
= ctrl_idx
+1;
1612 if (new_idx
>= (int)ctrl
->GetPageCount())
1613 new_idx
= ctrl_idx
-1;
1615 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1617 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1621 // set the active page to the first page that
1622 // isn't the one being deleted
1623 size_t i
, page_count
= m_tabs
.GetPageCount();
1624 for (i
= 0; i
< page_count
; ++i
)
1626 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1629 new_active
= m_tabs
.GetWindowFromIdx(i
);
1635 // remove the tab from main catalog
1636 if (!m_tabs
.RemovePage(wnd
))
1639 // remove the tab from the onscreen tab ctrl
1640 ctrl
->RemovePage(wnd
);
1642 // actually destroy the window now
1643 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1645 // delete the child frame with pending delete, as is
1646 // customary with frame windows
1647 if (!wxPendingDelete
.Member(wnd
))
1648 wxPendingDelete
.Append(wnd
);
1655 RemoveEmptyTabFrames();
1657 // set new active pane
1661 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1669 // RemovePage() removes a tab from the multi-notebook,
1670 // but does not destroy the window
1671 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1673 // remove the tab from our own catalog
1674 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1675 if (!m_tabs
.RemovePage(wnd
))
1678 // remove the tab from the onscreen tab ctrl
1681 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1683 ctrl
->RemovePage(wnd
);
1690 // SetPageText() changes the tab caption of the specified page
1691 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1693 if (page_idx
>= m_tabs
.GetPageCount())
1696 // update our own tab catalog
1697 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1698 page_info
.caption
= text
;
1700 // update what's on screen
1703 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1705 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1706 info
.caption
= text
;
1714 // GetSelection() returns the index of the currently active page
1715 int wxAuiNotebook::GetSelection() const
1720 // SetSelection() sets the currently active page
1721 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1723 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1727 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1728 evt
.SetSelection(new_page
);
1729 evt
.SetOldSelection(m_curpage
);
1730 evt
.SetEventObject(this);
1731 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1733 // program allows the page change
1734 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1735 (void)GetEventHandler()->ProcessEvent(evt
);
1741 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1743 m_tabs
.SetActivePage(wnd
);
1745 ctrl
->SetActivePage(ctrl_idx
);
1749 int old_curpage
= m_curpage
;
1750 m_curpage
= new_page
;
1754 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1755 size_t i
, pane_count
= all_panes
.GetCount();
1756 for (i
= 0; i
< pane_count
; ++i
)
1758 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1759 if (pane
.name
== wxT("dummy"))
1761 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1762 if (tabctrl
!= ctrl
)
1763 tabctrl
->SetSelectedFont(m_normal_font
);
1765 tabctrl
->SetSelectedFont(m_selected_font
);
1778 // GetPageCount() returns the total number of
1779 // pages managed by the multi-notebook
1780 size_t wxAuiNotebook::GetPageCount() const
1782 return m_tabs
.GetPageCount();
1785 // GetPage() returns the wxWindow pointer of the
1787 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1789 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1791 return m_tabs
.GetWindowFromIdx(page_idx
);
1794 // DoSizing() performs all sizing operations in each tab control
1795 void wxAuiNotebook::DoSizing()
1797 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1798 size_t i
, pane_count
= all_panes
.GetCount();
1799 for (i
= 0; i
< pane_count
; ++i
)
1801 if (all_panes
.Item(i
).name
== wxT("dummy"))
1804 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1805 tabframe
->DoSizing();
1809 // GetActiveTabCtrl() returns the active tab control. It is
1810 // called to determine which control gets new windows being added
1811 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1813 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1818 // find the tab ctrl with the current page
1819 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1826 // no current page, just find the first tab ctrl
1827 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1828 size_t i
, pane_count
= all_panes
.GetCount();
1829 for (i
= 0; i
< pane_count
; ++i
)
1831 if (all_panes
.Item(i
).name
== wxT("dummy"))
1834 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1835 return tabframe
->m_tabs
;
1838 // If there is no tabframe at all, create one
1839 wxTabFrame
* tabframe
= new wxTabFrame
;
1840 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1841 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1846 tabframe
->m_tabs
->SetFlags(m_flags
);
1847 m_mgr
.AddPane(tabframe
,
1848 wxAuiPaneInfo().Center().CaptionVisible(false));
1852 return tabframe
->m_tabs
;
1855 // FindTab() finds the tab control that currently contains the window as well
1856 // as the index of the window in the tab control. It returns true if the
1857 // window was found, otherwise false.
1858 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1860 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1861 size_t i
, pane_count
= all_panes
.GetCount();
1862 for (i
= 0; i
< pane_count
; ++i
)
1864 if (all_panes
.Item(i
).name
== wxT("dummy"))
1867 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1869 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1872 *ctrl
= tabframe
->m_tabs
;
1882 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
1886 void wxAuiNotebook::OnSize(wxSizeEvent
&)
1890 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1892 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1894 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1895 wxASSERT(ctrl
!= NULL
);
1897 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1898 wxASSERT(wnd
!= NULL
);
1900 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1901 wxASSERT(idx
!= -1);
1906 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1911 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1913 wxPoint screen_pt
= ::wxGetMousePosition();
1914 wxPoint client_pt
= ScreenToClient(screen_pt
);
1917 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1919 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
1920 if (dest_tabs
== src_tabs
)
1924 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
1927 // always hide the hint for inner-tabctrl drag
1930 // if tab moving is not allowed, leave
1931 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
1936 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
1937 wxWindow
* dest_location_tab
;
1939 // this is an inner-tab drag/reposition
1940 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
1942 int src_idx
= evt
.GetSelection();
1943 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
1945 // prevent jumpy drag
1946 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
1947 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
1948 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
1950 m_last_drag_x
= pt
.x
;
1955 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
1956 dest_tabs
->MovePage(src_tab
, dest_idx
);
1957 dest_tabs
->SetActivePage((size_t)dest_idx
);
1958 dest_tabs
->DoShowHide();
1959 dest_tabs
->Refresh();
1960 m_last_drag_x
= pt
.x
;
1968 // if tab moving is not allowed, leave
1969 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
1977 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
1983 wxRect hint_rect
= dest_tabs
->GetRect();
1984 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1985 m_mgr
.ShowHint(hint_rect
);
1989 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1995 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1997 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2001 // if tab moving is not allowed, leave
2002 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2007 // set cursor back to an arrow
2008 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2011 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2014 // get the mouse position, which will be used to determine the drop point
2015 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2016 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2019 // the src tab control is the control that fired this event
2020 wxAuiTabCtrl
* dest_tabs
= NULL
;
2023 // If the pointer is in an existing tab frame, do a tab insert
2024 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2025 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2026 int insert_idx
= -1;
2029 dest_tabs
= tab_frame
->m_tabs
;
2031 if (dest_tabs
== src_tabs
)
2035 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2036 wxWindow
* target
= NULL
;
2037 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2040 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2045 // If there is no tabframe at all, create one
2046 wxTabFrame
* new_tabs
= new wxTabFrame
;
2047 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2048 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2053 new_tabs
->m_tabs
->SetFlags(m_flags
);
2055 m_mgr
.AddPane(new_tabs
,
2056 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2059 dest_tabs
= new_tabs
->m_tabs
;
2064 // remove the page from the source tabs
2065 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2066 page_info
.active
= false;
2067 src_tabs
->RemovePage(page_info
.window
);
2068 if (src_tabs
->GetPageCount() > 0)
2070 src_tabs
->SetActivePage((size_t)0);
2071 src_tabs
->DoShowHide();
2072 src_tabs
->Refresh();
2077 // add the page to the destination tabs
2078 if (insert_idx
== -1)
2079 insert_idx
= dest_tabs
->GetPageCount();
2080 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2082 if (src_tabs
->GetPageCount() == 0)
2084 RemoveEmptyTabFrames();
2088 dest_tabs
->DoShowHide();
2089 dest_tabs
->Refresh();
2091 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2096 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2098 // if we've just removed the last tab from the source
2099 // tab set, the remove the tab control completely
2100 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2101 size_t i
, pane_count
= all_panes
.GetCount();
2102 for (i
= 0; i
< pane_count
; ++i
)
2104 if (all_panes
.Item(i
).name
== wxT("dummy"))
2107 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2108 if (tabframe
->m_tab_rect
.Contains(pt
))
2109 return tabframe
->m_tabs
;
2115 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2117 // if we've just removed the last tab from the source
2118 // tab set, the remove the tab control completely
2119 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2120 size_t i
, pane_count
= all_panes
.GetCount();
2121 for (i
= 0; i
< pane_count
; ++i
)
2123 if (all_panes
.Item(i
).name
== wxT("dummy"))
2126 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2127 if (tabframe
->m_tabs
== tab_ctrl
)
2136 void wxAuiNotebook::RemoveEmptyTabFrames()
2138 // if we've just removed the last tab from the source
2139 // tab set, the remove the tab control completely
2140 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2141 size_t i
, pane_count
= all_panes
.GetCount();
2142 for (i
= 0; i
< pane_count
; ++i
)
2144 if (all_panes
.Item(i
).name
== wxT("dummy"))
2147 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2148 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2150 m_mgr
.DetachPane(tab_frame
);
2152 // use pending delete because sometimes during
2153 // window closing, refreshs are pending
2154 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2155 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2156 //tab_frame->m_tabs->Destroy();
2163 // check to see if there is still a center pane;
2164 // if there isn't, make a frame the center pane
2165 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2166 pane_count
= panes
.GetCount();
2167 wxWindow
* first_good
= NULL
;
2168 bool center_found
= false;
2169 for (i
= 0; i
< pane_count
; ++i
)
2171 if (panes
.Item(i
).name
== wxT("dummy"))
2173 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2174 center_found
= true;
2176 first_good
= panes
.Item(i
).window
;
2179 if (!center_found
&& first_good
)
2181 m_mgr
.GetPane(first_good
).Centre();
2187 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2189 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2190 if (idx
!= -1 && idx
!= m_curpage
)
2197 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2199 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2200 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2202 int button_id
= evt
.GetInt();
2204 if (button_id
== wxAUI_BUTTON_CLOSE
)
2206 int selection
= tabs
->GetActivePage();
2208 if (selection
!= -1)
2210 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2212 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2218 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2219 DeletePage(main_idx
);