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
= tab_ctrl_size
.x
;
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
+1, points
[0].y
, points
[5].x
, 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 wxCoord tab_width
= measured_textx
+ 5;
491 wxCoord tab_height
= measured_texty
+ 10;
493 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
494 tab_width
+= m_active_close_bmp
.GetWidth() + 8;
497 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
499 tab_width
= m_fixed_tab_width
;
502 *x_extent
= tab_width
;
504 return wxSize(tab_width
, tab_height
);
508 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
509 wxWindow
* WXUNUSED(wnd
),
510 const wxRect
& in_rect
,
514 const wxBitmap
& bitmap_override
,
520 if (bitmap_override
.IsOk())
522 bmp
= bitmap_override
;
528 case wxAUI_BUTTON_CLOSE
:
529 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
530 bmp
= m_disabled_close_bmp
;
532 bmp
= m_active_close_bmp
;
534 case wxAUI_BUTTON_LEFT
:
535 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
536 bmp
= m_disabled_left_bmp
;
538 bmp
= m_active_left_bmp
;
540 case wxAUI_BUTTON_RIGHT
:
541 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
542 bmp
= m_disabled_right_bmp
;
544 bmp
= m_active_right_bmp
;
546 case wxAUI_BUTTON_WINDOWLIST
:
547 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
548 bmp
= m_disabled_windowlist_bmp
;
550 bmp
= m_active_windowlist_bmp
;
560 if (orientation
== wxLEFT
)
562 rect
.SetX(in_rect
.x
);
563 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
564 rect
.SetWidth(bmp
.GetWidth());
565 rect
.SetHeight(bmp
.GetHeight());
569 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
570 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
571 bmp
.GetWidth(), bmp
.GetHeight());
574 IndentPressedBitmap(&rect
, button_state
);
575 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
581 int wxAuiDefaultTabArt::ShowWindowList(wxWindow
* wnd
,
582 const wxArrayString
& items
,
587 size_t i
, count
= items
.GetCount();
588 for (i
= 0; i
< count
; ++i
)
590 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
593 if (active_idx
!= -1)
595 menuPopup
.Check(1000+active_idx
, true);
598 // find out where to put the popup menu of window
599 // items. Subtract 100 for now to center the menu
600 // a bit, until a better mechanism can be implemented
601 wxPoint pt
= ::wxGetMousePosition();
602 pt
= wnd
->ScreenToClient(pt
);
608 // find out the screen coordinate at the bottom of the tab ctrl
609 wxRect cli_rect
= wnd
->GetClientRect();
610 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
612 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
613 wnd
->PushEventHandler(cc
);
614 wnd
->PopupMenu(&menuPopup
, pt
);
615 int command
= cc
->GetCommandId();
616 wnd
->PopEventHandler(true);
624 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
627 dc
.SetFont(m_measuring_font
);
629 wxSize s
= GetTabSize(dc
,
633 wxAUI_BUTTON_STATE_HIDDEN
,
638 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
640 m_normal_font
= font
;
643 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
645 m_selected_font
= font
;
648 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
650 m_measuring_font
= font
;
654 // -- wxAuiSimpleTabArt class implementation --
656 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
658 m_normal_font
= *wxNORMAL_FONT
;
659 m_selected_font
= *wxNORMAL_FONT
;
660 m_selected_font
.SetWeight(wxBOLD
);
661 m_measuring_font
= m_selected_font
;
664 m_fixed_tab_width
= 100;
666 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
668 wxColour background_colour
= StepColour(base_colour
, 95);
669 wxColour normaltab_colour
= base_colour
;
670 wxColour selectedtab_colour
= *wxWHITE
;
672 m_bkbrush
= wxBrush(background_colour
);
673 m_normal_bkbrush
= wxBrush(normaltab_colour
);
674 m_normal_bkpen
= wxPen(normaltab_colour
);
675 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
676 m_selected_bkpen
= wxPen(selectedtab_colour
);
678 m_active_close_bmp
= BitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
679 m_disabled_close_bmp
= BitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
681 m_active_left_bmp
= BitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
682 m_disabled_left_bmp
= BitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
684 m_active_right_bmp
= BitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
685 m_disabled_right_bmp
= BitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
687 m_active_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
688 m_disabled_windowlist_bmp
= BitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
692 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
696 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
698 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
702 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
707 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
710 m_fixed_tab_width
= 100;
712 int tot_width
= tab_ctrl_size
.x
;
715 m_fixed_tab_width
= tot_width
/(int)tab_count
;
719 if (m_fixed_tab_width
< 100)
720 m_fixed_tab_width
= 100;
722 if (m_fixed_tab_width
> tot_width
/2)
723 m_fixed_tab_width
= tot_width
/2;
725 if (m_fixed_tab_width
> 220)
726 m_fixed_tab_width
= 220;
729 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
730 wxWindow
* WXUNUSED(wnd
),
734 dc
.SetBrush(m_bkbrush
);
735 dc
.SetPen(*wxTRANSPARENT_PEN
);
736 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
739 dc
.SetPen(*wxGREY_PEN
);
740 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
744 // DrawTab() draws an individual tab.
747 // in_rect - rectangle the tab should be confined to
748 // caption - tab's caption
749 // active - whether or not the tab is active
750 // out_rect - actual output rectangle
751 // x_extent - the advance x; where the next tab should start
753 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
755 const wxRect
& in_rect
,
756 const wxString
& caption_text
,
758 int close_button_state
,
759 wxRect
* out_tab_rect
,
760 wxRect
* out_button_rect
,
763 wxCoord normal_textx
, normal_texty
;
764 wxCoord selected_textx
, selected_texty
;
765 wxCoord textx
, texty
;
767 // if the caption is empty, measure some temporary text
768 wxString caption
= caption_text
;
769 if (caption_text
.empty())
772 dc
.SetFont(m_selected_font
);
773 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
775 dc
.SetFont(m_normal_font
);
776 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
778 // figure out the size of the tab
779 wxSize tab_size
= GetTabSize(dc
, wnd
, caption
, active
, close_button_state
, x_extent
);
781 wxCoord tab_height
= tab_size
.y
;
782 wxCoord tab_width
= tab_size
.x
;
783 wxCoord tab_x
= in_rect
.x
;
784 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
786 caption
= caption_text
;
788 // select pen, brush and font for the tab to be drawn
792 dc
.SetPen(m_selected_bkpen
);
793 dc
.SetBrush(m_selected_bkbrush
);
794 dc
.SetFont(m_selected_font
);
795 textx
= selected_textx
;
796 texty
= selected_texty
;
800 dc
.SetPen(m_normal_bkpen
);
801 dc
.SetBrush(m_normal_bkbrush
);
802 dc
.SetFont(m_normal_font
);
803 textx
= normal_textx
;
804 texty
= normal_texty
;
812 points
[0].y
= tab_y
+ tab_height
- 1;
813 points
[1].x
= tab_x
+ tab_height
- 3;
814 points
[1].y
= tab_y
+ 2;
815 points
[2].x
= tab_x
+ tab_height
+ 3;
817 points
[3].x
= tab_x
+ tab_width
- 2;
819 points
[4].x
= tab_x
+ tab_width
;
820 points
[4].y
= tab_y
+ 2;
821 points
[5].x
= tab_x
+ tab_width
;
822 points
[5].y
= tab_y
+ tab_height
- 1;
823 points
[6] = points
[0];
825 dc
.SetClippingRegion(in_rect
);
827 dc
.DrawPolygon(6, points
);
829 dc
.SetPen(*wxGREY_PEN
);
831 //dc.DrawLines(active ? 6 : 7, points);
832 dc
.DrawLines(7, points
);
837 int close_button_width
= 0;
838 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
840 close_button_width
= m_active_close_bmp
.GetWidth();
841 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
845 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
848 // set minimum text offset
849 if (text_offset
< tab_x
+ tab_height
)
850 text_offset
= tab_x
+ tab_height
;
852 // chop text if necessary
853 wxString draw_text
= ChopText(dc
,
855 tab_width
- (text_offset
-tab_x
) - close_button_width
);
858 dc
.DrawText(draw_text
,
860 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
863 // draw close button if necessary
864 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
868 bmp
= m_active_close_bmp
;
870 bmp
= m_disabled_close_bmp
;
872 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
873 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
876 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
878 *out_button_rect
= rect
;
882 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
884 dc
.DestroyClippingRegion();
887 int wxAuiSimpleTabArt::GetIndentSize()
892 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
893 wxWindow
* WXUNUSED(wnd
),
894 const wxString
& caption
,
895 bool WXUNUSED(active
),
896 int close_button_state
,
899 wxCoord measured_textx
, measured_texty
;
901 dc
.SetFont(m_measuring_font
);
902 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
904 wxCoord tab_height
= measured_texty
+ 4;
905 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
907 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
908 tab_width
+= m_active_close_bmp
.GetWidth();
910 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
912 tab_width
= m_fixed_tab_width
;
915 *x_extent
= tab_width
- (tab_height
/2) - 1;
917 return wxSize(tab_width
, tab_height
);
921 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
922 wxWindow
* WXUNUSED(wnd
),
923 const wxRect
& in_rect
,
927 const wxBitmap
& bitmap_override
,
933 if (bitmap_override
.IsOk())
935 bmp
= bitmap_override
;
941 case wxAUI_BUTTON_CLOSE
:
942 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
943 bmp
= m_disabled_close_bmp
;
945 bmp
= m_active_close_bmp
;
947 case wxAUI_BUTTON_LEFT
:
948 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
949 bmp
= m_disabled_left_bmp
;
951 bmp
= m_active_left_bmp
;
953 case wxAUI_BUTTON_RIGHT
:
954 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
955 bmp
= m_disabled_right_bmp
;
957 bmp
= m_active_right_bmp
;
959 case wxAUI_BUTTON_WINDOWLIST
:
960 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
961 bmp
= m_disabled_windowlist_bmp
;
963 bmp
= m_active_windowlist_bmp
;
973 if (orientation
== wxLEFT
)
975 rect
.SetX(in_rect
.x
);
976 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
977 rect
.SetWidth(bmp
.GetWidth());
978 rect
.SetHeight(bmp
.GetHeight());
982 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
983 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
984 bmp
.GetWidth(), bmp
.GetHeight());
988 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
994 int wxAuiSimpleTabArt::ShowWindowList(wxWindow
* wnd
,
995 const wxArrayString
& items
,
1000 size_t i
, count
= items
.GetCount();
1001 for (i
= 0; i
< count
; ++i
)
1003 menuPopup
.AppendCheckItem(1000+i
, items
.Item(i
));
1006 if (active_idx
!= -1)
1008 menuPopup
.Check(1000+active_idx
, true);
1011 // find out where to put the popup menu of window
1012 // items. Subtract 100 for now to center the menu
1013 // a bit, until a better mechanism can be implemented
1014 wxPoint pt
= ::wxGetMousePosition();
1015 pt
= wnd
->ScreenToClient(pt
);
1021 // find out the screen coordinate at the bottom of the tab ctrl
1022 wxRect cli_rect
= wnd
->GetClientRect();
1023 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1025 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1026 wnd
->PushEventHandler(cc
);
1027 wnd
->PopupMenu(&menuPopup
, pt
);
1028 int command
= cc
->GetCommandId();
1029 wnd
->PopEventHandler(true);
1031 if (command
>= 1000)
1032 return command
-1000;
1037 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
)
1040 dc
.SetFont(m_measuring_font
);
1042 wxSize s
= GetTabSize(dc
,
1046 wxAUI_BUTTON_STATE_HIDDEN
,
1051 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1053 m_normal_font
= font
;
1056 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1058 m_selected_font
= font
;
1061 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1063 m_measuring_font
= font
;
1069 // -- wxAuiTabContainer class implementation --
1072 // wxAuiTabContainer is a class which contains information about each
1073 // tab. It also can render an entire tab control to a specified DC.
1074 // It's not a window class itself, because this code will be used by
1075 // the wxFrameMananger, where it is disadvantageous to have separate
1076 // windows for each tab control in the case of "docked tabs"
1078 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1079 // which can be used as a tab control in the normal sense.
1082 wxAuiTabContainer::wxAuiTabContainer()
1086 m_art
= new wxAuiDefaultTabArt
;
1088 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1089 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1090 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1091 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1094 wxAuiTabContainer::~wxAuiTabContainer()
1099 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1106 m_art
->SetFlags(m_flags
);
1110 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider()
1115 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1119 // check for new close button settings
1120 RemoveButton(wxAUI_BUTTON_LEFT
);
1121 RemoveButton(wxAUI_BUTTON_RIGHT
);
1122 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1123 RemoveButton(wxAUI_BUTTON_CLOSE
);
1126 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1128 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1129 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1132 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1134 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1137 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1139 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1144 m_art
->SetFlags(m_flags
);
1148 unsigned int wxAuiTabContainer::GetFlags() const
1154 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1156 m_art
->SetNormalFont(font
);
1159 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1161 m_art
->SetSelectedFont(font
);
1164 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1166 m_art
->SetMeasuringFont(font
);
1169 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1175 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1179 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1180 const wxAuiNotebookPage
& info
)
1182 wxAuiNotebookPage page_info
;
1184 page_info
.window
= page
;
1186 m_pages
.Add(page_info
);
1188 // let the art provider know how many pages we have
1191 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1197 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1198 const wxAuiNotebookPage
& info
,
1201 wxAuiNotebookPage page_info
;
1203 page_info
.window
= page
;
1205 if (idx
>= m_pages
.GetCount())
1206 m_pages
.Add(page_info
);
1208 m_pages
.Insert(page_info
, idx
);
1210 // let the art provider know how many pages we have
1213 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1219 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1222 int idx
= GetIdxFromWindow(page
);
1226 // get page entry, make a copy of it
1227 wxAuiNotebookPage p
= GetPage(idx
);
1229 // remove old page entry
1232 // insert page where it should be
1233 InsertPage(page
, p
, new_idx
);
1238 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1240 size_t i
, page_count
= m_pages
.GetCount();
1241 for (i
= 0; i
< page_count
; ++i
)
1243 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1244 if (page
.window
== wnd
)
1246 m_pages
.RemoveAt(i
);
1248 // let the art provider know how many pages we have
1251 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1261 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1265 size_t i
, page_count
= m_pages
.GetCount();
1266 for (i
= 0; i
< page_count
; ++i
)
1268 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1269 if (page
.window
== wnd
)
1276 page
.active
= false;
1283 void wxAuiTabContainer::SetNoneActive()
1285 size_t i
, page_count
= m_pages
.GetCount();
1286 for (i
= 0; i
< page_count
; ++i
)
1288 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1289 page
.active
= false;
1293 bool wxAuiTabContainer::SetActivePage(size_t page
)
1295 if (page
>= m_pages
.GetCount())
1298 return SetActivePage(m_pages
.Item(page
).window
);
1301 int wxAuiTabContainer::GetActivePage() const
1303 size_t i
, page_count
= m_pages
.GetCount();
1304 for (i
= 0; i
< page_count
; ++i
)
1306 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1314 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1316 if (idx
>= m_pages
.GetCount())
1319 return m_pages
[idx
].window
;
1322 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1324 size_t i
, page_count
= m_pages
.GetCount();
1325 for (i
= 0; i
< page_count
; ++i
)
1327 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1328 if (page
.window
== wnd
)
1334 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1336 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1338 return m_pages
[idx
];
1341 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1346 size_t wxAuiTabContainer::GetPageCount() const
1348 return m_pages
.GetCount();
1351 void wxAuiTabContainer::AddButton(int id
,
1353 const wxBitmap
& normal_bitmap
,
1354 const wxBitmap
& disabled_bitmap
)
1356 wxAuiTabContainerButton button
;
1358 button
.bitmap
= normal_bitmap
;
1359 button
.dis_bitmap
= disabled_bitmap
;
1360 button
.location
= location
;
1361 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1363 m_buttons
.Add(button
);
1366 void wxAuiTabContainer::RemoveButton(int id
)
1368 size_t i
, button_count
= m_buttons
.GetCount();
1370 for (i
= 0; i
< button_count
; ++i
)
1372 if (m_buttons
.Item(i
).id
== id
)
1374 m_buttons
.RemoveAt(i
);
1382 size_t wxAuiTabContainer::GetTabOffset() const
1384 return m_tab_offset
;
1387 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1389 m_tab_offset
= offset
;
1395 // Render() renders the tab catalog to the specified DC
1396 // It is a virtual function and can be overridden to
1397 // provide custom drawing capabilities
1398 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1403 size_t page_count
= m_pages
.GetCount();
1404 size_t button_count
= m_buttons
.GetCount();
1406 // create off-screen bitmap
1407 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1408 dc
.SelectObject(bmp
);
1411 // find out if size of tabs is larger than can be
1412 // afforded on screen
1413 int total_width
= 0;
1414 int visible_width
= 0;
1415 for (i
= 0; i
< page_count
; ++i
)
1417 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1419 // determine if a close button is on this tab
1420 bool close_button
= false;
1421 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1422 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1424 close_button
= true;
1429 wxSize size
= m_art
->GetTabSize(dc
,
1434 wxAUI_BUTTON_STATE_NORMAL
:
1435 wxAUI_BUTTON_STATE_HIDDEN
,
1438 if (i
+1 < page_count
)
1439 total_width
+= x_extent
;
1441 total_width
+= size
.x
;
1443 if (i
>= m_tab_offset
)
1445 if (i
+1 < page_count
)
1446 visible_width
+= x_extent
;
1448 visible_width
+= size
.x
;
1452 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1454 // show left/right buttons
1455 for (i
= 0; i
< button_count
; ++i
)
1457 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1458 if (button
.id
== wxAUI_BUTTON_LEFT
||
1459 button
.id
== wxAUI_BUTTON_RIGHT
)
1461 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1467 // hide left/right buttons
1468 for (i
= 0; i
< button_count
; ++i
)
1470 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1471 if (button
.id
== wxAUI_BUTTON_LEFT
||
1472 button
.id
== wxAUI_BUTTON_RIGHT
)
1474 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1479 // determine whether left button should be enabled
1480 for (i
= 0; i
< button_count
; ++i
)
1482 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1483 if (button
.id
== wxAUI_BUTTON_LEFT
)
1485 if (m_tab_offset
== 0)
1486 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1488 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1490 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1492 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1493 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1495 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1502 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1505 int left_buttons_width
= 0;
1506 int right_buttons_width
= 0;
1510 // draw the buttons on the right side
1511 offset
= m_rect
.x
+ m_rect
.width
;
1512 for (i
= 0; i
< button_count
; ++i
)
1514 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1516 if (button
.location
!= wxRIGHT
)
1518 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1521 wxRect button_rect
= m_rect
;
1522 button_rect
.SetY(1);
1523 button_rect
.SetWidth(offset
);
1525 m_art
->DrawButton(dc
,
1534 offset
-= button
.rect
.GetWidth();
1535 right_buttons_width
+= button
.rect
.GetWidth();
1542 // draw the buttons on the left side
1544 for (i
= 0; i
< button_count
; ++i
)
1546 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1548 if (button
.location
!= wxLEFT
)
1550 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1553 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1555 m_art
->DrawButton(dc
,
1564 offset
+= button
.rect
.GetWidth();
1565 left_buttons_width
+= button
.rect
.GetWidth();
1568 offset
= left_buttons_width
;
1571 offset
+= m_art
->GetIndentSize();
1573 // prepare the tab-close-button array
1574 while (m_tab_close_buttons
.GetCount() < page_count
)
1576 wxAuiTabContainerButton tempbtn
;
1577 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1578 tempbtn
.location
= wxCENTER
;
1579 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1580 m_tab_close_buttons
.Add(tempbtn
);
1583 for (i
= 0; i
< m_tab_offset
; ++i
)
1585 // buttons before the tab offset must be set to hidden
1586 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1592 size_t active
= 999;
1593 int active_offset
= 0;
1597 wxRect rect
= m_rect
;
1599 rect
.height
= m_rect
.height
;
1601 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1603 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1604 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1606 // determine if a close button is on this tab
1607 bool close_button
= false;
1608 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1609 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1611 close_button
= true;
1612 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1614 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1615 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1616 tab_button
.location
= wxCENTER
;
1621 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1625 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1627 if (rect
.width
<= 0)
1638 tab_button
.cur_state
,
1646 active_offset
= offset
;
1653 // draw the active tab again so it stands in the foreground
1654 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1656 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1658 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1660 // determine if a close button is on this tab
1661 bool close_button
= false;
1662 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1663 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1665 close_button
= true;
1668 rect
.x
= active_offset
;
1674 tab_button
.cur_state
,
1681 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1682 m_rect
.GetWidth(), m_rect
.GetHeight(),
1687 // TabHitTest() tests if a tab was hit, passing the window pointer
1688 // back if that condition was fulfilled. The function returns
1689 // true if a tab was hit, otherwise false
1690 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1692 if (!m_rect
.Contains(x
,y
))
1695 wxAuiTabContainerButton
* btn
= NULL
;
1696 if (ButtonHitTest(x
, y
, &btn
))
1698 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1702 size_t i
, page_count
= m_pages
.GetCount();
1704 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1706 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1707 if (page
.rect
.Contains(x
,y
))
1718 // ButtonHitTest() tests if a button was hit. The function returns
1719 // true if a button was hit, otherwise false
1720 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1721 wxAuiTabContainerButton
** hit
) const
1723 if (!m_rect
.Contains(x
,y
))
1726 size_t i
, button_count
;
1729 button_count
= m_buttons
.GetCount();
1730 for (i
= 0; i
< button_count
; ++i
)
1732 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1733 if (button
.rect
.Contains(x
,y
))
1741 button_count
= m_tab_close_buttons
.GetCount();
1742 for (i
= 0; i
< button_count
; ++i
)
1744 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1745 if (button
.rect
.Contains(x
,y
))
1758 // the utility function ShowWnd() is the same as show,
1759 // except it handles wxAuiMDIChildFrame windows as well,
1760 // as the Show() method on this class is "unplugged"
1761 static void ShowWnd(wxWindow
* wnd
, bool show
)
1763 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1765 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1775 // DoShowHide() this function shows the active window, then
1776 // hides all of the other windows (in that order)
1777 void wxAuiTabContainer::DoShowHide()
1779 wxAuiNotebookPageArray
& pages
= GetPages();
1780 size_t i
, page_count
= pages
.GetCount();
1782 // show new active page first
1783 for (i
= 0; i
< page_count
; ++i
)
1785 wxAuiNotebookPage
& page
= pages
.Item(i
);
1788 ShowWnd(page
.window
, true);
1793 // hide all other pages
1794 for (i
= 0; i
< page_count
; ++i
)
1796 wxAuiNotebookPage
& page
= pages
.Item(i
);
1797 ShowWnd(page
.window
, page
.active
);
1806 // -- wxAuiTabCtrl class implementation --
1810 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1811 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1812 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1813 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1814 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1815 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1816 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1817 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1818 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1822 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1826 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1828 m_click_pt
= wxDefaultPosition
;
1829 m_is_dragging
= false;
1830 m_hover_button
= NULL
;
1833 wxAuiTabCtrl::~wxAuiTabCtrl()
1837 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1841 dc
.SetFont(GetFont());
1843 if (GetPageCount() > 0)
1847 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1851 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1853 wxSize s
= evt
.GetSize();
1854 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1858 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1861 m_click_pt
= wxDefaultPosition
;
1862 m_is_dragging
= false;
1866 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1868 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1869 e
.SetSelection(GetIdxFromWindow(wnd
));
1870 e
.SetOldSelection(GetActivePage());
1871 e
.SetEventObject(this);
1872 GetEventHandler()->ProcessEvent(e
);
1874 m_click_pt
.x
= evt
.m_x
;
1875 m_click_pt
.y
= evt
.m_y
;
1881 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1887 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1889 if (GetCapture() == this)
1894 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1895 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1896 evt
.SetOldSelection(evt
.GetSelection());
1897 evt
.SetEventObject(this);
1898 GetEventHandler()->ProcessEvent(evt
);
1904 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1908 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1910 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1911 evt
.SetInt(m_hover_button
->id
);
1912 evt
.SetEventObject(this);
1913 GetEventHandler()->ProcessEvent(evt
);
1917 m_click_pt
= wxDefaultPosition
;
1918 m_is_dragging
= false;
1922 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1924 wxPoint pos
= evt
.GetPosition();
1926 // check if the mouse is hovering above a button
1927 wxAuiTabContainerButton
* button
;
1928 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1930 if (m_hover_button
&& button
!= m_hover_button
)
1932 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1933 m_hover_button
= NULL
;
1938 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1940 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1943 m_hover_button
= button
;
1951 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1952 m_hover_button
= NULL
;
1959 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1964 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1965 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1966 evt
.SetOldSelection(evt
.GetSelection());
1967 evt
.SetEventObject(this);
1968 GetEventHandler()->ProcessEvent(evt
);
1973 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1974 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1976 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1977 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1979 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1980 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1981 evt
.SetOldSelection(evt
.GetSelection());
1982 evt
.SetEventObject(this);
1983 GetEventHandler()->ProcessEvent(evt
);
1985 m_is_dragging
= true;
1989 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1993 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1994 m_hover_button
= NULL
;
2000 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2002 int button
= event
.GetInt();
2004 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2006 if (button
== wxAUI_BUTTON_LEFT
)
2008 if (GetTabOffset() > 0)
2010 SetTabOffset(GetTabOffset()-1);
2017 SetTabOffset(GetTabOffset()+1);
2022 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2026 size_t i
, page_count
= m_pages
.GetCount();
2027 for (i
= 0; i
< page_count
; ++i
)
2029 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2030 as
.Add(page
.caption
);
2033 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2037 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2038 e
.SetSelection(idx
);
2039 e
.SetOldSelection(GetActivePage());
2040 e
.SetEventObject(this);
2041 GetEventHandler()->ProcessEvent(e
);
2050 // wxTabFrame is an interesting case. It's important that all child pages
2051 // of the multi-notebook control are all actually children of that control
2052 // (and not grandchildren). wxTabFrame facilitates this. There is one
2053 // instance of wxTabFrame for each tab control inside the multi-notebook.
2054 // It's important to know that wxTabFrame is not a real window, but it merely
2055 // used to capture the dimensions/positioning of the internal tab control and
2056 // it's managed page windows
2058 class wxTabFrame
: public wxWindow
2065 m_rect
= wxRect(0,0,200,200);
2066 m_tab_ctrl_height
= 20;
2069 void SetTabCtrlHeight(int h
)
2071 m_tab_ctrl_height
= h
;
2074 void DoSetSize(int x
, int y
,
2075 int width
, int height
,
2076 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2078 m_rect
= wxRect(x
, y
, width
, height
);
2082 void DoGetClientSize(int* x
, int* y
) const
2088 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2095 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2096 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2097 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2101 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2102 size_t i
, page_count
= pages
.GetCount();
2104 for (i
= 0; i
< page_count
; ++i
)
2106 wxAuiNotebookPage
& page
= pages
.Item(i
);
2107 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2108 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2110 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2112 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2113 wnd
->ApplyMDIChildFrameRect();
2118 void DoGetSize(int* x
, int* y
) const
2121 *x
= m_rect
.GetWidth();
2123 *y
= m_rect
.GetHeight();
2135 wxAuiTabCtrl
* m_tabs
;
2136 int m_tab_ctrl_height
;
2143 // -- wxAuiNotebook class implementation --
2145 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2146 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2147 //EVT_SIZE(wxAuiNotebook::OnSize)
2148 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2149 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2150 EVT_COMMAND_RANGE(10000, 10100,
2151 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2152 wxAuiNotebook::OnTabClicked
)
2153 EVT_COMMAND_RANGE(10000, 10100,
2154 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2155 wxAuiNotebook::OnTabBeginDrag
)
2156 EVT_COMMAND_RANGE(10000, 10100,
2157 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2158 wxAuiNotebook::OnTabEndDrag
)
2159 EVT_COMMAND_RANGE(10000, 10100,
2160 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2161 wxAuiNotebook::OnTabDragMotion
)
2162 EVT_COMMAND_RANGE(10000, 10100,
2163 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2164 wxAuiNotebook::OnTabButton
)
2167 wxAuiNotebook::wxAuiNotebook()
2170 m_tab_id_counter
= 10000;
2172 m_tab_ctrl_height
= 20;
2175 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2179 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2181 InitNotebook(style
);
2184 bool wxAuiNotebook::Create(wxWindow
* parent
,
2190 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2193 InitNotebook(style
);
2198 // InitNotebook() contains common initialization
2199 // code called by all constructors
2200 void wxAuiNotebook::InitNotebook(long style
)
2203 m_tab_id_counter
= 10000;
2205 m_tab_ctrl_height
= 20;
2206 m_flags
= (unsigned int)style
;
2208 m_normal_font
= *wxNORMAL_FONT
;
2209 m_selected_font
= *wxNORMAL_FONT
;
2210 m_selected_font
.SetWeight(wxBOLD
);
2212 SetArtProvider(new wxAuiDefaultTabArt
);
2214 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2215 m_dummy_wnd
->SetSize(200, 200);
2216 m_dummy_wnd
->Show(false);
2218 m_mgr
.SetManagedWindow(this);
2220 m_mgr
.AddPane(m_dummy_wnd
,
2221 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2226 wxAuiNotebook::~wxAuiNotebook()
2231 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2233 m_tabs
.SetArtProvider(art
);
2235 // choose a default for the tab height
2236 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2238 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2239 size_t i
, pane_count
= all_panes
.GetCount();
2240 for (i
= 0; i
< pane_count
; ++i
)
2242 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2243 if (pane
.name
== wxT("dummy"))
2245 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2246 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2247 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2248 tabctrl
->SetArtProvider(art
->Clone());
2249 tab_frame
->DoSizing();
2254 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2256 return m_tabs
.GetArtProvider();
2259 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2261 wxControl::SetWindowStyleFlag(style
);
2263 m_flags
= (unsigned int)style
;
2265 // if the control is already initialized
2266 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2268 // let all of the tab children know about the new style
2270 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2271 size_t i
, pane_count
= all_panes
.GetCount();
2272 for (i
= 0; i
< pane_count
; ++i
)
2274 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2275 if (pane
.name
== wxT("dummy"))
2277 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2278 tabctrl
->SetFlags(m_flags
);
2286 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2287 const wxString
& caption
,
2289 const wxBitmap
& bitmap
)
2291 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2294 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2296 const wxString
& caption
,
2298 const wxBitmap
& bitmap
)
2300 wxAuiNotebookPage info
;
2302 info
.caption
= caption
;
2303 info
.bitmap
= bitmap
;
2304 info
.active
= false;
2306 // if there are currently no tabs, the first added
2307 // tab must be active
2308 if (m_tabs
.GetPageCount() == 0)
2311 m_tabs
.InsertPage(page
, info
, page_idx
);
2313 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2314 if (page_idx
>= active_tabctrl
->GetPageCount())
2315 active_tabctrl
->AddPage(page
, info
);
2317 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2320 active_tabctrl
->DoShowHide();
2324 int idx
= m_tabs
.GetIdxFromWindow(page
);
2325 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2334 // DeletePage() removes a tab from the multi-notebook,
2335 // and destroys the window as well
2336 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2338 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2340 if (!RemovePage(page_idx
))
2344 // actually destroy the window now
2345 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2347 // delete the child frame with pending delete, as is
2348 // customary with frame windows
2349 if (!wxPendingDelete
.Member(wnd
))
2350 wxPendingDelete
.Append(wnd
);
2362 // RemovePage() removes a tab from the multi-notebook,
2363 // but does not destroy the window
2364 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2366 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2367 wxWindow
* new_active
= NULL
;
2369 // find out which onscreen tab ctrl owns this tab
2372 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2375 // find a new page and set it as active
2376 int new_idx
= ctrl_idx
+1;
2377 if (new_idx
>= (int)ctrl
->GetPageCount())
2378 new_idx
= ctrl_idx
-1;
2380 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2382 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2386 // set the active page to the first page that
2387 // isn't the one being deleted
2388 size_t i
, page_count
= m_tabs
.GetPageCount();
2389 for (i
= 0; i
< page_count
; ++i
)
2391 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2394 new_active
= m_tabs
.GetWindowFromIdx(i
);
2400 // remove the tab from main catalog
2401 if (!m_tabs
.RemovePage(wnd
))
2404 // remove the tab from the onscreen tab ctrl
2405 ctrl
->RemovePage(wnd
);
2408 RemoveEmptyTabFrames();
2410 // set new active pane
2414 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2420 // SetPageText() changes the tab caption of the specified page
2421 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2423 if (page_idx
>= m_tabs
.GetPageCount())
2426 // update our own tab catalog
2427 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2428 page_info
.caption
= text
;
2430 // update what's on screen
2433 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2435 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2436 info
.caption
= text
;
2444 // GetSelection() returns the index of the currently active page
2445 int wxAuiNotebook::GetSelection() const
2450 // SetSelection() sets the currently active page
2451 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2453 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2457 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2458 evt
.SetSelection(new_page
);
2459 evt
.SetOldSelection(m_curpage
);
2460 evt
.SetEventObject(this);
2461 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2463 // program allows the page change
2464 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2465 (void)GetEventHandler()->ProcessEvent(evt
);
2471 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2473 m_tabs
.SetActivePage(wnd
);
2475 ctrl
->SetActivePage(ctrl_idx
);
2479 int old_curpage
= m_curpage
;
2480 m_curpage
= new_page
;
2484 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2485 size_t i
, pane_count
= all_panes
.GetCount();
2486 for (i
= 0; i
< pane_count
; ++i
)
2488 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2489 if (pane
.name
== wxT("dummy"))
2491 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2492 if (tabctrl
!= ctrl
)
2493 tabctrl
->SetSelectedFont(m_normal_font
);
2495 tabctrl
->SetSelectedFont(m_selected_font
);
2508 // GetPageCount() returns the total number of
2509 // pages managed by the multi-notebook
2510 size_t wxAuiNotebook::GetPageCount() const
2512 return m_tabs
.GetPageCount();
2515 // GetPage() returns the wxWindow pointer of the
2517 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2519 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2521 return m_tabs
.GetWindowFromIdx(page_idx
);
2524 // DoSizing() performs all sizing operations in each tab control
2525 void wxAuiNotebook::DoSizing()
2527 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2528 size_t i
, pane_count
= all_panes
.GetCount();
2529 for (i
= 0; i
< pane_count
; ++i
)
2531 if (all_panes
.Item(i
).name
== wxT("dummy"))
2534 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2535 tabframe
->DoSizing();
2539 // GetActiveTabCtrl() returns the active tab control. It is
2540 // called to determine which control gets new windows being added
2541 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2543 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2548 // find the tab ctrl with the current page
2549 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2556 // no current page, just find the first tab ctrl
2557 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2558 size_t i
, pane_count
= all_panes
.GetCount();
2559 for (i
= 0; i
< pane_count
; ++i
)
2561 if (all_panes
.Item(i
).name
== wxT("dummy"))
2564 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2565 return tabframe
->m_tabs
;
2568 // If there is no tabframe at all, create one
2569 wxTabFrame
* tabframe
= new wxTabFrame
;
2570 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2571 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2576 tabframe
->m_tabs
->SetFlags(m_flags
);
2577 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2578 m_mgr
.AddPane(tabframe
,
2579 wxAuiPaneInfo().Center().CaptionVisible(false));
2583 return tabframe
->m_tabs
;
2586 // FindTab() finds the tab control that currently contains the window as well
2587 // as the index of the window in the tab control. It returns true if the
2588 // window was found, otherwise false.
2589 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2591 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2592 size_t i
, pane_count
= all_panes
.GetCount();
2593 for (i
= 0; i
< pane_count
; ++i
)
2595 if (all_panes
.Item(i
).name
== wxT("dummy"))
2598 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2600 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2603 *ctrl
= tabframe
->m_tabs
;
2613 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2617 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2621 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2623 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2625 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2626 wxASSERT(ctrl
!= NULL
);
2628 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2629 wxASSERT(wnd
!= NULL
);
2631 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2632 wxASSERT(idx
!= -1);
2637 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2642 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2644 wxPoint screen_pt
= ::wxGetMousePosition();
2645 wxPoint client_pt
= ScreenToClient(screen_pt
);
2648 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2649 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2651 if (dest_tabs
== src_tabs
)
2655 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2658 // always hide the hint for inner-tabctrl drag
2661 // if tab moving is not allowed, leave
2662 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2667 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2668 wxWindow
* dest_location_tab
;
2670 // this is an inner-tab drag/reposition
2671 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2673 int src_idx
= evt
.GetSelection();
2674 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2676 // prevent jumpy drag
2677 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2678 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2679 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2681 m_last_drag_x
= pt
.x
;
2686 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2687 dest_tabs
->MovePage(src_tab
, dest_idx
);
2688 dest_tabs
->SetActivePage((size_t)dest_idx
);
2689 dest_tabs
->DoShowHide();
2690 dest_tabs
->Refresh();
2691 m_last_drag_x
= pt
.x
;
2699 // if external drag is allowed, check if the tab is being dragged
2700 // over a different wxAuiNotebook control
2701 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2703 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2705 // make sure we are not over the hint window
2706 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2710 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2712 tab_ctrl
= tab_ctrl
->GetParent();
2717 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2721 wxRect hint_rect
= tab_ctrl
->GetRect();
2722 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2723 m_mgr
.ShowHint(hint_rect
);
2732 // if tab moving is not allowed, leave
2733 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2741 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2747 wxRect hint_rect
= dest_tabs
->GetRect();
2748 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2749 m_mgr
.ShowHint(hint_rect
);
2753 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2759 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2761 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2766 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2767 wxAuiTabCtrl
* dest_tabs
= NULL
;
2770 // set cursor back to an arrow
2771 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2774 // get the mouse position, which will be used to determine the drop point
2775 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2776 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2780 // check for an external move
2781 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2783 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2787 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2789 tab_ctrl
= tab_ctrl
->GetParent();
2794 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2798 // find out from the destination control
2799 // if it's ok to drop this tab here
2800 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2801 e
.SetSelection(evt
.GetSelection());
2802 e
.SetOldSelection(evt
.GetSelection());
2803 e
.SetEventObject(this);
2804 e
.SetDragSource(this);
2805 e
.Veto(); // dropping must be explicitly approved by control owner
2807 nb
->GetEventHandler()->ProcessEvent(e
);
2811 // no answer or negative answer
2817 int src_idx
= evt
.GetSelection();
2818 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2820 // get main index of the page
2821 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2823 // make a copy of the page info
2824 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2826 // remove the page from the source notebook
2827 RemovePage(main_idx
);
2829 // reparent the page
2830 src_page
->Reparent(nb
);
2833 // found out the insert idx
2834 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2835 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2837 wxWindow
* target
= NULL
;
2838 int insert_idx
= -1;
2839 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2842 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2846 // add the page to the new notebook
2847 if (insert_idx
== -1)
2848 insert_idx
= dest_tabs
->GetPageCount();
2849 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2850 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2853 dest_tabs
->DoShowHide();
2854 dest_tabs
->Refresh();
2856 // set the selection in the destination tab control
2857 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2867 // only perform a tab split if it's allowed
2868 if (m_flags
& wxAUI_NB_TAB_SPLIT
)
2870 // If the pointer is in an existing tab frame, do a tab insert
2871 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2872 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2873 int insert_idx
= -1;
2876 dest_tabs
= tab_frame
->m_tabs
;
2878 if (dest_tabs
== src_tabs
)
2882 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2883 wxWindow
* target
= NULL
;
2884 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2887 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2892 // If there is no tabframe at all, create one
2893 wxTabFrame
* new_tabs
= new wxTabFrame
;
2894 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2895 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2900 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2901 new_tabs
->m_tabs
->SetFlags(m_flags
);
2903 m_mgr
.AddPane(new_tabs
,
2904 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2907 dest_tabs
= new_tabs
->m_tabs
;
2912 // remove the page from the source tabs
2913 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2914 page_info
.active
= false;
2915 src_tabs
->RemovePage(page_info
.window
);
2916 if (src_tabs
->GetPageCount() > 0)
2918 src_tabs
->SetActivePage((size_t)0);
2919 src_tabs
->DoShowHide();
2920 src_tabs
->Refresh();
2925 // add the page to the destination tabs
2926 if (insert_idx
== -1)
2927 insert_idx
= dest_tabs
->GetPageCount();
2928 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2930 if (src_tabs
->GetPageCount() == 0)
2932 RemoveEmptyTabFrames();
2936 dest_tabs
->DoShowHide();
2937 dest_tabs
->Refresh();
2939 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2945 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2947 // if we've just removed the last tab from the source
2948 // tab set, the remove the tab control completely
2949 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2950 size_t i
, pane_count
= all_panes
.GetCount();
2951 for (i
= 0; i
< pane_count
; ++i
)
2953 if (all_panes
.Item(i
).name
== wxT("dummy"))
2956 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2957 if (tabframe
->m_tab_rect
.Contains(pt
))
2958 return tabframe
->m_tabs
;
2964 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2966 // if we've just removed the last tab from the source
2967 // tab set, the remove the tab control completely
2968 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2969 size_t i
, pane_count
= all_panes
.GetCount();
2970 for (i
= 0; i
< pane_count
; ++i
)
2972 if (all_panes
.Item(i
).name
== wxT("dummy"))
2975 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2976 if (tabframe
->m_tabs
== tab_ctrl
)
2985 void wxAuiNotebook::RemoveEmptyTabFrames()
2987 // if we've just removed the last tab from the source
2988 // tab set, the remove the tab control completely
2989 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2990 size_t i
, pane_count
= all_panes
.GetCount();
2991 for (i
= 0; i
< pane_count
; ++i
)
2993 if (all_panes
.Item(i
).name
== wxT("dummy"))
2996 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2997 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2999 m_mgr
.DetachPane(tab_frame
);
3001 // use pending delete because sometimes during
3002 // window closing, refreshs are pending
3003 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3004 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3005 //tab_frame->m_tabs->Destroy();
3012 // check to see if there is still a center pane;
3013 // if there isn't, make a frame the center pane
3014 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3015 pane_count
= panes
.GetCount();
3016 wxWindow
* first_good
= NULL
;
3017 bool center_found
= false;
3018 for (i
= 0; i
< pane_count
; ++i
)
3020 if (panes
.Item(i
).name
== wxT("dummy"))
3022 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3023 center_found
= true;
3025 first_good
= panes
.Item(i
).window
;
3028 if (!center_found
&& first_good
)
3030 m_mgr
.GetPane(first_good
).Centre();
3036 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3038 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3039 if (idx
!= -1 && idx
!= m_curpage
)
3046 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3048 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3049 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3051 int button_id
= evt
.GetInt();
3053 if (button_id
== wxAUI_BUTTON_CLOSE
)
3055 int selection
= tabs
->GetActivePage();
3057 if (selection
!= -1)
3059 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3062 // ask owner if it's ok to close the tab
3063 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3064 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3065 e
.SetOldSelection(evt
.GetSelection());
3066 e
.SetEventObject(this);
3067 GetEventHandler()->ProcessEvent(e
);
3072 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3078 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3079 DeletePage(main_idx
);