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 };
183 static unsigned char close_bits
[]={
184 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
185 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
186 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
189 static unsigned char left_bits
[] = {
190 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
191 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
192 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
194 static unsigned char right_bits
[] = {
195 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
196 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
197 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
199 static unsigned char list_bits
[] = {
200 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
201 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
209 // -- wxAuiDefaultTabArt class implementation --
211 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
213 m_normal_font
= *wxNORMAL_FONT
;
214 m_selected_font
= *wxNORMAL_FONT
;
215 m_selected_font
.SetWeight(wxBOLD
);
216 m_measuring_font
= m_selected_font
;
218 m_fixed_tab_width
= 100;
220 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
222 wxColour background_colour
= base_colour
;
223 wxColour normaltab_colour
= base_colour
;
224 wxColour selectedtab_colour
= base_colour
;
226 m_bkbrush
= wxBrush(background_colour
);
227 m_normal_bkbrush
= wxBrush(normaltab_colour
);
228 m_normal_bkpen
= wxPen(normaltab_colour
);
229 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
230 m_selected_bkpen
= wxPen(selectedtab_colour
);
233 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
234 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
236 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
237 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
239 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
240 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
242 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
243 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
248 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
252 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
254 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
257 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
262 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
265 m_fixed_tab_width
= 100;
267 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
270 m_fixed_tab_width
= tot_width
/(int)tab_count
;
274 if (m_fixed_tab_width
< 100)
275 m_fixed_tab_width
= 100;
277 if (m_fixed_tab_width
> tot_width
/2)
278 m_fixed_tab_width
= tot_width
/2;
280 if (m_fixed_tab_width
> 220)
281 m_fixed_tab_width
= 220;
285 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
286 wxWindow
* WXUNUSED(wnd
),
290 dc
.SetBrush(m_bkbrush
);
291 dc
.SetPen(*wxTRANSPARENT_PEN
);
292 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
295 dc
.SetPen(*wxGREY_PEN
);
296 dc
.DrawLine(0, rect
.GetHeight()-4, rect
.GetWidth(), rect
.GetHeight()-4);
297 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
301 // DrawTab() draws an individual tab.
304 // in_rect - rectangle the tab should be confined to
305 // caption - tab's caption
306 // active - whether or not the tab is active
307 // out_rect - actual output rectangle
308 // x_extent - the advance x; where the next tab should start
310 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
312 const wxRect
& in_rect
,
313 const wxString
& caption_text
,
315 int close_button_state
,
316 wxRect
* out_tab_rect
,
317 wxRect
* out_button_rect
,
320 wxCoord normal_textx
, normal_texty
;
321 wxCoord selected_textx
, selected_texty
;
322 wxCoord textx
, texty
;
324 // if the caption is empty, measure some temporary text
325 wxString caption
= caption_text
;
326 if (caption_text
.empty())
329 dc
.SetFont(m_selected_font
);
330 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
332 dc
.SetFont(m_normal_font
);
333 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
335 // figure out the size of the tab
336 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
338 wxCoord tab_height
= tab_size
.y
;
339 wxCoord tab_width
= tab_size
.x
;
340 wxCoord tab_x
= in_rect
.x
;
341 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
344 caption
= caption_text
;
346 dc
.SetClippingRegion(in_rect
);
350 // select pen, brush and font for the tab to be drawn
354 dc
.SetPen(m_selected_bkpen
);
355 dc
.SetBrush(m_selected_bkbrush
);
356 dc
.SetFont(m_selected_font
);
357 textx
= selected_textx
;
358 texty
= selected_texty
;
362 dc
.SetPen(m_normal_bkpen
);
363 dc
.SetBrush(m_normal_bkbrush
);
364 dc
.SetFont(m_normal_font
);
365 textx
= normal_textx
;
366 texty
= normal_texty
;
370 // create points that will make the tab outline
374 points
[0].y
= tab_y
+ tab_height
- 4;
376 points
[1].y
= tab_y
+ 2;
377 points
[2].x
= tab_x
+ 2;
379 points
[3].x
= tab_x
+ tab_width
- 2;
381 points
[4].x
= tab_x
+ tab_width
;
382 points
[4].y
= tab_y
+ 2;
383 points
[5].x
= tab_x
+ tab_width
;
384 points
[5].y
= tab_y
+ tab_height
- 4;
387 // draw gradient background
390 wxColour c
= m_bkbrush
.GetColour();
394 for (y
= points
[0].y
; y
> points
[2].y
; --y
)
396 if (y
< tab_y
+(tab_height
*3/5) && y
!= last_y
)
399 c
= StepColour(c
, 102);
403 dc
.DrawLine(points
[0].x
+1, y
, points
[5].x
, y
);
408 dc
.SetPen(*wxGREY_PEN
);
409 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
410 dc
.DrawPolygon(6, points
);
412 // there are two horizontal grey lines at the bottom of the tab control,
413 // this gets rid of the top one of those lines in the tab control
416 wxColour c
= m_bkbrush
.GetColour();
418 dc
.DrawLine(points
[0].x
, points
[0].y
, points
[5].x
+1, points
[5].y
);
423 int close_button_width
= 0;
425 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
427 close_button_width
= m_active_close_bmp
.GetWidth();
430 text_offset
= tab_x
+ 8;
433 wxString draw_text
= ChopText(dc
,
435 tab_width
- (text_offset
-tab_x
) - close_button_width
);
438 dc
.DrawText(draw_text
,
440 (tab_y
+ tab_height
)/2 - (texty
/2));
445 // draw close button if necessary
446 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
448 wxBitmap bmp
= m_disabled_close_bmp
;
450 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
451 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
453 bmp
= m_active_close_bmp
;
456 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
457 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
460 IndentPressedBitmap(&rect
, close_button_state
);
461 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
463 *out_button_rect
= rect
;
466 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
468 dc
.DestroyClippingRegion();
471 int wxAuiDefaultTabArt::GetIndentSize()
476 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
477 wxWindow
* WXUNUSED(wnd
),
478 const wxString
& caption
,
479 bool WXUNUSED(active
),
480 int close_button_state
,
483 wxCoord measured_textx
, measured_texty
, tmp
;
485 dc
.SetFont(m_measuring_font
);
486 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
488 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
490 // add padding around the text
491 wxCoord tab_width
= measured_textx
+ 16;
492 wxCoord tab_height
= measured_texty
+ 10;
494 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
495 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
498 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
500 tab_width
= m_fixed_tab_width
;
503 *x_extent
= tab_width
;
505 return wxSize(tab_width
, tab_height
);
509 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
510 wxWindow
* WXUNUSED(wnd
),
511 const wxRect
& in_rect
,
515 const wxBitmap
& bitmap_override
,
521 if (bitmap_override
.IsOk())
523 bmp
= bitmap_override
;
529 case wxAUI_BUTTON_CLOSE
:
530 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
531 bmp
= m_disabled_close_bmp
;
533 bmp
= m_active_close_bmp
;
535 case wxAUI_BUTTON_LEFT
:
536 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
537 bmp
= m_disabled_left_bmp
;
539 bmp
= m_active_left_bmp
;
541 case wxAUI_BUTTON_RIGHT
:
542 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
543 bmp
= m_disabled_right_bmp
;
545 bmp
= m_active_right_bmp
;
547 case wxAUI_BUTTON_WINDOWLIST
:
548 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
549 bmp
= m_disabled_windowlist_bmp
;
551 bmp
= m_active_windowlist_bmp
;
561 if (orientation
== wxLEFT
)
563 rect
.SetX(in_rect
.x
);
564 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
565 rect
.SetWidth(bmp
.GetWidth());
566 rect
.SetHeight(bmp
.GetHeight());
570 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
571 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
572 bmp
.GetWidth(), bmp
.GetHeight());
575 IndentPressedBitmap(&rect
, button_state
);
576 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
582 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
583 const wxArrayString
& items
,
588 size_t i
, count
= items
.GetCount();
589 for (i
= 0; i
< count
; ++i
)
591 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
594 if (active_idx
!= -1)
596 menuPopup
.Check(1000+active_idx
, true);
599 // find out where to put the popup menu of window
600 // items. Subtract 100 for now to center the menu
601 // a bit, until a better mechanism can be implemented
602 wxPoint pt
= ::wxGetMousePosition();
603 pt
= wnd
->ScreenToClient(pt
);
609 // find out the screen coordinate at the bottom of the tab ctrl
610 wxRect cli_rect
= wnd
->GetClientRect();
611 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
613 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
614 wnd
->PushEventHandler(cc
);
615 wnd
->PopupMenu(&menuPopup
, pt
);
616 int command
= cc
->GetCommandId();
617 wnd
->PopEventHandler(true);
625 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
628 dc
.SetFont(m_measuring_font
);
630 wxSize s
= GetTabSize(dc
,
634 wxAUI_BUTTON_STATE_HIDDEN
,
639 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
641 m_normal_font
= font
;
644 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
646 m_selected_font
= font
;
649 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
651 m_measuring_font
= font
;
655 // -- wxAuiSimpleTabArt class implementation --
657 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
659 m_normal_font
= *wxNORMAL_FONT
;
660 m_selected_font
= *wxNORMAL_FONT
;
661 m_selected_font
.SetWeight(wxBOLD
);
662 m_measuring_font
= m_selected_font
;
665 m_fixed_tab_width
= 100;
667 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
669 wxColour background_colour
= StepColour(base_colour
, 95);
670 wxColour normaltab_colour
= base_colour
;
671 wxColour selectedtab_colour
= *wxWHITE
;
673 m_bkbrush
= wxBrush(background_colour
);
674 m_normal_bkbrush
= wxBrush(normaltab_colour
);
675 m_normal_bkpen
= wxPen(normaltab_colour
);
676 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
677 m_selected_bkpen
= wxPen(selectedtab_colour
);
679 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
680 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
682 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
683 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
685 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
686 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
688 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
689 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
693 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
697 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
699 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
703 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
708 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
711 m_fixed_tab_width
= 100;
713 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
716 m_fixed_tab_width
= tot_width
/(int)tab_count
;
720 if (m_fixed_tab_width
< 100)
721 m_fixed_tab_width
= 100;
723 if (m_fixed_tab_width
> tot_width
/2)
724 m_fixed_tab_width
= tot_width
/2;
726 if (m_fixed_tab_width
> 220)
727 m_fixed_tab_width
= 220;
730 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
731 wxWindow
* WXUNUSED(wnd
),
735 dc
.SetBrush(m_bkbrush
);
736 dc
.SetPen(*wxTRANSPARENT_PEN
);
737 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
740 dc
.SetPen(*wxGREY_PEN
);
741 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
745 // DrawTab() draws an individual tab.
748 // in_rect - rectangle the tab should be confined to
749 // caption - tab's caption
750 // active - whether or not the tab is active
751 // out_rect - actual output rectangle
752 // x_extent - the advance x; where the next tab should start
754 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
756 const wxRect
& in_rect
,
757 const wxString
& caption_text
,
759 int close_button_state
,
760 wxRect
* out_tab_rect
,
761 wxRect
* out_button_rect
,
764 wxCoord normal_textx
, normal_texty
;
765 wxCoord selected_textx
, selected_texty
;
766 wxCoord textx
, texty
;
768 // if the caption is empty, measure some temporary text
769 wxString caption
= caption_text
;
770 if (caption_text
.empty())
773 dc
.SetFont(m_selected_font
);
774 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
776 dc
.SetFont(m_normal_font
);
777 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
779 // figure out the size of the tab
780 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
782 wxCoord tab_height
= tab_size
.y
;
783 wxCoord tab_width
= tab_size
.x
;
784 wxCoord tab_x
= in_rect
.x
;
785 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
787 caption
= caption_text
;
789 // select pen, brush and font for the tab to be drawn
793 dc
.SetPen(m_selected_bkpen
);
794 dc
.SetBrush(m_selected_bkbrush
);
795 dc
.SetFont(m_selected_font
);
796 textx
= selected_textx
;
797 texty
= selected_texty
;
801 dc
.SetPen(m_normal_bkpen
);
802 dc
.SetBrush(m_normal_bkbrush
);
803 dc
.SetFont(m_normal_font
);
804 textx
= normal_textx
;
805 texty
= normal_texty
;
813 points
[0].y
= tab_y
+ tab_height
- 1;
814 points
[1].x
= tab_x
+ tab_height
- 3;
815 points
[1].y
= tab_y
+ 2;
816 points
[2].x
= tab_x
+ tab_height
+ 3;
818 points
[3].x
= tab_x
+ tab_width
- 2;
820 points
[4].x
= tab_x
+ tab_width
;
821 points
[4].y
= tab_y
+ 2;
822 points
[5].x
= tab_x
+ tab_width
;
823 points
[5].y
= tab_y
+ tab_height
- 1;
824 points
[6] = points
[0];
826 dc
.SetClippingRegion(in_rect
);
828 dc
.DrawPolygon(6, points
);
830 dc
.SetPen(*wxGREY_PEN
);
832 //dc.DrawLines(active ? 6 : 7, points);
833 dc
.DrawLines(7, points
);
838 int close_button_width
= 0;
839 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
841 close_button_width
= m_active_close_bmp
.GetWidth();
842 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
846 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
849 // set minimum text offset
850 if (text_offset
< tab_x
+ tab_height
)
851 text_offset
= tab_x
+ tab_height
;
853 // chop text if necessary
854 wxString draw_text
= ChopText(dc
,
856 tab_width
- (text_offset
-tab_x
) - close_button_width
);
859 dc
.DrawText(draw_text
,
861 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
864 // draw close button if necessary
865 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
869 bmp
= m_active_close_bmp
;
871 bmp
= m_disabled_close_bmp
;
873 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
874 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
877 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
879 *out_button_rect
= rect
;
883 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
885 dc
.DestroyClippingRegion();
888 int wxAuiSimpleTabArt::GetIndentSize()
893 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
894 wxWindow
* WXUNUSED(wnd
),
895 const wxString
& caption
,
896 bool WXUNUSED(active
),
897 int close_button_state
,
900 wxCoord measured_textx
, measured_texty
;
902 dc
.SetFont(m_measuring_font
);
903 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
905 wxCoord tab_height
= measured_texty
+ 4;
906 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
908 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
909 tab_width
+= m_active_close_bmp
.GetWidth();
911 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
913 tab_width
= m_fixed_tab_width
;
916 *x_extent
= tab_width
- (tab_height
/2) - 1;
918 return wxSize(tab_width
, tab_height
);
922 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
923 wxWindow
* WXUNUSED(wnd
),
924 const wxRect
& in_rect
,
928 const wxBitmap
& bitmap_override
,
934 if (bitmap_override
.IsOk())
936 bmp
= bitmap_override
;
942 case wxAUI_BUTTON_CLOSE
:
943 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
944 bmp
= m_disabled_close_bmp
;
946 bmp
= m_active_close_bmp
;
948 case wxAUI_BUTTON_LEFT
:
949 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
950 bmp
= m_disabled_left_bmp
;
952 bmp
= m_active_left_bmp
;
954 case wxAUI_BUTTON_RIGHT
:
955 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
956 bmp
= m_disabled_right_bmp
;
958 bmp
= m_active_right_bmp
;
960 case wxAUI_BUTTON_WINDOWLIST
:
961 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
962 bmp
= m_disabled_windowlist_bmp
;
964 bmp
= m_active_windowlist_bmp
;
974 if (orientation
== wxLEFT
)
976 rect
.SetX(in_rect
.x
);
977 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
978 rect
.SetWidth(bmp
.GetWidth());
979 rect
.SetHeight(bmp
.GetHeight());
983 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
984 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
985 bmp
.GetWidth(), bmp
.GetHeight());
989 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
995 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
996 const wxArrayString
& items
,
1001 size_t i
, count
= items
.GetCount();
1002 for (i
= 0; i
< count
; ++i
)
1004 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1007 if (active_idx
!= -1)
1009 menuPopup
.Check(1000+active_idx
, true);
1012 // find out where to put the popup menu of window
1013 // items. Subtract 100 for now to center the menu
1014 // a bit, until a better mechanism can be implemented
1015 wxPoint pt
= ::wxGetMousePosition();
1016 pt
= wnd
->ScreenToClient(pt
);
1022 // find out the screen coordinate at the bottom of the tab ctrl
1023 wxRect cli_rect
= wnd
->GetClientRect();
1024 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1026 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1027 wnd
->PushEventHandler(cc
);
1028 wnd
->PopupMenu(&menuPopup
, pt
);
1029 int command
= cc
->GetCommandId();
1030 wnd
->PopEventHandler(true);
1032 if (command
>= 1000)
1033 return command
-1000;
1038 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
1041 dc
.SetFont(m_measuring_font
);
1043 wxSize s
= GetTabSize(dc
,
1047 wxAUI_BUTTON_STATE_HIDDEN
,
1052 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1054 m_normal_font
= font
;
1057 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1059 m_selected_font
= font
;
1062 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1064 m_measuring_font
= font
;
1070 // -- wxAuiTabContainer class implementation --
1073 // wxAuiTabContainer is a class which contains information about each
1074 // tab. It also can render an entire tab control to a specified DC.
1075 // It's not a window class itself, because this code will be used by
1076 // the wxFrameMananger, where it is disadvantageous to have separate
1077 // windows for each tab control in the case of "docked tabs"
1079 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1080 // which can be used as a tab control in the normal sense.
1083 wxAuiTabContainer::wxAuiTabContainer()
1087 m_art
= new wxAuiDefaultTabArt
;
1089 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1090 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1091 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1092 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1095 wxAuiTabContainer::~wxAuiTabContainer()
1100 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1107 m_art
->SetFlags(m_flags
);
1111 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1116 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1120 // check for new close button settings
1121 RemoveButton(wxAUI_BUTTON_LEFT
);
1122 RemoveButton(wxAUI_BUTTON_RIGHT
);
1123 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1124 RemoveButton(wxAUI_BUTTON_CLOSE
);
1127 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1129 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1130 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1133 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1135 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1138 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1140 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1145 m_art
->SetFlags(m_flags
);
1149 unsigned int wxAuiTabContainer::GetFlags() const
1155 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1157 m_art
->SetNormalFont(font
);
1160 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1162 m_art
->SetSelectedFont(font
);
1165 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1167 m_art
->SetMeasuringFont(font
);
1170 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1176 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1180 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1181 const wxAuiNotebookPage
& info
)
1183 wxAuiNotebookPage page_info
;
1185 page_info
.window
= page
;
1187 m_pages
.Add(page_info
);
1189 // let the art provider know how many pages we have
1192 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1198 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1199 const wxAuiNotebookPage
& info
,
1202 wxAuiNotebookPage page_info
;
1204 page_info
.window
= page
;
1206 if (idx
>= m_pages
.GetCount())
1207 m_pages
.Add(page_info
);
1209 m_pages
.Insert(page_info
, idx
);
1211 // let the art provider know how many pages we have
1214 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1220 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1223 int idx
= GetIdxFromWindow(page
);
1227 // get page entry, make a copy of it
1228 wxAuiNotebookPage p
= GetPage(idx
);
1230 // remove old page entry
1233 // insert page where it should be
1234 InsertPage(page
, p
, new_idx
);
1239 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1241 size_t i
, page_count
= m_pages
.GetCount();
1242 for (i
= 0; i
< page_count
; ++i
)
1244 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1245 if (page
.window
== wnd
)
1247 m_pages
.RemoveAt(i
);
1249 // let the art provider know how many pages we have
1252 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1262 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1266 size_t i
, page_count
= m_pages
.GetCount();
1267 for (i
= 0; i
< page_count
; ++i
)
1269 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1270 if (page
.window
== wnd
)
1277 page
.active
= false;
1284 void wxAuiTabContainer::SetNoneActive()
1286 size_t i
, page_count
= m_pages
.GetCount();
1287 for (i
= 0; i
< page_count
; ++i
)
1289 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1290 page
.active
= false;
1294 bool wxAuiTabContainer::SetActivePage(size_t page
)
1296 if (page
>= m_pages
.GetCount())
1299 return SetActivePage(m_pages
.Item(page
).window
);
1302 int wxAuiTabContainer::GetActivePage() const
1304 size_t i
, page_count
= m_pages
.GetCount();
1305 for (i
= 0; i
< page_count
; ++i
)
1307 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1315 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1317 if (idx
>= m_pages
.GetCount())
1320 return m_pages
[idx
].window
;
1323 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1325 size_t i
, page_count
= m_pages
.GetCount();
1326 for (i
= 0; i
< page_count
; ++i
)
1328 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1329 if (page
.window
== wnd
)
1335 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1337 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1339 return m_pages
[idx
];
1342 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1347 size_t wxAuiTabContainer::GetPageCount() const
1349 return m_pages
.GetCount();
1352 void wxAuiTabContainer::AddButton(int id
,
1354 const wxBitmap
& normal_bitmap
,
1355 const wxBitmap
& disabled_bitmap
)
1357 wxAuiTabContainerButton button
;
1359 button
.bitmap
= normal_bitmap
;
1360 button
.dis_bitmap
= disabled_bitmap
;
1361 button
.location
= location
;
1362 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1364 m_buttons
.Add(button
);
1367 void wxAuiTabContainer::RemoveButton(int id
)
1369 size_t i
, button_count
= m_buttons
.GetCount();
1371 for (i
= 0; i
< button_count
; ++i
)
1373 if (m_buttons
.Item(i
).id
== id
)
1375 m_buttons
.RemoveAt(i
);
1383 size_t wxAuiTabContainer::GetTabOffset() const
1385 return m_tab_offset
;
1388 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1390 m_tab_offset
= offset
;
1396 // Render() renders the tab catalog to the specified DC
1397 // It is a virtual function and can be overridden to
1398 // provide custom drawing capabilities
1399 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1404 size_t page_count
= m_pages
.GetCount();
1405 size_t button_count
= m_buttons
.GetCount();
1407 // create off-screen bitmap
1408 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1409 dc
.SelectObject(bmp
);
1412 // find out if size of tabs is larger than can be
1413 // afforded on screen
1414 int total_width
= 0;
1415 int visible_width
= 0;
1416 for (i
= 0; i
< page_count
; ++i
)
1418 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1420 // determine if a close button is on this tab
1421 bool close_button
= false;
1422 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1423 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1425 close_button
= true;
1430 wxSize size
= m_art
->GetTabSize(dc
,
1435 wxAUI_BUTTON_STATE_NORMAL
:
1436 wxAUI_BUTTON_STATE_HIDDEN
,
1439 if (i
+1 < page_count
)
1440 total_width
+= x_extent
;
1442 total_width
+= size
.x
;
1444 if (i
>= m_tab_offset
)
1446 if (i
+1 < page_count
)
1447 visible_width
+= x_extent
;
1449 visible_width
+= size
.x
;
1453 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1455 // show left/right buttons
1456 for (i
= 0; i
< button_count
; ++i
)
1458 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1459 if (button
.id
== wxAUI_BUTTON_LEFT
||
1460 button
.id
== wxAUI_BUTTON_RIGHT
)
1462 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1468 // hide left/right buttons
1469 for (i
= 0; i
< button_count
; ++i
)
1471 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1472 if (button
.id
== wxAUI_BUTTON_LEFT
||
1473 button
.id
== wxAUI_BUTTON_RIGHT
)
1475 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1480 // determine whether left button should be enabled
1481 for (i
= 0; i
< button_count
; ++i
)
1483 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1484 if (button
.id
== wxAUI_BUTTON_LEFT
)
1486 if (m_tab_offset
== 0)
1487 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1489 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1491 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1493 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1494 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1496 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1503 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1506 int left_buttons_width
= 0;
1507 int right_buttons_width
= 0;
1511 // draw the buttons on the right side
1512 offset
= m_rect
.x
+ m_rect
.width
;
1513 for (i
= 0; i
< button_count
; ++i
)
1515 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1517 if (button
.location
!= wxRIGHT
)
1519 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1522 wxRect button_rect
= m_rect
;
1523 button_rect
.SetY(1);
1524 button_rect
.SetWidth(offset
);
1526 m_art
->DrawButton(dc
,
1535 offset
-= button
.rect
.GetWidth();
1536 right_buttons_width
+= button
.rect
.GetWidth();
1543 // draw the buttons on the left side
1545 for (i
= 0; i
< button_count
; ++i
)
1547 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1549 if (button
.location
!= wxLEFT
)
1551 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1554 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1556 m_art
->DrawButton(dc
,
1565 offset
+= button
.rect
.GetWidth();
1566 left_buttons_width
+= button
.rect
.GetWidth();
1569 offset
= left_buttons_width
;
1572 offset
+= m_art
->GetIndentSize();
1574 // prepare the tab-close-button array
1575 while (m_tab_close_buttons
.GetCount() < page_count
)
1577 wxAuiTabContainerButton tempbtn
;
1578 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1579 tempbtn
.location
= wxCENTER
;
1580 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1581 m_tab_close_buttons
.Add(tempbtn
);
1584 for (i
= 0; i
< m_tab_offset
; ++i
)
1586 // buttons before the tab offset must be set to hidden
1587 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1593 size_t active
= 999;
1594 int active_offset
= 0;
1598 wxRect rect
= m_rect
;
1600 rect
.height
= m_rect
.height
;
1602 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1604 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1605 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1607 // determine if a close button is on this tab
1608 bool close_button
= false;
1609 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1610 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1612 close_button
= true;
1613 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1615 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1616 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1617 tab_button
.location
= wxCENTER
;
1622 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1626 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1628 if (rect
.width
<= 0)
1639 tab_button
.cur_state
,
1647 active_offset
= offset
;
1654 // draw the active tab again so it stands in the foreground
1655 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1657 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1659 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1661 // determine if a close button is on this tab
1662 bool close_button
= false;
1663 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1664 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1666 close_button
= true;
1669 rect
.x
= active_offset
;
1675 tab_button
.cur_state
,
1682 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1683 m_rect
.GetWidth(), m_rect
.GetHeight(),
1688 // TabHitTest() tests if a tab was hit, passing the window pointer
1689 // back if that condition was fulfilled. The function returns
1690 // true if a tab was hit, otherwise false
1691 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1693 if (!m_rect
.Contains(x
,y
))
1696 wxAuiTabContainerButton
* btn
= NULL
;
1697 if (ButtonHitTest(x
, y
, &btn
))
1699 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1703 size_t i
, page_count
= m_pages
.GetCount();
1705 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1707 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1708 if (page
.rect
.Contains(x
,y
))
1719 // ButtonHitTest() tests if a button was hit. The function returns
1720 // true if a button was hit, otherwise false
1721 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1722 wxAuiTabContainerButton
** hit
) const
1724 if (!m_rect
.Contains(x
,y
))
1727 size_t i
, button_count
;
1730 button_count
= m_buttons
.GetCount();
1731 for (i
= 0; i
< button_count
; ++i
)
1733 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1734 if (button
.rect
.Contains(x
,y
))
1742 button_count
= m_tab_close_buttons
.GetCount();
1743 for (i
= 0; i
< button_count
; ++i
)
1745 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1746 if (button
.rect
.Contains(x
,y
))
1759 // the utility function ShowWnd() is the same as show,
1760 // except it handles wxAuiMDIChildFrame windows as well,
1761 // as the Show() method on this class is "unplugged"
1762 static void ShowWnd(wxWindow
* wnd
, bool show
)
1764 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1766 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1776 // DoShowHide() this function shows the active window, then
1777 // hides all of the other windows (in that order)
1778 void wxAuiTabContainer::DoShowHide()
1780 wxAuiNotebookPageArray
& pages
= GetPages();
1781 size_t i
, page_count
= pages
.GetCount();
1783 // show new active page first
1784 for (i
= 0; i
< page_count
; ++i
)
1786 wxAuiNotebookPage
& page
= pages
.Item(i
);
1789 ShowWnd(page
.window
, true);
1794 // hide all other pages
1795 for (i
= 0; i
< page_count
; ++i
)
1797 wxAuiNotebookPage
& page
= pages
.Item(i
);
1798 ShowWnd(page
.window
, page
.active
);
1807 // -- wxAuiTabCtrl class implementation --
1811 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1812 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1813 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1814 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1815 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1816 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1817 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1818 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1819 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1823 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1827 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1829 m_click_pt
= wxDefaultPosition
;
1830 m_is_dragging
= false;
1831 m_hover_button
= NULL
;
1834 wxAuiTabCtrl::~wxAuiTabCtrl()
1838 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1842 dc
.SetFont(GetFont());
1844 if (GetPageCount() > 0)
1848 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1852 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1854 wxSize s
= evt
.GetSize();
1855 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1859 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1862 m_click_pt
= wxDefaultPosition
;
1863 m_is_dragging
= false;
1868 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1870 if (m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
)
1871 m_hover_button
= NULL
;
1873 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1874 e
.SetSelection(GetIdxFromWindow(wnd
));
1875 e
.SetOldSelection(GetActivePage());
1876 e
.SetEventObject(this);
1877 GetEventHandler()->ProcessEvent(e
);
1879 m_click_pt
.x
= evt
.m_x
;
1880 m_click_pt
.y
= evt
.m_y
;
1886 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1892 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1894 if (GetCapture() == this)
1899 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1900 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1901 evt
.SetOldSelection(evt
.GetSelection());
1902 evt
.SetEventObject(this);
1903 GetEventHandler()->ProcessEvent(evt
);
1909 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1913 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1915 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1916 evt
.SetInt(m_hover_button
->id
);
1917 evt
.SetEventObject(this);
1918 GetEventHandler()->ProcessEvent(evt
);
1922 m_click_pt
= wxDefaultPosition
;
1923 m_is_dragging
= false;
1927 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1929 wxPoint pos
= evt
.GetPosition();
1931 // check if the mouse is hovering above a button
1932 wxAuiTabContainerButton
* button
;
1933 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1935 if (m_hover_button
&& button
!= m_hover_button
)
1937 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1938 m_hover_button
= NULL
;
1943 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1945 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1948 m_hover_button
= button
;
1956 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1957 m_hover_button
= NULL
;
1964 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1969 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1970 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1971 evt
.SetOldSelection(evt
.GetSelection());
1972 evt
.SetEventObject(this);
1973 GetEventHandler()->ProcessEvent(evt
);
1978 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1979 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1981 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1982 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1984 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1985 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1986 evt
.SetOldSelection(evt
.GetSelection());
1987 evt
.SetEventObject(this);
1988 GetEventHandler()->ProcessEvent(evt
);
1990 m_is_dragging
= true;
1994 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1998 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1999 m_hover_button
= NULL
;
2005 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2007 int button
= event
.GetInt();
2009 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2011 if (button
== wxAUI_BUTTON_LEFT
)
2013 if (GetTabOffset() > 0)
2015 SetTabOffset(GetTabOffset()-1);
2022 SetTabOffset(GetTabOffset()+1);
2027 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2031 size_t i
, page_count
= m_pages
.GetCount();
2032 for (i
= 0; i
< page_count
; ++i
)
2034 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2035 as
.Add(page
.caption
);
2038 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2042 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2043 e
.SetSelection(idx
);
2044 e
.SetOldSelection(GetActivePage());
2045 e
.SetEventObject(this);
2046 GetEventHandler()->ProcessEvent(e
);
2055 // wxTabFrame is an interesting case. It's important that all child pages
2056 // of the multi-notebook control are all actually children of that control
2057 // (and not grandchildren). wxTabFrame facilitates this. There is one
2058 // instance of wxTabFrame for each tab control inside the multi-notebook.
2059 // It's important to know that wxTabFrame is not a real window, but it merely
2060 // used to capture the dimensions/positioning of the internal tab control and
2061 // it's managed page windows
2063 class wxTabFrame
: public wxWindow
2070 m_rect
= wxRect(0,0,200,200);
2071 m_tab_ctrl_height
= 20;
2074 void SetTabCtrlHeight(int h
)
2076 m_tab_ctrl_height
= h
;
2079 void DoSetSize(int x
, int y
,
2080 int width
, int height
,
2081 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2083 m_rect
= wxRect(x
, y
, width
, height
);
2087 void DoGetClientSize(int* x
, int* y
) const
2093 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2100 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2101 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2102 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2106 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2107 size_t i
, page_count
= pages
.GetCount();
2109 for (i
= 0; i
< page_count
; ++i
)
2111 wxAuiNotebookPage
& page
= pages
.Item(i
);
2112 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2113 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2115 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2117 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2118 wnd
->ApplyMDIChildFrameRect();
2123 void DoGetSize(int* x
, int* y
) const
2126 *x
= m_rect
.GetWidth();
2128 *y
= m_rect
.GetHeight();
2140 wxAuiTabCtrl
* m_tabs
;
2141 int m_tab_ctrl_height
;
2148 // -- wxAuiNotebook class implementation --
2150 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2151 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2152 //EVT_SIZE(wxAuiNotebook::OnSize)
2153 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2154 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2155 EVT_COMMAND_RANGE(10000, 10100,
2156 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2157 wxAuiNotebook::OnTabClicked
)
2158 EVT_COMMAND_RANGE(10000, 10100,
2159 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2160 wxAuiNotebook::OnTabBeginDrag
)
2161 EVT_COMMAND_RANGE(10000, 10100,
2162 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2163 wxAuiNotebook::OnTabEndDrag
)
2164 EVT_COMMAND_RANGE(10000, 10100,
2165 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2166 wxAuiNotebook::OnTabDragMotion
)
2167 EVT_COMMAND_RANGE(10000, 10100,
2168 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2169 wxAuiNotebook::OnTabButton
)
2172 wxAuiNotebook::wxAuiNotebook()
2175 m_tab_id_counter
= 10000;
2177 m_tab_ctrl_height
= 20;
2180 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2184 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2186 InitNotebook(style
);
2189 bool wxAuiNotebook::Create(wxWindow
* parent
,
2195 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2198 InitNotebook(style
);
2203 // InitNotebook() contains common initialization
2204 // code called by all constructors
2205 void wxAuiNotebook::InitNotebook(long style
)
2208 m_tab_id_counter
= 10000;
2210 m_tab_ctrl_height
= 20;
2211 m_flags
= (unsigned int)style
;
2213 m_normal_font
= *wxNORMAL_FONT
;
2214 m_selected_font
= *wxNORMAL_FONT
;
2215 m_selected_font
.SetWeight(wxBOLD
);
2217 SetArtProvider(new wxAuiDefaultTabArt
);
2219 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2220 m_dummy_wnd
->SetSize(200, 200);
2221 m_dummy_wnd
->Show(false);
2223 m_mgr
.SetManagedWindow(this);
2225 m_mgr
.AddPane(m_dummy_wnd
,
2226 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2231 wxAuiNotebook::~wxAuiNotebook()
2236 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2238 m_tabs
.SetArtProvider(art
);
2240 // choose a default for the tab height
2241 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2243 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2244 size_t i
, pane_count
= all_panes
.GetCount();
2245 for (i
= 0; i
< pane_count
; ++i
)
2247 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2248 if (pane
.name
== wxT("dummy"))
2250 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2251 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2252 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2253 tabctrl
->SetArtProvider(art
->Clone());
2254 tab_frame
->DoSizing();
2259 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2261 return m_tabs
.GetArtProvider();
2264 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2266 wxControl::SetWindowStyleFlag(style
);
2268 m_flags
= (unsigned int)style
;
2270 // if the control is already initialized
2271 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2273 // let all of the tab children know about the new style
2275 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2276 size_t i
, pane_count
= all_panes
.GetCount();
2277 for (i
= 0; i
< pane_count
; ++i
)
2279 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2280 if (pane
.name
== wxT("dummy"))
2282 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2283 tabctrl
->SetFlags(m_flags
);
2291 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2292 const wxString
& caption
,
2294 const wxBitmap
& bitmap
)
2296 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2299 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2301 const wxString
& caption
,
2303 const wxBitmap
& bitmap
)
2305 wxAuiNotebookPage info
;
2307 info
.caption
= caption
;
2308 info
.bitmap
= bitmap
;
2309 info
.active
= false;
2311 // if there are currently no tabs, the first added
2312 // tab must be active
2313 if (m_tabs
.GetPageCount() == 0)
2316 m_tabs
.InsertPage(page
, info
, page_idx
);
2318 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2319 if (page_idx
>= active_tabctrl
->GetPageCount())
2320 active_tabctrl
->AddPage(page
, info
);
2322 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2325 active_tabctrl
->DoShowHide();
2329 int idx
= m_tabs
.GetIdxFromWindow(page
);
2330 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2339 // DeletePage() removes a tab from the multi-notebook,
2340 // and destroys the window as well
2341 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2343 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2345 if (!RemovePage(page_idx
))
2349 // actually destroy the window now
2350 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2352 // delete the child frame with pending delete, as is
2353 // customary with frame windows
2354 if (!wxPendingDelete
.Member(wnd
))
2355 wxPendingDelete
.Append(wnd
);
2367 // RemovePage() removes a tab from the multi-notebook,
2368 // but does not destroy the window
2369 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2371 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2372 wxWindow
* new_active
= NULL
;
2374 // find out which onscreen tab ctrl owns this tab
2377 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2380 // find a new page and set it as active
2381 int new_idx
= ctrl_idx
+1;
2382 if (new_idx
>= (int)ctrl
->GetPageCount())
2383 new_idx
= ctrl_idx
-1;
2385 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2387 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2391 // set the active page to the first page that
2392 // isn't the one being deleted
2393 size_t i
, page_count
= m_tabs
.GetPageCount();
2394 for (i
= 0; i
< page_count
; ++i
)
2396 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2399 new_active
= m_tabs
.GetWindowFromIdx(i
);
2405 // remove the tab from main catalog
2406 if (!m_tabs
.RemovePage(wnd
))
2409 // remove the tab from the onscreen tab ctrl
2410 ctrl
->RemovePage(wnd
);
2413 RemoveEmptyTabFrames();
2415 // set new active pane
2419 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2425 // SetPageText() changes the tab caption of the specified page
2426 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2428 if (page_idx
>= m_tabs
.GetPageCount())
2431 // update our own tab catalog
2432 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2433 page_info
.caption
= text
;
2435 // update what's on screen
2438 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2440 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2441 info
.caption
= text
;
2449 // GetSelection() returns the index of the currently active page
2450 int wxAuiNotebook::GetSelection() const
2455 // SetSelection() sets the currently active page
2456 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2458 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2462 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2463 evt
.SetSelection(new_page
);
2464 evt
.SetOldSelection(m_curpage
);
2465 evt
.SetEventObject(this);
2466 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2468 // program allows the page change
2469 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2470 (void)GetEventHandler()->ProcessEvent(evt
);
2476 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2478 m_tabs
.SetActivePage(wnd
);
2480 ctrl
->SetActivePage(ctrl_idx
);
2484 int old_curpage
= m_curpage
;
2485 m_curpage
= new_page
;
2489 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2490 size_t i
, pane_count
= all_panes
.GetCount();
2491 for (i
= 0; i
< pane_count
; ++i
)
2493 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2494 if (pane
.name
== wxT("dummy"))
2496 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2497 if (tabctrl
!= ctrl
)
2498 tabctrl
->SetSelectedFont(m_normal_font
);
2500 tabctrl
->SetSelectedFont(m_selected_font
);
2513 // GetPageCount() returns the total number of
2514 // pages managed by the multi-notebook
2515 size_t wxAuiNotebook::GetPageCount() const
2517 return m_tabs
.GetPageCount();
2520 // GetPage() returns the wxWindow pointer of the
2522 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2524 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2526 return m_tabs
.GetWindowFromIdx(page_idx
);
2529 // DoSizing() performs all sizing operations in each tab control
2530 void wxAuiNotebook::DoSizing()
2532 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2533 size_t i
, pane_count
= all_panes
.GetCount();
2534 for (i
= 0; i
< pane_count
; ++i
)
2536 if (all_panes
.Item(i
).name
== wxT("dummy"))
2539 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2540 tabframe
->DoSizing();
2544 // GetActiveTabCtrl() returns the active tab control. It is
2545 // called to determine which control gets new windows being added
2546 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2548 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2553 // find the tab ctrl with the current page
2554 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2561 // no current page, just find the first tab ctrl
2562 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2563 size_t i
, pane_count
= all_panes
.GetCount();
2564 for (i
= 0; i
< pane_count
; ++i
)
2566 if (all_panes
.Item(i
).name
== wxT("dummy"))
2569 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2570 return tabframe
->m_tabs
;
2573 // If there is no tabframe at all, create one
2574 wxTabFrame
* tabframe
= new wxTabFrame
;
2575 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2576 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2581 tabframe
->m_tabs
->SetFlags(m_flags
);
2582 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2583 m_mgr
.AddPane(tabframe
,
2584 wxAuiPaneInfo().Center().CaptionVisible(false));
2588 return tabframe
->m_tabs
;
2591 // FindTab() finds the tab control that currently contains the window as well
2592 // as the index of the window in the tab control. It returns true if the
2593 // window was found, otherwise false.
2594 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2596 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2597 size_t i
, pane_count
= all_panes
.GetCount();
2598 for (i
= 0; i
< pane_count
; ++i
)
2600 if (all_panes
.Item(i
).name
== wxT("dummy"))
2603 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2605 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2608 *ctrl
= tabframe
->m_tabs
;
2618 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2622 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2626 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2628 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2630 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2631 wxASSERT(ctrl
!= NULL
);
2633 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2634 wxASSERT(wnd
!= NULL
);
2636 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2637 wxASSERT(idx
!= -1);
2642 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2647 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2649 wxPoint screen_pt
= ::wxGetMousePosition();
2650 wxPoint client_pt
= ScreenToClient(screen_pt
);
2653 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2654 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2656 if (dest_tabs
== src_tabs
)
2660 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2663 // always hide the hint for inner-tabctrl drag
2666 // if tab moving is not allowed, leave
2667 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2672 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2673 wxWindow
* dest_location_tab
;
2675 // this is an inner-tab drag/reposition
2676 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2678 int src_idx
= evt
.GetSelection();
2679 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2681 // prevent jumpy drag
2682 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2683 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2684 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2686 m_last_drag_x
= pt
.x
;
2691 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2692 dest_tabs
->MovePage(src_tab
, dest_idx
);
2693 dest_tabs
->SetActivePage((size_t)dest_idx
);
2694 dest_tabs
->DoShowHide();
2695 dest_tabs
->Refresh();
2696 m_last_drag_x
= pt
.x
;
2704 // if external drag is allowed, check if the tab is being dragged
2705 // over a different wxAuiNotebook control
2706 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2708 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2710 // make sure we are not over the hint window
2711 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2715 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2717 tab_ctrl
= tab_ctrl
->GetParent();
2722 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2726 wxRect hint_rect
= tab_ctrl
->GetRect();
2727 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2728 m_mgr
.ShowHint(hint_rect
);
2737 // if there are less than two panes, split can't happen, so leave
2738 if (m_tabs
.GetPageCount() < 2)
2741 // if tab moving is not allowed, leave
2742 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2748 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2754 wxRect hint_rect
= dest_tabs
->GetRect();
2755 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2756 m_mgr
.ShowHint(hint_rect
);
2760 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2766 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2768 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2773 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2774 wxAuiTabCtrl
* dest_tabs
= NULL
;
2777 // set cursor back to an arrow
2778 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2781 // get the mouse position, which will be used to determine the drop point
2782 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2783 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2787 // check for an external move
2788 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2790 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2794 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2796 tab_ctrl
= tab_ctrl
->GetParent();
2801 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2805 // find out from the destination control
2806 // if it's ok to drop this tab here
2807 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2808 e
.SetSelection(evt
.GetSelection());
2809 e
.SetOldSelection(evt
.GetSelection());
2810 e
.SetEventObject(this);
2811 e
.SetDragSource(this);
2812 e
.Veto(); // dropping must be explicitly approved by control owner
2814 nb
->GetEventHandler()->ProcessEvent(e
);
2818 // no answer or negative answer
2824 int src_idx
= evt
.GetSelection();
2825 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2827 // get main index of the page
2828 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2830 // make a copy of the page info
2831 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2833 // remove the page from the source notebook
2834 RemovePage(main_idx
);
2836 // reparent the page
2837 src_page
->Reparent(nb
);
2840 // found out the insert idx
2841 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2842 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2844 wxWindow
* target
= NULL
;
2845 int insert_idx
= -1;
2846 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2849 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2853 // add the page to the new notebook
2854 if (insert_idx
== -1)
2855 insert_idx
= dest_tabs
->GetPageCount();
2856 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2857 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2860 dest_tabs
->DoShowHide();
2861 dest_tabs
->Refresh();
2863 // set the selection in the destination tab control
2864 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2874 // only perform a tab split if it's allowed
2875 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
2877 // If the pointer is in an existing tab frame, do a tab insert
2878 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2879 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2880 int insert_idx
= -1;
2883 dest_tabs
= tab_frame
->m_tabs
;
2885 if (dest_tabs
== src_tabs
)
2889 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2890 wxWindow
* target
= NULL
;
2891 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2894 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2899 // If there is no tabframe at all, create one
2900 wxTabFrame
* new_tabs
= new wxTabFrame
;
2901 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2902 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2907 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2908 new_tabs
->m_tabs
->SetFlags(m_flags
);
2910 m_mgr
.AddPane(new_tabs
,
2911 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2914 dest_tabs
= new_tabs
->m_tabs
;
2919 // remove the page from the source tabs
2920 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2921 page_info
.active
= false;
2922 src_tabs
->RemovePage(page_info
.window
);
2923 if (src_tabs
->GetPageCount() > 0)
2925 src_tabs
->SetActivePage((size_t)0);
2926 src_tabs
->DoShowHide();
2927 src_tabs
->Refresh();
2932 // add the page to the destination tabs
2933 if (insert_idx
== -1)
2934 insert_idx
= dest_tabs
->GetPageCount();
2935 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2937 if (src_tabs
->GetPageCount() == 0)
2939 RemoveEmptyTabFrames();
2943 dest_tabs
->DoShowHide();
2944 dest_tabs
->Refresh();
2946 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2952 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2954 // if we've just removed the last tab from the source
2955 // tab set, the remove the tab control completely
2956 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2957 size_t i
, pane_count
= all_panes
.GetCount();
2958 for (i
= 0; i
< pane_count
; ++i
)
2960 if (all_panes
.Item(i
).name
== wxT("dummy"))
2963 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2964 if (tabframe
->m_tab_rect
.Contains(pt
))
2965 return tabframe
->m_tabs
;
2971 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2973 // if we've just removed the last tab from the source
2974 // tab set, the remove the tab control completely
2975 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2976 size_t i
, pane_count
= all_panes
.GetCount();
2977 for (i
= 0; i
< pane_count
; ++i
)
2979 if (all_panes
.Item(i
).name
== wxT("dummy"))
2982 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2983 if (tabframe
->m_tabs
== tab_ctrl
)
2992 void wxAuiNotebook::RemoveEmptyTabFrames()
2994 // if we've just removed the last tab from the source
2995 // tab set, the remove the tab control completely
2996 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2997 size_t i
, pane_count
= all_panes
.GetCount();
2998 for (i
= 0; i
< pane_count
; ++i
)
3000 if (all_panes
.Item(i
).name
== wxT("dummy"))
3003 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3004 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3006 m_mgr
.DetachPane(tab_frame
);
3008 // use pending delete because sometimes during
3009 // window closing, refreshs are pending
3010 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3011 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3012 //tab_frame->m_tabs->Destroy();
3019 // check to see if there is still a center pane;
3020 // if there isn't, make a frame the center pane
3021 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3022 pane_count
= panes
.GetCount();
3023 wxWindow
* first_good
= NULL
;
3024 bool center_found
= false;
3025 for (i
= 0; i
< pane_count
; ++i
)
3027 if (panes
.Item(i
).name
== wxT("dummy"))
3029 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3030 center_found
= true;
3032 first_good
= panes
.Item(i
).window
;
3035 if (!center_found
&& first_good
)
3037 m_mgr
.GetPane(first_good
).Centre();
3043 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3045 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3046 if (idx
!= -1 && idx
!= m_curpage
)
3053 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3055 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3056 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3058 int button_id
= evt
.GetInt();
3060 if (button_id
== wxAUI_BUTTON_CLOSE
)
3062 int selection
= tabs
->GetActivePage();
3064 if (selection
!= -1)
3066 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3069 // ask owner if it's ok to close the tab
3070 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3071 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3072 e
.SetOldSelection(evt
.GetSelection());
3073 e
.SetEventObject(this);
3074 GetEventHandler()->ProcessEvent(e
);
3079 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3085 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3086 DeletePage(main_idx
);