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 // -- wxDefaultTabArt class implementation --
108 wxDefaultTabArt::wxDefaultTabArt()
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 wxDefaultTabArt::~wxDefaultTabArt()
169 void wxDefaultTabArt::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 wxDefaultTabArt::DrawTab(wxDC
* dc
,
193 const wxRect
& in_rect
,
194 const wxString
& caption_text
,
199 wxCoord normal_textx
, normal_texty
;
200 wxCoord selected_textx
, selected_texty
;
201 wxCoord measured_textx
, measured_texty
;
202 wxCoord textx
, texty
;
205 // if the caption is empty, measure some temporary text
206 wxString caption
= caption_text
;
207 if (caption_text
.empty())
211 dc
->SetFont(m_measuring_font
);
212 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
214 dc
->SetFont(m_selected_font
);
215 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
217 dc
->SetFont(m_normal_font
);
218 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
220 caption
= caption_text
;
222 wxCoord tab_height
= measured_texty
+ 4;
223 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
224 wxCoord tab_x
= in_rect
.x
;
225 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
228 // select pen, brush and font for the tab to be drawn
232 dc
->SetPen(m_selected_bkpen
);
233 dc
->SetBrush(m_selected_bkbrush
);
234 dc
->SetFont(m_selected_font
);
235 textx
= selected_textx
;
236 texty
= selected_texty
;
240 dc
->SetPen(m_normal_bkpen
);
241 dc
->SetBrush(m_normal_bkbrush
);
242 dc
->SetFont(m_normal_font
);
243 textx
= normal_textx
;
244 texty
= normal_texty
;
252 points
[0].y
= tab_y
+ tab_height
- 1;
253 points
[1].x
= tab_x
+ tab_height
- 3;
254 points
[1].y
= tab_y
+ 2;
255 points
[2].x
= tab_x
+ tab_height
+ 3;
257 points
[3].x
= tab_x
+ tab_width
- 2;
259 points
[4].x
= tab_x
+ tab_width
;
260 points
[4].y
= tab_y
+ 2;
261 points
[5].x
= tab_x
+ tab_width
;
262 points
[5].y
= tab_y
+ tab_height
- 1;
263 points
[6] = points
[0];
266 dc
->DrawPolygon(6, points
);
268 dc
->SetPen(*wxGREY_PEN
);
270 //dc->DrawLines(active ? 6 : 7, points);
271 dc
->DrawLines(7, points
);
275 dc
->DrawText(caption
,
276 tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2),
277 tab_y
+ tab_height
- texty
- 2);
279 *out_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
280 *x_extent
= tab_width
- (tab_height
/2) - 1;
284 wxSize
wxDefaultTabArt::GetTabSize(wxDC
* dc
,
285 const wxString
& caption
,
286 bool WXUNUSED(active
),
289 wxCoord measured_textx
, measured_texty
;
291 dc
->SetFont(m_measuring_font
);
292 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
294 wxCoord tab_height
= measured_texty
+ 4;
295 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
297 *x_extent
= tab_width
- (tab_height
/2) - 1;
299 return wxSize(tab_width
, tab_height
);
303 void wxDefaultTabArt::DrawButton(
305 const wxRect
& in_rect
,
309 const wxBitmap
& bitmap_override
,
315 if (bitmap_override
.IsOk())
317 bmp
= bitmap_override
;
323 case wxAUI_BUTTON_CLOSE
:
324 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
325 bmp
= m_disabled_close_bmp
;
327 bmp
= m_active_close_bmp
;
329 case wxAUI_BUTTON_LEFT
:
330 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
331 bmp
= m_disabled_left_bmp
;
333 bmp
= m_active_left_bmp
;
335 case wxAUI_BUTTON_RIGHT
:
336 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
337 bmp
= m_disabled_right_bmp
;
339 bmp
= m_active_right_bmp
;
349 if (orientation
== wxLEFT
)
351 rect
.SetX(in_rect
.x
);
352 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
353 rect
.SetWidth(bmp
.GetWidth());
354 rect
.SetHeight(bmp
.GetHeight());
358 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
359 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
360 bmp
.GetWidth(), bmp
.GetHeight());
364 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
373 void wxDefaultTabArt::SetNormalFont(const wxFont
& font
)
375 m_normal_font
= font
;
378 void wxDefaultTabArt::SetSelectedFont(const wxFont
& font
)
380 m_selected_font
= font
;
383 void wxDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
385 m_measuring_font
= font
;
393 // -- wxAuiTabContainer class implementation --
396 // wxAuiTabContainer is a class which contains information about each
397 // tab. It also can render an entire tab control to a specified DC.
398 // It's not a window class itself, because this code will be used by
399 // the wxFrameMananger, where it is disadvantageous to have separate
400 // windows for each tab control in the case of "docked tabs"
402 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
403 // which can be used as a tab control in the normal sense.
406 wxAuiTabContainer::wxAuiTabContainer()
409 m_art
= new wxDefaultTabArt
;
411 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
412 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
413 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
416 wxAuiTabContainer::~wxAuiTabContainer()
421 void wxAuiTabContainer::SetArtProvider(wxTabArt
* art
)
427 wxTabArt
* wxAuiTabContainer::GetArtProvider()
432 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
434 m_art
->SetNormalFont(font
);
437 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
439 m_art
->SetSelectedFont(font
);
442 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
444 m_art
->SetMeasuringFont(font
);
447 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
452 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
453 const wxAuiNotebookPage
& info
)
455 wxAuiNotebookPage page_info
;
457 page_info
.window
= page
;
459 m_pages
.Add(page_info
);
464 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
465 const wxAuiNotebookPage
& info
,
468 wxAuiNotebookPage page_info
;
470 page_info
.window
= page
;
472 if (idx
>= m_pages
.GetCount())
473 m_pages
.Add(page_info
);
475 m_pages
.Insert(page_info
, idx
);
480 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
482 size_t i
, page_count
= m_pages
.GetCount();
483 for (i
= 0; i
< page_count
; ++i
)
485 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
486 if (page
.window
== wnd
)
496 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
500 size_t i
, page_count
= m_pages
.GetCount();
501 for (i
= 0; i
< page_count
; ++i
)
503 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
504 if (page
.window
== wnd
)
518 void wxAuiTabContainer::SetNoneActive()
520 size_t i
, page_count
= m_pages
.GetCount();
521 for (i
= 0; i
< page_count
; ++i
)
523 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
528 bool wxAuiTabContainer::SetActivePage(size_t page
)
530 if (page
>= m_pages
.GetCount())
533 return SetActivePage(m_pages
.Item(page
).window
);
536 int wxAuiTabContainer::GetActivePage() const
538 size_t i
, page_count
= m_pages
.GetCount();
539 for (i
= 0; i
< page_count
; ++i
)
541 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
549 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
551 if (idx
>= m_pages
.GetCount())
554 return m_pages
[idx
].window
;
557 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
559 size_t i
, page_count
= m_pages
.GetCount();
560 for (i
= 0; i
< page_count
; ++i
)
562 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
563 if (page
.window
== wnd
)
569 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
571 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
576 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
581 size_t wxAuiTabContainer::GetPageCount() const
583 return m_pages
.GetCount();
586 void wxAuiTabContainer::AddButton(int id
,
588 const wxBitmap
& normal_bitmap
,
589 const wxBitmap
& disabled_bitmap
)
591 wxAuiTabContainerButton button
;
593 button
.bitmap
= normal_bitmap
;
594 button
.dis_bitmap
= disabled_bitmap
;
595 button
.location
= location
;
596 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
598 m_buttons
.Add(button
);
601 size_t wxAuiTabContainer::GetTabOffset() const
606 void wxAuiTabContainer::SetTabOffset(size_t offset
)
608 m_tab_offset
= offset
;
611 // Render() renders the tab catalog to the specified DC
612 // It is a virtual function and can be overridden to
613 // provide custom drawing capabilities
614 void wxAuiTabContainer::Render(wxDC
* raw_dc
)
619 size_t page_count
= m_pages
.GetCount();
620 size_t button_count
= m_buttons
.GetCount();
622 // create off-screen bitmap
623 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
624 dc
.SelectObject(bmp
);
627 // find out if size of tabs is larger than can be
628 // afforded on screen
630 int visible_width
= 0;
631 for (i
= 0; i
< page_count
; ++i
)
633 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
635 wxSize size
= m_art
->GetTabSize(&dc
, page
.caption
, page
.active
, &x_extent
);
637 if (i
+1 < page_count
)
638 total_width
+= x_extent
;
640 total_width
+= size
.x
;
642 if (i
>= m_tab_offset
)
644 if (i
+1 < page_count
)
645 visible_width
+= x_extent
;
647 visible_width
+= size
.x
;
651 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
653 // show left/right buttons
654 for (i
= 0; i
< button_count
; ++i
)
656 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
657 if (button
.id
== wxAUI_BUTTON_LEFT
||
658 button
.id
== wxAUI_BUTTON_RIGHT
)
660 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
666 // hide left/right buttons
667 for (i
= 0; i
< button_count
; ++i
)
669 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
670 if (button
.id
== wxAUI_BUTTON_LEFT
||
671 button
.id
== wxAUI_BUTTON_RIGHT
)
673 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
678 // determine whether left button should be enabled
679 for (i
= 0; i
< button_count
; ++i
)
681 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
682 if (button
.id
== wxAUI_BUTTON_LEFT
)
684 if (m_tab_offset
== 0)
685 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
687 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
689 if (button
.id
== wxAUI_BUTTON_RIGHT
)
691 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
692 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
694 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
701 m_art
->DrawBackground(&dc
, m_rect
);
704 int left_buttons_width
= 0;
705 int right_buttons_width
= 0;
709 // draw the buttons on the right side
710 offset
= m_rect
.x
+ m_rect
.width
;
711 for (i
= 0; i
< button_count
; ++i
)
713 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
715 if (button
.location
!= wxRIGHT
)
717 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
720 wxRect button_rect
= m_rect
;
722 button_rect
.SetWidth(offset
);
724 m_art
->DrawButton(&dc
,
732 offset
-= button
.rect
.GetWidth();
733 right_buttons_width
+= button
.rect
.GetWidth();
740 // draw the buttons on the left side
742 for (i
= 0; i
< button_count
; ++i
)
744 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
746 if (button
.location
!= wxLEFT
)
748 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
751 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
753 m_art
->DrawButton(&dc
,
761 offset
+= button
.rect
.GetWidth();
762 left_buttons_width
+= button
.rect
.GetWidth();
765 offset
= left_buttons_width
;
768 dc
.SetClippingRegion(left_buttons_width
, 0,
769 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
775 int active_offset
= 0;
778 wxRect rect
= m_rect
;
781 rect
.height
= m_rect
.height
;
783 for (i
= m_tab_offset
; i
< page_count
; ++i
)
785 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
799 active_offset
= offset
;
805 // draw the active tab again so it stands in the foreground
806 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
808 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
810 rect
.x
= active_offset
;
819 dc
.DestroyClippingRegion();
821 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
822 m_rect
.GetWidth(), m_rect
.GetHeight(),
827 // TabHitTest() tests if a tab was hit, passing the window pointer
828 // back if that condition was fulfilled. The function returns
829 // true if a tab was hit, otherwise false
830 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
832 if (!m_rect
.Contains(x
,y
))
835 if (ButtonHitTest(x
, y
, NULL
))
838 size_t i
, page_count
= m_pages
.GetCount();
840 for (i
= m_tab_offset
; i
< page_count
; ++i
)
842 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
843 if (page
.rect
.Contains(x
,y
))
854 // ButtonHitTest() tests if a button was hit. The function returns
855 // true if a button was hit, otherwise false
856 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
857 wxAuiTabContainerButton
** hit
) const
859 if (!m_rect
.Contains(x
,y
))
862 size_t i
, button_count
= m_buttons
.GetCount();
864 for (i
= 0; i
< button_count
; ++i
)
866 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
867 if (button
.rect
.Contains(x
,y
))
880 // the utility function ShowWnd() is the same as show,
881 // except it handles wxTabMDIChildFrame windows as well,
882 // as the Show() method on this class is "unplugged"
883 static void ShowWnd(wxWindow
* wnd
, bool show
)
885 if (wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
887 wxTabMDIChildFrame
* cf
= (wxTabMDIChildFrame
*)wnd
;
897 // DoShowHide() this function shows the active window, then
898 // hides all of the other windows (in that order)
899 void wxAuiTabContainer::DoShowHide()
901 wxAuiNotebookPageArray
& pages
= GetPages();
902 size_t i
, page_count
= pages
.GetCount();
904 // show new active page first
905 for (i
= 0; i
< page_count
; ++i
)
907 wxAuiNotebookPage
& page
= pages
.Item(i
);
910 ShowWnd(page
.window
, true);
915 // hide all other pages
916 for (i
= 0; i
< page_count
; ++i
)
918 wxAuiNotebookPage
& page
= pages
.Item(i
);
919 ShowWnd(page
.window
, page
.active
);
928 // -- wxAuiTabCtrl class implementation --
932 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
933 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
934 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
935 EVT_SIZE(wxAuiTabCtrl::OnSize
)
936 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
937 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
938 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
939 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
940 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
944 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
948 long style
) : wxControl(parent
, id
, pos
, size
, style
)
950 m_click_pt
= wxDefaultPosition
;
951 m_is_dragging
= false;
952 m_hover_button
= NULL
;
956 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
960 dc
.SetFont(GetFont());
962 if (GetPageCount() > 0)
966 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
970 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
972 wxSize s
= evt
.GetSize();
973 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
977 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
980 m_click_pt
= wxDefaultPosition
;
981 m_is_dragging
= false;
985 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
987 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
988 e
.SetSelection(GetIdxFromWindow(wnd
));
989 e
.SetOldSelection(GetActivePage());
990 e
.SetEventObject(this);
991 GetEventHandler()->ProcessEvent(e
);
993 m_click_pt
.x
= evt
.m_x
;
994 m_click_pt
.y
= evt
.m_y
;
995 m_click_tab
= e
.GetSelection();
1000 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1006 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1008 if (GetCapture() == this)
1013 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1014 evt
.SetSelection(m_click_tab
);
1015 evt
.SetOldSelection(m_click_tab
);
1016 evt
.SetEventObject(this);
1017 GetEventHandler()->ProcessEvent(evt
);
1023 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1027 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1029 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1030 evt
.SetInt(m_hover_button
->id
);
1031 evt
.SetEventObject(this);
1032 GetEventHandler()->ProcessEvent(evt
);
1036 m_click_pt
= wxDefaultPosition
;
1037 m_is_dragging
= false;
1041 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1043 wxPoint pos
= evt
.GetPosition();
1045 // check if the mouse is hovering above a button
1046 wxAuiTabContainerButton
* button
;
1047 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1049 if (m_hover_button
&& button
!= m_hover_button
)
1051 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1052 m_hover_button
= NULL
;
1057 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1059 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1062 m_hover_button
= button
;
1070 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1071 m_hover_button
= NULL
;
1078 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1083 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1084 evt
.SetSelection(m_click_tab
);
1085 evt
.SetOldSelection(m_click_tab
);
1086 evt
.SetEventObject(this);
1087 GetEventHandler()->ProcessEvent(evt
);
1092 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1093 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1095 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1096 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1098 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1099 evt
.SetSelection(m_click_tab
);
1100 evt
.SetOldSelection(m_click_tab
);
1101 evt
.SetEventObject(this);
1102 GetEventHandler()->ProcessEvent(evt
);
1104 m_is_dragging
= true;
1108 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1112 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1113 m_hover_button
= NULL
;
1119 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1121 int button
= event
.GetInt();
1123 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1125 if (button
== wxAUI_BUTTON_LEFT
)
1127 if (GetTabOffset() > 0)
1129 SetTabOffset(GetTabOffset()-1);
1136 SetTabOffset(GetTabOffset()+1);
1147 // wxTabFrame is an interesting case. It's important that all child pages
1148 // of the multi-notebook control are all actually children of that control
1149 // (and not grandchildren). wxTabFrame facilitates this. There is one
1150 // instance of wxTabFrame for each tab control inside the multi-notebook.
1151 // It's important to know that wxTabFrame is not a real window, but it merely
1152 // used to capture the dimensions/positioning of the internal tab control and
1153 // it's managed page windows
1155 class wxTabFrame
: public wxWindow
1162 m_rect
= wxRect(0,0,200,200);
1163 m_tab_ctrl_height
= 20;
1166 void SetTabCtrlHeight(int h
)
1168 m_tab_ctrl_height
= h
;
1171 void DoSetSize(int x
, int y
,
1172 int width
, int height
,
1173 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1175 m_rect
= wxRect(x
, y
, width
, height
);
1179 void DoGetClientSize(int* x
, int* y
) const
1185 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1192 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1193 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1194 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1195 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1199 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1200 size_t i
, page_count
= pages
.GetCount();
1202 for (i
= 0; i
< page_count
; ++i
)
1204 wxAuiNotebookPage
& page
= pages
.Item(i
);
1205 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
, m_rect
.width
, m_rect
.height
-tab_height
);
1207 if (page
.window
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1209 wxTabMDIChildFrame
* wnd
= (wxTabMDIChildFrame
*)page
.window
;
1210 wnd
->ApplyMDIChildFrameRect();
1215 void DoGetSize(int* x
, int* y
) const
1218 *x
= m_rect
.GetWidth();
1220 *y
= m_rect
.GetHeight();
1232 wxAuiTabCtrl
* m_tabs
;
1233 int m_tab_ctrl_height
;
1240 // -- wxAuiMultiNotebook class implementation --
1242 BEGIN_EVENT_TABLE(wxAuiMultiNotebook
, wxControl
)
1243 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
1244 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
1245 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
1246 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus
)
1247 EVT_COMMAND_RANGE(10000, 10100,
1248 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1249 wxAuiMultiNotebook::OnTabClicked
)
1250 EVT_COMMAND_RANGE(10000, 10100,
1251 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1252 wxAuiMultiNotebook::OnTabBeginDrag
)
1253 EVT_COMMAND_RANGE(10000, 10100,
1254 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1255 wxAuiMultiNotebook::OnTabEndDrag
)
1256 EVT_COMMAND_RANGE(10000, 10100,
1257 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1258 wxAuiMultiNotebook::OnTabDragMotion
)
1259 EVT_COMMAND_RANGE(10000, 10100,
1260 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1261 wxAuiMultiNotebook::OnTabButton
)
1264 wxAuiMultiNotebook::wxAuiMultiNotebook()
1267 m_tab_id_counter
= 10000;
1269 m_tab_ctrl_height
= 20;
1272 wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow
*parent
,
1276 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1281 bool wxAuiMultiNotebook::Create(wxWindow
* parent
,
1287 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1295 // InitNotebook() contains common initialization
1296 // code called by all constructors
1297 void wxAuiMultiNotebook::InitNotebook()
1300 m_tab_id_counter
= 10000;
1302 m_tab_ctrl_height
= 20;
1304 m_normal_font
= *wxNORMAL_FONT
;
1305 m_selected_font
= *wxNORMAL_FONT
;
1306 m_selected_font
.SetWeight(wxBOLD
);
1308 // choose a default for the tab height
1309 wxClientDC
dc(this);
1311 dc
.SetFont(m_selected_font
);
1312 dc
.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx
, &ty
);
1313 m_tab_ctrl_height
= (ty
*150)/100;
1315 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1316 m_dummy_wnd
->SetSize(200, 200);
1317 m_dummy_wnd
->Show(false);
1319 m_mgr
.SetManagedWindow(this);
1321 m_mgr
.AddPane(m_dummy_wnd
,
1322 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1327 wxAuiMultiNotebook::~wxAuiMultiNotebook()
1332 void wxAuiMultiNotebook::SetArtProvider(wxTabArt
* art
)
1334 m_tabs
.SetArtProvider(art
);
1337 wxTabArt
* wxAuiMultiNotebook::GetArtProvider()
1339 return m_tabs
.GetArtProvider();
1342 bool wxAuiMultiNotebook::AddPage(wxWindow
* page
,
1343 const wxString
& caption
,
1345 const wxBitmap
& bitmap
)
1347 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1350 bool wxAuiMultiNotebook::InsertPage(size_t page_idx
,
1352 const wxString
& caption
,
1354 const wxBitmap
& bitmap
)
1356 wxAuiNotebookPage info
;
1358 info
.caption
= caption
;
1359 info
.bitmap
= bitmap
;
1360 info
.active
= false;
1362 // if there are currently no tabs, the first added
1363 // tab must be active
1364 if (m_tabs
.GetPageCount() == 0)
1367 m_tabs
.InsertPage(page
, info
, page_idx
);
1369 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1370 if (page_idx
>= active_tabctrl
->GetPageCount())
1371 active_tabctrl
->AddPage(page
, info
);
1373 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1376 active_tabctrl
->DoShowHide();
1380 int idx
= m_tabs
.GetIdxFromWindow(page
);
1381 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
1390 // DeletePage() removes a tab from the multi-notebook,
1391 // and destroys the window as well
1392 bool wxAuiMultiNotebook::DeletePage(size_t page_idx
)
1394 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1395 wxWindow
* new_active
= NULL
;
1397 // find out which onscreen tab ctrl owns this tab
1400 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1403 // find a new page and set it as active
1404 int new_idx
= ctrl_idx
+1;
1405 if (new_idx
>= (int)ctrl
->GetPageCount())
1406 new_idx
= ctrl_idx
-1;
1408 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1410 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1414 // set the active page to the first page that
1415 // isn't the one being deleted
1416 size_t i
, page_count
= m_tabs
.GetPageCount();
1417 for (i
= 0; i
< page_count
; ++i
)
1419 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1422 new_active
= m_tabs
.GetWindowFromIdx(i
);
1428 // remove the tab from main catalog
1429 if (!m_tabs
.RemovePage(wnd
))
1432 // remove the tab from the onscreen tab ctrl
1433 ctrl
->RemovePage(wnd
);
1435 // actually destroy the window now
1436 if (wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1438 // delete the child frame with pending delete, as is
1439 // customary with frame windows
1440 if (!wxPendingDelete
.Member(wnd
))
1441 wxPendingDelete
.Append(wnd
);
1448 RemoveEmptyTabFrames();
1450 // set new active pane
1454 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1462 // RemovePage() removes a tab from the multi-notebook,
1463 // but does not destroy the window
1464 bool wxAuiMultiNotebook::RemovePage(size_t page_idx
)
1466 // remove the tab from our own catalog
1467 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1468 if (!m_tabs
.RemovePage(wnd
))
1471 // remove the tab from the onscreen tab ctrl
1474 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1476 ctrl
->RemovePage(wnd
);
1483 // SetPageText() changes the tab caption of the specified page
1484 bool wxAuiMultiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1486 if (page_idx
>= m_tabs
.GetPageCount())
1489 // update our own tab catalog
1490 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1491 page_info
.caption
= text
;
1493 // update what's on screen
1496 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1498 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1499 info
.caption
= text
;
1507 // GetSelection() returns the index of the currently active page
1508 int wxAuiMultiNotebook::GetSelection() const
1513 // SetSelection() sets the currently active page
1514 size_t wxAuiMultiNotebook::SetSelection(size_t new_page
)
1516 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1520 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1521 evt
.SetSelection(new_page
);
1522 evt
.SetOldSelection(m_curpage
);
1523 evt
.SetEventObject(this);
1524 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1526 // program allows the page change
1527 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1528 (void)GetEventHandler()->ProcessEvent(evt
);
1534 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1536 m_tabs
.SetActivePage(wnd
);
1538 ctrl
->SetActivePage(ctrl_idx
);
1542 int old_curpage
= m_curpage
;
1543 m_curpage
= new_page
;
1547 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1548 size_t i
, pane_count
= all_panes
.GetCount();
1549 for (i
= 0; i
< pane_count
; ++i
)
1551 wxPaneInfo
& pane
= all_panes
.Item(i
);
1552 if (pane
.name
== wxT("dummy"))
1554 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1555 if (tabctrl
!= ctrl
)
1556 tabctrl
->SetSelectedFont(m_normal_font
);
1558 tabctrl
->SetSelectedFont(m_selected_font
);
1571 // GetPageCount() returns the total number of
1572 // pages managed by the multi-notebook
1573 size_t wxAuiMultiNotebook::GetPageCount() const
1575 return m_tabs
.GetPageCount();
1578 // GetPage() returns the wxWindow pointer of the
1580 wxWindow
* wxAuiMultiNotebook::GetPage(size_t page_idx
) const
1582 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1584 return m_tabs
.GetWindowFromIdx(page_idx
);
1587 // DoSizing() performs all sizing operations in each tab control
1588 void wxAuiMultiNotebook::DoSizing()
1590 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1591 size_t i
, pane_count
= all_panes
.GetCount();
1592 for (i
= 0; i
< pane_count
; ++i
)
1594 if (all_panes
.Item(i
).name
== wxT("dummy"))
1597 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1598 tabframe
->DoSizing();
1602 // GetActiveTabCtrl() returns the active tab control. It is
1603 // called to determine which control gets new windows being added
1604 wxAuiTabCtrl
* wxAuiMultiNotebook::GetActiveTabCtrl()
1606 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1611 // find the tab ctrl with the current page
1612 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1619 // no current page, just find the first tab ctrl
1620 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1621 size_t i
, pane_count
= all_panes
.GetCount();
1622 for (i
= 0; i
< pane_count
; ++i
)
1624 if (all_panes
.Item(i
).name
== wxT("dummy"))
1627 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1628 return tabframe
->m_tabs
;
1631 // If there is no tabframe at all, create one
1632 wxTabFrame
* tabframe
= new wxTabFrame
;
1633 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1634 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1639 m_mgr
.AddPane(tabframe
,
1640 wxPaneInfo().Center().CaptionVisible(false));
1644 return tabframe
->m_tabs
;
1647 // FindTab() finds the tab control that currently contains the window as well
1648 // as the index of the window in the tab control. It returns true if the
1649 // window was found, otherwise false.
1650 bool wxAuiMultiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1652 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1653 size_t i
, pane_count
= all_panes
.GetCount();
1654 for (i
= 0; i
< pane_count
; ++i
)
1656 if (all_panes
.Item(i
).name
== wxT("dummy"))
1659 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1661 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1664 *ctrl
= tabframe
->m_tabs
;
1674 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent
&)
1678 void wxAuiMultiNotebook::OnSize(wxSizeEvent
&)
1682 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1684 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1686 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1687 wxASSERT(ctrl
!= NULL
);
1689 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1690 wxASSERT(wnd
!= NULL
);
1692 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1693 wxASSERT(idx
!= -1);
1698 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1702 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1704 wxPoint screen_pt
= ::wxGetMousePosition();
1705 wxPoint client_pt
= ScreenToClient(screen_pt
);
1708 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1710 wxAuiTabCtrl
* tab_ctrl
= GetTabCtrlFromPoint(client_pt
);
1711 if (tab_ctrl
== src_tabs
)
1713 // inner-tabctrl dragging is not yet implemented
1720 wxRect hint_rect
= tab_ctrl
->GetRect();
1721 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1722 m_mgr
.ShowHint(hint_rect
);
1726 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1732 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1734 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1739 // get the mouse position, which will be used to determine the drop point
1740 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1741 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1744 // the src tab control is the control that fired this event
1745 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1746 wxAuiTabCtrl
* dest_tabs
= NULL
;
1749 // If the pointer is in an existing tab frame, do a tab insert
1750 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1751 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1754 dest_tabs
= tab_frame
->m_tabs
;
1756 if (dest_tabs
== src_tabs
)
1761 // If there is no tabframe at all, create one
1762 wxTabFrame
* new_tabs
= new wxTabFrame
;
1763 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1764 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1769 m_mgr
.AddPane(new_tabs
,
1770 wxPaneInfo().Bottom().CaptionVisible(false),
1773 dest_tabs
= new_tabs
->m_tabs
;
1778 // remove the page from the source tabs
1779 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
1780 page_info
.active
= false;
1781 src_tabs
->RemovePage(page_info
.window
);
1782 if (src_tabs
->GetPageCount() > 0)
1784 src_tabs
->SetActivePage((size_t)0);
1785 src_tabs
->DoShowHide();
1786 src_tabs
->Refresh();
1791 // add the page to the destination tabs
1792 dest_tabs
->AddPage(page_info
.window
, page_info
);
1794 if (src_tabs
->GetPageCount() == 0)
1796 RemoveEmptyTabFrames();
1800 dest_tabs
->DoShowHide();
1801 dest_tabs
->Refresh();
1803 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
1806 wxAuiTabCtrl
* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
1808 // if we've just removed the last tab from the source
1809 // tab set, the remove the tab control completely
1810 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1811 size_t i
, pane_count
= all_panes
.GetCount();
1812 for (i
= 0; i
< pane_count
; ++i
)
1814 if (all_panes
.Item(i
).name
== wxT("dummy"))
1817 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1818 if (tabframe
->m_tab_rect
.Contains(pt
))
1819 return tabframe
->m_tabs
;
1825 wxWindow
* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
1827 // if we've just removed the last tab from the source
1828 // tab set, the remove the tab control completely
1829 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1830 size_t i
, pane_count
= all_panes
.GetCount();
1831 for (i
= 0; i
< pane_count
; ++i
)
1833 if (all_panes
.Item(i
).name
== wxT("dummy"))
1836 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1837 if (tabframe
->m_tabs
== tab_ctrl
)
1846 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1848 // if we've just removed the last tab from the source
1849 // tab set, the remove the tab control completely
1850 wxPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
1851 size_t i
, pane_count
= all_panes
.GetCount();
1852 for (i
= 0; i
< pane_count
; ++i
)
1854 if (all_panes
.Item(i
).name
== wxT("dummy"))
1857 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1858 if (tab_frame
->m_tabs
->GetPageCount() == 0)
1860 m_mgr
.DetachPane(tab_frame
);
1862 // use pending delete because sometimes during
1863 // window closing, refreshs are pending
1864 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
1865 wxPendingDelete
.Append(tab_frame
->m_tabs
);
1866 //tab_frame->m_tabs->Destroy();
1873 // check to see if there is still a center pane;
1874 // if there isn't, make a frame the center pane
1875 wxPaneInfoArray panes
= m_mgr
.GetAllPanes();
1876 pane_count
= panes
.GetCount();
1877 wxWindow
* first_good
= NULL
;
1878 bool center_found
= false;
1879 for (i
= 0; i
< pane_count
; ++i
)
1881 if (panes
.Item(i
).name
== wxT("dummy"))
1883 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
1884 center_found
= true;
1886 first_good
= panes
.Item(i
).window
;
1889 if (!center_found
&& first_good
)
1891 m_mgr
.GetPane(first_good
).Centre();
1897 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
1899 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
1900 if (idx
!= -1 && idx
!= m_curpage
)
1907 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
1909 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1910 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1912 int button_id
= evt
.GetInt();
1914 if (button_id
== wxAUI_BUTTON_CLOSE
)
1916 int selection
= tabs
->GetActivePage();
1918 if (selection
!= -1)
1920 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
1922 if (close_wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1928 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
1929 DeletePage(main_idx
);