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() const
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
)
1655 m_tab_close_buttons
.RemoveAt(m_tab_close_buttons
.GetCount()-1);
1657 while (m_tab_close_buttons
.GetCount() < page_count
)
1659 wxAuiTabContainerButton tempbtn
;
1660 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1661 tempbtn
.location
= wxCENTER
;
1662 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1663 m_tab_close_buttons
.Add(tempbtn
);
1667 // buttons before the tab offset must be set to hidden
1668 for (i
= 0; i
< m_tab_offset
; ++i
)
1670 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1676 size_t active
= 999;
1677 int active_offset
= 0;
1681 wxRect rect
= m_rect
;
1683 rect
.height
= m_rect
.height
;
1685 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1687 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1688 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1690 // determine if a close button is on this tab
1691 bool close_button
= false;
1692 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1693 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1695 close_button
= true;
1696 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1698 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1699 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1700 tab_button
.location
= wxCENTER
;
1705 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1709 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1711 if (rect
.width
<= 0)
1720 tab_button
.cur_state
,
1728 active_offset
= offset
;
1736 // make sure to deactivate buttons which are off the screen to the right
1737 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1739 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1743 // draw the active tab again so it stands in the foreground
1744 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1746 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1748 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1750 // determine if a close button is on this tab
1751 bool close_button
= false;
1752 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1753 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1755 close_button
= true;
1758 rect
.x
= active_offset
;
1765 tab_button
.cur_state
,
1772 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1773 m_rect
.GetWidth(), m_rect
.GetHeight(),
1778 // TabHitTest() tests if a tab was hit, passing the window pointer
1779 // back if that condition was fulfilled. The function returns
1780 // true if a tab was hit, otherwise false
1781 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1783 if (!m_rect
.Contains(x
,y
))
1786 wxAuiTabContainerButton
* btn
= NULL
;
1787 if (ButtonHitTest(x
, y
, &btn
))
1789 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1793 size_t i
, page_count
= m_pages
.GetCount();
1795 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1797 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1798 if (page
.rect
.Contains(x
,y
))
1809 // ButtonHitTest() tests if a button was hit. The function returns
1810 // true if a button was hit, otherwise false
1811 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1812 wxAuiTabContainerButton
** hit
) const
1814 if (!m_rect
.Contains(x
,y
))
1817 size_t i
, button_count
;
1820 button_count
= m_buttons
.GetCount();
1821 for (i
= 0; i
< button_count
; ++i
)
1823 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1824 if (button
.rect
.Contains(x
,y
) &&
1825 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1826 wxAUI_BUTTON_STATE_DISABLED
)))
1834 button_count
= m_tab_close_buttons
.GetCount();
1835 for (i
= 0; i
< button_count
; ++i
)
1837 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1838 if (button
.rect
.Contains(x
,y
) &&
1839 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1840 wxAUI_BUTTON_STATE_DISABLED
)))
1853 // the utility function ShowWnd() is the same as show,
1854 // except it handles wxAuiMDIChildFrame windows as well,
1855 // as the Show() method on this class is "unplugged"
1856 static void ShowWnd(wxWindow
* wnd
, bool show
)
1858 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1860 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1870 // DoShowHide() this function shows the active window, then
1871 // hides all of the other windows (in that order)
1872 void wxAuiTabContainer::DoShowHide()
1874 wxAuiNotebookPageArray
& pages
= GetPages();
1875 size_t i
, page_count
= pages
.GetCount();
1877 // show new active page first
1878 for (i
= 0; i
< page_count
; ++i
)
1880 wxAuiNotebookPage
& page
= pages
.Item(i
);
1883 ShowWnd(page
.window
, true);
1888 // hide all other pages
1889 for (i
= 0; i
< page_count
; ++i
)
1891 wxAuiNotebookPage
& page
= pages
.Item(i
);
1892 ShowWnd(page
.window
, page
.active
);
1901 // -- wxAuiTabCtrl class implementation --
1905 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1906 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1907 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1908 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1909 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1910 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1911 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1912 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1913 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1917 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1921 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1923 m_click_pt
= wxDefaultPosition
;
1924 m_is_dragging
= false;
1925 m_hover_button
= NULL
;
1926 m_pressed_button
= NULL
;
1929 wxAuiTabCtrl::~wxAuiTabCtrl()
1933 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1937 dc
.SetFont(GetFont());
1939 if (GetPageCount() > 0)
1943 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1947 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1949 wxSize s
= evt
.GetSize();
1950 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1954 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1957 m_click_pt
= wxDefaultPosition
;
1958 m_is_dragging
= false;
1960 m_pressed_button
= NULL
;
1964 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1966 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1967 e
.SetSelection(GetIdxFromWindow(wnd
));
1968 e
.SetOldSelection(GetActivePage());
1969 e
.SetEventObject(this);
1970 GetEventHandler()->ProcessEvent(e
);
1972 m_click_pt
.x
= evt
.m_x
;
1973 m_click_pt
.y
= evt
.m_y
;
1979 m_pressed_button
= m_hover_button
;
1980 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1986 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
1988 if (GetCapture() == this)
1993 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1994 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1995 evt
.SetOldSelection(evt
.GetSelection());
1996 evt
.SetEventObject(this);
1997 GetEventHandler()->ProcessEvent(evt
);
2001 if (m_pressed_button
)
2003 // make sure we're still clicking the button
2004 wxAuiTabContainerButton
* button
= NULL
;
2005 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2008 if (button
!= m_pressed_button
)
2010 m_pressed_button
= NULL
;
2017 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2019 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2020 evt
.SetInt(m_pressed_button
->id
);
2021 evt
.SetEventObject(this);
2022 GetEventHandler()->ProcessEvent(evt
);
2025 m_pressed_button
= NULL
;
2028 m_click_pt
= wxDefaultPosition
;
2029 m_is_dragging
= false;
2033 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2035 wxPoint pos
= evt
.GetPosition();
2037 // check if the mouse is hovering above a button
2038 wxAuiTabContainerButton
* button
;
2039 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2041 if (m_hover_button
&& button
!= m_hover_button
)
2043 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2044 m_hover_button
= NULL
;
2049 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2051 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2054 m_hover_button
= button
;
2062 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2063 m_hover_button
= NULL
;
2070 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2075 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2076 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2077 evt
.SetOldSelection(evt
.GetSelection());
2078 evt
.SetEventObject(this);
2079 GetEventHandler()->ProcessEvent(evt
);
2084 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2085 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2087 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2088 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2090 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2091 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2092 evt
.SetOldSelection(evt
.GetSelection());
2093 evt
.SetEventObject(this);
2094 GetEventHandler()->ProcessEvent(evt
);
2096 m_is_dragging
= true;
2100 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2104 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2105 m_hover_button
= NULL
;
2111 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2113 int button
= event
.GetInt();
2115 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2117 if (button
== wxAUI_BUTTON_LEFT
)
2119 if (GetTabOffset() > 0)
2121 SetTabOffset(GetTabOffset()-1);
2128 SetTabOffset(GetTabOffset()+1);
2133 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2137 size_t i
, page_count
= m_pages
.GetCount();
2138 for (i
= 0; i
< page_count
; ++i
)
2140 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2141 as
.Add(page
.caption
);
2144 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2148 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2149 e
.SetSelection(idx
);
2150 e
.SetOldSelection(GetActivePage());
2151 e
.SetEventObject(this);
2152 GetEventHandler()->ProcessEvent(e
);
2161 // wxTabFrame is an interesting case. It's important that all child pages
2162 // of the multi-notebook control are all actually children of that control
2163 // (and not grandchildren). wxTabFrame facilitates this. There is one
2164 // instance of wxTabFrame for each tab control inside the multi-notebook.
2165 // It's important to know that wxTabFrame is not a real window, but it merely
2166 // used to capture the dimensions/positioning of the internal tab control and
2167 // it's managed page windows
2169 class wxTabFrame
: public wxWindow
2176 m_rect
= wxRect(0,0,200,200);
2177 m_tab_ctrl_height
= 20;
2180 void SetTabCtrlHeight(int h
)
2182 m_tab_ctrl_height
= h
;
2185 void DoSetSize(int x
, int y
,
2186 int width
, int height
,
2187 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2189 m_rect
= wxRect(x
, y
, width
, height
);
2193 void DoGetClientSize(int* x
, int* y
) const
2199 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2206 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2207 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2208 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2212 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2213 size_t i
, page_count
= pages
.GetCount();
2215 for (i
= 0; i
< page_count
; ++i
)
2217 wxAuiNotebookPage
& page
= pages
.Item(i
);
2218 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2219 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2221 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2223 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2224 wnd
->ApplyMDIChildFrameRect();
2229 void DoGetSize(int* x
, int* y
) const
2232 *x
= m_rect
.GetWidth();
2234 *y
= m_rect
.GetHeight();
2246 wxAuiTabCtrl
* m_tabs
;
2247 int m_tab_ctrl_height
;
2254 // -- wxAuiNotebook class implementation --
2256 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2257 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2258 //EVT_SIZE(wxAuiNotebook::OnSize)
2259 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2260 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2261 EVT_COMMAND_RANGE(10000, 10100,
2262 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2263 wxAuiNotebook::OnTabClicked
)
2264 EVT_COMMAND_RANGE(10000, 10100,
2265 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2266 wxAuiNotebook::OnTabBeginDrag
)
2267 EVT_COMMAND_RANGE(10000, 10100,
2268 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2269 wxAuiNotebook::OnTabEndDrag
)
2270 EVT_COMMAND_RANGE(10000, 10100,
2271 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2272 wxAuiNotebook::OnTabDragMotion
)
2273 EVT_COMMAND_RANGE(10000, 10100,
2274 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2275 wxAuiNotebook::OnTabButton
)
2278 wxAuiNotebook::wxAuiNotebook()
2281 m_tab_id_counter
= 10000;
2283 m_tab_ctrl_height
= 20;
2286 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2290 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2292 InitNotebook(style
);
2295 bool wxAuiNotebook::Create(wxWindow
* parent
,
2301 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2304 InitNotebook(style
);
2309 // InitNotebook() contains common initialization
2310 // code called by all constructors
2311 void wxAuiNotebook::InitNotebook(long style
)
2314 m_tab_id_counter
= 10000;
2316 m_tab_ctrl_height
= 20;
2317 m_flags
= (unsigned int)style
;
2319 m_normal_font
= *wxNORMAL_FONT
;
2320 m_selected_font
= *wxNORMAL_FONT
;
2321 m_selected_font
.SetWeight(wxBOLD
);
2323 SetArtProvider(new wxAuiDefaultTabArt
);
2325 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2326 m_dummy_wnd
->SetSize(200, 200);
2327 m_dummy_wnd
->Show(false);
2329 m_mgr
.SetManagedWindow(this);
2331 m_mgr
.AddPane(m_dummy_wnd
,
2332 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2337 wxAuiNotebook::~wxAuiNotebook()
2342 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2344 m_tabs
.SetArtProvider(art
);
2346 SetTabCtrlHeight(CalculateTabCtrlHeight());
2349 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2351 // if the tab control height needs to change, update
2352 // all of our tab controls with the new height
2353 if (m_tab_ctrl_height
!= height
)
2355 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2357 m_tab_ctrl_height
= height
;
2359 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2360 size_t i
, pane_count
= all_panes
.GetCount();
2361 for (i
= 0; i
< pane_count
; ++i
)
2363 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2364 if (pane
.name
== wxT("dummy"))
2366 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2367 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2368 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2369 tabctrl
->SetArtProvider(art
->Clone());
2370 tab_frame
->DoSizing();
2375 int wxAuiNotebook::CalculateTabCtrlHeight()
2377 // find out new best tab height
2378 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2380 return art
->GetBestTabCtrlSize(this, m_tabs
.GetPages());
2384 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2386 return m_tabs
.GetArtProvider();
2389 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2391 wxControl::SetWindowStyleFlag(style
);
2393 m_flags
= (unsigned int)style
;
2395 // if the control is already initialized
2396 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2398 // let all of the tab children know about the new style
2400 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2401 size_t i
, pane_count
= all_panes
.GetCount();
2402 for (i
= 0; i
< pane_count
; ++i
)
2404 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2405 if (pane
.name
== wxT("dummy"))
2407 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2408 tabctrl
->SetFlags(m_flags
);
2416 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2417 const wxString
& caption
,
2419 const wxBitmap
& bitmap
)
2421 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2424 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2426 const wxString
& caption
,
2428 const wxBitmap
& bitmap
)
2430 wxAuiNotebookPage info
;
2432 info
.caption
= caption
;
2433 info
.bitmap
= bitmap
;
2434 info
.active
= false;
2436 // if there are currently no tabs, the first added
2437 // tab must be active
2438 if (m_tabs
.GetPageCount() == 0)
2441 m_tabs
.InsertPage(page
, info
, page_idx
);
2443 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2444 if (page_idx
>= active_tabctrl
->GetPageCount())
2445 active_tabctrl
->AddPage(page
, info
);
2447 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2449 SetTabCtrlHeight(CalculateTabCtrlHeight());
2451 active_tabctrl
->DoShowHide();
2455 int idx
= m_tabs
.GetIdxFromWindow(page
);
2456 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2465 // DeletePage() removes a tab from the multi-notebook,
2466 // and destroys the window as well
2467 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2469 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2471 if (!RemovePage(page_idx
))
2475 // actually destroy the window now
2476 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2478 // delete the child frame with pending delete, as is
2479 // customary with frame windows
2480 if (!wxPendingDelete
.Member(wnd
))
2481 wxPendingDelete
.Append(wnd
);
2493 // RemovePage() removes a tab from the multi-notebook,
2494 // but does not destroy the window
2495 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2497 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2498 wxWindow
* new_active
= NULL
;
2500 // find out which onscreen tab ctrl owns this tab
2503 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2506 // find a new page and set it as active
2507 int new_idx
= ctrl_idx
+1;
2508 if (new_idx
>= (int)ctrl
->GetPageCount())
2509 new_idx
= ctrl_idx
-1;
2511 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2513 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2517 // set the active page to the first page that
2518 // isn't the one being deleted
2519 size_t i
, page_count
= m_tabs
.GetPageCount();
2520 for (i
= 0; i
< page_count
; ++i
)
2522 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2525 new_active
= m_tabs
.GetWindowFromIdx(i
);
2531 // remove the tab from main catalog
2532 if (!m_tabs
.RemovePage(wnd
))
2535 // remove the tab from the onscreen tab ctrl
2536 ctrl
->RemovePage(wnd
);
2539 RemoveEmptyTabFrames();
2541 // set new active pane
2545 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2551 // GetPageIndex() returns the index of the page, or -1 if the
2552 // page could not be located in the notebook
2553 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2555 return m_tabs
.GetIdxFromWindow(page_wnd
);
2560 // SetPageText() changes the tab caption of the specified page
2561 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2563 if (page_idx
>= m_tabs
.GetPageCount())
2566 // update our own tab catalog
2567 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2568 page_info
.caption
= text
;
2570 // update what's on screen
2573 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2575 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2576 info
.caption
= text
;
2585 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2587 if (page_idx
>= m_tabs
.GetPageCount())
2590 // update our own tab catalog
2591 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2592 page_info
.bitmap
= bitmap
;
2594 // tab height might have changed
2595 SetTabCtrlHeight(CalculateTabCtrlHeight());
2597 // update what's on screen
2600 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2602 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2603 info
.bitmap
= bitmap
;
2612 // GetSelection() returns the index of the currently active page
2613 int wxAuiNotebook::GetSelection() const
2618 // SetSelection() sets the currently active page
2619 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2621 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2625 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2626 evt
.SetSelection(new_page
);
2627 evt
.SetOldSelection(m_curpage
);
2628 evt
.SetEventObject(this);
2629 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2631 // program allows the page change
2632 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2633 (void)GetEventHandler()->ProcessEvent(evt
);
2639 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2641 m_tabs
.SetActivePage(wnd
);
2643 ctrl
->SetActivePage(ctrl_idx
);
2647 int old_curpage
= m_curpage
;
2648 m_curpage
= new_page
;
2652 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2653 size_t i
, pane_count
= all_panes
.GetCount();
2654 for (i
= 0; i
< pane_count
; ++i
)
2656 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2657 if (pane
.name
== wxT("dummy"))
2659 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2660 if (tabctrl
!= ctrl
)
2661 tabctrl
->SetSelectedFont(m_normal_font
);
2663 tabctrl
->SetSelectedFont(m_selected_font
);
2676 // GetPageCount() returns the total number of
2677 // pages managed by the multi-notebook
2678 size_t wxAuiNotebook::GetPageCount() const
2680 return m_tabs
.GetPageCount();
2683 // GetPage() returns the wxWindow pointer of the
2685 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2687 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2689 return m_tabs
.GetWindowFromIdx(page_idx
);
2692 // DoSizing() performs all sizing operations in each tab control
2693 void wxAuiNotebook::DoSizing()
2695 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2696 size_t i
, pane_count
= all_panes
.GetCount();
2697 for (i
= 0; i
< pane_count
; ++i
)
2699 if (all_panes
.Item(i
).name
== wxT("dummy"))
2702 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2703 tabframe
->DoSizing();
2707 // GetActiveTabCtrl() returns the active tab control. It is
2708 // called to determine which control gets new windows being added
2709 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2711 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2716 // find the tab ctrl with the current page
2717 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2724 // no current page, just find the first tab ctrl
2725 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2726 size_t i
, pane_count
= all_panes
.GetCount();
2727 for (i
= 0; i
< pane_count
; ++i
)
2729 if (all_panes
.Item(i
).name
== wxT("dummy"))
2732 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2733 return tabframe
->m_tabs
;
2736 // If there is no tabframe at all, create one
2737 wxTabFrame
* tabframe
= new wxTabFrame
;
2738 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2739 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2744 tabframe
->m_tabs
->SetFlags(m_flags
);
2745 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2746 m_mgr
.AddPane(tabframe
,
2747 wxAuiPaneInfo().Center().CaptionVisible(false));
2751 return tabframe
->m_tabs
;
2754 // FindTab() finds the tab control that currently contains the window as well
2755 // as the index of the window in the tab control. It returns true if the
2756 // window was found, otherwise false.
2757 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2759 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2760 size_t i
, pane_count
= all_panes
.GetCount();
2761 for (i
= 0; i
< pane_count
; ++i
)
2763 if (all_panes
.Item(i
).name
== wxT("dummy"))
2766 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2768 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2771 *ctrl
= tabframe
->m_tabs
;
2781 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2785 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2789 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2791 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2793 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2794 wxASSERT(ctrl
!= NULL
);
2796 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2797 wxASSERT(wnd
!= NULL
);
2799 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2800 wxASSERT(idx
!= -1);
2805 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2810 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2812 wxPoint screen_pt
= ::wxGetMousePosition();
2813 wxPoint client_pt
= ScreenToClient(screen_pt
);
2816 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2817 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2819 if (dest_tabs
== src_tabs
)
2823 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2826 // always hide the hint for inner-tabctrl drag
2829 // if tab moving is not allowed, leave
2830 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2835 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2836 wxWindow
* dest_location_tab
;
2838 // this is an inner-tab drag/reposition
2839 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2841 int src_idx
= evt
.GetSelection();
2842 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2844 // prevent jumpy drag
2845 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2846 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2847 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2849 m_last_drag_x
= pt
.x
;
2854 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2855 dest_tabs
->MovePage(src_tab
, dest_idx
);
2856 dest_tabs
->SetActivePage((size_t)dest_idx
);
2857 dest_tabs
->DoShowHide();
2858 dest_tabs
->Refresh();
2859 m_last_drag_x
= pt
.x
;
2867 // if external drag is allowed, check if the tab is being dragged
2868 // over a different wxAuiNotebook control
2869 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2871 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2873 // if we aren't over any window, stop here
2877 // make sure we are not over the hint window
2878 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2882 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2884 tab_ctrl
= tab_ctrl
->GetParent();
2889 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2893 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2894 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2895 m_mgr
.ShowHint(hint_rect
);
2904 // we are either over a hint window, or not over a tab
2905 // window, and there is no where to drag to, so exit
2912 // if there are less than two panes, split can't happen, so leave
2913 if (m_tabs
.GetPageCount() < 2)
2916 // if tab moving is not allowed, leave
2917 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2923 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2929 wxRect hint_rect
= dest_tabs
->GetRect();
2930 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2931 m_mgr
.ShowHint(hint_rect
);
2935 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2941 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2943 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2948 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2949 wxAuiTabCtrl
* dest_tabs
= NULL
;
2952 // set cursor back to an arrow
2953 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2956 // get the mouse position, which will be used to determine the drop point
2957 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2958 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2962 // check for an external move
2963 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2965 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2969 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2971 tab_ctrl
= tab_ctrl
->GetParent();
2976 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2980 // find out from the destination control
2981 // if it's ok to drop this tab here
2982 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2983 e
.SetSelection(evt
.GetSelection());
2984 e
.SetOldSelection(evt
.GetSelection());
2985 e
.SetEventObject(this);
2986 e
.SetDragSource(this);
2987 e
.Veto(); // dropping must be explicitly approved by control owner
2989 nb
->GetEventHandler()->ProcessEvent(e
);
2993 // no answer or negative answer
2999 int src_idx
= evt
.GetSelection();
3000 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3002 // get main index of the page
3003 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3005 // make a copy of the page info
3006 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3008 // remove the page from the source notebook
3009 RemovePage(main_idx
);
3011 // reparent the page
3012 src_page
->Reparent(nb
);
3015 // found out the insert idx
3016 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3017 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3019 wxWindow
* target
= NULL
;
3020 int insert_idx
= -1;
3021 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3024 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3028 // add the page to the new notebook
3029 if (insert_idx
== -1)
3030 insert_idx
= dest_tabs
->GetPageCount();
3031 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3032 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3035 dest_tabs
->DoShowHide();
3036 dest_tabs
->Refresh();
3038 // set the selection in the destination tab control
3039 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3049 // only perform a tab split if it's allowed
3050 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3052 // If the pointer is in an existing tab frame, do a tab insert
3053 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3054 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3055 int insert_idx
= -1;
3058 dest_tabs
= tab_frame
->m_tabs
;
3060 if (dest_tabs
== src_tabs
)
3064 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3065 wxWindow
* target
= NULL
;
3066 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3069 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3074 // If there is no tabframe at all, create one
3075 wxTabFrame
* new_tabs
= new wxTabFrame
;
3076 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3077 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3082 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3083 new_tabs
->m_tabs
->SetFlags(m_flags
);
3085 m_mgr
.AddPane(new_tabs
,
3086 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3089 dest_tabs
= new_tabs
->m_tabs
;
3094 // remove the page from the source tabs
3095 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3096 page_info
.active
= false;
3097 src_tabs
->RemovePage(page_info
.window
);
3098 if (src_tabs
->GetPageCount() > 0)
3100 src_tabs
->SetActivePage((size_t)0);
3101 src_tabs
->DoShowHide();
3102 src_tabs
->Refresh();
3107 // add the page to the destination tabs
3108 if (insert_idx
== -1)
3109 insert_idx
= dest_tabs
->GetPageCount();
3110 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3112 if (src_tabs
->GetPageCount() == 0)
3114 RemoveEmptyTabFrames();
3118 dest_tabs
->DoShowHide();
3119 dest_tabs
->Refresh();
3121 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3127 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3129 // if we've just removed the last tab from the source
3130 // tab set, the remove the tab control completely
3131 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3132 size_t i
, pane_count
= all_panes
.GetCount();
3133 for (i
= 0; i
< pane_count
; ++i
)
3135 if (all_panes
.Item(i
).name
== wxT("dummy"))
3138 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3139 if (tabframe
->m_tab_rect
.Contains(pt
))
3140 return tabframe
->m_tabs
;
3146 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3148 // if we've just removed the last tab from the source
3149 // tab set, the remove the tab control completely
3150 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3151 size_t i
, pane_count
= all_panes
.GetCount();
3152 for (i
= 0; i
< pane_count
; ++i
)
3154 if (all_panes
.Item(i
).name
== wxT("dummy"))
3157 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3158 if (tabframe
->m_tabs
== tab_ctrl
)
3167 void wxAuiNotebook::RemoveEmptyTabFrames()
3169 // if we've just removed the last tab from the source
3170 // tab set, the remove the tab control completely
3171 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3172 size_t i
, pane_count
= all_panes
.GetCount();
3173 for (i
= 0; i
< pane_count
; ++i
)
3175 if (all_panes
.Item(i
).name
== wxT("dummy"))
3178 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3179 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3181 m_mgr
.DetachPane(tab_frame
);
3183 // use pending delete because sometimes during
3184 // window closing, refreshs are pending
3185 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3186 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3187 //tab_frame->m_tabs->Destroy();
3194 // check to see if there is still a center pane;
3195 // if there isn't, make a frame the center pane
3196 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3197 pane_count
= panes
.GetCount();
3198 wxWindow
* first_good
= NULL
;
3199 bool center_found
= false;
3200 for (i
= 0; i
< pane_count
; ++i
)
3202 if (panes
.Item(i
).name
== wxT("dummy"))
3204 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3205 center_found
= true;
3207 first_good
= panes
.Item(i
).window
;
3210 if (!center_found
&& first_good
)
3212 m_mgr
.GetPane(first_good
).Centre();
3218 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3220 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3221 if (idx
!= -1 && idx
!= m_curpage
)
3228 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3230 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3231 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3233 int button_id
= evt
.GetInt();
3235 if (button_id
== wxAUI_BUTTON_CLOSE
)
3237 int selection
= tabs
->GetActivePage();
3239 if (selection
!= -1)
3241 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3244 // ask owner if it's ok to close the tab
3245 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3246 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3247 e
.SetOldSelection(evt
.GetSelection());
3248 e
.SetEventObject(this);
3249 GetEventHandler()->ProcessEvent(e
);
3254 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3260 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3261 DeletePage(main_idx
);