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;
1634 tab_button
.cur_state
,
1642 active_offset
= offset
;
1649 // draw the active tab again so it stands in the foreground
1650 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1652 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1654 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1656 // determine if a close button is on this tab
1657 bool close_button
= false;
1658 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1659 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1661 close_button
= true;
1664 rect
.x
= active_offset
;
1670 tab_button
.cur_state
,
1677 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1678 m_rect
.GetWidth(), m_rect
.GetHeight(),
1683 // TabHitTest() tests if a tab was hit, passing the window pointer
1684 // back if that condition was fulfilled. The function returns
1685 // true if a tab was hit, otherwise false
1686 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1688 if (!m_rect
.Contains(x
,y
))
1691 wxAuiTabContainerButton
* btn
= NULL
;
1692 if (ButtonHitTest(x
, y
, &btn
))
1694 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1698 size_t i
, page_count
= m_pages
.GetCount();
1700 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1702 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1703 if (page
.rect
.Contains(x
,y
))
1714 // ButtonHitTest() tests if a button was hit. The function returns
1715 // true if a button was hit, otherwise false
1716 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1717 wxAuiTabContainerButton
** hit
) const
1719 if (!m_rect
.Contains(x
,y
))
1722 size_t i
, button_count
;
1725 button_count
= m_buttons
.GetCount();
1726 for (i
= 0; i
< button_count
; ++i
)
1728 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1729 if (button
.rect
.Contains(x
,y
))
1737 button_count
= m_tab_close_buttons
.GetCount();
1738 for (i
= 0; i
< button_count
; ++i
)
1740 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1741 if (button
.rect
.Contains(x
,y
))
1754 // the utility function ShowWnd() is the same as show,
1755 // except it handles wxAuiMDIChildFrame windows as well,
1756 // as the Show() method on this class is "unplugged"
1757 static void ShowWnd(wxWindow
* wnd
, bool show
)
1759 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1761 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1771 // DoShowHide() this function shows the active window, then
1772 // hides all of the other windows (in that order)
1773 void wxAuiTabContainer::DoShowHide()
1775 wxAuiNotebookPageArray
& pages
= GetPages();
1776 size_t i
, page_count
= pages
.GetCount();
1778 // show new active page first
1779 for (i
= 0; i
< page_count
; ++i
)
1781 wxAuiNotebookPage
& page
= pages
.Item(i
);
1784 ShowWnd(page
.window
, true);
1789 // hide all other pages
1790 for (i
= 0; i
< page_count
; ++i
)
1792 wxAuiNotebookPage
& page
= pages
.Item(i
);
1793 ShowWnd(page
.window
, page
.active
);
1802 // -- wxAuiTabCtrl class implementation --
1806 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1807 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1808 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1809 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1810 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1811 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1812 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1813 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1814 EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton
)
1818 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1822 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1824 m_click_pt
= wxDefaultPosition
;
1825 m_is_dragging
= false;
1826 m_hover_button
= NULL
;
1829 wxAuiTabCtrl::~wxAuiTabCtrl()
1833 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1837 dc
.SetFont(GetFont());
1839 if (GetPageCount() > 0)
1843 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1847 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1849 wxSize s
= evt
.GetSize();
1850 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
1854 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
1857 m_click_pt
= wxDefaultPosition
;
1858 m_is_dragging
= false;
1862 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
1864 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
1865 e
.SetSelection(GetIdxFromWindow(wnd
));
1866 e
.SetOldSelection(GetActivePage());
1867 e
.SetEventObject(this);
1868 GetEventHandler()->ProcessEvent(e
);
1870 m_click_pt
.x
= evt
.m_x
;
1871 m_click_pt
.y
= evt
.m_y
;
1877 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
1883 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
&)
1885 if (GetCapture() == this)
1890 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
1891 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1892 evt
.SetOldSelection(evt
.GetSelection());
1893 evt
.SetEventObject(this);
1894 GetEventHandler()->ProcessEvent(evt
);
1900 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1904 if (!(m_hover_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
1906 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
1907 evt
.SetInt(m_hover_button
->id
);
1908 evt
.SetEventObject(this);
1909 GetEventHandler()->ProcessEvent(evt
);
1913 m_click_pt
= wxDefaultPosition
;
1914 m_is_dragging
= false;
1918 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
1920 wxPoint pos
= evt
.GetPosition();
1922 // check if the mouse is hovering above a button
1923 wxAuiTabContainerButton
* button
;
1924 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
1926 if (m_hover_button
&& button
!= m_hover_button
)
1928 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1929 m_hover_button
= NULL
;
1934 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
1936 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
1939 m_hover_button
= button
;
1947 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1948 m_hover_button
= NULL
;
1955 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
1960 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
1961 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1962 evt
.SetOldSelection(evt
.GetSelection());
1963 evt
.SetEventObject(this);
1964 GetEventHandler()->ProcessEvent(evt
);
1969 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
1970 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
1972 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
1973 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
1975 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
1976 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
1977 evt
.SetOldSelection(evt
.GetSelection());
1978 evt
.SetEventObject(this);
1979 GetEventHandler()->ProcessEvent(evt
);
1981 m_is_dragging
= true;
1985 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
1989 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1990 m_hover_button
= NULL
;
1996 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
1998 int button
= event
.GetInt();
2000 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2002 if (button
== wxAUI_BUTTON_LEFT
)
2004 if (GetTabOffset() > 0)
2006 SetTabOffset(GetTabOffset()-1);
2013 SetTabOffset(GetTabOffset()+1);
2018 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2022 size_t i
, page_count
= m_pages
.GetCount();
2023 for (i
= 0; i
< page_count
; ++i
)
2025 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2026 as
.Add(page
.caption
);
2029 int idx
= GetArtProvider()->ShowWindowList(this, as
, GetActivePage());
2033 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2034 e
.SetSelection(idx
);
2035 e
.SetOldSelection(GetActivePage());
2036 e
.SetEventObject(this);
2037 GetEventHandler()->ProcessEvent(e
);
2046 // wxTabFrame is an interesting case. It's important that all child pages
2047 // of the multi-notebook control are all actually children of that control
2048 // (and not grandchildren). wxTabFrame facilitates this. There is one
2049 // instance of wxTabFrame for each tab control inside the multi-notebook.
2050 // It's important to know that wxTabFrame is not a real window, but it merely
2051 // used to capture the dimensions/positioning of the internal tab control and
2052 // it's managed page windows
2054 class wxTabFrame
: public wxWindow
2061 m_rect
= wxRect(0,0,200,200);
2062 m_tab_ctrl_height
= 20;
2065 void SetTabCtrlHeight(int h
)
2067 m_tab_ctrl_height
= h
;
2070 void DoSetSize(int x
, int y
,
2071 int width
, int height
,
2072 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2074 m_rect
= wxRect(x
, y
, width
, height
);
2078 void DoGetClientSize(int* x
, int* y
) const
2084 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2091 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2092 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2093 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2097 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2098 size_t i
, page_count
= pages
.GetCount();
2100 for (i
= 0; i
< page_count
; ++i
)
2102 wxAuiNotebookPage
& page
= pages
.Item(i
);
2103 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2104 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2106 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2108 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2109 wnd
->ApplyMDIChildFrameRect();
2114 void DoGetSize(int* x
, int* y
) const
2117 *x
= m_rect
.GetWidth();
2119 *y
= m_rect
.GetHeight();
2131 wxAuiTabCtrl
* m_tabs
;
2132 int m_tab_ctrl_height
;
2139 // -- wxAuiNotebook class implementation --
2141 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2142 //EVT_ERASE_BACKGROUND(wxAuiNotebook::OnEraseBackground)
2143 //EVT_SIZE(wxAuiNotebook::OnSize)
2144 //EVT_LEFT_DOWN(wxAuiNotebook::OnLeftDown)
2145 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2146 EVT_COMMAND_RANGE(10000, 10100,
2147 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2148 wxAuiNotebook::OnTabClicked
)
2149 EVT_COMMAND_RANGE(10000, 10100,
2150 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2151 wxAuiNotebook::OnTabBeginDrag
)
2152 EVT_COMMAND_RANGE(10000, 10100,
2153 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2154 wxAuiNotebook::OnTabEndDrag
)
2155 EVT_COMMAND_RANGE(10000, 10100,
2156 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2157 wxAuiNotebook::OnTabDragMotion
)
2158 EVT_COMMAND_RANGE(10000, 10100,
2159 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2160 wxAuiNotebook::OnTabButton
)
2163 wxAuiNotebook::wxAuiNotebook()
2166 m_tab_id_counter
= 10000;
2168 m_tab_ctrl_height
= 20;
2171 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2175 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2177 InitNotebook(style
);
2180 bool wxAuiNotebook::Create(wxWindow
* parent
,
2186 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2189 InitNotebook(style
);
2194 // InitNotebook() contains common initialization
2195 // code called by all constructors
2196 void wxAuiNotebook::InitNotebook(long style
)
2199 m_tab_id_counter
= 10000;
2201 m_tab_ctrl_height
= 20;
2202 m_flags
= (unsigned int)style
;
2204 m_normal_font
= *wxNORMAL_FONT
;
2205 m_selected_font
= *wxNORMAL_FONT
;
2206 m_selected_font
.SetWeight(wxBOLD
);
2208 SetArtProvider(new wxAuiDefaultTabArt
);
2210 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2211 m_dummy_wnd
->SetSize(200, 200);
2212 m_dummy_wnd
->Show(false);
2214 m_mgr
.SetManagedWindow(this);
2216 m_mgr
.AddPane(m_dummy_wnd
,
2217 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
2222 wxAuiNotebook::~wxAuiNotebook()
2227 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2229 m_tabs
.SetArtProvider(art
);
2231 // choose a default for the tab height
2232 m_tab_ctrl_height
= art
->GetBestTabCtrlSize(this);
2234 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2235 size_t i
, pane_count
= all_panes
.GetCount();
2236 for (i
= 0; i
< pane_count
; ++i
)
2238 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2239 if (pane
.name
== wxT("dummy"))
2241 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2242 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2243 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2244 tabctrl
->SetArtProvider(art
->Clone());
2245 tab_frame
->DoSizing();
2250 wxAuiTabArt
* wxAuiNotebook::GetArtProvider()
2252 return m_tabs
.GetArtProvider();
2255 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2257 wxControl::SetWindowStyleFlag(style
);
2259 m_flags
= (unsigned int)style
;
2261 // if the control is already initialized
2262 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2264 // let all of the tab children know about the new style
2266 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2267 size_t i
, pane_count
= all_panes
.GetCount();
2268 for (i
= 0; i
< pane_count
; ++i
)
2270 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2271 if (pane
.name
== wxT("dummy"))
2273 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2274 tabctrl
->SetFlags(m_flags
);
2282 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2283 const wxString
& caption
,
2285 const wxBitmap
& bitmap
)
2287 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2290 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2292 const wxString
& caption
,
2294 const wxBitmap
& bitmap
)
2296 wxAuiNotebookPage info
;
2298 info
.caption
= caption
;
2299 info
.bitmap
= bitmap
;
2300 info
.active
= false;
2302 // if there are currently no tabs, the first added
2303 // tab must be active
2304 if (m_tabs
.GetPageCount() == 0)
2307 m_tabs
.InsertPage(page
, info
, page_idx
);
2309 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2310 if (page_idx
>= active_tabctrl
->GetPageCount())
2311 active_tabctrl
->AddPage(page
, info
);
2313 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2316 active_tabctrl
->DoShowHide();
2320 int idx
= m_tabs
.GetIdxFromWindow(page
);
2321 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2330 // DeletePage() removes a tab from the multi-notebook,
2331 // and destroys the window as well
2332 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2334 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2336 if (!RemovePage(page_idx
))
2340 // actually destroy the window now
2341 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2343 // delete the child frame with pending delete, as is
2344 // customary with frame windows
2345 if (!wxPendingDelete
.Member(wnd
))
2346 wxPendingDelete
.Append(wnd
);
2358 // RemovePage() removes a tab from the multi-notebook,
2359 // but does not destroy the window
2360 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2362 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2363 wxWindow
* new_active
= NULL
;
2365 // find out which onscreen tab ctrl owns this tab
2368 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2371 // find a new page and set it as active
2372 int new_idx
= ctrl_idx
+1;
2373 if (new_idx
>= (int)ctrl
->GetPageCount())
2374 new_idx
= ctrl_idx
-1;
2376 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2378 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2382 // set the active page to the first page that
2383 // isn't the one being deleted
2384 size_t i
, page_count
= m_tabs
.GetPageCount();
2385 for (i
= 0; i
< page_count
; ++i
)
2387 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2390 new_active
= m_tabs
.GetWindowFromIdx(i
);
2396 // remove the tab from main catalog
2397 if (!m_tabs
.RemovePage(wnd
))
2400 // remove the tab from the onscreen tab ctrl
2401 ctrl
->RemovePage(wnd
);
2404 RemoveEmptyTabFrames();
2406 // set new active pane
2410 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2416 // SetPageText() changes the tab caption of the specified page
2417 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2419 if (page_idx
>= m_tabs
.GetPageCount())
2422 // update our own tab catalog
2423 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2424 page_info
.caption
= text
;
2426 // update what's on screen
2429 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2431 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2432 info
.caption
= text
;
2440 // GetSelection() returns the index of the currently active page
2441 int wxAuiNotebook::GetSelection() const
2446 // SetSelection() sets the currently active page
2447 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2449 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2453 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2454 evt
.SetSelection(new_page
);
2455 evt
.SetOldSelection(m_curpage
);
2456 evt
.SetEventObject(this);
2457 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2459 // program allows the page change
2460 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2461 (void)GetEventHandler()->ProcessEvent(evt
);
2467 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2469 m_tabs
.SetActivePage(wnd
);
2471 ctrl
->SetActivePage(ctrl_idx
);
2475 int old_curpage
= m_curpage
;
2476 m_curpage
= new_page
;
2480 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2481 size_t i
, pane_count
= all_panes
.GetCount();
2482 for (i
= 0; i
< pane_count
; ++i
)
2484 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2485 if (pane
.name
== wxT("dummy"))
2487 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2488 if (tabctrl
!= ctrl
)
2489 tabctrl
->SetSelectedFont(m_normal_font
);
2491 tabctrl
->SetSelectedFont(m_selected_font
);
2504 // GetPageCount() returns the total number of
2505 // pages managed by the multi-notebook
2506 size_t wxAuiNotebook::GetPageCount() const
2508 return m_tabs
.GetPageCount();
2511 // GetPage() returns the wxWindow pointer of the
2513 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2515 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2517 return m_tabs
.GetWindowFromIdx(page_idx
);
2520 // DoSizing() performs all sizing operations in each tab control
2521 void wxAuiNotebook::DoSizing()
2523 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2524 size_t i
, pane_count
= all_panes
.GetCount();
2525 for (i
= 0; i
< pane_count
; ++i
)
2527 if (all_panes
.Item(i
).name
== wxT("dummy"))
2530 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2531 tabframe
->DoSizing();
2535 // GetActiveTabCtrl() returns the active tab control. It is
2536 // called to determine which control gets new windows being added
2537 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2539 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2544 // find the tab ctrl with the current page
2545 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2552 // no current page, just find the first tab ctrl
2553 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2554 size_t i
, pane_count
= all_panes
.GetCount();
2555 for (i
= 0; i
< pane_count
; ++i
)
2557 if (all_panes
.Item(i
).name
== wxT("dummy"))
2560 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2561 return tabframe
->m_tabs
;
2564 // If there is no tabframe at all, create one
2565 wxTabFrame
* tabframe
= new wxTabFrame
;
2566 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2567 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2572 tabframe
->m_tabs
->SetFlags(m_flags
);
2573 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2574 m_mgr
.AddPane(tabframe
,
2575 wxAuiPaneInfo().Center().CaptionVisible(false));
2579 return tabframe
->m_tabs
;
2582 // FindTab() finds the tab control that currently contains the window as well
2583 // as the index of the window in the tab control. It returns true if the
2584 // window was found, otherwise false.
2585 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2587 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2588 size_t i
, pane_count
= all_panes
.GetCount();
2589 for (i
= 0; i
< pane_count
; ++i
)
2591 if (all_panes
.Item(i
).name
== wxT("dummy"))
2594 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2596 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2599 *ctrl
= tabframe
->m_tabs
;
2609 void wxAuiNotebook::OnEraseBackground(wxEraseEvent
&)
2613 void wxAuiNotebook::OnSize(wxSizeEvent
&)
2617 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
2619 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2621 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2622 wxASSERT(ctrl
!= NULL
);
2624 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
2625 wxASSERT(wnd
!= NULL
);
2627 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
2628 wxASSERT(idx
!= -1);
2633 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
2638 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
2640 wxPoint screen_pt
= ::wxGetMousePosition();
2641 wxPoint client_pt
= ScreenToClient(screen_pt
);
2644 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2645 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
2647 if (dest_tabs
== src_tabs
)
2651 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2654 // always hide the hint for inner-tabctrl drag
2657 // if tab moving is not allowed, leave
2658 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
2663 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
2664 wxWindow
* dest_location_tab
;
2666 // this is an inner-tab drag/reposition
2667 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
2669 int src_idx
= evt
.GetSelection();
2670 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
2672 // prevent jumpy drag
2673 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
2674 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
2675 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
2677 m_last_drag_x
= pt
.x
;
2682 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
2683 dest_tabs
->MovePage(src_tab
, dest_idx
);
2684 dest_tabs
->SetActivePage((size_t)dest_idx
);
2685 dest_tabs
->DoShowHide();
2686 dest_tabs
->Refresh();
2687 m_last_drag_x
= pt
.x
;
2695 // if external drag is allowed, check if the tab is being dragged
2696 // over a different wxAuiNotebook control
2697 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2699 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
2701 // make sure we are not over the hint window
2702 if (tab_ctrl
&& !tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
2706 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2708 tab_ctrl
= tab_ctrl
->GetParent();
2713 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2717 wxRect hint_rect
= tab_ctrl
->GetRect();
2718 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2719 m_mgr
.ShowHint(hint_rect
);
2728 // if tab moving is not allowed, leave
2729 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
2737 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
2743 wxRect hint_rect
= dest_tabs
->GetRect();
2744 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
2745 m_mgr
.ShowHint(hint_rect
);
2749 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
2755 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
2757 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
2762 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
2763 wxAuiTabCtrl
* dest_tabs
= NULL
;
2766 // set cursor back to an arrow
2767 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
2770 // get the mouse position, which will be used to determine the drop point
2771 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
2772 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
2776 // check for an external move
2777 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
2779 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2783 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
2785 tab_ctrl
= tab_ctrl
->GetParent();
2790 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
2794 // find out from the destination control
2795 // if it's ok to drop this tab here
2796 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
2797 e
.SetSelection(evt
.GetSelection());
2798 e
.SetOldSelection(evt
.GetSelection());
2799 e
.SetEventObject(this);
2800 e
.SetDragSource(this);
2801 e
.Veto(); // dropping must be explicitly approved by control owner
2803 nb
->GetEventHandler()->ProcessEvent(e
);
2807 // no answer or negative answer
2813 int src_idx
= evt
.GetSelection();
2814 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
2816 // get main index of the page
2817 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
2819 // make a copy of the page info
2820 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
2822 // remove the page from the source notebook
2823 RemovePage(main_idx
);
2825 // reparent the page
2826 src_page
->Reparent(nb
);
2829 // found out the insert idx
2830 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
2831 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2833 wxWindow
* target
= NULL
;
2834 int insert_idx
= -1;
2835 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2838 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2842 // add the page to the new notebook
2843 if (insert_idx
== -1)
2844 insert_idx
= dest_tabs
->GetPageCount();
2845 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2846 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
2849 dest_tabs
->DoShowHide();
2850 dest_tabs
->Refresh();
2852 // set the selection in the destination tab control
2853 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
2863 // only perform a tab split if it's allowed
2864 if (m_flags
& wxAUI_NB_TAB_SPLIT
)
2866 // If the pointer is in an existing tab frame, do a tab insert
2867 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
2868 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
2869 int insert_idx
= -1;
2872 dest_tabs
= tab_frame
->m_tabs
;
2874 if (dest_tabs
== src_tabs
)
2878 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
2879 wxWindow
* target
= NULL
;
2880 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
2883 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
2888 // If there is no tabframe at all, create one
2889 wxTabFrame
* new_tabs
= new wxTabFrame
;
2890 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
2891 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
2896 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2897 new_tabs
->m_tabs
->SetFlags(m_flags
);
2899 m_mgr
.AddPane(new_tabs
,
2900 wxAuiPaneInfo().Bottom().CaptionVisible(false),
2903 dest_tabs
= new_tabs
->m_tabs
;
2908 // remove the page from the source tabs
2909 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
2910 page_info
.active
= false;
2911 src_tabs
->RemovePage(page_info
.window
);
2912 if (src_tabs
->GetPageCount() > 0)
2914 src_tabs
->SetActivePage((size_t)0);
2915 src_tabs
->DoShowHide();
2916 src_tabs
->Refresh();
2921 // add the page to the destination tabs
2922 if (insert_idx
== -1)
2923 insert_idx
= dest_tabs
->GetPageCount();
2924 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
2926 if (src_tabs
->GetPageCount() == 0)
2928 RemoveEmptyTabFrames();
2932 dest_tabs
->DoShowHide();
2933 dest_tabs
->Refresh();
2935 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
2941 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
2943 // if we've just removed the last tab from the source
2944 // tab set, the remove the tab control completely
2945 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2946 size_t i
, pane_count
= all_panes
.GetCount();
2947 for (i
= 0; i
< pane_count
; ++i
)
2949 if (all_panes
.Item(i
).name
== wxT("dummy"))
2952 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2953 if (tabframe
->m_tab_rect
.Contains(pt
))
2954 return tabframe
->m_tabs
;
2960 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
2962 // if we've just removed the last tab from the source
2963 // tab set, the remove the tab control completely
2964 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2965 size_t i
, pane_count
= all_panes
.GetCount();
2966 for (i
= 0; i
< pane_count
; ++i
)
2968 if (all_panes
.Item(i
).name
== wxT("dummy"))
2971 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2972 if (tabframe
->m_tabs
== tab_ctrl
)
2981 void wxAuiNotebook::RemoveEmptyTabFrames()
2983 // if we've just removed the last tab from the source
2984 // tab set, the remove the tab control completely
2985 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
2986 size_t i
, pane_count
= all_panes
.GetCount();
2987 for (i
= 0; i
< pane_count
; ++i
)
2989 if (all_panes
.Item(i
).name
== wxT("dummy"))
2992 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2993 if (tab_frame
->m_tabs
->GetPageCount() == 0)
2995 m_mgr
.DetachPane(tab_frame
);
2997 // use pending delete because sometimes during
2998 // window closing, refreshs are pending
2999 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3000 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3001 //tab_frame->m_tabs->Destroy();
3008 // check to see if there is still a center pane;
3009 // if there isn't, make a frame the center pane
3010 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3011 pane_count
= panes
.GetCount();
3012 wxWindow
* first_good
= NULL
;
3013 bool center_found
= false;
3014 for (i
= 0; i
< pane_count
; ++i
)
3016 if (panes
.Item(i
).name
== wxT("dummy"))
3018 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3019 center_found
= true;
3021 first_good
= panes
.Item(i
).window
;
3024 if (!center_found
&& first_good
)
3026 m_mgr
.GetPane(first_good
).Centre();
3032 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3034 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3035 if (idx
!= -1 && idx
!= m_curpage
)
3042 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3044 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3045 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3047 int button_id
= evt
.GetInt();
3049 if (button_id
== wxAUI_BUTTON_CLOSE
)
3051 int selection
= tabs
->GetActivePage();
3053 if (selection
!= -1)
3055 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3058 // ask owner if it's ok to close the tab
3059 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3060 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3061 e
.SetOldSelection(evt
.GetSelection());
3062 e
.SetEventObject(this);
3063 GetEventHandler()->ProcessEvent(e
);
3068 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3074 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3075 DeletePage(main_idx
);