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"
34 #include "wx/renderer.h"
37 #include "wx/osx/private.h"
40 #include "wx/arrimpl.cpp"
41 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
42 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
44 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, wxAuiNotebookEvent
);
45 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, wxAuiNotebookEvent
);
46 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, wxAuiNotebookEvent
);
47 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
, wxAuiNotebookEvent
);
48 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, wxAuiNotebookEvent
);
49 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, wxAuiNotebookEvent
);
50 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, wxAuiNotebookEvent
);
51 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, wxAuiNotebookEvent
);
52 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, wxAuiNotebookEvent
);
53 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, wxAuiNotebookEvent
);
54 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, wxAuiNotebookEvent
);
55 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, wxAuiNotebookEvent
);
56 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, wxAuiNotebookEvent
);
57 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, wxAuiNotebookEvent
);
58 wxDEFINE_EVENT(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, wxAuiNotebookEvent
);
60 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
61 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
62 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
68 // these functions live in dockart.cpp -- they'll eventually
69 // be moved to a new utility cpp file
71 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
72 const wxColour
& color
);
74 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
76 static void DrawButtons(wxDC
& dc
,
79 const wxColour
& bkcolour
,
84 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
90 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
91 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
93 dc
.SetBrush(wxBrush(bkcolour
.ChangeLightness(120)));
94 dc
.SetPen(wxPen(bkcolour
.ChangeLightness(75)));
96 // draw the background behind the button
97 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
100 // draw the button itself
101 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
104 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
106 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
115 // -- GUI helper classes and functions --
117 class wxAuiCommandCapture
: public wxEvtHandler
121 wxAuiCommandCapture() { m_last_id
= 0; }
122 int GetCommandId() const { return m_last_id
; }
124 bool ProcessEvent(wxEvent
& evt
)
126 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
128 m_last_id
= evt
.GetId();
132 if (GetNextHandler())
133 return GetNextHandler()->ProcessEvent(evt
);
145 #if defined( __WXMAC__ )
146 static const unsigned char close_bits
[]={
147 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
148 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
149 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
150 #elif defined( __WXGTK__)
151 static const unsigned char close_bits
[]={
152 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
153 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
154 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
156 static const unsigned char close_bits
[]={
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
158 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
162 static const unsigned char left_bits
[] = {
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
164 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
167 static const unsigned char right_bits
[] = {
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
169 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
172 static const unsigned char list_bits
[] = {
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
174 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
182 // -- wxAuiDefaultTabArt class implementation --
184 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
186 m_normal_font
= *wxNORMAL_FONT
;
187 m_selected_font
= *wxNORMAL_FONT
;
188 m_selected_font
.SetWeight(wxBOLD
);
189 m_measuring_font
= m_selected_font
;
191 m_fixed_tab_width
= 100;
192 m_tab_ctrl_height
= 0;
194 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
195 wxColor base_colour
= wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground
));
197 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
200 // the base_colour is too pale to use as our base colour,
201 // so darken it a bit --
202 if ((255-base_colour
.Red()) +
203 (255-base_colour
.Green()) +
204 (255-base_colour
.Blue()) < 60)
206 base_colour
= base_colour
.ChangeLightness(92);
209 m_base_colour
= base_colour
;
210 wxColor border_colour
= base_colour
.ChangeLightness(75);
212 m_border_pen
= wxPen(border_colour
);
213 m_base_colour_pen
= wxPen(m_base_colour
);
214 m_base_colour_brush
= wxBrush(m_base_colour
);
216 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
217 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
219 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
220 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
222 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
223 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
225 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
226 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
231 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
235 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
237 return new wxAuiDefaultTabArt(*this);
240 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
245 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
248 m_fixed_tab_width
= 100;
250 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
252 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
253 tot_width
-= m_active_close_bmp
.GetWidth();
254 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
255 tot_width
-= m_active_windowlist_bmp
.GetWidth();
259 m_fixed_tab_width
= tot_width
/(int)tab_count
;
263 if (m_fixed_tab_width
< 100)
264 m_fixed_tab_width
= 100;
266 if (m_fixed_tab_width
> tot_width
/2)
267 m_fixed_tab_width
= tot_width
/2;
269 if (m_fixed_tab_width
> 220)
270 m_fixed_tab_width
= 220;
272 m_tab_ctrl_height
= tab_ctrl_size
.y
;
276 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
277 wxWindow
* WXUNUSED(wnd
),
282 wxColor top_color
= m_base_colour
.ChangeLightness(90);
283 wxColor bottom_color
= m_base_colour
.ChangeLightness(170);
286 if (m_flags
&wxAUI_NB_BOTTOM
)
287 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
);
288 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
289 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
290 else //for wxAUI_NB_TOP
291 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
293 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
298 dc
.SetPen(m_border_pen
);
299 int y
= rect
.GetHeight();
300 int w
= rect
.GetWidth();
302 if (m_flags
&wxAUI_NB_BOTTOM
)
304 dc
.SetBrush(wxBrush(bottom_color
));
305 dc
.DrawRectangle(-1, 0, w
+2, 4);
307 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
308 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
309 else //for wxAUI_NB_TOP
311 dc
.SetBrush(m_base_colour_brush
);
312 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
317 // DrawTab() draws an individual tab.
320 // in_rect - rectangle the tab should be confined to
321 // caption - tab's caption
322 // active - whether or not the tab is active
323 // out_rect - actual output rectangle
324 // x_extent - the advance x; where the next tab should start
326 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
328 const wxAuiNotebookPage
& page
,
329 const wxRect
& in_rect
,
330 int close_button_state
,
331 wxRect
* out_tab_rect
,
332 wxRect
* out_button_rect
,
335 wxCoord normal_textx
, normal_texty
;
336 wxCoord selected_textx
, selected_texty
;
339 // if the caption is empty, measure some temporary text
340 wxString caption
= page
.caption
;
344 dc
.SetFont(m_selected_font
);
345 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
347 dc
.SetFont(m_normal_font
);
348 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
350 // figure out the size of the tab
351 wxSize tab_size
= GetTabSize(dc
,
359 wxCoord tab_height
= m_tab_ctrl_height
- 3;
360 wxCoord tab_width
= tab_size
.x
;
361 wxCoord tab_x
= in_rect
.x
;
362 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
365 caption
= page
.caption
;
368 // select pen, brush and font for the tab to be drawn
372 dc
.SetFont(m_selected_font
);
373 texty
= selected_texty
;
377 dc
.SetFont(m_normal_font
);
378 texty
= normal_texty
;
382 // create points that will make the tab outline
384 int clip_width
= tab_width
;
385 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
386 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
389 wxPoint clip_points[6];
390 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
391 clip_points[1] = wxPoint(tab_x, tab_y+2);
392 clip_points[2] = wxPoint(tab_x+2, tab_y);
393 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
394 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
395 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
397 // FIXME: these ports don't provide wxRegion ctor from array of points
398 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
399 // set the clipping region for the tab --
400 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
401 dc.SetClippingRegion(clipping_region);
402 #endif // !wxDFB && !wxCocoa
404 // since the above code above doesn't play well with WXDFB or WXCOCOA,
405 // we'll just use a rectangle for the clipping region for now --
406 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
409 wxPoint border_points
[6];
410 if (m_flags
&wxAUI_NB_BOTTOM
)
412 border_points
[0] = wxPoint(tab_x
, tab_y
);
413 border_points
[1] = wxPoint(tab_x
, tab_y
+tab_height
-6);
414 border_points
[2] = wxPoint(tab_x
+2, tab_y
+tab_height
-4);
415 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
+tab_height
-4);
416 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-6);
417 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
);
419 else //if (m_flags & wxAUI_NB_TOP) {}
421 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
422 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
423 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
424 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
425 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
426 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
428 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
429 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
431 int drawn_tab_yoff
= border_points
[1].y
;
432 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
439 // draw base background color
440 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
441 dc
.SetPen(m_base_colour_pen
);
442 dc
.SetBrush(m_base_colour_brush
);
443 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
445 // this white helps fill out the gradient at the top of the tab
446 dc
.SetPen(*wxWHITE_PEN
);
447 dc
.SetBrush(*wxWHITE_BRUSH
);
448 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
450 // these two points help the rounded corners appear more antialiased
451 dc
.SetPen(m_base_colour_pen
);
452 dc
.DrawPoint(r
.x
+2, r
.y
+1);
453 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
455 // set rectangle down a bit for gradient drawing
456 r
.SetHeight(r
.GetHeight()/2);
462 // draw gradient background
463 wxColor top_color
= *wxWHITE
;
464 wxColor bottom_color
= m_base_colour
;
465 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
471 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
473 // start the gradent up a bit and leave the inside border inset
474 // by a pixel for a 3D look. Only the top half of the inactive
475 // tab will have a slight gradient
482 // -- draw top gradient fill for glossy look
483 wxColor top_color
= m_base_colour
;
484 wxColor bottom_color
= top_color
.ChangeLightness(160);
485 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
490 // -- draw bottom fill for glossy look
491 top_color
= m_base_colour
;
492 bottom_color
= m_base_colour
;
493 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
497 dc
.SetPen(m_border_pen
);
498 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
499 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
501 // there are two horizontal grey lines at the bottom of the tab control,
502 // this gets rid of the top one of those lines in the tab control
505 if (m_flags
&wxAUI_NB_BOTTOM
)
506 dc
.SetPen(wxPen(m_base_colour
.ChangeLightness(170)));
507 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
508 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
509 else //for wxAUI_NB_TOP
510 dc
.SetPen(m_base_colour_pen
);
511 dc
.DrawLine(border_points
[0].x
+1,
518 int text_offset
= tab_x
+ 8;
519 int close_button_width
= 0;
520 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
522 close_button_width
= m_active_close_bmp
.GetWidth();
525 int bitmap_offset
= 0;
526 if (page
.bitmap
.IsOk())
528 bitmap_offset
= tab_x
+ 8;
531 dc
.DrawBitmap(page
.bitmap
,
533 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
536 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
537 text_offset
+= 3; // bitmap padding
542 text_offset
= tab_x
+ 8;
546 wxString draw_text
= wxAuiChopText(dc
,
548 tab_width
- (text_offset
-tab_x
) - close_button_width
);
551 dc
.DrawText(draw_text
,
553 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
555 // draw focus rectangle
556 if (page
.active
&& (wnd
->FindFocus() == wnd
))
558 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
559 selected_textx
, selected_texty
);
562 wxRect focusRectBitmap
;
564 if (page
.bitmap
.IsOk())
565 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
566 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
568 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
569 focusRect
= focusRectBitmap
;
570 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
571 focusRect
= focusRectText
;
572 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
573 focusRect
= focusRectText
.Union(focusRectBitmap
);
575 focusRect
.Inflate(2, 2);
577 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
580 // draw close button if necessary
581 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
583 wxBitmap bmp
= m_disabled_close_bmp
;
585 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
586 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
588 bmp
= m_active_close_bmp
;
591 int offsetY
= tab_y
-1;
592 if (m_flags
& wxAUI_NB_BOTTOM
)
595 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
596 offsetY
+ (tab_height
/2) - (bmp
.GetHeight()/2),
600 IndentPressedBitmap(&rect
, close_button_state
);
601 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
603 *out_button_rect
= rect
;
606 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
608 dc
.DestroyClippingRegion();
611 int wxAuiDefaultTabArt::GetIndentSize()
616 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
617 wxWindow
* WXUNUSED(wnd
),
618 const wxString
& caption
,
619 const wxBitmap
& bitmap
,
620 bool WXUNUSED(active
),
621 int close_button_state
,
624 wxCoord measured_textx
, measured_texty
, tmp
;
626 dc
.SetFont(m_measuring_font
);
627 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
629 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
631 // add padding around the text
632 wxCoord tab_width
= measured_textx
;
633 wxCoord tab_height
= measured_texty
;
635 // if the close button is showing, add space for it
636 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
637 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
639 // if there's a bitmap, add space for it
642 tab_width
+= bitmap
.GetWidth();
643 tab_width
+= 3; // right side bitmap padding
644 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
651 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
653 tab_width
= m_fixed_tab_width
;
656 *x_extent
= tab_width
;
658 return wxSize(tab_width
, tab_height
);
662 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
663 wxWindow
* WXUNUSED(wnd
),
664 const wxRect
& in_rect
,
675 case wxAUI_BUTTON_CLOSE
:
676 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
677 bmp
= m_disabled_close_bmp
;
679 bmp
= m_active_close_bmp
;
681 case wxAUI_BUTTON_LEFT
:
682 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
683 bmp
= m_disabled_left_bmp
;
685 bmp
= m_active_left_bmp
;
687 case wxAUI_BUTTON_RIGHT
:
688 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
689 bmp
= m_disabled_right_bmp
;
691 bmp
= m_active_right_bmp
;
693 case wxAUI_BUTTON_WINDOWLIST
:
694 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
695 bmp
= m_disabled_windowlist_bmp
;
697 bmp
= m_active_windowlist_bmp
;
707 if (orientation
== wxLEFT
)
709 rect
.SetX(in_rect
.x
);
710 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
711 rect
.SetWidth(bmp
.GetWidth());
712 rect
.SetHeight(bmp
.GetHeight());
716 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
717 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
718 bmp
.GetWidth(), bmp
.GetHeight());
721 IndentPressedBitmap(&rect
, button_state
);
722 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
727 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
728 const wxAuiNotebookPageArray
& pages
,
733 size_t i
, count
= pages
.GetCount();
734 for (i
= 0; i
< count
; ++i
)
736 const wxAuiNotebookPage
& page
= pages
.Item(i
);
737 wxString caption
= page
.caption
;
739 // if there is no caption, make it a space. This will prevent
740 // an assert in the menu code.
741 if (caption
.IsEmpty())
744 wxMenuItem
* item
= new wxMenuItem(NULL
, 1000+i
, caption
);
745 if (page
.bitmap
.IsOk())
746 item
->SetBitmap(page
.bitmap
);
747 menuPopup
.Append(item
);
750 // find out where to put the popup menu of window items
751 wxPoint pt
= ::wxGetMousePosition();
752 pt
= wnd
->ScreenToClient(pt
);
754 // find out the screen coordinate at the bottom of the tab ctrl
755 wxRect cli_rect
= wnd
->GetClientRect();
756 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
758 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
759 wnd
->PushEventHandler(cc
);
760 wnd
->PopupMenu(&menuPopup
, pt
);
761 int command
= cc
->GetCommandId();
762 wnd
->PopEventHandler(true);
770 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
771 const wxAuiNotebookPageArray
& pages
,
772 const wxSize
& required_bmp_size
)
775 dc
.SetFont(m_measuring_font
);
777 // sometimes a standard bitmap size needs to be enforced, especially
778 // if some tabs have bitmaps and others don't. This is important because
779 // it prevents the tab control from resizing when tabs are added.
780 wxBitmap measure_bmp
;
781 if (required_bmp_size
.IsFullySpecified())
783 measure_bmp
.Create(required_bmp_size
.x
,
784 required_bmp_size
.y
);
789 size_t i
, page_count
= pages
.GetCount();
790 for (i
= 0; i
< page_count
; ++i
)
792 wxAuiNotebookPage
& page
= pages
.Item(i
);
795 if (measure_bmp
.IsOk())
800 // we don't use the caption text because we don't
801 // want tab heights to be different in the case
802 // of a very short piece of text on one tab and a very
803 // tall piece of text on another tab
805 wxSize s
= GetTabSize(dc
,
810 wxAUI_BUTTON_STATE_HIDDEN
,
813 max_y
= wxMax(max_y
, s
.y
);
819 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
821 m_normal_font
= font
;
824 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
826 m_selected_font
= font
;
829 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
831 m_measuring_font
= font
;
835 // -- wxAuiSimpleTabArt class implementation --
837 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
839 m_normal_font
= *wxNORMAL_FONT
;
840 m_selected_font
= *wxNORMAL_FONT
;
841 m_selected_font
.SetWeight(wxBOLD
);
842 m_measuring_font
= m_selected_font
;
845 m_fixed_tab_width
= 100;
847 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
849 wxColour background_colour
= base_colour
;
850 wxColour normaltab_colour
= base_colour
;
851 wxColour selectedtab_colour
= *wxWHITE
;
853 m_bkbrush
= wxBrush(background_colour
);
854 m_normal_bkbrush
= wxBrush(normaltab_colour
);
855 m_normal_bkpen
= wxPen(normaltab_colour
);
856 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
857 m_selected_bkpen
= wxPen(selectedtab_colour
);
859 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
860 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
862 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
863 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
865 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
866 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
868 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
869 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
873 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
877 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
879 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
883 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
888 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
891 m_fixed_tab_width
= 100;
893 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
895 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
896 tot_width
-= m_active_close_bmp
.GetWidth();
897 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
898 tot_width
-= m_active_windowlist_bmp
.GetWidth();
902 m_fixed_tab_width
= tot_width
/(int)tab_count
;
906 if (m_fixed_tab_width
< 100)
907 m_fixed_tab_width
= 100;
909 if (m_fixed_tab_width
> tot_width
/2)
910 m_fixed_tab_width
= tot_width
/2;
912 if (m_fixed_tab_width
> 220)
913 m_fixed_tab_width
= 220;
916 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
917 wxWindow
* WXUNUSED(wnd
),
921 dc
.SetBrush(m_bkbrush
);
922 dc
.SetPen(*wxTRANSPARENT_PEN
);
923 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
926 dc
.SetPen(*wxGREY_PEN
);
927 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
931 // DrawTab() draws an individual tab.
934 // in_rect - rectangle the tab should be confined to
935 // caption - tab's caption
936 // active - whether or not the tab is active
937 // out_rect - actual output rectangle
938 // x_extent - the advance x; where the next tab should start
940 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
942 const wxAuiNotebookPage
& page
,
943 const wxRect
& in_rect
,
944 int close_button_state
,
945 wxRect
* out_tab_rect
,
946 wxRect
* out_button_rect
,
949 wxCoord normal_textx
, normal_texty
;
950 wxCoord selected_textx
, selected_texty
;
951 wxCoord textx
, texty
;
953 // if the caption is empty, measure some temporary text
954 wxString caption
= page
.caption
;
958 dc
.SetFont(m_selected_font
);
959 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
961 dc
.SetFont(m_normal_font
);
962 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
964 // figure out the size of the tab
965 wxSize tab_size
= GetTabSize(dc
,
973 wxCoord tab_height
= tab_size
.y
;
974 wxCoord tab_width
= tab_size
.x
;
975 wxCoord tab_x
= in_rect
.x
;
976 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
978 caption
= page
.caption
;
980 // select pen, brush and font for the tab to be drawn
984 dc
.SetPen(m_selected_bkpen
);
985 dc
.SetBrush(m_selected_bkbrush
);
986 dc
.SetFont(m_selected_font
);
987 textx
= selected_textx
;
988 texty
= selected_texty
;
992 dc
.SetPen(m_normal_bkpen
);
993 dc
.SetBrush(m_normal_bkbrush
);
994 dc
.SetFont(m_normal_font
);
995 textx
= normal_textx
;
996 texty
= normal_texty
;
1003 points
[0].x
= tab_x
;
1004 points
[0].y
= tab_y
+ tab_height
- 1;
1005 points
[1].x
= tab_x
+ tab_height
- 3;
1006 points
[1].y
= tab_y
+ 2;
1007 points
[2].x
= tab_x
+ tab_height
+ 3;
1008 points
[2].y
= tab_y
;
1009 points
[3].x
= tab_x
+ tab_width
- 2;
1010 points
[3].y
= tab_y
;
1011 points
[4].x
= tab_x
+ tab_width
;
1012 points
[4].y
= tab_y
+ 2;
1013 points
[5].x
= tab_x
+ tab_width
;
1014 points
[5].y
= tab_y
+ tab_height
- 1;
1015 points
[6] = points
[0];
1017 dc
.SetClippingRegion(in_rect
);
1019 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
1021 dc
.SetPen(*wxGREY_PEN
);
1023 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1024 dc
.DrawLines(WXSIZEOF(points
), points
);
1029 int close_button_width
= 0;
1030 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1032 close_button_width
= m_active_close_bmp
.GetWidth();
1033 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1037 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1040 // set minimum text offset
1041 if (text_offset
< tab_x
+ tab_height
)
1042 text_offset
= tab_x
+ tab_height
;
1044 // chop text if necessary
1045 wxString draw_text
= wxAuiChopText(dc
,
1047 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1050 dc
.DrawText(draw_text
,
1052 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1055 // draw focus rectangle
1056 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1058 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1059 selected_textx
, selected_texty
);
1061 focusRect
.Inflate(2, 2);
1063 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1066 // draw close button if necessary
1067 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1071 bmp
= m_active_close_bmp
;
1073 bmp
= m_disabled_close_bmp
;
1075 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1076 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1079 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1081 *out_button_rect
= rect
;
1085 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1087 dc
.DestroyClippingRegion();
1090 int wxAuiSimpleTabArt::GetIndentSize()
1095 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1096 wxWindow
* WXUNUSED(wnd
),
1097 const wxString
& caption
,
1098 const wxBitmap
& WXUNUSED(bitmap
),
1099 bool WXUNUSED(active
),
1100 int close_button_state
,
1103 wxCoord measured_textx
, measured_texty
;
1105 dc
.SetFont(m_measuring_font
);
1106 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1108 wxCoord tab_height
= measured_texty
+ 4;
1109 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1111 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1112 tab_width
+= m_active_close_bmp
.GetWidth();
1114 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1116 tab_width
= m_fixed_tab_width
;
1119 *x_extent
= tab_width
- (tab_height
/2) - 1;
1121 return wxSize(tab_width
, tab_height
);
1125 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1126 wxWindow
* WXUNUSED(wnd
),
1127 const wxRect
& in_rect
,
1138 case wxAUI_BUTTON_CLOSE
:
1139 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1140 bmp
= m_disabled_close_bmp
;
1142 bmp
= m_active_close_bmp
;
1144 case wxAUI_BUTTON_LEFT
:
1145 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1146 bmp
= m_disabled_left_bmp
;
1148 bmp
= m_active_left_bmp
;
1150 case wxAUI_BUTTON_RIGHT
:
1151 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1152 bmp
= m_disabled_right_bmp
;
1154 bmp
= m_active_right_bmp
;
1156 case wxAUI_BUTTON_WINDOWLIST
:
1157 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1158 bmp
= m_disabled_windowlist_bmp
;
1160 bmp
= m_active_windowlist_bmp
;
1169 if (orientation
== wxLEFT
)
1171 rect
.SetX(in_rect
.x
);
1172 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1173 rect
.SetWidth(bmp
.GetWidth());
1174 rect
.SetHeight(bmp
.GetHeight());
1178 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1179 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1180 bmp
.GetWidth(), bmp
.GetHeight());
1184 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1189 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1190 const wxAuiNotebookPageArray
& pages
,
1195 size_t i
, count
= pages
.GetCount();
1196 for (i
= 0; i
< count
; ++i
)
1198 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1199 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1202 if (active_idx
!= -1)
1204 menuPopup
.Check(1000+active_idx
, true);
1207 // find out where to put the popup menu of window
1208 // items. Subtract 100 for now to center the menu
1209 // a bit, until a better mechanism can be implemented
1210 wxPoint pt
= ::wxGetMousePosition();
1211 pt
= wnd
->ScreenToClient(pt
);
1217 // find out the screen coordinate at the bottom of the tab ctrl
1218 wxRect cli_rect
= wnd
->GetClientRect();
1219 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1221 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1222 wnd
->PushEventHandler(cc
);
1223 wnd
->PopupMenu(&menuPopup
, pt
);
1224 int command
= cc
->GetCommandId();
1225 wnd
->PopEventHandler(true);
1227 if (command
>= 1000)
1228 return command
-1000;
1233 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1234 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1235 const wxSize
& WXUNUSED(required_bmp_size
))
1238 dc
.SetFont(m_measuring_font
);
1240 wxSize s
= GetTabSize(dc
,
1245 wxAUI_BUTTON_STATE_HIDDEN
,
1250 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1252 m_normal_font
= font
;
1255 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1257 m_selected_font
= font
;
1260 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1262 m_measuring_font
= font
;
1268 // -- wxAuiTabContainer class implementation --
1271 // wxAuiTabContainer is a class which contains information about each
1272 // tab. It also can render an entire tab control to a specified DC.
1273 // It's not a window class itself, because this code will be used by
1274 // the wxFrameMananger, where it is disadvantageous to have separate
1275 // windows for each tab control in the case of "docked tabs"
1277 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1278 // which can be used as a tab control in the normal sense.
1281 wxAuiTabContainer::wxAuiTabContainer()
1285 m_art
= new wxAuiDefaultTabArt
;
1287 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1288 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1289 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1290 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1293 wxAuiTabContainer::~wxAuiTabContainer()
1298 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1305 m_art
->SetFlags(m_flags
);
1309 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1314 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1318 // check for new close button settings
1319 RemoveButton(wxAUI_BUTTON_LEFT
);
1320 RemoveButton(wxAUI_BUTTON_RIGHT
);
1321 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1322 RemoveButton(wxAUI_BUTTON_CLOSE
);
1325 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1327 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1328 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1331 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1333 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1336 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1338 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1343 m_art
->SetFlags(m_flags
);
1347 unsigned int wxAuiTabContainer::GetFlags() const
1353 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1355 m_art
->SetNormalFont(font
);
1358 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1360 m_art
->SetSelectedFont(font
);
1363 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1365 m_art
->SetMeasuringFont(font
);
1368 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1374 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1378 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1379 const wxAuiNotebookPage
& info
)
1381 wxAuiNotebookPage page_info
;
1383 page_info
.window
= page
;
1385 m_pages
.Add(page_info
);
1387 // let the art provider know how many pages we have
1390 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1396 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1397 const wxAuiNotebookPage
& info
,
1400 wxAuiNotebookPage page_info
;
1402 page_info
.window
= page
;
1404 if (idx
>= m_pages
.GetCount())
1405 m_pages
.Add(page_info
);
1407 m_pages
.Insert(page_info
, idx
);
1409 // let the art provider know how many pages we have
1412 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1418 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1421 int idx
= GetIdxFromWindow(page
);
1425 // get page entry, make a copy of it
1426 wxAuiNotebookPage p
= GetPage(idx
);
1428 // remove old page entry
1431 // insert page where it should be
1432 InsertPage(page
, p
, new_idx
);
1437 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1439 size_t i
, page_count
= m_pages
.GetCount();
1440 for (i
= 0; i
< page_count
; ++i
)
1442 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1443 if (page
.window
== wnd
)
1445 m_pages
.RemoveAt(i
);
1447 // let the art provider know how many pages we have
1450 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1460 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1464 size_t i
, page_count
= m_pages
.GetCount();
1465 for (i
= 0; i
< page_count
; ++i
)
1467 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1468 if (page
.window
== wnd
)
1475 page
.active
= false;
1482 void wxAuiTabContainer::SetNoneActive()
1484 size_t i
, page_count
= m_pages
.GetCount();
1485 for (i
= 0; i
< page_count
; ++i
)
1487 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1488 page
.active
= false;
1492 bool wxAuiTabContainer::SetActivePage(size_t page
)
1494 if (page
>= m_pages
.GetCount())
1497 return SetActivePage(m_pages
.Item(page
).window
);
1500 int wxAuiTabContainer::GetActivePage() const
1502 size_t i
, page_count
= m_pages
.GetCount();
1503 for (i
= 0; i
< page_count
; ++i
)
1505 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1513 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1515 if (idx
>= m_pages
.GetCount())
1518 return m_pages
[idx
].window
;
1521 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1523 const size_t page_count
= m_pages
.GetCount();
1524 for ( size_t i
= 0; i
< page_count
; ++i
)
1526 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1527 if (page
.window
== wnd
)
1533 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1535 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1537 return m_pages
[idx
];
1540 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1542 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1544 return m_pages
[idx
];
1547 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1552 size_t wxAuiTabContainer::GetPageCount() const
1554 return m_pages
.GetCount();
1557 void wxAuiTabContainer::AddButton(int id
,
1559 const wxBitmap
& normal_bitmap
,
1560 const wxBitmap
& disabled_bitmap
)
1562 wxAuiTabContainerButton button
;
1564 button
.bitmap
= normal_bitmap
;
1565 button
.dis_bitmap
= disabled_bitmap
;
1566 button
.location
= location
;
1567 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1569 m_buttons
.Add(button
);
1572 void wxAuiTabContainer::RemoveButton(int id
)
1574 size_t i
, button_count
= m_buttons
.GetCount();
1576 for (i
= 0; i
< button_count
; ++i
)
1578 if (m_buttons
.Item(i
).id
== id
)
1580 m_buttons
.RemoveAt(i
);
1588 size_t wxAuiTabContainer::GetTabOffset() const
1590 return m_tab_offset
;
1593 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1595 m_tab_offset
= offset
;
1601 // Render() renders the tab catalog to the specified DC
1602 // It is a virtual function and can be overridden to
1603 // provide custom drawing capabilities
1604 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1606 if (!raw_dc
|| !raw_dc
->IsOk())
1611 // use the same layout direction as the window DC uses to ensure that the
1612 // text is rendered correctly
1613 dc
.SetLayoutDirection(raw_dc
->GetLayoutDirection());
1617 size_t page_count
= m_pages
.GetCount();
1618 size_t button_count
= m_buttons
.GetCount();
1620 // create off-screen bitmap
1621 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1622 dc
.SelectObject(bmp
);
1627 // find out if size of tabs is larger than can be
1628 // afforded on screen
1629 int total_width
= 0;
1630 int visible_width
= 0;
1631 for (i
= 0; i
< page_count
; ++i
)
1633 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1635 // determine if a close button is on this tab
1636 bool close_button
= false;
1637 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1638 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1640 close_button
= true;
1645 wxSize size
= m_art
->GetTabSize(dc
,
1651 wxAUI_BUTTON_STATE_NORMAL
:
1652 wxAUI_BUTTON_STATE_HIDDEN
,
1655 if (i
+1 < page_count
)
1656 total_width
+= x_extent
;
1658 total_width
+= size
.x
;
1660 if (i
>= m_tab_offset
)
1662 if (i
+1 < page_count
)
1663 visible_width
+= x_extent
;
1665 visible_width
+= size
.x
;
1669 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1671 // show left/right buttons
1672 for (i
= 0; i
< button_count
; ++i
)
1674 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1675 if (button
.id
== wxAUI_BUTTON_LEFT
||
1676 button
.id
== wxAUI_BUTTON_RIGHT
)
1678 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1684 // hide left/right buttons
1685 for (i
= 0; i
< button_count
; ++i
)
1687 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1688 if (button
.id
== wxAUI_BUTTON_LEFT
||
1689 button
.id
== wxAUI_BUTTON_RIGHT
)
1691 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1696 // determine whether left button should be enabled
1697 for (i
= 0; i
< button_count
; ++i
)
1699 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1700 if (button
.id
== wxAUI_BUTTON_LEFT
)
1702 if (m_tab_offset
== 0)
1703 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1705 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1707 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1709 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1710 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1712 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1719 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1722 int left_buttons_width
= 0;
1723 int right_buttons_width
= 0;
1727 // draw the buttons on the right side
1728 offset
= m_rect
.x
+ m_rect
.width
;
1729 for (i
= 0; i
< button_count
; ++i
)
1731 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1733 if (button
.location
!= wxRIGHT
)
1735 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1738 wxRect button_rect
= m_rect
;
1739 button_rect
.SetY(1);
1740 button_rect
.SetWidth(offset
);
1742 m_art
->DrawButton(dc
,
1750 offset
-= button
.rect
.GetWidth();
1751 right_buttons_width
+= button
.rect
.GetWidth();
1758 // draw the buttons on the left side
1760 for (i
= 0; i
< button_count
; ++i
)
1762 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1764 if (button
.location
!= wxLEFT
)
1766 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1769 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1771 m_art
->DrawButton(dc
,
1779 offset
+= button
.rect
.GetWidth();
1780 left_buttons_width
+= button
.rect
.GetWidth();
1783 offset
= left_buttons_width
;
1786 offset
+= m_art
->GetIndentSize();
1789 // prepare the tab-close-button array
1790 // make sure tab button entries which aren't used are marked as hidden
1791 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1792 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1794 // make sure there are enough tab button entries to accommodate all tabs
1795 while (m_tab_close_buttons
.GetCount() < page_count
)
1797 wxAuiTabContainerButton tempbtn
;
1798 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1799 tempbtn
.location
= wxCENTER
;
1800 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1801 m_tab_close_buttons
.Add(tempbtn
);
1805 // buttons before the tab offset must be set to hidden
1806 for (i
= 0; i
< m_tab_offset
; ++i
)
1808 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1814 size_t active
= 999;
1815 int active_offset
= 0;
1819 wxRect rect
= m_rect
;
1821 rect
.height
= m_rect
.height
;
1823 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1825 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1826 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1828 // determine if a close button is on this tab
1829 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1830 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1832 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1834 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1835 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1836 tab_button
.location
= wxCENTER
;
1841 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1845 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1847 if (rect
.width
<= 0)
1854 tab_button
.cur_state
,
1862 active_offset
= offset
;
1870 // make sure to deactivate buttons which are off the screen to the right
1871 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1873 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1877 // draw the active tab again so it stands in the foreground
1878 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1880 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1882 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1884 rect
.x
= active_offset
;
1889 tab_button
.cur_state
,
1896 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1897 m_rect
.GetWidth(), m_rect
.GetHeight(),
1901 // Is the tab visible?
1902 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1904 if (!dc
|| !dc
->IsOk())
1908 size_t page_count
= m_pages
.GetCount();
1909 size_t button_count
= m_buttons
.GetCount();
1911 // Hasn't been rendered yet; assume it's visible
1912 if (m_tab_close_buttons
.GetCount() < page_count
)
1915 // First check if both buttons are disabled - if so, there's no need to
1916 // check further for visibility.
1917 int arrowButtonVisibleCount
= 0;
1918 for (i
= 0; i
< button_count
; ++i
)
1920 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1921 if (button
.id
== wxAUI_BUTTON_LEFT
||
1922 button
.id
== wxAUI_BUTTON_RIGHT
)
1924 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1925 arrowButtonVisibleCount
++;
1929 // Tab must be visible
1930 if (arrowButtonVisibleCount
== 0)
1933 // If tab is less than the given offset, it must be invisible by definition
1934 if (tabPage
< tabOffset
)
1938 int left_buttons_width
= 0;
1939 int right_buttons_width
= 0;
1943 // calculate size of the buttons on the right side
1944 offset
= m_rect
.x
+ m_rect
.width
;
1945 for (i
= 0; i
< button_count
; ++i
)
1947 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1949 if (button
.location
!= wxRIGHT
)
1951 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1954 offset
-= button
.rect
.GetWidth();
1955 right_buttons_width
+= button
.rect
.GetWidth();
1960 // calculate size of the buttons on the left side
1961 for (i
= 0; i
< button_count
; ++i
)
1963 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1965 if (button
.location
!= wxLEFT
)
1967 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1970 offset
+= button
.rect
.GetWidth();
1971 left_buttons_width
+= button
.rect
.GetWidth();
1974 offset
= left_buttons_width
;
1977 offset
+= m_art
->GetIndentSize();
1981 wxRect rect
= m_rect
;
1983 rect
.height
= m_rect
.height
;
1985 // See if the given page is visible at the given tab offset (effectively scroll position)
1986 for (i
= tabOffset
; i
< page_count
; ++i
)
1988 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1989 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1992 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1994 if (rect
.width
<= 0)
1995 return false; // haven't found the tab, and we've run out of space, so return false
1998 wxSize size
= m_art
->GetTabSize(*dc
,
2003 tab_button
.cur_state
,
2008 if (i
== (size_t) tabPage
)
2010 // If not all of the tab is visible, and supposing there's space to display it all,
2011 // we could do better so we return false.
2012 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
2019 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2020 // further looping in calling code.
2024 // Make the tab visible if it wasn't already
2025 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
2028 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2031 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2033 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2043 // TabHitTest() tests if a tab was hit, passing the window pointer
2044 // back if that condition was fulfilled. The function returns
2045 // true if a tab was hit, otherwise false
2046 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2048 if (!m_rect
.Contains(x
,y
))
2051 wxAuiTabContainerButton
* btn
= NULL
;
2052 if (ButtonHitTest(x
, y
, &btn
) && !(btn
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2054 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2058 size_t i
, page_count
= m_pages
.GetCount();
2060 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2062 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2063 if (page
.rect
.Contains(x
,y
))
2074 // ButtonHitTest() tests if a button was hit. The function returns
2075 // true if a button was hit, otherwise false
2076 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2077 wxAuiTabContainerButton
** hit
) const
2079 if (!m_rect
.Contains(x
,y
))
2082 size_t i
, button_count
;
2085 button_count
= m_buttons
.GetCount();
2086 for (i
= 0; i
< button_count
; ++i
)
2088 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2089 if (button
.rect
.Contains(x
,y
) &&
2090 !(button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
))
2098 button_count
= m_tab_close_buttons
.GetCount();
2099 for (i
= 0; i
< button_count
; ++i
)
2101 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2102 if (button
.rect
.Contains(x
,y
) &&
2103 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2104 wxAUI_BUTTON_STATE_DISABLED
)))
2117 // the utility function ShowWnd() is the same as show,
2118 // except it handles wxAuiMDIChildFrame windows as well,
2119 // as the Show() method on this class is "unplugged"
2120 static void ShowWnd(wxWindow
* wnd
, bool show
)
2123 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2125 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2136 // DoShowHide() this function shows the active window, then
2137 // hides all of the other windows (in that order)
2138 void wxAuiTabContainer::DoShowHide()
2140 wxAuiNotebookPageArray
& pages
= GetPages();
2141 size_t i
, page_count
= pages
.GetCount();
2143 // show new active page first
2144 for (i
= 0; i
< page_count
; ++i
)
2146 wxAuiNotebookPage
& page
= pages
.Item(i
);
2149 ShowWnd(page
.window
, true);
2154 // hide all other pages
2155 for (i
= 0; i
< page_count
; ++i
)
2157 wxAuiNotebookPage
& page
= pages
.Item(i
);
2159 ShowWnd(page
.window
, false);
2168 // -- wxAuiTabCtrl class implementation --
2172 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2173 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2174 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2175 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2176 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2177 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick
)
2178 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2179 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2180 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2181 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2182 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2183 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2184 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2185 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2186 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2187 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2188 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2189 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost
)
2193 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2197 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2199 SetName(wxT("wxAuiTabCtrl"));
2200 m_click_pt
= wxDefaultPosition
;
2201 m_is_dragging
= false;
2202 m_hover_button
= NULL
;
2203 m_pressed_button
= NULL
;
2206 wxAuiTabCtrl::~wxAuiTabCtrl()
2210 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2214 dc
.SetFont(GetFont());
2216 if (GetPageCount() > 0)
2220 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2224 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2226 wxSize s
= evt
.GetSize();
2227 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2231 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2234 m_click_pt
= wxDefaultPosition
;
2235 m_is_dragging
= false;
2237 m_pressed_button
= NULL
;
2241 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2243 int new_selection
= GetIdxFromWindow(wnd
);
2245 // wxAuiNotebooks always want to receive this event
2246 // even if the tab is already active, because they may
2247 // have multiple tab controls
2248 if (new_selection
!= GetActivePage() ||
2249 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2251 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2252 e
.SetSelection(new_selection
);
2253 e
.SetOldSelection(GetActivePage());
2254 e
.SetEventObject(this);
2255 GetEventHandler()->ProcessEvent(e
);
2258 m_click_pt
.x
= evt
.m_x
;
2259 m_click_pt
.y
= evt
.m_y
;
2265 m_pressed_button
= m_hover_button
;
2266 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2272 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
2276 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2278 if (GetCapture() == this)
2283 m_is_dragging
= false;
2285 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2286 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2287 evt
.SetOldSelection(evt
.GetSelection());
2288 evt
.SetEventObject(this);
2289 GetEventHandler()->ProcessEvent(evt
);
2294 if (m_pressed_button
)
2296 // make sure we're still clicking the button
2297 wxAuiTabContainerButton
* button
= NULL
;
2298 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
) ||
2299 button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
)
2302 if (button
!= m_pressed_button
)
2304 m_pressed_button
= NULL
;
2311 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2313 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2314 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2315 evt
.SetInt(m_pressed_button
->id
);
2316 evt
.SetEventObject(this);
2317 GetEventHandler()->ProcessEvent(evt
);
2320 m_pressed_button
= NULL
;
2323 m_click_pt
= wxDefaultPosition
;
2324 m_is_dragging
= false;
2328 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2330 wxWindow
* wnd
= NULL
;
2331 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2334 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2335 e
.SetEventObject(this);
2336 e
.SetSelection(GetIdxFromWindow(wnd
));
2337 GetEventHandler()->ProcessEvent(e
);
2340 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2342 wxWindow
* wnd
= NULL
;
2343 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2346 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2347 e
.SetEventObject(this);
2348 e
.SetSelection(GetIdxFromWindow(wnd
));
2349 GetEventHandler()->ProcessEvent(e
);
2352 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2354 wxWindow
* wnd
= NULL
;
2355 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2358 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2359 e
.SetEventObject(this);
2360 e
.SetSelection(GetIdxFromWindow(wnd
));
2361 GetEventHandler()->ProcessEvent(e
);
2364 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2366 wxWindow
* wnd
= NULL
;
2367 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2370 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2371 e
.SetEventObject(this);
2372 e
.SetSelection(GetIdxFromWindow(wnd
));
2373 GetEventHandler()->ProcessEvent(e
);
2376 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent
& evt
)
2379 wxAuiTabContainerButton
* button
;
2380 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
) && !ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2382 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
2383 e
.SetEventObject(this);
2384 GetEventHandler()->ProcessEvent(e
);
2388 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2390 wxPoint pos
= evt
.GetPosition();
2392 // check if the mouse is hovering above a button
2393 wxAuiTabContainerButton
* button
;
2394 if (ButtonHitTest(pos
.x
, pos
.y
, &button
) && !(button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2396 if (m_hover_button
&& button
!= m_hover_button
)
2398 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2399 m_hover_button
= NULL
;
2404 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2406 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2409 m_hover_button
= button
;
2417 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2418 m_hover_button
= NULL
;
2425 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2430 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2431 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2432 evt
.SetOldSelection(evt
.GetSelection());
2433 evt
.SetEventObject(this);
2434 GetEventHandler()->ProcessEvent(evt
);
2439 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2440 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2442 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2443 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2445 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2446 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2447 evt
.SetOldSelection(evt
.GetSelection());
2448 evt
.SetEventObject(this);
2449 GetEventHandler()->ProcessEvent(evt
);
2451 m_is_dragging
= true;
2455 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2459 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2460 m_hover_button
= NULL
;
2466 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2468 int button
= event
.GetInt();
2470 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2472 if (button
== wxAUI_BUTTON_LEFT
)
2474 if (GetTabOffset() > 0)
2476 SetTabOffset(GetTabOffset()-1);
2483 SetTabOffset(GetTabOffset()+1);
2488 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2490 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2494 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2495 e
.SetSelection(idx
);
2496 e
.SetOldSelection(GetActivePage());
2497 e
.SetEventObject(this);
2498 GetEventHandler()->ProcessEvent(e
);
2507 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2512 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2517 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2519 if (GetActivePage() == -1)
2525 // We can't leave tab processing to the system; on Windows, tabs and keys
2526 // get eaten by the system and not processed properly if we specify both
2527 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2528 // we don't key arrow key events.
2530 int key
= event
.GetKeyCode();
2532 if (key
== WXK_NUMPAD_PAGEUP
)
2534 if (key
== WXK_NUMPAD_PAGEDOWN
)
2536 if (key
== WXK_NUMPAD_HOME
)
2538 if (key
== WXK_NUMPAD_END
)
2540 if (key
== WXK_NUMPAD_LEFT
)
2542 if (key
== WXK_NUMPAD_RIGHT
)
2545 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2547 bool bCtrlDown
= event
.ControlDown();
2548 bool bShiftDown
= event
.ShiftDown();
2550 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2551 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2552 bool bFromTab
= (key
== WXK_TAB
);
2554 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2561 wxNavigationKeyEvent keyEvent
;
2562 keyEvent
.SetDirection(bForward
);
2563 keyEvent
.SetWindowChange(bWindowChange
);
2564 keyEvent
.SetFromTab(bFromTab
);
2565 keyEvent
.SetEventObject(nb
);
2567 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2569 // Not processed? Do an explicit tab into the page.
2570 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2577 if (m_pages
.GetCount() < 2)
2585 int forwardKey
, backwardKey
;
2586 if (GetLayoutDirection() == wxLayout_RightToLeft
)
2588 forwardKey
= WXK_LEFT
;
2589 backwardKey
= WXK_RIGHT
;
2593 forwardKey
= WXK_RIGHT
;
2594 backwardKey
= WXK_LEFT
;
2597 if (key
== forwardKey
)
2599 if (m_pages
.GetCount() > 1)
2601 if (GetActivePage() == -1)
2603 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2604 newPage
= GetActivePage() + 1;
2607 else if (key
== backwardKey
)
2609 if (m_pages
.GetCount() > 1)
2611 if (GetActivePage() == -1)
2612 newPage
= (int) (m_pages
.GetCount() - 1);
2613 else if (GetActivePage() > 0)
2614 newPage
= GetActivePage() - 1;
2617 else if (key
== WXK_HOME
)
2621 else if (key
== WXK_END
)
2623 newPage
= (int) (m_pages
.GetCount() - 1);
2630 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2631 e
.SetSelection(newPage
);
2632 e
.SetOldSelection(newPage
);
2633 e
.SetEventObject(this);
2634 this->GetEventHandler()->ProcessEvent(e
);
2640 // wxTabFrame is an interesting case. It's important that all child pages
2641 // of the multi-notebook control are all actually children of that control
2642 // (and not grandchildren). wxTabFrame facilitates this. There is one
2643 // instance of wxTabFrame for each tab control inside the multi-notebook.
2644 // It's important to know that wxTabFrame is not a real window, but it merely
2645 // used to capture the dimensions/positioning of the internal tab control and
2646 // it's managed page windows
2648 class wxTabFrame
: public wxWindow
2655 m_rect
= wxRect(0,0,200,200);
2656 m_tab_ctrl_height
= 20;
2664 void SetTabCtrlHeight(int h
)
2666 m_tab_ctrl_height
= h
;
2670 void DoSetSize(int x
, int y
,
2671 int width
, int height
,
2672 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2674 m_rect
= wxRect(x
, y
, width
, height
);
2678 void DoGetClientSize(int* x
, int* y
) const
2685 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2692 if (m_tabs
->IsFrozen() || m_tabs
->GetParent()->IsFrozen())
2695 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2696 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2698 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2699 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2700 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2702 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2704 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2705 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2706 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2708 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2709 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2714 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2715 size_t i
, page_count
= pages
.GetCount();
2717 for (i
= 0; i
< page_count
; ++i
)
2719 int height
= m_rect
.height
- m_tab_ctrl_height
;
2722 // avoid passing negative height to wxWindow::SetSize(), this
2723 // results in assert failures/GTK+ warnings
2727 wxAuiNotebookPage
& page
= pages
.Item(i
);
2728 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2730 page
.window
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, height
);
2732 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2734 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2735 m_rect
.width
, height
);
2737 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2738 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2741 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2743 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2744 wnd
->ApplyMDIChildFrameRect();
2751 void DoGetSize(int* x
, int* y
) const
2754 *x
= m_rect
.GetWidth();
2756 *y
= m_rect
.GetHeight();
2767 wxAuiTabCtrl
* m_tabs
;
2768 int m_tab_ctrl_height
;
2772 const int wxAuiBaseTabCtrlId
= 5380;
2775 // -- wxAuiNotebook class implementation --
2777 #define EVT_AUI_RANGE(id1, id2, event, func) \
2778 wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func))
2780 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2781 EVT_SIZE(wxAuiNotebook::OnSize
)
2782 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2783 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2784 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2785 wxAuiNotebook::OnTabClicked
)
2786 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2787 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2788 wxAuiNotebook::OnTabBeginDrag
)
2789 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2790 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2791 wxAuiNotebook::OnTabEndDrag
)
2792 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2793 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2794 wxAuiNotebook::OnTabDragMotion
)
2795 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2796 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2797 wxAuiNotebook::OnTabButton
)
2798 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2799 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2800 wxAuiNotebook::OnTabMiddleDown
)
2801 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2802 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2803 wxAuiNotebook::OnTabMiddleUp
)
2804 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2805 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2806 wxAuiNotebook::OnTabRightDown
)
2807 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2808 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2809 wxAuiNotebook::OnTabRightUp
)
2810 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2811 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
,
2812 wxAuiNotebook::OnTabBgDClick
)
2813 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2815 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2816 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2818 // Avoid clash with container event handler functions
2819 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2823 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2825 wxAuiNotebook::wxAuiNotebook()
2828 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2830 m_tab_ctrl_height
= 20;
2831 m_requested_bmp_size
= wxDefaultSize
;
2832 m_requested_tabctrl_height
= -1;
2835 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2839 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2842 m_requested_bmp_size
= wxDefaultSize
;
2843 m_requested_tabctrl_height
= -1;
2844 InitNotebook(style
);
2847 bool wxAuiNotebook::Create(wxWindow
* parent
,
2853 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2856 InitNotebook(style
);
2861 // InitNotebook() contains common initialization
2862 // code called by all constructors
2863 void wxAuiNotebook::InitNotebook(long style
)
2865 WX_INIT_CONTROL_CONTAINER();
2866 // SetCanFocus(false);
2868 SetName(wxT("wxAuiNotebook"));
2870 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2872 m_flags
= (unsigned int)style
;
2873 m_tab_ctrl_height
= 20;
2875 m_normal_font
= *wxNORMAL_FONT
;
2876 m_selected_font
= *wxNORMAL_FONT
;
2877 m_selected_font
.SetWeight(wxBOLD
);
2879 SetArtProvider(new wxAuiDefaultTabArt
);
2881 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2882 m_dummy_wnd
->SetSize(200, 200);
2883 m_dummy_wnd
->Show(false);
2885 m_mgr
.SetManagedWindow(this);
2886 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2887 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2889 m_mgr
.AddPane(m_dummy_wnd
,
2890 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2895 wxAuiNotebook::~wxAuiNotebook()
2897 // Indicate we're deleting pages
2900 while ( GetPageCount() > 0 )
2906 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2908 m_tabs
.SetArtProvider(art
);
2910 // Update the height and do nothing else if it did something but otherwise
2911 // (i.e. if the new art provider uses the same height as the old one) we
2912 // need to manually set the art provider for all tabs ourselves.
2913 if ( !UpdateTabCtrlHeight() )
2915 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2916 const size_t pane_count
= all_panes
.GetCount();
2917 for (size_t i
= 0; i
< pane_count
; ++i
)
2919 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2920 if (pane
.name
== wxT("dummy"))
2922 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2923 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2924 tabctrl
->SetArtProvider(art
->Clone());
2929 // SetTabCtrlHeight() is the highest-level override of the
2930 // tab height. A call to this function effectively enforces a
2931 // specified tab ctrl height, overriding all other considerations,
2932 // such as text or bitmap height. It overrides any call to
2933 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2934 // any previous call and returns to the default behavior
2936 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2938 m_requested_tabctrl_height
= height
;
2940 // if window is already initialized, recalculate the tab height
2943 UpdateTabCtrlHeight();
2948 // SetUniformBitmapSize() ensures that all tabs will have
2949 // the same height, even if some tabs don't have bitmaps
2950 // Passing wxDefaultSize to this function will instruct
2951 // the control to use dynamic tab height-- so when a tab
2952 // with a large bitmap is added, the tab ctrl's height will
2953 // automatically increase to accommodate the bitmap
2955 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2957 m_requested_bmp_size
= size
;
2959 // if window is already initialized, recalculate the tab height
2962 UpdateTabCtrlHeight();
2966 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2967 // to be used internally
2968 bool wxAuiNotebook::UpdateTabCtrlHeight()
2970 // get the tab ctrl height we will use
2971 int height
= CalculateTabCtrlHeight();
2973 // if the tab control height needs to change, update
2974 // all of our tab controls with the new height
2975 if (m_tab_ctrl_height
== height
)
2978 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2980 m_tab_ctrl_height
= height
;
2982 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2983 size_t i
, pane_count
= all_panes
.GetCount();
2984 for (i
= 0; i
< pane_count
; ++i
)
2986 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2987 if (pane
.name
== wxT("dummy"))
2989 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2990 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2991 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2992 tabctrl
->SetArtProvider(art
->Clone());
2993 tab_frame
->DoSizing();
2999 void wxAuiNotebook::UpdateHintWindowSize()
3001 wxSize size
= CalculateNewSplitSize();
3003 // the placeholder hint window should be set to this size
3004 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
3008 info
.BestSize(size
);
3009 m_dummy_wnd
->SetSize(size
);
3014 // calculates the size of the new split
3015 wxSize
wxAuiNotebook::CalculateNewSplitSize()
3017 // count number of tab controls
3018 int tab_ctrl_count
= 0;
3019 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3020 size_t i
, pane_count
= all_panes
.GetCount();
3021 for (i
= 0; i
< pane_count
; ++i
)
3023 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3024 if (pane
.name
== wxT("dummy"))
3029 wxSize new_split_size
;
3031 // if there is only one tab control, the first split
3032 // should happen around the middle
3033 if (tab_ctrl_count
< 2)
3035 new_split_size
= GetClientSize();
3036 new_split_size
.x
/= 2;
3037 new_split_size
.y
/= 2;
3041 // this is in place of a more complicated calculation
3042 // that needs to be implemented
3043 new_split_size
= wxSize(180,180);
3046 return new_split_size
;
3049 int wxAuiNotebook::CalculateTabCtrlHeight()
3051 // if a fixed tab ctrl height is specified,
3052 // just return that instead of calculating a
3054 if (m_requested_tabctrl_height
!= -1)
3055 return m_requested_tabctrl_height
;
3057 // find out new best tab height
3058 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
3060 return art
->GetBestTabCtrlSize(this,
3062 m_requested_bmp_size
);
3066 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
3068 return m_tabs
.GetArtProvider();
3071 void wxAuiNotebook::SetWindowStyleFlag(long style
)
3073 wxControl::SetWindowStyleFlag(style
);
3075 m_flags
= (unsigned int)style
;
3077 // if the control is already initialized
3078 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
3080 // let all of the tab children know about the new style
3082 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3083 size_t i
, pane_count
= all_panes
.GetCount();
3084 for (i
= 0; i
< pane_count
; ++i
)
3086 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3087 if (pane
.name
== wxT("dummy"))
3089 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3090 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
3091 tabctrl
->SetFlags(m_flags
);
3092 tabframe
->DoSizing();
3100 bool wxAuiNotebook::AddPage(wxWindow
* page
,
3101 const wxString
& caption
,
3103 const wxBitmap
& bitmap
)
3105 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
3108 bool wxAuiNotebook::InsertPage(size_t page_idx
,
3110 const wxString
& caption
,
3112 const wxBitmap
& bitmap
)
3114 wxASSERT_MSG(page
, wxT("page pointer must be non-NULL"));
3118 page
->Reparent(this);
3120 wxAuiNotebookPage info
;
3122 info
.caption
= caption
;
3123 info
.bitmap
= bitmap
;
3124 info
.active
= false;
3126 // if there are currently no tabs, the first added
3127 // tab must be active
3128 if (m_tabs
.GetPageCount() == 0)
3131 m_tabs
.InsertPage(page
, info
, page_idx
);
3133 // if that was the first page added, even if
3134 // select is false, it must become the "current page"
3135 // (though no select events will be fired)
3136 if (!select
&& m_tabs
.GetPageCount() == 1)
3138 //m_curpage = GetPageIndex(page);
3140 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3141 if (page_idx
>= active_tabctrl
->GetPageCount())
3142 active_tabctrl
->AddPage(page
, info
);
3144 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3146 UpdateTabCtrlHeight();
3148 active_tabctrl
->DoShowHide();
3150 // adjust selected index
3151 if(m_curpage
>= (int) page_idx
)
3156 SetSelectionToWindow(page
);
3163 // DeletePage() removes a tab from the multi-notebook,
3164 // and destroys the window as well
3165 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3167 if (page_idx
>= m_tabs
.GetPageCount())
3170 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3172 // hide the window in advance, as this will
3174 ShowWnd(wnd
, false);
3176 if (!RemovePage(page_idx
))
3180 // actually destroy the window now
3181 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3183 // delete the child frame with pending delete, as is
3184 // customary with frame windows
3185 if (!wxPendingDelete
.Member(wnd
))
3186 wxPendingDelete
.Append(wnd
);
3199 // RemovePage() removes a tab from the multi-notebook,
3200 // but does not destroy the window
3201 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3203 // save active window pointer
3204 wxWindow
* active_wnd
= NULL
;
3206 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3208 // save pointer of window being deleted
3209 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3210 wxWindow
* new_active
= NULL
;
3212 // make sure we found the page
3216 // find out which onscreen tab ctrl owns this tab
3219 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3222 bool is_curpage
= (m_curpage
== (int)page_idx
);
3223 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3226 // remove the tab from main catalog
3227 if (!m_tabs
.RemovePage(wnd
))
3230 // remove the tab from the onscreen tab ctrl
3231 ctrl
->RemovePage(wnd
);
3233 if (is_active_in_split
)
3235 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3237 if (ctrl_idx
>= ctrl_new_page_count
)
3238 ctrl_idx
= ctrl_new_page_count
-1;
3240 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3242 // set new page as active in the tab split
3243 ctrl
->SetActivePage(ctrl_idx
);
3245 // if the page deleted was the current page for the
3246 // entire tab control, then record the window
3247 // pointer of the new active page for activation
3250 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3256 // we are not deleting the active page, so keep it the same
3257 new_active
= active_wnd
;
3263 // we haven't yet found a new page to active,
3264 // so select the next page from the main tab
3267 if (page_idx
< m_tabs
.GetPageCount())
3269 new_active
= m_tabs
.GetPage(page_idx
).window
;
3272 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3274 new_active
= m_tabs
.GetPage(0).window
;
3279 RemoveEmptyTabFrames();
3281 m_curpage
= wxNOT_FOUND
;
3283 // set new active pane unless we're being destroyed anyhow
3284 if (new_active
&& !m_isBeingDeleted
)
3285 SetSelectionToWindow(new_active
);
3290 // GetPageIndex() returns the index of the page, or -1 if the
3291 // page could not be located in the notebook
3292 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3294 return m_tabs
.GetIdxFromWindow(page_wnd
);
3299 // SetPageText() changes the tab caption of the specified page
3300 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3302 if (page_idx
>= m_tabs
.GetPageCount())
3305 // update our own tab catalog
3306 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3307 page_info
.caption
= text
;
3309 // update what's on screen
3312 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3314 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3315 info
.caption
= text
;
3323 // returns the page caption
3324 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3326 if (page_idx
>= m_tabs
.GetPageCount())
3327 return wxEmptyString
;
3329 // update our own tab catalog
3330 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3331 return page_info
.caption
;
3334 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3336 if (page_idx
>= m_tabs
.GetPageCount())
3339 // update our own tab catalog
3340 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3341 page_info
.bitmap
= bitmap
;
3343 // tab height might have changed
3344 UpdateTabCtrlHeight();
3346 // update what's on screen
3349 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3351 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3352 info
.bitmap
= bitmap
;
3360 // returns the page bitmap
3361 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3363 if (page_idx
>= m_tabs
.GetPageCount())
3366 // update our own tab catalog
3367 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3368 return page_info
.bitmap
;
3371 // GetSelection() returns the index of the currently active page
3372 int wxAuiNotebook::GetSelection() const
3377 // SetSelection() sets the currently active page
3378 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3380 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3384 // don't change the page unless necessary;
3385 // however, clicking again on a tab should give it the focus.
3386 if ((int)new_page
== m_curpage
)
3390 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3392 if (FindFocus() != ctrl
)
3398 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3399 evt
.SetSelection(new_page
);
3400 evt
.SetOldSelection(m_curpage
);
3401 evt
.SetEventObject(this);
3402 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3404 int old_curpage
= m_curpage
;
3405 m_curpage
= new_page
;
3407 // program allows the page change
3408 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3409 (void)GetEventHandler()->ProcessEvent(evt
);
3414 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3416 m_tabs
.SetActivePage(wnd
);
3418 ctrl
->SetActivePage(ctrl_idx
);
3422 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3425 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3426 size_t i
, pane_count
= all_panes
.GetCount();
3427 for (i
= 0; i
< pane_count
; ++i
)
3429 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3430 if (pane
.name
== wxT("dummy"))
3432 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3433 if (tabctrl
!= ctrl
)
3434 tabctrl
->SetSelectedFont(m_normal_font
);
3436 tabctrl
->SetSelectedFont(m_selected_font
);
3440 // Set the focus to the page if we're not currently focused on the tab.
3441 // This is Firefox-like behaviour.
3442 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3452 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3454 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3455 wxCHECK_RET( idx
!= wxNOT_FOUND
, wxT("invalid notebook page") );
3458 // since a tab was clicked, let the parent know that we received
3459 // the focus, even if we will assign that focus immediately
3460 // to the child tab in the SetSelection call below
3461 // (the child focus event will also let wxAuiManager, if any,
3462 // know that the notebook control has been activated)
3464 wxWindow
* parent
= GetParent();
3467 wxChildFocusEvent
eventFocus(this);
3468 parent
->GetEventHandler()->ProcessEvent(eventFocus
);
3475 // GetPageCount() returns the total number of
3476 // pages managed by the multi-notebook
3477 size_t wxAuiNotebook::GetPageCount() const
3479 return m_tabs
.GetPageCount();
3482 // GetPage() returns the wxWindow pointer of the
3484 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3486 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3488 return m_tabs
.GetWindowFromIdx(page_idx
);
3491 // DoSizing() performs all sizing operations in each tab control
3492 void wxAuiNotebook::DoSizing()
3494 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3495 size_t i
, pane_count
= all_panes
.GetCount();
3496 for (i
= 0; i
< pane_count
; ++i
)
3498 if (all_panes
.Item(i
).name
== wxT("dummy"))
3501 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3502 tabframe
->DoSizing();
3506 // GetActiveTabCtrl() returns the active tab control. It is
3507 // called to determine which control gets new windows being added
3508 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3510 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3515 // find the tab ctrl with the current page
3516 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3523 // no current page, just find the first tab ctrl
3524 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3525 size_t i
, pane_count
= all_panes
.GetCount();
3526 for (i
= 0; i
< pane_count
; ++i
)
3528 if (all_panes
.Item(i
).name
== wxT("dummy"))
3531 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3532 return tabframe
->m_tabs
;
3535 // If there is no tabframe at all, create one
3536 wxTabFrame
* tabframe
= new wxTabFrame
;
3537 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3538 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3542 wxNO_BORDER
|wxWANTS_CHARS
);
3543 tabframe
->m_tabs
->SetFlags(m_flags
);
3544 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3545 m_mgr
.AddPane(tabframe
,
3546 wxAuiPaneInfo().Center().CaptionVisible(false));
3550 return tabframe
->m_tabs
;
3553 // FindTab() finds the tab control that currently contains the window as well
3554 // as the index of the window in the tab control. It returns true if the
3555 // window was found, otherwise false.
3556 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3558 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3559 size_t i
, pane_count
= all_panes
.GetCount();
3560 for (i
= 0; i
< pane_count
; ++i
)
3562 if (all_panes
.Item(i
).name
== wxT("dummy"))
3565 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3567 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3570 *ctrl
= tabframe
->m_tabs
;
3579 void wxAuiNotebook::Split(size_t page
, int direction
)
3581 wxSize cli_size
= GetClientSize();
3583 // get the page's window pointer
3584 wxWindow
* wnd
= GetPage(page
);
3588 // notebooks with 1 or less pages can't be split
3589 if (GetPageCount() < 2)
3592 // find out which tab control the page currently belongs to
3593 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3596 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3598 if (!src_tabs
|| src_idx
== -1)
3601 // choose a split size
3603 if (GetPageCount() > 2)
3605 split_size
= CalculateNewSplitSize();
3609 // because there are two panes, always split them
3611 split_size
= GetClientSize();
3617 // create a new tab frame
3618 wxTabFrame
* new_tabs
= new wxTabFrame
;
3619 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3620 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3621 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3625 wxNO_BORDER
|wxWANTS_CHARS
);
3626 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3627 new_tabs
->m_tabs
->SetFlags(m_flags
);
3628 dest_tabs
= new_tabs
->m_tabs
;
3630 // create a pane info structure with the information
3631 // about where the pane should be added
3632 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3635 if (direction
== wxLEFT
)
3638 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3640 else if (direction
== wxRIGHT
)
3643 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3645 else if (direction
== wxTOP
)
3648 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3650 else if (direction
== wxBOTTOM
)
3653 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3656 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3659 // remove the page from the source tabs
3660 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3661 page_info
.active
= false;
3662 src_tabs
->RemovePage(page_info
.window
);
3663 if (src_tabs
->GetPageCount() > 0)
3665 src_tabs
->SetActivePage((size_t)0);
3666 src_tabs
->DoShowHide();
3667 src_tabs
->Refresh();
3671 // add the page to the destination tabs
3672 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3674 if (src_tabs
->GetPageCount() == 0)
3676 RemoveEmptyTabFrames();
3680 dest_tabs
->DoShowHide();
3681 dest_tabs
->Refresh();
3683 // force the set selection function reset the selection
3686 // set the active page to the one we just split off
3687 SetSelectionToPage(page_info
);
3689 UpdateHintWindowSize();
3693 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3695 UpdateHintWindowSize();
3700 void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent
& evt
)
3702 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3703 wxASSERT(ctrl
!= NULL
);
3705 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3706 wxASSERT(wnd
!= NULL
);
3708 SetSelectionToWindow(wnd
);
3711 void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent
& WXUNUSED(evt
))
3713 // notify owner that the tabbar background has been double-clicked
3714 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
3715 e
.SetEventObject(this);
3716 GetEventHandler()->ProcessEvent(e
);
3719 void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent
&)
3724 void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent
& evt
)
3726 wxPoint screen_pt
= ::wxGetMousePosition();
3727 wxPoint client_pt
= ScreenToClient(screen_pt
);
3730 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3731 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3733 if (dest_tabs
== src_tabs
)
3737 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3740 // always hide the hint for inner-tabctrl drag
3743 // if tab moving is not allowed, leave
3744 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3749 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3750 wxWindow
* dest_location_tab
;
3752 // this is an inner-tab drag/reposition
3753 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3755 int src_idx
= evt
.GetSelection();
3756 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3758 // prevent jumpy drag
3759 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3760 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3761 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3763 m_last_drag_x
= pt
.x
;
3768 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3769 dest_tabs
->MovePage(src_tab
, dest_idx
);
3770 dest_tabs
->SetActivePage((size_t)dest_idx
);
3771 dest_tabs
->DoShowHide();
3772 dest_tabs
->Refresh();
3773 m_last_drag_x
= pt
.x
;
3781 // if external drag is allowed, check if the tab is being dragged
3782 // over a different wxAuiNotebook control
3783 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3785 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3787 // if we aren't over any window, stop here
3791 // make sure we are not over the hint window
3792 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3796 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3798 tab_ctrl
= tab_ctrl
->GetParent();
3803 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3807 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3808 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3809 m_mgr
.ShowHint(hint_rect
);
3818 // we are either over a hint window, or not over a tab
3819 // window, and there is no where to drag to, so exit
3826 // if there are less than two panes, split can't happen, so leave
3827 if (m_tabs
.GetPageCount() < 2)
3830 // if tab moving is not allowed, leave
3831 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3837 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3843 wxRect hint_rect
= dest_tabs
->GetRect();
3844 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3845 m_mgr
.ShowHint(hint_rect
);
3849 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3855 void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent
& evt
)
3860 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3861 wxCHECK_RET( src_tabs
, wxT("no source object?") );
3863 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3865 // get the mouse position, which will be used to determine the drop point
3866 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3867 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3871 // check for an external move
3872 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3874 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3878 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3880 tab_ctrl
= tab_ctrl
->GetParent();
3885 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3889 // find out from the destination control
3890 // if it's ok to drop this tab here
3891 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3892 e
.SetSelection(evt
.GetSelection());
3893 e
.SetOldSelection(evt
.GetSelection());
3894 e
.SetEventObject(this);
3895 e
.SetDragSource(this);
3896 e
.Veto(); // dropping must be explicitly approved by control owner
3898 nb
->GetEventHandler()->ProcessEvent(e
);
3902 // no answer or negative answer
3908 int src_idx
= evt
.GetSelection();
3909 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3911 // Check that it's not an impossible parent relationship
3913 while (p
&& !p
->IsTopLevel())
3922 // get main index of the page
3923 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3924 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no source page?") );
3927 // make a copy of the page info
3928 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3930 // remove the page from the source notebook
3931 RemovePage(main_idx
);
3933 // reparent the page
3934 src_page
->Reparent(nb
);
3937 // found out the insert idx
3938 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3939 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3941 wxWindow
* target
= NULL
;
3942 int insert_idx
= -1;
3943 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3946 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3950 // add the page to the new notebook
3951 if (insert_idx
== -1)
3952 insert_idx
= dest_tabs
->GetPageCount();
3953 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3954 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3957 dest_tabs
->DoShowHide();
3958 dest_tabs
->Refresh();
3960 // set the selection in the destination tab control
3961 nb
->SetSelectionToPage(page_info
);
3963 // notify owner that the tab has been dragged
3964 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3965 e2
.SetSelection(evt
.GetSelection());
3966 e2
.SetOldSelection(evt
.GetSelection());
3967 e2
.SetEventObject(this);
3968 GetEventHandler()->ProcessEvent(e2
);
3978 // only perform a tab split if it's allowed
3979 wxAuiTabCtrl
* dest_tabs
= NULL
;
3981 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3983 // If the pointer is in an existing tab frame, do a tab insert
3984 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3985 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3986 int insert_idx
= -1;
3989 dest_tabs
= tab_frame
->m_tabs
;
3991 if (dest_tabs
== src_tabs
)
3995 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3996 wxWindow
* target
= NULL
;
3997 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
4000 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
4006 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
4011 // there is no suitable drop location here, exit out
4015 // If there is no tabframe at all, create one
4016 wxTabFrame
* new_tabs
= new wxTabFrame
;
4017 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
4018 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
4019 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
4023 wxNO_BORDER
|wxWANTS_CHARS
);
4024 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
4025 new_tabs
->m_tabs
->SetFlags(m_flags
);
4027 m_mgr
.AddPane(new_tabs
,
4028 wxAuiPaneInfo().Bottom().CaptionVisible(false),
4031 dest_tabs
= new_tabs
->m_tabs
;
4036 // remove the page from the source tabs
4037 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
4038 page_info
.active
= false;
4039 src_tabs
->RemovePage(page_info
.window
);
4040 if (src_tabs
->GetPageCount() > 0)
4042 src_tabs
->SetActivePage((size_t)0);
4043 src_tabs
->DoShowHide();
4044 src_tabs
->Refresh();
4049 // add the page to the destination tabs
4050 if (insert_idx
== -1)
4051 insert_idx
= dest_tabs
->GetPageCount();
4052 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
4054 if (src_tabs
->GetPageCount() == 0)
4056 RemoveEmptyTabFrames();
4060 dest_tabs
->DoShowHide();
4061 dest_tabs
->Refresh();
4063 // force the set selection function reset the selection
4066 // set the active page to the one we just split off
4067 SetSelectionToPage(page_info
);
4069 UpdateHintWindowSize();
4072 // notify owner that the tab has been dragged
4073 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
4074 e
.SetSelection(evt
.GetSelection());
4075 e
.SetOldSelection(evt
.GetSelection());
4076 e
.SetEventObject(this);
4077 GetEventHandler()->ProcessEvent(e
);
4082 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
4084 // if we've just removed the last tab from the source
4085 // tab set, the remove the tab control completely
4086 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4087 size_t i
, pane_count
= all_panes
.GetCount();
4088 for (i
= 0; i
< pane_count
; ++i
)
4090 if (all_panes
.Item(i
).name
== wxT("dummy"))
4093 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4094 if (tabframe
->m_tab_rect
.Contains(pt
))
4095 return tabframe
->m_tabs
;
4101 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
4103 // if we've just removed the last tab from the source
4104 // tab set, the remove the tab control completely
4105 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4106 size_t i
, pane_count
= all_panes
.GetCount();
4107 for (i
= 0; i
< pane_count
; ++i
)
4109 if (all_panes
.Item(i
).name
== wxT("dummy"))
4112 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4113 if (tabframe
->m_tabs
== tab_ctrl
)
4122 void wxAuiNotebook::RemoveEmptyTabFrames()
4124 // if we've just removed the last tab from the source
4125 // tab set, the remove the tab control completely
4126 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
4127 size_t i
, pane_count
= all_panes
.GetCount();
4128 for (i
= 0; i
< pane_count
; ++i
)
4130 if (all_panes
.Item(i
).name
== wxT("dummy"))
4133 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4134 if (tab_frame
->m_tabs
->GetPageCount() == 0)
4136 m_mgr
.DetachPane(tab_frame
);
4138 // use pending delete because sometimes during
4139 // window closing, refreshs are pending
4140 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
4141 wxPendingDelete
.Append(tab_frame
->m_tabs
);
4143 tab_frame
->m_tabs
= NULL
;
4150 // check to see if there is still a center pane;
4151 // if there isn't, make a frame the center pane
4152 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4153 pane_count
= panes
.GetCount();
4154 wxWindow
* first_good
= NULL
;
4155 bool center_found
= false;
4156 for (i
= 0; i
< pane_count
; ++i
)
4158 if (panes
.Item(i
).name
== wxT("dummy"))
4160 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4161 center_found
= true;
4163 first_good
= panes
.Item(i
).window
;
4166 if (!center_found
&& first_good
)
4168 m_mgr
.GetPane(first_good
).Centre();
4171 if (!m_isBeingDeleted
)
4175 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4179 // if we're dragging a tab, don't change the current selection.
4180 // This code prevents a bug that used to happen when the hint window
4181 // was hidden. In the bug, the focus would return to the notebook
4182 // child, which would then enter this handler and call
4183 // SetSelection, which is not desired turn tab dragging.
4185 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4186 size_t i
, pane_count
= all_panes
.GetCount();
4187 for (i
= 0; i
< pane_count
; ++i
)
4189 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4190 if (pane
.name
== wxT("dummy"))
4192 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4193 if (tabframe
->m_tabs
->IsDragging())
4198 // change the tab selection to the child
4199 // which was focused
4200 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4201 if (idx
!= -1 && idx
!= m_curpage
)
4207 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4209 if ( event
.IsWindowChange() ) {
4211 // FIXME: the problem with this is that if we have a split notebook,
4212 // we selection may go all over the place.
4213 AdvanceSelection(event
.GetDirection());
4216 // we get this event in 3 cases
4218 // a) one of our pages might have generated it because the user TABbed
4219 // out from it in which case we should propagate the event upwards and
4220 // our parent will take care of setting the focus to prev/next sibling
4224 // b) the parent panel wants to give the focus to us so that we
4225 // forward it to our selected page. We can't deal with this in
4226 // OnSetFocus() because we don't know which direction the focus came
4227 // from in this case and so can't choose between setting the focus to
4228 // first or last panel child
4232 // c) we ourselves (see MSWTranslateMessage) generated the event
4234 wxWindow
* const parent
= GetParent();
4236 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4237 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4238 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4240 if ( isFromParent
|| isFromSelf
)
4242 // no, it doesn't come from child, case (b) or (c): forward to a
4243 // page but only if direction is backwards (TAB) or from ourselves,
4244 if ( GetSelection() != wxNOT_FOUND
&&
4245 (!event
.GetDirection() || isFromSelf
) )
4247 // so that the page knows that the event comes from it's parent
4248 // and is being propagated downwards
4249 event
.SetEventObject(this);
4251 wxWindow
*page
= GetPage(GetSelection());
4252 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4256 //else: page manages focus inside it itself
4258 else // otherwise set the focus to the notebook itself
4265 // it comes from our child, case (a), pass to the parent, but only
4266 // if the direction is forwards. Otherwise set the focus to the
4267 // notebook itself. The notebook is always the 'first' control of a
4269 if ( !event
.GetDirection() )
4275 event
.SetCurrentFocus(this);
4276 parent
->GetEventHandler()->ProcessEvent(event
);
4282 void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent
& evt
)
4284 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4286 int button_id
= evt
.GetInt();
4288 if (button_id
== wxAUI_BUTTON_CLOSE
)
4290 int selection
= evt
.GetSelection();
4292 if (selection
== -1)
4294 // if the close button is to the right, use the active
4295 // page selection to determine which page to close
4296 selection
= tabs
->GetActivePage();
4299 if (selection
!= -1)
4301 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4303 // ask owner if it's ok to close the tab
4304 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4305 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4306 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4307 e
.SetSelection(idx
);
4308 e
.SetOldSelection(evt
.GetSelection());
4309 e
.SetEventObject(this);
4310 GetEventHandler()->ProcessEvent(e
);
4316 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4323 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4324 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no page to delete?") );
4326 DeletePage(main_idx
);
4329 // notify owner that the tab has been closed
4330 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4331 e2
.SetSelection(idx
);
4332 e2
.SetEventObject(this);
4333 GetEventHandler()->ProcessEvent(e2
);
4339 void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent
& evt
)
4341 // patch event through to owner
4342 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4343 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4345 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4346 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4347 e
.SetEventObject(this);
4348 GetEventHandler()->ProcessEvent(e
);
4351 void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent
& evt
)
4353 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4354 // click should act like a tab close action. However, first
4355 // give the owner an opportunity to handle the middle up event
4356 // for custom action
4358 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4359 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4361 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4362 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4363 e
.SetEventObject(this);
4364 if (GetEventHandler()->ProcessEvent(e
))
4369 // check if we are supposed to close on middle-up
4370 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4373 // simulate the user pressing the close button on the tab
4374 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4378 void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent
& evt
)
4380 // patch event through to owner
4381 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4382 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4384 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4385 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4386 e
.SetEventObject(this);
4387 GetEventHandler()->ProcessEvent(e
);
4390 void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent
& evt
)
4392 // patch event through to owner
4393 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4394 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4396 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4397 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4398 e
.SetEventObject(this);
4399 GetEventHandler()->ProcessEvent(e
);
4402 // Sets the normal font
4403 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4405 m_normal_font
= font
;
4406 GetArtProvider()->SetNormalFont(font
);
4409 // Sets the selected tab font
4410 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4412 m_selected_font
= font
;
4413 GetArtProvider()->SetSelectedFont(font
);
4416 // Sets the measuring font
4417 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4419 GetArtProvider()->SetMeasuringFont(font
);
4422 // Sets the tab font
4423 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4425 wxControl::SetFont(font
);
4427 wxFont
normalFont(font
);
4428 wxFont
selectedFont(normalFont
);
4429 selectedFont
.SetWeight(wxBOLD
);
4431 SetNormalFont(normalFont
);
4432 SetSelectedFont(selectedFont
);
4433 SetMeasuringFont(selectedFont
);
4438 // Gets the tab control height
4439 int wxAuiNotebook::GetTabCtrlHeight() const
4441 return m_tab_ctrl_height
;
4444 // Gets the height of the notebook for a given page height
4445 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4447 UpdateTabCtrlHeight();
4449 int tabCtrlHeight
= GetTabCtrlHeight();
4450 int decorHeight
= 2;
4451 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4454 // Advances the selection, generation page selection events
4455 void wxAuiNotebook::AdvanceSelection(bool forward
)
4457 if (GetPageCount() <= 1)
4460 int currentSelection
= GetSelection();
4464 if (currentSelection
== (int) (GetPageCount() - 1))
4466 else if (currentSelection
== -1)
4467 currentSelection
= 0;
4469 currentSelection
++;
4473 if (currentSelection
<= 0)
4476 currentSelection
--;
4479 SetSelection(currentSelection
);
4482 // Shows the window menu
4483 bool wxAuiNotebook::ShowWindowMenu()
4485 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4487 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4491 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4492 e
.SetSelection(idx
);
4493 e
.SetOldSelection(tabCtrl
->GetActivePage());
4494 e
.SetEventObject(tabCtrl
);
4495 GetEventHandler()->ProcessEvent(e
);
4503 void wxAuiNotebook::Thaw()