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"
31 #include "wx/aui/tabmdi.h"
32 #include "wx/dcbuffer.h"
35 #include "wx/mac/carbon/private.h"
38 #include "wx/arrimpl.cpp"
39 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
40 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
)
56 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
57 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
58 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
64 // these functions live in dockart.cpp -- they'll eventually
65 // be moved to a new utility cpp file
67 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
69 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
70 const wxColour
& color
);
72 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
74 static void DrawButtons(wxDC
& dc
,
77 const wxColour
& bkcolour
,
82 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
88 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
89 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
91 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
92 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
94 // draw the background behind the button
95 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
98 // draw the button itself
99 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
102 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
104 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
113 // -- GUI helper classes and functions --
115 class wxAuiCommandCapture
: public wxEvtHandler
119 wxAuiCommandCapture() { m_last_id
= 0; }
120 int GetCommandId() const { return m_last_id
; }
122 bool ProcessEvent(wxEvent
& evt
)
124 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
126 m_last_id
= evt
.GetId();
130 if (GetNextHandler())
131 return GetNextHandler()->ProcessEvent(evt
);
143 #if defined( __WXMAC__ )
144 static unsigned char close_bits
[]={
145 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
146 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
147 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
148 #elif defined( __WXGTK__)
149 static unsigned char close_bits
[]={
150 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
151 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
152 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
154 static unsigned char close_bits
[]={
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
156 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
160 static unsigned char left_bits
[] = {
161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
162 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
165 static unsigned char right_bits
[] = {
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
167 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
170 static unsigned char list_bits
[] = {
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
180 // -- wxAuiDefaultTabArt class implementation --
182 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
184 m_normal_font
= *wxNORMAL_FONT
;
185 m_selected_font
= *wxNORMAL_FONT
;
186 m_selected_font
.SetWeight(wxBOLD
);
187 m_measuring_font
= m_selected_font
;
189 m_fixed_tab_width
= 100;
190 m_tab_ctrl_height
= 0;
193 wxBrush toolbarbrush
;
194 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
195 wxColor base_colour
= toolbarbrush
.GetColour();
197 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
200 // the base_colour is too pale to use as our base colour,
201 // so darken it a bit --
202 if ((255-base_colour
.Red()) +
203 (255-base_colour
.Green()) +
204 (255-base_colour
.Blue()) < 60)
206 base_colour
= wxAuiStepColour(base_colour
, 92);
209 m_base_colour
= base_colour
;
210 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
212 m_border_pen
= wxPen(border_colour
);
213 m_base_colour_pen
= wxPen(m_base_colour
);
214 m_base_colour_brush
= wxBrush(m_base_colour
);
216 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
217 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
219 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
220 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
222 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
223 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
225 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
226 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
231 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
235 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
237 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
238 art
->SetNormalFont(m_normal_font
);
239 art
->SetSelectedFont(m_selected_font
);
240 art
->SetMeasuringFont(m_measuring_font
);
245 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
250 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
253 m_fixed_tab_width
= 100;
255 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
257 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
258 tot_width
-= m_active_close_bmp
.GetWidth();
259 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
260 tot_width
-= m_active_windowlist_bmp
.GetWidth();
264 m_fixed_tab_width
= tot_width
/(int)tab_count
;
268 if (m_fixed_tab_width
< 100)
269 m_fixed_tab_width
= 100;
271 if (m_fixed_tab_width
> tot_width
/2)
272 m_fixed_tab_width
= tot_width
/2;
274 if (m_fixed_tab_width
> 220)
275 m_fixed_tab_width
= 220;
277 m_tab_ctrl_height
= tab_ctrl_size
.y
;
281 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
282 wxWindow
* WXUNUSED(wnd
),
286 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
287 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
288 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
289 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
292 int y
= rect
.GetHeight();
293 int w
= rect
.GetWidth();
294 dc
.SetPen(m_border_pen
);
295 dc
.SetBrush(m_base_colour_brush
);
296 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
300 // DrawTab() draws an individual tab.
303 // in_rect - rectangle the tab should be confined to
304 // caption - tab's caption
305 // active - whether or not the tab is active
306 // out_rect - actual output rectangle
307 // x_extent - the advance x; where the next tab should start
309 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
311 const wxAuiNotebookPage
& page
,
312 const wxRect
& in_rect
,
313 int close_button_state
,
314 wxRect
* out_tab_rect
,
315 wxRect
* out_button_rect
,
318 wxCoord normal_textx
, normal_texty
;
319 wxCoord selected_textx
, selected_texty
;
320 wxCoord textx
, texty
;
322 // if the caption is empty, measure some temporary text
323 wxString caption
= page
.caption
;
327 dc
.SetFont(m_selected_font
);
328 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
330 dc
.SetFont(m_normal_font
);
331 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
333 // figure out the size of the tab
334 wxSize tab_size
= GetTabSize(dc
,
342 wxCoord tab_height
= m_tab_ctrl_height
- 3;
343 wxCoord tab_width
= tab_size
.x
;
344 wxCoord tab_x
= in_rect
.x
;
345 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
348 caption
= page
.caption
;
351 // select pen, brush and font for the tab to be drawn
355 dc
.SetFont(m_selected_font
);
356 textx
= selected_textx
;
357 texty
= selected_texty
;
361 dc
.SetFont(m_normal_font
);
362 textx
= normal_textx
;
363 texty
= normal_texty
;
367 // create points that will make the tab outline
369 int clip_width
= tab_width
;
370 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
371 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
374 wxPoint clip_points[6];
375 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
376 clip_points[1] = wxPoint(tab_x, tab_y+2);
377 clip_points[2] = wxPoint(tab_x+2, tab_y);
378 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
379 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
380 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
382 // FIXME: these ports don't provide wxRegion ctor from array of points
383 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
384 // set the clipping region for the tab --
385 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
386 dc.SetClippingRegion(clipping_region);
387 #endif // !wxDFB && !wxCocoa
389 // since the above code above doesn't play well with WXDFB or WXCOCOA,
390 // we'll just use a rectangle for the clipping region for now --
391 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
394 wxPoint border_points
[6];
395 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
396 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
397 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
398 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
399 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
400 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
403 int drawn_tab_yoff
= border_points
[1].y
;
404 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
411 // draw base background color
412 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
413 dc
.SetPen(m_base_colour_pen
);
414 dc
.SetBrush(m_base_colour_brush
);
415 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
417 // this white helps fill out the gradient at the top of the tab
418 dc
.SetPen(*wxWHITE_PEN
);
419 dc
.SetBrush(*wxWHITE_BRUSH
);
420 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
422 // these two points help the rounded corners appear more antialiased
423 dc
.SetPen(m_base_colour_pen
);
424 dc
.DrawPoint(r
.x
+2, r
.y
+1);
425 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
427 // set rectangle down a bit for gradient drawing
428 r
.SetHeight(r
.GetHeight()/2);
434 // draw gradient background
435 wxColor top_color
= *wxWHITE
;
436 wxColor bottom_color
= m_base_colour
;
437 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
443 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
445 // start the gradent up a bit and leave the inside border inset
446 // by a pixel for a 3D look. Only the top half of the inactive
447 // tab will have a slight gradient
454 // -- draw top gradient fill for glossy look
455 wxColor top_color
= m_base_colour
;
456 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
457 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
462 // -- draw bottom fill for glossy look
463 top_color
= m_base_colour
;
464 bottom_color
= m_base_colour
;
465 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
469 dc
.SetPen(m_border_pen
);
470 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
471 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
473 // there are two horizontal grey lines at the bottom of the tab control,
474 // this gets rid of the top one of those lines in the tab control
477 wxColor start_color
= m_base_colour
;
478 dc
.SetPen(m_base_colour_pen
);
479 dc
.DrawLine(border_points
[0].x
+1,
486 int text_offset
= tab_x
+ 8;
487 int close_button_width
= 0;
488 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
490 close_button_width
= m_active_close_bmp
.GetWidth();
494 if (page
.bitmap
.IsOk())
496 int bitmap_offset
= tab_x
+ 8;
499 dc
.DrawBitmap(page
.bitmap
,
501 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
504 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
505 text_offset
+= 3; // bitmap padding
509 text_offset
= tab_x
+ 8;
513 wxString draw_text
= wxAuiChopText(dc
,
515 tab_width
- (text_offset
-tab_x
) - close_button_width
);
518 dc
.DrawText(draw_text
,
520 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
525 // draw close button if necessary
526 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
528 wxBitmap bmp
= m_disabled_close_bmp
;
530 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
531 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
533 bmp
= m_active_close_bmp
;
536 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
537 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
540 IndentPressedBitmap(&rect
, close_button_state
);
541 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
543 *out_button_rect
= rect
;
546 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
548 dc
.DestroyClippingRegion();
551 int wxAuiDefaultTabArt::GetIndentSize()
556 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
557 wxWindow
* WXUNUSED(wnd
),
558 const wxString
& caption
,
559 const wxBitmap
& bitmap
,
560 bool WXUNUSED(active
),
561 int close_button_state
,
564 wxCoord measured_textx
, measured_texty
, tmp
;
566 dc
.SetFont(m_measuring_font
);
567 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
569 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
571 // add padding around the text
572 wxCoord tab_width
= measured_textx
;
573 wxCoord tab_height
= measured_texty
;
575 // if the close button is showing, add space for it
576 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
577 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
579 // if there's a bitmap, add space for it
582 tab_width
+= bitmap
.GetWidth();
583 tab_width
+= 3; // right side bitmap padding
584 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
591 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
593 tab_width
= m_fixed_tab_width
;
596 *x_extent
= tab_width
;
598 return wxSize(tab_width
, tab_height
);
602 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
603 wxWindow
* WXUNUSED(wnd
),
604 const wxRect
& in_rect
,
615 case wxAUI_BUTTON_CLOSE
:
616 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
617 bmp
= m_disabled_close_bmp
;
619 bmp
= m_active_close_bmp
;
621 case wxAUI_BUTTON_LEFT
:
622 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
623 bmp
= m_disabled_left_bmp
;
625 bmp
= m_active_left_bmp
;
627 case wxAUI_BUTTON_RIGHT
:
628 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
629 bmp
= m_disabled_right_bmp
;
631 bmp
= m_active_right_bmp
;
633 case wxAUI_BUTTON_WINDOWLIST
:
634 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
635 bmp
= m_disabled_windowlist_bmp
;
637 bmp
= m_active_windowlist_bmp
;
647 if (orientation
== wxLEFT
)
649 rect
.SetX(in_rect
.x
);
650 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
651 rect
.SetWidth(bmp
.GetWidth());
652 rect
.SetHeight(bmp
.GetHeight());
656 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
657 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
658 bmp
.GetWidth(), bmp
.GetHeight());
661 IndentPressedBitmap(&rect
, button_state
);
662 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
668 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
669 const wxAuiNotebookPageArray
& pages
,
674 size_t i
, count
= pages
.GetCount();
675 for (i
= 0; i
< count
; ++i
)
677 const wxAuiNotebookPage
& page
= pages
.Item(i
);
678 wxString caption
= page
.caption
;
680 // if there is no caption, make it a space. This will prevent
681 // an assert in the menu code.
682 if (caption
.IsEmpty())
685 menuPopup
.AppendCheckItem(1000+i
, caption
);
688 if (active_idx
!= -1)
690 menuPopup
.Check(1000+active_idx
, true);
693 // find out where to put the popup menu of window items
694 wxPoint pt
= ::wxGetMousePosition();
695 pt
= wnd
->ScreenToClient(pt
);
697 // find out the screen coordinate at the bottom of the tab ctrl
698 wxRect cli_rect
= wnd
->GetClientRect();
699 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
701 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
702 wnd
->PushEventHandler(cc
);
703 wnd
->PopupMenu(&menuPopup
, pt
);
704 int command
= cc
->GetCommandId();
705 wnd
->PopEventHandler(true);
713 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
714 const wxAuiNotebookPageArray
& pages
,
715 const wxSize
& required_bmp_size
)
718 dc
.SetFont(m_measuring_font
);
720 // sometimes a standard bitmap size needs to be enforced, especially
721 // if some tabs have bitmaps and others don't. This is important because
722 // it prevents the tab control from resizing when tabs are added.
723 wxBitmap measure_bmp
;
724 if (required_bmp_size
.IsFullySpecified())
726 measure_bmp
.Create(required_bmp_size
.x
,
727 required_bmp_size
.y
);
732 size_t i
, page_count
= pages
.GetCount();
733 for (i
= 0; i
< page_count
; ++i
)
735 wxAuiNotebookPage
& page
= pages
.Item(i
);
738 if (measure_bmp
.IsOk())
743 // we don't use the caption text because we don't
744 // want tab heights to be different in the case
745 // of a very short piece of text on one tab and a very
746 // tall piece of text on another tab
748 wxSize s
= GetTabSize(dc
,
753 wxAUI_BUTTON_STATE_HIDDEN
,
756 max_y
= wxMax(max_y
, s
.y
);
762 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
764 m_normal_font
= font
;
767 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
769 m_selected_font
= font
;
772 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
774 m_measuring_font
= font
;
778 // -- wxAuiSimpleTabArt class implementation --
780 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
782 m_normal_font
= *wxNORMAL_FONT
;
783 m_selected_font
= *wxNORMAL_FONT
;
784 m_selected_font
.SetWeight(wxBOLD
);
785 m_measuring_font
= m_selected_font
;
788 m_fixed_tab_width
= 100;
790 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
792 wxColour background_colour
= base_colour
;
793 wxColour normaltab_colour
= base_colour
;
794 wxColour selectedtab_colour
= *wxWHITE
;
796 m_bkbrush
= wxBrush(background_colour
);
797 m_normal_bkbrush
= wxBrush(normaltab_colour
);
798 m_normal_bkpen
= wxPen(normaltab_colour
);
799 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
800 m_selected_bkpen
= wxPen(selectedtab_colour
);
802 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
803 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
805 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
806 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
808 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
809 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
811 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
812 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
816 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
820 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
822 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
826 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
831 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
834 m_fixed_tab_width
= 100;
836 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
838 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
839 tot_width
-= m_active_close_bmp
.GetWidth();
840 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
841 tot_width
-= m_active_windowlist_bmp
.GetWidth();
845 m_fixed_tab_width
= tot_width
/(int)tab_count
;
849 if (m_fixed_tab_width
< 100)
850 m_fixed_tab_width
= 100;
852 if (m_fixed_tab_width
> tot_width
/2)
853 m_fixed_tab_width
= tot_width
/2;
855 if (m_fixed_tab_width
> 220)
856 m_fixed_tab_width
= 220;
859 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
860 wxWindow
* WXUNUSED(wnd
),
864 dc
.SetBrush(m_bkbrush
);
865 dc
.SetPen(*wxTRANSPARENT_PEN
);
866 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
869 dc
.SetPen(*wxGREY_PEN
);
870 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
874 // DrawTab() draws an individual tab.
877 // in_rect - rectangle the tab should be confined to
878 // caption - tab's caption
879 // active - whether or not the tab is active
880 // out_rect - actual output rectangle
881 // x_extent - the advance x; where the next tab should start
883 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
885 const wxAuiNotebookPage
& page
,
886 const wxRect
& in_rect
,
887 int close_button_state
,
888 wxRect
* out_tab_rect
,
889 wxRect
* out_button_rect
,
892 wxCoord normal_textx
, normal_texty
;
893 wxCoord selected_textx
, selected_texty
;
894 wxCoord textx
, texty
;
896 // if the caption is empty, measure some temporary text
897 wxString caption
= page
.caption
;
901 dc
.SetFont(m_selected_font
);
902 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
904 dc
.SetFont(m_normal_font
);
905 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
907 // figure out the size of the tab
908 wxSize tab_size
= GetTabSize(dc
,
916 wxCoord tab_height
= tab_size
.y
;
917 wxCoord tab_width
= tab_size
.x
;
918 wxCoord tab_x
= in_rect
.x
;
919 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
921 caption
= page
.caption
;
923 // select pen, brush and font for the tab to be drawn
927 dc
.SetPen(m_selected_bkpen
);
928 dc
.SetBrush(m_selected_bkbrush
);
929 dc
.SetFont(m_selected_font
);
930 textx
= selected_textx
;
931 texty
= selected_texty
;
935 dc
.SetPen(m_normal_bkpen
);
936 dc
.SetBrush(m_normal_bkbrush
);
937 dc
.SetFont(m_normal_font
);
938 textx
= normal_textx
;
939 texty
= normal_texty
;
947 points
[0].y
= tab_y
+ tab_height
- 1;
948 points
[1].x
= tab_x
+ tab_height
- 3;
949 points
[1].y
= tab_y
+ 2;
950 points
[2].x
= tab_x
+ tab_height
+ 3;
952 points
[3].x
= tab_x
+ tab_width
- 2;
954 points
[4].x
= tab_x
+ tab_width
;
955 points
[4].y
= tab_y
+ 2;
956 points
[5].x
= tab_x
+ tab_width
;
957 points
[5].y
= tab_y
+ tab_height
- 1;
958 points
[6] = points
[0];
960 dc
.SetClippingRegion(in_rect
);
962 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
964 dc
.SetPen(*wxGREY_PEN
);
966 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
967 dc
.DrawLines(WXSIZEOF(points
), points
);
972 int close_button_width
= 0;
973 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
975 close_button_width
= m_active_close_bmp
.GetWidth();
976 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
980 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
983 // set minimum text offset
984 if (text_offset
< tab_x
+ tab_height
)
985 text_offset
= tab_x
+ tab_height
;
987 // chop text if necessary
988 wxString draw_text
= wxAuiChopText(dc
,
990 tab_width
- (text_offset
-tab_x
) - close_button_width
);
993 dc
.DrawText(draw_text
,
995 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
998 // draw close button if necessary
999 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1003 bmp
= m_active_close_bmp
;
1005 bmp
= m_disabled_close_bmp
;
1007 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1008 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1011 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1013 *out_button_rect
= rect
;
1017 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1019 dc
.DestroyClippingRegion();
1022 int wxAuiSimpleTabArt::GetIndentSize()
1027 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1028 wxWindow
* WXUNUSED(wnd
),
1029 const wxString
& caption
,
1030 const wxBitmap
& WXUNUSED(bitmap
),
1031 bool WXUNUSED(active
),
1032 int close_button_state
,
1035 wxCoord measured_textx
, measured_texty
;
1037 dc
.SetFont(m_measuring_font
);
1038 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1040 wxCoord tab_height
= measured_texty
+ 4;
1041 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1043 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1044 tab_width
+= m_active_close_bmp
.GetWidth();
1046 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1048 tab_width
= m_fixed_tab_width
;
1051 *x_extent
= tab_width
- (tab_height
/2) - 1;
1053 return wxSize(tab_width
, tab_height
);
1057 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1058 wxWindow
* WXUNUSED(wnd
),
1059 const wxRect
& in_rect
,
1070 case wxAUI_BUTTON_CLOSE
:
1071 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1072 bmp
= m_disabled_close_bmp
;
1074 bmp
= m_active_close_bmp
;
1076 case wxAUI_BUTTON_LEFT
:
1077 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1078 bmp
= m_disabled_left_bmp
;
1080 bmp
= m_active_left_bmp
;
1082 case wxAUI_BUTTON_RIGHT
:
1083 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1084 bmp
= m_disabled_right_bmp
;
1086 bmp
= m_active_right_bmp
;
1088 case wxAUI_BUTTON_WINDOWLIST
:
1089 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1090 bmp
= m_disabled_windowlist_bmp
;
1092 bmp
= m_active_windowlist_bmp
;
1101 if (orientation
== wxLEFT
)
1103 rect
.SetX(in_rect
.x
);
1104 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1105 rect
.SetWidth(bmp
.GetWidth());
1106 rect
.SetHeight(bmp
.GetHeight());
1110 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1111 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1112 bmp
.GetWidth(), bmp
.GetHeight());
1116 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1122 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1123 const wxAuiNotebookPageArray
& pages
,
1128 size_t i
, count
= pages
.GetCount();
1129 for (i
= 0; i
< count
; ++i
)
1131 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1132 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1135 if (active_idx
!= -1)
1137 menuPopup
.Check(1000+active_idx
, true);
1140 // find out where to put the popup menu of window
1141 // items. Subtract 100 for now to center the menu
1142 // a bit, until a better mechanism can be implemented
1143 wxPoint pt
= ::wxGetMousePosition();
1144 pt
= wnd
->ScreenToClient(pt
);
1150 // find out the screen coordinate at the bottom of the tab ctrl
1151 wxRect cli_rect
= wnd
->GetClientRect();
1152 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1154 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1155 wnd
->PushEventHandler(cc
);
1156 wnd
->PopupMenu(&menuPopup
, pt
);
1157 int command
= cc
->GetCommandId();
1158 wnd
->PopEventHandler(true);
1160 if (command
>= 1000)
1161 return command
-1000;
1166 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1167 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1168 const wxSize
& WXUNUSED(required_bmp_size
))
1171 dc
.SetFont(m_measuring_font
);
1173 wxSize s
= GetTabSize(dc
,
1178 wxAUI_BUTTON_STATE_HIDDEN
,
1183 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1185 m_normal_font
= font
;
1188 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1190 m_selected_font
= font
;
1193 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1195 m_measuring_font
= font
;
1201 // -- wxAuiTabContainer class implementation --
1204 // wxAuiTabContainer is a class which contains information about each
1205 // tab. It also can render an entire tab control to a specified DC.
1206 // It's not a window class itself, because this code will be used by
1207 // the wxFrameMananger, where it is disadvantageous to have separate
1208 // windows for each tab control in the case of "docked tabs"
1210 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1211 // which can be used as a tab control in the normal sense.
1214 wxAuiTabContainer::wxAuiTabContainer()
1218 m_art
= new wxAuiDefaultTabArt
;
1220 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1221 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1222 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1223 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1226 wxAuiTabContainer::~wxAuiTabContainer()
1231 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1238 m_art
->SetFlags(m_flags
);
1242 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1247 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1251 // check for new close button settings
1252 RemoveButton(wxAUI_BUTTON_LEFT
);
1253 RemoveButton(wxAUI_BUTTON_RIGHT
);
1254 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1255 RemoveButton(wxAUI_BUTTON_CLOSE
);
1258 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1260 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1261 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1264 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1266 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1269 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1271 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1276 m_art
->SetFlags(m_flags
);
1280 unsigned int wxAuiTabContainer::GetFlags() const
1286 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1288 m_art
->SetNormalFont(font
);
1291 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1293 m_art
->SetSelectedFont(font
);
1296 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1298 m_art
->SetMeasuringFont(font
);
1301 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1307 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1311 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1312 const wxAuiNotebookPage
& info
)
1314 wxAuiNotebookPage page_info
;
1316 page_info
.window
= page
;
1318 m_pages
.Add(page_info
);
1320 // let the art provider know how many pages we have
1323 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1329 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1330 const wxAuiNotebookPage
& info
,
1333 wxAuiNotebookPage page_info
;
1335 page_info
.window
= page
;
1337 if (idx
>= m_pages
.GetCount())
1338 m_pages
.Add(page_info
);
1340 m_pages
.Insert(page_info
, idx
);
1342 // let the art provider know how many pages we have
1345 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1351 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1354 int idx
= GetIdxFromWindow(page
);
1358 // get page entry, make a copy of it
1359 wxAuiNotebookPage p
= GetPage(idx
);
1361 // remove old page entry
1364 // insert page where it should be
1365 InsertPage(page
, p
, new_idx
);
1370 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1372 size_t i
, page_count
= m_pages
.GetCount();
1373 for (i
= 0; i
< page_count
; ++i
)
1375 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1376 if (page
.window
== wnd
)
1378 m_pages
.RemoveAt(i
);
1380 // let the art provider know how many pages we have
1383 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1393 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1397 size_t i
, page_count
= m_pages
.GetCount();
1398 for (i
= 0; i
< page_count
; ++i
)
1400 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1401 if (page
.window
== wnd
)
1408 page
.active
= false;
1415 void wxAuiTabContainer::SetNoneActive()
1417 size_t i
, page_count
= m_pages
.GetCount();
1418 for (i
= 0; i
< page_count
; ++i
)
1420 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1421 page
.active
= false;
1425 bool wxAuiTabContainer::SetActivePage(size_t page
)
1427 if (page
>= m_pages
.GetCount())
1430 return SetActivePage(m_pages
.Item(page
).window
);
1433 int wxAuiTabContainer::GetActivePage() const
1435 size_t i
, page_count
= m_pages
.GetCount();
1436 for (i
= 0; i
< page_count
; ++i
)
1438 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1446 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1448 if (idx
>= m_pages
.GetCount())
1451 return m_pages
[idx
].window
;
1454 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1456 const size_t page_count
= m_pages
.GetCount();
1457 for ( size_t i
= 0; i
< page_count
; ++i
)
1459 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1460 if (page
.window
== wnd
)
1466 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1468 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1470 return m_pages
[idx
];
1473 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1475 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1477 return m_pages
[idx
];
1480 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1485 size_t wxAuiTabContainer::GetPageCount() const
1487 return m_pages
.GetCount();
1490 void wxAuiTabContainer::AddButton(int id
,
1492 const wxBitmap
& normal_bitmap
,
1493 const wxBitmap
& disabled_bitmap
)
1495 wxAuiTabContainerButton button
;
1497 button
.bitmap
= normal_bitmap
;
1498 button
.dis_bitmap
= disabled_bitmap
;
1499 button
.location
= location
;
1500 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1502 m_buttons
.Add(button
);
1505 void wxAuiTabContainer::RemoveButton(int id
)
1507 size_t i
, button_count
= m_buttons
.GetCount();
1509 for (i
= 0; i
< button_count
; ++i
)
1511 if (m_buttons
.Item(i
).id
== id
)
1513 m_buttons
.RemoveAt(i
);
1521 size_t wxAuiTabContainer::GetTabOffset() const
1523 return m_tab_offset
;
1526 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1528 m_tab_offset
= offset
;
1534 // Render() renders the tab catalog to the specified DC
1535 // It is a virtual function and can be overridden to
1536 // provide custom drawing capabilities
1537 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1539 if (!raw_dc
|| !raw_dc
->IsOk())
1545 size_t page_count
= m_pages
.GetCount();
1546 size_t button_count
= m_buttons
.GetCount();
1548 // create off-screen bitmap
1549 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1550 dc
.SelectObject(bmp
);
1555 // find out if size of tabs is larger than can be
1556 // afforded on screen
1557 int total_width
= 0;
1558 int visible_width
= 0;
1559 for (i
= 0; i
< page_count
; ++i
)
1561 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1563 // determine if a close button is on this tab
1564 bool close_button
= false;
1565 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1566 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1568 close_button
= true;
1573 wxSize size
= m_art
->GetTabSize(dc
,
1579 wxAUI_BUTTON_STATE_NORMAL
:
1580 wxAUI_BUTTON_STATE_HIDDEN
,
1583 if (i
+1 < page_count
)
1584 total_width
+= x_extent
;
1586 total_width
+= size
.x
;
1588 if (i
>= m_tab_offset
)
1590 if (i
+1 < page_count
)
1591 visible_width
+= x_extent
;
1593 visible_width
+= size
.x
;
1597 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1599 // show left/right buttons
1600 for (i
= 0; i
< button_count
; ++i
)
1602 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1603 if (button
.id
== wxAUI_BUTTON_LEFT
||
1604 button
.id
== wxAUI_BUTTON_RIGHT
)
1606 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1612 // hide left/right buttons
1613 for (i
= 0; i
< button_count
; ++i
)
1615 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1616 if (button
.id
== wxAUI_BUTTON_LEFT
||
1617 button
.id
== wxAUI_BUTTON_RIGHT
)
1619 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1624 // determine whether left button should be enabled
1625 for (i
= 0; i
< button_count
; ++i
)
1627 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1628 if (button
.id
== wxAUI_BUTTON_LEFT
)
1630 if (m_tab_offset
== 0)
1631 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1633 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1635 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1637 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1638 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1640 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1647 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1650 int left_buttons_width
= 0;
1651 int right_buttons_width
= 0;
1655 // draw the buttons on the right side
1656 offset
= m_rect
.x
+ m_rect
.width
;
1657 for (i
= 0; i
< button_count
; ++i
)
1659 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1661 if (button
.location
!= wxRIGHT
)
1663 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1666 wxRect button_rect
= m_rect
;
1667 button_rect
.SetY(1);
1668 button_rect
.SetWidth(offset
);
1670 m_art
->DrawButton(dc
,
1678 offset
-= button
.rect
.GetWidth();
1679 right_buttons_width
+= button
.rect
.GetWidth();
1686 // draw the buttons on the left side
1688 for (i
= 0; i
< button_count
; ++i
)
1690 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1692 if (button
.location
!= wxLEFT
)
1694 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1697 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1699 m_art
->DrawButton(dc
,
1707 offset
+= button
.rect
.GetWidth();
1708 left_buttons_width
+= button
.rect
.GetWidth();
1711 offset
= left_buttons_width
;
1714 offset
+= m_art
->GetIndentSize();
1717 // prepare the tab-close-button array
1718 // make sure tab button entries which aren't used are marked as hidden
1719 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1720 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1722 // make sure there are enough tab button entries to accommodate all tabs
1723 while (m_tab_close_buttons
.GetCount() < page_count
)
1725 wxAuiTabContainerButton tempbtn
;
1726 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1727 tempbtn
.location
= wxCENTER
;
1728 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1729 m_tab_close_buttons
.Add(tempbtn
);
1733 // buttons before the tab offset must be set to hidden
1734 for (i
= 0; i
< m_tab_offset
; ++i
)
1736 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1742 size_t active
= 999;
1743 int active_offset
= 0;
1747 wxRect rect
= m_rect
;
1749 rect
.height
= m_rect
.height
;
1751 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1753 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1754 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1756 // determine if a close button is on this tab
1757 bool close_button
= false;
1758 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1759 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1761 close_button
= true;
1762 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1764 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1765 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1766 tab_button
.location
= wxCENTER
;
1771 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1775 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1777 if (rect
.width
<= 0)
1784 tab_button
.cur_state
,
1792 active_offset
= offset
;
1800 // make sure to deactivate buttons which are off the screen to the right
1801 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1803 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1807 // draw the active tab again so it stands in the foreground
1808 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1810 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1812 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1814 // determine if a close button is on this tab
1815 bool close_button
= false;
1816 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1817 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1819 close_button
= true;
1822 rect
.x
= active_offset
;
1827 tab_button
.cur_state
,
1834 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1835 m_rect
.GetWidth(), m_rect
.GetHeight(),
1840 // TabHitTest() tests if a tab was hit, passing the window pointer
1841 // back if that condition was fulfilled. The function returns
1842 // true if a tab was hit, otherwise false
1843 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1845 if (!m_rect
.Contains(x
,y
))
1848 wxAuiTabContainerButton
* btn
= NULL
;
1849 if (ButtonHitTest(x
, y
, &btn
))
1851 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1855 size_t i
, page_count
= m_pages
.GetCount();
1857 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1859 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1860 if (page
.rect
.Contains(x
,y
))
1871 // ButtonHitTest() tests if a button was hit. The function returns
1872 // true if a button was hit, otherwise false
1873 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1874 wxAuiTabContainerButton
** hit
) const
1876 if (!m_rect
.Contains(x
,y
))
1879 size_t i
, button_count
;
1882 button_count
= m_buttons
.GetCount();
1883 for (i
= 0; i
< button_count
; ++i
)
1885 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1886 if (button
.rect
.Contains(x
,y
) &&
1887 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1888 wxAUI_BUTTON_STATE_DISABLED
)))
1896 button_count
= m_tab_close_buttons
.GetCount();
1897 for (i
= 0; i
< button_count
; ++i
)
1899 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1900 if (button
.rect
.Contains(x
,y
) &&
1901 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1902 wxAUI_BUTTON_STATE_DISABLED
)))
1915 // the utility function ShowWnd() is the same as show,
1916 // except it handles wxAuiMDIChildFrame windows as well,
1917 // as the Show() method on this class is "unplugged"
1918 static void ShowWnd(wxWindow
* wnd
, bool show
)
1920 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1922 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1932 // DoShowHide() this function shows the active window, then
1933 // hides all of the other windows (in that order)
1934 void wxAuiTabContainer::DoShowHide()
1936 wxAuiNotebookPageArray
& pages
= GetPages();
1937 size_t i
, page_count
= pages
.GetCount();
1939 // show new active page first
1940 for (i
= 0; i
< page_count
; ++i
)
1942 wxAuiNotebookPage
& page
= pages
.Item(i
);
1945 ShowWnd(page
.window
, true);
1950 // hide all other pages
1951 for (i
= 0; i
< page_count
; ++i
)
1953 wxAuiNotebookPage
& page
= pages
.Item(i
);
1955 ShowWnd(page
.window
, false);
1964 // -- wxAuiTabCtrl class implementation --
1968 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1969 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1970 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1971 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1972 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1973 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1974 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1975 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
1976 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
1977 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
1978 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
1979 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1980 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1981 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
1985 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1989 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1991 m_click_pt
= wxDefaultPosition
;
1992 m_is_dragging
= false;
1993 m_hover_button
= NULL
;
1994 m_pressed_button
= NULL
;
1997 wxAuiTabCtrl::~wxAuiTabCtrl()
2001 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2005 dc
.SetFont(GetFont());
2007 if (GetPageCount() > 0)
2011 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2015 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2017 wxSize s
= evt
.GetSize();
2018 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2022 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2025 m_click_pt
= wxDefaultPosition
;
2026 m_is_dragging
= false;
2028 m_pressed_button
= NULL
;
2032 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2034 int new_selection
= GetIdxFromWindow(wnd
);
2036 // wxAuiNotebooks always want to receive this event
2037 // even if the tab is already active, because they may
2038 // have multiple tab controls
2039 if (new_selection
!= GetActivePage() ||
2040 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2042 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2043 e
.SetSelection(new_selection
);
2044 e
.SetOldSelection(GetActivePage());
2045 e
.SetEventObject(this);
2046 GetEventHandler()->ProcessEvent(e
);
2049 m_click_pt
.x
= evt
.m_x
;
2050 m_click_pt
.y
= evt
.m_y
;
2056 m_pressed_button
= m_hover_button
;
2057 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2063 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2065 if (GetCapture() == this)
2070 m_is_dragging
= false;
2072 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2073 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2074 evt
.SetOldSelection(evt
.GetSelection());
2075 evt
.SetEventObject(this);
2076 GetEventHandler()->ProcessEvent(evt
);
2081 if (m_pressed_button
)
2083 // make sure we're still clicking the button
2084 wxAuiTabContainerButton
* button
= NULL
;
2085 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2088 if (button
!= m_pressed_button
)
2090 m_pressed_button
= NULL
;
2097 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2099 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2100 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2101 evt
.SetInt(m_pressed_button
->id
);
2102 evt
.SetEventObject(this);
2103 GetEventHandler()->ProcessEvent(evt
);
2106 m_pressed_button
= NULL
;
2109 m_click_pt
= wxDefaultPosition
;
2110 m_is_dragging
= false;
2114 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2116 wxWindow
* wnd
= NULL
;
2117 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2120 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2121 e
.SetEventObject(this);
2122 e
.SetSelection(GetIdxFromWindow(wnd
));
2123 GetEventHandler()->ProcessEvent(e
);
2126 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2128 wxWindow
* wnd
= NULL
;
2129 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2132 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2133 e
.SetEventObject(this);
2134 e
.SetSelection(GetIdxFromWindow(wnd
));
2135 GetEventHandler()->ProcessEvent(e
);
2138 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2140 wxWindow
* wnd
= NULL
;
2141 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2144 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2145 e
.SetEventObject(this);
2146 e
.SetSelection(GetIdxFromWindow(wnd
));
2147 GetEventHandler()->ProcessEvent(e
);
2150 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2152 wxWindow
* wnd
= NULL
;
2153 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2156 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2157 e
.SetEventObject(this);
2158 e
.SetSelection(GetIdxFromWindow(wnd
));
2159 GetEventHandler()->ProcessEvent(e
);
2162 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2164 wxPoint pos
= evt
.GetPosition();
2166 // check if the mouse is hovering above a button
2167 wxAuiTabContainerButton
* button
;
2168 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2170 if (m_hover_button
&& button
!= m_hover_button
)
2172 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2173 m_hover_button
= NULL
;
2178 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2180 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2183 m_hover_button
= button
;
2191 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2192 m_hover_button
= NULL
;
2199 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2204 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2205 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2206 evt
.SetOldSelection(evt
.GetSelection());
2207 evt
.SetEventObject(this);
2208 GetEventHandler()->ProcessEvent(evt
);
2213 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2214 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2216 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2217 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2219 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2220 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2221 evt
.SetOldSelection(evt
.GetSelection());
2222 evt
.SetEventObject(this);
2223 GetEventHandler()->ProcessEvent(evt
);
2225 m_is_dragging
= true;
2229 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2233 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2234 m_hover_button
= NULL
;
2240 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2242 int button
= event
.GetInt();
2244 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2246 if (button
== wxAUI_BUTTON_LEFT
)
2248 if (GetTabOffset() > 0)
2250 SetTabOffset(GetTabOffset()-1);
2257 SetTabOffset(GetTabOffset()+1);
2262 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2264 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2268 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2269 e
.SetSelection(idx
);
2270 e
.SetOldSelection(GetActivePage());
2271 e
.SetEventObject(this);
2272 GetEventHandler()->ProcessEvent(e
);
2281 // wxTabFrame is an interesting case. It's important that all child pages
2282 // of the multi-notebook control are all actually children of that control
2283 // (and not grandchildren). wxTabFrame facilitates this. There is one
2284 // instance of wxTabFrame for each tab control inside the multi-notebook.
2285 // It's important to know that wxTabFrame is not a real window, but it merely
2286 // used to capture the dimensions/positioning of the internal tab control and
2287 // it's managed page windows
2289 class wxTabFrame
: public wxWindow
2296 m_rect
= wxRect(0,0,200,200);
2297 m_tab_ctrl_height
= 20;
2305 void SetTabCtrlHeight(int h
)
2307 m_tab_ctrl_height
= h
;
2310 void DoSetSize(int x
, int y
,
2311 int width
, int height
,
2312 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2314 m_rect
= wxRect(x
, y
, width
, height
);
2318 void DoGetClientSize(int* x
, int* y
) const
2324 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2331 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2332 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2333 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2337 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2338 size_t i
, page_count
= pages
.GetCount();
2340 for (i
= 0; i
< page_count
; ++i
)
2342 wxAuiNotebookPage
& page
= pages
.Item(i
);
2343 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2344 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2346 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2348 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2349 wnd
->ApplyMDIChildFrameRect();
2354 void DoGetSize(int* x
, int* y
) const
2357 *x
= m_rect
.GetWidth();
2359 *y
= m_rect
.GetHeight();
2371 wxAuiTabCtrl
* m_tabs
;
2372 int m_tab_ctrl_height
;
2376 const int wxAuiBaseTabCtrlId
= 5380;
2379 // -- wxAuiNotebook class implementation --
2381 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2382 EVT_SIZE(wxAuiNotebook::OnSize
)
2383 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2384 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2385 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2386 wxAuiNotebook::OnTabClicked
)
2387 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2388 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2389 wxAuiNotebook::OnTabBeginDrag
)
2390 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2391 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2392 wxAuiNotebook::OnTabEndDrag
)
2393 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2394 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2395 wxAuiNotebook::OnTabDragMotion
)
2396 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2397 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2398 wxAuiNotebook::OnTabButton
)
2399 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2400 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2401 wxAuiNotebook::OnTabMiddleDown
)
2402 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2403 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2404 wxAuiNotebook::OnTabMiddleUp
)
2405 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2406 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2407 wxAuiNotebook::OnTabRightDown
)
2408 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2409 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2410 wxAuiNotebook::OnTabRightUp
)
2413 wxAuiNotebook::wxAuiNotebook()
2416 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2418 m_tab_ctrl_height
= 20;
2419 m_requested_bmp_size
= wxDefaultSize
;
2420 m_requested_tabctrl_height
= -1;
2423 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2427 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2430 m_requested_bmp_size
= wxDefaultSize
;
2431 m_requested_tabctrl_height
= -1;
2432 InitNotebook(style
);
2435 bool wxAuiNotebook::Create(wxWindow
* parent
,
2441 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2444 InitNotebook(style
);
2449 // InitNotebook() contains common initialization
2450 // code called by all constructors
2451 void wxAuiNotebook::InitNotebook(long style
)
2454 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2456 m_flags
= (unsigned int)style
;
2457 m_tab_ctrl_height
= 20;
2459 m_normal_font
= *wxNORMAL_FONT
;
2460 m_selected_font
= *wxNORMAL_FONT
;
2461 m_selected_font
.SetWeight(wxBOLD
);
2463 SetArtProvider(new wxAuiDefaultTabArt
);
2465 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2466 m_dummy_wnd
->SetSize(200, 200);
2467 m_dummy_wnd
->Show(false);
2469 m_mgr
.SetManagedWindow(this);
2470 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2471 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2473 m_mgr
.AddPane(m_dummy_wnd
,
2474 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2479 wxAuiNotebook::~wxAuiNotebook()
2484 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2486 m_tabs
.SetArtProvider(art
);
2488 UpdateTabCtrlHeight();
2491 // SetTabCtrlHeight() is the highest-level override of the
2492 // tab height. A call to this function effectively enforces a
2493 // specified tab ctrl height, overriding all other considerations,
2494 // such as text or bitmap height. It overrides any call to
2495 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2496 // any previous call and returns to the default behavior
2498 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2500 m_requested_tabctrl_height
= height
;
2502 // if window is already initialized, recalculate the tab height
2505 UpdateTabCtrlHeight();
2510 // SetUniformBitmapSize() ensures that all tabs will have
2511 // the same height, even if some tabs don't have bitmaps
2512 // Passing wxDefaultSize to this function will instruct
2513 // the control to use dynamic tab height-- so when a tab
2514 // with a large bitmap is added, the tab ctrl's height will
2515 // automatically increase to accommodate the bitmap
2517 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2519 m_requested_bmp_size
= size
;
2521 // if window is already initialized, recalculate the tab height
2524 UpdateTabCtrlHeight();
2528 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2529 // to be used interally
2530 void wxAuiNotebook::UpdateTabCtrlHeight()
2532 // get the tab ctrl height we will use
2533 int height
= CalculateTabCtrlHeight();
2535 // if the tab control height needs to change, update
2536 // all of our tab controls with the new height
2537 if (m_tab_ctrl_height
!= height
)
2539 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2541 m_tab_ctrl_height
= height
;
2543 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2544 size_t i
, pane_count
= all_panes
.GetCount();
2545 for (i
= 0; i
< pane_count
; ++i
)
2547 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2548 if (pane
.name
== wxT("dummy"))
2550 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2551 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2552 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2553 tabctrl
->SetArtProvider(art
->Clone());
2554 tab_frame
->DoSizing();
2559 void wxAuiNotebook::UpdateHintWindowSize()
2561 wxSize size
= CalculateNewSplitSize();
2563 // the placeholder hint window should be set to this size
2564 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2568 info
.BestSize(size
);
2569 m_dummy_wnd
->SetSize(size
);
2574 // calculates the size of the new split
2575 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2577 // count number of tab controls
2578 int tab_ctrl_count
= 0;
2579 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2580 size_t i
, pane_count
= all_panes
.GetCount();
2581 for (i
= 0; i
< pane_count
; ++i
)
2583 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2584 if (pane
.name
== wxT("dummy"))
2589 wxSize new_split_size
;
2591 // if there is only one tab control, the first split
2592 // should happen around the middle
2593 if (tab_ctrl_count
< 2)
2595 new_split_size
= GetClientSize();
2596 new_split_size
.x
/= 2;
2597 new_split_size
.y
/= 2;
2601 // this is in place of a more complicated calculation
2602 // that needs to be implemented
2603 new_split_size
= wxSize(180,180);
2606 return new_split_size
;
2609 int wxAuiNotebook::CalculateTabCtrlHeight()
2611 // if a fixed tab ctrl height is specified,
2612 // just return that instead of calculating a
2614 if (m_requested_tabctrl_height
!= -1)
2615 return m_requested_tabctrl_height
;
2617 // find out new best tab height
2618 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2620 return art
->GetBestTabCtrlSize(this,
2622 m_requested_bmp_size
);
2626 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2628 return m_tabs
.GetArtProvider();
2631 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2633 wxControl::SetWindowStyleFlag(style
);
2635 m_flags
= (unsigned int)style
;
2637 // if the control is already initialized
2638 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2640 // let all of the tab children know about the new style
2642 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2643 size_t i
, pane_count
= all_panes
.GetCount();
2644 for (i
= 0; i
< pane_count
; ++i
)
2646 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2647 if (pane
.name
== wxT("dummy"))
2649 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2650 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2651 tabctrl
->SetFlags(m_flags
);
2652 tabframe
->DoSizing();
2660 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2661 const wxString
& caption
,
2663 const wxBitmap
& bitmap
)
2665 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2668 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2670 const wxString
& caption
,
2672 const wxBitmap
& bitmap
)
2674 wxAuiNotebookPage info
;
2676 info
.caption
= caption
;
2677 info
.bitmap
= bitmap
;
2678 info
.active
= false;
2680 // if there are currently no tabs, the first added
2681 // tab must be active
2682 if (m_tabs
.GetPageCount() == 0)
2685 m_tabs
.InsertPage(page
, info
, page_idx
);
2687 // if that was the first page added, even if
2688 // select is false, it must become the "current page"
2689 // (though no select events will be fired)
2690 if (!select
&& m_tabs
.GetPageCount() == 1)
2692 //m_curpage = GetPageIndex(page);
2694 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2695 if (page_idx
>= active_tabctrl
->GetPageCount())
2696 active_tabctrl
->AddPage(page
, info
);
2698 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2700 UpdateTabCtrlHeight();
2702 active_tabctrl
->DoShowHide();
2706 SetSelectionToWindow(page
);
2713 // DeletePage() removes a tab from the multi-notebook,
2714 // and destroys the window as well
2715 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2717 if (page_idx
>= m_tabs
.GetPageCount())
2720 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2722 // hide the window in advance, as this will
2724 ShowWnd(wnd
, false);
2726 if (!RemovePage(page_idx
))
2729 // actually destroy the window now
2730 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2732 // delete the child frame with pending delete, as is
2733 // customary with frame windows
2734 if (!wxPendingDelete
.Member(wnd
))
2735 wxPendingDelete
.Append(wnd
);
2747 // RemovePage() removes a tab from the multi-notebook,
2748 // but does not destroy the window
2749 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2751 // save active window pointer
2752 wxWindow
* active_wnd
= NULL
;
2754 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
2756 // save pointer of window being deleted
2757 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2758 wxWindow
* new_active
= NULL
;
2760 // make sure we found the page
2764 // find out which onscreen tab ctrl owns this tab
2767 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2770 bool is_curpage
= (m_curpage
== (int)page_idx
);
2771 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
2774 // remove the tab from main catalog
2775 if (!m_tabs
.RemovePage(wnd
))
2778 // remove the tab from the onscreen tab ctrl
2779 ctrl
->RemovePage(wnd
);
2781 if (is_active_in_split
)
2783 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
2785 if (ctrl_idx
>= ctrl_new_page_count
)
2786 ctrl_idx
= ctrl_new_page_count
-1;
2788 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
2790 // set new page as active in the tab split
2791 ctrl
->SetActivePage(ctrl_idx
);
2793 // if the page deleted was the current page for the
2794 // entire tab control, then record the window
2795 // pointer of the new active page for activation
2798 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
2804 // we are not deleting the active page, so keep it the same
2805 new_active
= active_wnd
;
2811 // we haven't yet found a new page to active,
2812 // so select the next page from the main tab
2815 if (page_idx
< m_tabs
.GetPageCount())
2817 new_active
= m_tabs
.GetPage(page_idx
).window
;
2820 if (!new_active
&& m_tabs
.GetPageCount() > 0)
2822 new_active
= m_tabs
.GetPage(0).window
;
2827 RemoveEmptyTabFrames();
2829 // set new active pane
2833 SetSelectionToWindow(new_active
);
2839 // GetPageIndex() returns the index of the page, or -1 if the
2840 // page could not be located in the notebook
2841 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2843 return m_tabs
.GetIdxFromWindow(page_wnd
);
2848 // SetPageText() changes the tab caption of the specified page
2849 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2851 if (page_idx
>= m_tabs
.GetPageCount())
2854 // update our own tab catalog
2855 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2856 page_info
.caption
= text
;
2858 // update what's on screen
2861 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2863 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2864 info
.caption
= text
;
2872 // returns the page caption
2873 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2875 if (page_idx
>= m_tabs
.GetPageCount())
2876 return wxEmptyString
;
2878 // update our own tab catalog
2879 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2880 return page_info
.caption
;
2883 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2885 if (page_idx
>= m_tabs
.GetPageCount())
2888 // update our own tab catalog
2889 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2890 page_info
.bitmap
= bitmap
;
2892 // tab height might have changed
2893 UpdateTabCtrlHeight();
2895 // update what's on screen
2898 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2900 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2901 info
.bitmap
= bitmap
;
2909 // returns the page bitmap
2910 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2912 if (page_idx
>= m_tabs
.GetPageCount())
2915 // update our own tab catalog
2916 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2917 return page_info
.bitmap
;
2920 // GetSelection() returns the index of the currently active page
2921 int wxAuiNotebook::GetSelection() const
2926 // SetSelection() sets the currently active page
2927 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2929 // don't change the page unless necessary
2930 if ((int)new_page
== m_curpage
)
2933 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2937 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2938 evt
.SetSelection(new_page
);
2939 evt
.SetOldSelection(m_curpage
);
2940 evt
.SetEventObject(this);
2941 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2943 int old_curpage
= m_curpage
;
2944 m_curpage
= new_page
;
2946 // program allows the page change
2947 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2948 (void)GetEventHandler()->ProcessEvent(evt
);
2953 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2955 m_tabs
.SetActivePage(wnd
);
2957 ctrl
->SetActivePage(ctrl_idx
);
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 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2969 if (pane
.name
== wxT("dummy"))
2971 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2972 if (tabctrl
!= ctrl
)
2973 tabctrl
->SetSelectedFont(m_normal_font
);
2975 tabctrl
->SetSelectedFont(m_selected_font
);
2988 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2990 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2991 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2996 // GetPageCount() returns the total number of
2997 // pages managed by the multi-notebook
2998 size_t wxAuiNotebook::GetPageCount() const
3000 return m_tabs
.GetPageCount();
3003 // GetPage() returns the wxWindow pointer of the
3005 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3007 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3009 return m_tabs
.GetWindowFromIdx(page_idx
);
3012 // DoSizing() performs all sizing operations in each tab control
3013 void wxAuiNotebook::DoSizing()
3015 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3016 size_t i
, pane_count
= all_panes
.GetCount();
3017 for (i
= 0; i
< pane_count
; ++i
)
3019 if (all_panes
.Item(i
).name
== wxT("dummy"))
3022 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3023 tabframe
->DoSizing();
3027 // GetActiveTabCtrl() returns the active tab control. It is
3028 // called to determine which control gets new windows being added
3029 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3031 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3036 // find the tab ctrl with the current page
3037 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3044 // no current page, just find the first tab ctrl
3045 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3046 size_t i
, pane_count
= all_panes
.GetCount();
3047 for (i
= 0; i
< pane_count
; ++i
)
3049 if (all_panes
.Item(i
).name
== wxT("dummy"))
3052 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3053 return tabframe
->m_tabs
;
3056 // If there is no tabframe at all, create one
3057 wxTabFrame
* tabframe
= new wxTabFrame
;
3058 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3059 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3064 tabframe
->m_tabs
->SetFlags(m_flags
);
3065 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3066 m_mgr
.AddPane(tabframe
,
3067 wxAuiPaneInfo().Center().CaptionVisible(false));
3071 return tabframe
->m_tabs
;
3074 // FindTab() finds the tab control that currently contains the window as well
3075 // as the index of the window in the tab control. It returns true if the
3076 // window was found, otherwise false.
3077 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3079 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3080 size_t i
, pane_count
= all_panes
.GetCount();
3081 for (i
= 0; i
< pane_count
; ++i
)
3083 if (all_panes
.Item(i
).name
== wxT("dummy"))
3086 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3088 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3091 *ctrl
= tabframe
->m_tabs
;
3100 void wxAuiNotebook::Split(size_t page
, int direction
)
3102 wxSize cli_size
= GetClientSize();
3104 // get the page's window pointer
3105 wxWindow
* wnd
= GetPage(page
);
3109 // notebooks with 1 or less pages can't be split
3110 if (GetPageCount() < 2)
3113 // find out which tab control the page currently belongs to
3114 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3117 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3119 if (!src_tabs
|| src_idx
== -1)
3122 // choose a split size
3124 if (GetPageCount() > 2)
3126 split_size
= CalculateNewSplitSize();
3130 // because there are two panes, always split them
3132 split_size
= GetClientSize();
3138 // create a new tab frame
3139 wxTabFrame
* new_tabs
= new wxTabFrame
;
3140 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3141 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3142 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3147 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3148 new_tabs
->m_tabs
->SetFlags(m_flags
);
3149 dest_tabs
= new_tabs
->m_tabs
;
3151 // create a pane info structure with the information
3152 // about where the pane should be added
3153 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3156 if (direction
== wxLEFT
)
3159 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3161 else if (direction
== wxRIGHT
)
3164 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3166 else if (direction
== wxTOP
)
3169 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3171 else if (direction
== wxBOTTOM
)
3174 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3177 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3180 // remove the page from the source tabs
3181 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3182 page_info
.active
= false;
3183 src_tabs
->RemovePage(page_info
.window
);
3184 if (src_tabs
->GetPageCount() > 0)
3186 src_tabs
->SetActivePage((size_t)0);
3187 src_tabs
->DoShowHide();
3188 src_tabs
->Refresh();
3192 // add the page to the destination tabs
3193 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3195 if (src_tabs
->GetPageCount() == 0)
3197 RemoveEmptyTabFrames();
3201 dest_tabs
->DoShowHide();
3202 dest_tabs
->Refresh();
3204 // force the set selection function reset the selection
3207 // set the active page to the one we just split off
3208 SetSelectionToPage(page_info
);
3210 UpdateHintWindowSize();
3214 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3216 UpdateHintWindowSize();
3221 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3223 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3225 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3226 wxASSERT(ctrl
!= NULL
);
3228 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3229 wxASSERT(wnd
!= NULL
);
3231 SetSelectionToWindow(wnd
);
3234 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3239 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3241 wxPoint screen_pt
= ::wxGetMousePosition();
3242 wxPoint client_pt
= ScreenToClient(screen_pt
);
3245 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3246 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3248 if (dest_tabs
== src_tabs
)
3252 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3255 // always hide the hint for inner-tabctrl drag
3258 // if tab moving is not allowed, leave
3259 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3264 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3265 wxWindow
* dest_location_tab
;
3267 // this is an inner-tab drag/reposition
3268 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3270 int src_idx
= evt
.GetSelection();
3271 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3273 // prevent jumpy drag
3274 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3275 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3276 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3278 m_last_drag_x
= pt
.x
;
3283 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3284 dest_tabs
->MovePage(src_tab
, dest_idx
);
3285 dest_tabs
->SetActivePage((size_t)dest_idx
);
3286 dest_tabs
->DoShowHide();
3287 dest_tabs
->Refresh();
3288 m_last_drag_x
= pt
.x
;
3296 // if external drag is allowed, check if the tab is being dragged
3297 // over a different wxAuiNotebook control
3298 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3300 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3302 // if we aren't over any window, stop here
3306 // make sure we are not over the hint window
3307 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3311 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3313 tab_ctrl
= tab_ctrl
->GetParent();
3318 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3322 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3323 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3324 m_mgr
.ShowHint(hint_rect
);
3333 // we are either over a hint window, or not over a tab
3334 // window, and there is no where to drag to, so exit
3341 // if there are less than two panes, split can't happen, so leave
3342 if (m_tabs
.GetPageCount() < 2)
3345 // if tab moving is not allowed, leave
3346 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3352 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3358 wxRect hint_rect
= dest_tabs
->GetRect();
3359 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3360 m_mgr
.ShowHint(hint_rect
);
3364 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3370 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3372 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3377 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3378 wxCHECK_RET( src_tabs
, _T("no source object?") );
3380 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3382 // get the mouse position, which will be used to determine the drop point
3383 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3384 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3388 // check for an external move
3389 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3391 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3395 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3397 tab_ctrl
= tab_ctrl
->GetParent();
3402 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3406 // find out from the destination control
3407 // if it's ok to drop this tab here
3408 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3409 e
.SetSelection(evt
.GetSelection());
3410 e
.SetOldSelection(evt
.GetSelection());
3411 e
.SetEventObject(this);
3412 e
.SetDragSource(this);
3413 e
.Veto(); // dropping must be explicitly approved by control owner
3415 nb
->GetEventHandler()->ProcessEvent(e
);
3419 // no answer or negative answer
3425 int src_idx
= evt
.GetSelection();
3426 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3428 // get main index of the page
3429 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3430 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3433 // make a copy of the page info
3434 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3436 // remove the page from the source notebook
3437 RemovePage(main_idx
);
3439 // reparent the page
3440 src_page
->Reparent(nb
);
3443 // found out the insert idx
3444 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3445 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3447 wxWindow
* target
= NULL
;
3448 int insert_idx
= -1;
3449 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3452 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3456 // add the page to the new notebook
3457 if (insert_idx
== -1)
3458 insert_idx
= dest_tabs
->GetPageCount();
3459 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3460 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3463 dest_tabs
->DoShowHide();
3464 dest_tabs
->Refresh();
3466 // set the selection in the destination tab control
3467 nb
->SetSelectionToPage(page_info
);
3477 // only perform a tab split if it's allowed
3478 wxAuiTabCtrl
* dest_tabs
= NULL
;
3480 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3482 // If the pointer is in an existing tab frame, do a tab insert
3483 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3484 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3485 int insert_idx
= -1;
3488 dest_tabs
= tab_frame
->m_tabs
;
3490 if (dest_tabs
== src_tabs
)
3494 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3495 wxWindow
* target
= NULL
;
3496 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3499 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3505 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3510 // there is no suitable drop location here, exit out
3514 // If there is no tabframe at all, create one
3515 wxTabFrame
* new_tabs
= new wxTabFrame
;
3516 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3517 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3518 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3523 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3524 new_tabs
->m_tabs
->SetFlags(m_flags
);
3526 m_mgr
.AddPane(new_tabs
,
3527 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3530 dest_tabs
= new_tabs
->m_tabs
;
3535 // remove the page from the source tabs
3536 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3537 page_info
.active
= false;
3538 src_tabs
->RemovePage(page_info
.window
);
3539 if (src_tabs
->GetPageCount() > 0)
3541 src_tabs
->SetActivePage((size_t)0);
3542 src_tabs
->DoShowHide();
3543 src_tabs
->Refresh();
3548 // add the page to the destination tabs
3549 if (insert_idx
== -1)
3550 insert_idx
= dest_tabs
->GetPageCount();
3551 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3553 if (src_tabs
->GetPageCount() == 0)
3555 RemoveEmptyTabFrames();
3559 dest_tabs
->DoShowHide();
3560 dest_tabs
->Refresh();
3562 // force the set selection function reset the selection
3565 // set the active page to the one we just split off
3566 SetSelectionToPage(page_info
);
3568 UpdateHintWindowSize();
3574 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3576 // if we've just removed the last tab from the source
3577 // tab set, the remove the tab control completely
3578 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3579 size_t i
, pane_count
= all_panes
.GetCount();
3580 for (i
= 0; i
< pane_count
; ++i
)
3582 if (all_panes
.Item(i
).name
== wxT("dummy"))
3585 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3586 if (tabframe
->m_tab_rect
.Contains(pt
))
3587 return tabframe
->m_tabs
;
3593 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3595 // if we've just removed the last tab from the source
3596 // tab set, the remove the tab control completely
3597 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3598 size_t i
, pane_count
= all_panes
.GetCount();
3599 for (i
= 0; i
< pane_count
; ++i
)
3601 if (all_panes
.Item(i
).name
== wxT("dummy"))
3604 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3605 if (tabframe
->m_tabs
== tab_ctrl
)
3614 void wxAuiNotebook::RemoveEmptyTabFrames()
3616 // if we've just removed the last tab from the source
3617 // tab set, the remove the tab control completely
3618 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3619 size_t i
, pane_count
= all_panes
.GetCount();
3620 for (i
= 0; i
< pane_count
; ++i
)
3622 if (all_panes
.Item(i
).name
== wxT("dummy"))
3625 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3626 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3628 m_mgr
.DetachPane(tab_frame
);
3630 // use pending delete because sometimes during
3631 // window closing, refreshs are pending
3632 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3633 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3635 tab_frame
->m_tabs
= NULL
;
3642 // check to see if there is still a center pane;
3643 // if there isn't, make a frame the center pane
3644 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3645 pane_count
= panes
.GetCount();
3646 wxWindow
* first_good
= NULL
;
3647 bool center_found
= false;
3648 for (i
= 0; i
< pane_count
; ++i
)
3650 if (panes
.Item(i
).name
== wxT("dummy"))
3652 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3653 center_found
= true;
3655 first_good
= panes
.Item(i
).window
;
3658 if (!center_found
&& first_good
)
3660 m_mgr
.GetPane(first_good
).Centre();
3666 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3668 // if we're dragging a tab, don't change the current selection.
3669 // This code prevents a bug that used to happen when the hint window
3670 // was hidden. In the bug, the focus would return to the notebook
3671 // child, which would then enter this handler and call
3672 // SetSelection, which is not desired turn tab dragging.
3674 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3675 size_t i
, pane_count
= all_panes
.GetCount();
3676 for (i
= 0; i
< pane_count
; ++i
)
3678 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3679 if (pane
.name
== wxT("dummy"))
3681 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3682 if (tabframe
->m_tabs
->IsDragging())
3687 // change the tab selection to the child
3688 // which was focused
3689 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3690 if (idx
!= -1 && idx
!= m_curpage
)
3697 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3699 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3700 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3702 int button_id
= evt
.GetInt();
3704 if (button_id
== wxAUI_BUTTON_CLOSE
)
3706 int selection
= evt
.GetSelection();
3708 if (selection
!= -1)
3710 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3712 // ask owner if it's ok to close the tab
3713 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3714 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3715 e
.SetOldSelection(evt
.GetSelection());
3716 e
.SetEventObject(this);
3717 GetEventHandler()->ProcessEvent(e
);
3722 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3728 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3729 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3731 DeletePage(main_idx
);
3738 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
3740 // patch event through to owner
3741 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3742 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3744 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
3745 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3746 e
.SetEventObject(this);
3747 GetEventHandler()->ProcessEvent(e
);
3750 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
3752 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
3753 // click should act like a tab close action. However, first
3754 // give the owner an opportunity to handle the middle up event
3755 // for custom action
3757 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3758 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3760 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
3761 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3762 e
.SetEventObject(this);
3763 if (GetEventHandler()->ProcessEvent(e
))
3768 // check if we are supposed to close on middle-up
3769 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
3772 // simulate the user pressing the close button on the tab
3773 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
3777 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
3779 // patch event through to owner
3780 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3781 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3783 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
3784 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3785 e
.SetEventObject(this);
3786 GetEventHandler()->ProcessEvent(e
);
3789 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
3791 // patch event through to owner
3792 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3793 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3795 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
3796 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3797 e
.SetEventObject(this);
3798 GetEventHandler()->ProcessEvent(e
);
3801 // Sets the normal font
3802 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
3804 m_normal_font
= font
;
3805 GetArtProvider()->SetNormalFont(font
);
3808 // Sets the selected tab font
3809 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
3811 m_selected_font
= font
;
3812 GetArtProvider()->SetSelectedFont(font
);
3815 // Sets the measuring font
3816 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
3818 GetArtProvider()->SetMeasuringFont(font
);
3821 // Sets the tab font
3822 bool wxAuiNotebook::SetFont(const wxFont
& font
)
3824 wxControl::SetFont(font
);
3826 wxFont
normalFont(font
);
3827 wxFont
selectedFont(normalFont
);
3828 selectedFont
.SetWeight(wxBOLD
);
3830 SetNormalFont(normalFont
);
3831 SetSelectedFont(selectedFont
);
3832 SetMeasuringFont(selectedFont
);
3837 // Gets the tab control height
3838 int wxAuiNotebook::GetTabCtrlHeight() const
3840 return m_tab_ctrl_height
;
3843 // Gets the height of the notebook for a given page height
3844 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
3846 UpdateTabCtrlHeight();
3848 int tabCtrlHeight
= GetTabCtrlHeight();
3849 int decorHeight
= 2;
3850 return tabCtrlHeight
+ pageHeight
+ decorHeight
;