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 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2071 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2072 evt
.SetOldSelection(evt
.GetSelection());
2073 evt
.SetEventObject(this);
2074 GetEventHandler()->ProcessEvent(evt
);
2078 if (m_pressed_button
)
2080 // make sure we're still clicking the button
2081 wxAuiTabContainerButton
* button
= NULL
;
2082 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2085 if (button
!= m_pressed_button
)
2087 m_pressed_button
= NULL
;
2094 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2096 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2097 evt
.SetInt(m_pressed_button
->id
);
2098 evt
.SetEventObject(this);
2099 GetEventHandler()->ProcessEvent(evt
);
2102 m_pressed_button
= NULL
;
2105 m_click_pt
= wxDefaultPosition
;
2106 m_is_dragging
= false;
2110 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2112 wxWindow
* wnd
= NULL
;
2113 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2116 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2117 e
.SetEventObject(this);
2118 e
.SetSelection(GetIdxFromWindow(wnd
));
2119 GetEventHandler()->ProcessEvent(e
);
2122 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2124 wxWindow
* wnd
= NULL
;
2125 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2128 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2129 e
.SetEventObject(this);
2130 e
.SetSelection(GetIdxFromWindow(wnd
));
2131 GetEventHandler()->ProcessEvent(e
);
2134 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2136 wxWindow
* wnd
= NULL
;
2137 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2140 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2141 e
.SetEventObject(this);
2142 e
.SetSelection(GetIdxFromWindow(wnd
));
2143 GetEventHandler()->ProcessEvent(e
);
2146 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2148 wxWindow
* wnd
= NULL
;
2149 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2152 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2153 e
.SetEventObject(this);
2154 e
.SetSelection(GetIdxFromWindow(wnd
));
2155 GetEventHandler()->ProcessEvent(e
);
2158 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2160 wxPoint pos
= evt
.GetPosition();
2162 // check if the mouse is hovering above a button
2163 wxAuiTabContainerButton
* button
;
2164 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2166 if (m_hover_button
&& button
!= m_hover_button
)
2168 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2169 m_hover_button
= NULL
;
2174 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2176 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2179 m_hover_button
= button
;
2187 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2188 m_hover_button
= NULL
;
2195 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2200 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2201 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2202 evt
.SetOldSelection(evt
.GetSelection());
2203 evt
.SetEventObject(this);
2204 GetEventHandler()->ProcessEvent(evt
);
2209 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2210 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2212 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2213 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2215 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2216 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2217 evt
.SetOldSelection(evt
.GetSelection());
2218 evt
.SetEventObject(this);
2219 GetEventHandler()->ProcessEvent(evt
);
2221 m_is_dragging
= true;
2225 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2229 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2230 m_hover_button
= NULL
;
2236 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2238 int button
= event
.GetInt();
2240 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2242 if (button
== wxAUI_BUTTON_LEFT
)
2244 if (GetTabOffset() > 0)
2246 SetTabOffset(GetTabOffset()-1);
2253 SetTabOffset(GetTabOffset()+1);
2258 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2260 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2264 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2265 e
.SetSelection(idx
);
2266 e
.SetOldSelection(GetActivePage());
2267 e
.SetEventObject(this);
2268 GetEventHandler()->ProcessEvent(e
);
2277 // wxTabFrame is an interesting case. It's important that all child pages
2278 // of the multi-notebook control are all actually children of that control
2279 // (and not grandchildren). wxTabFrame facilitates this. There is one
2280 // instance of wxTabFrame for each tab control inside the multi-notebook.
2281 // It's important to know that wxTabFrame is not a real window, but it merely
2282 // used to capture the dimensions/positioning of the internal tab control and
2283 // it's managed page windows
2285 class wxTabFrame
: public wxWindow
2292 m_rect
= wxRect(0,0,200,200);
2293 m_tab_ctrl_height
= 20;
2301 void SetTabCtrlHeight(int h
)
2303 m_tab_ctrl_height
= h
;
2306 void DoSetSize(int x
, int y
,
2307 int width
, int height
,
2308 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2310 m_rect
= wxRect(x
, y
, width
, height
);
2314 void DoGetClientSize(int* x
, int* y
) const
2320 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2327 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2328 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2329 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2333 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2334 size_t i
, page_count
= pages
.GetCount();
2336 for (i
= 0; i
< page_count
; ++i
)
2338 wxAuiNotebookPage
& page
= pages
.Item(i
);
2339 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2340 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2342 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2344 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2345 wnd
->ApplyMDIChildFrameRect();
2350 void DoGetSize(int* x
, int* y
) const
2353 *x
= m_rect
.GetWidth();
2355 *y
= m_rect
.GetHeight();
2367 wxAuiTabCtrl
* m_tabs
;
2368 int m_tab_ctrl_height
;
2372 const int wxAuiBaseTabCtrlId
= 5380;
2375 // -- wxAuiNotebook class implementation --
2377 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2378 EVT_SIZE(wxAuiNotebook::OnSize
)
2379 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2380 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2381 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2382 wxAuiNotebook::OnTabClicked
)
2383 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2384 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2385 wxAuiNotebook::OnTabBeginDrag
)
2386 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2387 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2388 wxAuiNotebook::OnTabEndDrag
)
2389 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2390 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2391 wxAuiNotebook::OnTabDragMotion
)
2392 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2393 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2394 wxAuiNotebook::OnTabButton
)
2395 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2396 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2397 wxAuiNotebook::OnTabMiddleDown
)
2398 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2399 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2400 wxAuiNotebook::OnTabMiddleUp
)
2401 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2402 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2403 wxAuiNotebook::OnTabRightDown
)
2404 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2405 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2406 wxAuiNotebook::OnTabRightUp
)
2409 wxAuiNotebook::wxAuiNotebook()
2412 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2414 m_tab_ctrl_height
= 20;
2415 m_requested_bmp_size
= wxDefaultSize
;
2416 m_requested_tabctrl_height
= -1;
2419 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2423 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2426 m_requested_bmp_size
= wxDefaultSize
;
2427 m_requested_tabctrl_height
= -1;
2428 InitNotebook(style
);
2431 bool wxAuiNotebook::Create(wxWindow
* parent
,
2437 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2440 InitNotebook(style
);
2445 // InitNotebook() contains common initialization
2446 // code called by all constructors
2447 void wxAuiNotebook::InitNotebook(long style
)
2450 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2452 m_flags
= (unsigned int)style
;
2453 m_tab_ctrl_height
= 20;
2455 m_normal_font
= *wxNORMAL_FONT
;
2456 m_selected_font
= *wxNORMAL_FONT
;
2457 m_selected_font
.SetWeight(wxBOLD
);
2459 SetArtProvider(new wxAuiDefaultTabArt
);
2461 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2462 m_dummy_wnd
->SetSize(200, 200);
2463 m_dummy_wnd
->Show(false);
2465 m_mgr
.SetManagedWindow(this);
2466 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2467 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2469 m_mgr
.AddPane(m_dummy_wnd
,
2470 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2475 wxAuiNotebook::~wxAuiNotebook()
2480 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2482 m_tabs
.SetArtProvider(art
);
2484 UpdateTabCtrlHeight();
2487 // SetTabCtrlHeight() is the highest-level override of the
2488 // tab height. A call to this function effectively enforces a
2489 // specified tab ctrl height, overriding all other considerations,
2490 // such as text or bitmap height. It overrides any call to
2491 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2492 // any previous call and returns to the default behavior
2494 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2496 m_requested_tabctrl_height
= height
;
2498 // if window is already initialized, recalculate the tab height
2501 UpdateTabCtrlHeight();
2506 // SetUniformBitmapSize() ensures that all tabs will have
2507 // the same height, even if some tabs don't have bitmaps
2508 // Passing wxDefaultSize to this function will instruct
2509 // the control to use dynamic tab height-- so when a tab
2510 // with a large bitmap is added, the tab ctrl's height will
2511 // automatically increase to accommodate the bitmap
2513 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2515 m_requested_bmp_size
= size
;
2517 // if window is already initialized, recalculate the tab height
2520 UpdateTabCtrlHeight();
2524 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2525 // to be used interally
2526 void wxAuiNotebook::UpdateTabCtrlHeight()
2528 // get the tab ctrl height we will use
2529 int height
= CalculateTabCtrlHeight();
2531 // if the tab control height needs to change, update
2532 // all of our tab controls with the new height
2533 if (m_tab_ctrl_height
!= height
)
2535 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2537 m_tab_ctrl_height
= height
;
2539 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2540 size_t i
, pane_count
= all_panes
.GetCount();
2541 for (i
= 0; i
< pane_count
; ++i
)
2543 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2544 if (pane
.name
== wxT("dummy"))
2546 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2547 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2548 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2549 tabctrl
->SetArtProvider(art
->Clone());
2550 tab_frame
->DoSizing();
2555 void wxAuiNotebook::UpdateHintWindowSize()
2557 wxSize size
= CalculateNewSplitSize();
2559 // the placeholder hint window should be set to this size
2560 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2564 info
.BestSize(size
);
2565 m_dummy_wnd
->SetSize(size
);
2570 // calculates the size of the new split
2571 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2573 // count number of tab controls
2574 int tab_ctrl_count
= 0;
2575 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2576 size_t i
, pane_count
= all_panes
.GetCount();
2577 for (i
= 0; i
< pane_count
; ++i
)
2579 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2580 if (pane
.name
== wxT("dummy"))
2585 wxSize new_split_size
;
2587 // if there is only one tab control, the first split
2588 // should happen around the middle
2589 if (tab_ctrl_count
< 2)
2591 new_split_size
= GetClientSize();
2592 new_split_size
.x
/= 2;
2593 new_split_size
.y
/= 2;
2597 // this is in place of a more complicated calculation
2598 // that needs to be implemented
2599 new_split_size
= wxSize(180,180);
2602 return new_split_size
;
2605 int wxAuiNotebook::CalculateTabCtrlHeight()
2607 // if a fixed tab ctrl height is specified,
2608 // just return that instead of calculating a
2610 if (m_requested_tabctrl_height
!= -1)
2611 return m_requested_tabctrl_height
;
2613 // find out new best tab height
2614 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2616 return art
->GetBestTabCtrlSize(this,
2618 m_requested_bmp_size
);
2622 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2624 return m_tabs
.GetArtProvider();
2627 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2629 wxControl::SetWindowStyleFlag(style
);
2631 m_flags
= (unsigned int)style
;
2633 // if the control is already initialized
2634 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2636 // let all of the tab children know about the new style
2638 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2639 size_t i
, pane_count
= all_panes
.GetCount();
2640 for (i
= 0; i
< pane_count
; ++i
)
2642 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2643 if (pane
.name
== wxT("dummy"))
2645 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2646 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2647 tabctrl
->SetFlags(m_flags
);
2648 tabframe
->DoSizing();
2656 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2657 const wxString
& caption
,
2659 const wxBitmap
& bitmap
)
2661 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2664 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2666 const wxString
& caption
,
2668 const wxBitmap
& bitmap
)
2670 wxAuiNotebookPage info
;
2672 info
.caption
= caption
;
2673 info
.bitmap
= bitmap
;
2674 info
.active
= false;
2676 // if there are currently no tabs, the first added
2677 // tab must be active
2678 if (m_tabs
.GetPageCount() == 0)
2681 m_tabs
.InsertPage(page
, info
, page_idx
);
2683 // if that was the first page added, even if
2684 // select is false, it must become the "current page"
2685 // (though no select events will be fired)
2686 if (!select
&& m_tabs
.GetPageCount() == 1)
2688 //m_curpage = GetPageIndex(page);
2690 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2691 if (page_idx
>= active_tabctrl
->GetPageCount())
2692 active_tabctrl
->AddPage(page
, info
);
2694 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2696 UpdateTabCtrlHeight();
2698 active_tabctrl
->DoShowHide();
2702 SetSelectionToWindow(page
);
2709 // DeletePage() removes a tab from the multi-notebook,
2710 // and destroys the window as well
2711 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2713 if (page_idx
>= m_tabs
.GetPageCount())
2716 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2718 // hide the window in advance, as this will
2720 ShowWnd(wnd
, false);
2722 if (!RemovePage(page_idx
))
2725 // actually destroy the window now
2726 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2728 // delete the child frame with pending delete, as is
2729 // customary with frame windows
2730 if (!wxPendingDelete
.Member(wnd
))
2731 wxPendingDelete
.Append(wnd
);
2743 // RemovePage() removes a tab from the multi-notebook,
2744 // but does not destroy the window
2745 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2747 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2748 wxWindow
* new_active
= NULL
;
2750 // make sure we found the page
2754 // find out which onscreen tab ctrl owns this tab
2757 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2760 bool is_curpage
= (m_curpage
== (int)page_idx
);
2761 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
2764 // remove the tab from main catalog
2765 if (!m_tabs
.RemovePage(wnd
))
2768 // remove the tab from the onscreen tab ctrl
2769 ctrl
->RemovePage(wnd
);
2771 if (is_active_in_split
)
2773 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
2775 if (ctrl_idx
>= ctrl_new_page_count
)
2776 ctrl_idx
= ctrl_new_page_count
-1;
2778 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
2780 // set new page as active in the tab split
2781 ctrl
->SetActivePage(ctrl_idx
);
2783 // if the page deleted was the current page for the
2784 // entire tab control, then record the window
2785 // pointer of the new active page for activation
2788 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
2796 // we haven't yet found a new page to active,
2797 // so select the next page from the main tab
2800 if (page_idx
< m_tabs
.GetPageCount())
2802 new_active
= m_tabs
.GetPage(page_idx
).window
;
2805 if (!new_active
&& m_tabs
.GetPageCount() > 0)
2807 new_active
= m_tabs
.GetPage(0).window
;
2812 RemoveEmptyTabFrames();
2814 // set new active pane
2818 SetSelectionToWindow(new_active
);
2824 // GetPageIndex() returns the index of the page, or -1 if the
2825 // page could not be located in the notebook
2826 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2828 return m_tabs
.GetIdxFromWindow(page_wnd
);
2833 // SetPageText() changes the tab caption of the specified page
2834 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2836 if (page_idx
>= m_tabs
.GetPageCount())
2839 // update our own tab catalog
2840 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2841 page_info
.caption
= text
;
2843 // update what's on screen
2846 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2848 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2849 info
.caption
= text
;
2857 // returns the page caption
2858 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2860 if (page_idx
>= m_tabs
.GetPageCount())
2861 return wxEmptyString
;
2863 // update our own tab catalog
2864 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2865 return page_info
.caption
;
2868 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2870 if (page_idx
>= m_tabs
.GetPageCount())
2873 // update our own tab catalog
2874 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2875 page_info
.bitmap
= bitmap
;
2877 // tab height might have changed
2878 UpdateTabCtrlHeight();
2880 // update what's on screen
2883 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2885 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2886 info
.bitmap
= bitmap
;
2894 // returns the page bitmap
2895 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2897 if (page_idx
>= m_tabs
.GetPageCount())
2900 // update our own tab catalog
2901 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2902 return page_info
.bitmap
;
2905 // GetSelection() returns the index of the currently active page
2906 int wxAuiNotebook::GetSelection() const
2911 // SetSelection() sets the currently active page
2912 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2914 // don't change the page unless necessary
2915 if ((int)new_page
== m_curpage
)
2918 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2922 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2923 evt
.SetSelection(new_page
);
2924 evt
.SetOldSelection(m_curpage
);
2925 evt
.SetEventObject(this);
2926 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2928 int old_curpage
= m_curpage
;
2929 m_curpage
= new_page
;
2931 // program allows the page change
2932 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2933 (void)GetEventHandler()->ProcessEvent(evt
);
2938 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2940 m_tabs
.SetActivePage(wnd
);
2942 ctrl
->SetActivePage(ctrl_idx
);
2949 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2950 size_t i
, pane_count
= all_panes
.GetCount();
2951 for (i
= 0; i
< pane_count
; ++i
)
2953 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2954 if (pane
.name
== wxT("dummy"))
2956 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2957 if (tabctrl
!= ctrl
)
2958 tabctrl
->SetSelectedFont(m_normal_font
);
2960 tabctrl
->SetSelectedFont(m_selected_font
);
2973 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2975 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2976 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2981 // GetPageCount() returns the total number of
2982 // pages managed by the multi-notebook
2983 size_t wxAuiNotebook::GetPageCount() const
2985 return m_tabs
.GetPageCount();
2988 // GetPage() returns the wxWindow pointer of the
2990 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2992 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2994 return m_tabs
.GetWindowFromIdx(page_idx
);
2997 // DoSizing() performs all sizing operations in each tab control
2998 void wxAuiNotebook::DoSizing()
3000 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3001 size_t i
, pane_count
= all_panes
.GetCount();
3002 for (i
= 0; i
< pane_count
; ++i
)
3004 if (all_panes
.Item(i
).name
== wxT("dummy"))
3007 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3008 tabframe
->DoSizing();
3012 // GetActiveTabCtrl() returns the active tab control. It is
3013 // called to determine which control gets new windows being added
3014 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3016 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3021 // find the tab ctrl with the current page
3022 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3029 // no current page, just find the first tab ctrl
3030 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3031 size_t i
, pane_count
= all_panes
.GetCount();
3032 for (i
= 0; i
< pane_count
; ++i
)
3034 if (all_panes
.Item(i
).name
== wxT("dummy"))
3037 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3038 return tabframe
->m_tabs
;
3041 // If there is no tabframe at all, create one
3042 wxTabFrame
* tabframe
= new wxTabFrame
;
3043 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3044 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3049 tabframe
->m_tabs
->SetFlags(m_flags
);
3050 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3051 m_mgr
.AddPane(tabframe
,
3052 wxAuiPaneInfo().Center().CaptionVisible(false));
3056 return tabframe
->m_tabs
;
3059 // FindTab() finds the tab control that currently contains the window as well
3060 // as the index of the window in the tab control. It returns true if the
3061 // window was found, otherwise false.
3062 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3064 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3065 size_t i
, pane_count
= all_panes
.GetCount();
3066 for (i
= 0; i
< pane_count
; ++i
)
3068 if (all_panes
.Item(i
).name
== wxT("dummy"))
3071 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3073 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3076 *ctrl
= tabframe
->m_tabs
;
3085 void wxAuiNotebook::Split(size_t page
, int direction
)
3087 wxSize cli_size
= GetClientSize();
3089 // get the page's window pointer
3090 wxWindow
* wnd
= GetPage(page
);
3094 // notebooks with 1 or less pages can't be split
3095 if (GetPageCount() < 2)
3098 // find out which tab control the page currently belongs to
3099 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3102 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3104 if (!src_tabs
|| src_idx
== -1)
3107 // choose a split size
3109 if (GetPageCount() > 2)
3111 split_size
= CalculateNewSplitSize();
3115 // because there are two panes, always split them
3117 split_size
= GetClientSize();
3123 // create a new tab frame
3124 wxTabFrame
* new_tabs
= new wxTabFrame
;
3125 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3126 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3127 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3132 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3133 new_tabs
->m_tabs
->SetFlags(m_flags
);
3134 dest_tabs
= new_tabs
->m_tabs
;
3136 // create a pane info structure with the information
3137 // about where the pane should be added
3138 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3141 if (direction
== wxLEFT
)
3144 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3146 else if (direction
== wxRIGHT
)
3149 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3151 else if (direction
== wxTOP
)
3154 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3156 else if (direction
== wxBOTTOM
)
3159 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3162 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3165 // remove the page from the source tabs
3166 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3167 page_info
.active
= false;
3168 src_tabs
->RemovePage(page_info
.window
);
3169 if (src_tabs
->GetPageCount() > 0)
3171 src_tabs
->SetActivePage((size_t)0);
3172 src_tabs
->DoShowHide();
3173 src_tabs
->Refresh();
3177 // add the page to the destination tabs
3178 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3180 if (src_tabs
->GetPageCount() == 0)
3182 RemoveEmptyTabFrames();
3186 dest_tabs
->DoShowHide();
3187 dest_tabs
->Refresh();
3189 // force the set selection function reset the selection
3192 // set the active page to the one we just split off
3193 SetSelectionToPage(page_info
);
3195 UpdateHintWindowSize();
3199 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3201 UpdateHintWindowSize();
3206 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3208 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3210 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3211 wxASSERT(ctrl
!= NULL
);
3213 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3214 wxASSERT(wnd
!= NULL
);
3216 SetSelectionToWindow(wnd
);
3219 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3224 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3226 wxPoint screen_pt
= ::wxGetMousePosition();
3227 wxPoint client_pt
= ScreenToClient(screen_pt
);
3230 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3231 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3233 if (dest_tabs
== src_tabs
)
3237 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3240 // always hide the hint for inner-tabctrl drag
3243 // if tab moving is not allowed, leave
3244 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3249 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3250 wxWindow
* dest_location_tab
;
3252 // this is an inner-tab drag/reposition
3253 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3255 int src_idx
= evt
.GetSelection();
3256 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3258 // prevent jumpy drag
3259 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3260 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3261 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3263 m_last_drag_x
= pt
.x
;
3268 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3269 dest_tabs
->MovePage(src_tab
, dest_idx
);
3270 dest_tabs
->SetActivePage((size_t)dest_idx
);
3271 dest_tabs
->DoShowHide();
3272 dest_tabs
->Refresh();
3273 m_last_drag_x
= pt
.x
;
3281 // if external drag is allowed, check if the tab is being dragged
3282 // over a different wxAuiNotebook control
3283 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3285 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3287 // if we aren't over any window, stop here
3291 // make sure we are not over the hint window
3292 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3296 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3298 tab_ctrl
= tab_ctrl
->GetParent();
3303 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3307 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3308 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3309 m_mgr
.ShowHint(hint_rect
);
3318 // we are either over a hint window, or not over a tab
3319 // window, and there is no where to drag to, so exit
3326 // if there are less than two panes, split can't happen, so leave
3327 if (m_tabs
.GetPageCount() < 2)
3330 // if tab moving is not allowed, leave
3331 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3337 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3343 wxRect hint_rect
= dest_tabs
->GetRect();
3344 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3345 m_mgr
.ShowHint(hint_rect
);
3349 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3355 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3357 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3362 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3363 wxCHECK_RET( src_tabs
, _T("no source object?") );
3365 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3367 // get the mouse position, which will be used to determine the drop point
3368 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3369 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3373 // check for an external move
3374 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3376 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3380 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3382 tab_ctrl
= tab_ctrl
->GetParent();
3387 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3391 // find out from the destination control
3392 // if it's ok to drop this tab here
3393 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3394 e
.SetSelection(evt
.GetSelection());
3395 e
.SetOldSelection(evt
.GetSelection());
3396 e
.SetEventObject(this);
3397 e
.SetDragSource(this);
3398 e
.Veto(); // dropping must be explicitly approved by control owner
3400 nb
->GetEventHandler()->ProcessEvent(e
);
3404 // no answer or negative answer
3410 int src_idx
= evt
.GetSelection();
3411 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3413 // get main index of the page
3414 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3415 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3418 // make a copy of the page info
3419 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3421 // remove the page from the source notebook
3422 RemovePage(main_idx
);
3424 // reparent the page
3425 src_page
->Reparent(nb
);
3428 // found out the insert idx
3429 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3430 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3432 wxWindow
* target
= NULL
;
3433 int insert_idx
= -1;
3434 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3437 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3441 // add the page to the new notebook
3442 if (insert_idx
== -1)
3443 insert_idx
= dest_tabs
->GetPageCount();
3444 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3445 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3448 dest_tabs
->DoShowHide();
3449 dest_tabs
->Refresh();
3451 // set the selection in the destination tab control
3452 nb
->SetSelectionToPage(page_info
);
3462 // only perform a tab split if it's allowed
3463 wxAuiTabCtrl
* dest_tabs
= NULL
;
3465 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3467 // If the pointer is in an existing tab frame, do a tab insert
3468 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3469 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3470 int insert_idx
= -1;
3473 dest_tabs
= tab_frame
->m_tabs
;
3475 if (dest_tabs
== src_tabs
)
3479 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3480 wxWindow
* target
= NULL
;
3481 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3484 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3490 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3495 // there is no suitable drop location here, exit out
3499 // If there is no tabframe at all, create one
3500 wxTabFrame
* new_tabs
= new wxTabFrame
;
3501 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3502 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3503 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3508 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3509 new_tabs
->m_tabs
->SetFlags(m_flags
);
3511 m_mgr
.AddPane(new_tabs
,
3512 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3515 dest_tabs
= new_tabs
->m_tabs
;
3520 // remove the page from the source tabs
3521 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3522 page_info
.active
= false;
3523 src_tabs
->RemovePage(page_info
.window
);
3524 if (src_tabs
->GetPageCount() > 0)
3526 src_tabs
->SetActivePage((size_t)0);
3527 src_tabs
->DoShowHide();
3528 src_tabs
->Refresh();
3533 // add the page to the destination tabs
3534 if (insert_idx
== -1)
3535 insert_idx
= dest_tabs
->GetPageCount();
3536 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3538 if (src_tabs
->GetPageCount() == 0)
3540 RemoveEmptyTabFrames();
3544 dest_tabs
->DoShowHide();
3545 dest_tabs
->Refresh();
3547 // force the set selection function reset the selection
3550 // set the active page to the one we just split off
3551 SetSelectionToPage(page_info
);
3553 UpdateHintWindowSize();
3559 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3561 // if we've just removed the last tab from the source
3562 // tab set, the remove the tab control completely
3563 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3564 size_t i
, pane_count
= all_panes
.GetCount();
3565 for (i
= 0; i
< pane_count
; ++i
)
3567 if (all_panes
.Item(i
).name
== wxT("dummy"))
3570 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3571 if (tabframe
->m_tab_rect
.Contains(pt
))
3572 return tabframe
->m_tabs
;
3578 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3580 // if we've just removed the last tab from the source
3581 // tab set, the remove the tab control completely
3582 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3583 size_t i
, pane_count
= all_panes
.GetCount();
3584 for (i
= 0; i
< pane_count
; ++i
)
3586 if (all_panes
.Item(i
).name
== wxT("dummy"))
3589 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3590 if (tabframe
->m_tabs
== tab_ctrl
)
3599 void wxAuiNotebook::RemoveEmptyTabFrames()
3601 // if we've just removed the last tab from the source
3602 // tab set, the remove the tab control completely
3603 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3604 size_t i
, pane_count
= all_panes
.GetCount();
3605 for (i
= 0; i
< pane_count
; ++i
)
3607 if (all_panes
.Item(i
).name
== wxT("dummy"))
3610 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3611 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3613 m_mgr
.DetachPane(tab_frame
);
3615 // use pending delete because sometimes during
3616 // window closing, refreshs are pending
3617 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3618 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3620 tab_frame
->m_tabs
= NULL
;
3627 // check to see if there is still a center pane;
3628 // if there isn't, make a frame the center pane
3629 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3630 pane_count
= panes
.GetCount();
3631 wxWindow
* first_good
= NULL
;
3632 bool center_found
= false;
3633 for (i
= 0; i
< pane_count
; ++i
)
3635 if (panes
.Item(i
).name
== wxT("dummy"))
3637 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3638 center_found
= true;
3640 first_good
= panes
.Item(i
).window
;
3643 if (!center_found
&& first_good
)
3645 m_mgr
.GetPane(first_good
).Centre();
3651 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3653 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3654 if (idx
!= -1 && idx
!= m_curpage
)
3661 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3663 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3664 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3666 int button_id
= evt
.GetInt();
3668 if (button_id
== wxAUI_BUTTON_CLOSE
)
3670 int selection
= tabs
->GetActivePage();
3672 if (selection
!= -1)
3674 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3677 // ask owner if it's ok to close the tab
3678 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3679 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3680 e
.SetOldSelection(evt
.GetSelection());
3681 e
.SetEventObject(this);
3682 GetEventHandler()->ProcessEvent(e
);
3687 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3693 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3694 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3696 DeletePage(main_idx
);
3703 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
3705 // patch event through to owner
3706 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3707 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3709 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
3710 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3711 e
.SetEventObject(this);
3712 GetEventHandler()->ProcessEvent(e
);
3715 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
3717 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
3718 // click should act like a tab close action. However, first
3719 // give the owner an opportunity to handle the middle up event
3720 // for custom action
3722 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3723 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3725 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
3726 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3727 e
.SetEventObject(this);
3728 if (GetEventHandler()->ProcessEvent(e
))
3733 // check if we are supposed to close on middle-up
3734 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
3737 // simulate the user pressing the close button on the tab
3738 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
3742 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
3744 // patch event through to owner
3745 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3746 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3748 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
3749 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3750 e
.SetEventObject(this);
3751 GetEventHandler()->ProcessEvent(e
);
3754 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
3756 // patch event through to owner
3757 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3758 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3760 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
3761 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3762 e
.SetEventObject(this);
3763 GetEventHandler()->ProcessEvent(e
);
3766 // Sets the normal font
3767 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
3769 m_normal_font
= font
;
3770 GetArtProvider()->SetNormalFont(font
);
3773 // Sets the selected tab font
3774 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
3776 m_selected_font
= font
;
3777 GetArtProvider()->SetSelectedFont(font
);
3780 // Sets the measuring font
3781 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
3783 GetArtProvider()->SetMeasuringFont(font
);
3786 // Sets the tab font
3787 bool wxAuiNotebook::SetFont(const wxFont
& font
)
3789 wxControl::SetFont(font
);
3791 wxFont
normalFont(font
);
3792 wxFont
selectedFont(normalFont
);
3793 selectedFont
.SetWeight(wxBOLD
);
3795 SetNormalFont(normalFont
);
3796 SetSelectedFont(selectedFont
);
3797 SetMeasuringFont(selectedFont
);
3802 // Gets the tab control height
3803 int wxAuiNotebook::GetTabCtrlHeight() const
3805 return m_tab_ctrl_height
;
3808 // Gets the height of the notebook for a given page height
3809 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
3811 UpdateTabCtrlHeight();
3813 int tabCtrlHeight
= GetTabCtrlHeight();
3814 int decorHeight
= 2;
3815 return tabCtrlHeight
+ pageHeight
+ decorHeight
;