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::MovePage(wxWindow
* page
,
483 int idx
= GetIdxFromWindow(page
);
487 // get page entry, make a copy of it
488 wxAuiNotebookPage p
= GetPage(idx
);
490 // remove old page entry
493 // insert page where it should be
494 InsertPage(page
, p
, new_idx
);
499 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
501 size_t i
, page_count
= m_pages
.GetCount();
502 for (i
= 0; i
< page_count
; ++i
)
504 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
505 if (page
.window
== wnd
)
515 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
519 size_t i
, page_count
= m_pages
.GetCount();
520 for (i
= 0; i
< page_count
; ++i
)
522 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
523 if (page
.window
== wnd
)
537 void wxAuiTabContainer::SetNoneActive()
539 size_t i
, page_count
= m_pages
.GetCount();
540 for (i
= 0; i
< page_count
; ++i
)
542 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
547 bool wxAuiTabContainer::SetActivePage(size_t page
)
549 if (page
>= m_pages
.GetCount())
552 return SetActivePage(m_pages
.Item(page
).window
);
555 int wxAuiTabContainer::GetActivePage() const
557 size_t i
, page_count
= m_pages
.GetCount();
558 for (i
= 0; i
< page_count
; ++i
)
560 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
568 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
570 if (idx
>= m_pages
.GetCount())
573 return m_pages
[idx
].window
;
576 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
578 size_t i
, page_count
= m_pages
.GetCount();
579 for (i
= 0; i
< page_count
; ++i
)
581 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
582 if (page
.window
== wnd
)
588 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
590 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
595 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
600 size_t wxAuiTabContainer::GetPageCount() const
602 return m_pages
.GetCount();
605 void wxAuiTabContainer::AddButton(int id
,
607 const wxBitmap
& normal_bitmap
,
608 const wxBitmap
& disabled_bitmap
)
610 wxAuiTabContainerButton button
;
612 button
.bitmap
= normal_bitmap
;
613 button
.dis_bitmap
= disabled_bitmap
;
614 button
.location
= location
;
615 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
617 m_buttons
.Add(button
);
620 size_t wxAuiTabContainer::GetTabOffset() const
625 void wxAuiTabContainer::SetTabOffset(size_t offset
)
627 m_tab_offset
= offset
;
630 // Render() renders the tab catalog to the specified DC
631 // It is a virtual function and can be overridden to
632 // provide custom drawing capabilities
633 void wxAuiTabContainer::Render(wxDC
* raw_dc
)
638 size_t page_count
= m_pages
.GetCount();
639 size_t button_count
= m_buttons
.GetCount();
641 // create off-screen bitmap
642 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
643 dc
.SelectObject(bmp
);
646 // find out if size of tabs is larger than can be
647 // afforded on screen
649 int visible_width
= 0;
650 for (i
= 0; i
< page_count
; ++i
)
652 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
654 wxSize size
= m_art
->GetTabSize(&dc
, page
.caption
, page
.active
, &x_extent
);
656 if (i
+1 < page_count
)
657 total_width
+= x_extent
;
659 total_width
+= size
.x
;
661 if (i
>= m_tab_offset
)
663 if (i
+1 < page_count
)
664 visible_width
+= x_extent
;
666 visible_width
+= size
.x
;
670 if (total_width
> m_rect
.GetWidth() - 20 || m_tab_offset
!= 0)
672 // show left/right buttons
673 for (i
= 0; i
< button_count
; ++i
)
675 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
676 if (button
.id
== wxAUI_BUTTON_LEFT
||
677 button
.id
== wxAUI_BUTTON_RIGHT
)
679 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
685 // hide left/right buttons
686 for (i
= 0; i
< button_count
; ++i
)
688 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
689 if (button
.id
== wxAUI_BUTTON_LEFT
||
690 button
.id
== wxAUI_BUTTON_RIGHT
)
692 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
697 // determine whether left button should be enabled
698 for (i
= 0; i
< button_count
; ++i
)
700 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
701 if (button
.id
== wxAUI_BUTTON_LEFT
)
703 if (m_tab_offset
== 0)
704 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
706 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
708 if (button
.id
== wxAUI_BUTTON_RIGHT
)
710 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
711 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
713 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
720 m_art
->DrawBackground(&dc
, m_rect
);
723 int left_buttons_width
= 0;
724 int right_buttons_width
= 0;
728 // draw the buttons on the right side
729 offset
= m_rect
.x
+ m_rect
.width
;
730 for (i
= 0; i
< button_count
; ++i
)
732 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
734 if (button
.location
!= wxRIGHT
)
736 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
739 wxRect button_rect
= m_rect
;
741 button_rect
.SetWidth(offset
);
743 m_art
->DrawButton(&dc
,
751 offset
-= button
.rect
.GetWidth();
752 right_buttons_width
+= button
.rect
.GetWidth();
759 // draw the buttons on the left side
761 for (i
= 0; i
< button_count
; ++i
)
763 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
765 if (button
.location
!= wxLEFT
)
767 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
770 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
772 m_art
->DrawButton(&dc
,
780 offset
+= button
.rect
.GetWidth();
781 left_buttons_width
+= button
.rect
.GetWidth();
784 offset
= left_buttons_width
;
787 dc
.SetClippingRegion(left_buttons_width
, 0,
788 m_rect
.GetWidth() - right_buttons_width
- left_buttons_width
- 2,
794 int active_offset
= 0;
797 wxRect rect
= m_rect
;
800 rect
.height
= m_rect
.height
;
802 for (i
= m_tab_offset
; i
< page_count
; ++i
)
804 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
818 active_offset
= offset
;
824 // draw the active tab again so it stands in the foreground
825 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
827 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
829 rect
.x
= active_offset
;
838 dc
.DestroyClippingRegion();
840 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
841 m_rect
.GetWidth(), m_rect
.GetHeight(),
846 // TabHitTest() tests if a tab was hit, passing the window pointer
847 // back if that condition was fulfilled. The function returns
848 // true if a tab was hit, otherwise false
849 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
851 if (!m_rect
.Contains(x
,y
))
854 if (ButtonHitTest(x
, y
, NULL
))
857 size_t i
, page_count
= m_pages
.GetCount();
859 for (i
= m_tab_offset
; i
< page_count
; ++i
)
861 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
862 if (page
.rect
.Contains(x
,y
))
873 // ButtonHitTest() tests if a button was hit. The function returns
874 // true if a button was hit, otherwise false
875 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
876 wxAuiTabContainerButton
** hit
) const
878 if (!m_rect
.Contains(x
,y
))
881 size_t i
, button_count
= m_buttons
.GetCount();
883 for (i
= 0; i
< button_count
; ++i
)
885 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
886 if (button
.rect
.Contains(x
,y
))
899 // the utility function ShowWnd() is the same as show,
900 // except it handles wxTabMDIChildFrame windows as well,
901 // as the Show() method on this class is "unplugged"
902 static void ShowWnd(wxWindow
* wnd
, bool show
)
904 if (wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
906 wxTabMDIChildFrame
* cf
= (wxTabMDIChildFrame
*)wnd
;
916 // DoShowHide() this function shows the active window, then
917 // hides all of the other windows (in that order)
918 void wxAuiTabContainer::DoShowHide()
920 wxAuiNotebookPageArray
& pages
= GetPages();
921 size_t i
, page_count
= pages
.GetCount();
923 // show new active page first
924 for (i
= 0; i
< page_count
; ++i
)
926 wxAuiNotebookPage
& page
= pages
.Item(i
);
929 ShowWnd(page
.window
, true);
934 // hide all other pages
935 for (i
= 0; i
< page_count
; ++i
)
937 wxAuiNotebookPage
& page
= pages
.Item(i
);
938 ShowWnd(page
.window
, page
.active
);
947 // -- wxAuiTabCtrl class implementation --
951 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
952 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
953 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
954 EVT_SIZE(wxAuiTabCtrl::OnSize
)
955 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
956 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
957 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
958 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
959 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
963 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
967 long style
) : wxControl(parent
, id
, pos
, size
, style
)
969 m_click_pt
= wxDefaultPosition
;
970 m_is_dragging
= false;
971 m_hover_button
= NULL
;
974 wxAuiTabCtrl::~wxAuiTabCtrl()
978 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
982 dc
.SetFont(GetFont());
984 if (GetPageCount() > 0)
988 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
992 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
994 wxSize s
= evt
.GetSize();
995 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
999 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1002 m_click_pt
= wxDefaultPosition
;
1003 m_is_dragging
= false;
1007 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1009 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1010 e
.SetSelection(GetIdxFromWindow(wnd
));
1011 e
.SetOldSelection(GetActivePage());
1012 e
.SetEventObject(this);
1013 GetEventHandler()->ProcessEvent(e
);
1015 m_click_pt
.x
= evt
.m_x
;
1016 m_click_pt
.y
= evt
.m_y
;
1022 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1028 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1030 if (GetCapture() == this)
1035 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1036 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1037 evt
.SetOldSelection(evt
.GetSelection());
1038 evt
.SetEventObject(this);
1039 GetEventHandler()->ProcessEvent(evt
);
1045 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1049 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1051 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1052 evt
.SetInt(m_hover_button
->id
);
1053 evt
.SetEventObject(this);
1054 GetEventHandler()->ProcessEvent(evt
);
1058 m_click_pt
= wxDefaultPosition
;
1059 m_is_dragging
= false;
1063 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1065 wxPoint pos
= evt
.GetPosition();
1067 // check if the mouse is hovering above a button
1068 wxAuiTabContainerButton
* button
;
1069 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1071 if (m_hover_button
&& button
!= m_hover_button
)
1073 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1074 m_hover_button
= NULL
;
1079 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1081 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1084 m_hover_button
= button
;
1092 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1093 m_hover_button
= NULL
;
1100 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1105 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1106 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1107 evt
.SetOldSelection(evt
.GetSelection());
1108 evt
.SetEventObject(this);
1109 GetEventHandler()->ProcessEvent(evt
);
1114 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1115 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1117 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1118 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1120 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1121 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1122 evt
.SetOldSelection(evt
.GetSelection());
1123 evt
.SetEventObject(this);
1124 GetEventHandler()->ProcessEvent(evt
);
1126 m_is_dragging
= true;
1130 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1134 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1135 m_hover_button
= NULL
;
1141 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1143 int button
= event
.GetInt();
1145 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
1147 if (button
== wxAUI_BUTTON_LEFT
)
1149 if (GetTabOffset() > 0)
1151 SetTabOffset(GetTabOffset()-1);
1158 SetTabOffset(GetTabOffset()+1);
1169 // wxTabFrame is an interesting case. It's important that all child pages
1170 // of the multi-notebook control are all actually children of that control
1171 // (and not grandchildren). wxTabFrame facilitates this. There is one
1172 // instance of wxTabFrame for each tab control inside the multi-notebook.
1173 // It's important to know that wxTabFrame is not a real window, but it merely
1174 // used to capture the dimensions/positioning of the internal tab control and
1175 // it's managed page windows
1177 class wxTabFrame
: public wxWindow
1184 m_rect
= wxRect(0,0,200,200);
1185 m_tab_ctrl_height
= 20;
1188 void SetTabCtrlHeight(int h
)
1190 m_tab_ctrl_height
= h
;
1193 void DoSetSize(int x
, int y
,
1194 int width
, int height
,
1195 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
1197 m_rect
= wxRect(x
, y
, width
, height
);
1201 void DoGetClientSize(int* x
, int* y
) const
1207 bool Show( bool WXUNUSED(show
= true) ) { return false; }
1214 int tab_height
= wxMin(m_rect
.height
, m_tab_ctrl_height
);
1215 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1216 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, tab_height
);
1217 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, tab_height
));
1221 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
1222 size_t i
, page_count
= pages
.GetCount();
1224 for (i
= 0; i
< page_count
; ++i
)
1226 wxAuiNotebookPage
& page
= pages
.Item(i
);
1227 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+tab_height
, m_rect
.width
, m_rect
.height
-tab_height
);
1229 if (page
.window
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1231 wxTabMDIChildFrame
* wnd
= (wxTabMDIChildFrame
*)page
.window
;
1232 wnd
->ApplyMDIChildFrameRect();
1237 void DoGetSize(int* x
, int* y
) const
1240 *x
= m_rect
.GetWidth();
1242 *y
= m_rect
.GetHeight();
1254 wxAuiTabCtrl
* m_tabs
;
1255 int m_tab_ctrl_height
;
1262 // -- wxAuiMultiNotebook class implementation --
1264 BEGIN_EVENT_TABLE(wxAuiMultiNotebook
, wxControl
)
1265 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
1266 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
1267 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
1268 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus
)
1269 EVT_COMMAND_RANGE(10000, 10100,
1270 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
1271 wxAuiMultiNotebook::OnTabClicked
)
1272 EVT_COMMAND_RANGE(10000, 10100,
1273 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
1274 wxAuiMultiNotebook::OnTabBeginDrag
)
1275 EVT_COMMAND_RANGE(10000, 10100,
1276 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
1277 wxAuiMultiNotebook::OnTabEndDrag
)
1278 EVT_COMMAND_RANGE(10000, 10100,
1279 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
1280 wxAuiMultiNotebook::OnTabDragMotion
)
1281 EVT_COMMAND_RANGE(10000, 10100,
1282 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
1283 wxAuiMultiNotebook::OnTabButton
)
1286 wxAuiMultiNotebook::wxAuiMultiNotebook()
1289 m_tab_id_counter
= 10000;
1291 m_tab_ctrl_height
= 20;
1294 wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow
*parent
,
1298 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1303 bool wxAuiMultiNotebook::Create(wxWindow
* parent
,
1309 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
1317 // InitNotebook() contains common initialization
1318 // code called by all constructors
1319 void wxAuiMultiNotebook::InitNotebook()
1322 m_tab_id_counter
= 10000;
1324 m_tab_ctrl_height
= 20;
1326 m_normal_font
= *wxNORMAL_FONT
;
1327 m_selected_font
= *wxNORMAL_FONT
;
1328 m_selected_font
.SetWeight(wxBOLD
);
1330 // choose a default for the tab height
1331 m_tab_ctrl_height
= m_tabs
.GetArtProvider()->GetBestTabCtrlSize(this);
1333 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
1334 m_dummy_wnd
->SetSize(200, 200);
1335 m_dummy_wnd
->Show(false);
1337 m_mgr
.SetManagedWindow(this);
1339 m_mgr
.AddPane(m_dummy_wnd
,
1340 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
1345 wxAuiMultiNotebook::~wxAuiMultiNotebook()
1350 void wxAuiMultiNotebook::SetArtProvider(wxTabArt
* art
)
1352 m_tabs
.SetArtProvider(art
);
1355 wxTabArt
* wxAuiMultiNotebook::GetArtProvider()
1357 return m_tabs
.GetArtProvider();
1360 bool wxAuiMultiNotebook::AddPage(wxWindow
* page
,
1361 const wxString
& caption
,
1363 const wxBitmap
& bitmap
)
1365 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
1368 bool wxAuiMultiNotebook::InsertPage(size_t page_idx
,
1370 const wxString
& caption
,
1372 const wxBitmap
& bitmap
)
1374 wxAuiNotebookPage info
;
1376 info
.caption
= caption
;
1377 info
.bitmap
= bitmap
;
1378 info
.active
= false;
1380 // if there are currently no tabs, the first added
1381 // tab must be active
1382 if (m_tabs
.GetPageCount() == 0)
1385 m_tabs
.InsertPage(page
, info
, page_idx
);
1387 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
1388 if (page_idx
>= active_tabctrl
->GetPageCount())
1389 active_tabctrl
->AddPage(page
, info
);
1391 active_tabctrl
->InsertPage(page
, info
, page_idx
);
1394 active_tabctrl
->DoShowHide();
1398 int idx
= m_tabs
.GetIdxFromWindow(page
);
1399 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
1408 // DeletePage() removes a tab from the multi-notebook,
1409 // and destroys the window as well
1410 bool wxAuiMultiNotebook::DeletePage(size_t page_idx
)
1412 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1413 wxWindow
* new_active
= NULL
;
1415 // find out which onscreen tab ctrl owns this tab
1418 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
1421 // find a new page and set it as active
1422 int new_idx
= ctrl_idx
+1;
1423 if (new_idx
>= (int)ctrl
->GetPageCount())
1424 new_idx
= ctrl_idx
-1;
1426 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
1428 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
1432 // set the active page to the first page that
1433 // isn't the one being deleted
1434 size_t i
, page_count
= m_tabs
.GetPageCount();
1435 for (i
= 0; i
< page_count
; ++i
)
1437 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
1440 new_active
= m_tabs
.GetWindowFromIdx(i
);
1446 // remove the tab from main catalog
1447 if (!m_tabs
.RemovePage(wnd
))
1450 // remove the tab from the onscreen tab ctrl
1451 ctrl
->RemovePage(wnd
);
1453 // actually destroy the window now
1454 if (wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1456 // delete the child frame with pending delete, as is
1457 // customary with frame windows
1458 if (!wxPendingDelete
.Member(wnd
))
1459 wxPendingDelete
.Append(wnd
);
1466 RemoveEmptyTabFrames();
1468 // set new active pane
1472 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
1480 // RemovePage() removes a tab from the multi-notebook,
1481 // but does not destroy the window
1482 bool wxAuiMultiNotebook::RemovePage(size_t page_idx
)
1484 // remove the tab from our own catalog
1485 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
1486 if (!m_tabs
.RemovePage(wnd
))
1489 // remove the tab from the onscreen tab ctrl
1492 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1494 ctrl
->RemovePage(wnd
);
1501 // SetPageText() changes the tab caption of the specified page
1502 bool wxAuiMultiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
1504 if (page_idx
>= m_tabs
.GetPageCount())
1507 // update our own tab catalog
1508 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
1509 page_info
.caption
= text
;
1511 // update what's on screen
1514 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
1516 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
1517 info
.caption
= text
;
1525 // GetSelection() returns the index of the currently active page
1526 int wxAuiMultiNotebook::GetSelection() const
1531 // SetSelection() sets the currently active page
1532 size_t wxAuiMultiNotebook::SetSelection(size_t new_page
)
1534 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
1538 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1539 evt
.SetSelection(new_page
);
1540 evt
.SetOldSelection(m_curpage
);
1541 evt
.SetEventObject(this);
1542 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
1544 // program allows the page change
1545 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
1546 (void)GetEventHandler()->ProcessEvent(evt
);
1552 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
1554 m_tabs
.SetActivePage(wnd
);
1556 ctrl
->SetActivePage(ctrl_idx
);
1560 int old_curpage
= m_curpage
;
1561 m_curpage
= new_page
;
1565 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1566 size_t i
, pane_count
= all_panes
.GetCount();
1567 for (i
= 0; i
< pane_count
; ++i
)
1569 wxPaneInfo
& pane
= all_panes
.Item(i
);
1570 if (pane
.name
== wxT("dummy"))
1572 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
1573 if (tabctrl
!= ctrl
)
1574 tabctrl
->SetSelectedFont(m_normal_font
);
1576 tabctrl
->SetSelectedFont(m_selected_font
);
1589 // GetPageCount() returns the total number of
1590 // pages managed by the multi-notebook
1591 size_t wxAuiMultiNotebook::GetPageCount() const
1593 return m_tabs
.GetPageCount();
1596 // GetPage() returns the wxWindow pointer of the
1598 wxWindow
* wxAuiMultiNotebook::GetPage(size_t page_idx
) const
1600 wxASSERT(page_idx
< m_tabs
.GetPageCount());
1602 return m_tabs
.GetWindowFromIdx(page_idx
);
1605 // DoSizing() performs all sizing operations in each tab control
1606 void wxAuiMultiNotebook::DoSizing()
1608 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1609 size_t i
, pane_count
= all_panes
.GetCount();
1610 for (i
= 0; i
< pane_count
; ++i
)
1612 if (all_panes
.Item(i
).name
== wxT("dummy"))
1615 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1616 tabframe
->DoSizing();
1620 // GetActiveTabCtrl() returns the active tab control. It is
1621 // called to determine which control gets new windows being added
1622 wxAuiTabCtrl
* wxAuiMultiNotebook::GetActiveTabCtrl()
1624 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
1629 // find the tab ctrl with the current page
1630 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
1637 // no current page, just find the first tab ctrl
1638 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1639 size_t i
, pane_count
= all_panes
.GetCount();
1640 for (i
= 0; i
< pane_count
; ++i
)
1642 if (all_panes
.Item(i
).name
== wxT("dummy"))
1645 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1646 return tabframe
->m_tabs
;
1649 // If there is no tabframe at all, create one
1650 wxTabFrame
* tabframe
= new wxTabFrame
;
1651 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
1652 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
1657 m_mgr
.AddPane(tabframe
,
1658 wxPaneInfo().Center().CaptionVisible(false));
1662 return tabframe
->m_tabs
;
1665 // FindTab() finds the tab control that currently contains the window as well
1666 // as the index of the window in the tab control. It returns true if the
1667 // window was found, otherwise false.
1668 bool wxAuiMultiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
1670 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1671 size_t i
, pane_count
= all_panes
.GetCount();
1672 for (i
= 0; i
< pane_count
; ++i
)
1674 if (all_panes
.Item(i
).name
== wxT("dummy"))
1677 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1679 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
1682 *ctrl
= tabframe
->m_tabs
;
1692 void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent
&)
1696 void wxAuiMultiNotebook::OnSize(wxSizeEvent
&)
1700 void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
1702 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1704 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1705 wxASSERT(ctrl
!= NULL
);
1707 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
1708 wxASSERT(wnd
!= NULL
);
1710 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
1711 wxASSERT(idx
!= -1);
1716 void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent
&)
1721 void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
1723 wxPoint screen_pt
= ::wxGetMousePosition();
1724 wxPoint client_pt
= ScreenToClient(screen_pt
);
1727 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1729 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
1730 if (dest_tabs
== src_tabs
)
1732 // always hide the hint for inner-tabctrl drag
1735 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
1736 wxWindow
* dest_location_tab
;
1738 // this is an inner-tab drag/reposition
1739 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
1741 int src_idx
= evt
.GetSelection();
1742 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
1744 // prevent jumpy drag
1745 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
1746 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
1747 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
1749 m_last_drag_x
= pt
.x
;
1754 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
1755 dest_tabs
->MovePage(src_tab
, dest_idx
);
1756 dest_tabs
->SetActivePage((size_t)dest_idx
);
1757 dest_tabs
->DoShowHide();
1758 dest_tabs
->Refresh();
1759 m_last_drag_x
= pt
.x
;
1768 wxRect hint_rect
= dest_tabs
->GetRect();
1769 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
1770 m_mgr
.ShowHint(hint_rect
);
1774 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
1780 void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
1782 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1787 // get the mouse position, which will be used to determine the drop point
1788 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
1789 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
1792 // the src tab control is the control that fired this event
1793 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1794 wxAuiTabCtrl
* dest_tabs
= NULL
;
1797 // If the pointer is in an existing tab frame, do a tab insert
1798 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
1799 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
1802 dest_tabs
= tab_frame
->m_tabs
;
1804 if (dest_tabs
== src_tabs
)
1809 // If there is no tabframe at all, create one
1810 wxTabFrame
* new_tabs
= new wxTabFrame
;
1811 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
1812 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
1817 m_mgr
.AddPane(new_tabs
,
1818 wxPaneInfo().Bottom().CaptionVisible(false),
1821 dest_tabs
= new_tabs
->m_tabs
;
1826 // remove the page from the source tabs
1827 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
1828 page_info
.active
= false;
1829 src_tabs
->RemovePage(page_info
.window
);
1830 if (src_tabs
->GetPageCount() > 0)
1832 src_tabs
->SetActivePage((size_t)0);
1833 src_tabs
->DoShowHide();
1834 src_tabs
->Refresh();
1839 // add the page to the destination tabs
1840 dest_tabs
->AddPage(page_info
.window
, page_info
);
1842 if (src_tabs
->GetPageCount() == 0)
1844 RemoveEmptyTabFrames();
1848 dest_tabs
->DoShowHide();
1849 dest_tabs
->Refresh();
1851 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
1854 wxAuiTabCtrl
* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
1856 // if we've just removed the last tab from the source
1857 // tab set, the remove the tab control completely
1858 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1859 size_t i
, pane_count
= all_panes
.GetCount();
1860 for (i
= 0; i
< pane_count
; ++i
)
1862 if (all_panes
.Item(i
).name
== wxT("dummy"))
1865 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1866 if (tabframe
->m_tab_rect
.Contains(pt
))
1867 return tabframe
->m_tabs
;
1873 wxWindow
* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
1875 // if we've just removed the last tab from the source
1876 // tab set, the remove the tab control completely
1877 wxPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
1878 size_t i
, pane_count
= all_panes
.GetCount();
1879 for (i
= 0; i
< pane_count
; ++i
)
1881 if (all_panes
.Item(i
).name
== wxT("dummy"))
1884 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1885 if (tabframe
->m_tabs
== tab_ctrl
)
1894 void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1896 // if we've just removed the last tab from the source
1897 // tab set, the remove the tab control completely
1898 wxPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
1899 size_t i
, pane_count
= all_panes
.GetCount();
1900 for (i
= 0; i
< pane_count
; ++i
)
1902 if (all_panes
.Item(i
).name
== wxT("dummy"))
1905 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
1906 if (tab_frame
->m_tabs
->GetPageCount() == 0)
1908 m_mgr
.DetachPane(tab_frame
);
1910 // use pending delete because sometimes during
1911 // window closing, refreshs are pending
1912 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
1913 wxPendingDelete
.Append(tab_frame
->m_tabs
);
1914 //tab_frame->m_tabs->Destroy();
1921 // check to see if there is still a center pane;
1922 // if there isn't, make a frame the center pane
1923 wxPaneInfoArray panes
= m_mgr
.GetAllPanes();
1924 pane_count
= panes
.GetCount();
1925 wxWindow
* first_good
= NULL
;
1926 bool center_found
= false;
1927 for (i
= 0; i
< pane_count
; ++i
)
1929 if (panes
.Item(i
).name
== wxT("dummy"))
1931 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
1932 center_found
= true;
1934 first_good
= panes
.Item(i
).window
;
1937 if (!center_found
&& first_good
)
1939 m_mgr
.GetPane(first_good
).Centre();
1945 void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
1947 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
1948 if (idx
!= -1 && idx
!= m_curpage
)
1955 void wxAuiMultiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
1957 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
1958 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
1960 int button_id
= evt
.GetInt();
1962 if (button_id
== wxAUI_BUTTON_CLOSE
)
1964 int selection
= tabs
->GetActivePage();
1966 if (selection
!= -1)
1968 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
1970 if (close_wnd
->IsKindOf(CLASSINFO(wxTabMDIChildFrame
)))
1976 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
1977 DeletePage(main_idx
);