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"
34 #include "wx/arrimpl.cpp"
35 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
36 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
38 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
39 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
40 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
41 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
48 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
49 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
50 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
56 // This functions are here for this proof of concept
57 // and will be factored out later. See dockart.cpp
58 static wxColor
StepColour(const wxColor
& c
, int percent
)
60 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
61 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
62 (unsigned char)wxMin((g
*percent
)/100,255),
63 (unsigned char)wxMin((b
*percent
)/100,255));
66 // This functions are here for this proof of concept
67 // and will be factored out later. See dockart.cpp
68 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
69 const wxColour
& color
)
71 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
72 img
.Replace(0,0,0,123,123,123);
73 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
74 img
.SetMaskColour(123,123,123);
78 static void DrawButtons(wxDC
& dc
,
81 const wxColour
& bkcolour
,
86 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
93 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
95 dc
.SetBrush(wxBrush(StepColour(bkcolour
, 120)));
96 dc
.SetPen(wxPen(StepColour(bkcolour
, 70)));
98 // draw the background behind the button
99 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
102 // draw the button itself
103 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
106 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
108 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
115 // chops the text so that it fits within |max_size| pixels.
116 // Also adds an elipsis if necessary
118 static wxString
ChopText(wxDC
& dc
, const wxString
& text
, int max_size
)
122 // first check if the text fits with no problems
123 dc
.GetTextExtent(text
, &x
, &y
);
127 size_t i
, len
= text
.Length();
128 size_t last_good_length
= 0;
129 for (i
= 0; i
< len
; ++i
)
131 wxString s
= text
.Left(i
);
134 dc
.GetTextExtent(s
, &x
, &y
);
138 last_good_length
= i
;
141 wxString ret
= text
.Left(last_good_length
);
147 // -- GUI helper classes and functions --
149 class wxAuiCommandCapture
: public wxEvtHandler
153 wxAuiCommandCapture() { m_last_id
= 0; }
154 int GetCommandId() const { return m_last_id
; }
156 bool ProcessEvent(wxEvent
& evt
)
158 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
160 m_last_id
= evt
.GetId();
164 if (GetNextHandler())
165 return GetNextHandler()->ProcessEvent(evt
);
177 #if defined( __WXMAC__ )
178 static unsigned char close_bits
[]={
179 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
180 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
181 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
182 #elif defined( __WXGTK__)
183 static unsigned char close_bits
[]={
184 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
185 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
186 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
188 static unsigned char close_bits
[]={
189 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
190 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
191 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
194 static unsigned char left_bits
[] = {
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
196 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
199 static unsigned char right_bits
[] = {
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
201 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
204 static unsigned char list_bits
[] = {
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
214 // -- wxAuiDefaultTabArt class implementation --
216 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
218 m_normal_font
= *wxNORMAL_FONT
;
219 m_selected_font
= *wxNORMAL_FONT
;
220 m_selected_font
.SetWeight(wxBOLD
);
221 m_measuring_font
= m_selected_font
;
223 m_fixed_tab_width
= 100;
225 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
227 wxColour background_colour
= base_colour
;
228 wxColour normaltab_colour
= base_colour
;
229 wxColour selectedtab_colour
= base_colour
;
231 m_bkbrush
= wxBrush(background_colour
);
232 m_normal_bkbrush
= wxBrush(normaltab_colour
);
233 m_normal_bkpen
= wxPen(normaltab_colour
);
234 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
235 m_selected_bkpen
= wxPen(selectedtab_colour
);
238 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
239 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
241 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
242 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
244 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
245 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
247 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
248 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
253 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
257 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
259 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
262 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
267 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
270 m_fixed_tab_width
= 100;
272 int tot_width
= tab_ctrl_size
.x
;
275 m_fixed_tab_width
= tot_width
/(int)tab_count
;
279 if (m_fixed_tab_width
< 100)
280 m_fixed_tab_width
= 100;
282 if (m_fixed_tab_width
> tot_width
/2)
283 m_fixed_tab_width
= tot_width
/2;
285 if (m_fixed_tab_width
> 220)
286 m_fixed_tab_width
= 220;
290 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
291 wxWindow
* WXUNUSED(wnd
),
295 dc
.SetBrush(m_bkbrush
);
296 dc
.SetPen(*wxTRANSPARENT_PEN
);
297 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
300 dc
.SetPen(*wxGREY_PEN
);
301 dc
.DrawLine(0, rect
.GetHeight()-4, rect
.GetWidth(), rect
.GetHeight()-4);
302 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
306 // DrawTab() draws an individual tab.
309 // in_rect - rectangle the tab should be confined to
310 // caption - tab's caption
311 // active - whether or not the tab is active
312 // out_rect - actual output rectangle
313 // x_extent - the advance x; where the next tab should start
315 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
317 const wxRect
& in_rect
,
318 const wxString
& caption_text
,
320 int close_button_state
,
321 wxRect
* out_tab_rect
,
322 wxRect
* out_button_rect
,
325 wxCoord normal_textx
, normal_texty
;
326 wxCoord selected_textx
, selected_texty
;
327 wxCoord textx
, texty
;
329 // if the caption is empty, measure some temporary text
330 wxString caption
= caption_text
;
331 if (caption_text
.empty())
334 dc
.SetFont(m_selected_font
);
335 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
337 dc
.SetFont(m_normal_font
);
338 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
340 // figure out the size of the tab
341 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
343 wxCoord tab_height
= tab_size
.y
;
344 wxCoord tab_width
= tab_size
.x
;
345 wxCoord tab_x
= in_rect
.x
;
346 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
349 caption
= caption_text
;
351 dc
.SetClippingRegion(in_rect
);
355 // select pen, brush and font for the tab to be drawn
359 dc
.SetPen(m_selected_bkpen
);
360 dc
.SetBrush(m_selected_bkbrush
);
361 dc
.SetFont(m_selected_font
);
362 textx
= selected_textx
;
363 texty
= selected_texty
;
367 dc
.SetPen(m_normal_bkpen
);
368 dc
.SetBrush(m_normal_bkbrush
);
369 dc
.SetFont(m_normal_font
);
370 textx
= normal_textx
;
371 texty
= normal_texty
;
375 // -- create points that will make the tab outline --
379 points
[0].y
= tab_y
+ tab_height
- 4;
381 points
[1].y
= tab_y
+ 2;
382 points
[2].x
= tab_x
+ 2;
384 points
[3].x
= tab_x
+ tab_width
- 2;
386 points
[4].x
= tab_x
+ tab_width
;
387 points
[4].y
= tab_y
+ 2;
388 points
[5].x
= tab_x
+ tab_width
;
389 points
[5].y
= tab_y
+ tab_height
- 4;
392 // -- draw gradient background --
395 wxColour c
= m_bkbrush
.GetColour();
398 int x
, y
, last_y
= -1;
399 for (y
= points
[0].y
; y
> points
[2].y
; --y
)
401 if (y
< tab_y
+(tab_height
*3/5) && y
!= last_y
)
404 c
= StepColour(c
, 102);
408 for (x
= points
[0].x
+1; x
< points
[5].x
; ++x
)
415 // -- draw tab outline --
416 dc
.SetPen(*wxGREY_PEN
);
417 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
418 dc
.DrawPolygon(6, points
);
420 // -- there are two horizontal grey lines at the bottom of the tab control,
421 // this gets rid of the top one of those lines in the tab control --
424 wxColour c
= m_bkbrush
.GetColour();
426 dc
.DrawLine(points
[0].x
+1, points
[0].y
, points
[5].x
, points
[5].y
);
431 int close_button_width
= 0;
433 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
435 close_button_width
= m_active_close_bmp
.GetWidth();
438 text_offset
= tab_x
+ 8;
441 wxString draw_text
= ChopText(dc
,
443 tab_width
- (text_offset
-tab_x
) - close_button_width
);
446 dc
.DrawText(draw_text
,
448 (tab_y
+ tab_height
)/2 - (texty
/2));
453 // draw close button if necessary
454 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
456 wxBitmap bmp
= m_disabled_close_bmp
;
458 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
459 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
461 bmp
= m_active_close_bmp
;
464 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
465 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
468 IndentPressedBitmap(&rect
, close_button_state
);
469 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
471 *out_button_rect
= rect
;
474 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
476 dc
.DestroyClippingRegion();
479 int wxAuiDefaultTabArt::GetIndentSize()
484 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
485 wxWindow
* WXUNUSED(wnd
),
486 const wxString
& caption
,
487 bool WXUNUSED(active
),
488 int close_button_state
,
491 wxCoord measured_textx
, measured_texty
, tmp
;
493 dc
.SetFont(m_measuring_font
);
494 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
496 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
498 wxCoord tab_width
= measured_textx
+ 5;
499 wxCoord tab_height
= measured_texty
+ 10;
501 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
502 tab_width
+= m_active_close_bmp
.GetWidth() + 8;
505 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
507 tab_width
= m_fixed_tab_width
;
510 *x_extent
= tab_width
;
512 return wxSize(tab_width
, tab_height
);
516 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
517 wxWindow
* WXUNUSED(wnd
),
518 const wxRect
& in_rect
,
522 const wxBitmap
& bitmap_override
,
528 if (bitmap_override
.IsOk())
530 bmp
= bitmap_override
;
536 case wxAUI_BUTTON_CLOSE
:
537 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
538 bmp
= m_disabled_close_bmp
;
540 bmp
= m_active_close_bmp
;
542 case wxAUI_BUTTON_LEFT
:
543 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
544 bmp
= m_disabled_left_bmp
;
546 bmp
= m_active_left_bmp
;
548 case wxAUI_BUTTON_RIGHT
:
549 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
550 bmp
= m_disabled_right_bmp
;
552 bmp
= m_active_right_bmp
;
554 case wxAUI_BUTTON_WINDOWLIST
:
555 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
556 bmp
= m_disabled_windowlist_bmp
;
558 bmp
= m_active_windowlist_bmp
;
568 if (orientation
== wxLEFT
)
570 rect
.SetX(in_rect
.x
);
571 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
572 rect
.SetWidth(bmp
.GetWidth());
573 rect
.SetHeight(bmp
.GetHeight());
577 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
578 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
579 bmp
.GetWidth(), bmp
.GetHeight());
582 IndentPressedBitmap(&rect
, button_state
);
583 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
589 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
590 const wxArrayString
& items
,
595 size_t i
, count
= items
.GetCount();
596 for (i
= 0; i
< count
; ++i
)
598 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
601 if (active_idx
!= -1)
603 menuPopup
.Check(1000+active_idx
, true);
606 // find out where to put the popup menu of window
607 // items. Subtract 100 for now to center the menu
608 // a bit, until a better mechanism can be implemented
609 wxPoint pt
= ::wxGetMousePosition();
610 pt
= wnd
->ScreenToClient(pt
);
616 // find out the screen coordinate at the bottom of the tab ctrl
617 wxRect cli_rect
= wnd
->GetClientRect();
618 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
620 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
621 wnd
->PushEventHandler(cc
);
622 wnd
->PopupMenu(&menuPopup
, pt
);
623 int command
= cc
->GetCommandId();
624 wnd
->PopEventHandler(true);
632 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
635 dc
.SetFont(m_measuring_font
);
637 wxSize s
= GetTabSize(dc
,
641 wxAUI_BUTTON_STATE_HIDDEN
,
646 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
648 m_normal_font
= font
;
651 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
653 m_selected_font
= font
;
656 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
658 m_measuring_font
= font
;
662 // -- wxAuiSimpleTabArt class implementation --
664 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
666 m_normal_font
= *wxNORMAL_FONT
;
667 m_selected_font
= *wxNORMAL_FONT
;
668 m_selected_font
.SetWeight(wxBOLD
);
669 m_measuring_font
= m_selected_font
;
672 m_fixed_tab_width
= 100;
674 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
676 wxColour background_colour
= StepColour(base_colour
, 95);
677 wxColour normaltab_colour
= base_colour
;
678 wxColour selectedtab_colour
= *wxWHITE
;
680 m_bkbrush
= wxBrush(background_colour
);
681 m_normal_bkbrush
= wxBrush(normaltab_colour
);
682 m_normal_bkpen
= wxPen(normaltab_colour
);
683 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
684 m_selected_bkpen
= wxPen(selectedtab_colour
);
686 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
687 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
689 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
690 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
692 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
693 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
695 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
696 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
700 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
704 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
706 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
710 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
715 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
718 m_fixed_tab_width
= 100;
720 int tot_width
= tab_ctrl_size
.x
;
723 m_fixed_tab_width
= tot_width
/(int)tab_count
;
727 if (m_fixed_tab_width
< 100)
728 m_fixed_tab_width
= 100;
730 if (m_fixed_tab_width
> tot_width
/2)
731 m_fixed_tab_width
= tot_width
/2;
733 if (m_fixed_tab_width
> 220)
734 m_fixed_tab_width
= 220;
737 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
738 wxWindow
* WXUNUSED(wnd
),
742 dc
.SetBrush(m_bkbrush
);
743 dc
.SetPen(*wxTRANSPARENT_PEN
);
744 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
747 dc
.SetPen(*wxGREY_PEN
);
748 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
752 // DrawTab() draws an individual tab.
755 // in_rect - rectangle the tab should be confined to
756 // caption - tab's caption
757 // active - whether or not the tab is active
758 // out_rect - actual output rectangle
759 // x_extent - the advance x; where the next tab should start
761 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
763 const wxRect
& in_rect
,
764 const wxString
& caption_text
,
766 int close_button_state
,
767 wxRect
* out_tab_rect
,
768 wxRect
* out_button_rect
,
771 wxCoord normal_textx
, normal_texty
;
772 wxCoord selected_textx
, selected_texty
;
773 wxCoord textx
, texty
;
775 // if the caption is empty, measure some temporary text
776 wxString caption
= caption_text
;
777 if (caption_text
.empty())
780 dc
.SetFont(m_selected_font
);
781 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
783 dc
.SetFont(m_normal_font
);
784 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
786 // figure out the size of the tab
787 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
789 wxCoord tab_height
= tab_size
.y
;
790 wxCoord tab_width
= tab_size
.x
;
791 wxCoord tab_x
= in_rect
.x
;
792 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
794 caption
= caption_text
;
796 // select pen, brush and font for the tab to be drawn
800 dc
.SetPen(m_selected_bkpen
);
801 dc
.SetBrush(m_selected_bkbrush
);
802 dc
.SetFont(m_selected_font
);
803 textx
= selected_textx
;
804 texty
= selected_texty
;
808 dc
.SetPen(m_normal_bkpen
);
809 dc
.SetBrush(m_normal_bkbrush
);
810 dc
.SetFont(m_normal_font
);
811 textx
= normal_textx
;
812 texty
= normal_texty
;
820 points
[0].y
= tab_y
+ tab_height
- 1;
821 points
[1].x
= tab_x
+ tab_height
- 3;
822 points
[1].y
= tab_y
+ 2;
823 points
[2].x
= tab_x
+ tab_height
+ 3;
825 points
[3].x
= tab_x
+ tab_width
- 2;
827 points
[4].x
= tab_x
+ tab_width
;
828 points
[4].y
= tab_y
+ 2;
829 points
[5].x
= tab_x
+ tab_width
;
830 points
[5].y
= tab_y
+ tab_height
- 1;
831 points
[6] = points
[0];
833 dc
.SetClippingRegion(in_rect
);
835 dc
.DrawPolygon(6, points
);
837 dc
.SetPen(*wxGREY_PEN
);
839 //dc.DrawLines(active ? 6 : 7, points);
840 dc
.DrawLines(7, points
);
845 int close_button_width
= 0;
846 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
848 close_button_width
= m_active_close_bmp
.GetWidth();
849 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
853 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
856 // set minimum text offset
857 if (text_offset
< tab_x
+ tab_height
)
858 text_offset
= tab_x
+ tab_height
;
860 // chop text if necessary
861 wxString draw_text
= ChopText(dc
,
863 tab_width
- (text_offset
-tab_x
) - close_button_width
);
866 dc
.DrawText(draw_text
,
868 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
871 // draw close button if necessary
872 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
876 bmp
= m_active_close_bmp
;
878 bmp
= m_disabled_close_bmp
;
880 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
881 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
884 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
886 *out_button_rect
= rect
;
890 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
892 dc
.DestroyClippingRegion();
895 int wxAuiSimpleTabArt::GetIndentSize()
900 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
901 wxWindow
* WXUNUSED(wnd
),
902 const wxString
& caption
,
903 bool WXUNUSED(active
),
904 int close_button_state
,
907 wxCoord measured_textx
, measured_texty
;
909 dc
.SetFont(m_measuring_font
);
910 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
912 wxCoord tab_height
= measured_texty
+ 4;
913 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
915 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
916 tab_width
+= m_active_close_bmp
.GetWidth();
918 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
920 tab_width
= m_fixed_tab_width
;
923 *x_extent
= tab_width
- (tab_height
/2) - 1;
925 return wxSize(tab_width
, tab_height
);
929 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
930 wxWindow
* WXUNUSED(wnd
),
931 const wxRect
& in_rect
,
935 const wxBitmap
& bitmap_override
,
941 if (bitmap_override
.IsOk())
943 bmp
= bitmap_override
;
949 case wxAUI_BUTTON_CLOSE
:
950 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
951 bmp
= m_disabled_close_bmp
;
953 bmp
= m_active_close_bmp
;
955 case wxAUI_BUTTON_LEFT
:
956 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
957 bmp
= m_disabled_left_bmp
;
959 bmp
= m_active_left_bmp
;
961 case wxAUI_BUTTON_RIGHT
:
962 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
963 bmp
= m_disabled_right_bmp
;
965 bmp
= m_active_right_bmp
;
967 case wxAUI_BUTTON_WINDOWLIST
:
968 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
969 bmp
= m_disabled_windowlist_bmp
;
971 bmp
= m_active_windowlist_bmp
;
981 if (orientation
== wxLEFT
)
983 rect
.SetX(in_rect
.x
);
984 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
985 rect
.SetWidth(bmp
.GetWidth());
986 rect
.SetHeight(bmp
.GetHeight());
990 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
991 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
992 bmp
.GetWidth(), bmp
.GetHeight());
996 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1002 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1003 const wxArrayString
& items
,
1008 size_t i
, count
= items
.GetCount();
1009 for (i
= 0; i
< count
; ++i
)
1011 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1014 if (active_idx
!= -1)
1016 menuPopup
.Check(1000+active_idx
, true);
1019 // find out where to put the popup menu of window
1020 // items. Subtract 100 for now to center the menu
1021 // a bit, until a better mechanism can be implemented
1022 wxPoint pt
= ::wxGetMousePosition();
1023 pt
= wnd
->ScreenToClient(pt
);
1029 // find out the screen coordinate at the bottom of the tab ctrl
1030 wxRect cli_rect
= wnd
->GetClientRect();
1031 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1033 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1034 wnd
->PushEventHandler(cc
);
1035 wnd
->PopupMenu(&menuPopup
, pt
);
1036 int command
= cc
->GetCommandId();
1037 wnd
->PopEventHandler(true);
1039 if (command
>= 1000)
1040 return command
-1000;
1045 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
1048 dc
.SetFont(m_measuring_font
);
1050 wxSize s
= GetTabSize(dc
,
1054 wxAUI_BUTTON_STATE_HIDDEN
,
1059 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1061 m_normal_font
= font
;
1064 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1066 m_selected_font
= font
;
1069 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1071 m_measuring_font
= font
;
1077 // -- wxAuiTabContainer class implementation --
1080 // wxAuiTabContainer is a class which contains information about each
1081 // tab. It also can render an entire tab control to a specified DC.
1082 // It's not a window class itself, because this code will be used by
1083 // the wxFrameMananger, where it is disadvantageous to have separate
1084 // windows for each tab control in the case of "docked tabs"
1086 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1087 // which can be used as a tab control in the normal sense.
1090 wxAuiTabContainer::wxAuiTabContainer()
1094 m_art
= new wxAuiDefaultTabArt
;
1096 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1097 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1098 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1099 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1102 wxAuiTabContainer::~wxAuiTabContainer()
1107 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1114 m_art
->SetFlags(m_flags
);
1118 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1123 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1127 // check for new close button settings
1128 RemoveButton(wxAUI_BUTTON_LEFT
);
1129 RemoveButton(wxAUI_BUTTON_RIGHT
);
1130 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1131 RemoveButton(wxAUI_BUTTON_CLOSE
);
1134 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1136 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1137 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1140 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1142 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1145 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1147 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1152 m_art
->SetFlags(m_flags
);
1156 unsigned int wxAuiTabContainer::GetFlags() const
1162 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1164 m_art
->SetNormalFont(font
);
1167 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1169 m_art
->SetSelectedFont(font
);
1172 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1174 m_art
->SetMeasuringFont(font
);
1177 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1183 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1187 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1188 const wxAuiNotebookPage
& info
)
1190 wxAuiNotebookPage page_info
;
1192 page_info
.window
= page
;
1194 m_pages
.Add(page_info
);
1196 // let the art provider know how many pages we have
1199 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1205 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1206 const wxAuiNotebookPage
& info
,
1209 wxAuiNotebookPage page_info
;
1211 page_info
.window
= page
;
1213 if (idx
>= m_pages
.GetCount())
1214 m_pages
.Add(page_info
);
1216 m_pages
.Insert(page_info
, idx
);
1218 // let the art provider know how many pages we have
1221 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1227 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1230 int idx
= GetIdxFromWindow(page
);
1234 // get page entry, make a copy of it
1235 wxAuiNotebookPage p
= GetPage(idx
);
1237 // remove old page entry
1240 // insert page where it should be
1241 InsertPage(page
, p
, new_idx
);
1246 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1248 size_t i
, page_count
= m_pages
.GetCount();
1249 for (i
= 0; i
< page_count
; ++i
)
1251 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1252 if (page
.window
== wnd
)
1254 m_pages
.RemoveAt(i
);
1256 // let the art provider know how many pages we have
1259 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1269 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1273 size_t i
, page_count
= m_pages
.GetCount();
1274 for (i
= 0; i
< page_count
; ++i
)
1276 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1277 if (page
.window
== wnd
)
1284 page
.active
= false;
1291 void wxAuiTabContainer::SetNoneActive()
1293 size_t i
, page_count
= m_pages
.GetCount();
1294 for (i
= 0; i
< page_count
; ++i
)
1296 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1297 page
.active
= false;
1301 bool wxAuiTabContainer::SetActivePage(size_t page
)
1303 if (page
>= m_pages
.GetCount())
1306 return SetActivePage(m_pages
.Item(page
).window
);
1309 int wxAuiTabContainer::GetActivePage() const
1311 size_t i
, page_count
= m_pages
.GetCount();
1312 for (i
= 0; i
< page_count
; ++i
)
1314 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1322 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1324 if (idx
>= m_pages
.GetCount())
1327 return m_pages
[idx
].window
;
1330 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1332 size_t i
, page_count
= m_pages
.GetCount();
1333 for (i
= 0; i
< page_count
; ++i
)
1335 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1336 if (page
.window
== wnd
)
1342 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1344 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1346 return m_pages
[idx
];
1349 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1354 size_t wxAuiTabContainer::GetPageCount() const
1356 return m_pages
.GetCount();
1359 void wxAuiTabContainer::AddButton(int id
,
1361 const wxBitmap
& normal_bitmap
,
1362 const wxBitmap
& disabled_bitmap
)
1364 wxAuiTabContainerButton button
;
1366 button
.bitmap
= normal_bitmap
;
1367 button
.dis_bitmap
= disabled_bitmap
;
1368 button
.location
= location
;
1369 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1371 m_buttons
.Add(button
);
1374 void wxAuiTabContainer::RemoveButton(int id
)
1376 size_t i
, button_count
= m_buttons
.GetCount();
1378 for (i
= 0; i
< button_count
; ++i
)
1380 if (m_buttons
.Item(i
).id
== id
)
1382 m_buttons
.RemoveAt(i
);
1390 size_t wxAuiTabContainer::GetTabOffset() const
1392 return m_tab_offset
;
1395 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1397 m_tab_offset
= offset
;
1403 // Render() renders the tab catalog to the specified DC
1404 // It is a virtual function and can be overridden to
1405 // provide custom drawing capabilities
1406 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1411 size_t page_count
= m_pages
.GetCount();
1412 size_t button_count
= m_buttons
.GetCount();
1414 // create off-screen bitmap
1415 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1416 dc
.SelectObject(bmp
);
1419 // find out if size of tabs is larger than can be
1420 // afforded on screen
1421 int total_width
= 0;
1422 int visible_width
= 0;
1423 for (i
= 0; i
< page_count
; ++i
)
1425 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1427 // determine if a close button is on this tab
1428 bool close_button
= false;
1429 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1430 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1432 close_button
= true;
1437 wxSize size
= m_art
->GetTabSize(dc
,
1442 wxAUI_BUTTON_STATE_NORMAL
:
1443 wxAUI_BUTTON_STATE_HIDDEN
,
1446 if (i
+1 < page_count
)
1447 total_width
+= x_extent
;
1449 total_width
+= size
.x
;
1451 if (i
>= m_tab_offset
)
1453 if (i
+1 < page_count
)
1454 visible_width
+= x_extent
;
1456 visible_width
+= size
.x
;
1460 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1462 // show left/right buttons
1463 for (i
= 0; i
< button_count
; ++i
)
1465 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1466 if (button
.id
== wxAUI_BUTTON_LEFT
||
1467 button
.id
== wxAUI_BUTTON_RIGHT
)
1469 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1475 // hide left/right buttons
1476 for (i
= 0; i
< button_count
; ++i
)
1478 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1479 if (button
.id
== wxAUI_BUTTON_LEFT
||
1480 button
.id
== wxAUI_BUTTON_RIGHT
)
1482 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1487 // determine whether left button should be enabled
1488 for (i
= 0; i
< button_count
; ++i
)
1490 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1491 if (button
.id
== wxAUI_BUTTON_LEFT
)
1493 if (m_tab_offset
== 0)
1494 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1496 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1498 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1500 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1501 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1503 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1510 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1513 int left_buttons_width
= 0;
1514 int right_buttons_width
= 0;
1518 // draw the buttons on the right side
1519 offset
= m_rect
.x
+ m_rect
.width
;
1520 for (i
= 0; i
< button_count
; ++i
)
1522 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1524 if (button
.location
!= wxRIGHT
)
1526 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1529 wxRect button_rect
= m_rect
;
1530 button_rect
.SetY(1);
1531 button_rect
.SetWidth(offset
);
1533 m_art
->DrawButton(dc
,
1542 offset
-= button
.rect
.GetWidth();
1543 right_buttons_width
+= button
.rect
.GetWidth();
1550 // draw the buttons on the left side
1552 for (i
= 0; i
< button_count
; ++i
)
1554 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1556 if (button
.location
!= wxLEFT
)
1558 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1561 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1563 m_art
->DrawButton(dc
,
1572 offset
+= button
.rect
.GetWidth();
1573 left_buttons_width
+= button
.rect
.GetWidth();
1576 offset
= left_buttons_width
;
1579 offset
+= m_art
->GetIndentSize();
1581 // prepare the tab-close-button array
1582 while (m_tab_close_buttons
.GetCount() < page_count
)
1584 wxAuiTabContainerButton tempbtn
;
1585 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1586 tempbtn
.location
= wxCENTER
;
1587 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1588 m_tab_close_buttons
.Add(tempbtn
);
1591 for (i
= 0; i
< m_tab_offset
; ++i
)
1593 // buttons before the tab offset must be set to hidden
1594 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1600 size_t active
= 999;
1601 int active_offset
= 0;
1605 wxRect rect
= m_rect
;
1607 rect
.height
= m_rect
.height
;
1609 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1611 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1612 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1614 // determine if a close button is on this tab
1615 bool close_button
= false;
1616 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1617 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1619 close_button
= true;
1620 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1622 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1623 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1624 tab_button
.location
= wxCENTER
;
1629 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1633 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1642 tab_button
.cur_state
,
1650 active_offset
= offset
;
1657 // draw the active tab again so it stands in the foreground
1658 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1660 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1662 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1664 // determine if a close button is on this tab
1665 bool close_button
= false;
1666 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1667 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1669 close_button
= true;
1672 rect
.x
= active_offset
;
1678 tab_button
.cur_state
,
1685 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1686 m_rect
.GetWidth(), m_rect
.GetHeight(),
1691 // TabHitTest() tests if a tab was hit, passing the window pointer
1692 // back if that condition was fulfilled. The function returns
1693 // true if a tab was hit, otherwise false
1694 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1696 if (!m_rect
.Contains(x
,y
))
1699 wxAuiTabContainerButton
* btn
= NULL
;
1700 if (ButtonHitTest(x
, y
, &btn
))
1702 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1706 size_t i
, page_count
= m_pages
.GetCount();
1708 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1710 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1711 if (page
.rect
.Contains(x
,y
))
1722 // ButtonHitTest() tests if a button was hit. The function returns
1723 // true if a button was hit, otherwise false
1724 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1725 wxAuiTabContainerButton
** hit
) const
1727 if (!m_rect
.Contains(x
,y
))
1730 size_t i
, button_count
;
1733 button_count
= m_buttons
.GetCount();
1734 for (i
= 0; i
< button_count
; ++i
)
1736 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1737 if (button
.rect
.Contains(x
,y
))
1745 button_count
= m_tab_close_buttons
.GetCount();
1746 for (i
= 0; i
< button_count
; ++i
)
1748 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1749 if (button
.rect
.Contains(x
,y
))
1762 // the utility function ShowWnd() is the same as show,
1763 // except it handles wxAuiMDIChildFrame windows as well,
1764 // as the Show() method on this class is "unplugged"
1765 static void ShowWnd(wxWindow
* wnd
, bool show
)
1767 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1769 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1779 // DoShowHide() this function shows the active window, then
1780 // hides all of the other windows (in that order)
1781 void wxAuiTabContainer::DoShowHide()
1783 wxAuiNotebookPageArray
& pages
= GetPages();
1784 size_t i
, page_count
= pages
.GetCount();
1786 // show new active page first
1787 for (i
= 0; i
< page_count
; ++i
)
1789 wxAuiNotebookPage
& page
= pages
.Item(i
);
1792 ShowWnd(page
.window
, true);
1797 // hide all other pages
1798 for (i
= 0; i
< page_count
; ++i
)
1800 wxAuiNotebookPage
& page
= pages
.Item(i
);
1801 ShowWnd(page
.window
, page
.active
);
1810 // -- wxAuiTabCtrl class implementation --
1814 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1815 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1816 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1817 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1818 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1819 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1820 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1821 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1822 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1826 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1830 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1832 m_click_pt
= wxDefaultPosition
;
1833 m_is_dragging
= false;
1834 m_hover_button
= NULL
;
1837 wxAuiTabCtrl::~wxAuiTabCtrl()
1841 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1845 dc
.SetFont(GetFont());
1847 if (GetPageCount() > 0)
1851 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1855 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1857 wxSize s
= evt
.GetSize();
1858 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1862 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1865 m_click_pt
= wxDefaultPosition
;
1866 m_is_dragging
= false;
1870 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1872 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1873 e
.SetSelection(GetIdxFromWindow(wnd
));
1874 e
.SetOldSelection(GetActivePage());
1875 e
.SetEventObject(this);
1876 GetEventHandler()->ProcessEvent(e
);
1878 m_click_pt
.x
= evt
.m_x
;
1879 m_click_pt
.y
= evt
.m_y
;
1885 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1891 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1893 if (GetCapture() == this)
1898 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1899 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1900 evt
.SetOldSelection(evt
.GetSelection());
1901 evt
.SetEventObject(this);
1902 GetEventHandler()->ProcessEvent(evt
);
1908 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1912 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1914 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1915 evt
.SetInt(m_hover_button
->id
);
1916 evt
.SetEventObject(this);
1917 GetEventHandler()->ProcessEvent(evt
);
1921 m_click_pt
= wxDefaultPosition
;
1922 m_is_dragging
= false;
1926 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1928 wxPoint pos
= evt
.GetPosition();
1930 // check if the mouse is hovering above a button
1931 wxAuiTabContainerButton
* button
;
1932 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1934 if (m_hover_button
&& button
!= m_hover_button
)
1936 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1937 m_hover_button
= NULL
;
1942 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1944 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1947 m_hover_button
= button
;
1955 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1956 m_hover_button
= NULL
;
1963 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1968 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1969 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1970 evt
.SetOldSelection(evt
.GetSelection());
1971 evt
.SetEventObject(this);
1972 GetEventHandler()->ProcessEvent(evt
);
1977 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1978 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1980 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1981 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1983 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1984 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1985 evt
.SetOldSelection(evt
.GetSelection());
1986 evt
.SetEventObject(this);
1987 GetEventHandler()->ProcessEvent(evt
);
1989 m_is_dragging
= true;
1993 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1997 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1998 m_hover_button
= NULL
;
2004 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2006 int button
= event
.GetInt();
2008 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2010 if (button
== wxAUI_BUTTON_LEFT
)
2012 if (GetTabOffset() > 0)
2014 SetTabOffset(GetTabOffset()-1);
2021 SetTabOffset(GetTabOffset()+1);
2026 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2030 size_t i
, page_count
= m_pages
.GetCount();
2031 for (i
= 0; i
< page_count
; ++i
)
2033 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2034 as
.Add(page
.caption
);
2037 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2041 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2042 e
.SetSelection(idx
);
2043 e
.SetOldSelection(GetActivePage());
2044 e
.SetEventObject(this);
2045 GetEventHandler()->ProcessEvent(e
);
2054 // wxTabFrame is an interesting case. It's important that all child pages
2055 // of the multi-notebook control are all actually children of that control
2056 // (and not grandchildren). wxTabFrame facilitates this. There is one
2057 // instance of wxTabFrame for each tab control inside the multi-notebook.
2058 // It's important to know that wxTabFrame is not a real window, but it merely
2059 // used to capture the dimensions/positioning of the internal tab control and
2060 // it's managed page windows
2062 class wxTabFrame
: public wxWindow
2069 m_rect
= wxRect(0,0,200,200);
2070 m_tab_ctrl_height
= 20;
2073 void SetTabCtrlHeight(int h
)
2075 m_tab_ctrl_height
= h
;
2078 void DoSetSize(int x
, int y
,
2079 int width
, int height
,
2080 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2082 m_rect
= wxRect(x
, y
, width
, height
);
2086 void DoGetClientSize(int* x
, int* y
) const
2092 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2099 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2100 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2101 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2105 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2106 size_t i
, page_count
= pages
.GetCount();
2108 for (i
= 0; i
< page_count
; ++i
)
2110 wxAuiNotebookPage
& page
= pages
.Item(i
);
2111 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2112 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2114 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2116 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2117 wnd
->ApplyMDIChildFrameRect();
2122 void DoGetSize(int* x
, int* y
) const
2125 *x
= m_rect
.GetWidth();
2127 *y
= m_rect
.GetHeight();
2139 wxAuiTabCtrl
* m_tabs
;
2140 int m_tab_ctrl_height
;
2147 // -- wxAuiNotebook class implementation --
2149 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2150 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2151 //EVT_SIZE(wxAuiNotebook::OnSize)
2152 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2153 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2154 EVT_COMMAND_RANGE(10000, 10100,
2155 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2156 wxAuiNotebook::OnTabClicked
)
2157 EVT_COMMAND_RANGE(10000, 10100,
2158 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2159 wxAuiNotebook::OnTabBeginDrag
)
2160 EVT_COMMAND_RANGE(10000, 10100,
2161 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2162 wxAuiNotebook::OnTabEndDrag
)
2163 EVT_COMMAND_RANGE(10000, 10100,
2164 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2165 wxAuiNotebook::OnTabDragMotion
)
2166 EVT_COMMAND_RANGE(10000, 10100,
2167 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2168 wxAuiNotebook::OnTabButton
)
2171 wxAuiNotebook::wxAuiNotebook()
2174 m_tab_id_counter
= 10000;
2176 m_tab_ctrl_height
= 20;
2179 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2183 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2185 InitNotebook(style
);
2188 bool wxAuiNotebook::Create(wxWindow
* parent
,
2194 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2197 InitNotebook(style
);
2202 // InitNotebook() contains common initialization
2203 // code called by all constructors
2204 void wxAuiNotebook::InitNotebook(long style
)
2207 m_tab_id_counter
= 10000;
2209 m_tab_ctrl_height
= 20;
2210 m_flags
= (unsigned int)style
;
2212 m_normal_font
= *wxNORMAL_FONT
;
2213 m_selected_font
= *wxNORMAL_FONT
;
2214 m_selected_font
.SetWeight(wxBOLD
);
2216 SetArtProvider(new wxAuiDefaultTabArt
);
2218 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2219 m_dummy_wnd
->SetSize(200, 200);
2220 m_dummy_wnd
->Show(false);
2222 m_mgr
.SetManagedWindow(this);
2224 m_mgr
.AddPane(m_dummy_wnd
,
2225 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2230 wxAuiNotebook::~wxAuiNotebook()
2235 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2237 m_tabs
.SetArtProvider(art
);
2239 // choose a default for the tab height
2240 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2242 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2243 size_t i
, pane_count
= all_panes
.GetCount();
2244 for (i
= 0; i
< pane_count
; ++i
)
2246 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2247 if (pane
.name
== wxT("dummy"))
2249 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2250 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2251 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2252 tabctrl
->SetArtProvider(art
->Clone());
2253 tab_frame
->DoSizing();
2258 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2260 return m_tabs
.GetArtProvider();
2263 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2265 wxControl::SetWindowStyleFlag(style
);
2267 m_flags
= (unsigned int)style
;
2269 // if the control is already initialized
2270 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2272 // let all of the tab children know about the new style
2274 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2275 size_t i
, pane_count
= all_panes
.GetCount();
2276 for (i
= 0; i
< pane_count
; ++i
)
2278 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2279 if (pane
.name
== wxT("dummy"))
2281 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2282 tabctrl
->SetFlags(m_flags
);
2290 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2291 const wxString
& caption
,
2293 const wxBitmap
& bitmap
)
2295 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2298 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2300 const wxString
& caption
,
2302 const wxBitmap
& bitmap
)
2304 wxAuiNotebookPage info
;
2306 info
.caption
= caption
;
2307 info
.bitmap
= bitmap
;
2308 info
.active
= false;
2310 // if there are currently no tabs, the first added
2311 // tab must be active
2312 if (m_tabs
.GetPageCount() == 0)
2315 m_tabs
.InsertPage(page
, info
, page_idx
);
2317 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2318 if (page_idx
>= active_tabctrl
->GetPageCount())
2319 active_tabctrl
->AddPage(page
, info
);
2321 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2324 active_tabctrl
->DoShowHide();
2328 int idx
= m_tabs
.GetIdxFromWindow(page
);
2329 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2338 // DeletePage() removes a tab from the multi-notebook,
2339 // and destroys the window as well
2340 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2342 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2344 if (!RemovePage(page_idx
))
2348 // actually destroy the window now
2349 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2351 // delete the child frame with pending delete, as is
2352 // customary with frame windows
2353 if (!wxPendingDelete
.Member(wnd
))
2354 wxPendingDelete
.Append(wnd
);
2366 // RemovePage() removes a tab from the multi-notebook,
2367 // but does not destroy the window
2368 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2370 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2371 wxWindow
* new_active
= NULL
;
2373 // find out which onscreen tab ctrl owns this tab
2376 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2379 // find a new page and set it as active
2380 int new_idx
= ctrl_idx
+1;
2381 if (new_idx
>= (int)ctrl
->GetPageCount())
2382 new_idx
= ctrl_idx
-1;
2384 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2386 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2390 // set the active page to the first page that
2391 // isn't the one being deleted
2392 size_t i
, page_count
= m_tabs
.GetPageCount();
2393 for (i
= 0; i
< page_count
; ++i
)
2395 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2398 new_active
= m_tabs
.GetWindowFromIdx(i
);
2404 // remove the tab from main catalog
2405 if (!m_tabs
.RemovePage(wnd
))
2408 // remove the tab from the onscreen tab ctrl
2409 ctrl
->RemovePage(wnd
);
2412 RemoveEmptyTabFrames();
2414 // set new active pane
2418 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2424 // SetPageText() changes the tab caption of the specified page
2425 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2427 if (page_idx
>= m_tabs
.GetPageCount())
2430 // update our own tab catalog
2431 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2432 page_info
.caption
= text
;
2434 // update what's on screen
2437 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2439 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2440 info
.caption
= text
;
2448 // GetSelection() returns the index of the currently active page
2449 int wxAuiNotebook::GetSelection() const
2454 // SetSelection() sets the currently active page
2455 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2457 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2461 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2462 evt
.SetSelection(new_page
);
2463 evt
.SetOldSelection(m_curpage
);
2464 evt
.SetEventObject(this);
2465 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2467 // program allows the page change
2468 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2469 (void)GetEventHandler()->ProcessEvent(evt
);
2475 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2477 m_tabs
.SetActivePage(wnd
);
2479 ctrl
->SetActivePage(ctrl_idx
);
2483 int old_curpage
= m_curpage
;
2484 m_curpage
= new_page
;
2488 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2489 size_t i
, pane_count
= all_panes
.GetCount();
2490 for (i
= 0; i
< pane_count
; ++i
)
2492 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2493 if (pane
.name
== wxT("dummy"))
2495 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2496 if (tabctrl
!= ctrl
)
2497 tabctrl
->SetSelectedFont(m_normal_font
);
2499 tabctrl
->SetSelectedFont(m_selected_font
);
2512 // GetPageCount() returns the total number of
2513 // pages managed by the multi-notebook
2514 size_t wxAuiNotebook::GetPageCount() const
2516 return m_tabs
.GetPageCount();
2519 // GetPage() returns the wxWindow pointer of the
2521 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2523 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2525 return m_tabs
.GetWindowFromIdx(page_idx
);
2528 // DoSizing() performs all sizing operations in each tab control
2529 void wxAuiNotebook::DoSizing()
2531 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2532 size_t i
, pane_count
= all_panes
.GetCount();
2533 for (i
= 0; i
< pane_count
; ++i
)
2535 if (all_panes
.Item(i
).name
== wxT("dummy"))
2538 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2539 tabframe
->DoSizing();
2543 // GetActiveTabCtrl() returns the active tab control. It is
2544 // called to determine which control gets new windows being added
2545 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2547 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2552 // find the tab ctrl with the current page
2553 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2560 // no current page, just find the first tab ctrl
2561 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2562 size_t i
, pane_count
= all_panes
.GetCount();
2563 for (i
= 0; i
< pane_count
; ++i
)
2565 if (all_panes
.Item(i
).name
== wxT("dummy"))
2568 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2569 return tabframe
->m_tabs
;
2572 // If there is no tabframe at all, create one
2573 wxTabFrame
* tabframe
= new wxTabFrame
;
2574 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2575 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2580 tabframe
->m_tabs
->SetFlags(m_flags
);
2581 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2582 m_mgr
.AddPane(tabframe
,
2583 wxAuiPaneInfo().Center().CaptionVisible(false));
2587 return tabframe
->m_tabs
;
2590 // FindTab() finds the tab control that currently contains the window as well
2591 // as the index of the window in the tab control. It returns true if the
2592 // window was found, otherwise false.
2593 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2595 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2596 size_t i
, pane_count
= all_panes
.GetCount();
2597 for (i
= 0; i
< pane_count
; ++i
)
2599 if (all_panes
.Item(i
).name
== wxT("dummy"))
2602 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2604 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2607 *ctrl
= tabframe
->m_tabs
;
2617 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2621 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2625 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2627 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2629 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2630 wxASSERT(ctrl
!= NULL
);
2632 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2633 wxASSERT(wnd
!= NULL
);
2635 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2636 wxASSERT(idx
!= -1);
2641 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2646 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2648 wxPoint screen_pt
= ::wxGetMousePosition();
2649 wxPoint client_pt
= ScreenToClient(screen_pt
);
2652 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2653 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2655 if (dest_tabs
== src_tabs
)
2659 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2662 // always hide the hint for inner-tabctrl drag
2665 // if tab moving is not allowed, leave
2666 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2671 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2672 wxWindow
* dest_location_tab
;
2674 // this is an inner-tab drag/reposition
2675 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2677 int src_idx
= evt
.GetSelection();
2678 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2680 // prevent jumpy drag
2681 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2682 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2683 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2685 m_last_drag_x
= pt
.x
;
2690 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2691 dest_tabs
->MovePage(src_tab
, dest_idx
);
2692 dest_tabs
->SetActivePage((size_t)dest_idx
);
2693 dest_tabs
->DoShowHide();
2694 dest_tabs
->Refresh();
2695 m_last_drag_x
= pt
.x
;
2703 // if external drag is allowed, check if the tab is being dragged
2704 // over a different wxAuiNotebook control
2705 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2707 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2709 // make sure we are not over the hint window
2710 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2714 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2716 tab_ctrl
= tab_ctrl
->GetParent();
2721 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2725 wxRect hint_rect
= tab_ctrl
->GetRect();
2726 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2727 m_mgr
.ShowHint(hint_rect
);
2736 // if tab moving is not allowed, leave
2737 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2745 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2751 wxRect hint_rect
= dest_tabs
->GetRect();
2752 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2753 m_mgr
.ShowHint(hint_rect
);
2757 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2763 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2765 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2770 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2771 wxAuiTabCtrl
* dest_tabs
= NULL
;
2774 // set cursor back to an arrow
2775 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2778 // get the mouse position, which will be used to determine the drop point
2779 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2780 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2784 // check for an external move
2785 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2787 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2791 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2793 tab_ctrl
= tab_ctrl
->GetParent();
2798 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2802 // find out from the destination control
2803 // if it's ok to drop this tab here
2804 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2805 e
.SetSelection(evt
.GetSelection());
2806 e
.SetOldSelection(evt
.GetSelection());
2807 e
.SetEventObject(this);
2808 e
.SetDragSource(this);
2809 e
.Veto(); // dropping must be explicitly approved by control owner
2811 nb
->GetEventHandler()->ProcessEvent(e
);
2815 // no answer or negative answer
2821 int src_idx
= evt
.GetSelection();
2822 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2824 // get main index of the page
2825 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2827 // make a copy of the page info
2828 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2830 // remove the page from the source notebook
2831 RemovePage(main_idx
);
2833 // reparent the page
2834 src_page
->Reparent(nb
);
2837 // found out the insert idx
2838 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2839 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2841 wxWindow
* target
= NULL
;
2842 int insert_idx
= -1;
2843 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2846 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2850 // add the page to the new notebook
2851 if (insert_idx
== -1)
2852 insert_idx
= dest_tabs
->GetPageCount();
2853 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2854 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2857 dest_tabs
->DoShowHide();
2858 dest_tabs
->Refresh();
2860 // set the selection in the destination tab control
2861 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2871 // only perform a tab split if it's allowed
2872 if (m_flags
& wxAUI_NB_TAB_SPLIT
)
2874 // If the pointer is in an existing tab frame, do a tab insert
2875 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2876 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2877 int insert_idx
= -1;
2880 dest_tabs
= tab_frame
->m_tabs
;
2882 if (dest_tabs
== src_tabs
)
2886 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2887 wxWindow
* target
= NULL
;
2888 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2891 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2896 // If there is no tabframe at all, create one
2897 wxTabFrame
* new_tabs
= new wxTabFrame
;
2898 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2899 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2904 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2905 new_tabs
->m_tabs
->SetFlags(m_flags
);
2907 m_mgr
.AddPane(new_tabs
,
2908 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2911 dest_tabs
= new_tabs
->m_tabs
;
2916 // remove the page from the source tabs
2917 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2918 page_info
.active
= false;
2919 src_tabs
->RemovePage(page_info
.window
);
2920 if (src_tabs
->GetPageCount() > 0)
2922 src_tabs
->SetActivePage((size_t)0);
2923 src_tabs
->DoShowHide();
2924 src_tabs
->Refresh();
2929 // add the page to the destination tabs
2930 if (insert_idx
== -1)
2931 insert_idx
= dest_tabs
->GetPageCount();
2932 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2934 if (src_tabs
->GetPageCount() == 0)
2936 RemoveEmptyTabFrames();
2940 dest_tabs
->DoShowHide();
2941 dest_tabs
->Refresh();
2943 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2949 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2951 // if we've just removed the last tab from the source
2952 // tab set, the remove the tab control completely
2953 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2954 size_t i
, pane_count
= all_panes
.GetCount();
2955 for (i
= 0; i
< pane_count
; ++i
)
2957 if (all_panes
.Item(i
).name
== wxT("dummy"))
2960 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2961 if (tabframe
->m_tab_rect
.Contains(pt
))
2962 return tabframe
->m_tabs
;
2968 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2970 // if we've just removed the last tab from the source
2971 // tab set, the remove the tab control completely
2972 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2973 size_t i
, pane_count
= all_panes
.GetCount();
2974 for (i
= 0; i
< pane_count
; ++i
)
2976 if (all_panes
.Item(i
).name
== wxT("dummy"))
2979 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2980 if (tabframe
->m_tabs
== tab_ctrl
)
2989 void wxAuiNotebook::RemoveEmptyTabFrames()
2991 // if we've just removed the last tab from the source
2992 // tab set, the remove the tab control completely
2993 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2994 size_t i
, pane_count
= all_panes
.GetCount();
2995 for (i
= 0; i
< pane_count
; ++i
)
2997 if (all_panes
.Item(i
).name
== wxT("dummy"))
3000 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3001 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3003 m_mgr
.DetachPane(tab_frame
);
3005 // use pending delete because sometimes during
3006 // window closing, refreshs are pending
3007 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3008 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3009 //tab_frame->m_tabs->Destroy();
3016 // check to see if there is still a center pane;
3017 // if there isn't, make a frame the center pane
3018 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3019 pane_count
= panes
.GetCount();
3020 wxWindow
* first_good
= NULL
;
3021 bool center_found
= false;
3022 for (i
= 0; i
< pane_count
; ++i
)
3024 if (panes
.Item(i
).name
== wxT("dummy"))
3026 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3027 center_found
= true;
3029 first_good
= panes
.Item(i
).window
;
3032 if (!center_found
&& first_good
)
3034 m_mgr
.GetPane(first_good
).Centre();
3040 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3042 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3043 if (idx
!= -1 && idx
!= m_curpage
)
3050 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3052 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3053 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3055 int button_id
= evt
.GetInt();
3057 if (button_id
== wxAUI_BUTTON_CLOSE
)
3059 int selection
= tabs
->GetActivePage();
3061 if (selection
!= -1)
3063 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3066 // ask owner if it's ok to close the tab
3067 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3068 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3069 e
.SetOldSelection(evt
.GetSelection());
3070 e
.SetEventObject(this);
3071 GetEventHandler()->ProcessEvent(e
);
3076 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3082 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3083 DeletePage(main_idx
);