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
)
1406 if (!raw_dc
|| !raw_dc
->IsOk())
1412 size_t page_count
= m_pages
.GetCount();
1413 size_t button_count
= m_buttons
.GetCount();
1415 // create off-screen bitmap
1416 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1417 dc
.SelectObject(bmp
);
1422 // find out if size of tabs is larger than can be
1423 // afforded on screen
1424 int total_width
= 0;
1425 int visible_width
= 0;
1426 for (i
= 0; i
< page_count
; ++i
)
1428 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1430 // determine if a close button is on this tab
1431 bool close_button
= false;
1432 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1433 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1435 close_button
= true;
1440 wxSize size
= m_art
->GetTabSize(dc
,
1445 wxAUI_BUTTON_STATE_NORMAL
:
1446 wxAUI_BUTTON_STATE_HIDDEN
,
1449 if (i
+1 < page_count
)
1450 total_width
+= x_extent
;
1452 total_width
+= size
.x
;
1454 if (i
>= m_tab_offset
)
1456 if (i
+1 < page_count
)
1457 visible_width
+= x_extent
;
1459 visible_width
+= size
.x
;
1463 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1465 // show left/right buttons
1466 for (i
= 0; i
< button_count
; ++i
)
1468 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1469 if (button
.id
== wxAUI_BUTTON_LEFT
||
1470 button
.id
== wxAUI_BUTTON_RIGHT
)
1472 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1478 // hide left/right buttons
1479 for (i
= 0; i
< button_count
; ++i
)
1481 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1482 if (button
.id
== wxAUI_BUTTON_LEFT
||
1483 button
.id
== wxAUI_BUTTON_RIGHT
)
1485 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1490 // determine whether left button should be enabled
1491 for (i
= 0; i
< button_count
; ++i
)
1493 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1494 if (button
.id
== wxAUI_BUTTON_LEFT
)
1496 if (m_tab_offset
== 0)
1497 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1499 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1501 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1503 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1504 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1506 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1513 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1516 int left_buttons_width
= 0;
1517 int right_buttons_width
= 0;
1521 // draw the buttons on the right side
1522 offset
= m_rect
.x
+ m_rect
.width
;
1523 for (i
= 0; i
< button_count
; ++i
)
1525 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1527 if (button
.location
!= wxRIGHT
)
1529 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1532 wxRect button_rect
= m_rect
;
1533 button_rect
.SetY(1);
1534 button_rect
.SetWidth(offset
);
1536 m_art
->DrawButton(dc
,
1545 offset
-= button
.rect
.GetWidth();
1546 right_buttons_width
+= button
.rect
.GetWidth();
1553 // draw the buttons on the left side
1555 for (i
= 0; i
< button_count
; ++i
)
1557 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1559 if (button
.location
!= wxLEFT
)
1561 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1564 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1566 m_art
->DrawButton(dc
,
1575 offset
+= button
.rect
.GetWidth();
1576 left_buttons_width
+= button
.rect
.GetWidth();
1579 offset
= left_buttons_width
;
1582 offset
+= m_art
->GetIndentSize();
1584 // prepare the tab-close-button array
1585 while (m_tab_close_buttons
.GetCount() < page_count
)
1587 wxAuiTabContainerButton tempbtn
;
1588 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1589 tempbtn
.location
= wxCENTER
;
1590 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1591 m_tab_close_buttons
.Add(tempbtn
);
1594 for (i
= 0; i
< m_tab_offset
; ++i
)
1596 // buttons before the tab offset must be set to hidden
1597 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1603 size_t active
= 999;
1604 int active_offset
= 0;
1608 wxRect rect
= m_rect
;
1610 rect
.height
= m_rect
.height
;
1612 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1614 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1615 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1617 // determine if a close button is on this tab
1618 bool close_button
= false;
1619 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1620 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1622 close_button
= true;
1623 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1625 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1626 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1627 tab_button
.location
= wxCENTER
;
1632 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1636 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1638 if (rect
.width
<= 0)
1649 tab_button
.cur_state
,
1657 active_offset
= offset
;
1664 // draw the active tab again so it stands in the foreground
1665 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1667 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1669 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1671 // determine if a close button is on this tab
1672 bool close_button
= false;
1673 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1674 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1676 close_button
= true;
1679 rect
.x
= active_offset
;
1685 tab_button
.cur_state
,
1692 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1693 m_rect
.GetWidth(), m_rect
.GetHeight(),
1698 // TabHitTest() tests if a tab was hit, passing the window pointer
1699 // back if that condition was fulfilled. The function returns
1700 // true if a tab was hit, otherwise false
1701 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1703 if (!m_rect
.Contains(x
,y
))
1706 wxAuiTabContainerButton
* btn
= NULL
;
1707 if (ButtonHitTest(x
, y
, &btn
))
1709 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1713 size_t i
, page_count
= m_pages
.GetCount();
1715 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1717 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1718 if (page
.rect
.Contains(x
,y
))
1729 // ButtonHitTest() tests if a button was hit. The function returns
1730 // true if a button was hit, otherwise false
1731 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1732 wxAuiTabContainerButton
** hit
) const
1734 if (!m_rect
.Contains(x
,y
))
1737 size_t i
, button_count
;
1740 button_count
= m_buttons
.GetCount();
1741 for (i
= 0; i
< button_count
; ++i
)
1743 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1744 if (button
.rect
.Contains(x
,y
) &&
1745 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1746 wxAUI_BUTTON_STATE_DISABLED
)))
1754 button_count
= m_tab_close_buttons
.GetCount();
1755 for (i
= 0; i
< button_count
; ++i
)
1757 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1758 if (button
.rect
.Contains(x
,y
) &&
1759 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1760 wxAUI_BUTTON_STATE_DISABLED
)))
1773 // the utility function ShowWnd() is the same as show,
1774 // except it handles wxAuiMDIChildFrame windows as well,
1775 // as the Show() method on this class is "unplugged"
1776 static void ShowWnd(wxWindow
* wnd
, bool show
)
1778 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1780 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1790 // DoShowHide() this function shows the active window, then
1791 // hides all of the other windows (in that order)
1792 void wxAuiTabContainer::DoShowHide()
1794 wxAuiNotebookPageArray
& pages
= GetPages();
1795 size_t i
, page_count
= pages
.GetCount();
1797 // show new active page first
1798 for (i
= 0; i
< page_count
; ++i
)
1800 wxAuiNotebookPage
& page
= pages
.Item(i
);
1803 ShowWnd(page
.window
, true);
1808 // hide all other pages
1809 for (i
= 0; i
< page_count
; ++i
)
1811 wxAuiNotebookPage
& page
= pages
.Item(i
);
1812 ShowWnd(page
.window
, page
.active
);
1821 // -- wxAuiTabCtrl class implementation --
1825 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1826 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1827 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1828 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1829 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1830 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1831 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1832 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1833 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1837 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1841 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1843 m_click_pt
= wxDefaultPosition
;
1844 m_is_dragging
= false;
1845 m_hover_button
= NULL
;
1846 m_pressed_button
= NULL
;
1849 wxAuiTabCtrl::~wxAuiTabCtrl()
1853 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1857 dc
.SetFont(GetFont());
1859 if (GetPageCount() > 0)
1863 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1867 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1869 wxSize s
= evt
.GetSize();
1870 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1874 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1877 m_click_pt
= wxDefaultPosition
;
1878 m_is_dragging
= false;
1880 m_pressed_button
= NULL
;
1884 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1886 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1887 e
.SetSelection(GetIdxFromWindow(wnd
));
1888 e
.SetOldSelection(GetActivePage());
1889 e
.SetEventObject(this);
1890 GetEventHandler()->ProcessEvent(e
);
1892 m_click_pt
.x
= evt
.m_x
;
1893 m_click_pt
.y
= evt
.m_y
;
1899 m_pressed_button
= m_hover_button
;
1900 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1906 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
1908 if (GetCapture() == this)
1913 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1914 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1915 evt
.SetOldSelection(evt
.GetSelection());
1916 evt
.SetEventObject(this);
1917 GetEventHandler()->ProcessEvent(evt
);
1921 if (m_pressed_button
)
1923 // make sure we're still clicking the button
1924 wxAuiTabContainerButton
* button
= NULL
;
1925 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
1928 if (button
!= m_pressed_button
)
1930 m_pressed_button
= NULL
;
1937 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1939 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1940 evt
.SetInt(m_pressed_button
->id
);
1941 evt
.SetEventObject(this);
1942 GetEventHandler()->ProcessEvent(evt
);
1945 m_pressed_button
= NULL
;
1948 m_click_pt
= wxDefaultPosition
;
1949 m_is_dragging
= false;
1953 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1955 wxPoint pos
= evt
.GetPosition();
1957 // check if the mouse is hovering above a button
1958 wxAuiTabContainerButton
* button
;
1959 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1961 if (m_hover_button
&& button
!= m_hover_button
)
1963 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1964 m_hover_button
= NULL
;
1969 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1971 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1974 m_hover_button
= button
;
1982 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1983 m_hover_button
= NULL
;
1990 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1995 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1996 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1997 evt
.SetOldSelection(evt
.GetSelection());
1998 evt
.SetEventObject(this);
1999 GetEventHandler()->ProcessEvent(evt
);
2004 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2005 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2007 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2008 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2010 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2011 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2012 evt
.SetOldSelection(evt
.GetSelection());
2013 evt
.SetEventObject(this);
2014 GetEventHandler()->ProcessEvent(evt
);
2016 m_is_dragging
= true;
2020 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2024 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2025 m_hover_button
= NULL
;
2031 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2033 int button
= event
.GetInt();
2035 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2037 if (button
== wxAUI_BUTTON_LEFT
)
2039 if (GetTabOffset() > 0)
2041 SetTabOffset(GetTabOffset()-1);
2048 SetTabOffset(GetTabOffset()+1);
2053 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2057 size_t i
, page_count
= m_pages
.GetCount();
2058 for (i
= 0; i
< page_count
; ++i
)
2060 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2061 as
.Add(page
.caption
);
2064 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2068 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2069 e
.SetSelection(idx
);
2070 e
.SetOldSelection(GetActivePage());
2071 e
.SetEventObject(this);
2072 GetEventHandler()->ProcessEvent(e
);
2081 // wxTabFrame is an interesting case. It's important that all child pages
2082 // of the multi-notebook control are all actually children of that control
2083 // (and not grandchildren). wxTabFrame facilitates this. There is one
2084 // instance of wxTabFrame for each tab control inside the multi-notebook.
2085 // It's important to know that wxTabFrame is not a real window, but it merely
2086 // used to capture the dimensions/positioning of the internal tab control and
2087 // it's managed page windows
2089 class wxTabFrame
: public wxWindow
2096 m_rect
= wxRect(0,0,200,200);
2097 m_tab_ctrl_height
= 20;
2100 void SetTabCtrlHeight(int h
)
2102 m_tab_ctrl_height
= h
;
2105 void DoSetSize(int x
, int y
,
2106 int width
, int height
,
2107 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2109 m_rect
= wxRect(x
, y
, width
, height
);
2113 void DoGetClientSize(int* x
, int* y
) const
2119 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2126 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2127 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2128 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2132 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2133 size_t i
, page_count
= pages
.GetCount();
2135 for (i
= 0; i
< page_count
; ++i
)
2137 wxAuiNotebookPage
& page
= pages
.Item(i
);
2138 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2139 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2141 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2143 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2144 wnd
->ApplyMDIChildFrameRect();
2149 void DoGetSize(int* x
, int* y
) const
2152 *x
= m_rect
.GetWidth();
2154 *y
= m_rect
.GetHeight();
2166 wxAuiTabCtrl
* m_tabs
;
2167 int m_tab_ctrl_height
;
2174 // -- wxAuiNotebook class implementation --
2176 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2177 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2178 //EVT_SIZE(wxAuiNotebook::OnSize)
2179 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2180 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2181 EVT_COMMAND_RANGE(10000, 10100,
2182 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2183 wxAuiNotebook::OnTabClicked
)
2184 EVT_COMMAND_RANGE(10000, 10100,
2185 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2186 wxAuiNotebook::OnTabBeginDrag
)
2187 EVT_COMMAND_RANGE(10000, 10100,
2188 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2189 wxAuiNotebook::OnTabEndDrag
)
2190 EVT_COMMAND_RANGE(10000, 10100,
2191 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2192 wxAuiNotebook::OnTabDragMotion
)
2193 EVT_COMMAND_RANGE(10000, 10100,
2194 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2195 wxAuiNotebook::OnTabButton
)
2198 wxAuiNotebook::wxAuiNotebook()
2201 m_tab_id_counter
= 10000;
2203 m_tab_ctrl_height
= 20;
2206 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2210 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2212 InitNotebook(style
);
2215 bool wxAuiNotebook::Create(wxWindow
* parent
,
2221 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2224 InitNotebook(style
);
2229 // InitNotebook() contains common initialization
2230 // code called by all constructors
2231 void wxAuiNotebook::InitNotebook(long style
)
2234 m_tab_id_counter
= 10000;
2236 m_tab_ctrl_height
= 20;
2237 m_flags
= (unsigned int)style
;
2239 m_normal_font
= *wxNORMAL_FONT
;
2240 m_selected_font
= *wxNORMAL_FONT
;
2241 m_selected_font
.SetWeight(wxBOLD
);
2243 SetArtProvider(new wxAuiDefaultTabArt
);
2245 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2246 m_dummy_wnd
->SetSize(200, 200);
2247 m_dummy_wnd
->Show(false);
2249 m_mgr
.SetManagedWindow(this);
2251 m_mgr
.AddPane(m_dummy_wnd
,
2252 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2257 wxAuiNotebook::~wxAuiNotebook()
2262 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2264 m_tabs
.SetArtProvider(art
);
2266 // choose a default for the tab height
2267 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2269 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2270 size_t i
, pane_count
= all_panes
.GetCount();
2271 for (i
= 0; i
< pane_count
; ++i
)
2273 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2274 if (pane
.name
== wxT("dummy"))
2276 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2277 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2278 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2279 tabctrl
->SetArtProvider(art
->Clone());
2280 tab_frame
->DoSizing();
2285 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2287 return m_tabs
.GetArtProvider();
2290 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2292 wxControl::SetWindowStyleFlag(style
);
2294 m_flags
= (unsigned int)style
;
2296 // if the control is already initialized
2297 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2299 // let all of the tab children know about the new style
2301 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2302 size_t i
, pane_count
= all_panes
.GetCount();
2303 for (i
= 0; i
< pane_count
; ++i
)
2305 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2306 if (pane
.name
== wxT("dummy"))
2308 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2309 tabctrl
->SetFlags(m_flags
);
2317 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2318 const wxString
& caption
,
2320 const wxBitmap
& bitmap
)
2322 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2325 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2327 const wxString
& caption
,
2329 const wxBitmap
& bitmap
)
2331 wxAuiNotebookPage info
;
2333 info
.caption
= caption
;
2334 info
.bitmap
= bitmap
;
2335 info
.active
= false;
2337 // if there are currently no tabs, the first added
2338 // tab must be active
2339 if (m_tabs
.GetPageCount() == 0)
2342 m_tabs
.InsertPage(page
, info
, page_idx
);
2344 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2345 if (page_idx
>= active_tabctrl
->GetPageCount())
2346 active_tabctrl
->AddPage(page
, info
);
2348 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2351 active_tabctrl
->DoShowHide();
2355 int idx
= m_tabs
.GetIdxFromWindow(page
);
2356 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2365 // DeletePage() removes a tab from the multi-notebook,
2366 // and destroys the window as well
2367 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2369 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2371 if (!RemovePage(page_idx
))
2375 // actually destroy the window now
2376 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2378 // delete the child frame with pending delete, as is
2379 // customary with frame windows
2380 if (!wxPendingDelete
.Member(wnd
))
2381 wxPendingDelete
.Append(wnd
);
2393 // RemovePage() removes a tab from the multi-notebook,
2394 // but does not destroy the window
2395 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2397 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2398 wxWindow
* new_active
= NULL
;
2400 // find out which onscreen tab ctrl owns this tab
2403 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2406 // find a new page and set it as active
2407 int new_idx
= ctrl_idx
+1;
2408 if (new_idx
>= (int)ctrl
->GetPageCount())
2409 new_idx
= ctrl_idx
-1;
2411 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2413 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2417 // set the active page to the first page that
2418 // isn't the one being deleted
2419 size_t i
, page_count
= m_tabs
.GetPageCount();
2420 for (i
= 0; i
< page_count
; ++i
)
2422 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2425 new_active
= m_tabs
.GetWindowFromIdx(i
);
2431 // remove the tab from main catalog
2432 if (!m_tabs
.RemovePage(wnd
))
2435 // remove the tab from the onscreen tab ctrl
2436 ctrl
->RemovePage(wnd
);
2439 RemoveEmptyTabFrames();
2441 // set new active pane
2445 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2451 // SetPageText() changes the tab caption of the specified page
2452 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2454 if (page_idx
>= m_tabs
.GetPageCount())
2457 // update our own tab catalog
2458 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2459 page_info
.caption
= text
;
2461 // update what's on screen
2464 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2466 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2467 info
.caption
= text
;
2475 // GetSelection() returns the index of the currently active page
2476 int wxAuiNotebook::GetSelection() const
2481 // SetSelection() sets the currently active page
2482 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2484 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2488 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2489 evt
.SetSelection(new_page
);
2490 evt
.SetOldSelection(m_curpage
);
2491 evt
.SetEventObject(this);
2492 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2494 // program allows the page change
2495 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2496 (void)GetEventHandler()->ProcessEvent(evt
);
2502 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2504 m_tabs
.SetActivePage(wnd
);
2506 ctrl
->SetActivePage(ctrl_idx
);
2510 int old_curpage
= m_curpage
;
2511 m_curpage
= new_page
;
2515 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2516 size_t i
, pane_count
= all_panes
.GetCount();
2517 for (i
= 0; i
< pane_count
; ++i
)
2519 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2520 if (pane
.name
== wxT("dummy"))
2522 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2523 if (tabctrl
!= ctrl
)
2524 tabctrl
->SetSelectedFont(m_normal_font
);
2526 tabctrl
->SetSelectedFont(m_selected_font
);
2539 // GetPageCount() returns the total number of
2540 // pages managed by the multi-notebook
2541 size_t wxAuiNotebook::GetPageCount() const
2543 return m_tabs
.GetPageCount();
2546 // GetPage() returns the wxWindow pointer of the
2548 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2550 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2552 return m_tabs
.GetWindowFromIdx(page_idx
);
2555 // DoSizing() performs all sizing operations in each tab control
2556 void wxAuiNotebook::DoSizing()
2558 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2559 size_t i
, pane_count
= all_panes
.GetCount();
2560 for (i
= 0; i
< pane_count
; ++i
)
2562 if (all_panes
.Item(i
).name
== wxT("dummy"))
2565 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2566 tabframe
->DoSizing();
2570 // GetActiveTabCtrl() returns the active tab control. It is
2571 // called to determine which control gets new windows being added
2572 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2574 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2579 // find the tab ctrl with the current page
2580 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2587 // no current page, just find the first tab ctrl
2588 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2589 size_t i
, pane_count
= all_panes
.GetCount();
2590 for (i
= 0; i
< pane_count
; ++i
)
2592 if (all_panes
.Item(i
).name
== wxT("dummy"))
2595 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2596 return tabframe
->m_tabs
;
2599 // If there is no tabframe at all, create one
2600 wxTabFrame
* tabframe
= new wxTabFrame
;
2601 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2602 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2607 tabframe
->m_tabs
->SetFlags(m_flags
);
2608 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2609 m_mgr
.AddPane(tabframe
,
2610 wxAuiPaneInfo().Center().CaptionVisible(false));
2614 return tabframe
->m_tabs
;
2617 // FindTab() finds the tab control that currently contains the window as well
2618 // as the index of the window in the tab control. It returns true if the
2619 // window was found, otherwise false.
2620 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2622 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2623 size_t i
, pane_count
= all_panes
.GetCount();
2624 for (i
= 0; i
< pane_count
; ++i
)
2626 if (all_panes
.Item(i
).name
== wxT("dummy"))
2629 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2631 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2634 *ctrl
= tabframe
->m_tabs
;
2644 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2648 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2652 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2654 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2656 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2657 wxASSERT(ctrl
!= NULL
);
2659 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2660 wxASSERT(wnd
!= NULL
);
2662 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2663 wxASSERT(idx
!= -1);
2668 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2673 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2675 wxPoint screen_pt
= ::wxGetMousePosition();
2676 wxPoint client_pt
= ScreenToClient(screen_pt
);
2679 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2680 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2682 if (dest_tabs
== src_tabs
)
2686 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2689 // always hide the hint for inner-tabctrl drag
2692 // if tab moving is not allowed, leave
2693 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2698 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2699 wxWindow
* dest_location_tab
;
2701 // this is an inner-tab drag/reposition
2702 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2704 int src_idx
= evt
.GetSelection();
2705 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2707 // prevent jumpy drag
2708 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2709 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2710 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2712 m_last_drag_x
= pt
.x
;
2717 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2718 dest_tabs
->MovePage(src_tab
, dest_idx
);
2719 dest_tabs
->SetActivePage((size_t)dest_idx
);
2720 dest_tabs
->DoShowHide();
2721 dest_tabs
->Refresh();
2722 m_last_drag_x
= pt
.x
;
2730 // if external drag is allowed, check if the tab is being dragged
2731 // over a different wxAuiNotebook control
2732 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2734 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2736 // if we aren't over any window, stop here
2740 // make sure we are not over the hint window
2741 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2745 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2747 tab_ctrl
= tab_ctrl
->GetParent();
2752 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2756 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2757 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2758 m_mgr
.ShowHint(hint_rect
);
2767 // we are either over a hint window, or not over a tab
2768 // window, and there is no where to drag to, so exit
2775 // if there are less than two panes, split can't happen, so leave
2776 if (m_tabs
.GetPageCount() < 2)
2779 // if tab moving is not allowed, leave
2780 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2786 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2792 wxRect hint_rect
= dest_tabs
->GetRect();
2793 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2794 m_mgr
.ShowHint(hint_rect
);
2798 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2804 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2806 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2811 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2812 wxAuiTabCtrl
* dest_tabs
= NULL
;
2815 // set cursor back to an arrow
2816 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2819 // get the mouse position, which will be used to determine the drop point
2820 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2821 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2825 // check for an external move
2826 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2828 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2832 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2834 tab_ctrl
= tab_ctrl
->GetParent();
2839 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2843 // find out from the destination control
2844 // if it's ok to drop this tab here
2845 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2846 e
.SetSelection(evt
.GetSelection());
2847 e
.SetOldSelection(evt
.GetSelection());
2848 e
.SetEventObject(this);
2849 e
.SetDragSource(this);
2850 e
.Veto(); // dropping must be explicitly approved by control owner
2852 nb
->GetEventHandler()->ProcessEvent(e
);
2856 // no answer or negative answer
2862 int src_idx
= evt
.GetSelection();
2863 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2865 // get main index of the page
2866 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2868 // make a copy of the page info
2869 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2871 // remove the page from the source notebook
2872 RemovePage(main_idx
);
2874 // reparent the page
2875 src_page
->Reparent(nb
);
2878 // found out the insert idx
2879 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2880 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2882 wxWindow
* target
= NULL
;
2883 int insert_idx
= -1;
2884 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2887 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2891 // add the page to the new notebook
2892 if (insert_idx
== -1)
2893 insert_idx
= dest_tabs
->GetPageCount();
2894 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2895 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2898 dest_tabs
->DoShowHide();
2899 dest_tabs
->Refresh();
2901 // set the selection in the destination tab control
2902 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2912 // only perform a tab split if it's allowed
2913 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
2915 // If the pointer is in an existing tab frame, do a tab insert
2916 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2917 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2918 int insert_idx
= -1;
2921 dest_tabs
= tab_frame
->m_tabs
;
2923 if (dest_tabs
== src_tabs
)
2927 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2928 wxWindow
* target
= NULL
;
2929 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2932 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2937 // If there is no tabframe at all, create one
2938 wxTabFrame
* new_tabs
= new wxTabFrame
;
2939 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2940 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2945 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2946 new_tabs
->m_tabs
->SetFlags(m_flags
);
2948 m_mgr
.AddPane(new_tabs
,
2949 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2952 dest_tabs
= new_tabs
->m_tabs
;
2957 // remove the page from the source tabs
2958 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2959 page_info
.active
= false;
2960 src_tabs
->RemovePage(page_info
.window
);
2961 if (src_tabs
->GetPageCount() > 0)
2963 src_tabs
->SetActivePage((size_t)0);
2964 src_tabs
->DoShowHide();
2965 src_tabs
->Refresh();
2970 // add the page to the destination tabs
2971 if (insert_idx
== -1)
2972 insert_idx
= dest_tabs
->GetPageCount();
2973 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2975 if (src_tabs
->GetPageCount() == 0)
2977 RemoveEmptyTabFrames();
2981 dest_tabs
->DoShowHide();
2982 dest_tabs
->Refresh();
2984 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2990 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2992 // if we've just removed the last tab from the source
2993 // tab set, the remove the tab control completely
2994 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2995 size_t i
, pane_count
= all_panes
.GetCount();
2996 for (i
= 0; i
< pane_count
; ++i
)
2998 if (all_panes
.Item(i
).name
== wxT("dummy"))
3001 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3002 if (tabframe
->m_tab_rect
.Contains(pt
))
3003 return tabframe
->m_tabs
;
3009 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3011 // if we've just removed the last tab from the source
3012 // tab set, the remove the tab control completely
3013 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3014 size_t i
, pane_count
= all_panes
.GetCount();
3015 for (i
= 0; i
< pane_count
; ++i
)
3017 if (all_panes
.Item(i
).name
== wxT("dummy"))
3020 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3021 if (tabframe
->m_tabs
== tab_ctrl
)
3030 void wxAuiNotebook::RemoveEmptyTabFrames()
3032 // if we've just removed the last tab from the source
3033 // tab set, the remove the tab control completely
3034 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3035 size_t i
, pane_count
= all_panes
.GetCount();
3036 for (i
= 0; i
< pane_count
; ++i
)
3038 if (all_panes
.Item(i
).name
== wxT("dummy"))
3041 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3042 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3044 m_mgr
.DetachPane(tab_frame
);
3046 // use pending delete because sometimes during
3047 // window closing, refreshs are pending
3048 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3049 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3050 //tab_frame->m_tabs->Destroy();
3057 // check to see if there is still a center pane;
3058 // if there isn't, make a frame the center pane
3059 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3060 pane_count
= panes
.GetCount();
3061 wxWindow
* first_good
= NULL
;
3062 bool center_found
= false;
3063 for (i
= 0; i
< pane_count
; ++i
)
3065 if (panes
.Item(i
).name
== wxT("dummy"))
3067 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3068 center_found
= true;
3070 first_good
= panes
.Item(i
).window
;
3073 if (!center_found
&& first_good
)
3075 m_mgr
.GetPane(first_good
).Centre();
3081 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3083 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3084 if (idx
!= -1 && idx
!= m_curpage
)
3091 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3093 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3094 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3096 int button_id
= evt
.GetInt();
3098 if (button_id
== wxAUI_BUTTON_CLOSE
)
3100 int selection
= tabs
->GetActivePage();
3102 if (selection
!= -1)
3104 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3107 // ask owner if it's ok to close the tab
3108 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3109 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3110 e
.SetOldSelection(evt
.GetSelection());
3111 e
.SetEventObject(this);
3112 GetEventHandler()->ProcessEvent(e
);
3117 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3123 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3124 DeletePage(main_idx
);