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 return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
);
236 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
241 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
244 m_fixed_tab_width
= 100;
246 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
248 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
249 tot_width
-= m_active_close_bmp
.GetWidth();
250 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
251 tot_width
-= m_active_windowlist_bmp
.GetWidth();
255 m_fixed_tab_width
= tot_width
/(int)tab_count
;
259 if (m_fixed_tab_width
< 100)
260 m_fixed_tab_width
= 100;
262 if (m_fixed_tab_width
> tot_width
/2)
263 m_fixed_tab_width
= tot_width
/2;
265 if (m_fixed_tab_width
> 220)
266 m_fixed_tab_width
= 220;
268 m_tab_ctrl_height
= tab_ctrl_size
.y
;
272 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
273 wxWindow
* WXUNUSED(wnd
),
277 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
278 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
279 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
280 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
283 int y
= rect
.GetHeight();
284 int w
= rect
.GetWidth();
285 dc
.SetPen(m_border_pen
);
286 dc
.SetBrush(m_base_colour_brush
);
287 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
291 // DrawTab() draws an individual tab.
294 // in_rect - rectangle the tab should be confined to
295 // caption - tab's caption
296 // active - whether or not the tab is active
297 // out_rect - actual output rectangle
298 // x_extent - the advance x; where the next tab should start
300 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
302 const wxAuiNotebookPage
& page
,
303 const wxRect
& in_rect
,
304 int close_button_state
,
305 wxRect
* out_tab_rect
,
306 wxRect
* out_button_rect
,
309 wxCoord normal_textx
, normal_texty
;
310 wxCoord selected_textx
, selected_texty
;
311 wxCoord textx
, texty
;
313 // if the caption is empty, measure some temporary text
314 wxString caption
= page
.caption
;
318 dc
.SetFont(m_selected_font
);
319 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
321 dc
.SetFont(m_normal_font
);
322 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
324 // figure out the size of the tab
325 wxSize tab_size
= GetTabSize(dc
,
333 wxCoord tab_height
= m_tab_ctrl_height
- 3;
334 wxCoord tab_width
= tab_size
.x
;
335 wxCoord tab_x
= in_rect
.x
;
336 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
339 caption
= page
.caption
;
342 // select pen, brush and font for the tab to be drawn
346 dc
.SetFont(m_selected_font
);
347 textx
= selected_textx
;
348 texty
= selected_texty
;
352 dc
.SetFont(m_normal_font
);
353 textx
= normal_textx
;
354 texty
= normal_texty
;
358 // create points that will make the tab outline
360 int clip_width
= tab_width
;
361 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
362 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
365 wxPoint clip_points[6];
366 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
367 clip_points[1] = wxPoint(tab_x, tab_y+2);
368 clip_points[2] = wxPoint(tab_x+2, tab_y);
369 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
370 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
371 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
373 // FIXME: these ports don't provide wxRegion ctor from array of points
374 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
375 // set the clipping region for the tab --
376 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
377 dc.SetClippingRegion(clipping_region);
378 #endif // !wxDFB && !wxCocoa
380 // since the above code above doesn't play well with WXDFB or WXCOCOA,
381 // we'll just use a rectangle for the clipping region for now --
382 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
385 wxPoint border_points
[6];
386 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
387 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
388 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
389 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
390 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
391 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
394 int drawn_tab_yoff
= border_points
[1].y
;
395 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
402 // draw base background color
403 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
404 dc
.SetPen(m_base_colour_pen
);
405 dc
.SetBrush(m_base_colour_brush
);
406 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
408 // this white helps fill out the gradient at the top of the tab
409 dc
.SetPen(*wxWHITE_PEN
);
410 dc
.SetBrush(*wxWHITE_BRUSH
);
411 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
413 // these two points help the rounded corners appear more antialiased
414 dc
.SetPen(m_base_colour_pen
);
415 dc
.DrawPoint(r
.x
+2, r
.y
+1);
416 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
418 // set rectangle down a bit for gradient drawing
419 r
.SetHeight(r
.GetHeight()/2);
425 // draw gradient background
426 wxColor top_color
= *wxWHITE
;
427 wxColor bottom_color
= m_base_colour
;
428 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
434 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
436 // start the gradent up a bit and leave the inside border inset
437 // by a pixel for a 3D look. Only the top half of the inactive
438 // tab will have a slight gradient
445 // -- draw top gradient fill for glossy look
446 wxColor top_color
= m_base_colour
;
447 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
448 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
453 // -- draw bottom fill for glossy look
454 top_color
= m_base_colour
;
455 bottom_color
= m_base_colour
;
456 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
460 dc
.SetPen(m_border_pen
);
461 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
462 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
464 // there are two horizontal grey lines at the bottom of the tab control,
465 // this gets rid of the top one of those lines in the tab control
468 wxColor start_color
= m_base_colour
;
469 dc
.SetPen(m_base_colour_pen
);
470 dc
.DrawLine(border_points
[0].x
+1,
477 int text_offset
= tab_x
+ 8;
478 int close_button_width
= 0;
479 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
481 close_button_width
= m_active_close_bmp
.GetWidth();
485 if (page
.bitmap
.IsOk())
487 int bitmap_offset
= tab_x
+ 8;
490 dc
.DrawBitmap(page
.bitmap
,
492 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
495 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
496 text_offset
+= 3; // bitmap padding
500 text_offset
= tab_x
+ 8;
504 wxString draw_text
= wxAuiChopText(dc
,
506 tab_width
- (text_offset
-tab_x
) - close_button_width
);
509 dc
.DrawText(draw_text
,
511 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
516 // draw close button if necessary
517 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
519 wxBitmap bmp
= m_disabled_close_bmp
;
521 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
522 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
524 bmp
= m_active_close_bmp
;
527 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
528 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
531 IndentPressedBitmap(&rect
, close_button_state
);
532 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
534 *out_button_rect
= rect
;
537 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
539 dc
.DestroyClippingRegion();
542 int wxAuiDefaultTabArt::GetIndentSize()
547 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
548 wxWindow
* WXUNUSED(wnd
),
549 const wxString
& caption
,
550 const wxBitmap
& bitmap
,
551 bool WXUNUSED(active
),
552 int close_button_state
,
555 wxCoord measured_textx
, measured_texty
, tmp
;
557 dc
.SetFont(m_measuring_font
);
558 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
560 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
562 // add padding around the text
563 wxCoord tab_width
= measured_textx
;
564 wxCoord tab_height
= measured_texty
;
566 // if the close button is showing, add space for it
567 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
568 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
570 // if there's a bitmap, add space for it
573 tab_width
+= bitmap
.GetWidth();
574 tab_width
+= 3; // right side bitmap padding
575 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
582 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
584 tab_width
= m_fixed_tab_width
;
587 *x_extent
= tab_width
;
589 return wxSize(tab_width
, tab_height
);
593 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
594 wxWindow
* WXUNUSED(wnd
),
595 const wxRect
& in_rect
,
606 case wxAUI_BUTTON_CLOSE
:
607 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
608 bmp
= m_disabled_close_bmp
;
610 bmp
= m_active_close_bmp
;
612 case wxAUI_BUTTON_LEFT
:
613 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
614 bmp
= m_disabled_left_bmp
;
616 bmp
= m_active_left_bmp
;
618 case wxAUI_BUTTON_RIGHT
:
619 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
620 bmp
= m_disabled_right_bmp
;
622 bmp
= m_active_right_bmp
;
624 case wxAUI_BUTTON_WINDOWLIST
:
625 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
626 bmp
= m_disabled_windowlist_bmp
;
628 bmp
= m_active_windowlist_bmp
;
638 if (orientation
== wxLEFT
)
640 rect
.SetX(in_rect
.x
);
641 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
642 rect
.SetWidth(bmp
.GetWidth());
643 rect
.SetHeight(bmp
.GetHeight());
647 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
648 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
649 bmp
.GetWidth(), bmp
.GetHeight());
652 IndentPressedBitmap(&rect
, button_state
);
653 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
659 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
660 const wxAuiNotebookPageArray
& pages
,
665 size_t i
, count
= pages
.GetCount();
666 for (i
= 0; i
< count
; ++i
)
668 const wxAuiNotebookPage
& page
= pages
.Item(i
);
669 wxString caption
= page
.caption
;
671 // if there is no caption, make it a space. This will prevent
672 // an assert in the menu code.
673 if (caption
.IsEmpty())
676 menuPopup
.AppendCheckItem(1000+i
, caption
);
679 if (active_idx
!= -1)
681 menuPopup
.Check(1000+active_idx
, true);
684 // find out where to put the popup menu of window items
685 wxPoint pt
= ::wxGetMousePosition();
686 pt
= wnd
->ScreenToClient(pt
);
688 // find out the screen coordinate at the bottom of the tab ctrl
689 wxRect cli_rect
= wnd
->GetClientRect();
690 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
692 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
693 wnd
->PushEventHandler(cc
);
694 wnd
->PopupMenu(&menuPopup
, pt
);
695 int command
= cc
->GetCommandId();
696 wnd
->PopEventHandler(true);
704 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
705 const wxAuiNotebookPageArray
& pages
,
706 const wxSize
& required_bmp_size
)
709 dc
.SetFont(m_measuring_font
);
711 // sometimes a standard bitmap size needs to be enforced, especially
712 // if some tabs have bitmaps and others don't. This is important because
713 // it prevents the tab control from resizing when tabs are added.
714 wxBitmap measure_bmp
;
715 if (required_bmp_size
.IsFullySpecified())
717 measure_bmp
.Create(required_bmp_size
.x
,
718 required_bmp_size
.y
);
723 size_t i
, page_count
= pages
.GetCount();
724 for (i
= 0; i
< page_count
; ++i
)
726 wxAuiNotebookPage
& page
= pages
.Item(i
);
729 if (measure_bmp
.IsOk())
734 // we don't use the caption text because we don't
735 // want tab heights to be different in the case
736 // of a very short piece of text on one tab and a very
737 // tall piece of text on another tab
739 wxSize s
= GetTabSize(dc
,
744 wxAUI_BUTTON_STATE_HIDDEN
,
747 max_y
= wxMax(max_y
, s
.y
);
753 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
755 m_normal_font
= font
;
758 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
760 m_selected_font
= font
;
763 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
765 m_measuring_font
= font
;
769 // -- wxAuiSimpleTabArt class implementation --
771 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
773 m_normal_font
= *wxNORMAL_FONT
;
774 m_selected_font
= *wxNORMAL_FONT
;
775 m_selected_font
.SetWeight(wxBOLD
);
776 m_measuring_font
= m_selected_font
;
779 m_fixed_tab_width
= 100;
781 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
783 wxColour background_colour
= base_colour
;
784 wxColour normaltab_colour
= base_colour
;
785 wxColour selectedtab_colour
= *wxWHITE
;
787 m_bkbrush
= wxBrush(background_colour
);
788 m_normal_bkbrush
= wxBrush(normaltab_colour
);
789 m_normal_bkpen
= wxPen(normaltab_colour
);
790 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
791 m_selected_bkpen
= wxPen(selectedtab_colour
);
793 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
794 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
796 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
797 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
799 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
800 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
802 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
803 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
807 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
811 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
813 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
817 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
822 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
825 m_fixed_tab_width
= 100;
827 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
829 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
830 tot_width
-= m_active_close_bmp
.GetWidth();
831 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
832 tot_width
-= m_active_windowlist_bmp
.GetWidth();
836 m_fixed_tab_width
= tot_width
/(int)tab_count
;
840 if (m_fixed_tab_width
< 100)
841 m_fixed_tab_width
= 100;
843 if (m_fixed_tab_width
> tot_width
/2)
844 m_fixed_tab_width
= tot_width
/2;
846 if (m_fixed_tab_width
> 220)
847 m_fixed_tab_width
= 220;
850 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
851 wxWindow
* WXUNUSED(wnd
),
855 dc
.SetBrush(m_bkbrush
);
856 dc
.SetPen(*wxTRANSPARENT_PEN
);
857 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
860 dc
.SetPen(*wxGREY_PEN
);
861 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
865 // DrawTab() draws an individual tab.
868 // in_rect - rectangle the tab should be confined to
869 // caption - tab's caption
870 // active - whether or not the tab is active
871 // out_rect - actual output rectangle
872 // x_extent - the advance x; where the next tab should start
874 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
876 const wxAuiNotebookPage
& page
,
877 const wxRect
& in_rect
,
878 int close_button_state
,
879 wxRect
* out_tab_rect
,
880 wxRect
* out_button_rect
,
883 wxCoord normal_textx
, normal_texty
;
884 wxCoord selected_textx
, selected_texty
;
885 wxCoord textx
, texty
;
887 // if the caption is empty, measure some temporary text
888 wxString caption
= page
.caption
;
892 dc
.SetFont(m_selected_font
);
893 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
895 dc
.SetFont(m_normal_font
);
896 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
898 // figure out the size of the tab
899 wxSize tab_size
= GetTabSize(dc
,
907 wxCoord tab_height
= tab_size
.y
;
908 wxCoord tab_width
= tab_size
.x
;
909 wxCoord tab_x
= in_rect
.x
;
910 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
912 caption
= page
.caption
;
914 // select pen, brush and font for the tab to be drawn
918 dc
.SetPen(m_selected_bkpen
);
919 dc
.SetBrush(m_selected_bkbrush
);
920 dc
.SetFont(m_selected_font
);
921 textx
= selected_textx
;
922 texty
= selected_texty
;
926 dc
.SetPen(m_normal_bkpen
);
927 dc
.SetBrush(m_normal_bkbrush
);
928 dc
.SetFont(m_normal_font
);
929 textx
= normal_textx
;
930 texty
= normal_texty
;
938 points
[0].y
= tab_y
+ tab_height
- 1;
939 points
[1].x
= tab_x
+ tab_height
- 3;
940 points
[1].y
= tab_y
+ 2;
941 points
[2].x
= tab_x
+ tab_height
+ 3;
943 points
[3].x
= tab_x
+ tab_width
- 2;
945 points
[4].x
= tab_x
+ tab_width
;
946 points
[4].y
= tab_y
+ 2;
947 points
[5].x
= tab_x
+ tab_width
;
948 points
[5].y
= tab_y
+ tab_height
- 1;
949 points
[6] = points
[0];
951 dc
.SetClippingRegion(in_rect
);
953 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
955 dc
.SetPen(*wxGREY_PEN
);
957 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
958 dc
.DrawLines(WXSIZEOF(points
), points
);
963 int close_button_width
= 0;
964 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
966 close_button_width
= m_active_close_bmp
.GetWidth();
967 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
971 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
974 // set minimum text offset
975 if (text_offset
< tab_x
+ tab_height
)
976 text_offset
= tab_x
+ tab_height
;
978 // chop text if necessary
979 wxString draw_text
= wxAuiChopText(dc
,
981 tab_width
- (text_offset
-tab_x
) - close_button_width
);
984 dc
.DrawText(draw_text
,
986 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
989 // draw close button if necessary
990 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
994 bmp
= m_active_close_bmp
;
996 bmp
= m_disabled_close_bmp
;
998 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
999 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1002 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1004 *out_button_rect
= rect
;
1008 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1010 dc
.DestroyClippingRegion();
1013 int wxAuiSimpleTabArt::GetIndentSize()
1018 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1019 wxWindow
* WXUNUSED(wnd
),
1020 const wxString
& caption
,
1021 const wxBitmap
& WXUNUSED(bitmap
),
1022 bool WXUNUSED(active
),
1023 int close_button_state
,
1026 wxCoord measured_textx
, measured_texty
;
1028 dc
.SetFont(m_measuring_font
);
1029 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1031 wxCoord tab_height
= measured_texty
+ 4;
1032 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1034 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1035 tab_width
+= m_active_close_bmp
.GetWidth();
1037 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1039 tab_width
= m_fixed_tab_width
;
1042 *x_extent
= tab_width
- (tab_height
/2) - 1;
1044 return wxSize(tab_width
, tab_height
);
1048 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1049 wxWindow
* WXUNUSED(wnd
),
1050 const wxRect
& in_rect
,
1061 case wxAUI_BUTTON_CLOSE
:
1062 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1063 bmp
= m_disabled_close_bmp
;
1065 bmp
= m_active_close_bmp
;
1067 case wxAUI_BUTTON_LEFT
:
1068 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1069 bmp
= m_disabled_left_bmp
;
1071 bmp
= m_active_left_bmp
;
1073 case wxAUI_BUTTON_RIGHT
:
1074 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1075 bmp
= m_disabled_right_bmp
;
1077 bmp
= m_active_right_bmp
;
1079 case wxAUI_BUTTON_WINDOWLIST
:
1080 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1081 bmp
= m_disabled_windowlist_bmp
;
1083 bmp
= m_active_windowlist_bmp
;
1092 if (orientation
== wxLEFT
)
1094 rect
.SetX(in_rect
.x
);
1095 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1096 rect
.SetWidth(bmp
.GetWidth());
1097 rect
.SetHeight(bmp
.GetHeight());
1101 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1102 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1103 bmp
.GetWidth(), bmp
.GetHeight());
1107 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1113 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1114 const wxAuiNotebookPageArray
& pages
,
1119 size_t i
, count
= pages
.GetCount();
1120 for (i
= 0; i
< count
; ++i
)
1122 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1123 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1126 if (active_idx
!= -1)
1128 menuPopup
.Check(1000+active_idx
, true);
1131 // find out where to put the popup menu of window
1132 // items. Subtract 100 for now to center the menu
1133 // a bit, until a better mechanism can be implemented
1134 wxPoint pt
= ::wxGetMousePosition();
1135 pt
= wnd
->ScreenToClient(pt
);
1141 // find out the screen coordinate at the bottom of the tab ctrl
1142 wxRect cli_rect
= wnd
->GetClientRect();
1143 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1145 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1146 wnd
->PushEventHandler(cc
);
1147 wnd
->PopupMenu(&menuPopup
, pt
);
1148 int command
= cc
->GetCommandId();
1149 wnd
->PopEventHandler(true);
1151 if (command
>= 1000)
1152 return command
-1000;
1157 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1158 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1159 const wxSize
& WXUNUSED(required_bmp_size
))
1162 dc
.SetFont(m_measuring_font
);
1164 wxSize s
= GetTabSize(dc
,
1169 wxAUI_BUTTON_STATE_HIDDEN
,
1174 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1176 m_normal_font
= font
;
1179 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1181 m_selected_font
= font
;
1184 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1186 m_measuring_font
= font
;
1192 // -- wxAuiTabContainer class implementation --
1195 // wxAuiTabContainer is a class which contains information about each
1196 // tab. It also can render an entire tab control to a specified DC.
1197 // It's not a window class itself, because this code will be used by
1198 // the wxFrameMananger, where it is disadvantageous to have separate
1199 // windows for each tab control in the case of "docked tabs"
1201 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1202 // which can be used as a tab control in the normal sense.
1205 wxAuiTabContainer::wxAuiTabContainer()
1209 m_art
= new wxAuiDefaultTabArt
;
1211 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1212 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1213 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1214 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1217 wxAuiTabContainer::~wxAuiTabContainer()
1222 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1229 m_art
->SetFlags(m_flags
);
1233 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1238 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1242 // check for new close button settings
1243 RemoveButton(wxAUI_BUTTON_LEFT
);
1244 RemoveButton(wxAUI_BUTTON_RIGHT
);
1245 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1246 RemoveButton(wxAUI_BUTTON_CLOSE
);
1249 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1251 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1252 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1255 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1257 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1260 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1262 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1267 m_art
->SetFlags(m_flags
);
1271 unsigned int wxAuiTabContainer::GetFlags() const
1277 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1279 m_art
->SetNormalFont(font
);
1282 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1284 m_art
->SetSelectedFont(font
);
1287 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1289 m_art
->SetMeasuringFont(font
);
1292 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1298 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1302 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1303 const wxAuiNotebookPage
& info
)
1305 wxAuiNotebookPage page_info
;
1307 page_info
.window
= page
;
1309 m_pages
.Add(page_info
);
1311 // let the art provider know how many pages we have
1314 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1320 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1321 const wxAuiNotebookPage
& info
,
1324 wxAuiNotebookPage page_info
;
1326 page_info
.window
= page
;
1328 if (idx
>= m_pages
.GetCount())
1329 m_pages
.Add(page_info
);
1331 m_pages
.Insert(page_info
, idx
);
1333 // let the art provider know how many pages we have
1336 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1342 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1345 int idx
= GetIdxFromWindow(page
);
1349 // get page entry, make a copy of it
1350 wxAuiNotebookPage p
= GetPage(idx
);
1352 // remove old page entry
1355 // insert page where it should be
1356 InsertPage(page
, p
, new_idx
);
1361 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1363 size_t i
, page_count
= m_pages
.GetCount();
1364 for (i
= 0; i
< page_count
; ++i
)
1366 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1367 if (page
.window
== wnd
)
1369 m_pages
.RemoveAt(i
);
1371 // let the art provider know how many pages we have
1374 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1384 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1388 size_t i
, page_count
= m_pages
.GetCount();
1389 for (i
= 0; i
< page_count
; ++i
)
1391 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1392 if (page
.window
== wnd
)
1399 page
.active
= false;
1406 void wxAuiTabContainer::SetNoneActive()
1408 size_t i
, page_count
= m_pages
.GetCount();
1409 for (i
= 0; i
< page_count
; ++i
)
1411 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1412 page
.active
= false;
1416 bool wxAuiTabContainer::SetActivePage(size_t page
)
1418 if (page
>= m_pages
.GetCount())
1421 return SetActivePage(m_pages
.Item(page
).window
);
1424 int wxAuiTabContainer::GetActivePage() const
1426 size_t i
, page_count
= m_pages
.GetCount();
1427 for (i
= 0; i
< page_count
; ++i
)
1429 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1437 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1439 if (idx
>= m_pages
.GetCount())
1442 return m_pages
[idx
].window
;
1445 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1447 const size_t page_count
= m_pages
.GetCount();
1448 for ( size_t i
= 0; i
< page_count
; ++i
)
1450 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1451 if (page
.window
== wnd
)
1457 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1459 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1461 return m_pages
[idx
];
1464 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1466 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1468 return m_pages
[idx
];
1471 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1476 size_t wxAuiTabContainer::GetPageCount() const
1478 return m_pages
.GetCount();
1481 void wxAuiTabContainer::AddButton(int id
,
1483 const wxBitmap
& normal_bitmap
,
1484 const wxBitmap
& disabled_bitmap
)
1486 wxAuiTabContainerButton button
;
1488 button
.bitmap
= normal_bitmap
;
1489 button
.dis_bitmap
= disabled_bitmap
;
1490 button
.location
= location
;
1491 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1493 m_buttons
.Add(button
);
1496 void wxAuiTabContainer::RemoveButton(int id
)
1498 size_t i
, button_count
= m_buttons
.GetCount();
1500 for (i
= 0; i
< button_count
; ++i
)
1502 if (m_buttons
.Item(i
).id
== id
)
1504 m_buttons
.RemoveAt(i
);
1512 size_t wxAuiTabContainer::GetTabOffset() const
1514 return m_tab_offset
;
1517 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1519 m_tab_offset
= offset
;
1525 // Render() renders the tab catalog to the specified DC
1526 // It is a virtual function and can be overridden to
1527 // provide custom drawing capabilities
1528 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1530 if (!raw_dc
|| !raw_dc
->IsOk())
1536 size_t page_count
= m_pages
.GetCount();
1537 size_t button_count
= m_buttons
.GetCount();
1539 // create off-screen bitmap
1540 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1541 dc
.SelectObject(bmp
);
1546 // find out if size of tabs is larger than can be
1547 // afforded on screen
1548 int total_width
= 0;
1549 int visible_width
= 0;
1550 for (i
= 0; i
< page_count
; ++i
)
1552 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1554 // determine if a close button is on this tab
1555 bool close_button
= false;
1556 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1557 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1559 close_button
= true;
1564 wxSize size
= m_art
->GetTabSize(dc
,
1570 wxAUI_BUTTON_STATE_NORMAL
:
1571 wxAUI_BUTTON_STATE_HIDDEN
,
1574 if (i
+1 < page_count
)
1575 total_width
+= x_extent
;
1577 total_width
+= size
.x
;
1579 if (i
>= m_tab_offset
)
1581 if (i
+1 < page_count
)
1582 visible_width
+= x_extent
;
1584 visible_width
+= size
.x
;
1588 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1590 // show left/right buttons
1591 for (i
= 0; i
< button_count
; ++i
)
1593 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1594 if (button
.id
== wxAUI_BUTTON_LEFT
||
1595 button
.id
== wxAUI_BUTTON_RIGHT
)
1597 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1603 // hide left/right buttons
1604 for (i
= 0; i
< button_count
; ++i
)
1606 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1607 if (button
.id
== wxAUI_BUTTON_LEFT
||
1608 button
.id
== wxAUI_BUTTON_RIGHT
)
1610 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1615 // determine whether left button should be enabled
1616 for (i
= 0; i
< button_count
; ++i
)
1618 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1619 if (button
.id
== wxAUI_BUTTON_LEFT
)
1621 if (m_tab_offset
== 0)
1622 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1624 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1626 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1628 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1629 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1631 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1638 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1641 int left_buttons_width
= 0;
1642 int right_buttons_width
= 0;
1646 // draw the buttons on the right side
1647 offset
= m_rect
.x
+ m_rect
.width
;
1648 for (i
= 0; i
< button_count
; ++i
)
1650 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1652 if (button
.location
!= wxRIGHT
)
1654 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1657 wxRect button_rect
= m_rect
;
1658 button_rect
.SetY(1);
1659 button_rect
.SetWidth(offset
);
1661 m_art
->DrawButton(dc
,
1669 offset
-= button
.rect
.GetWidth();
1670 right_buttons_width
+= button
.rect
.GetWidth();
1677 // draw the buttons on the left side
1679 for (i
= 0; i
< button_count
; ++i
)
1681 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1683 if (button
.location
!= wxLEFT
)
1685 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1688 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1690 m_art
->DrawButton(dc
,
1698 offset
+= button
.rect
.GetWidth();
1699 left_buttons_width
+= button
.rect
.GetWidth();
1702 offset
= left_buttons_width
;
1705 offset
+= m_art
->GetIndentSize();
1708 // prepare the tab-close-button array
1709 // make sure tab button entries which aren't used are marked as hidden
1710 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1711 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1713 // make sure there are enough tab button entries to accommodate all tabs
1714 while (m_tab_close_buttons
.GetCount() < page_count
)
1716 wxAuiTabContainerButton tempbtn
;
1717 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1718 tempbtn
.location
= wxCENTER
;
1719 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1720 m_tab_close_buttons
.Add(tempbtn
);
1724 // buttons before the tab offset must be set to hidden
1725 for (i
= 0; i
< m_tab_offset
; ++i
)
1727 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1733 size_t active
= 999;
1734 int active_offset
= 0;
1738 wxRect rect
= m_rect
;
1740 rect
.height
= m_rect
.height
;
1742 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1744 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1745 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1747 // determine if a close button is on this tab
1748 bool close_button
= false;
1749 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1750 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1752 close_button
= true;
1753 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1755 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1756 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1757 tab_button
.location
= wxCENTER
;
1762 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1766 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1768 if (rect
.width
<= 0)
1775 tab_button
.cur_state
,
1783 active_offset
= offset
;
1791 // make sure to deactivate buttons which are off the screen to the right
1792 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1794 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1798 // draw the active tab again so it stands in the foreground
1799 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1801 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1803 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1805 // determine if a close button is on this tab
1806 bool close_button
= false;
1807 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1808 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1810 close_button
= true;
1813 rect
.x
= active_offset
;
1818 tab_button
.cur_state
,
1825 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1826 m_rect
.GetWidth(), m_rect
.GetHeight(),
1831 // TabHitTest() tests if a tab was hit, passing the window pointer
1832 // back if that condition was fulfilled. The function returns
1833 // true if a tab was hit, otherwise false
1834 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1836 if (!m_rect
.Contains(x
,y
))
1839 wxAuiTabContainerButton
* btn
= NULL
;
1840 if (ButtonHitTest(x
, y
, &btn
))
1842 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1846 size_t i
, page_count
= m_pages
.GetCount();
1848 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1850 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1851 if (page
.rect
.Contains(x
,y
))
1862 // ButtonHitTest() tests if a button was hit. The function returns
1863 // true if a button was hit, otherwise false
1864 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1865 wxAuiTabContainerButton
** hit
) const
1867 if (!m_rect
.Contains(x
,y
))
1870 size_t i
, button_count
;
1873 button_count
= m_buttons
.GetCount();
1874 for (i
= 0; i
< button_count
; ++i
)
1876 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1877 if (button
.rect
.Contains(x
,y
) &&
1878 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1879 wxAUI_BUTTON_STATE_DISABLED
)))
1887 button_count
= m_tab_close_buttons
.GetCount();
1888 for (i
= 0; i
< button_count
; ++i
)
1890 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1891 if (button
.rect
.Contains(x
,y
) &&
1892 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1893 wxAUI_BUTTON_STATE_DISABLED
)))
1906 // the utility function ShowWnd() is the same as show,
1907 // except it handles wxAuiMDIChildFrame windows as well,
1908 // as the Show() method on this class is "unplugged"
1909 static void ShowWnd(wxWindow
* wnd
, bool show
)
1911 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1913 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1923 // DoShowHide() this function shows the active window, then
1924 // hides all of the other windows (in that order)
1925 void wxAuiTabContainer::DoShowHide()
1927 wxAuiNotebookPageArray
& pages
= GetPages();
1928 size_t i
, page_count
= pages
.GetCount();
1930 // show new active page first
1931 for (i
= 0; i
< page_count
; ++i
)
1933 wxAuiNotebookPage
& page
= pages
.Item(i
);
1936 ShowWnd(page
.window
, true);
1941 // hide all other pages
1942 for (i
= 0; i
< page_count
; ++i
)
1944 wxAuiNotebookPage
& page
= pages
.Item(i
);
1946 ShowWnd(page
.window
, false);
1955 // -- wxAuiTabCtrl class implementation --
1959 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1960 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1961 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1962 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1963 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1964 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1965 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1966 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1967 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1968 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
1972 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1976 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1978 m_click_pt
= wxDefaultPosition
;
1979 m_is_dragging
= false;
1980 m_hover_button
= NULL
;
1981 m_pressed_button
= NULL
;
1984 wxAuiTabCtrl::~wxAuiTabCtrl()
1988 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1992 dc
.SetFont(GetFont());
1994 if (GetPageCount() > 0)
1998 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2002 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2004 wxSize s
= evt
.GetSize();
2005 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2009 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2012 m_click_pt
= wxDefaultPosition
;
2013 m_is_dragging
= false;
2015 m_pressed_button
= NULL
;
2019 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2021 int new_selection
= GetIdxFromWindow(wnd
);
2023 // wxAuiNotebooks always want to receive this event
2024 // even if the tab is already active, because they may
2025 // have multiple tab controls
2026 if (new_selection
!= GetActivePage() ||
2027 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2029 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2030 e
.SetSelection(new_selection
);
2031 e
.SetOldSelection(GetActivePage());
2032 e
.SetEventObject(this);
2033 GetEventHandler()->ProcessEvent(e
);
2036 m_click_pt
.x
= evt
.m_x
;
2037 m_click_pt
.y
= evt
.m_y
;
2043 m_pressed_button
= m_hover_button
;
2044 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2050 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2052 if (GetCapture() == this)
2057 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2058 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2059 evt
.SetOldSelection(evt
.GetSelection());
2060 evt
.SetEventObject(this);
2061 GetEventHandler()->ProcessEvent(evt
);
2065 if (m_pressed_button
)
2067 // make sure we're still clicking the button
2068 wxAuiTabContainerButton
* button
= NULL
;
2069 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2072 if (button
!= m_pressed_button
)
2074 m_pressed_button
= NULL
;
2081 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2083 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2084 evt
.SetInt(m_pressed_button
->id
);
2085 evt
.SetEventObject(this);
2086 GetEventHandler()->ProcessEvent(evt
);
2089 m_pressed_button
= NULL
;
2092 m_click_pt
= wxDefaultPosition
;
2093 m_is_dragging
= false;
2097 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2099 wxPoint pos
= evt
.GetPosition();
2101 // check if the mouse is hovering above a button
2102 wxAuiTabContainerButton
* button
;
2103 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2105 if (m_hover_button
&& button
!= m_hover_button
)
2107 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2108 m_hover_button
= NULL
;
2113 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2115 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2118 m_hover_button
= button
;
2126 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2127 m_hover_button
= NULL
;
2134 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2139 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2140 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2141 evt
.SetOldSelection(evt
.GetSelection());
2142 evt
.SetEventObject(this);
2143 GetEventHandler()->ProcessEvent(evt
);
2148 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2149 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2151 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2152 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2154 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2155 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2156 evt
.SetOldSelection(evt
.GetSelection());
2157 evt
.SetEventObject(this);
2158 GetEventHandler()->ProcessEvent(evt
);
2160 m_is_dragging
= true;
2164 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2168 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2169 m_hover_button
= NULL
;
2175 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2177 int button
= event
.GetInt();
2179 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2181 if (button
== wxAUI_BUTTON_LEFT
)
2183 if (GetTabOffset() > 0)
2185 SetTabOffset(GetTabOffset()-1);
2192 SetTabOffset(GetTabOffset()+1);
2197 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2199 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2203 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2204 e
.SetSelection(idx
);
2205 e
.SetOldSelection(GetActivePage());
2206 e
.SetEventObject(this);
2207 GetEventHandler()->ProcessEvent(e
);
2216 // wxTabFrame is an interesting case. It's important that all child pages
2217 // of the multi-notebook control are all actually children of that control
2218 // (and not grandchildren). wxTabFrame facilitates this. There is one
2219 // instance of wxTabFrame for each tab control inside the multi-notebook.
2220 // It's important to know that wxTabFrame is not a real window, but it merely
2221 // used to capture the dimensions/positioning of the internal tab control and
2222 // it's managed page windows
2224 class wxTabFrame
: public wxWindow
2231 m_rect
= wxRect(0,0,200,200);
2232 m_tab_ctrl_height
= 20;
2235 void SetTabCtrlHeight(int h
)
2237 m_tab_ctrl_height
= h
;
2240 void DoSetSize(int x
, int y
,
2241 int width
, int height
,
2242 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2244 m_rect
= wxRect(x
, y
, width
, height
);
2248 void DoGetClientSize(int* x
, int* y
) const
2254 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2261 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2262 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2263 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2267 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2268 size_t i
, page_count
= pages
.GetCount();
2270 for (i
= 0; i
< page_count
; ++i
)
2272 wxAuiNotebookPage
& page
= pages
.Item(i
);
2273 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2274 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2276 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2278 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2279 wnd
->ApplyMDIChildFrameRect();
2284 void DoGetSize(int* x
, int* y
) const
2287 *x
= m_rect
.GetWidth();
2289 *y
= m_rect
.GetHeight();
2301 wxAuiTabCtrl
* m_tabs
;
2302 int m_tab_ctrl_height
;
2306 const int wxAuiBaseTabCtrlId
= 5380;
2309 // -- wxAuiNotebook class implementation --
2311 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2312 EVT_SIZE(wxAuiNotebook::OnSize
)
2313 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2314 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2315 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2316 wxAuiNotebook::OnTabClicked
)
2317 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2318 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2319 wxAuiNotebook::OnTabBeginDrag
)
2320 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2321 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2322 wxAuiNotebook::OnTabEndDrag
)
2323 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2324 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2325 wxAuiNotebook::OnTabDragMotion
)
2326 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2327 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2328 wxAuiNotebook::OnTabButton
)
2331 wxAuiNotebook::wxAuiNotebook()
2334 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2336 m_tab_ctrl_height
= 20;
2337 m_requested_bmp_size
= wxDefaultSize
;
2338 m_requested_tabctrl_height
= -1;
2341 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2345 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2348 m_requested_bmp_size
= wxDefaultSize
;
2349 m_requested_tabctrl_height
= -1;
2350 InitNotebook(style
);
2353 bool wxAuiNotebook::Create(wxWindow
* parent
,
2359 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2362 InitNotebook(style
);
2367 // InitNotebook() contains common initialization
2368 // code called by all constructors
2369 void wxAuiNotebook::InitNotebook(long style
)
2372 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2374 m_flags
= (unsigned int)style
;
2375 m_tab_ctrl_height
= 20;
2377 m_normal_font
= *wxNORMAL_FONT
;
2378 m_selected_font
= *wxNORMAL_FONT
;
2379 m_selected_font
.SetWeight(wxBOLD
);
2381 SetArtProvider(new wxAuiDefaultTabArt
);
2383 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2384 m_dummy_wnd
->SetSize(200, 200);
2385 m_dummy_wnd
->Show(false);
2387 m_mgr
.SetManagedWindow(this);
2388 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2389 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2391 m_mgr
.AddPane(m_dummy_wnd
,
2392 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2397 wxAuiNotebook::~wxAuiNotebook()
2402 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2404 m_tabs
.SetArtProvider(art
);
2406 UpdateTabCtrlHeight();
2409 // SetTabCtrlHeight() is the highest-level override of the
2410 // tab height. A call to this function effectively enforces a
2411 // specified tab ctrl height, overriding all other considerations,
2412 // such as text or bitmap height. It overrides any call to
2413 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2414 // any previous call and returns to the default behavior
2416 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2418 m_requested_tabctrl_height
= height
;
2420 // if window is already initialized, recalculate the tab height
2423 UpdateTabCtrlHeight();
2428 // SetUniformBitmapSize() ensures that all tabs will have
2429 // the same height, even if some tabs don't have bitmaps
2430 // Passing wxDefaultSize to this function will instruct
2431 // the control to use dynamic tab height-- so when a tab
2432 // with a large bitmap is added, the tab ctrl's height will
2433 // automatically increase to accommodate the bitmap
2435 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2437 m_requested_bmp_size
= size
;
2439 // if window is already initialized, recalculate the tab height
2442 UpdateTabCtrlHeight();
2446 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2447 // to be used interally
2448 void wxAuiNotebook::UpdateTabCtrlHeight()
2450 // get the tab ctrl height we will use
2451 int height
= CalculateTabCtrlHeight();
2453 // if the tab control height needs to change, update
2454 // all of our tab controls with the new height
2455 if (m_tab_ctrl_height
!= height
)
2457 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2459 m_tab_ctrl_height
= height
;
2461 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2462 size_t i
, pane_count
= all_panes
.GetCount();
2463 for (i
= 0; i
< pane_count
; ++i
)
2465 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2466 if (pane
.name
== wxT("dummy"))
2468 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2469 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2470 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2471 tabctrl
->SetArtProvider(art
->Clone());
2472 tab_frame
->DoSizing();
2477 void wxAuiNotebook::UpdateHintWindowSize()
2479 wxSize size
= CalculateNewSplitSize();
2481 // the placeholder hint window should be set to this size
2482 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2486 info
.BestSize(size
);
2487 m_dummy_wnd
->SetSize(size
);
2492 // calculates the size of the new split
2493 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2495 // count number of tab controls
2496 int tab_ctrl_count
= 0;
2497 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2498 size_t i
, pane_count
= all_panes
.GetCount();
2499 for (i
= 0; i
< pane_count
; ++i
)
2501 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2502 if (pane
.name
== wxT("dummy"))
2507 wxSize new_split_size
;
2509 // if there is only one tab control, the first split
2510 // should happen around the middle
2511 if (tab_ctrl_count
< 2)
2513 new_split_size
= GetClientSize();
2514 new_split_size
.x
/= 2;
2515 new_split_size
.y
/= 2;
2519 // this is in place of a more complicated calculation
2520 // that needs to be implemented
2521 new_split_size
= wxSize(180,180);
2524 return new_split_size
;
2527 int wxAuiNotebook::CalculateTabCtrlHeight()
2529 // if a fixed tab ctrl height is specified,
2530 // just return that instead of calculating a
2532 if (m_requested_tabctrl_height
!= -1)
2533 return m_requested_tabctrl_height
;
2535 // find out new best tab height
2536 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2538 return art
->GetBestTabCtrlSize(this,
2540 m_requested_bmp_size
);
2544 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2546 return m_tabs
.GetArtProvider();
2549 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2551 wxControl::SetWindowStyleFlag(style
);
2553 m_flags
= (unsigned int)style
;
2555 // if the control is already initialized
2556 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2558 // let all of the tab children know about the new style
2560 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2561 size_t i
, pane_count
= all_panes
.GetCount();
2562 for (i
= 0; i
< pane_count
; ++i
)
2564 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2565 if (pane
.name
== wxT("dummy"))
2567 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2568 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2569 tabctrl
->SetFlags(m_flags
);
2570 tabframe
->DoSizing();
2578 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2579 const wxString
& caption
,
2581 const wxBitmap
& bitmap
)
2583 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2586 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2588 const wxString
& caption
,
2590 const wxBitmap
& bitmap
)
2592 wxAuiNotebookPage info
;
2594 info
.caption
= caption
;
2595 info
.bitmap
= bitmap
;
2596 info
.active
= false;
2598 // if there are currently no tabs, the first added
2599 // tab must be active
2600 if (m_tabs
.GetPageCount() == 0)
2603 m_tabs
.InsertPage(page
, info
, page_idx
);
2605 // if that was the first page added, even if
2606 // select is false, it must become the "current page"
2607 // (though no select events will be fired)
2608 if (!select
&& m_tabs
.GetPageCount() == 1)
2610 //m_curpage = GetPageIndex(page);
2612 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2613 if (page_idx
>= active_tabctrl
->GetPageCount())
2614 active_tabctrl
->AddPage(page
, info
);
2616 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2618 UpdateTabCtrlHeight();
2620 active_tabctrl
->DoShowHide();
2624 SetSelectionToWindow(page
);
2631 // DeletePage() removes a tab from the multi-notebook,
2632 // and destroys the window as well
2633 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2635 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2637 if (!RemovePage(page_idx
))
2640 // actually destroy the window now
2641 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2643 // delete the child frame with pending delete, as is
2644 // customary with frame windows
2645 if (!wxPendingDelete
.Member(wnd
))
2646 wxPendingDelete
.Append(wnd
);
2658 // RemovePage() removes a tab from the multi-notebook,
2659 // but does not destroy the window
2660 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2662 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2663 wxWindow
* new_active
= NULL
;
2665 // find out which onscreen tab ctrl owns this tab
2668 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2671 // find a new page and set it as active
2672 int new_idx
= ctrl_idx
+1;
2673 if (new_idx
>= (int)ctrl
->GetPageCount())
2674 new_idx
= ctrl_idx
-1;
2676 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2678 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2682 // set the active page to the first page that
2683 // isn't the one being deleted
2684 size_t i
, page_count
= m_tabs
.GetPageCount();
2685 for (i
= 0; i
< page_count
; ++i
)
2687 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2690 new_active
= m_tabs
.GetWindowFromIdx(i
);
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
);
2704 RemoveEmptyTabFrames();
2706 // set new active pane
2710 SetSelectionToWindow(new_active
);
2716 // GetPageIndex() returns the index of the page, or -1 if the
2717 // page could not be located in the notebook
2718 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2720 return m_tabs
.GetIdxFromWindow(page_wnd
);
2725 // SetPageText() changes the tab caption of the specified page
2726 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2728 if (page_idx
>= m_tabs
.GetPageCount())
2731 // update our own tab catalog
2732 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2733 page_info
.caption
= text
;
2735 // update what's on screen
2738 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2740 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2741 info
.caption
= text
;
2749 // returns the page caption
2750 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2752 if (page_idx
>= m_tabs
.GetPageCount())
2753 return wxEmptyString
;
2755 // update our own tab catalog
2756 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2757 return page_info
.caption
;
2760 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2762 if (page_idx
>= m_tabs
.GetPageCount())
2765 // update our own tab catalog
2766 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2767 page_info
.bitmap
= bitmap
;
2769 // tab height might have changed
2770 UpdateTabCtrlHeight();
2772 // update what's on screen
2775 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2777 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2778 info
.bitmap
= bitmap
;
2786 // returns the page bitmap
2787 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2789 if (page_idx
>= m_tabs
.GetPageCount())
2792 // update our own tab catalog
2793 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2794 return page_info
.bitmap
;
2797 // GetSelection() returns the index of the currently active page
2798 int wxAuiNotebook::GetSelection() const
2803 // SetSelection() sets the currently active page
2804 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2806 // don't change the page unless necessary
2807 if ((int)new_page
== m_curpage
)
2810 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2814 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2815 evt
.SetSelection(new_page
);
2816 evt
.SetOldSelection(m_curpage
);
2817 evt
.SetEventObject(this);
2818 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2820 int old_curpage
= m_curpage
;
2821 m_curpage
= new_page
;
2823 // program allows the page change
2824 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2825 (void)GetEventHandler()->ProcessEvent(evt
);
2830 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2832 m_tabs
.SetActivePage(wnd
);
2834 ctrl
->SetActivePage(ctrl_idx
);
2841 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2842 size_t i
, pane_count
= all_panes
.GetCount();
2843 for (i
= 0; i
< pane_count
; ++i
)
2845 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2846 if (pane
.name
== wxT("dummy"))
2848 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2849 if (tabctrl
!= ctrl
)
2850 tabctrl
->SetSelectedFont(m_normal_font
);
2852 tabctrl
->SetSelectedFont(m_selected_font
);
2865 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2867 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2868 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2873 // GetPageCount() returns the total number of
2874 // pages managed by the multi-notebook
2875 size_t wxAuiNotebook::GetPageCount() const
2877 return m_tabs
.GetPageCount();
2880 // GetPage() returns the wxWindow pointer of the
2882 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2884 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2886 return m_tabs
.GetWindowFromIdx(page_idx
);
2889 // DoSizing() performs all sizing operations in each tab control
2890 void wxAuiNotebook::DoSizing()
2892 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2893 size_t i
, pane_count
= all_panes
.GetCount();
2894 for (i
= 0; i
< pane_count
; ++i
)
2896 if (all_panes
.Item(i
).name
== wxT("dummy"))
2899 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2900 tabframe
->DoSizing();
2904 // GetActiveTabCtrl() returns the active tab control. It is
2905 // called to determine which control gets new windows being added
2906 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2908 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2913 // find the tab ctrl with the current page
2914 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2921 // no current page, just find the first tab ctrl
2922 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2923 size_t i
, pane_count
= all_panes
.GetCount();
2924 for (i
= 0; i
< pane_count
; ++i
)
2926 if (all_panes
.Item(i
).name
== wxT("dummy"))
2929 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2930 return tabframe
->m_tabs
;
2933 // If there is no tabframe at all, create one
2934 wxTabFrame
* tabframe
= new wxTabFrame
;
2935 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2936 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2941 tabframe
->m_tabs
->SetFlags(m_flags
);
2942 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2943 m_mgr
.AddPane(tabframe
,
2944 wxAuiPaneInfo().Center().CaptionVisible(false));
2948 return tabframe
->m_tabs
;
2951 // FindTab() finds the tab control that currently contains the window as well
2952 // as the index of the window in the tab control. It returns true if the
2953 // window was found, otherwise false.
2954 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2956 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2957 size_t i
, pane_count
= all_panes
.GetCount();
2958 for (i
= 0; i
< pane_count
; ++i
)
2960 if (all_panes
.Item(i
).name
== wxT("dummy"))
2963 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2965 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2968 *ctrl
= tabframe
->m_tabs
;
2977 void wxAuiNotebook::Split(size_t page
, int direction
)
2979 wxSize cli_size
= GetClientSize();
2981 // get the page's window pointer
2982 wxWindow
* wnd
= GetPage(page
);
2986 // notebooks with 1 or less pages can't be split
2987 if (GetPageCount() < 2)
2990 // find out which tab control the page currently belongs to
2991 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
2994 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
2996 if (!src_tabs
|| src_idx
== -1)
2999 // choose a split size
3001 if (GetPageCount() > 2)
3003 split_size
= CalculateNewSplitSize();
3007 // because there are two panes, always split them
3009 split_size
= GetClientSize();
3015 // create a new tab frame
3016 wxTabFrame
* new_tabs
= new wxTabFrame
;
3017 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3018 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3019 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3024 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3025 new_tabs
->m_tabs
->SetFlags(m_flags
);
3026 dest_tabs
= new_tabs
->m_tabs
;
3028 // create a pane info structure with the information
3029 // about where the pane should be added
3030 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3033 if (direction
== wxLEFT
)
3036 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3038 else if (direction
== wxRIGHT
)
3041 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3043 else if (direction
== wxTOP
)
3046 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3048 else if (direction
== wxBOTTOM
)
3051 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3054 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3057 // remove the page from the source tabs
3058 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3059 page_info
.active
= false;
3060 src_tabs
->RemovePage(page_info
.window
);
3061 if (src_tabs
->GetPageCount() > 0)
3063 src_tabs
->SetActivePage((size_t)0);
3064 src_tabs
->DoShowHide();
3065 src_tabs
->Refresh();
3069 // add the page to the destination tabs
3070 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3072 if (src_tabs
->GetPageCount() == 0)
3074 RemoveEmptyTabFrames();
3078 dest_tabs
->DoShowHide();
3079 dest_tabs
->Refresh();
3081 // force the set selection function reset the selection
3084 // set the active page to the one we just split off
3085 SetSelectionToPage(page_info
);
3087 UpdateHintWindowSize();
3091 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3093 UpdateHintWindowSize();
3098 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3100 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3102 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3103 wxASSERT(ctrl
!= NULL
);
3105 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3106 wxASSERT(wnd
!= NULL
);
3108 SetSelectionToWindow(wnd
);
3111 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3116 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3118 wxPoint screen_pt
= ::wxGetMousePosition();
3119 wxPoint client_pt
= ScreenToClient(screen_pt
);
3122 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3123 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3125 if (dest_tabs
== src_tabs
)
3129 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3132 // always hide the hint for inner-tabctrl drag
3135 // if tab moving is not allowed, leave
3136 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3141 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3142 wxWindow
* dest_location_tab
;
3144 // this is an inner-tab drag/reposition
3145 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3147 int src_idx
= evt
.GetSelection();
3148 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3150 // prevent jumpy drag
3151 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3152 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3153 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3155 m_last_drag_x
= pt
.x
;
3160 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3161 dest_tabs
->MovePage(src_tab
, dest_idx
);
3162 dest_tabs
->SetActivePage((size_t)dest_idx
);
3163 dest_tabs
->DoShowHide();
3164 dest_tabs
->Refresh();
3165 m_last_drag_x
= pt
.x
;
3173 // if external drag is allowed, check if the tab is being dragged
3174 // over a different wxAuiNotebook control
3175 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3177 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3179 // if we aren't over any window, stop here
3183 // make sure we are not over the hint window
3184 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3188 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3190 tab_ctrl
= tab_ctrl
->GetParent();
3195 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3199 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3200 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3201 m_mgr
.ShowHint(hint_rect
);
3210 // we are either over a hint window, or not over a tab
3211 // window, and there is no where to drag to, so exit
3218 // if there are less than two panes, split can't happen, so leave
3219 if (m_tabs
.GetPageCount() < 2)
3222 // if tab moving is not allowed, leave
3223 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3229 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3235 wxRect hint_rect
= dest_tabs
->GetRect();
3236 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3237 m_mgr
.ShowHint(hint_rect
);
3241 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3247 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3249 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3254 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3255 wxCHECK_RET( src_tabs
, _T("no source object?") );
3257 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3259 // get the mouse position, which will be used to determine the drop point
3260 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3261 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3265 // check for an external move
3266 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3268 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3272 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3274 tab_ctrl
= tab_ctrl
->GetParent();
3279 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3283 // find out from the destination control
3284 // if it's ok to drop this tab here
3285 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3286 e
.SetSelection(evt
.GetSelection());
3287 e
.SetOldSelection(evt
.GetSelection());
3288 e
.SetEventObject(this);
3289 e
.SetDragSource(this);
3290 e
.Veto(); // dropping must be explicitly approved by control owner
3292 nb
->GetEventHandler()->ProcessEvent(e
);
3296 // no answer or negative answer
3302 int src_idx
= evt
.GetSelection();
3303 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3305 // get main index of the page
3306 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3307 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3310 // make a copy of the page info
3311 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3313 // remove the page from the source notebook
3314 RemovePage(main_idx
);
3316 // reparent the page
3317 src_page
->Reparent(nb
);
3320 // found out the insert idx
3321 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3322 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3324 wxWindow
* target
= NULL
;
3325 int insert_idx
= -1;
3326 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3329 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3333 // add the page to the new notebook
3334 if (insert_idx
== -1)
3335 insert_idx
= dest_tabs
->GetPageCount();
3336 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3337 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3340 dest_tabs
->DoShowHide();
3341 dest_tabs
->Refresh();
3343 // set the selection in the destination tab control
3344 nb
->SetSelectionToPage(page_info
);
3354 // only perform a tab split if it's allowed
3355 wxAuiTabCtrl
* dest_tabs
= NULL
;
3357 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3359 // If the pointer is in an existing tab frame, do a tab insert
3360 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3361 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3362 int insert_idx
= -1;
3365 dest_tabs
= tab_frame
->m_tabs
;
3367 if (dest_tabs
== src_tabs
)
3371 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3372 wxWindow
* target
= NULL
;
3373 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3376 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3382 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3387 // there is no suitable drop location here, exit out
3391 // If there is no tabframe at all, create one
3392 wxTabFrame
* new_tabs
= new wxTabFrame
;
3393 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3394 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3395 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3400 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3401 new_tabs
->m_tabs
->SetFlags(m_flags
);
3403 m_mgr
.AddPane(new_tabs
,
3404 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3407 dest_tabs
= new_tabs
->m_tabs
;
3412 // remove the page from the source tabs
3413 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3414 page_info
.active
= false;
3415 src_tabs
->RemovePage(page_info
.window
);
3416 if (src_tabs
->GetPageCount() > 0)
3418 src_tabs
->SetActivePage((size_t)0);
3419 src_tabs
->DoShowHide();
3420 src_tabs
->Refresh();
3425 // add the page to the destination tabs
3426 if (insert_idx
== -1)
3427 insert_idx
= dest_tabs
->GetPageCount();
3428 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3430 if (src_tabs
->GetPageCount() == 0)
3432 RemoveEmptyTabFrames();
3436 dest_tabs
->DoShowHide();
3437 dest_tabs
->Refresh();
3439 // force the set selection function reset the selection
3442 // set the active page to the one we just split off
3443 SetSelectionToPage(page_info
);
3445 UpdateHintWindowSize();
3451 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3453 // if we've just removed the last tab from the source
3454 // tab set, the remove the tab control completely
3455 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3456 size_t i
, pane_count
= all_panes
.GetCount();
3457 for (i
= 0; i
< pane_count
; ++i
)
3459 if (all_panes
.Item(i
).name
== wxT("dummy"))
3462 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3463 if (tabframe
->m_tab_rect
.Contains(pt
))
3464 return tabframe
->m_tabs
;
3470 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3472 // if we've just removed the last tab from the source
3473 // tab set, the remove the tab control completely
3474 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3475 size_t i
, pane_count
= all_panes
.GetCount();
3476 for (i
= 0; i
< pane_count
; ++i
)
3478 if (all_panes
.Item(i
).name
== wxT("dummy"))
3481 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3482 if (tabframe
->m_tabs
== tab_ctrl
)
3491 void wxAuiNotebook::RemoveEmptyTabFrames()
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
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3503 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3505 m_mgr
.DetachPane(tab_frame
);
3507 // use pending delete because sometimes during
3508 // window closing, refreshs are pending
3509 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3510 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3511 //tab_frame->m_tabs->Destroy();
3518 // check to see if there is still a center pane;
3519 // if there isn't, make a frame the center pane
3520 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3521 pane_count
= panes
.GetCount();
3522 wxWindow
* first_good
= NULL
;
3523 bool center_found
= false;
3524 for (i
= 0; i
< pane_count
; ++i
)
3526 if (panes
.Item(i
).name
== wxT("dummy"))
3528 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3529 center_found
= true;
3531 first_good
= panes
.Item(i
).window
;
3534 if (!center_found
&& first_good
)
3536 m_mgr
.GetPane(first_good
).Centre();
3542 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3544 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3545 if (idx
!= -1 && idx
!= m_curpage
)
3552 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3554 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3555 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3557 int button_id
= evt
.GetInt();
3559 if (button_id
== wxAUI_BUTTON_CLOSE
)
3561 int selection
= tabs
->GetActivePage();
3563 if (selection
!= -1)
3565 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3568 // ask owner if it's ok to close the tab
3569 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3570 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3571 e
.SetOldSelection(evt
.GetSelection());
3572 e
.SetEventObject(this);
3573 GetEventHandler()->ProcessEvent(e
);
3578 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3584 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3585 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3587 DeletePage(main_idx
);