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
);
2365 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
2366 wxWindow* new_active = NULL;
2368 // find out which onscreen tab ctrl owns this tab
2371 if (!FindTab(wnd, &ctrl, &ctrl_idx))
2374 // find a new page and set it as active
2375 int new_idx = ctrl_idx+1;
2376 if (new_idx >= (int)ctrl->GetPageCount())
2377 new_idx = ctrl_idx-1;
2379 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
2381 new_active = ctrl->GetWindowFromIdx(new_idx);
2385 // set the active page to the first page that
2386 // isn't the one being deleted
2387 size_t i, page_count = m_tabs.GetPageCount();
2388 for (i = 0; i < page_count; ++i)
2390 wxWindow* w = m_tabs.GetWindowFromIdx(i);
2393 new_active = m_tabs.GetWindowFromIdx(i);
2399 // remove the tab from main catalog
2400 if (!m_tabs.RemovePage(wnd))
2403 // remove the tab from the onscreen tab ctrl
2404 ctrl->RemovePage(wnd);
2406 // actually destroy the window now
2407 if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
2409 // delete the child frame with pending delete, as is
2410 // customary with frame windows
2411 if (!wxPendingDelete.Member(wnd))
2412 wxPendingDelete.Append(wnd);
2419 RemoveEmptyTabFrames();
2421 // set new active pane
2425 SetSelection(m_tabs.GetIdxFromWindow(new_active));
2434 // RemovePage() removes a tab from the multi-notebook,
2435 // but does not destroy the window
2436 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2438 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2439 wxWindow
* new_active
= NULL
;
2441 // find out which onscreen tab ctrl owns this tab
2444 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2447 // find a new page and set it as active
2448 int new_idx
= ctrl_idx
+1;
2449 if (new_idx
>= (int)ctrl
->GetPageCount())
2450 new_idx
= ctrl_idx
-1;
2452 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2454 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2458 // set the active page to the first page that
2459 // isn't the one being deleted
2460 size_t i
, page_count
= m_tabs
.GetPageCount();
2461 for (i
= 0; i
< page_count
; ++i
)
2463 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2466 new_active
= m_tabs
.GetWindowFromIdx(i
);
2472 // remove the tab from main catalog
2473 if (!m_tabs
.RemovePage(wnd
))
2476 // remove the tab from the onscreen tab ctrl
2477 ctrl
->RemovePage(wnd
);
2480 RemoveEmptyTabFrames();
2482 // set new active pane
2486 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2492 // SetPageText() changes the tab caption of the specified page
2493 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2495 if (page_idx
>= m_tabs
.GetPageCount())
2498 // update our own tab catalog
2499 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2500 page_info
.caption
= text
;
2502 // update what's on screen
2505 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2507 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2508 info
.caption
= text
;
2516 // GetSelection() returns the index of the currently active page
2517 int wxAuiNotebook::GetSelection() const
2522 // SetSelection() sets the currently active page
2523 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2525 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2529 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2530 evt
.SetSelection(new_page
);
2531 evt
.SetOldSelection(m_curpage
);
2532 evt
.SetEventObject(this);
2533 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2535 // program allows the page change
2536 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2537 (void)GetEventHandler()->ProcessEvent(evt
);
2543 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2545 m_tabs
.SetActivePage(wnd
);
2547 ctrl
->SetActivePage(ctrl_idx
);
2551 int old_curpage
= m_curpage
;
2552 m_curpage
= new_page
;
2556 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2557 size_t i
, pane_count
= all_panes
.GetCount();
2558 for (i
= 0; i
< pane_count
; ++i
)
2560 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2561 if (pane
.name
== wxT("dummy"))
2563 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2564 if (tabctrl
!= ctrl
)
2565 tabctrl
->SetSelectedFont(m_normal_font
);
2567 tabctrl
->SetSelectedFont(m_selected_font
);
2580 // GetPageCount() returns the total number of
2581 // pages managed by the multi-notebook
2582 size_t wxAuiNotebook::GetPageCount() const
2584 return m_tabs
.GetPageCount();
2587 // GetPage() returns the wxWindow pointer of the
2589 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2591 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2593 return m_tabs
.GetWindowFromIdx(page_idx
);
2596 // DoSizing() performs all sizing operations in each tab control
2597 void wxAuiNotebook::DoSizing()
2599 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2600 size_t i
, pane_count
= all_panes
.GetCount();
2601 for (i
= 0; i
< pane_count
; ++i
)
2603 if (all_panes
.Item(i
).name
== wxT("dummy"))
2606 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2607 tabframe
->DoSizing();
2611 // GetActiveTabCtrl() returns the active tab control. It is
2612 // called to determine which control gets new windows being added
2613 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2615 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2620 // find the tab ctrl with the current page
2621 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2628 // no current page, just find the first tab ctrl
2629 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2630 size_t i
, pane_count
= all_panes
.GetCount();
2631 for (i
= 0; i
< pane_count
; ++i
)
2633 if (all_panes
.Item(i
).name
== wxT("dummy"))
2636 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2637 return tabframe
->m_tabs
;
2640 // If there is no tabframe at all, create one
2641 wxTabFrame
* tabframe
= new wxTabFrame
;
2642 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2643 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2648 tabframe
->m_tabs
->SetFlags(m_flags
);
2649 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2650 m_mgr
.AddPane(tabframe
,
2651 wxAuiPaneInfo().Center().CaptionVisible(false));
2655 return tabframe
->m_tabs
;
2658 // FindTab() finds the tab control that currently contains the window as well
2659 // as the index of the window in the tab control. It returns true if the
2660 // window was found, otherwise false.
2661 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2663 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2664 size_t i
, pane_count
= all_panes
.GetCount();
2665 for (i
= 0; i
< pane_count
; ++i
)
2667 if (all_panes
.Item(i
).name
== wxT("dummy"))
2670 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2672 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2675 *ctrl
= tabframe
->m_tabs
;
2685 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2689 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2693 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2695 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2697 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2698 wxASSERT(ctrl
!= NULL
);
2700 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2701 wxASSERT(wnd
!= NULL
);
2703 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2704 wxASSERT(idx
!= -1);
2709 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2714 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2716 wxPoint screen_pt
= ::wxGetMousePosition();
2717 wxPoint client_pt
= ScreenToClient(screen_pt
);
2720 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2721 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2723 if (dest_tabs
== src_tabs
)
2727 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2730 // always hide the hint for inner-tabctrl drag
2733 // if tab moving is not allowed, leave
2734 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2739 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2740 wxWindow
* dest_location_tab
;
2742 // this is an inner-tab drag/reposition
2743 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2745 int src_idx
= evt
.GetSelection();
2746 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2748 // prevent jumpy drag
2749 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2750 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2751 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2753 m_last_drag_x
= pt
.x
;
2758 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2759 dest_tabs
->MovePage(src_tab
, dest_idx
);
2760 dest_tabs
->SetActivePage((size_t)dest_idx
);
2761 dest_tabs
->DoShowHide();
2762 dest_tabs
->Refresh();
2763 m_last_drag_x
= pt
.x
;
2771 // if external drag is allowed, check if the tab is being dragged
2772 // over a different wxAuiNotebook control
2773 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2775 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2777 // make sure we are not over the hint window
2778 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2782 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2784 tab_ctrl
= tab_ctrl
->GetParent();
2789 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2793 wxRect hint_rect
= tab_ctrl
->GetRect();
2794 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2795 m_mgr
.ShowHint(hint_rect
);
2804 // if tab moving is not allowed, leave
2805 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2813 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2819 wxRect hint_rect
= dest_tabs
->GetRect();
2820 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2821 m_mgr
.ShowHint(hint_rect
);
2825 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2831 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2833 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2838 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2839 wxAuiTabCtrl
* dest_tabs
= NULL
;
2842 // set cursor back to an arrow
2843 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2846 // get the mouse position, which will be used to determine the drop point
2847 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2848 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2852 // check for an external move
2853 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2855 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2859 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2861 tab_ctrl
= tab_ctrl
->GetParent();
2866 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2870 // find out from the destination control
2871 // if it's ok to drop this tab here
2872 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2873 e
.SetSelection(evt
.GetSelection());
2874 e
.SetOldSelection(evt
.GetSelection());
2875 e
.SetEventObject(this);
2876 e
.SetDragSource(this);
2877 e
.Veto(); // dropping must be explicitly approved by control owner
2879 nb
->GetEventHandler()->ProcessEvent(e
);
2883 // no answer or negative answer
2889 int src_idx
= evt
.GetSelection();
2890 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2892 // get main index of the page
2893 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2895 // make a copy of the page info
2896 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2898 // remove the page from the source notebook
2899 RemovePage(main_idx
);
2901 // reparent the page
2902 src_page
->Reparent(nb
);
2905 // found out the insert idx
2906 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2907 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2909 wxWindow
* target
= NULL
;
2910 int insert_idx
= -1;
2911 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2914 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2918 // add the page to the new notebook
2919 if (insert_idx
== -1)
2920 insert_idx
= dest_tabs
->GetPageCount();
2921 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2922 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2925 dest_tabs
->DoShowHide();
2926 dest_tabs
->Refresh();
2928 // set the selection in the destination tab control
2929 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2939 // only perform a tab split if it's allowed
2940 if (m_flags
& wxAUI_NB_TAB_SPLIT
)
2942 // If the pointer is in an existing tab frame, do a tab insert
2943 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2944 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2945 int insert_idx
= -1;
2948 dest_tabs
= tab_frame
->m_tabs
;
2950 if (dest_tabs
== src_tabs
)
2954 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2955 wxWindow
* target
= NULL
;
2956 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2959 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2964 // If there is no tabframe at all, create one
2965 wxTabFrame
* new_tabs
= new wxTabFrame
;
2966 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2967 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2972 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2973 new_tabs
->m_tabs
->SetFlags(m_flags
);
2975 m_mgr
.AddPane(new_tabs
,
2976 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2979 dest_tabs
= new_tabs
->m_tabs
;
2984 // remove the page from the source tabs
2985 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2986 page_info
.active
= false;
2987 src_tabs
->RemovePage(page_info
.window
);
2988 if (src_tabs
->GetPageCount() > 0)
2990 src_tabs
->SetActivePage((size_t)0);
2991 src_tabs
->DoShowHide();
2992 src_tabs
->Refresh();
2997 // add the page to the destination tabs
2998 if (insert_idx
== -1)
2999 insert_idx
= dest_tabs
->GetPageCount();
3000 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3002 if (src_tabs
->GetPageCount() == 0)
3004 RemoveEmptyTabFrames();
3008 dest_tabs
->DoShowHide();
3009 dest_tabs
->Refresh();
3011 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3017 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3019 // if we've just removed the last tab from the source
3020 // tab set, the remove the tab control completely
3021 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3022 size_t i
, pane_count
= all_panes
.GetCount();
3023 for (i
= 0; i
< pane_count
; ++i
)
3025 if (all_panes
.Item(i
).name
== wxT("dummy"))
3028 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3029 if (tabframe
->m_tab_rect
.Contains(pt
))
3030 return tabframe
->m_tabs
;
3036 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3038 // if we've just removed the last tab from the source
3039 // tab set, the remove the tab control completely
3040 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3041 size_t i
, pane_count
= all_panes
.GetCount();
3042 for (i
= 0; i
< pane_count
; ++i
)
3044 if (all_panes
.Item(i
).name
== wxT("dummy"))
3047 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3048 if (tabframe
->m_tabs
== tab_ctrl
)
3057 void wxAuiNotebook::RemoveEmptyTabFrames()
3059 // if we've just removed the last tab from the source
3060 // tab set, the remove the tab control completely
3061 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3062 size_t i
, pane_count
= all_panes
.GetCount();
3063 for (i
= 0; i
< pane_count
; ++i
)
3065 if (all_panes
.Item(i
).name
== wxT("dummy"))
3068 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3069 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3071 m_mgr
.DetachPane(tab_frame
);
3073 // use pending delete because sometimes during
3074 // window closing, refreshs are pending
3075 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3076 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3077 //tab_frame->m_tabs->Destroy();
3084 // check to see if there is still a center pane;
3085 // if there isn't, make a frame the center pane
3086 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3087 pane_count
= panes
.GetCount();
3088 wxWindow
* first_good
= NULL
;
3089 bool center_found
= false;
3090 for (i
= 0; i
< pane_count
; ++i
)
3092 if (panes
.Item(i
).name
== wxT("dummy"))
3094 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3095 center_found
= true;
3097 first_good
= panes
.Item(i
).window
;
3100 if (!center_found
&& first_good
)
3102 m_mgr
.GetPane(first_good
).Centre();
3108 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3110 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3111 if (idx
!= -1 && idx
!= m_curpage
)
3118 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3120 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3121 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3123 int button_id
= evt
.GetInt();
3125 if (button_id
== wxAUI_BUTTON_CLOSE
)
3127 int selection
= tabs
->GetActivePage();
3129 if (selection
!= -1)
3131 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3134 // ask owner if it's ok to close the tab
3135 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3136 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3137 e
.SetOldSelection(evt
.GetSelection());
3138 e
.SetEventObject(this);
3139 GetEventHandler()->ProcessEvent(e
);
3144 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3150 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3151 DeletePage(main_idx
);