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 bool with_close_button
,
200 wxCoord normal_textx
, normal_texty
;
201 wxCoord selected_textx
, selected_texty
;
202 wxCoord textx
, texty
;
204 // if the caption is empty, measure some temporary text
205 wxString caption
= caption_text
;
206 if (caption_text
.empty())
209 dc
->SetFont(m_selected_font
);
210 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
212 dc
->SetFont(m_normal_font
);
213 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
215 // figure out the size of the tab
216 wxSize tab_size
= GetTabSize(dc
, caption
, active
, with_close_button
, x_extent
);
218 wxCoord tab_height
= tab_size
.y
;
219 wxCoord tab_width
= tab_size
.x
;
220 wxCoord tab_x
= in_rect
.x
;
221 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
223 // select pen, brush and font for the tab to be drawn
227 dc
->SetPen(m_selected_bkpen
);
228 dc
->SetBrush(m_selected_bkbrush
);
229 dc
->SetFont(m_selected_font
);
230 textx
= selected_textx
;
231 texty
= selected_texty
;
235 dc
->SetPen(m_normal_bkpen
);
236 dc
->SetBrush(m_normal_bkbrush
);
237 dc
->SetFont(m_normal_font
);
238 textx
= normal_textx
;
239 texty
= normal_texty
;
247 points
[0].y
= tab_y
+ tab_height
- 1;
248 points
[1].x
= tab_x
+ tab_height
- 3;
249 points
[1].y
= tab_y
+ 2;
250 points
[2].x
= tab_x
+ tab_height
+ 3;
252 points
[3].x
= tab_x
+ tab_width
- 2;
254 points
[4].x
= tab_x
+ tab_width
;
255 points
[4].y
= tab_y
+ 2;
256 points
[5].x
= tab_x
+ tab_width
;
257 points
[5].y
= tab_y
+ tab_height
- 1;
258 points
[6] = points
[0];
261 dc
->DrawPolygon(6, points
);
263 dc
->SetPen(*wxGREY_PEN
);
265 //dc->DrawLines(active ? 6 : 7, points);
266 dc
->DrawLines(7, points
);
271 int close_button_width
= 0;
272 if (with_close_button
)
274 close_button_width
= m_active_close_bmp
.GetWidth();
275 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
279 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
284 dc
->DrawText(caption
,
286 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
289 // draw close button if necessary
290 if (with_close_button
)
294 bmp
= m_active_close_bmp
;
296 bmp
= m_disabled_close_bmp
;
298 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1, tab_y
+ 1,
299 close_button_width
, tab_height
- 1);
300 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, wxAUI_BUTTON_STATE_NORMAL
);
304 *out_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
308 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
* dc
,
309 const wxString
& caption
,
310 bool WXUNUSED(active
),
311 bool with_close_button
,
314 wxCoord measured_textx
, measured_texty
;
316 dc
->SetFont(m_measuring_font
);
317 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
319 wxCoord tab_height
= measured_texty
+ 4;
320 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
322 if (with_close_button
)
323 tab_width
+= m_active_close_bmp
.GetWidth();
325 *x_extent
= tab_width
- (tab_height
/2) - 1;
327 return wxSize(tab_width
, tab_height
);
331 void wxAuiDefaultTabArt::DrawButton(
333 const wxRect
& in_rect
,
337 const wxBitmap
& bitmap_override
,
343 if (bitmap_override
.IsOk())
345 bmp
= bitmap_override
;
351 case wxAUI_BUTTON_CLOSE
:
352 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
353 bmp
= m_disabled_close_bmp
;
355 bmp
= m_active_close_bmp
;
357 case wxAUI_BUTTON_LEFT
:
358 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
359 bmp
= m_disabled_left_bmp
;
361 bmp
= m_active_left_bmp
;
363 case wxAUI_BUTTON_RIGHT
:
364 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
365 bmp
= m_disabled_right_bmp
;
367 bmp
= m_active_right_bmp
;
377 if (orientation
== wxLEFT
)
379 rect
.SetX(in_rect
.x
);
380 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
381 rect
.SetWidth(bmp
.GetWidth());
382 rect
.SetHeight(bmp
.GetHeight());
386 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
387 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
388 bmp
.GetWidth(), bmp
.GetHeight());
392 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
399 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
402 dc
.SetFont(m_measuring_font
);
404 wxSize s
= GetTabSize(&dc
, wxT("ABCDEFGHIj"), true, false, &x_ext
);
408 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
410 m_normal_font
= font
;
413 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
415 m_selected_font
= font
;
418 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
420 m_measuring_font
= font
;
428 // -- wxAuiTabContainer class implementation --
431 // wxAuiTabContainer is a class which contains information about each
432 // tab. It also can render an entire tab control to a specified DC.
433 // It's not a window class itself, because this code will be used by
434 // the wxFrameMananger, where it is disadvantageous to have separate
435 // windows for each tab control in the case of "docked tabs"
437 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
438 // which can be used as a tab control in the normal sense.
441 wxAuiTabContainer::wxAuiTabContainer()
445 m_art
= new wxAuiDefaultTabArt
;
447 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
448 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
449 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
452 wxAuiTabContainer::~wxAuiTabContainer()
457 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
463 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
468 void wxAuiTabContainer::SetFlags(unsigned int flags
)
473 unsigned int wxAuiTabContainer::GetFlags() const
479 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
481 m_art
->SetNormalFont(font
);
484 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
486 m_art
->SetSelectedFont(font
);
489 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
491 m_art
->SetMeasuringFont(font
);
494 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
499 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
500 const wxAuiNotebookPage
& info
)
502 wxAuiNotebookPage page_info
;
504 page_info
.window
= page
;
506 m_pages
.Add(page_info
);
511 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
512 const wxAuiNotebookPage
& info
,
515 wxAuiNotebookPage page_info
;
517 page_info
.window
= page
;
519 if (idx
>= m_pages
.GetCount())
520 m_pages
.Add(page_info
);
522 m_pages
.Insert(page_info
, idx
);
527 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
530 int idx
= GetIdxFromWindow(page
);
534 // get page entry, make a copy of it
535 wxAuiNotebookPage p
= GetPage(idx
);
537 // remove old page entry
540 // insert page where it should be
541 InsertPage(page
, p
, new_idx
);
546 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
548 size_t i
, page_count
= m_pages
.GetCount();
549 for (i
= 0; i
< page_count
; ++i
)
551 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
552 if (page
.window
== wnd
)
562 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
566 size_t i
, page_count
= m_pages
.GetCount();
567 for (i
= 0; i
< page_count
; ++i
)
569 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
570 if (page
.window
== wnd
)
584 void wxAuiTabContainer::SetNoneActive()
586 size_t i
, page_count
= m_pages
.GetCount();
587 for (i
= 0; i
< page_count
; ++i
)
589 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
594 bool wxAuiTabContainer::SetActivePage(size_t page
)
596 if (page
>= m_pages
.GetCount())
599 return SetActivePage(m_pages
.Item(page
).window
);
602 int wxAuiTabContainer::GetActivePage() const
604 size_t i
, page_count
= m_pages
.GetCount();
605 for (i
= 0; i
< page_count
; ++i
)
607 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
615 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
617 if (idx
>= m_pages
.GetCount())
620 return m_pages
[idx
].window
;
623 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
625 size_t i
, page_count
= m_pages
.GetCount();
626 for (i
= 0; i
< page_count
; ++i
)
628 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
629 if (page
.window
== wnd
)
635 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
637 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
642 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
647 size_t wxAuiTabContainer::GetPageCount() const
649 return m_pages
.GetCount();
652 void wxAuiTabContainer::AddButton(int id
,
654 const wxBitmap
& normal_bitmap
,
655 const wxBitmap
& disabled_bitmap
)
657 wxAuiTabContainerButton button
;
659 button
.bitmap
= normal_bitmap
;
660 button
.dis_bitmap
= disabled_bitmap
;
661 button
.location
= location
;
662 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
664 m_buttons
.Add(button
);
667 size_t wxAuiTabContainer::GetTabOffset() const
672 void wxAuiTabContainer::SetTabOffset(size_t offset
)
674 m_tab_offset
= offset
;
677 // Render() renders the tab catalog to the specified DC
678 // It is a virtual function and can be overridden to
679 // provide custom drawing capabilities
680 void wxAuiTabContainer::Render(wxDC
* raw_dc
)
685 size_t page_count
= m_pages
.GetCount();
686 size_t button_count
= m_buttons
.GetCount();
688 // create off-screen bitmap
689 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
690 dc
.SelectObject(bmp
);
693 // find out if size of tabs is larger than can be
694 // afforded on screen
696 int visible_width
= 0;
697 for (i
= 0; i
< page_count
; ++i
)
699 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
701 // determine if a close button is on this tab
702 bool close_button
= false;
703 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
704 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
711 wxSize size
= m_art
->GetTabSize(&dc
, page
.caption
, page
.active
, close_button
, &x_extent
);
713 if (i
+1 < page_count
)
714 total_width
+= x_extent
;
716 total_width
+= size
.x
;
718 if (i
>= m_tab_offset
)
720 if (i
+1 < page_count
)
721 visible_width
+= x_extent
;
723 visible_width
+= size
.x
;
727 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
729 // show left/right buttons
730 for (i
= 0; i
< button_count
; ++i
)
732 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
733 if (button
.id
== wxAUI_BUTTON_LEFT
||
734 button
.id
== wxAUI_BUTTON_RIGHT
)
736 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
742 // hide left/right buttons
743 for (i
= 0; i
< button_count
; ++i
)
745 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
746 if (button
.id
== wxAUI_BUTTON_LEFT
||
747 button
.id
== wxAUI_BUTTON_RIGHT
)
749 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
754 // determine whether left button should be enabled
755 for (i
= 0; i
< button_count
; ++i
)
757 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
758 if (button
.id
== wxAUI_BUTTON_LEFT
)
760 if (m_tab_offset
== 0)
761 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
763 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
765 if (button
.id
== wxAUI_BUTTON_RIGHT
)
767 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
768 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
770 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
777 m_art
->DrawBackground(&dc
, m_rect
);
780 int left_buttons_width
= 0;
781 int right_buttons_width
= 0;
785 // draw the buttons on the right side
786 offset
= m_rect
.x
+ m_rect
.width
;
787 for (i
= 0; i
< button_count
; ++i
)
789 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
791 if (button
.location
!= wxRIGHT
)
793 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
796 wxRect button_rect
= m_rect
;
798 button_rect
.SetWidth(offset
);
800 m_art
->DrawButton(&dc
,
808 offset
-= button
.rect
.GetWidth();
809 right_buttons_width
+= button
.rect
.GetWidth();
816 // draw the buttons on the left side
818 for (i
= 0; i
< button_count
; ++i
)
820 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
822 if (button
.location
!= wxLEFT
)
824 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
827 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
829 m_art
->DrawButton(&dc
,
837 offset
+= button
.rect
.GetWidth();
838 left_buttons_width
+= button
.rect
.GetWidth();
841 offset
= left_buttons_width
;
843 // set a clipping region to the tabs don't draw over the buttons
844 dc
.SetClippingRegion(left_buttons_width
, 0,
845 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
853 int active_offset
= 0;
856 wxRect rect
= m_rect
;
859 rect
.height
= m_rect
.height
;
861 for (i
= m_tab_offset
; i
< page_count
; ++i
)
863 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
865 // determine if a close button is on this tab
866 bool close_button
= false;
867 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
868 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
886 active_offset
= offset
;
892 // draw the active tab again so it stands in the foreground
893 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
895 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
897 // determine if a close button is on this tab
898 bool close_button
= false;
899 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
900 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
905 rect
.x
= active_offset
;
915 dc
.DestroyClippingRegion();
917 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
918 m_rect
.GetWidth(), m_rect
.GetHeight(),
923 // TabHitTest() tests if a tab was hit, passing the window pointer
924 // back if that condition was fulfilled. The function returns
925 // true if a tab was hit, otherwise false
926 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
928 if (!m_rect
.Contains(x
,y
))
931 if (ButtonHitTest(x
, y
, NULL
))
934 size_t i
, page_count
= m_pages
.GetCount();
936 for (i
= m_tab_offset
; i
< page_count
; ++i
)
938 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
939 if (page
.rect
.Contains(x
,y
))
950 // ButtonHitTest() tests if a button was hit. The function returns
951 // true if a button was hit, otherwise false
952 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
953 wxAuiTabContainerButton
** hit
) const
955 if (!m_rect
.Contains(x
,y
))
958 size_t i
, button_count
= m_buttons
.GetCount();
960 for (i
= 0; i
< button_count
; ++i
)
962 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
963 if (button
.rect
.Contains(x
,y
))
976 // the utility function ShowWnd() is the same as show,
977 // except it handles wxAuiMDIChildFrame windows as well,
978 // as the Show() method on this class is "unplugged"
979 static void ShowWnd(wxWindow
* wnd
, bool show
)
981 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
983 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
993 // DoShowHide() this function shows the active window, then
994 // hides all of the other windows (in that order)
995 void wxAuiTabContainer::DoShowHide()
997 wxAuiNotebookPageArray
& pages
= GetPages();
998 size_t i
, page_count
= pages
.GetCount();
1000 // show new active page first
1001 for (i
= 0; i
< page_count
; ++i
)
1003 wxAuiNotebookPage
& page
= pages
.Item(i
);
1006 ShowWnd(page
.window
, true);
1011 // hide all other pages
1012 for (i
= 0; i
< page_count
; ++i
)
1014 wxAuiNotebookPage
& page
= pages
.Item(i
);
1015 ShowWnd(page
.window
, page
.active
);
1024 // -- wxAuiTabCtrl class implementation --
1028 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1029 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1030 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1031 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1032 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1033 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1034 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1035 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1036 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1040 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1044 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1046 m_click_pt
= wxDefaultPosition
;
1047 m_is_dragging
= false;
1048 m_hover_button
= NULL
;
1051 wxAuiTabCtrl::~wxAuiTabCtrl()
1055 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1059 dc
.SetFont(GetFont());
1061 if (GetPageCount() > 0)
1065 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1069 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1071 wxSize s
= evt
.GetSize();
1072 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1076 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1079 m_click_pt
= wxDefaultPosition
;
1080 m_is_dragging
= false;
1084 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1086 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1087 e
.SetSelection(GetIdxFromWindow(wnd
));
1088 e
.SetOldSelection(GetActivePage());
1089 e
.SetEventObject(this);
1090 GetEventHandler()->ProcessEvent(e
);
1092 m_click_pt
.x
= evt
.m_x
;
1093 m_click_pt
.y
= evt
.m_y
;
1099 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1105 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1107 if (GetCapture() == this)
1112 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1113 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1114 evt
.SetOldSelection(evt
.GetSelection());
1115 evt
.SetEventObject(this);
1116 GetEventHandler()->ProcessEvent(evt
);
1122 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1126 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1128 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1129 evt
.SetInt(m_hover_button
->id
);
1130 evt
.SetEventObject(this);
1131 GetEventHandler()->ProcessEvent(evt
);
1135 m_click_pt
= wxDefaultPosition
;
1136 m_is_dragging
= false;
1140 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1142 wxPoint pos
= evt
.GetPosition();
1144 // check if the mouse is hovering above a button
1145 wxAuiTabContainerButton
* button
;
1146 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1148 if (m_hover_button
&& button
!= m_hover_button
)
1150 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1151 m_hover_button
= NULL
;
1156 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1158 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1161 m_hover_button
= button
;
1169 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1170 m_hover_button
= NULL
;
1177 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1182 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1183 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1184 evt
.SetOldSelection(evt
.GetSelection());
1185 evt
.SetEventObject(this);
1186 GetEventHandler()->ProcessEvent(evt
);
1191 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1192 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1194 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1195 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1197 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1198 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1199 evt
.SetOldSelection(evt
.GetSelection());
1200 evt
.SetEventObject(this);
1201 GetEventHandler()->ProcessEvent(evt
);
1203 m_is_dragging
= true;
1207 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1211 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1212 m_hover_button
= NULL
;
1218 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1220 int button
= event
.GetInt();
1222 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1224 if (button
== wxAUI_BUTTON_LEFT
)
1226 if (GetTabOffset() > 0)
1228 SetTabOffset(GetTabOffset()-1);
1235 SetTabOffset(GetTabOffset()+1);
1246 // wxTabFrame is an interesting case. It's important that all child pages
1247 // of the multi-notebook control are all actually children of that control
1248 // (and not grandchildren). wxTabFrame facilitates this. There is one
1249 // instance of wxTabFrame for each tab control inside the multi-notebook.
1250 // It's important to know that wxTabFrame is not a real window, but it merely
1251 // used to capture the dimensions/positioning of the internal tab control and
1252 // it's managed page windows
1254 class wxTabFrame
: public wxWindow
1261 m_rect
= wxRect(0,0,200,200);
1262 m_tab_ctrl_height
= 20;
1265 void SetTabCtrlHeight(int h
)
1267 m_tab_ctrl_height
= h
;
1270 void DoSetSize(int x
, int y
,
1271 int width
, int height
,
1272 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1274 m_rect
= wxRect(x
, y
, width
, height
);
1278 void DoGetClientSize(int* x
, int* y
) const
1284 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1291 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1292 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1293 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1294 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1298 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1299 size_t i
, page_count
= pages
.GetCount();
1301 for (i
= 0; i
< page_count
; ++i
)
1303 wxAuiNotebookPage
& page
= pages
.Item(i
);
1304 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
, m_rect
.width
, m_rect
.height
-tab_height
);
1306 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1308 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
1309 wnd
->ApplyMDIChildFrameRect();
1314 void DoGetSize(int* x
, int* y
) const
1317 *x
= m_rect
.GetWidth();
1319 *y
= m_rect
.GetHeight();
1331 wxAuiTabCtrl
* m_tabs
;
1332 int m_tab_ctrl_height
;
1339 // -- wxAuiNotebook class implementation --
1341 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
1342 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
1343 //EVT_SIZE(wxAuiNotebook::OnSize)
1344 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
1345 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
1346 EVT_COMMAND_RANGE(10000, 10100,
1347 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1348 wxAuiNotebook::OnTabClicked
)
1349 EVT_COMMAND_RANGE(10000, 10100,
1350 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1351 wxAuiNotebook::OnTabBeginDrag
)
1352 EVT_COMMAND_RANGE(10000, 10100,
1353 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1354 wxAuiNotebook::OnTabEndDrag
)
1355 EVT_COMMAND_RANGE(10000, 10100,
1356 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1357 wxAuiNotebook::OnTabDragMotion
)
1358 EVT_COMMAND_RANGE(10000, 10100,
1359 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1360 wxAuiNotebook::OnTabButton
)
1363 wxAuiNotebook::wxAuiNotebook()
1366 m_tab_id_counter
= 10000;
1368 m_tab_ctrl_height
= 20;
1371 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
1375 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1377 InitNotebook(style
);
1380 bool wxAuiNotebook::Create(wxWindow
* parent
,
1386 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1389 InitNotebook(style
);
1394 // InitNotebook() contains common initialization
1395 // code called by all constructors
1396 void wxAuiNotebook::InitNotebook(long style
)
1399 m_tab_id_counter
= 10000;
1401 m_tab_ctrl_height
= 20;
1402 m_flags
= (unsigned int)style
;
1404 m_normal_font
= *wxNORMAL_FONT
;
1405 m_selected_font
= *wxNORMAL_FONT
;
1406 m_selected_font
.SetWeight(wxBOLD
);
1408 // choose a default for the tab height
1409 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1411 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1412 m_dummy_wnd
->SetSize(200, 200);
1413 m_dummy_wnd
->Show(false);
1415 m_mgr
.SetManagedWindow(this);
1417 m_mgr
.AddPane(m_dummy_wnd
,
1418 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1423 wxAuiNotebook::~wxAuiNotebook()
1428 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
1430 m_tabs
.SetArtProvider(art
);
1433 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
1435 return m_tabs
.GetArtProvider();
1438 bool wxAuiNotebook::AddPage(wxWindow
* page
,
1439 const wxString
& caption
,
1441 const wxBitmap
& bitmap
)
1443 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1446 bool wxAuiNotebook::InsertPage(size_t page_idx
,
1448 const wxString
& caption
,
1450 const wxBitmap
& bitmap
)
1452 wxAuiNotebookPage info
;
1454 info
.caption
= caption
;
1455 info
.bitmap
= bitmap
;
1456 info
.active
= false;
1458 // if there are currently no tabs, the first added
1459 // tab must be active
1460 if (m_tabs
.GetPageCount() == 0)
1463 m_tabs
.InsertPage(page
, info
, page_idx
);
1465 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1466 if (page_idx
>= active_tabctrl
->GetPageCount())
1467 active_tabctrl
->AddPage(page
, info
);
1469 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1472 active_tabctrl
->DoShowHide();
1476 int idx
= m_tabs
.GetIdxFromWindow(page
);
1477 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
1486 // DeletePage() removes a tab from the multi-notebook,
1487 // and destroys the window as well
1488 bool wxAuiNotebook::DeletePage(size_t page_idx
)
1490 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1491 wxWindow
* new_active
= NULL
;
1493 // find out which onscreen tab ctrl owns this tab
1496 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1499 // find a new page and set it as active
1500 int new_idx
= ctrl_idx
+1;
1501 if (new_idx
>= (int)ctrl
->GetPageCount())
1502 new_idx
= ctrl_idx
-1;
1504 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1506 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1510 // set the active page to the first page that
1511 // isn't the one being deleted
1512 size_t i
, page_count
= m_tabs
.GetPageCount();
1513 for (i
= 0; i
< page_count
; ++i
)
1515 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1518 new_active
= m_tabs
.GetWindowFromIdx(i
);
1524 // remove the tab from main catalog
1525 if (!m_tabs
.RemovePage(wnd
))
1528 // remove the tab from the onscreen tab ctrl
1529 ctrl
->RemovePage(wnd
);
1531 // actually destroy the window now
1532 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1534 // delete the child frame with pending delete, as is
1535 // customary with frame windows
1536 if (!wxPendingDelete
.Member(wnd
))
1537 wxPendingDelete
.Append(wnd
);
1544 RemoveEmptyTabFrames();
1546 // set new active pane
1550 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1558 // RemovePage() removes a tab from the multi-notebook,
1559 // but does not destroy the window
1560 bool wxAuiNotebook::RemovePage(size_t page_idx
)
1562 // remove the tab from our own catalog
1563 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1564 if (!m_tabs
.RemovePage(wnd
))
1567 // remove the tab from the onscreen tab ctrl
1570 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1572 ctrl
->RemovePage(wnd
);
1579 // SetPageText() changes the tab caption of the specified page
1580 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1582 if (page_idx
>= m_tabs
.GetPageCount())
1585 // update our own tab catalog
1586 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1587 page_info
.caption
= text
;
1589 // update what's on screen
1592 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1594 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1595 info
.caption
= text
;
1603 // GetSelection() returns the index of the currently active page
1604 int wxAuiNotebook::GetSelection() const
1609 // SetSelection() sets the currently active page
1610 size_t wxAuiNotebook::SetSelection(size_t new_page
)
1612 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1616 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1617 evt
.SetSelection(new_page
);
1618 evt
.SetOldSelection(m_curpage
);
1619 evt
.SetEventObject(this);
1620 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1622 // program allows the page change
1623 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1624 (void)GetEventHandler()->ProcessEvent(evt
);
1630 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1632 m_tabs
.SetActivePage(wnd
);
1634 ctrl
->SetActivePage(ctrl_idx
);
1638 int old_curpage
= m_curpage
;
1639 m_curpage
= new_page
;
1643 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1644 size_t i
, pane_count
= all_panes
.GetCount();
1645 for (i
= 0; i
< pane_count
; ++i
)
1647 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
1648 if (pane
.name
== wxT("dummy"))
1650 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1651 if (tabctrl
!= ctrl
)
1652 tabctrl
->SetSelectedFont(m_normal_font
);
1654 tabctrl
->SetSelectedFont(m_selected_font
);
1667 // GetPageCount() returns the total number of
1668 // pages managed by the multi-notebook
1669 size_t wxAuiNotebook::GetPageCount() const
1671 return m_tabs
.GetPageCount();
1674 // GetPage() returns the wxWindow pointer of the
1676 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
1678 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1680 return m_tabs
.GetWindowFromIdx(page_idx
);
1683 // DoSizing() performs all sizing operations in each tab control
1684 void wxAuiNotebook::DoSizing()
1686 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1687 size_t i
, pane_count
= all_panes
.GetCount();
1688 for (i
= 0; i
< pane_count
; ++i
)
1690 if (all_panes
.Item(i
).name
== wxT("dummy"))
1693 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1694 tabframe
->DoSizing();
1698 // GetActiveTabCtrl() returns the active tab control. It is
1699 // called to determine which control gets new windows being added
1700 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
1702 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1707 // find the tab ctrl with the current page
1708 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1715 // no current page, just find the first tab ctrl
1716 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1717 size_t i
, pane_count
= all_panes
.GetCount();
1718 for (i
= 0; i
< pane_count
; ++i
)
1720 if (all_panes
.Item(i
).name
== wxT("dummy"))
1723 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1724 return tabframe
->m_tabs
;
1727 // If there is no tabframe at all, create one
1728 wxTabFrame
* tabframe
= new wxTabFrame
;
1729 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1730 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1735 tabframe
->m_tabs
->SetFlags(m_flags
);
1736 m_mgr
.AddPane(tabframe
,
1737 wxAuiPaneInfo().Center().CaptionVisible(false));
1741 return tabframe
->m_tabs
;
1744 // FindTab() finds the tab control that currently contains the window as well
1745 // as the index of the window in the tab control. It returns true if the
1746 // window was found, otherwise false.
1747 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1749 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1750 size_t i
, pane_count
= all_panes
.GetCount();
1751 for (i
= 0; i
< pane_count
; ++i
)
1753 if (all_panes
.Item(i
).name
== wxT("dummy"))
1756 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1758 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1761 *ctrl
= tabframe
->m_tabs
;
1771 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
1775 void wxAuiNotebook::OnSize(wxSizeEvent
&)
1779 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1781 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1783 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1784 wxASSERT(ctrl
!= NULL
);
1786 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1787 wxASSERT(wnd
!= NULL
);
1789 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1790 wxASSERT(idx
!= -1);
1795 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1800 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1802 wxPoint screen_pt
= ::wxGetMousePosition();
1803 wxPoint client_pt
= ScreenToClient(screen_pt
);
1806 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1808 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
1809 if (dest_tabs
== src_tabs
)
1811 // always hide the hint for inner-tabctrl drag
1814 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
1815 wxWindow
* dest_location_tab
;
1817 // this is an inner-tab drag/reposition
1818 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
1820 int src_idx
= evt
.GetSelection();
1821 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
1823 // prevent jumpy drag
1824 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
1825 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
1826 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
1828 m_last_drag_x
= pt
.x
;
1833 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
1834 dest_tabs
->MovePage(src_tab
, dest_idx
);
1835 dest_tabs
->SetActivePage((size_t)dest_idx
);
1836 dest_tabs
->DoShowHide();
1837 dest_tabs
->Refresh();
1838 m_last_drag_x
= pt
.x
;
1847 wxRect hint_rect
= dest_tabs
->GetRect();
1848 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1849 m_mgr
.ShowHint(hint_rect
);
1853 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1859 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1861 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1866 // get the mouse position, which will be used to determine the drop point
1867 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1868 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1871 // the src tab control is the control that fired this event
1872 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1873 wxAuiTabCtrl
* dest_tabs
= NULL
;
1876 // If the pointer is in an existing tab frame, do a tab insert
1877 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1878 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1879 int insert_idx
= -1;
1882 dest_tabs
= tab_frame
->m_tabs
;
1884 if (dest_tabs
== src_tabs
)
1888 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
1889 wxWindow
* target
= NULL
;
1890 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
1893 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
1898 // If there is no tabframe at all, create one
1899 wxTabFrame
* new_tabs
= new wxTabFrame
;
1900 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1901 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1906 new_tabs
->m_tabs
->SetFlags(m_flags
);
1908 m_mgr
.AddPane(new_tabs
,
1909 wxAuiPaneInfo().Bottom().CaptionVisible(false),
1912 dest_tabs
= new_tabs
->m_tabs
;
1917 // remove the page from the source tabs
1918 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
1919 page_info
.active
= false;
1920 src_tabs
->RemovePage(page_info
.window
);
1921 if (src_tabs
->GetPageCount() > 0)
1923 src_tabs
->SetActivePage((size_t)0);
1924 src_tabs
->DoShowHide();
1925 src_tabs
->Refresh();
1930 // add the page to the destination tabs
1931 if (insert_idx
== -1)
1932 insert_idx
= dest_tabs
->GetPageCount();
1933 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
1935 if (src_tabs
->GetPageCount() == 0)
1937 RemoveEmptyTabFrames();
1941 dest_tabs
->DoShowHide();
1942 dest_tabs
->Refresh();
1944 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
1947 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
1949 // if we've just removed the last tab from the source
1950 // tab set, the remove the tab control completely
1951 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1952 size_t i
, pane_count
= all_panes
.GetCount();
1953 for (i
= 0; i
< pane_count
; ++i
)
1955 if (all_panes
.Item(i
).name
== wxT("dummy"))
1958 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1959 if (tabframe
->m_tab_rect
.Contains(pt
))
1960 return tabframe
->m_tabs
;
1966 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
1968 // if we've just removed the last tab from the source
1969 // tab set, the remove the tab control completely
1970 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1971 size_t i
, pane_count
= all_panes
.GetCount();
1972 for (i
= 0; i
< pane_count
; ++i
)
1974 if (all_panes
.Item(i
).name
== wxT("dummy"))
1977 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1978 if (tabframe
->m_tabs
== tab_ctrl
)
1987 void wxAuiNotebook::RemoveEmptyTabFrames()
1989 // if we've just removed the last tab from the source
1990 // tab set, the remove the tab control completely
1991 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
1992 size_t i
, pane_count
= all_panes
.GetCount();
1993 for (i
= 0; i
< pane_count
; ++i
)
1995 if (all_panes
.Item(i
).name
== wxT("dummy"))
1998 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1999 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2001 m_mgr
.DetachPane(tab_frame
);
2003 // use pending delete because sometimes during
2004 // window closing, refreshs are pending
2005 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
2006 wxPendingDelete
.Append(tab_frame
->m_tabs
);
2007 //tab_frame->m_tabs->Destroy();
2014 // check to see if there is still a center pane;
2015 // if there isn't, make a frame the center pane
2016 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
2017 pane_count
= panes
.GetCount();
2018 wxWindow
* first_good
= NULL
;
2019 bool center_found
= false;
2020 for (i
= 0; i
< pane_count
; ++i
)
2022 if (panes
.Item(i
).name
== wxT("dummy"))
2024 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
2025 center_found
= true;
2027 first_good
= panes
.Item(i
).window
;
2030 if (!center_found
&& first_good
)
2032 m_mgr
.GetPane(first_good
).Centre();
2038 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
2040 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
2041 if (idx
!= -1 && idx
!= m_curpage
)
2048 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
2050 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2051 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2053 int button_id
= evt
.GetInt();
2055 if (button_id
== wxAUI_BUTTON_CLOSE
)
2057 int selection
= tabs
->GetActivePage();
2059 if (selection
!= -1)
2061 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
2063 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2069 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
2070 DeletePage(main_idx
);