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 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
672 if (active_idx
!= -1)
674 menuPopup
.Check(1000+active_idx
, true);
677 // find out where to put the popup menu of window items
678 wxPoint pt
= ::wxGetMousePosition();
679 pt
= wnd
->ScreenToClient(pt
);
681 // find out the screen coordinate at the bottom of the tab ctrl
682 wxRect cli_rect
= wnd
->GetClientRect();
683 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
685 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
686 wnd
->PushEventHandler(cc
);
687 wnd
->PopupMenu(&menuPopup
, pt
);
688 int command
= cc
->GetCommandId();
689 wnd
->PopEventHandler(true);
697 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
698 const wxAuiNotebookPageArray
& pages
,
699 const wxSize
& required_bmp_size
)
702 dc
.SetFont(m_measuring_font
);
704 // sometimes a standard bitmap size needs to be enforced, especially
705 // if some tabs have bitmaps and others don't. This is important because
706 // it prevents the tab control from resizing when tabs are added.
707 wxBitmap measure_bmp
;
708 if (required_bmp_size
.IsFullySpecified())
710 measure_bmp
.Create(required_bmp_size
.x
,
711 required_bmp_size
.y
);
716 size_t i
, page_count
= pages
.GetCount();
717 for (i
= 0; i
< page_count
; ++i
)
719 wxAuiNotebookPage
& page
= pages
.Item(i
);
722 if (measure_bmp
.IsOk())
727 // we don't use the caption text because we don't
728 // want tab heights to be different in the case
729 // of a very short piece of text on one tab and a very
730 // tall piece of text on another tab
732 wxSize s
= GetTabSize(dc
,
737 wxAUI_BUTTON_STATE_HIDDEN
,
740 max_y
= wxMax(max_y
, s
.y
);
746 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
748 m_normal_font
= font
;
751 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
753 m_selected_font
= font
;
756 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
758 m_measuring_font
= font
;
762 // -- wxAuiSimpleTabArt class implementation --
764 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
766 m_normal_font
= *wxNORMAL_FONT
;
767 m_selected_font
= *wxNORMAL_FONT
;
768 m_selected_font
.SetWeight(wxBOLD
);
769 m_measuring_font
= m_selected_font
;
772 m_fixed_tab_width
= 100;
774 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
776 wxColour background_colour
= base_colour
;
777 wxColour normaltab_colour
= base_colour
;
778 wxColour selectedtab_colour
= *wxWHITE
;
780 m_bkbrush
= wxBrush(background_colour
);
781 m_normal_bkbrush
= wxBrush(normaltab_colour
);
782 m_normal_bkpen
= wxPen(normaltab_colour
);
783 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
784 m_selected_bkpen
= wxPen(selectedtab_colour
);
786 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
787 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
789 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
790 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
792 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
793 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
795 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
796 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
800 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
804 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
806 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
810 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
815 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
818 m_fixed_tab_width
= 100;
820 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
822 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
823 tot_width
-= m_active_close_bmp
.GetWidth();
824 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
825 tot_width
-= m_active_windowlist_bmp
.GetWidth();
829 m_fixed_tab_width
= tot_width
/(int)tab_count
;
833 if (m_fixed_tab_width
< 100)
834 m_fixed_tab_width
= 100;
836 if (m_fixed_tab_width
> tot_width
/2)
837 m_fixed_tab_width
= tot_width
/2;
839 if (m_fixed_tab_width
> 220)
840 m_fixed_tab_width
= 220;
843 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
844 wxWindow
* WXUNUSED(wnd
),
848 dc
.SetBrush(m_bkbrush
);
849 dc
.SetPen(*wxTRANSPARENT_PEN
);
850 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
853 dc
.SetPen(*wxGREY_PEN
);
854 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
858 // DrawTab() draws an individual tab.
861 // in_rect - rectangle the tab should be confined to
862 // caption - tab's caption
863 // active - whether or not the tab is active
864 // out_rect - actual output rectangle
865 // x_extent - the advance x; where the next tab should start
867 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
869 const wxAuiNotebookPage
& page
,
870 const wxRect
& in_rect
,
871 int close_button_state
,
872 wxRect
* out_tab_rect
,
873 wxRect
* out_button_rect
,
876 wxCoord normal_textx
, normal_texty
;
877 wxCoord selected_textx
, selected_texty
;
878 wxCoord textx
, texty
;
880 // if the caption is empty, measure some temporary text
881 wxString caption
= page
.caption
;
885 dc
.SetFont(m_selected_font
);
886 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
888 dc
.SetFont(m_normal_font
);
889 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
891 // figure out the size of the tab
892 wxSize tab_size
= GetTabSize(dc
,
900 wxCoord tab_height
= tab_size
.y
;
901 wxCoord tab_width
= tab_size
.x
;
902 wxCoord tab_x
= in_rect
.x
;
903 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
905 caption
= page
.caption
;
907 // select pen, brush and font for the tab to be drawn
911 dc
.SetPen(m_selected_bkpen
);
912 dc
.SetBrush(m_selected_bkbrush
);
913 dc
.SetFont(m_selected_font
);
914 textx
= selected_textx
;
915 texty
= selected_texty
;
919 dc
.SetPen(m_normal_bkpen
);
920 dc
.SetBrush(m_normal_bkbrush
);
921 dc
.SetFont(m_normal_font
);
922 textx
= normal_textx
;
923 texty
= normal_texty
;
931 points
[0].y
= tab_y
+ tab_height
- 1;
932 points
[1].x
= tab_x
+ tab_height
- 3;
933 points
[1].y
= tab_y
+ 2;
934 points
[2].x
= tab_x
+ tab_height
+ 3;
936 points
[3].x
= tab_x
+ tab_width
- 2;
938 points
[4].x
= tab_x
+ tab_width
;
939 points
[4].y
= tab_y
+ 2;
940 points
[5].x
= tab_x
+ tab_width
;
941 points
[5].y
= tab_y
+ tab_height
- 1;
942 points
[6] = points
[0];
944 dc
.SetClippingRegion(in_rect
);
946 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
948 dc
.SetPen(*wxGREY_PEN
);
950 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
951 dc
.DrawLines(WXSIZEOF(points
), points
);
956 int close_button_width
= 0;
957 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
959 close_button_width
= m_active_close_bmp
.GetWidth();
960 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
964 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
967 // set minimum text offset
968 if (text_offset
< tab_x
+ tab_height
)
969 text_offset
= tab_x
+ tab_height
;
971 // chop text if necessary
972 wxString draw_text
= wxAuiChopText(dc
,
974 tab_width
- (text_offset
-tab_x
) - close_button_width
);
977 dc
.DrawText(draw_text
,
979 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
982 // draw close button if necessary
983 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
987 bmp
= m_active_close_bmp
;
989 bmp
= m_disabled_close_bmp
;
991 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
992 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
995 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
997 *out_button_rect
= rect
;
1001 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1003 dc
.DestroyClippingRegion();
1006 int wxAuiSimpleTabArt::GetIndentSize()
1011 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1012 wxWindow
* WXUNUSED(wnd
),
1013 const wxString
& caption
,
1014 const wxBitmap
& WXUNUSED(bitmap
),
1015 bool WXUNUSED(active
),
1016 int close_button_state
,
1019 wxCoord measured_textx
, measured_texty
;
1021 dc
.SetFont(m_measuring_font
);
1022 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1024 wxCoord tab_height
= measured_texty
+ 4;
1025 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1027 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1028 tab_width
+= m_active_close_bmp
.GetWidth();
1030 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1032 tab_width
= m_fixed_tab_width
;
1035 *x_extent
= tab_width
- (tab_height
/2) - 1;
1037 return wxSize(tab_width
, tab_height
);
1041 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1042 wxWindow
* WXUNUSED(wnd
),
1043 const wxRect
& in_rect
,
1054 case wxAUI_BUTTON_CLOSE
:
1055 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1056 bmp
= m_disabled_close_bmp
;
1058 bmp
= m_active_close_bmp
;
1060 case wxAUI_BUTTON_LEFT
:
1061 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1062 bmp
= m_disabled_left_bmp
;
1064 bmp
= m_active_left_bmp
;
1066 case wxAUI_BUTTON_RIGHT
:
1067 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1068 bmp
= m_disabled_right_bmp
;
1070 bmp
= m_active_right_bmp
;
1072 case wxAUI_BUTTON_WINDOWLIST
:
1073 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1074 bmp
= m_disabled_windowlist_bmp
;
1076 bmp
= m_active_windowlist_bmp
;
1085 if (orientation
== wxLEFT
)
1087 rect
.SetX(in_rect
.x
);
1088 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1089 rect
.SetWidth(bmp
.GetWidth());
1090 rect
.SetHeight(bmp
.GetHeight());
1094 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1095 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1096 bmp
.GetWidth(), bmp
.GetHeight());
1100 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1106 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1107 const wxAuiNotebookPageArray
& pages
,
1112 size_t i
, count
= pages
.GetCount();
1113 for (i
= 0; i
< count
; ++i
)
1115 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1116 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1119 if (active_idx
!= -1)
1121 menuPopup
.Check(1000+active_idx
, true);
1124 // find out where to put the popup menu of window
1125 // items. Subtract 100 for now to center the menu
1126 // a bit, until a better mechanism can be implemented
1127 wxPoint pt
= ::wxGetMousePosition();
1128 pt
= wnd
->ScreenToClient(pt
);
1134 // find out the screen coordinate at the bottom of the tab ctrl
1135 wxRect cli_rect
= wnd
->GetClientRect();
1136 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1138 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1139 wnd
->PushEventHandler(cc
);
1140 wnd
->PopupMenu(&menuPopup
, pt
);
1141 int command
= cc
->GetCommandId();
1142 wnd
->PopEventHandler(true);
1144 if (command
>= 1000)
1145 return command
-1000;
1150 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1151 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1152 const wxSize
& WXUNUSED(required_bmp_size
))
1155 dc
.SetFont(m_measuring_font
);
1157 wxSize s
= GetTabSize(dc
,
1162 wxAUI_BUTTON_STATE_HIDDEN
,
1167 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1169 m_normal_font
= font
;
1172 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1174 m_selected_font
= font
;
1177 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1179 m_measuring_font
= font
;
1185 // -- wxAuiTabContainer class implementation --
1188 // wxAuiTabContainer is a class which contains information about each
1189 // tab. It also can render an entire tab control to a specified DC.
1190 // It's not a window class itself, because this code will be used by
1191 // the wxFrameMananger, where it is disadvantageous to have separate
1192 // windows for each tab control in the case of "docked tabs"
1194 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1195 // which can be used as a tab control in the normal sense.
1198 wxAuiTabContainer::wxAuiTabContainer()
1202 m_art
= new wxAuiDefaultTabArt
;
1204 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1205 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1206 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1207 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1210 wxAuiTabContainer::~wxAuiTabContainer()
1215 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1222 m_art
->SetFlags(m_flags
);
1226 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1231 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1235 // check for new close button settings
1236 RemoveButton(wxAUI_BUTTON_LEFT
);
1237 RemoveButton(wxAUI_BUTTON_RIGHT
);
1238 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1239 RemoveButton(wxAUI_BUTTON_CLOSE
);
1242 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1244 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1245 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1248 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1250 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1253 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1255 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1260 m_art
->SetFlags(m_flags
);
1264 unsigned int wxAuiTabContainer::GetFlags() const
1270 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1272 m_art
->SetNormalFont(font
);
1275 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1277 m_art
->SetSelectedFont(font
);
1280 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1282 m_art
->SetMeasuringFont(font
);
1285 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1291 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1295 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1296 const wxAuiNotebookPage
& info
)
1298 wxAuiNotebookPage page_info
;
1300 page_info
.window
= page
;
1302 m_pages
.Add(page_info
);
1304 // let the art provider know how many pages we have
1307 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1313 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1314 const wxAuiNotebookPage
& info
,
1317 wxAuiNotebookPage page_info
;
1319 page_info
.window
= page
;
1321 if (idx
>= m_pages
.GetCount())
1322 m_pages
.Add(page_info
);
1324 m_pages
.Insert(page_info
, idx
);
1326 // let the art provider know how many pages we have
1329 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1335 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1338 int idx
= GetIdxFromWindow(page
);
1342 // get page entry, make a copy of it
1343 wxAuiNotebookPage p
= GetPage(idx
);
1345 // remove old page entry
1348 // insert page where it should be
1349 InsertPage(page
, p
, new_idx
);
1354 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1356 size_t i
, page_count
= m_pages
.GetCount();
1357 for (i
= 0; i
< page_count
; ++i
)
1359 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1360 if (page
.window
== wnd
)
1362 m_pages
.RemoveAt(i
);
1364 // let the art provider know how many pages we have
1367 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1377 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1381 size_t i
, page_count
= m_pages
.GetCount();
1382 for (i
= 0; i
< page_count
; ++i
)
1384 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1385 if (page
.window
== wnd
)
1392 page
.active
= false;
1399 void wxAuiTabContainer::SetNoneActive()
1401 size_t i
, page_count
= m_pages
.GetCount();
1402 for (i
= 0; i
< page_count
; ++i
)
1404 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1405 page
.active
= false;
1409 bool wxAuiTabContainer::SetActivePage(size_t page
)
1411 if (page
>= m_pages
.GetCount())
1414 return SetActivePage(m_pages
.Item(page
).window
);
1417 int wxAuiTabContainer::GetActivePage() const
1419 size_t i
, page_count
= m_pages
.GetCount();
1420 for (i
= 0; i
< page_count
; ++i
)
1422 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1430 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1432 if (idx
>= m_pages
.GetCount())
1435 return m_pages
[idx
].window
;
1438 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1440 size_t i
, page_count
= m_pages
.GetCount();
1441 for (i
= 0; i
< page_count
; ++i
)
1443 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1444 if (page
.window
== wnd
)
1450 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1452 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1454 return m_pages
[idx
];
1457 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1459 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1461 return m_pages
[idx
];
1464 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1469 size_t wxAuiTabContainer::GetPageCount() const
1471 return m_pages
.GetCount();
1474 void wxAuiTabContainer::AddButton(int id
,
1476 const wxBitmap
& normal_bitmap
,
1477 const wxBitmap
& disabled_bitmap
)
1479 wxAuiTabContainerButton button
;
1481 button
.bitmap
= normal_bitmap
;
1482 button
.dis_bitmap
= disabled_bitmap
;
1483 button
.location
= location
;
1484 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1486 m_buttons
.Add(button
);
1489 void wxAuiTabContainer::RemoveButton(int id
)
1491 size_t i
, button_count
= m_buttons
.GetCount();
1493 for (i
= 0; i
< button_count
; ++i
)
1495 if (m_buttons
.Item(i
).id
== id
)
1497 m_buttons
.RemoveAt(i
);
1505 size_t wxAuiTabContainer::GetTabOffset() const
1507 return m_tab_offset
;
1510 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1512 m_tab_offset
= offset
;
1518 // Render() renders the tab catalog to the specified DC
1519 // It is a virtual function and can be overridden to
1520 // provide custom drawing capabilities
1521 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1523 if (!raw_dc
|| !raw_dc
->IsOk())
1529 size_t page_count
= m_pages
.GetCount();
1530 size_t button_count
= m_buttons
.GetCount();
1532 // create off-screen bitmap
1533 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1534 dc
.SelectObject(bmp
);
1539 // find out if size of tabs is larger than can be
1540 // afforded on screen
1541 int total_width
= 0;
1542 int visible_width
= 0;
1543 for (i
= 0; i
< page_count
; ++i
)
1545 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1547 // determine if a close button is on this tab
1548 bool close_button
= false;
1549 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1550 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1552 close_button
= true;
1557 wxSize size
= m_art
->GetTabSize(dc
,
1563 wxAUI_BUTTON_STATE_NORMAL
:
1564 wxAUI_BUTTON_STATE_HIDDEN
,
1567 if (i
+1 < page_count
)
1568 total_width
+= x_extent
;
1570 total_width
+= size
.x
;
1572 if (i
>= m_tab_offset
)
1574 if (i
+1 < page_count
)
1575 visible_width
+= x_extent
;
1577 visible_width
+= size
.x
;
1581 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1583 // show left/right buttons
1584 for (i
= 0; i
< button_count
; ++i
)
1586 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1587 if (button
.id
== wxAUI_BUTTON_LEFT
||
1588 button
.id
== wxAUI_BUTTON_RIGHT
)
1590 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1596 // hide left/right buttons
1597 for (i
= 0; i
< button_count
; ++i
)
1599 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1600 if (button
.id
== wxAUI_BUTTON_LEFT
||
1601 button
.id
== wxAUI_BUTTON_RIGHT
)
1603 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1608 // determine whether left button should be enabled
1609 for (i
= 0; i
< button_count
; ++i
)
1611 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1612 if (button
.id
== wxAUI_BUTTON_LEFT
)
1614 if (m_tab_offset
== 0)
1615 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1617 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1619 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1621 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1622 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1624 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1631 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1634 int left_buttons_width
= 0;
1635 int right_buttons_width
= 0;
1639 // draw the buttons on the right side
1640 offset
= m_rect
.x
+ m_rect
.width
;
1641 for (i
= 0; i
< button_count
; ++i
)
1643 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1645 if (button
.location
!= wxRIGHT
)
1647 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1650 wxRect button_rect
= m_rect
;
1651 button_rect
.SetY(1);
1652 button_rect
.SetWidth(offset
);
1654 m_art
->DrawButton(dc
,
1662 offset
-= button
.rect
.GetWidth();
1663 right_buttons_width
+= button
.rect
.GetWidth();
1670 // draw the buttons on the left side
1672 for (i
= 0; i
< button_count
; ++i
)
1674 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1676 if (button
.location
!= wxLEFT
)
1678 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1681 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1683 m_art
->DrawButton(dc
,
1691 offset
+= button
.rect
.GetWidth();
1692 left_buttons_width
+= button
.rect
.GetWidth();
1695 offset
= left_buttons_width
;
1698 offset
+= m_art
->GetIndentSize();
1701 // prepare the tab-close-button array
1702 // make sure tab button entries which aren't used are marked as hidden
1703 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1704 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1706 // make sure there are enough tab button entries to accommodate all tabs
1707 while (m_tab_close_buttons
.GetCount() < page_count
)
1709 wxAuiTabContainerButton tempbtn
;
1710 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1711 tempbtn
.location
= wxCENTER
;
1712 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1713 m_tab_close_buttons
.Add(tempbtn
);
1717 // buttons before the tab offset must be set to hidden
1718 for (i
= 0; i
< m_tab_offset
; ++i
)
1720 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1726 size_t active
= 999;
1727 int active_offset
= 0;
1731 wxRect rect
= m_rect
;
1733 rect
.height
= m_rect
.height
;
1735 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1737 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1738 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1740 // determine if a close button is on this tab
1741 bool close_button
= false;
1742 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1743 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1745 close_button
= true;
1746 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1748 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1749 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1750 tab_button
.location
= wxCENTER
;
1755 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1759 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1761 if (rect
.width
<= 0)
1768 tab_button
.cur_state
,
1776 active_offset
= offset
;
1784 // make sure to deactivate buttons which are off the screen to the right
1785 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1787 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1791 // draw the active tab again so it stands in the foreground
1792 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1794 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1796 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1798 // determine if a close button is on this tab
1799 bool close_button
= false;
1800 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1801 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1803 close_button
= true;
1806 rect
.x
= active_offset
;
1811 tab_button
.cur_state
,
1818 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1819 m_rect
.GetWidth(), m_rect
.GetHeight(),
1824 // TabHitTest() tests if a tab was hit, passing the window pointer
1825 // back if that condition was fulfilled. The function returns
1826 // true if a tab was hit, otherwise false
1827 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1829 if (!m_rect
.Contains(x
,y
))
1832 wxAuiTabContainerButton
* btn
= NULL
;
1833 if (ButtonHitTest(x
, y
, &btn
))
1835 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1839 size_t i
, page_count
= m_pages
.GetCount();
1841 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1843 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1844 if (page
.rect
.Contains(x
,y
))
1855 // ButtonHitTest() tests if a button was hit. The function returns
1856 // true if a button was hit, otherwise false
1857 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1858 wxAuiTabContainerButton
** hit
) const
1860 if (!m_rect
.Contains(x
,y
))
1863 size_t i
, button_count
;
1866 button_count
= m_buttons
.GetCount();
1867 for (i
= 0; i
< button_count
; ++i
)
1869 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1870 if (button
.rect
.Contains(x
,y
) &&
1871 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1872 wxAUI_BUTTON_STATE_DISABLED
)))
1880 button_count
= m_tab_close_buttons
.GetCount();
1881 for (i
= 0; i
< button_count
; ++i
)
1883 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1884 if (button
.rect
.Contains(x
,y
) &&
1885 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1886 wxAUI_BUTTON_STATE_DISABLED
)))
1899 // the utility function ShowWnd() is the same as show,
1900 // except it handles wxAuiMDIChildFrame windows as well,
1901 // as the Show() method on this class is "unplugged"
1902 static void ShowWnd(wxWindow
* wnd
, bool show
)
1904 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1906 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1916 // DoShowHide() this function shows the active window, then
1917 // hides all of the other windows (in that order)
1918 void wxAuiTabContainer::DoShowHide()
1920 wxAuiNotebookPageArray
& pages
= GetPages();
1921 size_t i
, page_count
= pages
.GetCount();
1923 // show new active page first
1924 for (i
= 0; i
< page_count
; ++i
)
1926 wxAuiNotebookPage
& page
= pages
.Item(i
);
1929 ShowWnd(page
.window
, true);
1934 // hide all other pages
1935 for (i
= 0; i
< page_count
; ++i
)
1937 wxAuiNotebookPage
& page
= pages
.Item(i
);
1938 ShowWnd(page
.window
, page
.active
);
1947 // -- wxAuiTabCtrl class implementation --
1951 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1952 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1953 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1954 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1955 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1956 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1957 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1958 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1959 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1960 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
1964 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1968 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1970 m_click_pt
= wxDefaultPosition
;
1971 m_is_dragging
= false;
1972 m_hover_button
= NULL
;
1973 m_pressed_button
= NULL
;
1976 wxAuiTabCtrl::~wxAuiTabCtrl()
1980 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1984 dc
.SetFont(GetFont());
1986 if (GetPageCount() > 0)
1990 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
1994 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
1996 wxSize s
= evt
.GetSize();
1997 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2001 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2004 m_click_pt
= wxDefaultPosition
;
2005 m_is_dragging
= false;
2007 m_pressed_button
= NULL
;
2011 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2013 int new_selection
= GetIdxFromWindow(wnd
);
2015 // wxAuiNotebooks always want to receive this event
2016 // even if the tab is already active, because they may
2017 // have multiple tab controls
2018 if (new_selection
!= GetActivePage() ||
2019 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2021 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2022 e
.SetSelection(new_selection
);
2023 e
.SetOldSelection(GetActivePage());
2024 e
.SetEventObject(this);
2025 GetEventHandler()->ProcessEvent(e
);
2028 m_click_pt
.x
= evt
.m_x
;
2029 m_click_pt
.y
= evt
.m_y
;
2035 m_pressed_button
= m_hover_button
;
2036 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2042 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2044 if (GetCapture() == this)
2049 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2050 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2051 evt
.SetOldSelection(evt
.GetSelection());
2052 evt
.SetEventObject(this);
2053 GetEventHandler()->ProcessEvent(evt
);
2057 if (m_pressed_button
)
2059 // make sure we're still clicking the button
2060 wxAuiTabContainerButton
* button
= NULL
;
2061 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2064 if (button
!= m_pressed_button
)
2066 m_pressed_button
= NULL
;
2073 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2075 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2076 evt
.SetInt(m_pressed_button
->id
);
2077 evt
.SetEventObject(this);
2078 GetEventHandler()->ProcessEvent(evt
);
2081 m_pressed_button
= NULL
;
2084 m_click_pt
= wxDefaultPosition
;
2085 m_is_dragging
= false;
2089 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2091 wxPoint pos
= evt
.GetPosition();
2093 // check if the mouse is hovering above a button
2094 wxAuiTabContainerButton
* button
;
2095 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2097 if (m_hover_button
&& button
!= m_hover_button
)
2099 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2100 m_hover_button
= NULL
;
2105 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2107 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2110 m_hover_button
= button
;
2118 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2119 m_hover_button
= NULL
;
2126 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2131 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2132 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2133 evt
.SetOldSelection(evt
.GetSelection());
2134 evt
.SetEventObject(this);
2135 GetEventHandler()->ProcessEvent(evt
);
2140 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2141 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2143 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2144 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2146 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2147 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2148 evt
.SetOldSelection(evt
.GetSelection());
2149 evt
.SetEventObject(this);
2150 GetEventHandler()->ProcessEvent(evt
);
2152 m_is_dragging
= true;
2156 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2160 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2161 m_hover_button
= NULL
;
2167 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2169 int button
= event
.GetInt();
2171 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2173 if (button
== wxAUI_BUTTON_LEFT
)
2175 if (GetTabOffset() > 0)
2177 SetTabOffset(GetTabOffset()-1);
2184 SetTabOffset(GetTabOffset()+1);
2189 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2191 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2195 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2196 e
.SetSelection(idx
);
2197 e
.SetOldSelection(GetActivePage());
2198 e
.SetEventObject(this);
2199 GetEventHandler()->ProcessEvent(e
);
2208 // wxTabFrame is an interesting case. It's important that all child pages
2209 // of the multi-notebook control are all actually children of that control
2210 // (and not grandchildren). wxTabFrame facilitates this. There is one
2211 // instance of wxTabFrame for each tab control inside the multi-notebook.
2212 // It's important to know that wxTabFrame is not a real window, but it merely
2213 // used to capture the dimensions/positioning of the internal tab control and
2214 // it's managed page windows
2216 class wxTabFrame
: public wxWindow
2223 m_rect
= wxRect(0,0,200,200);
2224 m_tab_ctrl_height
= 20;
2227 void SetTabCtrlHeight(int h
)
2229 m_tab_ctrl_height
= h
;
2232 void DoSetSize(int x
, int y
,
2233 int width
, int height
,
2234 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2236 m_rect
= wxRect(x
, y
, width
, height
);
2240 void DoGetClientSize(int* x
, int* y
) const
2246 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2253 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2254 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2255 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2259 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2260 size_t i
, page_count
= pages
.GetCount();
2262 for (i
= 0; i
< page_count
; ++i
)
2264 wxAuiNotebookPage
& page
= pages
.Item(i
);
2265 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2266 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2268 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2270 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2271 wnd
->ApplyMDIChildFrameRect();
2276 void DoGetSize(int* x
, int* y
) const
2279 *x
= m_rect
.GetWidth();
2281 *y
= m_rect
.GetHeight();
2293 wxAuiTabCtrl
* m_tabs
;
2294 int m_tab_ctrl_height
;
2298 const int wxAuiBaseTabCtrlId
= 5380;
2301 // -- wxAuiNotebook class implementation --
2303 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2304 EVT_SIZE(wxAuiNotebook::OnSize
)
2305 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2306 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2307 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2308 wxAuiNotebook::OnTabClicked
)
2309 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2310 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2311 wxAuiNotebook::OnTabBeginDrag
)
2312 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2313 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2314 wxAuiNotebook::OnTabEndDrag
)
2315 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2316 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2317 wxAuiNotebook::OnTabDragMotion
)
2318 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2319 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2320 wxAuiNotebook::OnTabButton
)
2323 wxAuiNotebook::wxAuiNotebook()
2326 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2328 m_tab_ctrl_height
= 20;
2329 m_requested_bmp_size
= wxDefaultSize
;
2330 m_requested_tabctrl_height
= -1;
2333 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2337 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2340 m_requested_bmp_size
= wxDefaultSize
;
2341 m_requested_tabctrl_height
= -1;
2342 InitNotebook(style
);
2345 bool wxAuiNotebook::Create(wxWindow
* parent
,
2351 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2354 InitNotebook(style
);
2359 // InitNotebook() contains common initialization
2360 // code called by all constructors
2361 void wxAuiNotebook::InitNotebook(long style
)
2364 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2366 m_flags
= (unsigned int)style
;
2367 m_tab_ctrl_height
= 20;
2369 m_normal_font
= *wxNORMAL_FONT
;
2370 m_selected_font
= *wxNORMAL_FONT
;
2371 m_selected_font
.SetWeight(wxBOLD
);
2373 SetArtProvider(new wxAuiDefaultTabArt
);
2375 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2376 m_dummy_wnd
->SetSize(200, 200);
2377 m_dummy_wnd
->Show(false);
2379 m_mgr
.SetManagedWindow(this);
2380 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2381 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2383 m_mgr
.AddPane(m_dummy_wnd
,
2384 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2389 wxAuiNotebook::~wxAuiNotebook()
2394 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2396 m_tabs
.SetArtProvider(art
);
2398 UpdateTabCtrlHeight();
2401 // SetTabCtrlHeight() is the highest-level override of the
2402 // tab height. A call to this function effectively enforces a
2403 // specified tab ctrl height, overriding all other considerations,
2404 // such as text or bitmap height. It overrides any call to
2405 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2406 // any previous call and returns to the default behavior
2408 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2410 m_requested_tabctrl_height
= height
;
2412 // if window is already initialized, recalculate the tab height
2415 UpdateTabCtrlHeight();
2420 // SetUniformBitmapSize() ensures that all tabs will have
2421 // the same height, even if some tabs don't have bitmaps
2422 // Passing wxDefaultSize to this function will instruct
2423 // the control to use dynamic tab height-- so when a tab
2424 // with a large bitmap is added, the tab ctrl's height will
2425 // automatically increase to accommodate the bitmap
2427 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2429 m_requested_bmp_size
= size
;
2431 // if window is already initialized, recalculate the tab height
2434 UpdateTabCtrlHeight();
2438 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2439 // to be used interally
2440 void wxAuiNotebook::UpdateTabCtrlHeight()
2442 // get the tab ctrl height we will use
2443 int height
= CalculateTabCtrlHeight();
2445 // if the tab control height needs to change, update
2446 // all of our tab controls with the new height
2447 if (m_tab_ctrl_height
!= height
)
2449 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2451 m_tab_ctrl_height
= height
;
2453 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2454 size_t i
, pane_count
= all_panes
.GetCount();
2455 for (i
= 0; i
< pane_count
; ++i
)
2457 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2458 if (pane
.name
== wxT("dummy"))
2460 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2461 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2462 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2463 tabctrl
->SetArtProvider(art
->Clone());
2464 tab_frame
->DoSizing();
2469 void wxAuiNotebook::UpdateHintWindowSize()
2471 wxSize size
= CalculateNewSplitSize();
2473 // the placeholder hint window should be set to this size
2474 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2478 info
.BestSize(size
);
2479 m_dummy_wnd
->SetSize(size
);
2484 // calculates the size of the new split
2485 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2487 // count number of tab controls
2488 int tab_ctrl_count
= 0;
2489 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2490 size_t i
, pane_count
= all_panes
.GetCount();
2491 for (i
= 0; i
< pane_count
; ++i
)
2493 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2494 if (pane
.name
== wxT("dummy"))
2499 wxSize new_split_size
;
2501 // if there is only one tab control, the first split
2502 // should happen around the middle
2503 if (tab_ctrl_count
< 2)
2505 new_split_size
= GetClientSize();
2506 new_split_size
.x
/= 2;
2507 new_split_size
.y
/= 2;
2511 // this is in place of a more complicated calculation
2512 // that needs to be implemented
2513 new_split_size
= wxSize(180,180);
2516 return new_split_size
;
2519 int wxAuiNotebook::CalculateTabCtrlHeight()
2521 // if a fixed tab ctrl height is specified,
2522 // just return that instead of calculating a
2524 if (m_requested_tabctrl_height
!= -1)
2525 return m_requested_tabctrl_height
;
2527 // find out new best tab height
2528 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2530 return art
->GetBestTabCtrlSize(this,
2532 m_requested_bmp_size
);
2536 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2538 return m_tabs
.GetArtProvider();
2541 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2543 wxControl::SetWindowStyleFlag(style
);
2545 m_flags
= (unsigned int)style
;
2547 // if the control is already initialized
2548 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2550 // let all of the tab children know about the new style
2552 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2553 size_t i
, pane_count
= all_panes
.GetCount();
2554 for (i
= 0; i
< pane_count
; ++i
)
2556 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2557 if (pane
.name
== wxT("dummy"))
2559 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2560 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2561 tabctrl
->SetFlags(m_flags
);
2562 tabframe
->DoSizing();
2570 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2571 const wxString
& caption
,
2573 const wxBitmap
& bitmap
)
2575 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2578 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2580 const wxString
& caption
,
2582 const wxBitmap
& bitmap
)
2584 wxAuiNotebookPage info
;
2586 info
.caption
= caption
;
2587 info
.bitmap
= bitmap
;
2588 info
.active
= false;
2590 // if there are currently no tabs, the first added
2591 // tab must be active
2592 if (m_tabs
.GetPageCount() == 0)
2595 m_tabs
.InsertPage(page
, info
, page_idx
);
2597 // if that was the first page added, even if
2598 // select is false, it must become the "current page"
2599 // (though no select events will be fired)
2600 if (!select
&& m_tabs
.GetPageCount() == 1)
2601 m_curpage
= GetPageIndex(page
);
2603 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2604 if (page_idx
>= active_tabctrl
->GetPageCount())
2605 active_tabctrl
->AddPage(page
, info
);
2607 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2609 UpdateTabCtrlHeight();
2611 active_tabctrl
->DoShowHide();
2615 int idx
= m_tabs
.GetIdxFromWindow(page
);
2616 wxASSERT_MSG(idx
!= -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
2625 // DeletePage() removes a tab from the multi-notebook,
2626 // and destroys the window as well
2627 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2629 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2631 if (!RemovePage(page_idx
))
2634 // actually destroy the window now
2635 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2637 // delete the child frame with pending delete, as is
2638 // customary with frame windows
2639 if (!wxPendingDelete
.Member(wnd
))
2640 wxPendingDelete
.Append(wnd
);
2652 // RemovePage() removes a tab from the multi-notebook,
2653 // but does not destroy the window
2654 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2656 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2657 wxWindow
* new_active
= NULL
;
2659 // find out which onscreen tab ctrl owns this tab
2662 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2665 // find a new page and set it as active
2666 int new_idx
= ctrl_idx
+1;
2667 if (new_idx
>= (int)ctrl
->GetPageCount())
2668 new_idx
= ctrl_idx
-1;
2670 if (new_idx
>= 0 && new_idx
< (int)ctrl
->GetPageCount())
2672 new_active
= ctrl
->GetWindowFromIdx(new_idx
);
2676 // set the active page to the first page that
2677 // isn't the one being deleted
2678 size_t i
, page_count
= m_tabs
.GetPageCount();
2679 for (i
= 0; i
< page_count
; ++i
)
2681 wxWindow
* w
= m_tabs
.GetWindowFromIdx(i
);
2684 new_active
= m_tabs
.GetWindowFromIdx(i
);
2690 // remove the tab from main catalog
2691 if (!m_tabs
.RemovePage(wnd
))
2694 // remove the tab from the onscreen tab ctrl
2695 ctrl
->RemovePage(wnd
);
2698 RemoveEmptyTabFrames();
2700 // set new active pane
2704 SetSelection(m_tabs
.GetIdxFromWindow(new_active
));
2710 // GetPageIndex() returns the index of the page, or -1 if the
2711 // page could not be located in the notebook
2712 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2714 return m_tabs
.GetIdxFromWindow(page_wnd
);
2719 // SetPageText() changes the tab caption of the specified page
2720 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2722 if (page_idx
>= m_tabs
.GetPageCount())
2725 // update our own tab catalog
2726 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2727 page_info
.caption
= text
;
2729 // update what's on screen
2732 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2734 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2735 info
.caption
= text
;
2743 // returns the page caption
2744 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2746 if (page_idx
>= m_tabs
.GetPageCount())
2747 return wxEmptyString
;
2749 // update our own tab catalog
2750 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2751 return page_info
.caption
;
2754 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2756 if (page_idx
>= m_tabs
.GetPageCount())
2759 // update our own tab catalog
2760 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2761 page_info
.bitmap
= bitmap
;
2763 // tab height might have changed
2764 UpdateTabCtrlHeight();
2766 // update what's on screen
2769 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2771 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2772 info
.bitmap
= bitmap
;
2780 // returns the page bitmap
2781 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2783 if (page_idx
>= m_tabs
.GetPageCount())
2786 // update our own tab catalog
2787 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2788 return page_info
.bitmap
;
2791 // GetSelection() returns the index of the currently active page
2792 int wxAuiNotebook::GetSelection() const
2797 // SetSelection() sets the currently active page
2798 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2800 // don't change the page unless necessary
2801 if ((int)new_page
== m_curpage
)
2804 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2808 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2809 evt
.SetSelection(new_page
);
2810 evt
.SetOldSelection(m_curpage
);
2811 evt
.SetEventObject(this);
2812 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2814 int old_curpage
= m_curpage
;
2815 m_curpage
= new_page
;
2817 // program allows the page change
2818 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2819 (void)GetEventHandler()->ProcessEvent(evt
);
2824 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2826 m_tabs
.SetActivePage(wnd
);
2828 ctrl
->SetActivePage(ctrl_idx
);
2835 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2836 size_t i
, pane_count
= all_panes
.GetCount();
2837 for (i
= 0; i
< pane_count
; ++i
)
2839 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2840 if (pane
.name
== wxT("dummy"))
2842 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2843 if (tabctrl
!= ctrl
)
2844 tabctrl
->SetSelectedFont(m_normal_font
);
2846 tabctrl
->SetSelectedFont(m_selected_font
);
2859 // GetPageCount() returns the total number of
2860 // pages managed by the multi-notebook
2861 size_t wxAuiNotebook::GetPageCount() const
2863 return m_tabs
.GetPageCount();
2866 // GetPage() returns the wxWindow pointer of the
2868 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2870 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2872 return m_tabs
.GetWindowFromIdx(page_idx
);
2875 // DoSizing() performs all sizing operations in each tab control
2876 void wxAuiNotebook::DoSizing()
2878 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2879 size_t i
, pane_count
= all_panes
.GetCount();
2880 for (i
= 0; i
< pane_count
; ++i
)
2882 if (all_panes
.Item(i
).name
== wxT("dummy"))
2885 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2886 tabframe
->DoSizing();
2890 // GetActiveTabCtrl() returns the active tab control. It is
2891 // called to determine which control gets new windows being added
2892 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
2894 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
2899 // find the tab ctrl with the current page
2900 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
2907 // no current page, just find the first tab ctrl
2908 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2909 size_t i
, pane_count
= all_panes
.GetCount();
2910 for (i
= 0; i
< pane_count
; ++i
)
2912 if (all_panes
.Item(i
).name
== wxT("dummy"))
2915 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2916 return tabframe
->m_tabs
;
2919 // If there is no tabframe at all, create one
2920 wxTabFrame
* tabframe
= new wxTabFrame
;
2921 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
2922 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
2927 tabframe
->m_tabs
->SetFlags(m_flags
);
2928 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
2929 m_mgr
.AddPane(tabframe
,
2930 wxAuiPaneInfo().Center().CaptionVisible(false));
2934 return tabframe
->m_tabs
;
2937 // FindTab() finds the tab control that currently contains the window as well
2938 // as the index of the window in the tab control. It returns true if the
2939 // window was found, otherwise false.
2940 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
2942 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2943 size_t i
, pane_count
= all_panes
.GetCount();
2944 for (i
= 0; i
< pane_count
; ++i
)
2946 if (all_panes
.Item(i
).name
== wxT("dummy"))
2949 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
2951 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
2954 *ctrl
= tabframe
->m_tabs
;
2963 void wxAuiNotebook::Split(size_t page
, int direction
)
2965 wxSize cli_size
= GetClientSize();
2967 // get the page's window pointer
2968 wxWindow
* wnd
= GetPage(page
);
2972 // notebooks with 1 or less pages can't be split
2973 if (GetPageCount() < 2)
2976 // find out which tab control the page currently belongs to
2977 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
2980 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
2982 if (!src_tabs
|| src_idx
== -1)
2985 // choose a split size
2987 if (GetPageCount() > 2)
2989 split_size
= CalculateNewSplitSize();
2993 // because there are two panes, always split them
2995 split_size
= GetClientSize();
3001 // create a new tab frame
3002 wxTabFrame
* new_tabs
= new wxTabFrame
;
3003 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3004 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3005 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3010 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3011 new_tabs
->m_tabs
->SetFlags(m_flags
);
3012 dest_tabs
= new_tabs
->m_tabs
;
3014 // create a pane info structure with the information
3015 // about where the pane should be added
3016 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3019 if (direction
== wxLEFT
)
3022 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3024 else if (direction
== wxRIGHT
)
3027 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3029 else if (direction
== wxTOP
)
3032 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3034 else if (direction
== wxBOTTOM
)
3037 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3040 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3043 // remove the page from the source tabs
3044 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3045 page_info
.active
= false;
3046 src_tabs
->RemovePage(page_info
.window
);
3047 if (src_tabs
->GetPageCount() > 0)
3049 src_tabs
->SetActivePage((size_t)0);
3050 src_tabs
->DoShowHide();
3051 src_tabs
->Refresh();
3055 // add the page to the destination tabs
3056 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3058 if (src_tabs
->GetPageCount() == 0)
3060 RemoveEmptyTabFrames();
3064 dest_tabs
->DoShowHide();
3065 dest_tabs
->Refresh();
3067 // force the set selection function reset the selection
3070 // set the active page to the one we just split off
3071 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3073 UpdateHintWindowSize();
3077 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3079 UpdateHintWindowSize();
3084 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3086 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3088 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3089 wxASSERT(ctrl
!= NULL
);
3091 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3092 wxASSERT(wnd
!= NULL
);
3094 int idx
= m_tabs
.GetIdxFromWindow(wnd
);
3095 wxASSERT(idx
!= -1);
3100 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3105 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3107 wxPoint screen_pt
= ::wxGetMousePosition();
3108 wxPoint client_pt
= ScreenToClient(screen_pt
);
3111 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3112 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3114 if (dest_tabs
== src_tabs
)
3118 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3121 // always hide the hint for inner-tabctrl drag
3124 // if tab moving is not allowed, leave
3125 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3130 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3131 wxWindow
* dest_location_tab
;
3133 // this is an inner-tab drag/reposition
3134 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3136 int src_idx
= evt
.GetSelection();
3137 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3139 // prevent jumpy drag
3140 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3141 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3142 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3144 m_last_drag_x
= pt
.x
;
3149 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3150 dest_tabs
->MovePage(src_tab
, dest_idx
);
3151 dest_tabs
->SetActivePage((size_t)dest_idx
);
3152 dest_tabs
->DoShowHide();
3153 dest_tabs
->Refresh();
3154 m_last_drag_x
= pt
.x
;
3162 // if external drag is allowed, check if the tab is being dragged
3163 // over a different wxAuiNotebook control
3164 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3166 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3168 // if we aren't over any window, stop here
3172 // make sure we are not over the hint window
3173 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3177 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3179 tab_ctrl
= tab_ctrl
->GetParent();
3184 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3188 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3189 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3190 m_mgr
.ShowHint(hint_rect
);
3199 // we are either over a hint window, or not over a tab
3200 // window, and there is no where to drag to, so exit
3207 // if there are less than two panes, split can't happen, so leave
3208 if (m_tabs
.GetPageCount() < 2)
3211 // if tab moving is not allowed, leave
3212 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3218 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3224 wxRect hint_rect
= dest_tabs
->GetRect();
3225 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3226 m_mgr
.ShowHint(hint_rect
);
3230 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3236 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3238 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3243 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3244 wxAuiTabCtrl
* dest_tabs
= NULL
;
3247 // set cursor back to an arrow
3248 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3251 // get the mouse position, which will be used to determine the drop point
3252 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3253 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3257 // check for an external move
3258 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3260 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3264 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3266 tab_ctrl
= tab_ctrl
->GetParent();
3271 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3275 // find out from the destination control
3276 // if it's ok to drop this tab here
3277 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3278 e
.SetSelection(evt
.GetSelection());
3279 e
.SetOldSelection(evt
.GetSelection());
3280 e
.SetEventObject(this);
3281 e
.SetDragSource(this);
3282 e
.Veto(); // dropping must be explicitly approved by control owner
3284 nb
->GetEventHandler()->ProcessEvent(e
);
3288 // no answer or negative answer
3294 int src_idx
= evt
.GetSelection();
3295 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3297 // get main index of the page
3298 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3300 // make a copy of the page info
3301 wxAuiNotebookPage page_info
= m_tabs
.GetPage((size_t)main_idx
);
3303 // remove the page from the source notebook
3304 RemovePage(main_idx
);
3306 // reparent the page
3307 src_page
->Reparent(nb
);
3310 // found out the insert idx
3311 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3312 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3314 wxWindow
* target
= NULL
;
3315 int insert_idx
= -1;
3316 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3319 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3323 // add the page to the new notebook
3324 if (insert_idx
== -1)
3325 insert_idx
= dest_tabs
->GetPageCount();
3326 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3327 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3330 dest_tabs
->DoShowHide();
3331 dest_tabs
->Refresh();
3333 // set the selection in the destination tab control
3334 nb
->SetSelection(nb
->m_tabs
.GetIdxFromWindow(page_info
.window
));
3344 // only perform a tab split if it's allowed
3345 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3347 // If the pointer is in an existing tab frame, do a tab insert
3348 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3349 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3350 int insert_idx
= -1;
3353 dest_tabs
= tab_frame
->m_tabs
;
3355 if (dest_tabs
== src_tabs
)
3359 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3360 wxWindow
* target
= NULL
;
3361 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3364 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3370 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3375 // there is no suitable drop location here, exit out
3379 // If there is no tabframe at all, create one
3380 wxTabFrame
* new_tabs
= new wxTabFrame
;
3381 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3382 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3383 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3388 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3389 new_tabs
->m_tabs
->SetFlags(m_flags
);
3391 m_mgr
.AddPane(new_tabs
,
3392 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3395 dest_tabs
= new_tabs
->m_tabs
;
3400 // remove the page from the source tabs
3401 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3402 page_info
.active
= false;
3403 src_tabs
->RemovePage(page_info
.window
);
3404 if (src_tabs
->GetPageCount() > 0)
3406 src_tabs
->SetActivePage((size_t)0);
3407 src_tabs
->DoShowHide();
3408 src_tabs
->Refresh();
3413 // add the page to the destination tabs
3414 if (insert_idx
== -1)
3415 insert_idx
= dest_tabs
->GetPageCount();
3416 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3418 if (src_tabs
->GetPageCount() == 0)
3420 RemoveEmptyTabFrames();
3424 dest_tabs
->DoShowHide();
3425 dest_tabs
->Refresh();
3427 // force the set selection function reset the selection
3430 // set the active page to the one we just split off
3431 SetSelection(m_tabs
.GetIdxFromWindow(page_info
.window
));
3433 UpdateHintWindowSize();
3439 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3441 // if we've just removed the last tab from the source
3442 // tab set, the remove the tab control completely
3443 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3444 size_t i
, pane_count
= all_panes
.GetCount();
3445 for (i
= 0; i
< pane_count
; ++i
)
3447 if (all_panes
.Item(i
).name
== wxT("dummy"))
3450 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3451 if (tabframe
->m_tab_rect
.Contains(pt
))
3452 return tabframe
->m_tabs
;
3458 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3460 // if we've just removed the last tab from the source
3461 // tab set, the remove the tab control completely
3462 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3463 size_t i
, pane_count
= all_panes
.GetCount();
3464 for (i
= 0; i
< pane_count
; ++i
)
3466 if (all_panes
.Item(i
).name
== wxT("dummy"))
3469 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3470 if (tabframe
->m_tabs
== tab_ctrl
)
3479 void wxAuiNotebook::RemoveEmptyTabFrames()
3481 // if we've just removed the last tab from the source
3482 // tab set, the remove the tab control completely
3483 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3484 size_t i
, pane_count
= all_panes
.GetCount();
3485 for (i
= 0; i
< pane_count
; ++i
)
3487 if (all_panes
.Item(i
).name
== wxT("dummy"))
3490 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3491 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3493 m_mgr
.DetachPane(tab_frame
);
3495 // use pending delete because sometimes during
3496 // window closing, refreshs are pending
3497 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3498 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3499 //tab_frame->m_tabs->Destroy();
3506 // check to see if there is still a center pane;
3507 // if there isn't, make a frame the center pane
3508 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3509 pane_count
= panes
.GetCount();
3510 wxWindow
* first_good
= NULL
;
3511 bool center_found
= false;
3512 for (i
= 0; i
< pane_count
; ++i
)
3514 if (panes
.Item(i
).name
== wxT("dummy"))
3516 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3517 center_found
= true;
3519 first_good
= panes
.Item(i
).window
;
3522 if (!center_found
&& first_good
)
3524 m_mgr
.GetPane(first_good
).Centre();
3530 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3532 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3533 if (idx
!= -1 && idx
!= m_curpage
)
3540 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3542 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3543 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3545 int button_id
= evt
.GetInt();
3547 if (button_id
== wxAUI_BUTTON_CLOSE
)
3549 int selection
= tabs
->GetActivePage();
3551 if (selection
!= -1)
3553 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3556 // ask owner if it's ok to close the tab
3557 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3558 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3559 e
.SetOldSelection(evt
.GetSelection());
3560 e
.SetEventObject(this);
3561 GetEventHandler()->ProcessEvent(e
);
3566 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3572 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3573 DeletePage(main_idx
);