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
)
52 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
53 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
54 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
60 // these functions live in dockart.cpp -- they'll eventually
61 // be moved to a new utility cpp file
63 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
65 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
66 const wxColour
& color
);
68 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
70 static void DrawButtons(wxDC
& dc
,
73 const wxColour
& bkcolour
,
78 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
84 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
85 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
87 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
88 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
90 // draw the background behind the button
91 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
94 // draw the button itself
95 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
98 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
100 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
109 // -- GUI helper classes and functions --
111 class wxAuiCommandCapture
: public wxEvtHandler
115 wxAuiCommandCapture() { m_last_id
= 0; }
116 int GetCommandId() const { return m_last_id
; }
118 bool ProcessEvent(wxEvent
& evt
)
120 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
122 m_last_id
= evt
.GetId();
126 if (GetNextHandler())
127 return GetNextHandler()->ProcessEvent(evt
);
139 #if defined( __WXMAC__ )
140 static unsigned char close_bits
[]={
141 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
142 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
143 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
144 #elif defined( __WXGTK__)
145 static unsigned char close_bits
[]={
146 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
147 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
148 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
150 static unsigned char close_bits
[]={
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
152 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
156 static unsigned char left_bits
[] = {
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
158 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
161 static unsigned char right_bits
[] = {
162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
163 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
166 static unsigned char list_bits
[] = {
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
168 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
176 // -- wxAuiDefaultTabArt class implementation --
178 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
180 m_normal_font
= *wxNORMAL_FONT
;
181 m_selected_font
= *wxNORMAL_FONT
;
182 m_selected_font
.SetWeight(wxBOLD
);
183 m_measuring_font
= m_selected_font
;
185 m_fixed_tab_width
= 100;
186 m_tab_ctrl_height
= 0;
189 wxBrush toolbarbrush
;
190 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
191 wxColor base_colour
= toolbarbrush
.GetColour();
193 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
196 // the base_colour is too pale to use as our base colour,
197 // so darken it a bit --
198 if ((255-base_colour
.Red()) +
199 (255-base_colour
.Green()) +
200 (255-base_colour
.Blue()) < 60)
202 base_colour
= wxAuiStepColour(base_colour
, 92);
205 m_base_colour
= base_colour
;
206 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
208 m_border_pen
= wxPen(border_colour
);
209 m_base_colour_pen
= wxPen(m_base_colour
);
210 m_base_colour_brush
= wxBrush(m_base_colour
);
212 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
213 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
215 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
216 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
218 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
219 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
221 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
222 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
227 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
231 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
233 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
234 art
->SetNormalFont(m_normal_font
);
235 art
->SetSelectedFont(m_selected_font
);
236 art
->SetMeasuringFont(m_measuring_font
);
241 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
246 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
249 m_fixed_tab_width
= 100;
251 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
253 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
254 tot_width
-= m_active_close_bmp
.GetWidth();
255 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
256 tot_width
-= m_active_windowlist_bmp
.GetWidth();
260 m_fixed_tab_width
= tot_width
/(int)tab_count
;
264 if (m_fixed_tab_width
< 100)
265 m_fixed_tab_width
= 100;
267 if (m_fixed_tab_width
> tot_width
/2)
268 m_fixed_tab_width
= tot_width
/2;
270 if (m_fixed_tab_width
> 220)
271 m_fixed_tab_width
= 220;
273 m_tab_ctrl_height
= tab_ctrl_size
.y
;
277 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
278 wxWindow
* WXUNUSED(wnd
),
282 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
283 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
284 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
285 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
288 int y
= rect
.GetHeight();
289 int w
= rect
.GetWidth();
290 dc
.SetPen(m_border_pen
);
291 dc
.SetBrush(m_base_colour_brush
);
292 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
296 // DrawTab() draws an individual tab.
299 // in_rect - rectangle the tab should be confined to
300 // caption - tab's caption
301 // active - whether or not the tab is active
302 // out_rect - actual output rectangle
303 // x_extent - the advance x; where the next tab should start
305 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
307 const wxAuiNotebookPage
& page
,
308 const wxRect
& in_rect
,
309 int close_button_state
,
310 wxRect
* out_tab_rect
,
311 wxRect
* out_button_rect
,
314 wxCoord normal_textx
, normal_texty
;
315 wxCoord selected_textx
, selected_texty
;
316 wxCoord textx
, texty
;
318 // if the caption is empty, measure some temporary text
319 wxString caption
= page
.caption
;
323 dc
.SetFont(m_selected_font
);
324 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
326 dc
.SetFont(m_normal_font
);
327 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
329 // figure out the size of the tab
330 wxSize tab_size
= GetTabSize(dc
,
338 wxCoord tab_height
= m_tab_ctrl_height
- 3;
339 wxCoord tab_width
= tab_size
.x
;
340 wxCoord tab_x
= in_rect
.x
;
341 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
344 caption
= page
.caption
;
347 // select pen, brush and font for the tab to be drawn
351 dc
.SetFont(m_selected_font
);
352 textx
= selected_textx
;
353 texty
= selected_texty
;
357 dc
.SetFont(m_normal_font
);
358 textx
= normal_textx
;
359 texty
= normal_texty
;
363 // create points that will make the tab outline
365 int clip_width
= tab_width
;
366 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
367 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
370 wxPoint clip_points[6];
371 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
372 clip_points[1] = wxPoint(tab_x, tab_y+2);
373 clip_points[2] = wxPoint(tab_x+2, tab_y);
374 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
375 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
376 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
378 // FIXME: these ports don't provide wxRegion ctor from array of points
379 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
380 // set the clipping region for the tab --
381 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
382 dc.SetClippingRegion(clipping_region);
383 #endif // !wxDFB && !wxCocoa
385 // since the above code above doesn't play well with WXDFB or WXCOCOA,
386 // we'll just use a rectangle for the clipping region for now --
387 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
390 wxPoint border_points
[6];
391 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
392 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
393 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
394 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
395 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
396 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
399 int drawn_tab_yoff
= border_points
[1].y
;
400 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
407 // draw base background color
408 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
409 dc
.SetPen(m_base_colour_pen
);
410 dc
.SetBrush(m_base_colour_brush
);
411 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
413 // this white helps fill out the gradient at the top of the tab
414 dc
.SetPen(*wxWHITE_PEN
);
415 dc
.SetBrush(*wxWHITE_BRUSH
);
416 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
418 // these two points help the rounded corners appear more antialiased
419 dc
.SetPen(m_base_colour_pen
);
420 dc
.DrawPoint(r
.x
+2, r
.y
+1);
421 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
423 // set rectangle down a bit for gradient drawing
424 r
.SetHeight(r
.GetHeight()/2);
430 // draw gradient background
431 wxColor top_color
= *wxWHITE
;
432 wxColor bottom_color
= m_base_colour
;
433 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
439 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
441 // start the gradent up a bit and leave the inside border inset
442 // by a pixel for a 3D look. Only the top half of the inactive
443 // tab will have a slight gradient
450 // -- draw top gradient fill for glossy look
451 wxColor top_color
= m_base_colour
;
452 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
453 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
458 // -- draw bottom fill for glossy look
459 top_color
= m_base_colour
;
460 bottom_color
= m_base_colour
;
461 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
465 dc
.SetPen(m_border_pen
);
466 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
467 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
469 // there are two horizontal grey lines at the bottom of the tab control,
470 // this gets rid of the top one of those lines in the tab control
473 wxColor start_color
= m_base_colour
;
474 dc
.SetPen(m_base_colour_pen
);
475 dc
.DrawLine(border_points
[0].x
+1,
482 int text_offset
= tab_x
+ 8;
483 int close_button_width
= 0;
484 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
486 close_button_width
= m_active_close_bmp
.GetWidth();
490 if (page
.bitmap
.IsOk())
492 int bitmap_offset
= tab_x
+ 8;
495 dc
.DrawBitmap(page
.bitmap
,
497 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
500 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
501 text_offset
+= 3; // bitmap padding
505 text_offset
= tab_x
+ 8;
509 wxString draw_text
= wxAuiChopText(dc
,
511 tab_width
- (text_offset
-tab_x
) - close_button_width
);
514 dc
.DrawText(draw_text
,
516 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
521 // draw close button if necessary
522 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
524 wxBitmap bmp
= m_disabled_close_bmp
;
526 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
527 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
529 bmp
= m_active_close_bmp
;
532 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
533 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
536 IndentPressedBitmap(&rect
, close_button_state
);
537 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
539 *out_button_rect
= rect
;
542 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
544 dc
.DestroyClippingRegion();
547 int wxAuiDefaultTabArt::GetIndentSize()
552 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
553 wxWindow
* WXUNUSED(wnd
),
554 const wxString
& caption
,
555 const wxBitmap
& bitmap
,
556 bool WXUNUSED(active
),
557 int close_button_state
,
560 wxCoord measured_textx
, measured_texty
, tmp
;
562 dc
.SetFont(m_measuring_font
);
563 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
565 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
567 // add padding around the text
568 wxCoord tab_width
= measured_textx
;
569 wxCoord tab_height
= measured_texty
;
571 // if the close button is showing, add space for it
572 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
573 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
575 // if there's a bitmap, add space for it
578 tab_width
+= bitmap
.GetWidth();
579 tab_width
+= 3; // right side bitmap padding
580 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
587 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
589 tab_width
= m_fixed_tab_width
;
592 *x_extent
= tab_width
;
594 return wxSize(tab_width
, tab_height
);
598 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
599 wxWindow
* WXUNUSED(wnd
),
600 const wxRect
& in_rect
,
611 case wxAUI_BUTTON_CLOSE
:
612 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
613 bmp
= m_disabled_close_bmp
;
615 bmp
= m_active_close_bmp
;
617 case wxAUI_BUTTON_LEFT
:
618 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
619 bmp
= m_disabled_left_bmp
;
621 bmp
= m_active_left_bmp
;
623 case wxAUI_BUTTON_RIGHT
:
624 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
625 bmp
= m_disabled_right_bmp
;
627 bmp
= m_active_right_bmp
;
629 case wxAUI_BUTTON_WINDOWLIST
:
630 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
631 bmp
= m_disabled_windowlist_bmp
;
633 bmp
= m_active_windowlist_bmp
;
643 if (orientation
== wxLEFT
)
645 rect
.SetX(in_rect
.x
);
646 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
647 rect
.SetWidth(bmp
.GetWidth());
648 rect
.SetHeight(bmp
.GetHeight());
652 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
653 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
654 bmp
.GetWidth(), bmp
.GetHeight());
657 IndentPressedBitmap(&rect
, button_state
);
658 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
664 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
665 const wxAuiNotebookPageArray
& pages
,
670 size_t i
, count
= pages
.GetCount();
671 for (i
= 0; i
< count
; ++i
)
673 const wxAuiNotebookPage
& page
= pages
.Item(i
);
674 wxString caption
= page
.caption
;
676 // if there is no caption, make it a space. This will prevent
677 // an assert in the menu code.
678 if (caption
.IsEmpty())
681 menuPopup
.AppendCheckItem(1000+i
, caption
);
684 if (active_idx
!= -1)
686 menuPopup
.Check(1000+active_idx
, true);
689 // find out where to put the popup menu of window items
690 wxPoint pt
= ::wxGetMousePosition();
691 pt
= wnd
->ScreenToClient(pt
);
693 // find out the screen coordinate at the bottom of the tab ctrl
694 wxRect cli_rect
= wnd
->GetClientRect();
695 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
697 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
698 wnd
->PushEventHandler(cc
);
699 wnd
->PopupMenu(&menuPopup
, pt
);
700 int command
= cc
->GetCommandId();
701 wnd
->PopEventHandler(true);
709 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
710 const wxAuiNotebookPageArray
& pages
,
711 const wxSize
& required_bmp_size
)
714 dc
.SetFont(m_measuring_font
);
716 // sometimes a standard bitmap size needs to be enforced, especially
717 // if some tabs have bitmaps and others don't. This is important because
718 // it prevents the tab control from resizing when tabs are added.
719 wxBitmap measure_bmp
;
720 if (required_bmp_size
.IsFullySpecified())
722 measure_bmp
.Create(required_bmp_size
.x
,
723 required_bmp_size
.y
);
728 size_t i
, page_count
= pages
.GetCount();
729 for (i
= 0; i
< page_count
; ++i
)
731 wxAuiNotebookPage
& page
= pages
.Item(i
);
734 if (measure_bmp
.IsOk())
739 // we don't use the caption text because we don't
740 // want tab heights to be different in the case
741 // of a very short piece of text on one tab and a very
742 // tall piece of text on another tab
744 wxSize s
= GetTabSize(dc
,
749 wxAUI_BUTTON_STATE_HIDDEN
,
752 max_y
= wxMax(max_y
, s
.y
);
758 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
760 m_normal_font
= font
;
763 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
765 m_selected_font
= font
;
768 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
770 m_measuring_font
= font
;
774 // -- wxAuiSimpleTabArt class implementation --
776 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
778 m_normal_font
= *wxNORMAL_FONT
;
779 m_selected_font
= *wxNORMAL_FONT
;
780 m_selected_font
.SetWeight(wxBOLD
);
781 m_measuring_font
= m_selected_font
;
784 m_fixed_tab_width
= 100;
786 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
788 wxColour background_colour
= base_colour
;
789 wxColour normaltab_colour
= base_colour
;
790 wxColour selectedtab_colour
= *wxWHITE
;
792 m_bkbrush
= wxBrush(background_colour
);
793 m_normal_bkbrush
= wxBrush(normaltab_colour
);
794 m_normal_bkpen
= wxPen(normaltab_colour
);
795 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
796 m_selected_bkpen
= wxPen(selectedtab_colour
);
798 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
799 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
801 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
802 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
804 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
805 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
807 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
808 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
812 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
816 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
818 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
822 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
827 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
830 m_fixed_tab_width
= 100;
832 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
834 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
835 tot_width
-= m_active_close_bmp
.GetWidth();
836 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
837 tot_width
-= m_active_windowlist_bmp
.GetWidth();
841 m_fixed_tab_width
= tot_width
/(int)tab_count
;
845 if (m_fixed_tab_width
< 100)
846 m_fixed_tab_width
= 100;
848 if (m_fixed_tab_width
> tot_width
/2)
849 m_fixed_tab_width
= tot_width
/2;
851 if (m_fixed_tab_width
> 220)
852 m_fixed_tab_width
= 220;
855 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
856 wxWindow
* WXUNUSED(wnd
),
860 dc
.SetBrush(m_bkbrush
);
861 dc
.SetPen(*wxTRANSPARENT_PEN
);
862 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
865 dc
.SetPen(*wxGREY_PEN
);
866 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
870 // DrawTab() draws an individual tab.
873 // in_rect - rectangle the tab should be confined to
874 // caption - tab's caption
875 // active - whether or not the tab is active
876 // out_rect - actual output rectangle
877 // x_extent - the advance x; where the next tab should start
879 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
881 const wxAuiNotebookPage
& page
,
882 const wxRect
& in_rect
,
883 int close_button_state
,
884 wxRect
* out_tab_rect
,
885 wxRect
* out_button_rect
,
888 wxCoord normal_textx
, normal_texty
;
889 wxCoord selected_textx
, selected_texty
;
890 wxCoord textx
, texty
;
892 // if the caption is empty, measure some temporary text
893 wxString caption
= page
.caption
;
897 dc
.SetFont(m_selected_font
);
898 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
900 dc
.SetFont(m_normal_font
);
901 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
903 // figure out the size of the tab
904 wxSize tab_size
= GetTabSize(dc
,
912 wxCoord tab_height
= tab_size
.y
;
913 wxCoord tab_width
= tab_size
.x
;
914 wxCoord tab_x
= in_rect
.x
;
915 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
917 caption
= page
.caption
;
919 // select pen, brush and font for the tab to be drawn
923 dc
.SetPen(m_selected_bkpen
);
924 dc
.SetBrush(m_selected_bkbrush
);
925 dc
.SetFont(m_selected_font
);
926 textx
= selected_textx
;
927 texty
= selected_texty
;
931 dc
.SetPen(m_normal_bkpen
);
932 dc
.SetBrush(m_normal_bkbrush
);
933 dc
.SetFont(m_normal_font
);
934 textx
= normal_textx
;
935 texty
= normal_texty
;
943 points
[0].y
= tab_y
+ tab_height
- 1;
944 points
[1].x
= tab_x
+ tab_height
- 3;
945 points
[1].y
= tab_y
+ 2;
946 points
[2].x
= tab_x
+ tab_height
+ 3;
948 points
[3].x
= tab_x
+ tab_width
- 2;
950 points
[4].x
= tab_x
+ tab_width
;
951 points
[4].y
= tab_y
+ 2;
952 points
[5].x
= tab_x
+ tab_width
;
953 points
[5].y
= tab_y
+ tab_height
- 1;
954 points
[6] = points
[0];
956 dc
.SetClippingRegion(in_rect
);
958 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
960 dc
.SetPen(*wxGREY_PEN
);
962 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
963 dc
.DrawLines(WXSIZEOF(points
), points
);
968 int close_button_width
= 0;
969 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
971 close_button_width
= m_active_close_bmp
.GetWidth();
972 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
976 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
979 // set minimum text offset
980 if (text_offset
< tab_x
+ tab_height
)
981 text_offset
= tab_x
+ tab_height
;
983 // chop text if necessary
984 wxString draw_text
= wxAuiChopText(dc
,
986 tab_width
- (text_offset
-tab_x
) - close_button_width
);
989 dc
.DrawText(draw_text
,
991 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
994 // draw close button if necessary
995 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
999 bmp
= m_active_close_bmp
;
1001 bmp
= m_disabled_close_bmp
;
1003 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1004 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1007 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1009 *out_button_rect
= rect
;
1013 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1015 dc
.DestroyClippingRegion();
1018 int wxAuiSimpleTabArt::GetIndentSize()
1023 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1024 wxWindow
* WXUNUSED(wnd
),
1025 const wxString
& caption
,
1026 const wxBitmap
& WXUNUSED(bitmap
),
1027 bool WXUNUSED(active
),
1028 int close_button_state
,
1031 wxCoord measured_textx
, measured_texty
;
1033 dc
.SetFont(m_measuring_font
);
1034 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1036 wxCoord tab_height
= measured_texty
+ 4;
1037 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1039 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1040 tab_width
+= m_active_close_bmp
.GetWidth();
1042 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1044 tab_width
= m_fixed_tab_width
;
1047 *x_extent
= tab_width
- (tab_height
/2) - 1;
1049 return wxSize(tab_width
, tab_height
);
1053 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1054 wxWindow
* WXUNUSED(wnd
),
1055 const wxRect
& in_rect
,
1066 case wxAUI_BUTTON_CLOSE
:
1067 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1068 bmp
= m_disabled_close_bmp
;
1070 bmp
= m_active_close_bmp
;
1072 case wxAUI_BUTTON_LEFT
:
1073 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1074 bmp
= m_disabled_left_bmp
;
1076 bmp
= m_active_left_bmp
;
1078 case wxAUI_BUTTON_RIGHT
:
1079 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1080 bmp
= m_disabled_right_bmp
;
1082 bmp
= m_active_right_bmp
;
1084 case wxAUI_BUTTON_WINDOWLIST
:
1085 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1086 bmp
= m_disabled_windowlist_bmp
;
1088 bmp
= m_active_windowlist_bmp
;
1097 if (orientation
== wxLEFT
)
1099 rect
.SetX(in_rect
.x
);
1100 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1101 rect
.SetWidth(bmp
.GetWidth());
1102 rect
.SetHeight(bmp
.GetHeight());
1106 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1107 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1108 bmp
.GetWidth(), bmp
.GetHeight());
1112 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1118 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1119 const wxAuiNotebookPageArray
& pages
,
1124 size_t i
, count
= pages
.GetCount();
1125 for (i
= 0; i
< count
; ++i
)
1127 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1128 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1131 if (active_idx
!= -1)
1133 menuPopup
.Check(1000+active_idx
, true);
1136 // find out where to put the popup menu of window
1137 // items. Subtract 100 for now to center the menu
1138 // a bit, until a better mechanism can be implemented
1139 wxPoint pt
= ::wxGetMousePosition();
1140 pt
= wnd
->ScreenToClient(pt
);
1146 // find out the screen coordinate at the bottom of the tab ctrl
1147 wxRect cli_rect
= wnd
->GetClientRect();
1148 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1150 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1151 wnd
->PushEventHandler(cc
);
1152 wnd
->PopupMenu(&menuPopup
, pt
);
1153 int command
= cc
->GetCommandId();
1154 wnd
->PopEventHandler(true);
1156 if (command
>= 1000)
1157 return command
-1000;
1162 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1163 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1164 const wxSize
& WXUNUSED(required_bmp_size
))
1167 dc
.SetFont(m_measuring_font
);
1169 wxSize s
= GetTabSize(dc
,
1174 wxAUI_BUTTON_STATE_HIDDEN
,
1179 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1181 m_normal_font
= font
;
1184 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1186 m_selected_font
= font
;
1189 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1191 m_measuring_font
= font
;
1197 // -- wxAuiTabContainer class implementation --
1200 // wxAuiTabContainer is a class which contains information about each
1201 // tab. It also can render an entire tab control to a specified DC.
1202 // It's not a window class itself, because this code will be used by
1203 // the wxFrameMananger, where it is disadvantageous to have separate
1204 // windows for each tab control in the case of "docked tabs"
1206 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1207 // which can be used as a tab control in the normal sense.
1210 wxAuiTabContainer::wxAuiTabContainer()
1214 m_art
= new wxAuiDefaultTabArt
;
1216 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1217 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1218 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1219 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1222 wxAuiTabContainer::~wxAuiTabContainer()
1227 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1234 m_art
->SetFlags(m_flags
);
1238 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1243 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1247 // check for new close button settings
1248 RemoveButton(wxAUI_BUTTON_LEFT
);
1249 RemoveButton(wxAUI_BUTTON_RIGHT
);
1250 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1251 RemoveButton(wxAUI_BUTTON_CLOSE
);
1254 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1256 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1257 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1260 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1262 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1265 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1267 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1272 m_art
->SetFlags(m_flags
);
1276 unsigned int wxAuiTabContainer::GetFlags() const
1282 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1284 m_art
->SetNormalFont(font
);
1287 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1289 m_art
->SetSelectedFont(font
);
1292 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1294 m_art
->SetMeasuringFont(font
);
1297 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1303 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1307 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1308 const wxAuiNotebookPage
& info
)
1310 wxAuiNotebookPage page_info
;
1312 page_info
.window
= page
;
1314 m_pages
.Add(page_info
);
1316 // let the art provider know how many pages we have
1319 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1325 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1326 const wxAuiNotebookPage
& info
,
1329 wxAuiNotebookPage page_info
;
1331 page_info
.window
= page
;
1333 if (idx
>= m_pages
.GetCount())
1334 m_pages
.Add(page_info
);
1336 m_pages
.Insert(page_info
, idx
);
1338 // let the art provider know how many pages we have
1341 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1347 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1350 int idx
= GetIdxFromWindow(page
);
1354 // get page entry, make a copy of it
1355 wxAuiNotebookPage p
= GetPage(idx
);
1357 // remove old page entry
1360 // insert page where it should be
1361 InsertPage(page
, p
, new_idx
);
1366 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1368 size_t i
, page_count
= m_pages
.GetCount();
1369 for (i
= 0; i
< page_count
; ++i
)
1371 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1372 if (page
.window
== wnd
)
1374 m_pages
.RemoveAt(i
);
1376 // let the art provider know how many pages we have
1379 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1389 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1393 size_t i
, page_count
= m_pages
.GetCount();
1394 for (i
= 0; i
< page_count
; ++i
)
1396 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1397 if (page
.window
== wnd
)
1404 page
.active
= false;
1411 void wxAuiTabContainer::SetNoneActive()
1413 size_t i
, page_count
= m_pages
.GetCount();
1414 for (i
= 0; i
< page_count
; ++i
)
1416 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1417 page
.active
= false;
1421 bool wxAuiTabContainer::SetActivePage(size_t page
)
1423 if (page
>= m_pages
.GetCount())
1426 return SetActivePage(m_pages
.Item(page
).window
);
1429 int wxAuiTabContainer::GetActivePage() const
1431 size_t i
, page_count
= m_pages
.GetCount();
1432 for (i
= 0; i
< page_count
; ++i
)
1434 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1442 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1444 if (idx
>= m_pages
.GetCount())
1447 return m_pages
[idx
].window
;
1450 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1452 const size_t page_count
= m_pages
.GetCount();
1453 for ( size_t i
= 0; i
< page_count
; ++i
)
1455 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1456 if (page
.window
== wnd
)
1462 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1464 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1466 return m_pages
[idx
];
1469 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1471 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1473 return m_pages
[idx
];
1476 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1481 size_t wxAuiTabContainer::GetPageCount() const
1483 return m_pages
.GetCount();
1486 void wxAuiTabContainer::AddButton(int id
,
1488 const wxBitmap
& normal_bitmap
,
1489 const wxBitmap
& disabled_bitmap
)
1491 wxAuiTabContainerButton button
;
1493 button
.bitmap
= normal_bitmap
;
1494 button
.dis_bitmap
= disabled_bitmap
;
1495 button
.location
= location
;
1496 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1498 m_buttons
.Add(button
);
1501 void wxAuiTabContainer::RemoveButton(int id
)
1503 size_t i
, button_count
= m_buttons
.GetCount();
1505 for (i
= 0; i
< button_count
; ++i
)
1507 if (m_buttons
.Item(i
).id
== id
)
1509 m_buttons
.RemoveAt(i
);
1517 size_t wxAuiTabContainer::GetTabOffset() const
1519 return m_tab_offset
;
1522 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1524 m_tab_offset
= offset
;
1530 // Render() renders the tab catalog to the specified DC
1531 // It is a virtual function and can be overridden to
1532 // provide custom drawing capabilities
1533 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1535 if (!raw_dc
|| !raw_dc
->IsOk())
1541 size_t page_count
= m_pages
.GetCount();
1542 size_t button_count
= m_buttons
.GetCount();
1544 // create off-screen bitmap
1545 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1546 dc
.SelectObject(bmp
);
1551 // find out if size of tabs is larger than can be
1552 // afforded on screen
1553 int total_width
= 0;
1554 int visible_width
= 0;
1555 for (i
= 0; i
< page_count
; ++i
)
1557 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1559 // determine if a close button is on this tab
1560 bool close_button
= false;
1561 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1562 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1564 close_button
= true;
1569 wxSize size
= m_art
->GetTabSize(dc
,
1575 wxAUI_BUTTON_STATE_NORMAL
:
1576 wxAUI_BUTTON_STATE_HIDDEN
,
1579 if (i
+1 < page_count
)
1580 total_width
+= x_extent
;
1582 total_width
+= size
.x
;
1584 if (i
>= m_tab_offset
)
1586 if (i
+1 < page_count
)
1587 visible_width
+= x_extent
;
1589 visible_width
+= size
.x
;
1593 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1595 // show left/right buttons
1596 for (i
= 0; i
< button_count
; ++i
)
1598 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1599 if (button
.id
== wxAUI_BUTTON_LEFT
||
1600 button
.id
== wxAUI_BUTTON_RIGHT
)
1602 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1608 // hide left/right buttons
1609 for (i
= 0; i
< button_count
; ++i
)
1611 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1612 if (button
.id
== wxAUI_BUTTON_LEFT
||
1613 button
.id
== wxAUI_BUTTON_RIGHT
)
1615 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1620 // determine whether left button should be enabled
1621 for (i
= 0; i
< button_count
; ++i
)
1623 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1624 if (button
.id
== wxAUI_BUTTON_LEFT
)
1626 if (m_tab_offset
== 0)
1627 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1629 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1631 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1633 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1634 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1636 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1643 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1646 int left_buttons_width
= 0;
1647 int right_buttons_width
= 0;
1651 // draw the buttons on the right side
1652 offset
= m_rect
.x
+ m_rect
.width
;
1653 for (i
= 0; i
< button_count
; ++i
)
1655 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1657 if (button
.location
!= wxRIGHT
)
1659 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1662 wxRect button_rect
= m_rect
;
1663 button_rect
.SetY(1);
1664 button_rect
.SetWidth(offset
);
1666 m_art
->DrawButton(dc
,
1674 offset
-= button
.rect
.GetWidth();
1675 right_buttons_width
+= button
.rect
.GetWidth();
1682 // draw the buttons on the left side
1684 for (i
= 0; i
< button_count
; ++i
)
1686 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1688 if (button
.location
!= wxLEFT
)
1690 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1693 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1695 m_art
->DrawButton(dc
,
1703 offset
+= button
.rect
.GetWidth();
1704 left_buttons_width
+= button
.rect
.GetWidth();
1707 offset
= left_buttons_width
;
1710 offset
+= m_art
->GetIndentSize();
1713 // prepare the tab-close-button array
1714 // make sure tab button entries which aren't used are marked as hidden
1715 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1716 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1718 // make sure there are enough tab button entries to accommodate all tabs
1719 while (m_tab_close_buttons
.GetCount() < page_count
)
1721 wxAuiTabContainerButton tempbtn
;
1722 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1723 tempbtn
.location
= wxCENTER
;
1724 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1725 m_tab_close_buttons
.Add(tempbtn
);
1729 // buttons before the tab offset must be set to hidden
1730 for (i
= 0; i
< m_tab_offset
; ++i
)
1732 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1738 size_t active
= 999;
1739 int active_offset
= 0;
1743 wxRect rect
= m_rect
;
1745 rect
.height
= m_rect
.height
;
1747 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1749 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1750 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1752 // determine if a close button is on this tab
1753 bool close_button
= false;
1754 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1755 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1757 close_button
= true;
1758 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1760 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1761 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1762 tab_button
.location
= wxCENTER
;
1767 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1771 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1773 if (rect
.width
<= 0)
1780 tab_button
.cur_state
,
1788 active_offset
= offset
;
1796 // make sure to deactivate buttons which are off the screen to the right
1797 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1799 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1803 // draw the active tab again so it stands in the foreground
1804 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1806 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1808 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1810 // determine if a close button is on this tab
1811 bool close_button
= false;
1812 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1813 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1815 close_button
= true;
1818 rect
.x
= active_offset
;
1823 tab_button
.cur_state
,
1830 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1831 m_rect
.GetWidth(), m_rect
.GetHeight(),
1836 // TabHitTest() tests if a tab was hit, passing the window pointer
1837 // back if that condition was fulfilled. The function returns
1838 // true if a tab was hit, otherwise false
1839 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1841 if (!m_rect
.Contains(x
,y
))
1844 wxAuiTabContainerButton
* btn
= NULL
;
1845 if (ButtonHitTest(x
, y
, &btn
))
1847 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1851 size_t i
, page_count
= m_pages
.GetCount();
1853 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1855 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1856 if (page
.rect
.Contains(x
,y
))
1867 // ButtonHitTest() tests if a button was hit. The function returns
1868 // true if a button was hit, otherwise false
1869 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1870 wxAuiTabContainerButton
** hit
) const
1872 if (!m_rect
.Contains(x
,y
))
1875 size_t i
, button_count
;
1878 button_count
= m_buttons
.GetCount();
1879 for (i
= 0; i
< button_count
; ++i
)
1881 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1882 if (button
.rect
.Contains(x
,y
) &&
1883 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1884 wxAUI_BUTTON_STATE_DISABLED
)))
1892 button_count
= m_tab_close_buttons
.GetCount();
1893 for (i
= 0; i
< button_count
; ++i
)
1895 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1896 if (button
.rect
.Contains(x
,y
) &&
1897 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1898 wxAUI_BUTTON_STATE_DISABLED
)))
1911 // the utility function ShowWnd() is the same as show,
1912 // except it handles wxAuiMDIChildFrame windows as well,
1913 // as the Show() method on this class is "unplugged"
1914 static void ShowWnd(wxWindow
* wnd
, bool show
)
1916 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1918 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1928 // DoShowHide() this function shows the active window, then
1929 // hides all of the other windows (in that order)
1930 void wxAuiTabContainer::DoShowHide()
1932 wxAuiNotebookPageArray
& pages
= GetPages();
1933 size_t i
, page_count
= pages
.GetCount();
1935 // show new active page first
1936 for (i
= 0; i
< page_count
; ++i
)
1938 wxAuiNotebookPage
& page
= pages
.Item(i
);
1941 ShowWnd(page
.window
, true);
1946 // hide all other pages
1947 for (i
= 0; i
< page_count
; ++i
)
1949 wxAuiNotebookPage
& page
= pages
.Item(i
);
1951 ShowWnd(page
.window
, false);
1960 // -- wxAuiTabCtrl class implementation --
1964 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1965 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1966 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1967 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1968 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1969 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1970 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1971 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1972 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1973 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
1977 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1981 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1983 m_click_pt
= wxDefaultPosition
;
1984 m_is_dragging
= false;
1985 m_hover_button
= NULL
;
1986 m_pressed_button
= NULL
;
1989 wxAuiTabCtrl::~wxAuiTabCtrl()
1993 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1997 dc
.SetFont(GetFont());
1999 if (GetPageCount() > 0)
2003 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2007 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2009 wxSize s
= evt
.GetSize();
2010 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2014 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2017 m_click_pt
= wxDefaultPosition
;
2018 m_is_dragging
= false;
2020 m_pressed_button
= NULL
;
2024 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2026 int new_selection
= GetIdxFromWindow(wnd
);
2028 // wxAuiNotebooks always want to receive this event
2029 // even if the tab is already active, because they may
2030 // have multiple tab controls
2031 if (new_selection
!= GetActivePage() ||
2032 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2034 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2035 e
.SetSelection(new_selection
);
2036 e
.SetOldSelection(GetActivePage());
2037 e
.SetEventObject(this);
2038 GetEventHandler()->ProcessEvent(e
);
2041 m_click_pt
.x
= evt
.m_x
;
2042 m_click_pt
.y
= evt
.m_y
;
2048 m_pressed_button
= m_hover_button
;
2049 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2055 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2057 if (GetCapture() == this)
2062 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2063 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2064 evt
.SetOldSelection(evt
.GetSelection());
2065 evt
.SetEventObject(this);
2066 GetEventHandler()->ProcessEvent(evt
);
2070 if (m_pressed_button
)
2072 // make sure we're still clicking the button
2073 wxAuiTabContainerButton
* button
= NULL
;
2074 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2077 if (button
!= m_pressed_button
)
2079 m_pressed_button
= NULL
;
2086 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2088 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2089 evt
.SetInt(m_pressed_button
->id
);
2090 evt
.SetEventObject(this);
2091 GetEventHandler()->ProcessEvent(evt
);
2094 m_pressed_button
= NULL
;
2097 m_click_pt
= wxDefaultPosition
;
2098 m_is_dragging
= false;
2102 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2104 wxPoint pos
= evt
.GetPosition();
2106 // check if the mouse is hovering above a button
2107 wxAuiTabContainerButton
* button
;
2108 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2110 if (m_hover_button
&& button
!= m_hover_button
)
2112 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2113 m_hover_button
= NULL
;
2118 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2120 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2123 m_hover_button
= button
;
2131 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2132 m_hover_button
= NULL
;
2139 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2144 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2145 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2146 evt
.SetOldSelection(evt
.GetSelection());
2147 evt
.SetEventObject(this);
2148 GetEventHandler()->ProcessEvent(evt
);
2153 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2154 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2156 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2157 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2159 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2160 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2161 evt
.SetOldSelection(evt
.GetSelection());
2162 evt
.SetEventObject(this);
2163 GetEventHandler()->ProcessEvent(evt
);
2165 m_is_dragging
= true;
2169 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2173 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2174 m_hover_button
= NULL
;
2180 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2182 int button
= event
.GetInt();
2184 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2186 if (button
== wxAUI_BUTTON_LEFT
)
2188 if (GetTabOffset() > 0)
2190 SetTabOffset(GetTabOffset()-1);
2197 SetTabOffset(GetTabOffset()+1);
2202 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2204 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2208 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2209 e
.SetSelection(idx
);
2210 e
.SetOldSelection(GetActivePage());
2211 e
.SetEventObject(this);
2212 GetEventHandler()->ProcessEvent(e
);
2221 // wxTabFrame is an interesting case. It's important that all child pages
2222 // of the multi-notebook control are all actually children of that control
2223 // (and not grandchildren). wxTabFrame facilitates this. There is one
2224 // instance of wxTabFrame for each tab control inside the multi-notebook.
2225 // It's important to know that wxTabFrame is not a real window, but it merely
2226 // used to capture the dimensions/positioning of the internal tab control and
2227 // it's managed page windows
2229 class wxTabFrame
: public wxWindow
2236 m_rect
= wxRect(0,0,200,200);
2237 m_tab_ctrl_height
= 20;
2245 void SetTabCtrlHeight(int h
)
2247 m_tab_ctrl_height
= h
;
2250 void DoSetSize(int x
, int y
,
2251 int width
, int height
,
2252 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2254 m_rect
= wxRect(x
, y
, width
, height
);
2258 void DoGetClientSize(int* x
, int* y
) const
2264 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2271 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2272 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2273 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2277 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2278 size_t i
, page_count
= pages
.GetCount();
2280 for (i
= 0; i
< page_count
; ++i
)
2282 wxAuiNotebookPage
& page
= pages
.Item(i
);
2283 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2284 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2286 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2288 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2289 wnd
->ApplyMDIChildFrameRect();
2294 void DoGetSize(int* x
, int* y
) const
2297 *x
= m_rect
.GetWidth();
2299 *y
= m_rect
.GetHeight();
2311 wxAuiTabCtrl
* m_tabs
;
2312 int m_tab_ctrl_height
;
2316 const int wxAuiBaseTabCtrlId
= 5380;
2319 // -- wxAuiNotebook class implementation --
2321 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2322 EVT_SIZE(wxAuiNotebook::OnSize
)
2323 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2324 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2325 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2326 wxAuiNotebook::OnTabClicked
)
2327 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2328 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2329 wxAuiNotebook::OnTabBeginDrag
)
2330 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2331 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2332 wxAuiNotebook::OnTabEndDrag
)
2333 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2334 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2335 wxAuiNotebook::OnTabDragMotion
)
2336 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2337 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2338 wxAuiNotebook::OnTabButton
)
2341 wxAuiNotebook::wxAuiNotebook()
2344 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2346 m_tab_ctrl_height
= 20;
2347 m_requested_bmp_size
= wxDefaultSize
;
2348 m_requested_tabctrl_height
= -1;
2351 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2355 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2358 m_requested_bmp_size
= wxDefaultSize
;
2359 m_requested_tabctrl_height
= -1;
2360 InitNotebook(style
);
2363 bool wxAuiNotebook::Create(wxWindow
* parent
,
2369 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2372 InitNotebook(style
);
2377 // InitNotebook() contains common initialization
2378 // code called by all constructors
2379 void wxAuiNotebook::InitNotebook(long style
)
2382 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2384 m_flags
= (unsigned int)style
;
2385 m_tab_ctrl_height
= 20;
2387 m_normal_font
= *wxNORMAL_FONT
;
2388 m_selected_font
= *wxNORMAL_FONT
;
2389 m_selected_font
.SetWeight(wxBOLD
);
2391 SetArtProvider(new wxAuiDefaultTabArt
);
2393 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2394 m_dummy_wnd
->SetSize(200, 200);
2395 m_dummy_wnd
->Show(false);
2397 m_mgr
.SetManagedWindow(this);
2398 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2399 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2401 m_mgr
.AddPane(m_dummy_wnd
,
2402 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2407 wxAuiNotebook::~wxAuiNotebook()
2412 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2414 m_tabs
.SetArtProvider(art
);
2416 UpdateTabCtrlHeight();
2419 // SetTabCtrlHeight() is the highest-level override of the
2420 // tab height. A call to this function effectively enforces a
2421 // specified tab ctrl height, overriding all other considerations,
2422 // such as text or bitmap height. It overrides any call to
2423 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2424 // any previous call and returns to the default behavior
2426 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2428 m_requested_tabctrl_height
= height
;
2430 // if window is already initialized, recalculate the tab height
2433 UpdateTabCtrlHeight();
2438 // SetUniformBitmapSize() ensures that all tabs will have
2439 // the same height, even if some tabs don't have bitmaps
2440 // Passing wxDefaultSize to this function will instruct
2441 // the control to use dynamic tab height-- so when a tab
2442 // with a large bitmap is added, the tab ctrl's height will
2443 // automatically increase to accommodate the bitmap
2445 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2447 m_requested_bmp_size
= size
;
2449 // if window is already initialized, recalculate the tab height
2452 UpdateTabCtrlHeight();
2456 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2457 // to be used interally
2458 void wxAuiNotebook::UpdateTabCtrlHeight()
2460 // get the tab ctrl height we will use
2461 int height
= CalculateTabCtrlHeight();
2463 // if the tab control height needs to change, update
2464 // all of our tab controls with the new height
2465 if (m_tab_ctrl_height
!= height
)
2467 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2469 m_tab_ctrl_height
= height
;
2471 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2472 size_t i
, pane_count
= all_panes
.GetCount();
2473 for (i
= 0; i
< pane_count
; ++i
)
2475 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2476 if (pane
.name
== wxT("dummy"))
2478 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2479 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2480 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2481 tabctrl
->SetArtProvider(art
->Clone());
2482 tab_frame
->DoSizing();
2487 void wxAuiNotebook::UpdateHintWindowSize()
2489 wxSize size
= CalculateNewSplitSize();
2491 // the placeholder hint window should be set to this size
2492 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2496 info
.BestSize(size
);
2497 m_dummy_wnd
->SetSize(size
);
2502 // calculates the size of the new split
2503 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2505 // count number of tab controls
2506 int tab_ctrl_count
= 0;
2507 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2508 size_t i
, pane_count
= all_panes
.GetCount();
2509 for (i
= 0; i
< pane_count
; ++i
)
2511 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2512 if (pane
.name
== wxT("dummy"))
2517 wxSize new_split_size
;
2519 // if there is only one tab control, the first split
2520 // should happen around the middle
2521 if (tab_ctrl_count
< 2)
2523 new_split_size
= GetClientSize();
2524 new_split_size
.x
/= 2;
2525 new_split_size
.y
/= 2;
2529 // this is in place of a more complicated calculation
2530 // that needs to be implemented
2531 new_split_size
= wxSize(180,180);
2534 return new_split_size
;
2537 int wxAuiNotebook::CalculateTabCtrlHeight()
2539 // if a fixed tab ctrl height is specified,
2540 // just return that instead of calculating a
2542 if (m_requested_tabctrl_height
!= -1)
2543 return m_requested_tabctrl_height
;
2545 // find out new best tab height
2546 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2548 return art
->GetBestTabCtrlSize(this,
2550 m_requested_bmp_size
);
2554 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2556 return m_tabs
.GetArtProvider();
2559 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2561 wxControl::SetWindowStyleFlag(style
);
2563 m_flags
= (unsigned int)style
;
2565 // if the control is already initialized
2566 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2568 // let all of the tab children know about the new style
2570 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2571 size_t i
, pane_count
= all_panes
.GetCount();
2572 for (i
= 0; i
< pane_count
; ++i
)
2574 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2575 if (pane
.name
== wxT("dummy"))
2577 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2578 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2579 tabctrl
->SetFlags(m_flags
);
2580 tabframe
->DoSizing();
2588 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2589 const wxString
& caption
,
2591 const wxBitmap
& bitmap
)
2593 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2596 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2598 const wxString
& caption
,
2600 const wxBitmap
& bitmap
)
2602 wxAuiNotebookPage info
;
2604 info
.caption
= caption
;
2605 info
.bitmap
= bitmap
;
2606 info
.active
= false;
2608 // if there are currently no tabs, the first added
2609 // tab must be active
2610 if (m_tabs
.GetPageCount() == 0)
2613 m_tabs
.InsertPage(page
, info
, page_idx
);
2615 // if that was the first page added, even if
2616 // select is false, it must become the "current page"
2617 // (though no select events will be fired)
2618 if (!select
&& m_tabs
.GetPageCount() == 1)
2620 //m_curpage = GetPageIndex(page);
2622 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2623 if (page_idx
>= active_tabctrl
->GetPageCount())
2624 active_tabctrl
->AddPage(page
, info
);
2626 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2628 UpdateTabCtrlHeight();
2630 active_tabctrl
->DoShowHide();
2634 SetSelectionToWindow(page
);
2641 // DeletePage() removes a tab from the multi-notebook,
2642 // and destroys the window as well
2643 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2645 if (page_idx
>= m_tabs
.GetPageCount())
2648 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2650 // hide the window in advance, as this will
2652 ShowWnd(wnd
, false);
2654 if (!RemovePage(page_idx
))
2657 // actually destroy the window now
2658 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2660 // delete the child frame with pending delete, as is
2661 // customary with frame windows
2662 if (!wxPendingDelete
.Member(wnd
))
2663 wxPendingDelete
.Append(wnd
);
2675 // RemovePage() removes a tab from the multi-notebook,
2676 // but does not destroy the window
2677 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2679 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2680 wxWindow
* new_active
= NULL
;
2682 // make sure we found the page
2686 // find out which onscreen tab ctrl owns this tab
2689 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2692 bool is_curpage
= (m_curpage
== (int)page_idx
);
2693 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
2696 // remove the tab from main catalog
2697 if (!m_tabs
.RemovePage(wnd
))
2700 // remove the tab from the onscreen tab ctrl
2701 ctrl
->RemovePage(wnd
);
2703 if (is_active_in_split
)
2705 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
2707 if (ctrl_idx
>= ctrl_new_page_count
)
2708 ctrl_idx
= ctrl_new_page_count
-1;
2710 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
2712 // set new page as active in the tab split
2713 ctrl
->SetActivePage(ctrl_idx
);
2715 // if the page deleted was the current page for the
2716 // entire tab control, then record the window
2717 // pointer of the new active page for activation
2720 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
2728 // we haven't yet found a new page to active,
2729 // so select the next page from the main tab
2732 if (page_idx
< m_tabs
.GetPageCount())
2734 new_active
= m_tabs
.GetPage(page_idx
).window
;
2737 if (!new_active
&& m_tabs
.GetPageCount() > 0)
2739 new_active
= m_tabs
.GetPage(0).window
;
2744 RemoveEmptyTabFrames();
2746 // set new active pane
2750 SetSelectionToWindow(new_active
);
2756 // GetPageIndex() returns the index of the page, or -1 if the
2757 // page could not be located in the notebook
2758 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2760 return m_tabs
.GetIdxFromWindow(page_wnd
);
2765 // SetPageText() changes the tab caption of the specified page
2766 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2768 if (page_idx
>= m_tabs
.GetPageCount())
2771 // update our own tab catalog
2772 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2773 page_info
.caption
= text
;
2775 // update what's on screen
2778 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2780 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2781 info
.caption
= text
;
2789 // returns the page caption
2790 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2792 if (page_idx
>= m_tabs
.GetPageCount())
2793 return wxEmptyString
;
2795 // update our own tab catalog
2796 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2797 return page_info
.caption
;
2800 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2802 if (page_idx
>= m_tabs
.GetPageCount())
2805 // update our own tab catalog
2806 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2807 page_info
.bitmap
= bitmap
;
2809 // tab height might have changed
2810 UpdateTabCtrlHeight();
2812 // update what's on screen
2815 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2817 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2818 info
.bitmap
= bitmap
;
2826 // returns the page bitmap
2827 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2829 if (page_idx
>= m_tabs
.GetPageCount())
2832 // update our own tab catalog
2833 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2834 return page_info
.bitmap
;
2837 // GetSelection() returns the index of the currently active page
2838 int wxAuiNotebook::GetSelection() const
2843 // SetSelection() sets the currently active page
2844 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2846 // don't change the page unless necessary
2847 if ((int)new_page
== m_curpage
)
2850 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2854 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2855 evt
.SetSelection(new_page
);
2856 evt
.SetOldSelection(m_curpage
);
2857 evt
.SetEventObject(this);
2858 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2860 int old_curpage
= m_curpage
;
2861 m_curpage
= new_page
;
2863 // program allows the page change
2864 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2865 (void)GetEventHandler()->ProcessEvent(evt
);
2870 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2872 m_tabs
.SetActivePage(wnd
);
2874 ctrl
->SetActivePage(ctrl_idx
);
2881 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2882 size_t i
, pane_count
= all_panes
.GetCount();
2883 for (i
= 0; i
< pane_count
; ++i
)
2885 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2886 if (pane
.name
== wxT("dummy"))
2888 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2889 if (tabctrl
!= ctrl
)
2890 tabctrl
->SetSelectedFont(m_normal_font
);
2892 tabctrl
->SetSelectedFont(m_selected_font
);
2905 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2907 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2908 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2913 // GetPageCount() returns the total number of
2914 // pages managed by the multi-notebook
2915 size_t wxAuiNotebook::GetPageCount() const
2917 return m_tabs
.GetPageCount();
2920 // GetPage() returns the wxWindow pointer of the
2922 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2924 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2926 return m_tabs
.GetWindowFromIdx(page_idx
);
2929 // DoSizing() performs all sizing operations in each tab control
2930 void wxAuiNotebook::DoSizing()
2932 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2933 size_t i
, pane_count
= all_panes
.GetCount();
2934 for (i
= 0; i
< pane_count
; ++i
)
2936 if (all_panes
.Item(i
).name
== wxT("dummy"))
2939 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2940 tabframe
->DoSizing();
2944 // GetActiveTabCtrl() returns the active tab control. It is
2945 // called to determine which control gets new windows being added
2946 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2948 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2953 // find the tab ctrl with the current page
2954 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2961 // no current page, just find the first tab ctrl
2962 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2963 size_t i
, pane_count
= all_panes
.GetCount();
2964 for (i
= 0; i
< pane_count
; ++i
)
2966 if (all_panes
.Item(i
).name
== wxT("dummy"))
2969 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2970 return tabframe
->m_tabs
;
2973 // If there is no tabframe at all, create one
2974 wxTabFrame
* tabframe
= new wxTabFrame
;
2975 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2976 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2981 tabframe
->m_tabs
->SetFlags(m_flags
);
2982 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2983 m_mgr
.AddPane(tabframe
,
2984 wxAuiPaneInfo().Center().CaptionVisible(false));
2988 return tabframe
->m_tabs
;
2991 // FindTab() finds the tab control that currently contains the window as well
2992 // as the index of the window in the tab control. It returns true if the
2993 // window was found, otherwise false.
2994 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2996 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2997 size_t i
, pane_count
= all_panes
.GetCount();
2998 for (i
= 0; i
< pane_count
; ++i
)
3000 if (all_panes
.Item(i
).name
== wxT("dummy"))
3003 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3005 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3008 *ctrl
= tabframe
->m_tabs
;
3017 void wxAuiNotebook::Split(size_t page
, int direction
)
3019 wxSize cli_size
= GetClientSize();
3021 // get the page's window pointer
3022 wxWindow
* wnd
= GetPage(page
);
3026 // notebooks with 1 or less pages can't be split
3027 if (GetPageCount() < 2)
3030 // find out which tab control the page currently belongs to
3031 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3034 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3036 if (!src_tabs
|| src_idx
== -1)
3039 // choose a split size
3041 if (GetPageCount() > 2)
3043 split_size
= CalculateNewSplitSize();
3047 // because there are two panes, always split them
3049 split_size
= GetClientSize();
3055 // create a new tab frame
3056 wxTabFrame
* new_tabs
= new wxTabFrame
;
3057 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3058 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3059 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3064 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3065 new_tabs
->m_tabs
->SetFlags(m_flags
);
3066 dest_tabs
= new_tabs
->m_tabs
;
3068 // create a pane info structure with the information
3069 // about where the pane should be added
3070 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3073 if (direction
== wxLEFT
)
3076 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3078 else if (direction
== wxRIGHT
)
3081 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3083 else if (direction
== wxTOP
)
3086 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3088 else if (direction
== wxBOTTOM
)
3091 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3094 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3097 // remove the page from the source tabs
3098 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3099 page_info
.active
= false;
3100 src_tabs
->RemovePage(page_info
.window
);
3101 if (src_tabs
->GetPageCount() > 0)
3103 src_tabs
->SetActivePage((size_t)0);
3104 src_tabs
->DoShowHide();
3105 src_tabs
->Refresh();
3109 // add the page to the destination tabs
3110 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3112 if (src_tabs
->GetPageCount() == 0)
3114 RemoveEmptyTabFrames();
3118 dest_tabs
->DoShowHide();
3119 dest_tabs
->Refresh();
3121 // force the set selection function reset the selection
3124 // set the active page to the one we just split off
3125 SetSelectionToPage(page_info
);
3127 UpdateHintWindowSize();
3131 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3133 UpdateHintWindowSize();
3138 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3140 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3142 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3143 wxASSERT(ctrl
!= NULL
);
3145 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3146 wxASSERT(wnd
!= NULL
);
3148 SetSelectionToWindow(wnd
);
3151 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3156 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3158 wxPoint screen_pt
= ::wxGetMousePosition();
3159 wxPoint client_pt
= ScreenToClient(screen_pt
);
3162 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3163 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3165 if (dest_tabs
== src_tabs
)
3169 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3172 // always hide the hint for inner-tabctrl drag
3175 // if tab moving is not allowed, leave
3176 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3181 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3182 wxWindow
* dest_location_tab
;
3184 // this is an inner-tab drag/reposition
3185 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3187 int src_idx
= evt
.GetSelection();
3188 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3190 // prevent jumpy drag
3191 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3192 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3193 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3195 m_last_drag_x
= pt
.x
;
3200 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3201 dest_tabs
->MovePage(src_tab
, dest_idx
);
3202 dest_tabs
->SetActivePage((size_t)dest_idx
);
3203 dest_tabs
->DoShowHide();
3204 dest_tabs
->Refresh();
3205 m_last_drag_x
= pt
.x
;
3213 // if external drag is allowed, check if the tab is being dragged
3214 // over a different wxAuiNotebook control
3215 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3217 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3219 // if we aren't over any window, stop here
3223 // make sure we are not over the hint window
3224 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3228 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3230 tab_ctrl
= tab_ctrl
->GetParent();
3235 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3239 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3240 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3241 m_mgr
.ShowHint(hint_rect
);
3250 // we are either over a hint window, or not over a tab
3251 // window, and there is no where to drag to, so exit
3258 // if there are less than two panes, split can't happen, so leave
3259 if (m_tabs
.GetPageCount() < 2)
3262 // if tab moving is not allowed, leave
3263 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3269 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3275 wxRect hint_rect
= dest_tabs
->GetRect();
3276 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3277 m_mgr
.ShowHint(hint_rect
);
3281 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3287 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3289 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3294 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3295 wxCHECK_RET( src_tabs
, _T("no source object?") );
3297 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3299 // get the mouse position, which will be used to determine the drop point
3300 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3301 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3305 // check for an external move
3306 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3308 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3312 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3314 tab_ctrl
= tab_ctrl
->GetParent();
3319 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3323 // find out from the destination control
3324 // if it's ok to drop this tab here
3325 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3326 e
.SetSelection(evt
.GetSelection());
3327 e
.SetOldSelection(evt
.GetSelection());
3328 e
.SetEventObject(this);
3329 e
.SetDragSource(this);
3330 e
.Veto(); // dropping must be explicitly approved by control owner
3332 nb
->GetEventHandler()->ProcessEvent(e
);
3336 // no answer or negative answer
3342 int src_idx
= evt
.GetSelection();
3343 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3345 // get main index of the page
3346 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3347 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3350 // make a copy of the page info
3351 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3353 // remove the page from the source notebook
3354 RemovePage(main_idx
);
3356 // reparent the page
3357 src_page
->Reparent(nb
);
3360 // found out the insert idx
3361 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3362 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3364 wxWindow
* target
= NULL
;
3365 int insert_idx
= -1;
3366 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3369 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3373 // add the page to the new notebook
3374 if (insert_idx
== -1)
3375 insert_idx
= dest_tabs
->GetPageCount();
3376 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3377 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3380 dest_tabs
->DoShowHide();
3381 dest_tabs
->Refresh();
3383 // set the selection in the destination tab control
3384 nb
->SetSelectionToPage(page_info
);
3394 // only perform a tab split if it's allowed
3395 wxAuiTabCtrl
* dest_tabs
= NULL
;
3397 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3399 // If the pointer is in an existing tab frame, do a tab insert
3400 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3401 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3402 int insert_idx
= -1;
3405 dest_tabs
= tab_frame
->m_tabs
;
3407 if (dest_tabs
== src_tabs
)
3411 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3412 wxWindow
* target
= NULL
;
3413 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3416 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3422 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3427 // there is no suitable drop location here, exit out
3431 // If there is no tabframe at all, create one
3432 wxTabFrame
* new_tabs
= new wxTabFrame
;
3433 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3434 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3435 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3440 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3441 new_tabs
->m_tabs
->SetFlags(m_flags
);
3443 m_mgr
.AddPane(new_tabs
,
3444 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3447 dest_tabs
= new_tabs
->m_tabs
;
3452 // remove the page from the source tabs
3453 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3454 page_info
.active
= false;
3455 src_tabs
->RemovePage(page_info
.window
);
3456 if (src_tabs
->GetPageCount() > 0)
3458 src_tabs
->SetActivePage((size_t)0);
3459 src_tabs
->DoShowHide();
3460 src_tabs
->Refresh();
3465 // add the page to the destination tabs
3466 if (insert_idx
== -1)
3467 insert_idx
= dest_tabs
->GetPageCount();
3468 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3470 if (src_tabs
->GetPageCount() == 0)
3472 RemoveEmptyTabFrames();
3476 dest_tabs
->DoShowHide();
3477 dest_tabs
->Refresh();
3479 // force the set selection function reset the selection
3482 // set the active page to the one we just split off
3483 SetSelectionToPage(page_info
);
3485 UpdateHintWindowSize();
3491 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3493 // if we've just removed the last tab from the source
3494 // tab set, the remove the tab control completely
3495 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3496 size_t i
, pane_count
= all_panes
.GetCount();
3497 for (i
= 0; i
< pane_count
; ++i
)
3499 if (all_panes
.Item(i
).name
== wxT("dummy"))
3502 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3503 if (tabframe
->m_tab_rect
.Contains(pt
))
3504 return tabframe
->m_tabs
;
3510 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3512 // if we've just removed the last tab from the source
3513 // tab set, the remove the tab control completely
3514 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3515 size_t i
, pane_count
= all_panes
.GetCount();
3516 for (i
= 0; i
< pane_count
; ++i
)
3518 if (all_panes
.Item(i
).name
== wxT("dummy"))
3521 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3522 if (tabframe
->m_tabs
== tab_ctrl
)
3531 void wxAuiNotebook::RemoveEmptyTabFrames()
3533 // if we've just removed the last tab from the source
3534 // tab set, the remove the tab control completely
3535 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3536 size_t i
, pane_count
= all_panes
.GetCount();
3537 for (i
= 0; i
< pane_count
; ++i
)
3539 if (all_panes
.Item(i
).name
== wxT("dummy"))
3542 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3543 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3545 m_mgr
.DetachPane(tab_frame
);
3547 // use pending delete because sometimes during
3548 // window closing, refreshs are pending
3549 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3550 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3552 tab_frame
->m_tabs
= NULL
;
3559 // check to see if there is still a center pane;
3560 // if there isn't, make a frame the center pane
3561 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3562 pane_count
= panes
.GetCount();
3563 wxWindow
* first_good
= NULL
;
3564 bool center_found
= false;
3565 for (i
= 0; i
< pane_count
; ++i
)
3567 if (panes
.Item(i
).name
== wxT("dummy"))
3569 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3570 center_found
= true;
3572 first_good
= panes
.Item(i
).window
;
3575 if (!center_found
&& first_good
)
3577 m_mgr
.GetPane(first_good
).Centre();
3583 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3585 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3586 if (idx
!= -1 && idx
!= m_curpage
)
3593 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3595 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3596 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3598 int button_id
= evt
.GetInt();
3600 if (button_id
== wxAUI_BUTTON_CLOSE
)
3602 int selection
= tabs
->GetActivePage();
3604 if (selection
!= -1)
3606 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3609 // ask owner if it's ok to close the tab
3610 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3611 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3612 e
.SetOldSelection(evt
.GetSelection());
3613 e
.SetEventObject(this);
3614 GetEventHandler()->ProcessEvent(e
);
3619 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3625 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3626 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3628 DeletePage(main_idx
);
3634 // Sets the normal font
3635 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
3637 m_normal_font
= font
;
3638 GetArtProvider()->SetNormalFont(font
);
3641 // Sets the selected tab font
3642 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
3644 m_selected_font
= font
;
3645 GetArtProvider()->SetSelectedFont(font
);
3648 // Sets the measuring font
3649 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
3651 GetArtProvider()->SetMeasuringFont(font
);
3654 // Sets the tab font
3655 bool wxAuiNotebook::SetFont(const wxFont
& font
)
3657 wxControl::SetFont(font
);
3659 wxFont
normalFont(font
);
3660 wxFont
selectedFont(normalFont
);
3661 selectedFont
.SetWeight(wxBOLD
);
3663 SetNormalFont(normalFont
);
3664 SetSelectedFont(selectedFont
);
3665 SetMeasuringFont(selectedFont
);
3670 // Gets the tab control height
3671 int wxAuiNotebook::GetTabCtrlHeight() const
3673 return m_tab_ctrl_height
;
3676 // Gets the height of the notebook for a given page height
3677 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
3679 UpdateTabCtrlHeight();
3681 int tabCtrlHeight
= GetTabCtrlHeight();
3682 int decorHeight
= 2;
3683 return tabCtrlHeight
+ pageHeight
+ decorHeight
;