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;
2240 void SetTabCtrlHeight(int h
)
2242 m_tab_ctrl_height
= h
;
2245 void DoSetSize(int x
, int y
,
2246 int width
, int height
,
2247 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2249 m_rect
= wxRect(x
, y
, width
, height
);
2253 void DoGetClientSize(int* x
, int* y
) const
2259 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2266 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2267 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2268 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2272 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2273 size_t i
, page_count
= pages
.GetCount();
2275 for (i
= 0; i
< page_count
; ++i
)
2277 wxAuiNotebookPage
& page
= pages
.Item(i
);
2278 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2279 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2281 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2283 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2284 wnd
->ApplyMDIChildFrameRect();
2289 void DoGetSize(int* x
, int* y
) const
2292 *x
= m_rect
.GetWidth();
2294 *y
= m_rect
.GetHeight();
2306 wxAuiTabCtrl
* m_tabs
;
2307 int m_tab_ctrl_height
;
2311 const int wxAuiBaseTabCtrlId
= 5380;
2314 // -- wxAuiNotebook class implementation --
2316 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2317 EVT_SIZE(wxAuiNotebook::OnSize
)
2318 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2319 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2320 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2321 wxAuiNotebook::OnTabClicked
)
2322 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2323 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2324 wxAuiNotebook::OnTabBeginDrag
)
2325 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2326 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2327 wxAuiNotebook::OnTabEndDrag
)
2328 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2329 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2330 wxAuiNotebook::OnTabDragMotion
)
2331 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2332 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2333 wxAuiNotebook::OnTabButton
)
2336 wxAuiNotebook::wxAuiNotebook()
2339 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2341 m_tab_ctrl_height
= 20;
2342 m_requested_bmp_size
= wxDefaultSize
;
2343 m_requested_tabctrl_height
= -1;
2346 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2350 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2353 m_requested_bmp_size
= wxDefaultSize
;
2354 m_requested_tabctrl_height
= -1;
2355 InitNotebook(style
);
2358 bool wxAuiNotebook::Create(wxWindow
* parent
,
2364 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2367 InitNotebook(style
);
2372 // InitNotebook() contains common initialization
2373 // code called by all constructors
2374 void wxAuiNotebook::InitNotebook(long style
)
2377 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2379 m_flags
= (unsigned int)style
;
2380 m_tab_ctrl_height
= 20;
2382 m_normal_font
= *wxNORMAL_FONT
;
2383 m_selected_font
= *wxNORMAL_FONT
;
2384 m_selected_font
.SetWeight(wxBOLD
);
2386 SetArtProvider(new wxAuiDefaultTabArt
);
2388 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2389 m_dummy_wnd
->SetSize(200, 200);
2390 m_dummy_wnd
->Show(false);
2392 m_mgr
.SetManagedWindow(this);
2393 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2394 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2396 m_mgr
.AddPane(m_dummy_wnd
,
2397 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2402 wxAuiNotebook::~wxAuiNotebook()
2407 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2409 m_tabs
.SetArtProvider(art
);
2411 UpdateTabCtrlHeight();
2414 // SetTabCtrlHeight() is the highest-level override of the
2415 // tab height. A call to this function effectively enforces a
2416 // specified tab ctrl height, overriding all other considerations,
2417 // such as text or bitmap height. It overrides any call to
2418 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2419 // any previous call and returns to the default behavior
2421 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2423 m_requested_tabctrl_height
= height
;
2425 // if window is already initialized, recalculate the tab height
2428 UpdateTabCtrlHeight();
2433 // SetUniformBitmapSize() ensures that all tabs will have
2434 // the same height, even if some tabs don't have bitmaps
2435 // Passing wxDefaultSize to this function will instruct
2436 // the control to use dynamic tab height-- so when a tab
2437 // with a large bitmap is added, the tab ctrl's height will
2438 // automatically increase to accommodate the bitmap
2440 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2442 m_requested_bmp_size
= size
;
2444 // if window is already initialized, recalculate the tab height
2447 UpdateTabCtrlHeight();
2451 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2452 // to be used interally
2453 void wxAuiNotebook::UpdateTabCtrlHeight()
2455 // get the tab ctrl height we will use
2456 int height
= CalculateTabCtrlHeight();
2458 // if the tab control height needs to change, update
2459 // all of our tab controls with the new height
2460 if (m_tab_ctrl_height
!= height
)
2462 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2464 m_tab_ctrl_height
= height
;
2466 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2467 size_t i
, pane_count
= all_panes
.GetCount();
2468 for (i
= 0; i
< pane_count
; ++i
)
2470 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2471 if (pane
.name
== wxT("dummy"))
2473 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2474 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2475 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2476 tabctrl
->SetArtProvider(art
->Clone());
2477 tab_frame
->DoSizing();
2482 void wxAuiNotebook::UpdateHintWindowSize()
2484 wxSize size
= CalculateNewSplitSize();
2486 // the placeholder hint window should be set to this size
2487 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2491 info
.BestSize(size
);
2492 m_dummy_wnd
->SetSize(size
);
2497 // calculates the size of the new split
2498 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2500 // count number of tab controls
2501 int tab_ctrl_count
= 0;
2502 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2503 size_t i
, pane_count
= all_panes
.GetCount();
2504 for (i
= 0; i
< pane_count
; ++i
)
2506 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2507 if (pane
.name
== wxT("dummy"))
2512 wxSize new_split_size
;
2514 // if there is only one tab control, the first split
2515 // should happen around the middle
2516 if (tab_ctrl_count
< 2)
2518 new_split_size
= GetClientSize();
2519 new_split_size
.x
/= 2;
2520 new_split_size
.y
/= 2;
2524 // this is in place of a more complicated calculation
2525 // that needs to be implemented
2526 new_split_size
= wxSize(180,180);
2529 return new_split_size
;
2532 int wxAuiNotebook::CalculateTabCtrlHeight()
2534 // if a fixed tab ctrl height is specified,
2535 // just return that instead of calculating a
2537 if (m_requested_tabctrl_height
!= -1)
2538 return m_requested_tabctrl_height
;
2540 // find out new best tab height
2541 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2543 return art
->GetBestTabCtrlSize(this,
2545 m_requested_bmp_size
);
2549 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2551 return m_tabs
.GetArtProvider();
2554 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2556 wxControl::SetWindowStyleFlag(style
);
2558 m_flags
= (unsigned int)style
;
2560 // if the control is already initialized
2561 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2563 // let all of the tab children know about the new style
2565 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2566 size_t i
, pane_count
= all_panes
.GetCount();
2567 for (i
= 0; i
< pane_count
; ++i
)
2569 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2570 if (pane
.name
== wxT("dummy"))
2572 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2573 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2574 tabctrl
->SetFlags(m_flags
);
2575 tabframe
->DoSizing();
2583 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2584 const wxString
& caption
,
2586 const wxBitmap
& bitmap
)
2588 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2591 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2593 const wxString
& caption
,
2595 const wxBitmap
& bitmap
)
2597 wxAuiNotebookPage info
;
2599 info
.caption
= caption
;
2600 info
.bitmap
= bitmap
;
2601 info
.active
= false;
2603 // if there are currently no tabs, the first added
2604 // tab must be active
2605 if (m_tabs
.GetPageCount() == 0)
2608 m_tabs
.InsertPage(page
, info
, page_idx
);
2610 // if that was the first page added, even if
2611 // select is false, it must become the "current page"
2612 // (though no select events will be fired)
2613 if (!select
&& m_tabs
.GetPageCount() == 1)
2615 //m_curpage = GetPageIndex(page);
2617 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2618 if (page_idx
>= active_tabctrl
->GetPageCount())
2619 active_tabctrl
->AddPage(page
, info
);
2621 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2623 UpdateTabCtrlHeight();
2625 active_tabctrl
->DoShowHide();
2629 SetSelectionToWindow(page
);
2636 // DeletePage() removes a tab from the multi-notebook,
2637 // and destroys the window as well
2638 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2640 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2642 if (!RemovePage(page_idx
))
2645 // actually destroy the window now
2646 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2648 // delete the child frame with pending delete, as is
2649 // customary with frame windows
2650 if (!wxPendingDelete
.Member(wnd
))
2651 wxPendingDelete
.Append(wnd
);
2663 // RemovePage() removes a tab from the multi-notebook,
2664 // but does not destroy the window
2665 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2667 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2668 wxWindow
* new_active
= NULL
;
2670 // find out which onscreen tab ctrl owns this tab
2673 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2676 // find a new page and set it as active
2677 int new_idx
= ctrl_idx
+1;
2678 if (new_idx
>= (int)ctrl
->GetPageCount())
2679 new_idx
= ctrl_idx
-1;
2681 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2683 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2687 // set the active page to the first page that
2688 // isn't the one being deleted
2689 size_t i
, page_count
= m_tabs
.GetPageCount();
2690 for (i
= 0; i
< page_count
; ++i
)
2692 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2695 new_active
= m_tabs
.GetWindowFromIdx(i
);
2701 // remove the tab from main catalog
2702 if (!m_tabs
.RemovePage(wnd
))
2705 // remove the tab from the onscreen tab ctrl
2706 ctrl
->RemovePage(wnd
);
2709 RemoveEmptyTabFrames();
2711 // set new active pane
2715 SetSelectionToWindow(new_active
);
2721 // GetPageIndex() returns the index of the page, or -1 if the
2722 // page could not be located in the notebook
2723 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2725 return m_tabs
.GetIdxFromWindow(page_wnd
);
2730 // SetPageText() changes the tab caption of the specified page
2731 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2733 if (page_idx
>= m_tabs
.GetPageCount())
2736 // update our own tab catalog
2737 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2738 page_info
.caption
= text
;
2740 // update what's on screen
2743 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2745 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2746 info
.caption
= text
;
2754 // returns the page caption
2755 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2757 if (page_idx
>= m_tabs
.GetPageCount())
2758 return wxEmptyString
;
2760 // update our own tab catalog
2761 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2762 return page_info
.caption
;
2765 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2767 if (page_idx
>= m_tabs
.GetPageCount())
2770 // update our own tab catalog
2771 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2772 page_info
.bitmap
= bitmap
;
2774 // tab height might have changed
2775 UpdateTabCtrlHeight();
2777 // update what's on screen
2780 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2782 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2783 info
.bitmap
= bitmap
;
2791 // returns the page bitmap
2792 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2794 if (page_idx
>= m_tabs
.GetPageCount())
2797 // update our own tab catalog
2798 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2799 return page_info
.bitmap
;
2802 // GetSelection() returns the index of the currently active page
2803 int wxAuiNotebook::GetSelection() const
2808 // SetSelection() sets the currently active page
2809 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2811 // don't change the page unless necessary
2812 if ((int)new_page
== m_curpage
)
2815 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2819 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2820 evt
.SetSelection(new_page
);
2821 evt
.SetOldSelection(m_curpage
);
2822 evt
.SetEventObject(this);
2823 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2825 int old_curpage
= m_curpage
;
2826 m_curpage
= new_page
;
2828 // program allows the page change
2829 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2830 (void)GetEventHandler()->ProcessEvent(evt
);
2835 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2837 m_tabs
.SetActivePage(wnd
);
2839 ctrl
->SetActivePage(ctrl_idx
);
2846 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2847 size_t i
, pane_count
= all_panes
.GetCount();
2848 for (i
= 0; i
< pane_count
; ++i
)
2850 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2851 if (pane
.name
== wxT("dummy"))
2853 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2854 if (tabctrl
!= ctrl
)
2855 tabctrl
->SetSelectedFont(m_normal_font
);
2857 tabctrl
->SetSelectedFont(m_selected_font
);
2870 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2872 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2873 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2878 // GetPageCount() returns the total number of
2879 // pages managed by the multi-notebook
2880 size_t wxAuiNotebook::GetPageCount() const
2882 return m_tabs
.GetPageCount();
2885 // GetPage() returns the wxWindow pointer of the
2887 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2889 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2891 return m_tabs
.GetWindowFromIdx(page_idx
);
2894 // DoSizing() performs all sizing operations in each tab control
2895 void wxAuiNotebook::DoSizing()
2897 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2898 size_t i
, pane_count
= all_panes
.GetCount();
2899 for (i
= 0; i
< pane_count
; ++i
)
2901 if (all_panes
.Item(i
).name
== wxT("dummy"))
2904 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2905 tabframe
->DoSizing();
2909 // GetActiveTabCtrl() returns the active tab control. It is
2910 // called to determine which control gets new windows being added
2911 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2913 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2918 // find the tab ctrl with the current page
2919 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2926 // no current page, just find the first tab ctrl
2927 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2928 size_t i
, pane_count
= all_panes
.GetCount();
2929 for (i
= 0; i
< pane_count
; ++i
)
2931 if (all_panes
.Item(i
).name
== wxT("dummy"))
2934 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2935 return tabframe
->m_tabs
;
2938 // If there is no tabframe at all, create one
2939 wxTabFrame
* tabframe
= new wxTabFrame
;
2940 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2941 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2946 tabframe
->m_tabs
->SetFlags(m_flags
);
2947 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2948 m_mgr
.AddPane(tabframe
,
2949 wxAuiPaneInfo().Center().CaptionVisible(false));
2953 return tabframe
->m_tabs
;
2956 // FindTab() finds the tab control that currently contains the window as well
2957 // as the index of the window in the tab control. It returns true if the
2958 // window was found, otherwise false.
2959 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2961 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2962 size_t i
, pane_count
= all_panes
.GetCount();
2963 for (i
= 0; i
< pane_count
; ++i
)
2965 if (all_panes
.Item(i
).name
== wxT("dummy"))
2968 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2970 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2973 *ctrl
= tabframe
->m_tabs
;
2982 void wxAuiNotebook::Split(size_t page
, int direction
)
2984 wxSize cli_size
= GetClientSize();
2986 // get the page's window pointer
2987 wxWindow
* wnd
= GetPage(page
);
2991 // notebooks with 1 or less pages can't be split
2992 if (GetPageCount() < 2)
2995 // find out which tab control the page currently belongs to
2996 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
2999 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3001 if (!src_tabs
|| src_idx
== -1)
3004 // choose a split size
3006 if (GetPageCount() > 2)
3008 split_size
= CalculateNewSplitSize();
3012 // because there are two panes, always split them
3014 split_size
= GetClientSize();
3020 // create a new tab frame
3021 wxTabFrame
* new_tabs
= new wxTabFrame
;
3022 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3023 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3024 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3029 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3030 new_tabs
->m_tabs
->SetFlags(m_flags
);
3031 dest_tabs
= new_tabs
->m_tabs
;
3033 // create a pane info structure with the information
3034 // about where the pane should be added
3035 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3038 if (direction
== wxLEFT
)
3041 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3043 else if (direction
== wxRIGHT
)
3046 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3048 else if (direction
== wxTOP
)
3051 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3053 else if (direction
== wxBOTTOM
)
3056 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3059 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3062 // remove the page from the source tabs
3063 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3064 page_info
.active
= false;
3065 src_tabs
->RemovePage(page_info
.window
);
3066 if (src_tabs
->GetPageCount() > 0)
3068 src_tabs
->SetActivePage((size_t)0);
3069 src_tabs
->DoShowHide();
3070 src_tabs
->Refresh();
3074 // add the page to the destination tabs
3075 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3077 if (src_tabs
->GetPageCount() == 0)
3079 RemoveEmptyTabFrames();
3083 dest_tabs
->DoShowHide();
3084 dest_tabs
->Refresh();
3086 // force the set selection function reset the selection
3089 // set the active page to the one we just split off
3090 SetSelectionToPage(page_info
);
3092 UpdateHintWindowSize();
3096 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3098 UpdateHintWindowSize();
3103 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3105 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3107 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3108 wxASSERT(ctrl
!= NULL
);
3110 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3111 wxASSERT(wnd
!= NULL
);
3113 SetSelectionToWindow(wnd
);
3116 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3121 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3123 wxPoint screen_pt
= ::wxGetMousePosition();
3124 wxPoint client_pt
= ScreenToClient(screen_pt
);
3127 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3128 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3130 if (dest_tabs
== src_tabs
)
3134 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3137 // always hide the hint for inner-tabctrl drag
3140 // if tab moving is not allowed, leave
3141 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3146 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3147 wxWindow
* dest_location_tab
;
3149 // this is an inner-tab drag/reposition
3150 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3152 int src_idx
= evt
.GetSelection();
3153 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3155 // prevent jumpy drag
3156 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3157 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3158 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3160 m_last_drag_x
= pt
.x
;
3165 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3166 dest_tabs
->MovePage(src_tab
, dest_idx
);
3167 dest_tabs
->SetActivePage((size_t)dest_idx
);
3168 dest_tabs
->DoShowHide();
3169 dest_tabs
->Refresh();
3170 m_last_drag_x
= pt
.x
;
3178 // if external drag is allowed, check if the tab is being dragged
3179 // over a different wxAuiNotebook control
3180 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3182 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3184 // if we aren't over any window, stop here
3188 // make sure we are not over the hint window
3189 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3193 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3195 tab_ctrl
= tab_ctrl
->GetParent();
3200 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3204 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3205 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3206 m_mgr
.ShowHint(hint_rect
);
3215 // we are either over a hint window, or not over a tab
3216 // window, and there is no where to drag to, so exit
3223 // if there are less than two panes, split can't happen, so leave
3224 if (m_tabs
.GetPageCount() < 2)
3227 // if tab moving is not allowed, leave
3228 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3234 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3240 wxRect hint_rect
= dest_tabs
->GetRect();
3241 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3242 m_mgr
.ShowHint(hint_rect
);
3246 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3252 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3254 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3259 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3260 wxCHECK_RET( src_tabs
, _T("no source object?") );
3262 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3264 // get the mouse position, which will be used to determine the drop point
3265 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3266 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3270 // check for an external move
3271 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3273 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3277 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3279 tab_ctrl
= tab_ctrl
->GetParent();
3284 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3288 // find out from the destination control
3289 // if it's ok to drop this tab here
3290 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3291 e
.SetSelection(evt
.GetSelection());
3292 e
.SetOldSelection(evt
.GetSelection());
3293 e
.SetEventObject(this);
3294 e
.SetDragSource(this);
3295 e
.Veto(); // dropping must be explicitly approved by control owner
3297 nb
->GetEventHandler()->ProcessEvent(e
);
3301 // no answer or negative answer
3307 int src_idx
= evt
.GetSelection();
3308 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3310 // get main index of the page
3311 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3312 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3315 // make a copy of the page info
3316 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3318 // remove the page from the source notebook
3319 RemovePage(main_idx
);
3321 // reparent the page
3322 src_page
->Reparent(nb
);
3325 // found out the insert idx
3326 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3327 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3329 wxWindow
* target
= NULL
;
3330 int insert_idx
= -1;
3331 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3334 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3338 // add the page to the new notebook
3339 if (insert_idx
== -1)
3340 insert_idx
= dest_tabs
->GetPageCount();
3341 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3342 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3345 dest_tabs
->DoShowHide();
3346 dest_tabs
->Refresh();
3348 // set the selection in the destination tab control
3349 nb
->SetSelectionToPage(page_info
);
3359 // only perform a tab split if it's allowed
3360 wxAuiTabCtrl
* dest_tabs
= NULL
;
3362 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3364 // If the pointer is in an existing tab frame, do a tab insert
3365 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3366 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3367 int insert_idx
= -1;
3370 dest_tabs
= tab_frame
->m_tabs
;
3372 if (dest_tabs
== src_tabs
)
3376 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3377 wxWindow
* target
= NULL
;
3378 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3381 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3387 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3392 // there is no suitable drop location here, exit out
3396 // If there is no tabframe at all, create one
3397 wxTabFrame
* new_tabs
= new wxTabFrame
;
3398 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3399 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3400 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3405 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3406 new_tabs
->m_tabs
->SetFlags(m_flags
);
3408 m_mgr
.AddPane(new_tabs
,
3409 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3412 dest_tabs
= new_tabs
->m_tabs
;
3417 // remove the page from the source tabs
3418 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3419 page_info
.active
= false;
3420 src_tabs
->RemovePage(page_info
.window
);
3421 if (src_tabs
->GetPageCount() > 0)
3423 src_tabs
->SetActivePage((size_t)0);
3424 src_tabs
->DoShowHide();
3425 src_tabs
->Refresh();
3430 // add the page to the destination tabs
3431 if (insert_idx
== -1)
3432 insert_idx
= dest_tabs
->GetPageCount();
3433 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3435 if (src_tabs
->GetPageCount() == 0)
3437 RemoveEmptyTabFrames();
3441 dest_tabs
->DoShowHide();
3442 dest_tabs
->Refresh();
3444 // force the set selection function reset the selection
3447 // set the active page to the one we just split off
3448 SetSelectionToPage(page_info
);
3450 UpdateHintWindowSize();
3456 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3458 // if we've just removed the last tab from the source
3459 // tab set, the remove the tab control completely
3460 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3461 size_t i
, pane_count
= all_panes
.GetCount();
3462 for (i
= 0; i
< pane_count
; ++i
)
3464 if (all_panes
.Item(i
).name
== wxT("dummy"))
3467 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3468 if (tabframe
->m_tab_rect
.Contains(pt
))
3469 return tabframe
->m_tabs
;
3475 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3477 // if we've just removed the last tab from the source
3478 // tab set, the remove the tab control completely
3479 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3480 size_t i
, pane_count
= all_panes
.GetCount();
3481 for (i
= 0; i
< pane_count
; ++i
)
3483 if (all_panes
.Item(i
).name
== wxT("dummy"))
3486 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3487 if (tabframe
->m_tabs
== tab_ctrl
)
3496 void wxAuiNotebook::RemoveEmptyTabFrames()
3498 // if we've just removed the last tab from the source
3499 // tab set, the remove the tab control completely
3500 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3501 size_t i
, pane_count
= all_panes
.GetCount();
3502 for (i
= 0; i
< pane_count
; ++i
)
3504 if (all_panes
.Item(i
).name
== wxT("dummy"))
3507 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3508 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3510 m_mgr
.DetachPane(tab_frame
);
3512 // use pending delete because sometimes during
3513 // window closing, refreshs are pending
3514 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3515 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3516 //tab_frame->m_tabs->Destroy();
3523 // check to see if there is still a center pane;
3524 // if there isn't, make a frame the center pane
3525 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3526 pane_count
= panes
.GetCount();
3527 wxWindow
* first_good
= NULL
;
3528 bool center_found
= false;
3529 for (i
= 0; i
< pane_count
; ++i
)
3531 if (panes
.Item(i
).name
== wxT("dummy"))
3533 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3534 center_found
= true;
3536 first_good
= panes
.Item(i
).window
;
3539 if (!center_found
&& first_good
)
3541 m_mgr
.GetPane(first_good
).Centre();
3547 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3549 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3550 if (idx
!= -1 && idx
!= m_curpage
)
3557 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3559 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3560 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3562 int button_id
= evt
.GetInt();
3564 if (button_id
== wxAUI_BUTTON_CLOSE
)
3566 int selection
= tabs
->GetActivePage();
3568 if (selection
!= -1)
3570 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3573 // ask owner if it's ok to close the tab
3574 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3575 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3576 e
.SetOldSelection(evt
.GetSelection());
3577 e
.SetEventObject(this);
3578 GetEventHandler()->ProcessEvent(e
);
3583 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3589 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3590 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3592 DeletePage(main_idx
);