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 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2647 if (!RemovePage(page_idx
))
2650 // actually destroy the window now
2651 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2653 // delete the child frame with pending delete, as is
2654 // customary with frame windows
2655 if (!wxPendingDelete
.Member(wnd
))
2656 wxPendingDelete
.Append(wnd
);
2668 // RemovePage() removes a tab from the multi-notebook,
2669 // but does not destroy the window
2670 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2672 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2673 wxWindow
* new_active
= NULL
;
2675 // find out which onscreen tab ctrl owns this tab
2678 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2681 // find a new page and set it as active
2682 int new_idx
= ctrl_idx
+1;
2683 if (new_idx
>= (int)ctrl
->GetPageCount())
2684 new_idx
= ctrl_idx
-1;
2686 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2688 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2692 // set the active page to the first page that
2693 // isn't the one being deleted
2694 size_t i
, page_count
= m_tabs
.GetPageCount();
2695 for (i
= 0; i
< page_count
; ++i
)
2697 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2700 new_active
= m_tabs
.GetWindowFromIdx(i
);
2706 // remove the tab from main catalog
2707 if (!m_tabs
.RemovePage(wnd
))
2710 // remove the tab from the onscreen tab ctrl
2711 ctrl
->RemovePage(wnd
);
2714 RemoveEmptyTabFrames();
2716 // set new active pane
2720 SetSelectionToWindow(new_active
);
2726 // GetPageIndex() returns the index of the page, or -1 if the
2727 // page could not be located in the notebook
2728 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2730 return m_tabs
.GetIdxFromWindow(page_wnd
);
2735 // SetPageText() changes the tab caption of the specified page
2736 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2738 if (page_idx
>= m_tabs
.GetPageCount())
2741 // update our own tab catalog
2742 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2743 page_info
.caption
= text
;
2745 // update what's on screen
2748 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2750 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2751 info
.caption
= text
;
2759 // returns the page caption
2760 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2762 if (page_idx
>= m_tabs
.GetPageCount())
2763 return wxEmptyString
;
2765 // update our own tab catalog
2766 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2767 return page_info
.caption
;
2770 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2772 if (page_idx
>= m_tabs
.GetPageCount())
2775 // update our own tab catalog
2776 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2777 page_info
.bitmap
= bitmap
;
2779 // tab height might have changed
2780 UpdateTabCtrlHeight();
2782 // update what's on screen
2785 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2787 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2788 info
.bitmap
= bitmap
;
2796 // returns the page bitmap
2797 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2799 if (page_idx
>= m_tabs
.GetPageCount())
2802 // update our own tab catalog
2803 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2804 return page_info
.bitmap
;
2807 // GetSelection() returns the index of the currently active page
2808 int wxAuiNotebook::GetSelection() const
2813 // SetSelection() sets the currently active page
2814 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2816 // don't change the page unless necessary
2817 if ((int)new_page
== m_curpage
)
2820 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2824 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2825 evt
.SetSelection(new_page
);
2826 evt
.SetOldSelection(m_curpage
);
2827 evt
.SetEventObject(this);
2828 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2830 int old_curpage
= m_curpage
;
2831 m_curpage
= new_page
;
2833 // program allows the page change
2834 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2835 (void)GetEventHandler()->ProcessEvent(evt
);
2840 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2842 m_tabs
.SetActivePage(wnd
);
2844 ctrl
->SetActivePage(ctrl_idx
);
2851 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2852 size_t i
, pane_count
= all_panes
.GetCount();
2853 for (i
= 0; i
< pane_count
; ++i
)
2855 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2856 if (pane
.name
== wxT("dummy"))
2858 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2859 if (tabctrl
!= ctrl
)
2860 tabctrl
->SetSelectedFont(m_normal_font
);
2862 tabctrl
->SetSelectedFont(m_selected_font
);
2875 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2877 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2878 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2883 // GetPageCount() returns the total number of
2884 // pages managed by the multi-notebook
2885 size_t wxAuiNotebook::GetPageCount() const
2887 return m_tabs
.GetPageCount();
2890 // GetPage() returns the wxWindow pointer of the
2892 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2894 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2896 return m_tabs
.GetWindowFromIdx(page_idx
);
2899 // DoSizing() performs all sizing operations in each tab control
2900 void wxAuiNotebook::DoSizing()
2902 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2903 size_t i
, pane_count
= all_panes
.GetCount();
2904 for (i
= 0; i
< pane_count
; ++i
)
2906 if (all_panes
.Item(i
).name
== wxT("dummy"))
2909 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2910 tabframe
->DoSizing();
2914 // GetActiveTabCtrl() returns the active tab control. It is
2915 // called to determine which control gets new windows being added
2916 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2918 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2923 // find the tab ctrl with the current page
2924 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2931 // no current page, just find the first tab ctrl
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 return tabframe
->m_tabs
;
2943 // If there is no tabframe at all, create one
2944 wxTabFrame
* tabframe
= new wxTabFrame
;
2945 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2946 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2951 tabframe
->m_tabs
->SetFlags(m_flags
);
2952 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2953 m_mgr
.AddPane(tabframe
,
2954 wxAuiPaneInfo().Center().CaptionVisible(false));
2958 return tabframe
->m_tabs
;
2961 // FindTab() finds the tab control that currently contains the window as well
2962 // as the index of the window in the tab control. It returns true if the
2963 // window was found, otherwise false.
2964 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2966 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2967 size_t i
, pane_count
= all_panes
.GetCount();
2968 for (i
= 0; i
< pane_count
; ++i
)
2970 if (all_panes
.Item(i
).name
== wxT("dummy"))
2973 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2975 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2978 *ctrl
= tabframe
->m_tabs
;
2987 void wxAuiNotebook::Split(size_t page
, int direction
)
2989 wxSize cli_size
= GetClientSize();
2991 // get the page's window pointer
2992 wxWindow
* wnd
= GetPage(page
);
2996 // notebooks with 1 or less pages can't be split
2997 if (GetPageCount() < 2)
3000 // find out which tab control the page currently belongs to
3001 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3004 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3006 if (!src_tabs
|| src_idx
== -1)
3009 // choose a split size
3011 if (GetPageCount() > 2)
3013 split_size
= CalculateNewSplitSize();
3017 // because there are two panes, always split them
3019 split_size
= GetClientSize();
3025 // create a new tab frame
3026 wxTabFrame
* new_tabs
= new wxTabFrame
;
3027 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3028 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3029 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3034 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3035 new_tabs
->m_tabs
->SetFlags(m_flags
);
3036 dest_tabs
= new_tabs
->m_tabs
;
3038 // create a pane info structure with the information
3039 // about where the pane should be added
3040 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3043 if (direction
== wxLEFT
)
3046 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3048 else if (direction
== wxRIGHT
)
3051 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3053 else if (direction
== wxTOP
)
3056 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3058 else if (direction
== wxBOTTOM
)
3061 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3064 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3067 // remove the page from the source tabs
3068 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3069 page_info
.active
= false;
3070 src_tabs
->RemovePage(page_info
.window
);
3071 if (src_tabs
->GetPageCount() > 0)
3073 src_tabs
->SetActivePage((size_t)0);
3074 src_tabs
->DoShowHide();
3075 src_tabs
->Refresh();
3079 // add the page to the destination tabs
3080 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3082 if (src_tabs
->GetPageCount() == 0)
3084 RemoveEmptyTabFrames();
3088 dest_tabs
->DoShowHide();
3089 dest_tabs
->Refresh();
3091 // force the set selection function reset the selection
3094 // set the active page to the one we just split off
3095 SetSelectionToPage(page_info
);
3097 UpdateHintWindowSize();
3101 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3103 UpdateHintWindowSize();
3108 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3110 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3112 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3113 wxASSERT(ctrl
!= NULL
);
3115 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3116 wxASSERT(wnd
!= NULL
);
3118 SetSelectionToWindow(wnd
);
3121 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3126 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3128 wxPoint screen_pt
= ::wxGetMousePosition();
3129 wxPoint client_pt
= ScreenToClient(screen_pt
);
3132 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3133 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3135 if (dest_tabs
== src_tabs
)
3139 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3142 // always hide the hint for inner-tabctrl drag
3145 // if tab moving is not allowed, leave
3146 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3151 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3152 wxWindow
* dest_location_tab
;
3154 // this is an inner-tab drag/reposition
3155 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3157 int src_idx
= evt
.GetSelection();
3158 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3160 // prevent jumpy drag
3161 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3162 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3163 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3165 m_last_drag_x
= pt
.x
;
3170 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3171 dest_tabs
->MovePage(src_tab
, dest_idx
);
3172 dest_tabs
->SetActivePage((size_t)dest_idx
);
3173 dest_tabs
->DoShowHide();
3174 dest_tabs
->Refresh();
3175 m_last_drag_x
= pt
.x
;
3183 // if external drag is allowed, check if the tab is being dragged
3184 // over a different wxAuiNotebook control
3185 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3187 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3189 // if we aren't over any window, stop here
3193 // make sure we are not over the hint window
3194 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3198 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3200 tab_ctrl
= tab_ctrl
->GetParent();
3205 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3209 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3210 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3211 m_mgr
.ShowHint(hint_rect
);
3220 // we are either over a hint window, or not over a tab
3221 // window, and there is no where to drag to, so exit
3228 // if there are less than two panes, split can't happen, so leave
3229 if (m_tabs
.GetPageCount() < 2)
3232 // if tab moving is not allowed, leave
3233 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3239 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3245 wxRect hint_rect
= dest_tabs
->GetRect();
3246 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3247 m_mgr
.ShowHint(hint_rect
);
3251 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3257 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3259 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3264 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3265 wxCHECK_RET( src_tabs
, _T("no source object?") );
3267 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3269 // get the mouse position, which will be used to determine the drop point
3270 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3271 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3275 // check for an external move
3276 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3278 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3282 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3284 tab_ctrl
= tab_ctrl
->GetParent();
3289 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3293 // find out from the destination control
3294 // if it's ok to drop this tab here
3295 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3296 e
.SetSelection(evt
.GetSelection());
3297 e
.SetOldSelection(evt
.GetSelection());
3298 e
.SetEventObject(this);
3299 e
.SetDragSource(this);
3300 e
.Veto(); // dropping must be explicitly approved by control owner
3302 nb
->GetEventHandler()->ProcessEvent(e
);
3306 // no answer or negative answer
3312 int src_idx
= evt
.GetSelection();
3313 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3315 // get main index of the page
3316 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3317 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3320 // make a copy of the page info
3321 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3323 // remove the page from the source notebook
3324 RemovePage(main_idx
);
3326 // reparent the page
3327 src_page
->Reparent(nb
);
3330 // found out the insert idx
3331 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3332 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3334 wxWindow
* target
= NULL
;
3335 int insert_idx
= -1;
3336 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3339 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3343 // add the page to the new notebook
3344 if (insert_idx
== -1)
3345 insert_idx
= dest_tabs
->GetPageCount();
3346 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3347 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3350 dest_tabs
->DoShowHide();
3351 dest_tabs
->Refresh();
3353 // set the selection in the destination tab control
3354 nb
->SetSelectionToPage(page_info
);
3364 // only perform a tab split if it's allowed
3365 wxAuiTabCtrl
* dest_tabs
= NULL
;
3367 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3369 // If the pointer is in an existing tab frame, do a tab insert
3370 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3371 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3372 int insert_idx
= -1;
3375 dest_tabs
= tab_frame
->m_tabs
;
3377 if (dest_tabs
== src_tabs
)
3381 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3382 wxWindow
* target
= NULL
;
3383 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3386 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3392 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3397 // there is no suitable drop location here, exit out
3401 // If there is no tabframe at all, create one
3402 wxTabFrame
* new_tabs
= new wxTabFrame
;
3403 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3404 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3405 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3410 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3411 new_tabs
->m_tabs
->SetFlags(m_flags
);
3413 m_mgr
.AddPane(new_tabs
,
3414 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3417 dest_tabs
= new_tabs
->m_tabs
;
3422 // remove the page from the source tabs
3423 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3424 page_info
.active
= false;
3425 src_tabs
->RemovePage(page_info
.window
);
3426 if (src_tabs
->GetPageCount() > 0)
3428 src_tabs
->SetActivePage((size_t)0);
3429 src_tabs
->DoShowHide();
3430 src_tabs
->Refresh();
3435 // add the page to the destination tabs
3436 if (insert_idx
== -1)
3437 insert_idx
= dest_tabs
->GetPageCount();
3438 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3440 if (src_tabs
->GetPageCount() == 0)
3442 RemoveEmptyTabFrames();
3446 dest_tabs
->DoShowHide();
3447 dest_tabs
->Refresh();
3449 // force the set selection function reset the selection
3452 // set the active page to the one we just split off
3453 SetSelectionToPage(page_info
);
3455 UpdateHintWindowSize();
3461 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3463 // if we've just removed the last tab from the source
3464 // tab set, the remove the tab control completely
3465 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3466 size_t i
, pane_count
= all_panes
.GetCount();
3467 for (i
= 0; i
< pane_count
; ++i
)
3469 if (all_panes
.Item(i
).name
== wxT("dummy"))
3472 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3473 if (tabframe
->m_tab_rect
.Contains(pt
))
3474 return tabframe
->m_tabs
;
3480 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3482 // if we've just removed the last tab from the source
3483 // tab set, the remove the tab control completely
3484 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3485 size_t i
, pane_count
= all_panes
.GetCount();
3486 for (i
= 0; i
< pane_count
; ++i
)
3488 if (all_panes
.Item(i
).name
== wxT("dummy"))
3491 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3492 if (tabframe
->m_tabs
== tab_ctrl
)
3501 void wxAuiNotebook::RemoveEmptyTabFrames()
3503 // if we've just removed the last tab from the source
3504 // tab set, the remove the tab control completely
3505 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3506 size_t i
, pane_count
= all_panes
.GetCount();
3507 for (i
= 0; i
< pane_count
; ++i
)
3509 if (all_panes
.Item(i
).name
== wxT("dummy"))
3512 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3513 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3515 m_mgr
.DetachPane(tab_frame
);
3517 // use pending delete because sometimes during
3518 // window closing, refreshs are pending
3519 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3520 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3521 //tab_frame->m_tabs->Destroy();
3528 // check to see if there is still a center pane;
3529 // if there isn't, make a frame the center pane
3530 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3531 pane_count
= panes
.GetCount();
3532 wxWindow
* first_good
= NULL
;
3533 bool center_found
= false;
3534 for (i
= 0; i
< pane_count
; ++i
)
3536 if (panes
.Item(i
).name
== wxT("dummy"))
3538 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3539 center_found
= true;
3541 first_good
= panes
.Item(i
).window
;
3544 if (!center_found
&& first_good
)
3546 m_mgr
.GetPane(first_good
).Centre();
3552 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3554 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3555 if (idx
!= -1 && idx
!= m_curpage
)
3562 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3564 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3565 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3567 int button_id
= evt
.GetInt();
3569 if (button_id
== wxAUI_BUTTON_CLOSE
)
3571 int selection
= tabs
->GetActivePage();
3573 if (selection
!= -1)
3575 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3578 // ask owner if it's ok to close the tab
3579 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3580 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3581 e
.SetOldSelection(evt
.GetSelection());
3582 e
.SetEventObject(this);
3583 GetEventHandler()->ProcessEvent(e
);
3588 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3594 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3595 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3597 DeletePage(main_idx
);
3603 // Sets the normal font
3604 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
3606 m_normal_font
= font
;
3607 GetArtProvider()->SetNormalFont(font
);
3610 // Sets the selected tab font
3611 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
3613 m_selected_font
= font
;
3614 GetArtProvider()->SetSelectedFont(font
);
3617 // Sets the measuring font
3618 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
3620 GetArtProvider()->SetMeasuringFont(font
);
3623 // Sets the tab font
3624 bool wxAuiNotebook::SetFont(const wxFont
& font
)
3626 wxControl::SetFont(font
);
3628 wxFont
normalFont(font
);
3629 wxFont
selectedFont(normalFont
);
3630 selectedFont
.SetWeight(wxBOLD
);
3632 SetNormalFont(normalFont
);
3633 SetSelectedFont(selectedFont
);
3634 SetMeasuringFont(selectedFont
);
3639 // Gets the tab control height
3640 int wxAuiNotebook::GetTabCtrlHeight() const
3642 return m_tab_ctrl_height
;
3645 // Gets the height of the notebook for a given page height
3646 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
3648 UpdateTabCtrlHeight();
3650 int tabCtrlHeight
= GetTabCtrlHeight();
3651 int decorHeight
= 2;
3652 return tabCtrlHeight
+ pageHeight
+ decorHeight
;