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;
224 m_tab_ctrl_height
= 0;
226 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
228 wxColour background_colour
= base_colour
;
229 wxColour normaltab_colour
= base_colour
;
230 wxColour selectedtab_colour
= base_colour
;
232 m_bkbrush
= wxBrush(background_colour
);
233 m_normal_bkbrush
= wxBrush(normaltab_colour
);
234 m_normal_bkpen
= wxPen(normaltab_colour
);
235 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
236 m_selected_bkpen
= wxPen(selectedtab_colour
);
239 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
240 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
242 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
243 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
245 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
246 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
248 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
249 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
254 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
258 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
260 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
263 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
268 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
271 m_fixed_tab_width
= 100;
273 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
276 m_fixed_tab_width
= tot_width
/(int)tab_count
;
280 if (m_fixed_tab_width
< 100)
281 m_fixed_tab_width
= 100;
283 if (m_fixed_tab_width
> tot_width
/2)
284 m_fixed_tab_width
= tot_width
/2;
286 if (m_fixed_tab_width
> 220)
287 m_fixed_tab_width
= 220;
289 m_tab_ctrl_height
= tab_ctrl_size
.y
;
293 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
294 wxWindow
* WXUNUSED(wnd
),
298 dc
.SetBrush(m_bkbrush
);
299 dc
.SetPen(*wxTRANSPARENT_PEN
);
300 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
303 dc
.SetPen(*wxGREY_PEN
);
304 dc
.DrawLine(0, rect
.GetHeight()-4, rect
.GetWidth(), rect
.GetHeight()-4);
305 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
309 // DrawTab() draws an individual tab.
312 // in_rect - rectangle the tab should be confined to
313 // caption - tab's caption
314 // active - whether or not the tab is active
315 // out_rect - actual output rectangle
316 // x_extent - the advance x; where the next tab should start
318 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
320 const wxRect
& in_rect
,
321 const wxString
& caption_text
,
322 const wxBitmap
& bitmap
,
324 int close_button_state
,
325 wxRect
* out_tab_rect
,
326 wxRect
* out_button_rect
,
329 wxCoord normal_textx
, normal_texty
;
330 wxCoord selected_textx
, selected_texty
;
331 wxCoord textx
, texty
;
333 // if the caption is empty, measure some temporary text
334 wxString caption
= caption_text
;
335 if (caption_text
.empty())
338 dc
.SetFont(m_selected_font
);
339 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
341 dc
.SetFont(m_normal_font
);
342 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
344 // figure out the size of the tab
345 wxSize tab_size
= GetTabSize(dc
,
353 wxCoord tab_height
= m_tab_ctrl_height
- 3;
354 wxCoord tab_width
= tab_size
.x
;
355 wxCoord tab_x
= in_rect
.x
;
356 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
359 caption
= caption_text
;
361 dc
.SetClippingRegion(in_rect
);
365 // select pen, brush and font for the tab to be drawn
369 dc
.SetPen(m_selected_bkpen
);
370 dc
.SetBrush(m_selected_bkbrush
);
371 dc
.SetFont(m_selected_font
);
372 textx
= selected_textx
;
373 texty
= selected_texty
;
377 dc
.SetPen(m_normal_bkpen
);
378 dc
.SetBrush(m_normal_bkbrush
);
379 dc
.SetFont(m_normal_font
);
380 textx
= normal_textx
;
381 texty
= normal_texty
;
385 // create points that will make the tab outline
389 points
[0].y
= tab_y
+ tab_height
- 4;
391 points
[1].y
= tab_y
+ 2;
392 points
[2].x
= tab_x
+ 2;
394 points
[3].x
= tab_x
+ tab_width
- 2;
396 points
[4].x
= tab_x
+ tab_width
;
397 points
[4].y
= tab_y
+ 2;
398 points
[5].x
= tab_x
+ tab_width
;
399 points
[5].y
= tab_y
+ tab_height
- 4;
401 int drawn_tab_yoff
= points
[1].y
;
402 int drawn_tab_height
= points
[0].y
- points
[1].y
;
405 // draw gradient background
408 wxColour c
= m_bkbrush
.GetColour();
412 for (y
= points
[0].y
; y
> points
[2].y
; --y
)
414 if (y
< tab_y
+(tab_height
*3/5) && y
!= last_y
)
417 c
= StepColour(c
, 102);
421 dc
.DrawLine(points
[0].x
+1, y
, points
[5].x
, y
);
426 dc
.SetPen(*wxGREY_PEN
);
427 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
428 dc
.DrawPolygon(6, points
);
430 // there are two horizontal grey lines at the bottom of the tab control,
431 // this gets rid of the top one of those lines in the tab control
434 wxColour c
= m_bkbrush
.GetColour();
436 dc
.DrawLine(points
[0].x
, points
[0].y
, points
[5].x
+1, points
[5].y
);
440 int text_offset
= tab_x
+ 8;
441 int close_button_width
= 0;
442 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
444 close_button_width
= m_active_close_bmp
.GetWidth();
450 int bitmap_offset
= tab_x
+ 8;
453 dc
.DrawBitmap(bitmap
,
455 drawn_tab_yoff
+ (drawn_tab_height
/2) - (bitmap
.GetHeight()/2) + 1,
458 text_offset
= bitmap_offset
+ bitmap
.GetWidth();
459 text_offset
+= 3; // bitmap padding
463 text_offset
= tab_x
+ 8;
467 wxString draw_text
= ChopText(dc
,
469 tab_width
- (text_offset
-tab_x
) - close_button_width
);
472 dc
.DrawText(draw_text
,
474 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
479 // draw close button if necessary
480 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
482 wxBitmap bmp
= m_disabled_close_bmp
;
484 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
485 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
487 bmp
= m_active_close_bmp
;
490 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
491 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
494 IndentPressedBitmap(&rect
, close_button_state
);
495 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
497 *out_button_rect
= rect
;
500 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
502 dc
.DestroyClippingRegion();
505 int wxAuiDefaultTabArt::GetIndentSize()
510 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
511 wxWindow
* WXUNUSED(wnd
),
512 const wxString
& caption
,
513 const wxBitmap
& bitmap
,
514 bool WXUNUSED(active
),
515 int close_button_state
,
518 wxCoord measured_textx
, measured_texty
, tmp
;
520 dc
.SetFont(m_measuring_font
);
521 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
523 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
525 // add padding around the text
526 wxCoord tab_width
= measured_textx
;
527 wxCoord tab_height
= measured_texty
;
529 // if the close button is showing, add space for it
530 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
531 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
533 // if there's a bitmap, add space for it
536 tab_width
+= bitmap
.GetWidth();
537 tab_width
+= 3; // right side bitmap padding
538 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
545 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
547 tab_width
= m_fixed_tab_width
;
550 *x_extent
= tab_width
;
552 return wxSize(tab_width
, tab_height
);
556 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
557 wxWindow
* WXUNUSED(wnd
),
558 const wxRect
& in_rect
,
562 const wxBitmap
& bitmap_override
,
568 if (bitmap_override
.IsOk())
570 bmp
= bitmap_override
;
576 case wxAUI_BUTTON_CLOSE
:
577 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
578 bmp
= m_disabled_close_bmp
;
580 bmp
= m_active_close_bmp
;
582 case wxAUI_BUTTON_LEFT
:
583 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
584 bmp
= m_disabled_left_bmp
;
586 bmp
= m_active_left_bmp
;
588 case wxAUI_BUTTON_RIGHT
:
589 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
590 bmp
= m_disabled_right_bmp
;
592 bmp
= m_active_right_bmp
;
594 case wxAUI_BUTTON_WINDOWLIST
:
595 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
596 bmp
= m_disabled_windowlist_bmp
;
598 bmp
= m_active_windowlist_bmp
;
608 if (orientation
== wxLEFT
)
610 rect
.SetX(in_rect
.x
);
611 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
612 rect
.SetWidth(bmp
.GetWidth());
613 rect
.SetHeight(bmp
.GetHeight());
617 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
618 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
619 bmp
.GetWidth(), bmp
.GetHeight());
622 IndentPressedBitmap(&rect
, button_state
);
623 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
629 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
630 const wxArrayString
& items
,
635 size_t i
, count
= items
.GetCount();
636 for (i
= 0; i
< count
; ++i
)
638 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
641 if (active_idx
!= -1)
643 menuPopup
.Check(1000+active_idx
, true);
646 // find out where to put the popup menu of window
647 // items. Subtract 100 for now to center the menu
648 // a bit, until a better mechanism can be implemented
649 wxPoint pt
= ::wxGetMousePosition();
650 pt
= wnd
->ScreenToClient(pt
);
656 // find out the screen coordinate at the bottom of the tab ctrl
657 wxRect cli_rect
= wnd
->GetClientRect();
658 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
660 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
661 wnd
->PushEventHandler(cc
);
662 wnd
->PopupMenu(&menuPopup
, pt
);
663 int command
= cc
->GetCommandId();
664 wnd
->PopEventHandler(true);
672 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
673 wxAuiNotebookPageArray
& pages
)
676 dc
.SetFont(m_measuring_font
);
679 size_t i
, page_count
= pages
.GetCount();
680 for (i
= 0; i
< page_count
; ++i
)
682 wxAuiNotebookPage
& page
= pages
.Item(i
);
684 // we don't use the caption text because we don't
685 // want tab heights to be different in the case
686 // of a very short piece of text on one tab and a very
687 // tall piece of text on another tab
689 wxSize s
= GetTabSize(dc
,
694 wxAUI_BUTTON_STATE_HIDDEN
,
696 max_y
= wxMax(max_y
, s
.y
);
702 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
704 m_normal_font
= font
;
707 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
709 m_selected_font
= font
;
712 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
714 m_measuring_font
= font
;
718 // -- wxAuiSimpleTabArt class implementation --
720 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
722 m_normal_font
= *wxNORMAL_FONT
;
723 m_selected_font
= *wxNORMAL_FONT
;
724 m_selected_font
.SetWeight(wxBOLD
);
725 m_measuring_font
= m_selected_font
;
728 m_fixed_tab_width
= 100;
730 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
732 wxColour background_colour
= StepColour(base_colour
, 95);
733 wxColour normaltab_colour
= base_colour
;
734 wxColour selectedtab_colour
= *wxWHITE
;
736 m_bkbrush
= wxBrush(background_colour
);
737 m_normal_bkbrush
= wxBrush(normaltab_colour
);
738 m_normal_bkpen
= wxPen(normaltab_colour
);
739 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
740 m_selected_bkpen
= wxPen(selectedtab_colour
);
742 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
743 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
745 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
746 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
748 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
749 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
751 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
752 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
756 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
760 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
762 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
766 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
771 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
774 m_fixed_tab_width
= 100;
776 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
779 m_fixed_tab_width
= tot_width
/(int)tab_count
;
783 if (m_fixed_tab_width
< 100)
784 m_fixed_tab_width
= 100;
786 if (m_fixed_tab_width
> tot_width
/2)
787 m_fixed_tab_width
= tot_width
/2;
789 if (m_fixed_tab_width
> 220)
790 m_fixed_tab_width
= 220;
793 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
794 wxWindow
* WXUNUSED(wnd
),
798 dc
.SetBrush(m_bkbrush
);
799 dc
.SetPen(*wxTRANSPARENT_PEN
);
800 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
803 dc
.SetPen(*wxGREY_PEN
);
804 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
808 // DrawTab() draws an individual tab.
811 // in_rect - rectangle the tab should be confined to
812 // caption - tab's caption
813 // active - whether or not the tab is active
814 // out_rect - actual output rectangle
815 // x_extent - the advance x; where the next tab should start
817 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
819 const wxRect
& in_rect
,
820 const wxString
& caption_text
,
821 const wxBitmap
& bitmap
,
823 int close_button_state
,
824 wxRect
* out_tab_rect
,
825 wxRect
* out_button_rect
,
828 wxCoord normal_textx
, normal_texty
;
829 wxCoord selected_textx
, selected_texty
;
830 wxCoord textx
, texty
;
832 // if the caption is empty, measure some temporary text
833 wxString caption
= caption_text
;
834 if (caption_text
.empty())
837 dc
.SetFont(m_selected_font
);
838 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
840 dc
.SetFont(m_normal_font
);
841 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
843 // figure out the size of the tab
844 wxSize tab_size
= GetTabSize(dc
,
852 wxCoord tab_height
= tab_size
.y
;
853 wxCoord tab_width
= tab_size
.x
;
854 wxCoord tab_x
= in_rect
.x
;
855 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
857 caption
= caption_text
;
859 // select pen, brush and font for the tab to be drawn
863 dc
.SetPen(m_selected_bkpen
);
864 dc
.SetBrush(m_selected_bkbrush
);
865 dc
.SetFont(m_selected_font
);
866 textx
= selected_textx
;
867 texty
= selected_texty
;
871 dc
.SetPen(m_normal_bkpen
);
872 dc
.SetBrush(m_normal_bkbrush
);
873 dc
.SetFont(m_normal_font
);
874 textx
= normal_textx
;
875 texty
= normal_texty
;
883 points
[0].y
= tab_y
+ tab_height
- 1;
884 points
[1].x
= tab_x
+ tab_height
- 3;
885 points
[1].y
= tab_y
+ 2;
886 points
[2].x
= tab_x
+ tab_height
+ 3;
888 points
[3].x
= tab_x
+ tab_width
- 2;
890 points
[4].x
= tab_x
+ tab_width
;
891 points
[4].y
= tab_y
+ 2;
892 points
[5].x
= tab_x
+ tab_width
;
893 points
[5].y
= tab_y
+ tab_height
- 1;
894 points
[6] = points
[0];
896 dc
.SetClippingRegion(in_rect
);
898 dc
.DrawPolygon(6, points
);
900 dc
.SetPen(*wxGREY_PEN
);
902 //dc.DrawLines(active ? 6 : 7, points);
903 dc
.DrawLines(7, points
);
908 int close_button_width
= 0;
909 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
911 close_button_width
= m_active_close_bmp
.GetWidth();
912 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
916 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
919 // set minimum text offset
920 if (text_offset
< tab_x
+ tab_height
)
921 text_offset
= tab_x
+ tab_height
;
923 // chop text if necessary
924 wxString draw_text
= ChopText(dc
,
926 tab_width
- (text_offset
-tab_x
) - close_button_width
);
929 dc
.DrawText(draw_text
,
931 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
934 // draw close button if necessary
935 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
939 bmp
= m_active_close_bmp
;
941 bmp
= m_disabled_close_bmp
;
943 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
944 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
947 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
949 *out_button_rect
= rect
;
953 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
955 dc
.DestroyClippingRegion();
958 int wxAuiSimpleTabArt::GetIndentSize()
963 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
964 wxWindow
* WXUNUSED(wnd
),
965 const wxString
& caption
,
966 const wxBitmap
& WXUNUSED(bitmap
),
967 bool WXUNUSED(active
),
968 int close_button_state
,
971 wxCoord measured_textx
, measured_texty
;
973 dc
.SetFont(m_measuring_font
);
974 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
976 wxCoord tab_height
= measured_texty
+ 4;
977 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
979 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
980 tab_width
+= m_active_close_bmp
.GetWidth();
982 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
984 tab_width
= m_fixed_tab_width
;
987 *x_extent
= tab_width
- (tab_height
/2) - 1;
989 return wxSize(tab_width
, tab_height
);
993 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
994 wxWindow
* WXUNUSED(wnd
),
995 const wxRect
& in_rect
,
999 const wxBitmap
& bitmap_override
,
1005 if (bitmap_override
.IsOk())
1007 bmp
= bitmap_override
;
1013 case wxAUI_BUTTON_CLOSE
:
1014 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1015 bmp
= m_disabled_close_bmp
;
1017 bmp
= m_active_close_bmp
;
1019 case wxAUI_BUTTON_LEFT
:
1020 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1021 bmp
= m_disabled_left_bmp
;
1023 bmp
= m_active_left_bmp
;
1025 case wxAUI_BUTTON_RIGHT
:
1026 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1027 bmp
= m_disabled_right_bmp
;
1029 bmp
= m_active_right_bmp
;
1031 case wxAUI_BUTTON_WINDOWLIST
:
1032 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1033 bmp
= m_disabled_windowlist_bmp
;
1035 bmp
= m_active_windowlist_bmp
;
1045 if (orientation
== wxLEFT
)
1047 rect
.SetX(in_rect
.x
);
1048 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1049 rect
.SetWidth(bmp
.GetWidth());
1050 rect
.SetHeight(bmp
.GetHeight());
1054 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1055 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1056 bmp
.GetWidth(), bmp
.GetHeight());
1060 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1066 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
1067 const wxArrayString
& items
,
1072 size_t i
, count
= items
.GetCount();
1073 for (i
= 0; i
< count
; ++i
)
1075 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1078 if (active_idx
!= -1)
1080 menuPopup
.Check(1000+active_idx
, true);
1083 // find out where to put the popup menu of window
1084 // items. Subtract 100 for now to center the menu
1085 // a bit, until a better mechanism can be implemented
1086 wxPoint pt
= ::wxGetMousePosition();
1087 pt
= wnd
->ScreenToClient(pt
);
1093 // find out the screen coordinate at the bottom of the tab ctrl
1094 wxRect cli_rect
= wnd
->GetClientRect();
1095 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1097 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1098 wnd
->PushEventHandler(cc
);
1099 wnd
->PopupMenu(&menuPopup
, pt
);
1100 int command
= cc
->GetCommandId();
1101 wnd
->PopEventHandler(true);
1103 if (command
>= 1000)
1104 return command
-1000;
1109 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1110 wxAuiNotebookPageArray
& WXUNUSED(pages
))
1113 dc
.SetFont(m_measuring_font
);
1115 wxSize s
= GetTabSize(dc
,
1120 wxAUI_BUTTON_STATE_HIDDEN
,
1125 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1127 m_normal_font
= font
;
1130 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1132 m_selected_font
= font
;
1135 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1137 m_measuring_font
= font
;
1143 // -- wxAuiTabContainer class implementation --
1146 // wxAuiTabContainer is a class which contains information about each
1147 // tab. It also can render an entire tab control to a specified DC.
1148 // It's not a window class itself, because this code will be used by
1149 // the wxFrameMananger, where it is disadvantageous to have separate
1150 // windows for each tab control in the case of "docked tabs"
1152 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1153 // which can be used as a tab control in the normal sense.
1156 wxAuiTabContainer::wxAuiTabContainer()
1160 m_art
= new wxAuiDefaultTabArt
;
1162 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1163 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1164 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1165 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1168 wxAuiTabContainer::~wxAuiTabContainer()
1173 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1180 m_art
->SetFlags(m_flags
);
1184 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1189 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1193 // check for new close button settings
1194 RemoveButton(wxAUI_BUTTON_LEFT
);
1195 RemoveButton(wxAUI_BUTTON_RIGHT
);
1196 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1197 RemoveButton(wxAUI_BUTTON_CLOSE
);
1200 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1202 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1203 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1206 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1208 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1211 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1213 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1218 m_art
->SetFlags(m_flags
);
1222 unsigned int wxAuiTabContainer::GetFlags() const
1228 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1230 m_art
->SetNormalFont(font
);
1233 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1235 m_art
->SetSelectedFont(font
);
1238 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1240 m_art
->SetMeasuringFont(font
);
1243 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1249 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1253 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1254 const wxAuiNotebookPage
& info
)
1256 wxAuiNotebookPage page_info
;
1258 page_info
.window
= page
;
1260 m_pages
.Add(page_info
);
1262 // let the art provider know how many pages we have
1265 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1271 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1272 const wxAuiNotebookPage
& info
,
1275 wxAuiNotebookPage page_info
;
1277 page_info
.window
= page
;
1279 if (idx
>= m_pages
.GetCount())
1280 m_pages
.Add(page_info
);
1282 m_pages
.Insert(page_info
, idx
);
1284 // let the art provider know how many pages we have
1287 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1293 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1296 int idx
= GetIdxFromWindow(page
);
1300 // get page entry, make a copy of it
1301 wxAuiNotebookPage p
= GetPage(idx
);
1303 // remove old page entry
1306 // insert page where it should be
1307 InsertPage(page
, p
, new_idx
);
1312 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1314 size_t i
, page_count
= m_pages
.GetCount();
1315 for (i
= 0; i
< page_count
; ++i
)
1317 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1318 if (page
.window
== wnd
)
1320 m_pages
.RemoveAt(i
);
1322 // let the art provider know how many pages we have
1325 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1335 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1339 size_t i
, page_count
= m_pages
.GetCount();
1340 for (i
= 0; i
< page_count
; ++i
)
1342 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1343 if (page
.window
== wnd
)
1350 page
.active
= false;
1357 void wxAuiTabContainer::SetNoneActive()
1359 size_t i
, page_count
= m_pages
.GetCount();
1360 for (i
= 0; i
< page_count
; ++i
)
1362 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1363 page
.active
= false;
1367 bool wxAuiTabContainer::SetActivePage(size_t page
)
1369 if (page
>= m_pages
.GetCount())
1372 return SetActivePage(m_pages
.Item(page
).window
);
1375 int wxAuiTabContainer::GetActivePage() const
1377 size_t i
, page_count
= m_pages
.GetCount();
1378 for (i
= 0; i
< page_count
; ++i
)
1380 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1388 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1390 if (idx
>= m_pages
.GetCount())
1393 return m_pages
[idx
].window
;
1396 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1398 size_t i
, page_count
= m_pages
.GetCount();
1399 for (i
= 0; i
< page_count
; ++i
)
1401 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1402 if (page
.window
== wnd
)
1408 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1410 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1412 return m_pages
[idx
];
1415 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1420 size_t wxAuiTabContainer::GetPageCount() const
1422 return m_pages
.GetCount();
1425 void wxAuiTabContainer::AddButton(int id
,
1427 const wxBitmap
& normal_bitmap
,
1428 const wxBitmap
& disabled_bitmap
)
1430 wxAuiTabContainerButton button
;
1432 button
.bitmap
= normal_bitmap
;
1433 button
.dis_bitmap
= disabled_bitmap
;
1434 button
.location
= location
;
1435 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1437 m_buttons
.Add(button
);
1440 void wxAuiTabContainer::RemoveButton(int id
)
1442 size_t i
, button_count
= m_buttons
.GetCount();
1444 for (i
= 0; i
< button_count
; ++i
)
1446 if (m_buttons
.Item(i
).id
== id
)
1448 m_buttons
.RemoveAt(i
);
1456 size_t wxAuiTabContainer::GetTabOffset() const
1458 return m_tab_offset
;
1461 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1463 m_tab_offset
= offset
;
1469 // Render() renders the tab catalog to the specified DC
1470 // It is a virtual function and can be overridden to
1471 // provide custom drawing capabilities
1472 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1474 if (!raw_dc
|| !raw_dc
->IsOk())
1480 size_t page_count
= m_pages
.GetCount();
1481 size_t button_count
= m_buttons
.GetCount();
1483 // create off-screen bitmap
1484 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1485 dc
.SelectObject(bmp
);
1490 // find out if size of tabs is larger than can be
1491 // afforded on screen
1492 int total_width
= 0;
1493 int visible_width
= 0;
1494 for (i
= 0; i
< page_count
; ++i
)
1496 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1498 // determine if a close button is on this tab
1499 bool close_button
= false;
1500 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1501 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1503 close_button
= true;
1508 wxSize size
= m_art
->GetTabSize(dc
,
1514 wxAUI_BUTTON_STATE_NORMAL
:
1515 wxAUI_BUTTON_STATE_HIDDEN
,
1518 if (i
+1 < page_count
)
1519 total_width
+= x_extent
;
1521 total_width
+= size
.x
;
1523 if (i
>= m_tab_offset
)
1525 if (i
+1 < page_count
)
1526 visible_width
+= x_extent
;
1528 visible_width
+= size
.x
;
1532 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1534 // show left/right buttons
1535 for (i
= 0; i
< button_count
; ++i
)
1537 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1538 if (button
.id
== wxAUI_BUTTON_LEFT
||
1539 button
.id
== wxAUI_BUTTON_RIGHT
)
1541 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1547 // hide left/right buttons
1548 for (i
= 0; i
< button_count
; ++i
)
1550 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1551 if (button
.id
== wxAUI_BUTTON_LEFT
||
1552 button
.id
== wxAUI_BUTTON_RIGHT
)
1554 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1559 // determine whether left button should be enabled
1560 for (i
= 0; i
< button_count
; ++i
)
1562 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1563 if (button
.id
== wxAUI_BUTTON_LEFT
)
1565 if (m_tab_offset
== 0)
1566 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1568 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1570 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1572 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1573 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1575 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1582 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1585 int left_buttons_width
= 0;
1586 int right_buttons_width
= 0;
1590 // draw the buttons on the right side
1591 offset
= m_rect
.x
+ m_rect
.width
;
1592 for (i
= 0; i
< button_count
; ++i
)
1594 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1596 if (button
.location
!= wxRIGHT
)
1598 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1601 wxRect button_rect
= m_rect
;
1602 button_rect
.SetY(1);
1603 button_rect
.SetWidth(offset
);
1605 m_art
->DrawButton(dc
,
1614 offset
-= button
.rect
.GetWidth();
1615 right_buttons_width
+= button
.rect
.GetWidth();
1622 // draw the buttons on the left side
1624 for (i
= 0; i
< button_count
; ++i
)
1626 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1628 if (button
.location
!= wxLEFT
)
1630 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1633 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1635 m_art
->DrawButton(dc
,
1644 offset
+= button
.rect
.GetWidth();
1645 left_buttons_width
+= button
.rect
.GetWidth();
1648 offset
= left_buttons_width
;
1651 offset
+= m_art
->GetIndentSize();
1653 // prepare the tab-close-button array
1654 while (m_tab_close_buttons
.GetCount() < page_count
)
1656 wxAuiTabContainerButton tempbtn
;
1657 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1658 tempbtn
.location
= wxCENTER
;
1659 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1660 m_tab_close_buttons
.Add(tempbtn
);
1663 for (i
= 0; i
< m_tab_offset
; ++i
)
1665 // buttons before the tab offset must be set to hidden
1666 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1672 size_t active
= 999;
1673 int active_offset
= 0;
1677 wxRect rect
= m_rect
;
1679 rect
.height
= m_rect
.height
;
1681 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1683 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1684 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1686 // determine if a close button is on this tab
1687 bool close_button
= false;
1688 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1689 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1691 close_button
= true;
1692 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1694 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1695 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1696 tab_button
.location
= wxCENTER
;
1701 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1705 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1707 if (rect
.width
<= 0)
1719 tab_button
.cur_state
,
1727 active_offset
= offset
;
1734 // draw the active tab again so it stands in the foreground
1735 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1737 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1739 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1741 // determine if a close button is on this tab
1742 bool close_button
= false;
1743 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1744 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1746 close_button
= true;
1749 rect
.x
= active_offset
;
1756 tab_button
.cur_state
,
1763 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1764 m_rect
.GetWidth(), m_rect
.GetHeight(),
1769 // TabHitTest() tests if a tab was hit, passing the window pointer
1770 // back if that condition was fulfilled. The function returns
1771 // true if a tab was hit, otherwise false
1772 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1774 if (!m_rect
.Contains(x
,y
))
1777 wxAuiTabContainerButton
* btn
= NULL
;
1778 if (ButtonHitTest(x
, y
, &btn
))
1780 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1784 size_t i
, page_count
= m_pages
.GetCount();
1786 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1788 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1789 if (page
.rect
.Contains(x
,y
))
1800 // ButtonHitTest() tests if a button was hit. The function returns
1801 // true if a button was hit, otherwise false
1802 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1803 wxAuiTabContainerButton
** hit
) const
1805 if (!m_rect
.Contains(x
,y
))
1808 size_t i
, button_count
;
1811 button_count
= m_buttons
.GetCount();
1812 for (i
= 0; i
< button_count
; ++i
)
1814 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1815 if (button
.rect
.Contains(x
,y
) &&
1816 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1817 wxAUI_BUTTON_STATE_DISABLED
)))
1825 button_count
= m_tab_close_buttons
.GetCount();
1826 for (i
= 0; i
< button_count
; ++i
)
1828 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1829 if (button
.rect
.Contains(x
,y
) &&
1830 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1831 wxAUI_BUTTON_STATE_DISABLED
)))
1844 // the utility function ShowWnd() is the same as show,
1845 // except it handles wxAuiMDIChildFrame windows as well,
1846 // as the Show() method on this class is "unplugged"
1847 static void ShowWnd(wxWindow
* wnd
, bool show
)
1849 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1851 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1861 // DoShowHide() this function shows the active window, then
1862 // hides all of the other windows (in that order)
1863 void wxAuiTabContainer::DoShowHide()
1865 wxAuiNotebookPageArray
& pages
= GetPages();
1866 size_t i
, page_count
= pages
.GetCount();
1868 // show new active page first
1869 for (i
= 0; i
< page_count
; ++i
)
1871 wxAuiNotebookPage
& page
= pages
.Item(i
);
1874 ShowWnd(page
.window
, true);
1879 // hide all other pages
1880 for (i
= 0; i
< page_count
; ++i
)
1882 wxAuiNotebookPage
& page
= pages
.Item(i
);
1883 ShowWnd(page
.window
, page
.active
);
1892 // -- wxAuiTabCtrl class implementation --
1896 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1897 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1898 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1899 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1900 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1901 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1902 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1903 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1904 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1908 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1912 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1914 m_click_pt
= wxDefaultPosition
;
1915 m_is_dragging
= false;
1916 m_hover_button
= NULL
;
1917 m_pressed_button
= NULL
;
1920 wxAuiTabCtrl::~wxAuiTabCtrl()
1924 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1928 dc
.SetFont(GetFont());
1930 if (GetPageCount() > 0)
1934 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1938 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1940 wxSize s
= evt
.GetSize();
1941 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1945 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1948 m_click_pt
= wxDefaultPosition
;
1949 m_is_dragging
= false;
1951 m_pressed_button
= NULL
;
1955 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1957 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1958 e
.SetSelection(GetIdxFromWindow(wnd
));
1959 e
.SetOldSelection(GetActivePage());
1960 e
.SetEventObject(this);
1961 GetEventHandler()->ProcessEvent(e
);
1963 m_click_pt
.x
= evt
.m_x
;
1964 m_click_pt
.y
= evt
.m_y
;
1970 m_pressed_button
= m_hover_button
;
1971 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1977 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
1979 if (GetCapture() == this)
1984 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1985 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1986 evt
.SetOldSelection(evt
.GetSelection());
1987 evt
.SetEventObject(this);
1988 GetEventHandler()->ProcessEvent(evt
);
1992 if (m_pressed_button
)
1994 // make sure we're still clicking the button
1995 wxAuiTabContainerButton
* button
= NULL
;
1996 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
1999 if (button
!= m_pressed_button
)
2001 m_pressed_button
= NULL
;
2008 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2010 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2011 evt
.SetInt(m_pressed_button
->id
);
2012 evt
.SetEventObject(this);
2013 GetEventHandler()->ProcessEvent(evt
);
2016 m_pressed_button
= NULL
;
2019 m_click_pt
= wxDefaultPosition
;
2020 m_is_dragging
= false;
2024 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2026 wxPoint pos
= evt
.GetPosition();
2028 // check if the mouse is hovering above a button
2029 wxAuiTabContainerButton
* button
;
2030 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2032 if (m_hover_button
&& button
!= m_hover_button
)
2034 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2035 m_hover_button
= NULL
;
2040 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2042 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2045 m_hover_button
= button
;
2053 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2054 m_hover_button
= NULL
;
2061 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2066 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2067 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2068 evt
.SetOldSelection(evt
.GetSelection());
2069 evt
.SetEventObject(this);
2070 GetEventHandler()->ProcessEvent(evt
);
2075 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2076 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2078 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2079 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2081 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2082 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2083 evt
.SetOldSelection(evt
.GetSelection());
2084 evt
.SetEventObject(this);
2085 GetEventHandler()->ProcessEvent(evt
);
2087 m_is_dragging
= true;
2091 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2095 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2096 m_hover_button
= NULL
;
2102 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2104 int button
= event
.GetInt();
2106 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2108 if (button
== wxAUI_BUTTON_LEFT
)
2110 if (GetTabOffset() > 0)
2112 SetTabOffset(GetTabOffset()-1);
2119 SetTabOffset(GetTabOffset()+1);
2124 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2128 size_t i
, page_count
= m_pages
.GetCount();
2129 for (i
= 0; i
< page_count
; ++i
)
2131 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2132 as
.Add(page
.caption
);
2135 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2139 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2140 e
.SetSelection(idx
);
2141 e
.SetOldSelection(GetActivePage());
2142 e
.SetEventObject(this);
2143 GetEventHandler()->ProcessEvent(e
);
2152 // wxTabFrame is an interesting case. It's important that all child pages
2153 // of the multi-notebook control are all actually children of that control
2154 // (and not grandchildren). wxTabFrame facilitates this. There is one
2155 // instance of wxTabFrame for each tab control inside the multi-notebook.
2156 // It's important to know that wxTabFrame is not a real window, but it merely
2157 // used to capture the dimensions/positioning of the internal tab control and
2158 // it's managed page windows
2160 class wxTabFrame
: public wxWindow
2167 m_rect
= wxRect(0,0,200,200);
2168 m_tab_ctrl_height
= 20;
2171 void SetTabCtrlHeight(int h
)
2173 m_tab_ctrl_height
= h
;
2176 void DoSetSize(int x
, int y
,
2177 int width
, int height
,
2178 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2180 m_rect
= wxRect(x
, y
, width
, height
);
2184 void DoGetClientSize(int* x
, int* y
) const
2190 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2197 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2198 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2199 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2203 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2204 size_t i
, page_count
= pages
.GetCount();
2206 for (i
= 0; i
< page_count
; ++i
)
2208 wxAuiNotebookPage
& page
= pages
.Item(i
);
2209 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2210 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2212 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2214 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2215 wnd
->ApplyMDIChildFrameRect();
2220 void DoGetSize(int* x
, int* y
) const
2223 *x
= m_rect
.GetWidth();
2225 *y
= m_rect
.GetHeight();
2237 wxAuiTabCtrl
* m_tabs
;
2238 int m_tab_ctrl_height
;
2245 // -- wxAuiNotebook class implementation --
2247 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2248 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2249 //EVT_SIZE(wxAuiNotebook::OnSize)
2250 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2251 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2252 EVT_COMMAND_RANGE(10000, 10100,
2253 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2254 wxAuiNotebook::OnTabClicked
)
2255 EVT_COMMAND_RANGE(10000, 10100,
2256 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2257 wxAuiNotebook::OnTabBeginDrag
)
2258 EVT_COMMAND_RANGE(10000, 10100,
2259 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2260 wxAuiNotebook::OnTabEndDrag
)
2261 EVT_COMMAND_RANGE(10000, 10100,
2262 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2263 wxAuiNotebook::OnTabDragMotion
)
2264 EVT_COMMAND_RANGE(10000, 10100,
2265 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2266 wxAuiNotebook::OnTabButton
)
2269 wxAuiNotebook::wxAuiNotebook()
2272 m_tab_id_counter
= 10000;
2274 m_tab_ctrl_height
= 20;
2277 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2281 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2283 InitNotebook(style
);
2286 bool wxAuiNotebook::Create(wxWindow
* parent
,
2292 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2295 InitNotebook(style
);
2300 // InitNotebook() contains common initialization
2301 // code called by all constructors
2302 void wxAuiNotebook::InitNotebook(long style
)
2305 m_tab_id_counter
= 10000;
2307 m_tab_ctrl_height
= 20;
2308 m_flags
= (unsigned int)style
;
2310 m_normal_font
= *wxNORMAL_FONT
;
2311 m_selected_font
= *wxNORMAL_FONT
;
2312 m_selected_font
.SetWeight(wxBOLD
);
2314 SetArtProvider(new wxAuiDefaultTabArt
);
2316 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2317 m_dummy_wnd
->SetSize(200, 200);
2318 m_dummy_wnd
->Show(false);
2320 m_mgr
.SetManagedWindow(this);
2322 m_mgr
.AddPane(m_dummy_wnd
,
2323 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2328 wxAuiNotebook::~wxAuiNotebook()
2333 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2335 m_tabs
.SetArtProvider(art
);
2337 SetTabCtrlHeight(CalculateTabCtrlHeight());
2340 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2342 // if the tab control height needs to change, update
2343 // all of our tab controls with the new height
2344 if (m_tab_ctrl_height
!= height
)
2346 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2348 m_tab_ctrl_height
= height
;
2350 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2351 size_t i
, pane_count
= all_panes
.GetCount();
2352 for (i
= 0; i
< pane_count
; ++i
)
2354 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2355 if (pane
.name
== wxT("dummy"))
2357 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2358 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2359 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2360 tabctrl
->SetArtProvider(art
->Clone());
2361 tab_frame
->DoSizing();
2366 int wxAuiNotebook::CalculateTabCtrlHeight()
2368 // find out new best tab height
2369 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2371 return art
->GetBestTabCtrlSize(this, m_tabs
.GetPages());
2375 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2377 return m_tabs
.GetArtProvider();
2380 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2382 wxControl::SetWindowStyleFlag(style
);
2384 m_flags
= (unsigned int)style
;
2386 // if the control is already initialized
2387 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2389 // let all of the tab children know about the new style
2391 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2392 size_t i
, pane_count
= all_panes
.GetCount();
2393 for (i
= 0; i
< pane_count
; ++i
)
2395 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2396 if (pane
.name
== wxT("dummy"))
2398 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2399 tabctrl
->SetFlags(m_flags
);
2407 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2408 const wxString
& caption
,
2410 const wxBitmap
& bitmap
)
2412 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2415 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2417 const wxString
& caption
,
2419 const wxBitmap
& bitmap
)
2421 wxAuiNotebookPage info
;
2423 info
.caption
= caption
;
2424 info
.bitmap
= bitmap
;
2425 info
.active
= false;
2427 // if there are currently no tabs, the first added
2428 // tab must be active
2429 if (m_tabs
.GetPageCount() == 0)
2432 m_tabs
.InsertPage(page
, info
, page_idx
);
2434 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2435 if (page_idx
>= active_tabctrl
->GetPageCount())
2436 active_tabctrl
->AddPage(page
, info
);
2438 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2440 SetTabCtrlHeight(CalculateTabCtrlHeight());
2442 active_tabctrl
->DoShowHide();
2446 int idx
= m_tabs
.GetIdxFromWindow(page
);
2447 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2456 // DeletePage() removes a tab from the multi-notebook,
2457 // and destroys the window as well
2458 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2460 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2462 if (!RemovePage(page_idx
))
2466 // actually destroy the window now
2467 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2469 // delete the child frame with pending delete, as is
2470 // customary with frame windows
2471 if (!wxPendingDelete
.Member(wnd
))
2472 wxPendingDelete
.Append(wnd
);
2484 // RemovePage() removes a tab from the multi-notebook,
2485 // but does not destroy the window
2486 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2488 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2489 wxWindow
* new_active
= NULL
;
2491 // find out which onscreen tab ctrl owns this tab
2494 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2497 // find a new page and set it as active
2498 int new_idx
= ctrl_idx
+1;
2499 if (new_idx
>= (int)ctrl
->GetPageCount())
2500 new_idx
= ctrl_idx
-1;
2502 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2504 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2508 // set the active page to the first page that
2509 // isn't the one being deleted
2510 size_t i
, page_count
= m_tabs
.GetPageCount();
2511 for (i
= 0; i
< page_count
; ++i
)
2513 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2516 new_active
= m_tabs
.GetWindowFromIdx(i
);
2522 // remove the tab from main catalog
2523 if (!m_tabs
.RemovePage(wnd
))
2526 // remove the tab from the onscreen tab ctrl
2527 ctrl
->RemovePage(wnd
);
2530 RemoveEmptyTabFrames();
2532 // set new active pane
2536 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2542 // SetPageText() changes the tab caption of the specified page
2543 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2545 if (page_idx
>= m_tabs
.GetPageCount())
2548 // update our own tab catalog
2549 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2550 page_info
.caption
= text
;
2552 // update what's on screen
2555 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2557 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2558 info
.caption
= text
;
2566 // GetSelection() returns the index of the currently active page
2567 int wxAuiNotebook::GetSelection() const
2572 // SetSelection() sets the currently active page
2573 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2575 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2579 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2580 evt
.SetSelection(new_page
);
2581 evt
.SetOldSelection(m_curpage
);
2582 evt
.SetEventObject(this);
2583 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2585 // program allows the page change
2586 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2587 (void)GetEventHandler()->ProcessEvent(evt
);
2593 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2595 m_tabs
.SetActivePage(wnd
);
2597 ctrl
->SetActivePage(ctrl_idx
);
2601 int old_curpage
= m_curpage
;
2602 m_curpage
= new_page
;
2606 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2607 size_t i
, pane_count
= all_panes
.GetCount();
2608 for (i
= 0; i
< pane_count
; ++i
)
2610 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2611 if (pane
.name
== wxT("dummy"))
2613 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2614 if (tabctrl
!= ctrl
)
2615 tabctrl
->SetSelectedFont(m_normal_font
);
2617 tabctrl
->SetSelectedFont(m_selected_font
);
2630 // GetPageCount() returns the total number of
2631 // pages managed by the multi-notebook
2632 size_t wxAuiNotebook::GetPageCount() const
2634 return m_tabs
.GetPageCount();
2637 // GetPage() returns the wxWindow pointer of the
2639 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2641 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2643 return m_tabs
.GetWindowFromIdx(page_idx
);
2646 // DoSizing() performs all sizing operations in each tab control
2647 void wxAuiNotebook::DoSizing()
2649 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2650 size_t i
, pane_count
= all_panes
.GetCount();
2651 for (i
= 0; i
< pane_count
; ++i
)
2653 if (all_panes
.Item(i
).name
== wxT("dummy"))
2656 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2657 tabframe
->DoSizing();
2661 // GetActiveTabCtrl() returns the active tab control. It is
2662 // called to determine which control gets new windows being added
2663 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2665 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2670 // find the tab ctrl with the current page
2671 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2678 // no current page, just find the first tab ctrl
2679 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2680 size_t i
, pane_count
= all_panes
.GetCount();
2681 for (i
= 0; i
< pane_count
; ++i
)
2683 if (all_panes
.Item(i
).name
== wxT("dummy"))
2686 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2687 return tabframe
->m_tabs
;
2690 // If there is no tabframe at all, create one
2691 wxTabFrame
* tabframe
= new wxTabFrame
;
2692 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2693 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2698 tabframe
->m_tabs
->SetFlags(m_flags
);
2699 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2700 m_mgr
.AddPane(tabframe
,
2701 wxAuiPaneInfo().Center().CaptionVisible(false));
2705 return tabframe
->m_tabs
;
2708 // FindTab() finds the tab control that currently contains the window as well
2709 // as the index of the window in the tab control. It returns true if the
2710 // window was found, otherwise false.
2711 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2713 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2714 size_t i
, pane_count
= all_panes
.GetCount();
2715 for (i
= 0; i
< pane_count
; ++i
)
2717 if (all_panes
.Item(i
).name
== wxT("dummy"))
2720 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2722 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2725 *ctrl
= tabframe
->m_tabs
;
2735 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2739 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2743 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2745 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2747 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2748 wxASSERT(ctrl
!= NULL
);
2750 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2751 wxASSERT(wnd
!= NULL
);
2753 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2754 wxASSERT(idx
!= -1);
2759 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2764 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2766 wxPoint screen_pt
= ::wxGetMousePosition();
2767 wxPoint client_pt
= ScreenToClient(screen_pt
);
2770 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2771 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2773 if (dest_tabs
== src_tabs
)
2777 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2780 // always hide the hint for inner-tabctrl drag
2783 // if tab moving is not allowed, leave
2784 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2789 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2790 wxWindow
* dest_location_tab
;
2792 // this is an inner-tab drag/reposition
2793 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2795 int src_idx
= evt
.GetSelection();
2796 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2798 // prevent jumpy drag
2799 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2800 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2801 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2803 m_last_drag_x
= pt
.x
;
2808 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2809 dest_tabs
->MovePage(src_tab
, dest_idx
);
2810 dest_tabs
->SetActivePage((size_t)dest_idx
);
2811 dest_tabs
->DoShowHide();
2812 dest_tabs
->Refresh();
2813 m_last_drag_x
= pt
.x
;
2821 // if external drag is allowed, check if the tab is being dragged
2822 // over a different wxAuiNotebook control
2823 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2825 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2827 // if we aren't over any window, stop here
2831 // make sure we are not over the hint window
2832 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2836 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2838 tab_ctrl
= tab_ctrl
->GetParent();
2843 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2847 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2848 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2849 m_mgr
.ShowHint(hint_rect
);
2858 // we are either over a hint window, or not over a tab
2859 // window, and there is no where to drag to, so exit
2866 // if there are less than two panes, split can't happen, so leave
2867 if (m_tabs
.GetPageCount() < 2)
2870 // if tab moving is not allowed, leave
2871 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2877 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2883 wxRect hint_rect
= dest_tabs
->GetRect();
2884 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2885 m_mgr
.ShowHint(hint_rect
);
2889 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2895 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2897 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2902 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2903 wxAuiTabCtrl
* dest_tabs
= NULL
;
2906 // set cursor back to an arrow
2907 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2910 // get the mouse position, which will be used to determine the drop point
2911 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2912 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2916 // check for an external move
2917 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2919 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2923 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2925 tab_ctrl
= tab_ctrl
->GetParent();
2930 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2934 // find out from the destination control
2935 // if it's ok to drop this tab here
2936 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2937 e
.SetSelection(evt
.GetSelection());
2938 e
.SetOldSelection(evt
.GetSelection());
2939 e
.SetEventObject(this);
2940 e
.SetDragSource(this);
2941 e
.Veto(); // dropping must be explicitly approved by control owner
2943 nb
->GetEventHandler()->ProcessEvent(e
);
2947 // no answer or negative answer
2953 int src_idx
= evt
.GetSelection();
2954 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2956 // get main index of the page
2957 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2959 // make a copy of the page info
2960 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2962 // remove the page from the source notebook
2963 RemovePage(main_idx
);
2965 // reparent the page
2966 src_page
->Reparent(nb
);
2969 // found out the insert idx
2970 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2971 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2973 wxWindow
* target
= NULL
;
2974 int insert_idx
= -1;
2975 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2978 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2982 // add the page to the new notebook
2983 if (insert_idx
== -1)
2984 insert_idx
= dest_tabs
->GetPageCount();
2985 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2986 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2989 dest_tabs
->DoShowHide();
2990 dest_tabs
->Refresh();
2992 // set the selection in the destination tab control
2993 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3003 // only perform a tab split if it's allowed
3004 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3006 // If the pointer is in an existing tab frame, do a tab insert
3007 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3008 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3009 int insert_idx
= -1;
3012 dest_tabs
= tab_frame
->m_tabs
;
3014 if (dest_tabs
== src_tabs
)
3018 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3019 wxWindow
* target
= NULL
;
3020 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3023 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3028 // If there is no tabframe at all, create one
3029 wxTabFrame
* new_tabs
= new wxTabFrame
;
3030 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3031 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3036 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3037 new_tabs
->m_tabs
->SetFlags(m_flags
);
3039 m_mgr
.AddPane(new_tabs
,
3040 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3043 dest_tabs
= new_tabs
->m_tabs
;
3048 // remove the page from the source tabs
3049 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3050 page_info
.active
= false;
3051 src_tabs
->RemovePage(page_info
.window
);
3052 if (src_tabs
->GetPageCount() > 0)
3054 src_tabs
->SetActivePage((size_t)0);
3055 src_tabs
->DoShowHide();
3056 src_tabs
->Refresh();
3061 // add the page to the destination tabs
3062 if (insert_idx
== -1)
3063 insert_idx
= dest_tabs
->GetPageCount();
3064 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3066 if (src_tabs
->GetPageCount() == 0)
3068 RemoveEmptyTabFrames();
3072 dest_tabs
->DoShowHide();
3073 dest_tabs
->Refresh();
3075 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3081 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3083 // if we've just removed the last tab from the source
3084 // tab set, the remove the tab control completely
3085 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3086 size_t i
, pane_count
= all_panes
.GetCount();
3087 for (i
= 0; i
< pane_count
; ++i
)
3089 if (all_panes
.Item(i
).name
== wxT("dummy"))
3092 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3093 if (tabframe
->m_tab_rect
.Contains(pt
))
3094 return tabframe
->m_tabs
;
3100 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3102 // if we've just removed the last tab from the source
3103 // tab set, the remove the tab control completely
3104 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3105 size_t i
, pane_count
= all_panes
.GetCount();
3106 for (i
= 0; i
< pane_count
; ++i
)
3108 if (all_panes
.Item(i
).name
== wxT("dummy"))
3111 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3112 if (tabframe
->m_tabs
== tab_ctrl
)
3121 void wxAuiNotebook::RemoveEmptyTabFrames()
3123 // if we've just removed the last tab from the source
3124 // tab set, the remove the tab control completely
3125 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3126 size_t i
, pane_count
= all_panes
.GetCount();
3127 for (i
= 0; i
< pane_count
; ++i
)
3129 if (all_panes
.Item(i
).name
== wxT("dummy"))
3132 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3133 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3135 m_mgr
.DetachPane(tab_frame
);
3137 // use pending delete because sometimes during
3138 // window closing, refreshs are pending
3139 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3140 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3141 //tab_frame->m_tabs->Destroy();
3148 // check to see if there is still a center pane;
3149 // if there isn't, make a frame the center pane
3150 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3151 pane_count
= panes
.GetCount();
3152 wxWindow
* first_good
= NULL
;
3153 bool center_found
= false;
3154 for (i
= 0; i
< pane_count
; ++i
)
3156 if (panes
.Item(i
).name
== wxT("dummy"))
3158 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3159 center_found
= true;
3161 first_good
= panes
.Item(i
).window
;
3164 if (!center_found
&& first_good
)
3166 m_mgr
.GetPane(first_good
).Centre();
3172 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3174 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3175 if (idx
!= -1 && idx
!= m_curpage
)
3182 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3184 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3185 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3187 int button_id
= evt
.GetInt();
3189 if (button_id
== wxAUI_BUTTON_CLOSE
)
3191 int selection
= tabs
->GetActivePage();
3193 if (selection
!= -1)
3195 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3198 // ask owner if it's ok to close the tab
3199 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3200 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3201 e
.SetOldSelection(evt
.GetSelection());
3202 e
.SetEventObject(this);
3203 GetEventHandler()->ProcessEvent(e
);
3208 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3214 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3215 DeletePage(main_idx
);