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, 0xe7, 0xf3, 0xcf, 0xf9,
190 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
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
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
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();
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 dc
.DrawLine(points
[0].x
+1, y
, points
[5].x
, y
);
413 dc
.SetPen(*wxGREY_PEN
);
414 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
415 dc
.DrawPolygon(6, points
);
417 // there are two horizontal grey lines at the bottom of the tab control,
418 // this gets rid of the top one of those lines in the tab control
421 wxColour c
= m_bkbrush
.GetColour();
423 dc
.DrawLine(points
[0].x
, points
[0].y
, points
[5].x
+1, points
[5].y
);
428 int close_button_width
= 0;
430 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
432 close_button_width
= m_active_close_bmp
.GetWidth();
435 text_offset
= tab_x
+ 8;
438 wxString draw_text
= ChopText(dc
,
440 tab_width
- (text_offset
-tab_x
) - close_button_width
);
443 dc
.DrawText(draw_text
,
445 (tab_y
+ tab_height
)/2 - (texty
/2));
450 // draw close button if necessary
451 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
453 wxBitmap bmp
= m_disabled_close_bmp
;
455 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
456 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
458 bmp
= m_active_close_bmp
;
461 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
462 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
465 IndentPressedBitmap(&rect
, close_button_state
);
466 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
468 *out_button_rect
= rect
;
471 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
473 dc
.DestroyClippingRegion();
476 int wxAuiDefaultTabArt::GetIndentSize()
481 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
482 wxWindow
* WXUNUSED(wnd
),
483 const wxString
& caption
,
484 bool WXUNUSED(active
),
485 int close_button_state
,
488 wxCoord measured_textx
, measured_texty
, tmp
;
490 dc
.SetFont(m_measuring_font
);
491 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
493 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
495 // add padding around the text
496 wxCoord tab_width
= measured_textx
+ 16;
497 wxCoord tab_height
= measured_texty
+ 10;
499 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
500 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
503 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
505 tab_width
= m_fixed_tab_width
;
508 *x_extent
= tab_width
;
510 return wxSize(tab_width
, tab_height
);
514 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
515 wxWindow
* WXUNUSED(wnd
),
516 const wxRect
& in_rect
,
520 const wxBitmap
& bitmap_override
,
526 if (bitmap_override
.IsOk())
528 bmp
= bitmap_override
;
534 case wxAUI_BUTTON_CLOSE
:
535 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
536 bmp
= m_disabled_close_bmp
;
538 bmp
= m_active_close_bmp
;
540 case wxAUI_BUTTON_LEFT
:
541 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
542 bmp
= m_disabled_left_bmp
;
544 bmp
= m_active_left_bmp
;
546 case wxAUI_BUTTON_RIGHT
:
547 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
548 bmp
= m_disabled_right_bmp
;
550 bmp
= m_active_right_bmp
;
552 case wxAUI_BUTTON_WINDOWLIST
:
553 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
554 bmp
= m_disabled_windowlist_bmp
;
556 bmp
= m_active_windowlist_bmp
;
566 if (orientation
== wxLEFT
)
568 rect
.SetX(in_rect
.x
);
569 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
570 rect
.SetWidth(bmp
.GetWidth());
571 rect
.SetHeight(bmp
.GetHeight());
575 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
576 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
577 bmp
.GetWidth(), bmp
.GetHeight());
580 IndentPressedBitmap(&rect
, button_state
);
581 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
587 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
588 const wxArrayString
& items
,
593 size_t i
, count
= items
.GetCount();
594 for (i
= 0; i
< count
; ++i
)
596 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
599 if (active_idx
!= -1)
601 menuPopup
.Check(1000+active_idx
, true);
604 // find out where to put the popup menu of window
605 // items. Subtract 100 for now to center the menu
606 // a bit, until a better mechanism can be implemented
607 wxPoint pt
= ::wxGetMousePosition();
608 pt
= wnd
->ScreenToClient(pt
);
614 // find out the screen coordinate at the bottom of the tab ctrl
615 wxRect cli_rect
= wnd
->GetClientRect();
616 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
618 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
619 wnd
->PushEventHandler(cc
);
620 wnd
->PopupMenu(&menuPopup
, pt
);
621 int command
= cc
->GetCommandId();
622 wnd
->PopEventHandler(true);
630 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
633 dc
.SetFont(m_measuring_font
);
635 wxSize s
= GetTabSize(dc
,
639 wxAUI_BUTTON_STATE_HIDDEN
,
644 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
646 m_normal_font
= font
;
649 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
651 m_selected_font
= font
;
654 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
656 m_measuring_font
= font
;
660 // -- wxAuiSimpleTabArt class implementation --
662 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
664 m_normal_font
= *wxNORMAL_FONT
;
665 m_selected_font
= *wxNORMAL_FONT
;
666 m_selected_font
.SetWeight(wxBOLD
);
667 m_measuring_font
= m_selected_font
;
670 m_fixed_tab_width
= 100;
672 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
674 wxColour background_colour
= StepColour(base_colour
, 95);
675 wxColour normaltab_colour
= base_colour
;
676 wxColour selectedtab_colour
= *wxWHITE
;
678 m_bkbrush
= wxBrush(background_colour
);
679 m_normal_bkbrush
= wxBrush(normaltab_colour
);
680 m_normal_bkpen
= wxPen(normaltab_colour
);
681 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
682 m_selected_bkpen
= wxPen(selectedtab_colour
);
684 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
685 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
687 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
688 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
690 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
691 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
693 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
694 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
698 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
702 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
704 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
708 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
713 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
716 m_fixed_tab_width
= 100;
718 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
721 m_fixed_tab_width
= tot_width
/(int)tab_count
;
725 if (m_fixed_tab_width
< 100)
726 m_fixed_tab_width
= 100;
728 if (m_fixed_tab_width
> tot_width
/2)
729 m_fixed_tab_width
= tot_width
/2;
731 if (m_fixed_tab_width
> 220)
732 m_fixed_tab_width
= 220;
735 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
736 wxWindow
* WXUNUSED(wnd
),
740 dc
.SetBrush(m_bkbrush
);
741 dc
.SetPen(*wxTRANSPARENT_PEN
);
742 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
745 dc
.SetPen(*wxGREY_PEN
);
746 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
750 // DrawTab() draws an individual tab.
753 // in_rect - rectangle the tab should be confined to
754 // caption - tab's caption
755 // active - whether or not the tab is active
756 // out_rect - actual output rectangle
757 // x_extent - the advance x; where the next tab should start
759 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
761 const wxRect
& in_rect
,
762 const wxString
& caption_text
,
764 int close_button_state
,
765 wxRect
* out_tab_rect
,
766 wxRect
* out_button_rect
,
769 wxCoord normal_textx
, normal_texty
;
770 wxCoord selected_textx
, selected_texty
;
771 wxCoord textx
, texty
;
773 // if the caption is empty, measure some temporary text
774 wxString caption
= caption_text
;
775 if (caption_text
.empty())
778 dc
.SetFont(m_selected_font
);
779 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
781 dc
.SetFont(m_normal_font
);
782 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
784 // figure out the size of the tab
785 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
787 wxCoord tab_height
= tab_size
.y
;
788 wxCoord tab_width
= tab_size
.x
;
789 wxCoord tab_x
= in_rect
.x
;
790 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
792 caption
= caption_text
;
794 // select pen, brush and font for the tab to be drawn
798 dc
.SetPen(m_selected_bkpen
);
799 dc
.SetBrush(m_selected_bkbrush
);
800 dc
.SetFont(m_selected_font
);
801 textx
= selected_textx
;
802 texty
= selected_texty
;
806 dc
.SetPen(m_normal_bkpen
);
807 dc
.SetBrush(m_normal_bkbrush
);
808 dc
.SetFont(m_normal_font
);
809 textx
= normal_textx
;
810 texty
= normal_texty
;
818 points
[0].y
= tab_y
+ tab_height
- 1;
819 points
[1].x
= tab_x
+ tab_height
- 3;
820 points
[1].y
= tab_y
+ 2;
821 points
[2].x
= tab_x
+ tab_height
+ 3;
823 points
[3].x
= tab_x
+ tab_width
- 2;
825 points
[4].x
= tab_x
+ tab_width
;
826 points
[4].y
= tab_y
+ 2;
827 points
[5].x
= tab_x
+ tab_width
;
828 points
[5].y
= tab_y
+ tab_height
- 1;
829 points
[6] = points
[0];
831 dc
.SetClippingRegion(in_rect
);
833 dc
.DrawPolygon(6, points
);
835 dc
.SetPen(*wxGREY_PEN
);
837 //dc.DrawLines(active ? 6 : 7, points);
838 dc
.DrawLines(7, points
);
843 int close_button_width
= 0;
844 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
846 close_button_width
= m_active_close_bmp
.GetWidth();
847 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
851 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
854 // set minimum text offset
855 if (text_offset
< tab_x
+ tab_height
)
856 text_offset
= tab_x
+ tab_height
;
858 // chop text if necessary
859 wxString draw_text
= ChopText(dc
,
861 tab_width
- (text_offset
-tab_x
) - close_button_width
);
864 dc
.DrawText(draw_text
,
866 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
869 // draw close button if necessary
870 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
874 bmp
= m_active_close_bmp
;
876 bmp
= m_disabled_close_bmp
;
878 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
879 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
882 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
884 *out_button_rect
= rect
;
888 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
890 dc
.DestroyClippingRegion();
893 int wxAuiSimpleTabArt::GetIndentSize()
898 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
899 wxWindow
* WXUNUSED(wnd
),
900 const wxString
& caption
,
901 bool WXUNUSED(active
),
902 int close_button_state
,
905 wxCoord measured_textx
, measured_texty
;
907 dc
.SetFont(m_measuring_font
);
908 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
910 wxCoord tab_height
= measured_texty
+ 4;
911 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
913 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
914 tab_width
+= m_active_close_bmp
.GetWidth();
916 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
918 tab_width
= m_fixed_tab_width
;
921 *x_extent
= tab_width
- (tab_height
/2) - 1;
923 return wxSize(tab_width
, tab_height
);
927 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
928 wxWindow
* WXUNUSED(wnd
),
929 const wxRect
& in_rect
,
933 const wxBitmap
& bitmap_override
,
939 if (bitmap_override
.IsOk())
941 bmp
= bitmap_override
;
947 case wxAUI_BUTTON_CLOSE
:
948 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
949 bmp
= m_disabled_close_bmp
;
951 bmp
= m_active_close_bmp
;
953 case wxAUI_BUTTON_LEFT
:
954 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
955 bmp
= m_disabled_left_bmp
;
957 bmp
= m_active_left_bmp
;
959 case wxAUI_BUTTON_RIGHT
:
960 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
961 bmp
= m_disabled_right_bmp
;
963 bmp
= m_active_right_bmp
;
965 case wxAUI_BUTTON_WINDOWLIST
:
966 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
967 bmp
= m_disabled_windowlist_bmp
;
969 bmp
= m_active_windowlist_bmp
;
979 if (orientation
== wxLEFT
)
981 rect
.SetX(in_rect
.x
);
982 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
983 rect
.SetWidth(bmp
.GetWidth());
984 rect
.SetHeight(bmp
.GetHeight());
988 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
989 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
990 bmp
.GetWidth(), bmp
.GetHeight());
994 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1000 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1001 const wxArrayString
& items
,
1006 size_t i
, count
= items
.GetCount();
1007 for (i
= 0; i
< count
; ++i
)
1009 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1012 if (active_idx
!= -1)
1014 menuPopup
.Check(1000+active_idx
, true);
1017 // find out where to put the popup menu of window
1018 // items. Subtract 100 for now to center the menu
1019 // a bit, until a better mechanism can be implemented
1020 wxPoint pt
= ::wxGetMousePosition();
1021 pt
= wnd
->ScreenToClient(pt
);
1027 // find out the screen coordinate at the bottom of the tab ctrl
1028 wxRect cli_rect
= wnd
->GetClientRect();
1029 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1031 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1032 wnd
->PushEventHandler(cc
);
1033 wnd
->PopupMenu(&menuPopup
, pt
);
1034 int command
= cc
->GetCommandId();
1035 wnd
->PopEventHandler(true);
1037 if (command
>= 1000)
1038 return command
-1000;
1043 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
1046 dc
.SetFont(m_measuring_font
);
1048 wxSize s
= GetTabSize(dc
,
1052 wxAUI_BUTTON_STATE_HIDDEN
,
1057 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1059 m_normal_font
= font
;
1062 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1064 m_selected_font
= font
;
1067 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1069 m_measuring_font
= font
;
1075 // -- wxAuiTabContainer class implementation --
1078 // wxAuiTabContainer is a class which contains information about each
1079 // tab. It also can render an entire tab control to a specified DC.
1080 // It's not a window class itself, because this code will be used by
1081 // the wxFrameMananger, where it is disadvantageous to have separate
1082 // windows for each tab control in the case of "docked tabs"
1084 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1085 // which can be used as a tab control in the normal sense.
1088 wxAuiTabContainer::wxAuiTabContainer()
1092 m_art
= new wxAuiDefaultTabArt
;
1094 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1095 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1096 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1097 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1100 wxAuiTabContainer::~wxAuiTabContainer()
1105 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1112 m_art
->SetFlags(m_flags
);
1116 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1121 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1125 // check for new close button settings
1126 RemoveButton(wxAUI_BUTTON_LEFT
);
1127 RemoveButton(wxAUI_BUTTON_RIGHT
);
1128 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1129 RemoveButton(wxAUI_BUTTON_CLOSE
);
1132 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1134 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1135 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1138 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1140 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1143 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1145 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1150 m_art
->SetFlags(m_flags
);
1154 unsigned int wxAuiTabContainer::GetFlags() const
1160 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1162 m_art
->SetNormalFont(font
);
1165 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1167 m_art
->SetSelectedFont(font
);
1170 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1172 m_art
->SetMeasuringFont(font
);
1175 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1181 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1185 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1186 const wxAuiNotebookPage
& info
)
1188 wxAuiNotebookPage page_info
;
1190 page_info
.window
= page
;
1192 m_pages
.Add(page_info
);
1194 // let the art provider know how many pages we have
1197 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1203 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1204 const wxAuiNotebookPage
& info
,
1207 wxAuiNotebookPage page_info
;
1209 page_info
.window
= page
;
1211 if (idx
>= m_pages
.GetCount())
1212 m_pages
.Add(page_info
);
1214 m_pages
.Insert(page_info
, idx
);
1216 // let the art provider know how many pages we have
1219 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1225 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1228 int idx
= GetIdxFromWindow(page
);
1232 // get page entry, make a copy of it
1233 wxAuiNotebookPage p
= GetPage(idx
);
1235 // remove old page entry
1238 // insert page where it should be
1239 InsertPage(page
, p
, new_idx
);
1244 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1246 size_t i
, page_count
= m_pages
.GetCount();
1247 for (i
= 0; i
< page_count
; ++i
)
1249 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1250 if (page
.window
== wnd
)
1252 m_pages
.RemoveAt(i
);
1254 // let the art provider know how many pages we have
1257 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1267 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1271 size_t i
, page_count
= m_pages
.GetCount();
1272 for (i
= 0; i
< page_count
; ++i
)
1274 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1275 if (page
.window
== wnd
)
1282 page
.active
= false;
1289 void wxAuiTabContainer::SetNoneActive()
1291 size_t i
, page_count
= m_pages
.GetCount();
1292 for (i
= 0; i
< page_count
; ++i
)
1294 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1295 page
.active
= false;
1299 bool wxAuiTabContainer::SetActivePage(size_t page
)
1301 if (page
>= m_pages
.GetCount())
1304 return SetActivePage(m_pages
.Item(page
).window
);
1307 int wxAuiTabContainer::GetActivePage() const
1309 size_t i
, page_count
= m_pages
.GetCount();
1310 for (i
= 0; i
< page_count
; ++i
)
1312 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1320 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1322 if (idx
>= m_pages
.GetCount())
1325 return m_pages
[idx
].window
;
1328 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1330 size_t i
, page_count
= m_pages
.GetCount();
1331 for (i
= 0; i
< page_count
; ++i
)
1333 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1334 if (page
.window
== wnd
)
1340 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1342 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1344 return m_pages
[idx
];
1347 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1352 size_t wxAuiTabContainer::GetPageCount() const
1354 return m_pages
.GetCount();
1357 void wxAuiTabContainer::AddButton(int id
,
1359 const wxBitmap
& normal_bitmap
,
1360 const wxBitmap
& disabled_bitmap
)
1362 wxAuiTabContainerButton button
;
1364 button
.bitmap
= normal_bitmap
;
1365 button
.dis_bitmap
= disabled_bitmap
;
1366 button
.location
= location
;
1367 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1369 m_buttons
.Add(button
);
1372 void wxAuiTabContainer::RemoveButton(int id
)
1374 size_t i
, button_count
= m_buttons
.GetCount();
1376 for (i
= 0; i
< button_count
; ++i
)
1378 if (m_buttons
.Item(i
).id
== id
)
1380 m_buttons
.RemoveAt(i
);
1388 size_t wxAuiTabContainer::GetTabOffset() const
1390 return m_tab_offset
;
1393 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1395 m_tab_offset
= offset
;
1401 // Render() renders the tab catalog to the specified DC
1402 // It is a virtual function and can be overridden to
1403 // provide custom drawing capabilities
1404 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1409 size_t page_count
= m_pages
.GetCount();
1410 size_t button_count
= m_buttons
.GetCount();
1412 // create off-screen bitmap
1413 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1414 dc
.SelectObject(bmp
);
1417 // find out if size of tabs is larger than can be
1418 // afforded on screen
1419 int total_width
= 0;
1420 int visible_width
= 0;
1421 for (i
= 0; i
< page_count
; ++i
)
1423 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1425 // determine if a close button is on this tab
1426 bool close_button
= false;
1427 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1428 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1430 close_button
= true;
1435 wxSize size
= m_art
->GetTabSize(dc
,
1440 wxAUI_BUTTON_STATE_NORMAL
:
1441 wxAUI_BUTTON_STATE_HIDDEN
,
1444 if (i
+1 < page_count
)
1445 total_width
+= x_extent
;
1447 total_width
+= size
.x
;
1449 if (i
>= m_tab_offset
)
1451 if (i
+1 < page_count
)
1452 visible_width
+= x_extent
;
1454 visible_width
+= size
.x
;
1458 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1460 // show left/right buttons
1461 for (i
= 0; i
< button_count
; ++i
)
1463 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1464 if (button
.id
== wxAUI_BUTTON_LEFT
||
1465 button
.id
== wxAUI_BUTTON_RIGHT
)
1467 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1473 // hide left/right buttons
1474 for (i
= 0; i
< button_count
; ++i
)
1476 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1477 if (button
.id
== wxAUI_BUTTON_LEFT
||
1478 button
.id
== wxAUI_BUTTON_RIGHT
)
1480 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1485 // determine whether left button should be enabled
1486 for (i
= 0; i
< button_count
; ++i
)
1488 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1489 if (button
.id
== wxAUI_BUTTON_LEFT
)
1491 if (m_tab_offset
== 0)
1492 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1494 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1496 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1498 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1499 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1501 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1508 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1511 int left_buttons_width
= 0;
1512 int right_buttons_width
= 0;
1516 // draw the buttons on the right side
1517 offset
= m_rect
.x
+ m_rect
.width
;
1518 for (i
= 0; i
< button_count
; ++i
)
1520 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1522 if (button
.location
!= wxRIGHT
)
1524 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1527 wxRect button_rect
= m_rect
;
1528 button_rect
.SetY(1);
1529 button_rect
.SetWidth(offset
);
1531 m_art
->DrawButton(dc
,
1540 offset
-= button
.rect
.GetWidth();
1541 right_buttons_width
+= button
.rect
.GetWidth();
1548 // draw the buttons on the left side
1550 for (i
= 0; i
< button_count
; ++i
)
1552 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1554 if (button
.location
!= wxLEFT
)
1556 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1559 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1561 m_art
->DrawButton(dc
,
1570 offset
+= button
.rect
.GetWidth();
1571 left_buttons_width
+= button
.rect
.GetWidth();
1574 offset
= left_buttons_width
;
1577 offset
+= m_art
->GetIndentSize();
1579 // prepare the tab-close-button array
1580 while (m_tab_close_buttons
.GetCount() < page_count
)
1582 wxAuiTabContainerButton tempbtn
;
1583 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1584 tempbtn
.location
= wxCENTER
;
1585 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1586 m_tab_close_buttons
.Add(tempbtn
);
1589 for (i
= 0; i
< m_tab_offset
; ++i
)
1591 // buttons before the tab offset must be set to hidden
1592 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1598 size_t active
= 999;
1599 int active_offset
= 0;
1603 wxRect rect
= m_rect
;
1605 rect
.height
= m_rect
.height
;
1607 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1609 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1610 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1612 // determine if a close button is on this tab
1613 bool close_button
= false;
1614 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1615 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1617 close_button
= true;
1618 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1620 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1621 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1622 tab_button
.location
= wxCENTER
;
1627 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1631 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1633 if (rect
.width
<= 0)
1644 tab_button
.cur_state
,
1652 active_offset
= offset
;
1659 // draw the active tab again so it stands in the foreground
1660 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1662 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1664 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1666 // determine if a close button is on this tab
1667 bool close_button
= false;
1668 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1669 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1671 close_button
= true;
1674 rect
.x
= active_offset
;
1680 tab_button
.cur_state
,
1687 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1688 m_rect
.GetWidth(), m_rect
.GetHeight(),
1693 // TabHitTest() tests if a tab was hit, passing the window pointer
1694 // back if that condition was fulfilled. The function returns
1695 // true if a tab was hit, otherwise false
1696 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1698 if (!m_rect
.Contains(x
,y
))
1701 wxAuiTabContainerButton
* btn
= NULL
;
1702 if (ButtonHitTest(x
, y
, &btn
))
1704 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1708 size_t i
, page_count
= m_pages
.GetCount();
1710 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1712 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1713 if (page
.rect
.Contains(x
,y
))
1724 // ButtonHitTest() tests if a button was hit. The function returns
1725 // true if a button was hit, otherwise false
1726 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1727 wxAuiTabContainerButton
** hit
) const
1729 if (!m_rect
.Contains(x
,y
))
1732 size_t i
, button_count
;
1735 button_count
= m_buttons
.GetCount();
1736 for (i
= 0; i
< button_count
; ++i
)
1738 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1739 if (button
.rect
.Contains(x
,y
) &&
1740 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1741 wxAUI_BUTTON_STATE_DISABLED
)))
1749 button_count
= m_tab_close_buttons
.GetCount();
1750 for (i
= 0; i
< button_count
; ++i
)
1752 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1753 if (button
.rect
.Contains(x
,y
) &&
1754 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1755 wxAUI_BUTTON_STATE_DISABLED
)))
1768 // the utility function ShowWnd() is the same as show,
1769 // except it handles wxAuiMDIChildFrame windows as well,
1770 // as the Show() method on this class is "unplugged"
1771 static void ShowWnd(wxWindow
* wnd
, bool show
)
1773 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1775 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1785 // DoShowHide() this function shows the active window, then
1786 // hides all of the other windows (in that order)
1787 void wxAuiTabContainer::DoShowHide()
1789 wxAuiNotebookPageArray
& pages
= GetPages();
1790 size_t i
, page_count
= pages
.GetCount();
1792 // show new active page first
1793 for (i
= 0; i
< page_count
; ++i
)
1795 wxAuiNotebookPage
& page
= pages
.Item(i
);
1798 ShowWnd(page
.window
, true);
1803 // hide all other pages
1804 for (i
= 0; i
< page_count
; ++i
)
1806 wxAuiNotebookPage
& page
= pages
.Item(i
);
1807 ShowWnd(page
.window
, page
.active
);
1816 // -- wxAuiTabCtrl class implementation --
1820 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1821 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1822 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1823 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1824 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1825 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1826 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1827 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1828 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1832 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1836 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1838 m_click_pt
= wxDefaultPosition
;
1839 m_is_dragging
= false;
1840 m_hover_button
= NULL
;
1841 m_pressed_button
= NULL
;
1844 wxAuiTabCtrl::~wxAuiTabCtrl()
1848 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1852 dc
.SetFont(GetFont());
1854 if (GetPageCount() > 0)
1858 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1862 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1864 wxSize s
= evt
.GetSize();
1865 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1869 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1872 m_click_pt
= wxDefaultPosition
;
1873 m_is_dragging
= false;
1875 m_pressed_button
= NULL
;
1879 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1881 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1882 e
.SetSelection(GetIdxFromWindow(wnd
));
1883 e
.SetOldSelection(GetActivePage());
1884 e
.SetEventObject(this);
1885 GetEventHandler()->ProcessEvent(e
);
1887 m_click_pt
.x
= evt
.m_x
;
1888 m_click_pt
.y
= evt
.m_y
;
1894 m_pressed_button
= m_hover_button
;
1895 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1901 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
1903 if (GetCapture() == this)
1908 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1909 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1910 evt
.SetOldSelection(evt
.GetSelection());
1911 evt
.SetEventObject(this);
1912 GetEventHandler()->ProcessEvent(evt
);
1916 if (m_pressed_button
)
1918 // make sure we're still clicking the button
1919 wxAuiTabContainerButton
* button
= NULL
;
1920 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
1923 if (button
!= m_pressed_button
)
1925 m_pressed_button
= NULL
;
1932 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1934 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1935 evt
.SetInt(m_pressed_button
->id
);
1936 evt
.SetEventObject(this);
1937 GetEventHandler()->ProcessEvent(evt
);
1940 m_pressed_button
= NULL
;
1943 m_click_pt
= wxDefaultPosition
;
1944 m_is_dragging
= false;
1948 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1950 wxPoint pos
= evt
.GetPosition();
1952 // check if the mouse is hovering above a button
1953 wxAuiTabContainerButton
* button
;
1954 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1956 if (m_hover_button
&& button
!= m_hover_button
)
1958 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1959 m_hover_button
= NULL
;
1964 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1966 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1969 m_hover_button
= button
;
1977 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1978 m_hover_button
= NULL
;
1985 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1990 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1991 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1992 evt
.SetOldSelection(evt
.GetSelection());
1993 evt
.SetEventObject(this);
1994 GetEventHandler()->ProcessEvent(evt
);
1999 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2000 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2002 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2003 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2005 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2006 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2007 evt
.SetOldSelection(evt
.GetSelection());
2008 evt
.SetEventObject(this);
2009 GetEventHandler()->ProcessEvent(evt
);
2011 m_is_dragging
= true;
2015 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2019 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2020 m_hover_button
= NULL
;
2026 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2028 int button
= event
.GetInt();
2030 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2032 if (button
== wxAUI_BUTTON_LEFT
)
2034 if (GetTabOffset() > 0)
2036 SetTabOffset(GetTabOffset()-1);
2043 SetTabOffset(GetTabOffset()+1);
2048 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2052 size_t i
, page_count
= m_pages
.GetCount();
2053 for (i
= 0; i
< page_count
; ++i
)
2055 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2056 as
.Add(page
.caption
);
2059 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2063 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2064 e
.SetSelection(idx
);
2065 e
.SetOldSelection(GetActivePage());
2066 e
.SetEventObject(this);
2067 GetEventHandler()->ProcessEvent(e
);
2076 // wxTabFrame is an interesting case. It's important that all child pages
2077 // of the multi-notebook control are all actually children of that control
2078 // (and not grandchildren). wxTabFrame facilitates this. There is one
2079 // instance of wxTabFrame for each tab control inside the multi-notebook.
2080 // It's important to know that wxTabFrame is not a real window, but it merely
2081 // used to capture the dimensions/positioning of the internal tab control and
2082 // it's managed page windows
2084 class wxTabFrame
: public wxWindow
2091 m_rect
= wxRect(0,0,200,200);
2092 m_tab_ctrl_height
= 20;
2095 void SetTabCtrlHeight(int h
)
2097 m_tab_ctrl_height
= h
;
2100 void DoSetSize(int x
, int y
,
2101 int width
, int height
,
2102 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2104 m_rect
= wxRect(x
, y
, width
, height
);
2108 void DoGetClientSize(int* x
, int* y
) const
2114 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2121 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2122 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2123 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2127 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2128 size_t i
, page_count
= pages
.GetCount();
2130 for (i
= 0; i
< page_count
; ++i
)
2132 wxAuiNotebookPage
& page
= pages
.Item(i
);
2133 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2134 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2136 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2138 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2139 wnd
->ApplyMDIChildFrameRect();
2144 void DoGetSize(int* x
, int* y
) const
2147 *x
= m_rect
.GetWidth();
2149 *y
= m_rect
.GetHeight();
2161 wxAuiTabCtrl
* m_tabs
;
2162 int m_tab_ctrl_height
;
2169 // -- wxAuiNotebook class implementation --
2171 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2172 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2173 //EVT_SIZE(wxAuiNotebook::OnSize)
2174 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2175 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2176 EVT_COMMAND_RANGE(10000, 10100,
2177 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2178 wxAuiNotebook::OnTabClicked
)
2179 EVT_COMMAND_RANGE(10000, 10100,
2180 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2181 wxAuiNotebook::OnTabBeginDrag
)
2182 EVT_COMMAND_RANGE(10000, 10100,
2183 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2184 wxAuiNotebook::OnTabEndDrag
)
2185 EVT_COMMAND_RANGE(10000, 10100,
2186 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2187 wxAuiNotebook::OnTabDragMotion
)
2188 EVT_COMMAND_RANGE(10000, 10100,
2189 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2190 wxAuiNotebook::OnTabButton
)
2193 wxAuiNotebook::wxAuiNotebook()
2196 m_tab_id_counter
= 10000;
2198 m_tab_ctrl_height
= 20;
2201 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2205 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2207 InitNotebook(style
);
2210 bool wxAuiNotebook::Create(wxWindow
* parent
,
2216 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2219 InitNotebook(style
);
2224 // InitNotebook() contains common initialization
2225 // code called by all constructors
2226 void wxAuiNotebook::InitNotebook(long style
)
2229 m_tab_id_counter
= 10000;
2231 m_tab_ctrl_height
= 20;
2232 m_flags
= (unsigned int)style
;
2234 m_normal_font
= *wxNORMAL_FONT
;
2235 m_selected_font
= *wxNORMAL_FONT
;
2236 m_selected_font
.SetWeight(wxBOLD
);
2238 SetArtProvider(new wxAuiDefaultTabArt
);
2240 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2241 m_dummy_wnd
->SetSize(200, 200);
2242 m_dummy_wnd
->Show(false);
2244 m_mgr
.SetManagedWindow(this);
2246 m_mgr
.AddPane(m_dummy_wnd
,
2247 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2252 wxAuiNotebook::~wxAuiNotebook()
2257 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2259 m_tabs
.SetArtProvider(art
);
2261 // choose a default for the tab height
2262 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2264 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2265 size_t i
, pane_count
= all_panes
.GetCount();
2266 for (i
= 0; i
< pane_count
; ++i
)
2268 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2269 if (pane
.name
== wxT("dummy"))
2271 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2272 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2273 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2274 tabctrl
->SetArtProvider(art
->Clone());
2275 tab_frame
->DoSizing();
2280 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2282 return m_tabs
.GetArtProvider();
2285 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2287 wxControl::SetWindowStyleFlag(style
);
2289 m_flags
= (unsigned int)style
;
2291 // if the control is already initialized
2292 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2294 // let all of the tab children know about the new style
2296 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2297 size_t i
, pane_count
= all_panes
.GetCount();
2298 for (i
= 0; i
< pane_count
; ++i
)
2300 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2301 if (pane
.name
== wxT("dummy"))
2303 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2304 tabctrl
->SetFlags(m_flags
);
2312 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2313 const wxString
& caption
,
2315 const wxBitmap
& bitmap
)
2317 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2320 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2322 const wxString
& caption
,
2324 const wxBitmap
& bitmap
)
2326 wxAuiNotebookPage info
;
2328 info
.caption
= caption
;
2329 info
.bitmap
= bitmap
;
2330 info
.active
= false;
2332 // if there are currently no tabs, the first added
2333 // tab must be active
2334 if (m_tabs
.GetPageCount() == 0)
2337 m_tabs
.InsertPage(page
, info
, page_idx
);
2339 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2340 if (page_idx
>= active_tabctrl
->GetPageCount())
2341 active_tabctrl
->AddPage(page
, info
);
2343 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2346 active_tabctrl
->DoShowHide();
2350 int idx
= m_tabs
.GetIdxFromWindow(page
);
2351 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2360 // DeletePage() removes a tab from the multi-notebook,
2361 // and destroys the window as well
2362 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2364 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2366 if (!RemovePage(page_idx
))
2370 // actually destroy the window now
2371 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2373 // delete the child frame with pending delete, as is
2374 // customary with frame windows
2375 if (!wxPendingDelete
.Member(wnd
))
2376 wxPendingDelete
.Append(wnd
);
2388 // RemovePage() removes a tab from the multi-notebook,
2389 // but does not destroy the window
2390 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2392 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2393 wxWindow
* new_active
= NULL
;
2395 // find out which onscreen tab ctrl owns this tab
2398 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2401 // find a new page and set it as active
2402 int new_idx
= ctrl_idx
+1;
2403 if (new_idx
>= (int)ctrl
->GetPageCount())
2404 new_idx
= ctrl_idx
-1;
2406 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2408 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2412 // set the active page to the first page that
2413 // isn't the one being deleted
2414 size_t i
, page_count
= m_tabs
.GetPageCount();
2415 for (i
= 0; i
< page_count
; ++i
)
2417 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2420 new_active
= m_tabs
.GetWindowFromIdx(i
);
2426 // remove the tab from main catalog
2427 if (!m_tabs
.RemovePage(wnd
))
2430 // remove the tab from the onscreen tab ctrl
2431 ctrl
->RemovePage(wnd
);
2434 RemoveEmptyTabFrames();
2436 // set new active pane
2440 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2446 // SetPageText() changes the tab caption of the specified page
2447 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2449 if (page_idx
>= m_tabs
.GetPageCount())
2452 // update our own tab catalog
2453 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2454 page_info
.caption
= text
;
2456 // update what's on screen
2459 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2461 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2462 info
.caption
= text
;
2470 // GetSelection() returns the index of the currently active page
2471 int wxAuiNotebook::GetSelection() const
2476 // SetSelection() sets the currently active page
2477 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2479 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2483 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2484 evt
.SetSelection(new_page
);
2485 evt
.SetOldSelection(m_curpage
);
2486 evt
.SetEventObject(this);
2487 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2489 // program allows the page change
2490 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2491 (void)GetEventHandler()->ProcessEvent(evt
);
2497 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2499 m_tabs
.SetActivePage(wnd
);
2501 ctrl
->SetActivePage(ctrl_idx
);
2505 int old_curpage
= m_curpage
;
2506 m_curpage
= new_page
;
2510 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2511 size_t i
, pane_count
= all_panes
.GetCount();
2512 for (i
= 0; i
< pane_count
; ++i
)
2514 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2515 if (pane
.name
== wxT("dummy"))
2517 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2518 if (tabctrl
!= ctrl
)
2519 tabctrl
->SetSelectedFont(m_normal_font
);
2521 tabctrl
->SetSelectedFont(m_selected_font
);
2534 // GetPageCount() returns the total number of
2535 // pages managed by the multi-notebook
2536 size_t wxAuiNotebook::GetPageCount() const
2538 return m_tabs
.GetPageCount();
2541 // GetPage() returns the wxWindow pointer of the
2543 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2545 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2547 return m_tabs
.GetWindowFromIdx(page_idx
);
2550 // DoSizing() performs all sizing operations in each tab control
2551 void wxAuiNotebook::DoSizing()
2553 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2554 size_t i
, pane_count
= all_panes
.GetCount();
2555 for (i
= 0; i
< pane_count
; ++i
)
2557 if (all_panes
.Item(i
).name
== wxT("dummy"))
2560 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2561 tabframe
->DoSizing();
2565 // GetActiveTabCtrl() returns the active tab control. It is
2566 // called to determine which control gets new windows being added
2567 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2569 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2574 // find the tab ctrl with the current page
2575 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2582 // no current page, just find the first tab ctrl
2583 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2584 size_t i
, pane_count
= all_panes
.GetCount();
2585 for (i
= 0; i
< pane_count
; ++i
)
2587 if (all_panes
.Item(i
).name
== wxT("dummy"))
2590 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2591 return tabframe
->m_tabs
;
2594 // If there is no tabframe at all, create one
2595 wxTabFrame
* tabframe
= new wxTabFrame
;
2596 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2597 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2602 tabframe
->m_tabs
->SetFlags(m_flags
);
2603 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2604 m_mgr
.AddPane(tabframe
,
2605 wxAuiPaneInfo().Center().CaptionVisible(false));
2609 return tabframe
->m_tabs
;
2612 // FindTab() finds the tab control that currently contains the window as well
2613 // as the index of the window in the tab control. It returns true if the
2614 // window was found, otherwise false.
2615 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2617 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2618 size_t i
, pane_count
= all_panes
.GetCount();
2619 for (i
= 0; i
< pane_count
; ++i
)
2621 if (all_panes
.Item(i
).name
== wxT("dummy"))
2624 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2626 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2629 *ctrl
= tabframe
->m_tabs
;
2639 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2643 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2647 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2649 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2651 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2652 wxASSERT(ctrl
!= NULL
);
2654 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2655 wxASSERT(wnd
!= NULL
);
2657 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2658 wxASSERT(idx
!= -1);
2663 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2668 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2670 wxPoint screen_pt
= ::wxGetMousePosition();
2671 wxPoint client_pt
= ScreenToClient(screen_pt
);
2674 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2675 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2677 if (dest_tabs
== src_tabs
)
2681 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2684 // always hide the hint for inner-tabctrl drag
2687 // if tab moving is not allowed, leave
2688 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2693 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2694 wxWindow
* dest_location_tab
;
2696 // this is an inner-tab drag/reposition
2697 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2699 int src_idx
= evt
.GetSelection();
2700 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2702 // prevent jumpy drag
2703 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2704 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2705 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2707 m_last_drag_x
= pt
.x
;
2712 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2713 dest_tabs
->MovePage(src_tab
, dest_idx
);
2714 dest_tabs
->SetActivePage((size_t)dest_idx
);
2715 dest_tabs
->DoShowHide();
2716 dest_tabs
->Refresh();
2717 m_last_drag_x
= pt
.x
;
2725 // if external drag is allowed, check if the tab is being dragged
2726 // over a different wxAuiNotebook control
2727 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2729 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2731 // if we aren't over any window, stop here
2735 // make sure we are not over the hint window
2736 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2740 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2742 tab_ctrl
= tab_ctrl
->GetParent();
2747 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2751 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2752 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2753 m_mgr
.ShowHint(hint_rect
);
2762 // we are either over a hint window, or not over a tab
2763 // window, and there is no where to drag to, so exit
2770 // if there are less than two panes, split can't happen, so leave
2771 if (m_tabs
.GetPageCount() < 2)
2774 // if tab moving is not allowed, leave
2775 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2781 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2787 wxRect hint_rect
= dest_tabs
->GetRect();
2788 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2789 m_mgr
.ShowHint(hint_rect
);
2793 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2799 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2801 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2806 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2807 wxAuiTabCtrl
* dest_tabs
= NULL
;
2810 // set cursor back to an arrow
2811 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2814 // get the mouse position, which will be used to determine the drop point
2815 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2816 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2820 // check for an external move
2821 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2823 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2827 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2829 tab_ctrl
= tab_ctrl
->GetParent();
2834 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2838 // find out from the destination control
2839 // if it's ok to drop this tab here
2840 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2841 e
.SetSelection(evt
.GetSelection());
2842 e
.SetOldSelection(evt
.GetSelection());
2843 e
.SetEventObject(this);
2844 e
.SetDragSource(this);
2845 e
.Veto(); // dropping must be explicitly approved by control owner
2847 nb
->GetEventHandler()->ProcessEvent(e
);
2851 // no answer or negative answer
2857 int src_idx
= evt
.GetSelection();
2858 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2860 // get main index of the page
2861 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2863 // make a copy of the page info
2864 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2866 // remove the page from the source notebook
2867 RemovePage(main_idx
);
2869 // reparent the page
2870 src_page
->Reparent(nb
);
2873 // found out the insert idx
2874 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2875 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2877 wxWindow
* target
= NULL
;
2878 int insert_idx
= -1;
2879 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2882 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2886 // add the page to the new notebook
2887 if (insert_idx
== -1)
2888 insert_idx
= dest_tabs
->GetPageCount();
2889 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2890 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2893 dest_tabs
->DoShowHide();
2894 dest_tabs
->Refresh();
2896 // set the selection in the destination tab control
2897 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2907 // only perform a tab split if it's allowed
2908 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
2910 // If the pointer is in an existing tab frame, do a tab insert
2911 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2912 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2913 int insert_idx
= -1;
2916 dest_tabs
= tab_frame
->m_tabs
;
2918 if (dest_tabs
== src_tabs
)
2922 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2923 wxWindow
* target
= NULL
;
2924 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2927 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2932 // If there is no tabframe at all, create one
2933 wxTabFrame
* new_tabs
= new wxTabFrame
;
2934 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2935 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2940 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2941 new_tabs
->m_tabs
->SetFlags(m_flags
);
2943 m_mgr
.AddPane(new_tabs
,
2944 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2947 dest_tabs
= new_tabs
->m_tabs
;
2952 // remove the page from the source tabs
2953 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2954 page_info
.active
= false;
2955 src_tabs
->RemovePage(page_info
.window
);
2956 if (src_tabs
->GetPageCount() > 0)
2958 src_tabs
->SetActivePage((size_t)0);
2959 src_tabs
->DoShowHide();
2960 src_tabs
->Refresh();
2965 // add the page to the destination tabs
2966 if (insert_idx
== -1)
2967 insert_idx
= dest_tabs
->GetPageCount();
2968 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2970 if (src_tabs
->GetPageCount() == 0)
2972 RemoveEmptyTabFrames();
2976 dest_tabs
->DoShowHide();
2977 dest_tabs
->Refresh();
2979 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2985 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2987 // if we've just removed the last tab from the source
2988 // tab set, the remove the tab control completely
2989 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2990 size_t i
, pane_count
= all_panes
.GetCount();
2991 for (i
= 0; i
< pane_count
; ++i
)
2993 if (all_panes
.Item(i
).name
== wxT("dummy"))
2996 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2997 if (tabframe
->m_tab_rect
.Contains(pt
))
2998 return tabframe
->m_tabs
;
3004 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3006 // if we've just removed the last tab from the source
3007 // tab set, the remove the tab control completely
3008 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3009 size_t i
, pane_count
= all_panes
.GetCount();
3010 for (i
= 0; i
< pane_count
; ++i
)
3012 if (all_panes
.Item(i
).name
== wxT("dummy"))
3015 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3016 if (tabframe
->m_tabs
== tab_ctrl
)
3025 void wxAuiNotebook::RemoveEmptyTabFrames()
3027 // if we've just removed the last tab from the source
3028 // tab set, the remove the tab control completely
3029 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3030 size_t i
, pane_count
= all_panes
.GetCount();
3031 for (i
= 0; i
< pane_count
; ++i
)
3033 if (all_panes
.Item(i
).name
== wxT("dummy"))
3036 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3037 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3039 m_mgr
.DetachPane(tab_frame
);
3041 // use pending delete because sometimes during
3042 // window closing, refreshs are pending
3043 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3044 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3045 //tab_frame->m_tabs->Destroy();
3052 // check to see if there is still a center pane;
3053 // if there isn't, make a frame the center pane
3054 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3055 pane_count
= panes
.GetCount();
3056 wxWindow
* first_good
= NULL
;
3057 bool center_found
= false;
3058 for (i
= 0; i
< pane_count
; ++i
)
3060 if (panes
.Item(i
).name
== wxT("dummy"))
3062 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3063 center_found
= true;
3065 first_good
= panes
.Item(i
).window
;
3068 if (!center_found
&& first_good
)
3070 m_mgr
.GetPane(first_good
).Centre();
3076 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3078 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3079 if (idx
!= -1 && idx
!= m_curpage
)
3086 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3088 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3089 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3091 int button_id
= evt
.GetInt();
3093 if (button_id
== wxAUI_BUTTON_CLOSE
)
3095 int selection
= tabs
->GetActivePage();
3097 if (selection
!= -1)
3099 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3102 // ask owner if it's ok to close the tab
3103 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3104 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3105 e
.SetOldSelection(evt
.GetSelection());
3106 e
.SetEventObject(this);
3107 GetEventHandler()->ProcessEvent(e
);
3112 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3118 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3119 DeletePage(main_idx
);