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
)
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()
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 // SetPageText() changes the tab caption of the specified page
2552 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2554 if (page_idx
>= m_tabs
.GetPageCount())
2557 // update our own tab catalog
2558 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2559 page_info
.caption
= text
;
2561 // update what's on screen
2564 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2566 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2567 info
.caption
= text
;
2575 // GetSelection() returns the index of the currently active page
2576 int wxAuiNotebook::GetSelection() const
2581 // SetSelection() sets the currently active page
2582 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2584 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2588 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2589 evt
.SetSelection(new_page
);
2590 evt
.SetOldSelection(m_curpage
);
2591 evt
.SetEventObject(this);
2592 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2594 // program allows the page change
2595 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2596 (void)GetEventHandler()->ProcessEvent(evt
);
2602 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2604 m_tabs
.SetActivePage(wnd
);
2606 ctrl
->SetActivePage(ctrl_idx
);
2610 int old_curpage
= m_curpage
;
2611 m_curpage
= new_page
;
2615 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2616 size_t i
, pane_count
= all_panes
.GetCount();
2617 for (i
= 0; i
< pane_count
; ++i
)
2619 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2620 if (pane
.name
== wxT("dummy"))
2622 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2623 if (tabctrl
!= ctrl
)
2624 tabctrl
->SetSelectedFont(m_normal_font
);
2626 tabctrl
->SetSelectedFont(m_selected_font
);
2639 // GetPageCount() returns the total number of
2640 // pages managed by the multi-notebook
2641 size_t wxAuiNotebook::GetPageCount() const
2643 return m_tabs
.GetPageCount();
2646 // GetPage() returns the wxWindow pointer of the
2648 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2650 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2652 return m_tabs
.GetWindowFromIdx(page_idx
);
2655 // DoSizing() performs all sizing operations in each tab control
2656 void wxAuiNotebook::DoSizing()
2658 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2659 size_t i
, pane_count
= all_panes
.GetCount();
2660 for (i
= 0; i
< pane_count
; ++i
)
2662 if (all_panes
.Item(i
).name
== wxT("dummy"))
2665 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2666 tabframe
->DoSizing();
2670 // GetActiveTabCtrl() returns the active tab control. It is
2671 // called to determine which control gets new windows being added
2672 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2674 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2679 // find the tab ctrl with the current page
2680 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2687 // no current page, just find the first tab ctrl
2688 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2689 size_t i
, pane_count
= all_panes
.GetCount();
2690 for (i
= 0; i
< pane_count
; ++i
)
2692 if (all_panes
.Item(i
).name
== wxT("dummy"))
2695 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2696 return tabframe
->m_tabs
;
2699 // If there is no tabframe at all, create one
2700 wxTabFrame
* tabframe
= new wxTabFrame
;
2701 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2702 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2707 tabframe
->m_tabs
->SetFlags(m_flags
);
2708 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2709 m_mgr
.AddPane(tabframe
,
2710 wxAuiPaneInfo().Center().CaptionVisible(false));
2714 return tabframe
->m_tabs
;
2717 // FindTab() finds the tab control that currently contains the window as well
2718 // as the index of the window in the tab control. It returns true if the
2719 // window was found, otherwise false.
2720 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2722 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2723 size_t i
, pane_count
= all_panes
.GetCount();
2724 for (i
= 0; i
< pane_count
; ++i
)
2726 if (all_panes
.Item(i
).name
== wxT("dummy"))
2729 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2731 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2734 *ctrl
= tabframe
->m_tabs
;
2744 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2748 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2752 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2754 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2756 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2757 wxASSERT(ctrl
!= NULL
);
2759 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2760 wxASSERT(wnd
!= NULL
);
2762 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2763 wxASSERT(idx
!= -1);
2768 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2773 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2775 wxPoint screen_pt
= ::wxGetMousePosition();
2776 wxPoint client_pt
= ScreenToClient(screen_pt
);
2779 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2780 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2782 if (dest_tabs
== src_tabs
)
2786 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2789 // always hide the hint for inner-tabctrl drag
2792 // if tab moving is not allowed, leave
2793 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2798 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2799 wxWindow
* dest_location_tab
;
2801 // this is an inner-tab drag/reposition
2802 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2804 int src_idx
= evt
.GetSelection();
2805 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2807 // prevent jumpy drag
2808 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2809 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2810 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2812 m_last_drag_x
= pt
.x
;
2817 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2818 dest_tabs
->MovePage(src_tab
, dest_idx
);
2819 dest_tabs
->SetActivePage((size_t)dest_idx
);
2820 dest_tabs
->DoShowHide();
2821 dest_tabs
->Refresh();
2822 m_last_drag_x
= pt
.x
;
2830 // if external drag is allowed, check if the tab is being dragged
2831 // over a different wxAuiNotebook control
2832 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2834 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2836 // if we aren't over any window, stop here
2840 // make sure we are not over the hint window
2841 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2845 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2847 tab_ctrl
= tab_ctrl
->GetParent();
2852 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2856 wxRect hint_rect
= tab_ctrl
->GetClientRect();
2857 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2858 m_mgr
.ShowHint(hint_rect
);
2867 // we are either over a hint window, or not over a tab
2868 // window, and there is no where to drag to, so exit
2875 // if there are less than two panes, split can't happen, so leave
2876 if (m_tabs
.GetPageCount() < 2)
2879 // if tab moving is not allowed, leave
2880 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2886 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2892 wxRect hint_rect
= dest_tabs
->GetRect();
2893 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2894 m_mgr
.ShowHint(hint_rect
);
2898 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2904 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2906 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2911 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2912 wxAuiTabCtrl
* dest_tabs
= NULL
;
2915 // set cursor back to an arrow
2916 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2919 // get the mouse position, which will be used to determine the drop point
2920 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2921 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2925 // check for an external move
2926 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2928 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2932 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2934 tab_ctrl
= tab_ctrl
->GetParent();
2939 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2943 // find out from the destination control
2944 // if it's ok to drop this tab here
2945 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2946 e
.SetSelection(evt
.GetSelection());
2947 e
.SetOldSelection(evt
.GetSelection());
2948 e
.SetEventObject(this);
2949 e
.SetDragSource(this);
2950 e
.Veto(); // dropping must be explicitly approved by control owner
2952 nb
->GetEventHandler()->ProcessEvent(e
);
2956 // no answer or negative answer
2962 int src_idx
= evt
.GetSelection();
2963 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2965 // get main index of the page
2966 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2968 // make a copy of the page info
2969 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2971 // remove the page from the source notebook
2972 RemovePage(main_idx
);
2974 // reparent the page
2975 src_page
->Reparent(nb
);
2978 // found out the insert idx
2979 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2980 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2982 wxWindow
* target
= NULL
;
2983 int insert_idx
= -1;
2984 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2987 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2991 // add the page to the new notebook
2992 if (insert_idx
== -1)
2993 insert_idx
= dest_tabs
->GetPageCount();
2994 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2995 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2998 dest_tabs
->DoShowHide();
2999 dest_tabs
->Refresh();
3001 // set the selection in the destination tab control
3002 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3012 // only perform a tab split if it's allowed
3013 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3015 // If the pointer is in an existing tab frame, do a tab insert
3016 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3017 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3018 int insert_idx
= -1;
3021 dest_tabs
= tab_frame
->m_tabs
;
3023 if (dest_tabs
== src_tabs
)
3027 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3028 wxWindow
* target
= NULL
;
3029 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3032 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3037 // If there is no tabframe at all, create one
3038 wxTabFrame
* new_tabs
= new wxTabFrame
;
3039 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3040 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3045 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3046 new_tabs
->m_tabs
->SetFlags(m_flags
);
3048 m_mgr
.AddPane(new_tabs
,
3049 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3052 dest_tabs
= new_tabs
->m_tabs
;
3057 // remove the page from the source tabs
3058 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3059 page_info
.active
= false;
3060 src_tabs
->RemovePage(page_info
.window
);
3061 if (src_tabs
->GetPageCount() > 0)
3063 src_tabs
->SetActivePage((size_t)0);
3064 src_tabs
->DoShowHide();
3065 src_tabs
->Refresh();
3070 // add the page to the destination tabs
3071 if (insert_idx
== -1)
3072 insert_idx
= dest_tabs
->GetPageCount();
3073 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3075 if (src_tabs
->GetPageCount() == 0)
3077 RemoveEmptyTabFrames();
3081 dest_tabs
->DoShowHide();
3082 dest_tabs
->Refresh();
3084 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3090 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3092 // if we've just removed the last tab from the source
3093 // tab set, the remove the tab control completely
3094 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3095 size_t i
, pane_count
= all_panes
.GetCount();
3096 for (i
= 0; i
< pane_count
; ++i
)
3098 if (all_panes
.Item(i
).name
== wxT("dummy"))
3101 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3102 if (tabframe
->m_tab_rect
.Contains(pt
))
3103 return tabframe
->m_tabs
;
3109 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3111 // if we've just removed the last tab from the source
3112 // tab set, the remove the tab control completely
3113 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3114 size_t i
, pane_count
= all_panes
.GetCount();
3115 for (i
= 0; i
< pane_count
; ++i
)
3117 if (all_panes
.Item(i
).name
== wxT("dummy"))
3120 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3121 if (tabframe
->m_tabs
== tab_ctrl
)
3130 void wxAuiNotebook::RemoveEmptyTabFrames()
3132 // if we've just removed the last tab from the source
3133 // tab set, the remove the tab control completely
3134 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3135 size_t i
, pane_count
= all_panes
.GetCount();
3136 for (i
= 0; i
< pane_count
; ++i
)
3138 if (all_panes
.Item(i
).name
== wxT("dummy"))
3141 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3142 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3144 m_mgr
.DetachPane(tab_frame
);
3146 // use pending delete because sometimes during
3147 // window closing, refreshs are pending
3148 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3149 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3150 //tab_frame->m_tabs->Destroy();
3157 // check to see if there is still a center pane;
3158 // if there isn't, make a frame the center pane
3159 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3160 pane_count
= panes
.GetCount();
3161 wxWindow
* first_good
= NULL
;
3162 bool center_found
= false;
3163 for (i
= 0; i
< pane_count
; ++i
)
3165 if (panes
.Item(i
).name
== wxT("dummy"))
3167 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3168 center_found
= true;
3170 first_good
= panes
.Item(i
).window
;
3173 if (!center_found
&& first_good
)
3175 m_mgr
.GetPane(first_good
).Centre();
3181 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3183 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3184 if (idx
!= -1 && idx
!= m_curpage
)
3191 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3193 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3194 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3196 int button_id
= evt
.GetInt();
3198 if (button_id
== wxAUI_BUTTON_CLOSE
)
3200 int selection
= tabs
->GetActivePage();
3202 if (selection
!= -1)
3204 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3207 // ask owner if it's ok to close the tab
3208 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3209 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3210 e
.SetOldSelection(evt
.GetSelection());
3211 e
.SetEventObject(this);
3212 GetEventHandler()->ProcessEvent(e
);
3217 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3223 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3224 DeletePage(main_idx
);