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 textx
, texty
;
203 // if the caption is empty, measure some temporary text
204 wxString caption
= caption_text
;
205 if (caption_text
.empty())
208 dc
->SetFont(m_selected_font
);
209 dc
->GetTextExtent(caption
, &selected_textx
, &selected_texty
);
211 dc
->SetFont(m_normal_font
);
212 dc
->GetTextExtent(caption
, &normal_textx
, &normal_texty
);
214 // figure out the size of the tab
215 wxSize tab_size
= GetTabSize(dc
, caption
, active
, x_extent
);
217 wxCoord tab_height
= tab_size
.y
;
218 wxCoord tab_width
= tab_size
.x
;
219 wxCoord tab_x
= in_rect
.x
;
220 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
222 // select pen, brush and font for the tab to be drawn
226 dc
->SetPen(m_selected_bkpen
);
227 dc
->SetBrush(m_selected_bkbrush
);
228 dc
->SetFont(m_selected_font
);
229 textx
= selected_textx
;
230 texty
= selected_texty
;
234 dc
->SetPen(m_normal_bkpen
);
235 dc
->SetBrush(m_normal_bkbrush
);
236 dc
->SetFont(m_normal_font
);
237 textx
= normal_textx
;
238 texty
= normal_texty
;
246 points
[0].y
= tab_y
+ tab_height
- 1;
247 points
[1].x
= tab_x
+ tab_height
- 3;
248 points
[1].y
= tab_y
+ 2;
249 points
[2].x
= tab_x
+ tab_height
+ 3;
251 points
[3].x
= tab_x
+ tab_width
- 2;
253 points
[4].x
= tab_x
+ tab_width
;
254 points
[4].y
= tab_y
+ 2;
255 points
[5].x
= tab_x
+ tab_width
;
256 points
[5].y
= tab_y
+ tab_height
- 1;
257 points
[6] = points
[0];
260 dc
->DrawPolygon(6, points
);
262 dc
->SetPen(*wxGREY_PEN
);
264 //dc->DrawLines(active ? 6 : 7, points);
265 dc
->DrawLines(7, points
);
269 dc
->DrawText(caption
,
270 tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2),
271 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
273 *out_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
277 wxSize
wxDefaultTabArt::GetTabSize(wxDC
* dc
,
278 const wxString
& caption
,
279 bool WXUNUSED(active
),
282 wxCoord measured_textx
, measured_texty
;
284 dc
->SetFont(m_measuring_font
);
285 dc
->GetTextExtent(caption
, &measured_textx
, &measured_texty
);
287 wxCoord tab_height
= measured_texty
+ 4;
288 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
290 *x_extent
= tab_width
- (tab_height
/2) - 1;
292 return wxSize(tab_width
, tab_height
);
296 void wxDefaultTabArt::DrawButton(
298 const wxRect
& in_rect
,
302 const wxBitmap
& bitmap_override
,
308 if (bitmap_override
.IsOk())
310 bmp
= bitmap_override
;
316 case wxAUI_BUTTON_CLOSE
:
317 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
318 bmp
= m_disabled_close_bmp
;
320 bmp
= m_active_close_bmp
;
322 case wxAUI_BUTTON_LEFT
:
323 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
324 bmp
= m_disabled_left_bmp
;
326 bmp
= m_active_left_bmp
;
328 case wxAUI_BUTTON_RIGHT
:
329 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
330 bmp
= m_disabled_right_bmp
;
332 bmp
= m_active_right_bmp
;
342 if (orientation
== wxLEFT
)
344 rect
.SetX(in_rect
.x
);
345 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
346 rect
.SetWidth(bmp
.GetWidth());
347 rect
.SetHeight(bmp
.GetHeight());
351 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
352 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
353 bmp
.GetWidth(), bmp
.GetHeight());
357 DrawButtonS(*dc
, rect
, bmp
, *wxWHITE
, button_state
);
364 int wxDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
367 dc
.SetFont(m_measuring_font
);
369 wxSize s
= GetTabSize(&dc
, wxT("ABCDEFGHIj"), true, &x_ext
);
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 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1311 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1312 m_dummy_wnd
->SetSize(200, 200);
1313 m_dummy_wnd
->Show(false);
1315 m_mgr
.SetManagedWindow(this);
1317 m_mgr
.AddPane(m_dummy_wnd
,
1318 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1323 wxAuiMultiNotebook::~wxAuiMultiNotebook()
1328 void wxAuiMultiNotebook::SetArtProvider(wxTabArt
* art
)
1330 m_tabs
.SetArtProvider(art
);
1333 wxTabArt
* wxAuiMultiNotebook::GetArtProvider()
1335 return m_tabs
.GetArtProvider();
1338 bool wxAuiMultiNotebook::AddPage(wxWindow
* page
,
1339 const wxString
& caption
,
1341 const wxBitmap
& bitmap
)
1343 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1346 bool wxAuiMultiNotebook::InsertPage(size_t page_idx
,
1348 const wxString
& caption
,
1350 const wxBitmap
& bitmap
)
1352 wxAuiNotebookPage info
;
1354 info
.caption
= caption
;
1355 info
.bitmap
= bitmap
;
1356 info
.active
= false;
1358 // if there are currently no tabs, the first added
1359 // tab must be active
1360 if (m_tabs
.GetPageCount() == 0)
1363 m_tabs
.InsertPage(page
, info
, page_idx
);
1365 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1366 if (page_idx
>= active_tabctrl
->GetPageCount())
1367 active_tabctrl
->AddPage(page
, info
);
1369 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1372 active_tabctrl
->DoShowHide();
1376 int idx
= m_tabs
.GetIdxFromWindow(page
);
1377 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
1386 // DeletePage() removes a tab from the multi-notebook,
1387 // and destroys the window as well
1388 bool wxAuiMultiNotebook::DeletePage(size_t page_idx
)
1390 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1391 wxWindow
* new_active
= NULL
;
1393 // find out which onscreen tab ctrl owns this tab
1396 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1399 // find a new page and set it as active
1400 int new_idx
= ctrl_idx
+1;
1401 if (new_idx
>= (int)ctrl
->GetPageCount())
1402 new_idx
= ctrl_idx
-1;
1404 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1406 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1410 // set the active page to the first page that
1411 // isn't the one being deleted
1412 size_t i
, page_count
= m_tabs
.GetPageCount();
1413 for (i
= 0; i
< page_count
; ++i
)
1415 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1418 new_active
= m_tabs
.GetWindowFromIdx(i
);
1424 // remove the tab from main catalog
1425 if (!m_tabs
.RemovePage(wnd
))
1428 // remove the tab from the onscreen tab ctrl
1429 ctrl
->RemovePage(wnd
);
1431 // actually destroy the window now
1432 if (wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1434 // delete the child frame with pending delete, as is
1435 // customary with frame windows
1436 if (!wxPendingDelete
.Member(wnd
))
1437 wxPendingDelete
.Append(wnd
);
1444 RemoveEmptyTabFrames();
1446 // set new active pane
1450 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1458 // RemovePage() removes a tab from the multi-notebook,
1459 // but does not destroy the window
1460 bool wxAuiMultiNotebook::RemovePage(size_t page_idx
)
1462 // remove the tab from our own catalog
1463 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1464 if (!m_tabs
.RemovePage(wnd
))
1467 // remove the tab from the onscreen tab ctrl
1470 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1472 ctrl
->RemovePage(wnd
);
1479 // SetPageText() changes the tab caption of the specified page
1480 bool wxAuiMultiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1482 if (page_idx
>= m_tabs
.GetPageCount())
1485 // update our own tab catalog
1486 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1487 page_info
.caption
= text
;
1489 // update what's on screen
1492 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1494 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1495 info
.caption
= text
;
1503 // GetSelection() returns the index of the currently active page
1504 int wxAuiMultiNotebook::GetSelection() const
1509 // SetSelection() sets the currently active page
1510 size_t wxAuiMultiNotebook::SetSelection(size_t new_page
)
1512 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1516 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1517 evt
.SetSelection(new_page
);
1518 evt
.SetOldSelection(m_curpage
);
1519 evt
.SetEventObject(this);
1520 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1522 // program allows the page change
1523 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1524 (void)GetEventHandler()->ProcessEvent(evt
);
1530 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1532 m_tabs
.SetActivePage(wnd
);
1534 ctrl
->SetActivePage(ctrl_idx
);
1538 int old_curpage
= m_curpage
;
1539 m_curpage
= new_page
;
1543 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1544 size_t i
, pane_count
= all_panes
.GetCount();
1545 for (i
= 0; i
< pane_count
; ++i
)
1547 wxPaneInfo
& pane
= all_panes
.Item(i
);
1548 if (pane
.name
== wxT("dummy"))
1550 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1551 if (tabctrl
!= ctrl
)
1552 tabctrl
->SetSelectedFont(m_normal_font
);
1554 tabctrl
->SetSelectedFont(m_selected_font
);
1567 // GetPageCount() returns the total number of
1568 // pages managed by the multi-notebook
1569 size_t wxAuiMultiNotebook::GetPageCount() const
1571 return m_tabs
.GetPageCount();
1574 // GetPage() returns the wxWindow pointer of the
1576 wxWindow
* wxAuiMultiNotebook::GetPage(size_t page_idx
) const
1578 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1580 return m_tabs
.GetWindowFromIdx(page_idx
);
1583 // DoSizing() performs all sizing operations in each tab control
1584 void wxAuiMultiNotebook::DoSizing()
1586 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1587 size_t i
, pane_count
= all_panes
.GetCount();
1588 for (i
= 0; i
< pane_count
; ++i
)
1590 if (all_panes
.Item(i
).name
== wxT("dummy"))
1593 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1594 tabframe
->DoSizing();
1598 // GetActiveTabCtrl() returns the active tab control. It is
1599 // called to determine which control gets new windows being added
1600 wxAuiTabCtrl
* wxAuiMultiNotebook::GetActiveTabCtrl()
1602 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1607 // find the tab ctrl with the current page
1608 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1615 // no current page, just find the first tab ctrl
1616 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1617 size_t i
, pane_count
= all_panes
.GetCount();
1618 for (i
= 0; i
< pane_count
; ++i
)
1620 if (all_panes
.Item(i
).name
== wxT("dummy"))
1623 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1624 return tabframe
->m_tabs
;
1627 // If there is no tabframe at all, create one
1628 wxTabFrame
* tabframe
= new wxTabFrame
;
1629 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1630 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1635 m_mgr
.AddPane(tabframe
,
1636 wxPaneInfo().Center().CaptionVisible(false));
1640 return tabframe
->m_tabs
;
1643 // FindTab() finds the tab control that currently contains the window as well
1644 // as the index of the window in the tab control. It returns true if the
1645 // window was found, otherwise false.
1646 bool wxAuiMultiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1648 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1649 size_t i
, pane_count
= all_panes
.GetCount();
1650 for (i
= 0; i
< pane_count
; ++i
)
1652 if (all_panes
.Item(i
).name
== wxT("dummy"))
1655 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1657 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1660 *ctrl
= tabframe
->m_tabs
;
1670 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent
&)
1674 void wxAuiMultiNotebook::OnSize(wxSizeEvent
&)
1678 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1680 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1682 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1683 wxASSERT(ctrl
!= NULL
);
1685 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1686 wxASSERT(wnd
!= NULL
);
1688 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1689 wxASSERT(idx
!= -1);
1694 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1698 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1700 wxPoint screen_pt
= ::wxGetMousePosition();
1701 wxPoint client_pt
= ScreenToClient(screen_pt
);
1704 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1706 wxAuiTabCtrl
* tab_ctrl
= GetTabCtrlFromPoint(client_pt
);
1707 if (tab_ctrl
== src_tabs
)
1709 // inner-tabctrl dragging is not yet implemented
1716 wxRect hint_rect
= tab_ctrl
->GetRect();
1717 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1718 m_mgr
.ShowHint(hint_rect
);
1722 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1728 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1730 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1735 // get the mouse position, which will be used to determine the drop point
1736 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1737 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1740 // the src tab control is the control that fired this event
1741 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1742 wxAuiTabCtrl
* dest_tabs
= NULL
;
1745 // If the pointer is in an existing tab frame, do a tab insert
1746 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1747 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1750 dest_tabs
= tab_frame
->m_tabs
;
1752 if (dest_tabs
== src_tabs
)
1757 // If there is no tabframe at all, create one
1758 wxTabFrame
* new_tabs
= new wxTabFrame
;
1759 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1760 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1765 m_mgr
.AddPane(new_tabs
,
1766 wxPaneInfo().Bottom().CaptionVisible(false),
1769 dest_tabs
= new_tabs
->m_tabs
;
1774 // remove the page from the source tabs
1775 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
1776 page_info
.active
= false;
1777 src_tabs
->RemovePage(page_info
.window
);
1778 if (src_tabs
->GetPageCount() > 0)
1780 src_tabs
->SetActivePage((size_t)0);
1781 src_tabs
->DoShowHide();
1782 src_tabs
->Refresh();
1787 // add the page to the destination tabs
1788 dest_tabs
->AddPage(page_info
.window
, page_info
);
1790 if (src_tabs
->GetPageCount() == 0)
1792 RemoveEmptyTabFrames();
1796 dest_tabs
->DoShowHide();
1797 dest_tabs
->Refresh();
1799 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
1802 wxAuiTabCtrl
* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
1804 // if we've just removed the last tab from the source
1805 // tab set, the remove the tab control completely
1806 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1807 size_t i
, pane_count
= all_panes
.GetCount();
1808 for (i
= 0; i
< pane_count
; ++i
)
1810 if (all_panes
.Item(i
).name
== wxT("dummy"))
1813 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1814 if (tabframe
->m_tab_rect
.Contains(pt
))
1815 return tabframe
->m_tabs
;
1821 wxWindow
* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
1823 // if we've just removed the last tab from the source
1824 // tab set, the remove the tab control completely
1825 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1826 size_t i
, pane_count
= all_panes
.GetCount();
1827 for (i
= 0; i
< pane_count
; ++i
)
1829 if (all_panes
.Item(i
).name
== wxT("dummy"))
1832 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1833 if (tabframe
->m_tabs
== tab_ctrl
)
1842 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1844 // if we've just removed the last tab from the source
1845 // tab set, the remove the tab control completely
1846 wxPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
1847 size_t i
, pane_count
= all_panes
.GetCount();
1848 for (i
= 0; i
< pane_count
; ++i
)
1850 if (all_panes
.Item(i
).name
== wxT("dummy"))
1853 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1854 if (tab_frame
->m_tabs
->GetPageCount() == 0)
1856 m_mgr
.DetachPane(tab_frame
);
1858 // use pending delete because sometimes during
1859 // window closing, refreshs are pending
1860 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
1861 wxPendingDelete
.Append(tab_frame
->m_tabs
);
1862 //tab_frame->m_tabs->Destroy();
1869 // check to see if there is still a center pane;
1870 // if there isn't, make a frame the center pane
1871 wxPaneInfoArray panes
= m_mgr
.GetAllPanes();
1872 pane_count
= panes
.GetCount();
1873 wxWindow
* first_good
= NULL
;
1874 bool center_found
= false;
1875 for (i
= 0; i
< pane_count
; ++i
)
1877 if (panes
.Item(i
).name
== wxT("dummy"))
1879 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
1880 center_found
= true;
1882 first_good
= panes
.Item(i
).window
;
1885 if (!center_found
&& first_good
)
1887 m_mgr
.GetPane(first_good
).Centre();
1893 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
1895 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
1896 if (idx
!= -1 && idx
!= m_curpage
)
1903 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
1905 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1906 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1908 int button_id
= evt
.GetInt();
1910 if (button_id
== wxAUI_BUTTON_CLOSE
)
1912 int selection
= tabs
->GetActivePage();
1914 if (selection
!= -1)
1916 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
1918 if (close_wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1924 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
1925 DeletePage(main_idx
);