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_active_colour
= base_colour
;
210 m_base_colour
= base_colour
;
211 wxColor border_colour
= base_colour
.ChangeLightness(75);
213 m_border_pen
= wxPen(border_colour
);
214 m_base_colour_pen
= wxPen(m_base_colour
);
215 m_base_colour_brush
= wxBrush(m_base_colour
);
217 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
218 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
220 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
221 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
223 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
224 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
226 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
227 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
232 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
236 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
238 return new wxAuiDefaultTabArt(*this);
241 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
246 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
249 m_fixed_tab_width
= 100;
251 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
253 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
254 tot_width
-= m_active_close_bmp
.GetWidth();
255 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
256 tot_width
-= m_active_windowlist_bmp
.GetWidth();
260 m_fixed_tab_width
= tot_width
/(int)tab_count
;
264 if (m_fixed_tab_width
< 100)
265 m_fixed_tab_width
= 100;
267 if (m_fixed_tab_width
> tot_width
/2)
268 m_fixed_tab_width
= tot_width
/2;
270 if (m_fixed_tab_width
> 220)
271 m_fixed_tab_width
= 220;
273 m_tab_ctrl_height
= tab_ctrl_size
.y
;
277 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
278 wxWindow
* WXUNUSED(wnd
),
283 wxColor top_color
= m_base_colour
.ChangeLightness(90);
284 wxColor bottom_color
= m_base_colour
.ChangeLightness(170);
287 if (m_flags
&wxAUI_NB_BOTTOM
)
288 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
);
289 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
290 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
291 else //for wxAUI_NB_TOP
292 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
294 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
299 dc
.SetPen(m_border_pen
);
300 int y
= rect
.GetHeight();
301 int w
= rect
.GetWidth();
303 if (m_flags
&wxAUI_NB_BOTTOM
)
305 dc
.SetBrush(wxBrush(bottom_color
));
306 dc
.DrawRectangle(-1, 0, w
+2, 4);
308 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
309 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
310 else //for wxAUI_NB_TOP
312 dc
.SetBrush(m_base_colour_brush
);
313 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
318 // DrawTab() draws an individual tab.
321 // in_rect - rectangle the tab should be confined to
322 // caption - tab's caption
323 // active - whether or not the tab is active
324 // out_rect - actual output rectangle
325 // x_extent - the advance x; where the next tab should start
327 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
329 const wxAuiNotebookPage
& page
,
330 const wxRect
& in_rect
,
331 int close_button_state
,
332 wxRect
* out_tab_rect
,
333 wxRect
* out_button_rect
,
336 wxCoord normal_textx
, normal_texty
;
337 wxCoord selected_textx
, selected_texty
;
340 // if the caption is empty, measure some temporary text
341 wxString caption
= page
.caption
;
345 dc
.SetFont(m_selected_font
);
346 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
348 dc
.SetFont(m_normal_font
);
349 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
351 // figure out the size of the tab
352 wxSize tab_size
= GetTabSize(dc
,
360 wxCoord tab_height
= m_tab_ctrl_height
- 3;
361 wxCoord tab_width
= tab_size
.x
;
362 wxCoord tab_x
= in_rect
.x
;
363 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
366 caption
= page
.caption
;
369 // select pen, brush and font for the tab to be drawn
373 dc
.SetFont(m_selected_font
);
374 texty
= selected_texty
;
378 dc
.SetFont(m_normal_font
);
379 texty
= normal_texty
;
383 // create points that will make the tab outline
385 int clip_width
= tab_width
;
386 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
387 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
390 wxPoint clip_points[6];
391 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
392 clip_points[1] = wxPoint(tab_x, tab_y+2);
393 clip_points[2] = wxPoint(tab_x+2, tab_y);
394 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
395 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
396 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
398 // FIXME: these ports don't provide wxRegion ctor from array of points
399 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
400 // set the clipping region for the tab --
401 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
402 dc.SetClippingRegion(clipping_region);
403 #endif // !wxDFB && !wxCocoa
405 // since the above code above doesn't play well with WXDFB or WXCOCOA,
406 // we'll just use a rectangle for the clipping region for now --
407 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
410 wxPoint border_points
[6];
411 if (m_flags
&wxAUI_NB_BOTTOM
)
413 border_points
[0] = wxPoint(tab_x
, tab_y
);
414 border_points
[1] = wxPoint(tab_x
, tab_y
+tab_height
-6);
415 border_points
[2] = wxPoint(tab_x
+2, tab_y
+tab_height
-4);
416 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
+tab_height
-4);
417 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-6);
418 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
);
420 else //if (m_flags & wxAUI_NB_TOP) {}
422 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
423 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
424 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
425 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
426 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
427 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
429 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
430 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
432 int drawn_tab_yoff
= border_points
[1].y
;
433 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
440 // draw base background color
441 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
442 dc
.SetPen(wxPen(m_active_colour
));
443 dc
.SetBrush(wxBrush(m_active_colour
));
444 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
446 // this white helps fill out the gradient at the top of the tab
447 dc
.SetPen(*wxWHITE_PEN
);
448 dc
.SetBrush(*wxWHITE_BRUSH
);
449 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
451 // these two points help the rounded corners appear more antialiased
452 dc
.SetPen(wxPen(m_active_colour
));
453 dc
.DrawPoint(r
.x
+2, r
.y
+1);
454 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
456 // set rectangle down a bit for gradient drawing
457 r
.SetHeight(r
.GetHeight()/2);
463 // draw gradient background
464 wxColor top_color
= *wxWHITE
;
465 wxColor bottom_color
= m_active_colour
;
466 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
472 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
474 // start the gradent up a bit and leave the inside border inset
475 // by a pixel for a 3D look. Only the top half of the inactive
476 // tab will have a slight gradient
483 // -- draw top gradient fill for glossy look
484 wxColor top_color
= m_base_colour
;
485 wxColor bottom_color
= top_color
.ChangeLightness(160);
486 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
491 // -- draw bottom fill for glossy look
492 top_color
= m_base_colour
;
493 bottom_color
= m_base_colour
;
494 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
498 dc
.SetPen(m_border_pen
);
499 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
500 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
502 // there are two horizontal grey lines at the bottom of the tab control,
503 // this gets rid of the top one of those lines in the tab control
506 if (m_flags
&wxAUI_NB_BOTTOM
)
507 dc
.SetPen(wxPen(m_base_colour
.ChangeLightness(170)));
508 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
509 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
510 else //for wxAUI_NB_TOP
511 dc
.SetPen(m_base_colour_pen
);
512 dc
.DrawLine(border_points
[0].x
+1,
519 int text_offset
= tab_x
+ 8;
520 int close_button_width
= 0;
521 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
523 close_button_width
= m_active_close_bmp
.GetWidth();
526 int bitmap_offset
= 0;
527 if (page
.bitmap
.IsOk())
529 bitmap_offset
= tab_x
+ 8;
532 dc
.DrawBitmap(page
.bitmap
,
534 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
537 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
538 text_offset
+= 3; // bitmap padding
543 text_offset
= tab_x
+ 8;
547 wxString draw_text
= wxAuiChopText(dc
,
549 tab_width
- (text_offset
-tab_x
) - close_button_width
);
552 dc
.DrawText(draw_text
,
554 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
556 // draw focus rectangle
557 if (page
.active
&& (wnd
->FindFocus() == wnd
))
559 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
560 selected_textx
, selected_texty
);
563 wxRect focusRectBitmap
;
565 if (page
.bitmap
.IsOk())
566 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
567 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
569 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
570 focusRect
= focusRectBitmap
;
571 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
572 focusRect
= focusRectText
;
573 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
574 focusRect
= focusRectText
.Union(focusRectBitmap
);
576 focusRect
.Inflate(2, 2);
578 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
581 // draw close button if necessary
582 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
584 wxBitmap bmp
= m_disabled_close_bmp
;
586 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
587 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
589 bmp
= m_active_close_bmp
;
592 int offsetY
= tab_y
-1;
593 if (m_flags
& wxAUI_NB_BOTTOM
)
596 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
597 offsetY
+ (tab_height
/2) - (bmp
.GetHeight()/2),
601 IndentPressedBitmap(&rect
, close_button_state
);
602 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
604 *out_button_rect
= rect
;
607 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
609 dc
.DestroyClippingRegion();
612 int wxAuiDefaultTabArt::GetIndentSize()
617 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
618 wxWindow
* WXUNUSED(wnd
),
619 const wxString
& caption
,
620 const wxBitmap
& bitmap
,
621 bool WXUNUSED(active
),
622 int close_button_state
,
625 wxCoord measured_textx
, measured_texty
, tmp
;
627 dc
.SetFont(m_measuring_font
);
628 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
630 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
632 // add padding around the text
633 wxCoord tab_width
= measured_textx
;
634 wxCoord tab_height
= measured_texty
;
636 // if the close button is showing, add space for it
637 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
638 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
640 // if there's a bitmap, add space for it
643 tab_width
+= bitmap
.GetWidth();
644 tab_width
+= 3; // right side bitmap padding
645 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
652 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
654 tab_width
= m_fixed_tab_width
;
657 *x_extent
= tab_width
;
659 return wxSize(tab_width
, tab_height
);
663 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
664 wxWindow
* WXUNUSED(wnd
),
665 const wxRect
& in_rect
,
676 case wxAUI_BUTTON_CLOSE
:
677 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
678 bmp
= m_disabled_close_bmp
;
680 bmp
= m_active_close_bmp
;
682 case wxAUI_BUTTON_LEFT
:
683 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
684 bmp
= m_disabled_left_bmp
;
686 bmp
= m_active_left_bmp
;
688 case wxAUI_BUTTON_RIGHT
:
689 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
690 bmp
= m_disabled_right_bmp
;
692 bmp
= m_active_right_bmp
;
694 case wxAUI_BUTTON_WINDOWLIST
:
695 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
696 bmp
= m_disabled_windowlist_bmp
;
698 bmp
= m_active_windowlist_bmp
;
708 if (orientation
== wxLEFT
)
710 rect
.SetX(in_rect
.x
);
711 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
712 rect
.SetWidth(bmp
.GetWidth());
713 rect
.SetHeight(bmp
.GetHeight());
717 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
718 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
719 bmp
.GetWidth(), bmp
.GetHeight());
722 IndentPressedBitmap(&rect
, button_state
);
723 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
728 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
729 const wxAuiNotebookPageArray
& pages
,
734 size_t i
, count
= pages
.GetCount();
735 for (i
= 0; i
< count
; ++i
)
737 const wxAuiNotebookPage
& page
= pages
.Item(i
);
738 wxString caption
= page
.caption
;
740 // if there is no caption, make it a space. This will prevent
741 // an assert in the menu code.
742 if (caption
.IsEmpty())
745 wxMenuItem
* item
= new wxMenuItem(NULL
, 1000+i
, caption
);
746 if (page
.bitmap
.IsOk())
747 item
->SetBitmap(page
.bitmap
);
748 menuPopup
.Append(item
);
751 // find out where to put the popup menu of window items
752 wxPoint pt
= ::wxGetMousePosition();
753 pt
= wnd
->ScreenToClient(pt
);
755 // find out the screen coordinate at the bottom of the tab ctrl
756 wxRect cli_rect
= wnd
->GetClientRect();
757 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
759 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
760 wnd
->PushEventHandler(cc
);
761 wnd
->PopupMenu(&menuPopup
, pt
);
762 int command
= cc
->GetCommandId();
763 wnd
->PopEventHandler(true);
771 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
772 const wxAuiNotebookPageArray
& pages
,
773 const wxSize
& required_bmp_size
)
776 dc
.SetFont(m_measuring_font
);
778 // sometimes a standard bitmap size needs to be enforced, especially
779 // if some tabs have bitmaps and others don't. This is important because
780 // it prevents the tab control from resizing when tabs are added.
781 wxBitmap measure_bmp
;
782 if (required_bmp_size
.IsFullySpecified())
784 measure_bmp
.Create(required_bmp_size
.x
,
785 required_bmp_size
.y
);
790 size_t i
, page_count
= pages
.GetCount();
791 for (i
= 0; i
< page_count
; ++i
)
793 wxAuiNotebookPage
& page
= pages
.Item(i
);
796 if (measure_bmp
.IsOk())
801 // we don't use the caption text because we don't
802 // want tab heights to be different in the case
803 // of a very short piece of text on one tab and a very
804 // tall piece of text on another tab
806 wxSize s
= GetTabSize(dc
,
811 wxAUI_BUTTON_STATE_HIDDEN
,
814 max_y
= wxMax(max_y
, s
.y
);
820 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
822 m_normal_font
= font
;
825 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
827 m_selected_font
= font
;
830 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
832 m_measuring_font
= font
;
835 void wxAuiDefaultTabArt::SetColour(const wxColour
& colour
)
837 m_base_colour
= colour
;
838 m_border_pen
= wxPen(m_base_colour
.ChangeLightness(75));
839 m_base_colour_pen
= wxPen(m_base_colour
);
840 m_base_colour_brush
= wxBrush(m_base_colour
);
843 void wxAuiDefaultTabArt::SetActiveColour(const wxColour
& colour
)
845 m_active_colour
= colour
;
848 // -- wxAuiSimpleTabArt class implementation --
850 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
852 m_normal_font
= *wxNORMAL_FONT
;
853 m_selected_font
= *wxNORMAL_FONT
;
854 m_selected_font
.SetWeight(wxBOLD
);
855 m_measuring_font
= m_selected_font
;
858 m_fixed_tab_width
= 100;
860 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
862 wxColour background_colour
= base_colour
;
863 wxColour normaltab_colour
= base_colour
;
864 wxColour selectedtab_colour
= *wxWHITE
;
866 m_bkbrush
= wxBrush(background_colour
);
867 m_normal_bkbrush
= wxBrush(normaltab_colour
);
868 m_normal_bkpen
= wxPen(normaltab_colour
);
869 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
870 m_selected_bkpen
= wxPen(selectedtab_colour
);
872 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
873 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
875 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
876 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
878 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
879 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
881 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
882 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
886 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
890 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
892 return new wxAuiSimpleTabArt(*this);
895 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
900 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
903 m_fixed_tab_width
= 100;
905 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
907 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
908 tot_width
-= m_active_close_bmp
.GetWidth();
909 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
910 tot_width
-= m_active_windowlist_bmp
.GetWidth();
914 m_fixed_tab_width
= tot_width
/(int)tab_count
;
918 if (m_fixed_tab_width
< 100)
919 m_fixed_tab_width
= 100;
921 if (m_fixed_tab_width
> tot_width
/2)
922 m_fixed_tab_width
= tot_width
/2;
924 if (m_fixed_tab_width
> 220)
925 m_fixed_tab_width
= 220;
928 void wxAuiSimpleTabArt::SetColour(const wxColour
& colour
)
930 m_bkbrush
= wxBrush(colour
);
931 m_normal_bkbrush
= wxBrush(colour
);
932 m_normal_bkpen
= wxPen(colour
);
935 void wxAuiSimpleTabArt::SetActiveColour(const wxColour
& colour
)
937 m_selected_bkbrush
= wxBrush(colour
);
938 m_selected_bkpen
= wxPen(colour
);
941 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
942 wxWindow
* WXUNUSED(wnd
),
946 dc
.SetBrush(m_bkbrush
);
947 dc
.SetPen(*wxTRANSPARENT_PEN
);
948 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
951 dc
.SetPen(*wxGREY_PEN
);
952 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
956 // DrawTab() draws an individual tab.
959 // in_rect - rectangle the tab should be confined to
960 // caption - tab's caption
961 // active - whether or not the tab is active
962 // out_rect - actual output rectangle
963 // x_extent - the advance x; where the next tab should start
965 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
967 const wxAuiNotebookPage
& page
,
968 const wxRect
& in_rect
,
969 int close_button_state
,
970 wxRect
* out_tab_rect
,
971 wxRect
* out_button_rect
,
974 wxCoord normal_textx
, normal_texty
;
975 wxCoord selected_textx
, selected_texty
;
976 wxCoord textx
, texty
;
978 // if the caption is empty, measure some temporary text
979 wxString caption
= page
.caption
;
983 dc
.SetFont(m_selected_font
);
984 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
986 dc
.SetFont(m_normal_font
);
987 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
989 // figure out the size of the tab
990 wxSize tab_size
= GetTabSize(dc
,
998 wxCoord tab_height
= tab_size
.y
;
999 wxCoord tab_width
= tab_size
.x
;
1000 wxCoord tab_x
= in_rect
.x
;
1001 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
1003 caption
= page
.caption
;
1005 // select pen, brush and font for the tab to be drawn
1009 dc
.SetPen(m_selected_bkpen
);
1010 dc
.SetBrush(m_selected_bkbrush
);
1011 dc
.SetFont(m_selected_font
);
1012 textx
= selected_textx
;
1013 texty
= selected_texty
;
1017 dc
.SetPen(m_normal_bkpen
);
1018 dc
.SetBrush(m_normal_bkbrush
);
1019 dc
.SetFont(m_normal_font
);
1020 textx
= normal_textx
;
1021 texty
= normal_texty
;
1028 points
[0].x
= tab_x
;
1029 points
[0].y
= tab_y
+ tab_height
- 1;
1030 points
[1].x
= tab_x
+ tab_height
- 3;
1031 points
[1].y
= tab_y
+ 2;
1032 points
[2].x
= tab_x
+ tab_height
+ 3;
1033 points
[2].y
= tab_y
;
1034 points
[3].x
= tab_x
+ tab_width
- 2;
1035 points
[3].y
= tab_y
;
1036 points
[4].x
= tab_x
+ tab_width
;
1037 points
[4].y
= tab_y
+ 2;
1038 points
[5].x
= tab_x
+ tab_width
;
1039 points
[5].y
= tab_y
+ tab_height
- 1;
1040 points
[6] = points
[0];
1042 dc
.SetClippingRegion(in_rect
);
1044 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
1046 dc
.SetPen(*wxGREY_PEN
);
1048 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1049 dc
.DrawLines(WXSIZEOF(points
), points
);
1054 int close_button_width
= 0;
1055 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1057 close_button_width
= m_active_close_bmp
.GetWidth();
1058 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1062 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1065 // set minimum text offset
1066 if (text_offset
< tab_x
+ tab_height
)
1067 text_offset
= tab_x
+ tab_height
;
1069 // chop text if necessary
1070 wxString draw_text
= wxAuiChopText(dc
,
1072 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1075 dc
.DrawText(draw_text
,
1077 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1080 // draw focus rectangle
1081 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1083 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1084 selected_textx
, selected_texty
);
1086 focusRect
.Inflate(2, 2);
1088 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1091 // draw close button if necessary
1092 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1096 bmp
= m_active_close_bmp
;
1098 bmp
= m_disabled_close_bmp
;
1100 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1101 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1104 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1106 *out_button_rect
= rect
;
1110 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1112 dc
.DestroyClippingRegion();
1115 int wxAuiSimpleTabArt::GetIndentSize()
1120 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1121 wxWindow
* WXUNUSED(wnd
),
1122 const wxString
& caption
,
1123 const wxBitmap
& WXUNUSED(bitmap
),
1124 bool WXUNUSED(active
),
1125 int close_button_state
,
1128 wxCoord measured_textx
, measured_texty
;
1130 dc
.SetFont(m_measuring_font
);
1131 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1133 wxCoord tab_height
= measured_texty
+ 4;
1134 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1136 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1137 tab_width
+= m_active_close_bmp
.GetWidth();
1139 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1141 tab_width
= m_fixed_tab_width
;
1144 *x_extent
= tab_width
- (tab_height
/2) - 1;
1146 return wxSize(tab_width
, tab_height
);
1150 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1151 wxWindow
* WXUNUSED(wnd
),
1152 const wxRect
& in_rect
,
1163 case wxAUI_BUTTON_CLOSE
:
1164 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1165 bmp
= m_disabled_close_bmp
;
1167 bmp
= m_active_close_bmp
;
1169 case wxAUI_BUTTON_LEFT
:
1170 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1171 bmp
= m_disabled_left_bmp
;
1173 bmp
= m_active_left_bmp
;
1175 case wxAUI_BUTTON_RIGHT
:
1176 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1177 bmp
= m_disabled_right_bmp
;
1179 bmp
= m_active_right_bmp
;
1181 case wxAUI_BUTTON_WINDOWLIST
:
1182 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1183 bmp
= m_disabled_windowlist_bmp
;
1185 bmp
= m_active_windowlist_bmp
;
1194 if (orientation
== wxLEFT
)
1196 rect
.SetX(in_rect
.x
);
1197 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1198 rect
.SetWidth(bmp
.GetWidth());
1199 rect
.SetHeight(bmp
.GetHeight());
1203 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1204 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1205 bmp
.GetWidth(), bmp
.GetHeight());
1209 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1214 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1215 const wxAuiNotebookPageArray
& pages
,
1220 size_t i
, count
= pages
.GetCount();
1221 for (i
= 0; i
< count
; ++i
)
1223 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1224 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1227 if (active_idx
!= -1)
1229 menuPopup
.Check(1000+active_idx
, true);
1232 // find out where to put the popup menu of window
1233 // items. Subtract 100 for now to center the menu
1234 // a bit, until a better mechanism can be implemented
1235 wxPoint pt
= ::wxGetMousePosition();
1236 pt
= wnd
->ScreenToClient(pt
);
1242 // find out the screen coordinate at the bottom of the tab ctrl
1243 wxRect cli_rect
= wnd
->GetClientRect();
1244 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1246 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1247 wnd
->PushEventHandler(cc
);
1248 wnd
->PopupMenu(&menuPopup
, pt
);
1249 int command
= cc
->GetCommandId();
1250 wnd
->PopEventHandler(true);
1252 if (command
>= 1000)
1253 return command
-1000;
1258 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1259 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1260 const wxSize
& WXUNUSED(required_bmp_size
))
1263 dc
.SetFont(m_measuring_font
);
1265 wxSize s
= GetTabSize(dc
,
1270 wxAUI_BUTTON_STATE_HIDDEN
,
1275 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1277 m_normal_font
= font
;
1280 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1282 m_selected_font
= font
;
1285 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1287 m_measuring_font
= font
;
1293 // -- wxAuiTabContainer class implementation --
1296 // wxAuiTabContainer is a class which contains information about each
1297 // tab. It also can render an entire tab control to a specified DC.
1298 // It's not a window class itself, because this code will be used by
1299 // the wxFrameMananger, where it is disadvantageous to have separate
1300 // windows for each tab control in the case of "docked tabs"
1302 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1303 // which can be used as a tab control in the normal sense.
1306 wxAuiTabContainer::wxAuiTabContainer()
1310 m_art
= new wxAuiDefaultTabArt
;
1312 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1313 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1314 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1315 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1318 wxAuiTabContainer::~wxAuiTabContainer()
1323 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1330 m_art
->SetFlags(m_flags
);
1334 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1339 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1343 // check for new close button settings
1344 RemoveButton(wxAUI_BUTTON_LEFT
);
1345 RemoveButton(wxAUI_BUTTON_RIGHT
);
1346 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1347 RemoveButton(wxAUI_BUTTON_CLOSE
);
1350 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1352 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1353 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1356 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1358 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1361 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1363 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1368 m_art
->SetFlags(m_flags
);
1372 unsigned int wxAuiTabContainer::GetFlags() const
1378 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1380 m_art
->SetNormalFont(font
);
1383 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1385 m_art
->SetSelectedFont(font
);
1388 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1390 m_art
->SetMeasuringFont(font
);
1393 void wxAuiTabContainer::SetColour(const wxColour
& colour
)
1395 m_art
->SetColour(colour
);
1398 void wxAuiTabContainer::SetActiveColour(const wxColour
& colour
)
1400 m_art
->SetActiveColour(colour
);
1403 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1409 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1413 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1414 const wxAuiNotebookPage
& info
)
1416 wxAuiNotebookPage page_info
;
1418 page_info
.window
= page
;
1420 m_pages
.Add(page_info
);
1422 // let the art provider know how many pages we have
1425 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1431 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1432 const wxAuiNotebookPage
& info
,
1435 wxAuiNotebookPage page_info
;
1437 page_info
.window
= page
;
1439 if (idx
>= m_pages
.GetCount())
1440 m_pages
.Add(page_info
);
1442 m_pages
.Insert(page_info
, idx
);
1444 // let the art provider know how many pages we have
1447 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1453 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1456 int idx
= GetIdxFromWindow(page
);
1460 // get page entry, make a copy of it
1461 wxAuiNotebookPage p
= GetPage(idx
);
1463 // remove old page entry
1466 // insert page where it should be
1467 InsertPage(page
, p
, new_idx
);
1472 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1474 size_t i
, page_count
= m_pages
.GetCount();
1475 for (i
= 0; i
< page_count
; ++i
)
1477 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1478 if (page
.window
== wnd
)
1480 m_pages
.RemoveAt(i
);
1482 // let the art provider know how many pages we have
1485 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1495 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1499 size_t i
, page_count
= m_pages
.GetCount();
1500 for (i
= 0; i
< page_count
; ++i
)
1502 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1503 if (page
.window
== wnd
)
1510 page
.active
= false;
1517 void wxAuiTabContainer::SetNoneActive()
1519 size_t i
, page_count
= m_pages
.GetCount();
1520 for (i
= 0; i
< page_count
; ++i
)
1522 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1523 page
.active
= false;
1527 bool wxAuiTabContainer::SetActivePage(size_t page
)
1529 if (page
>= m_pages
.GetCount())
1532 return SetActivePage(m_pages
.Item(page
).window
);
1535 int wxAuiTabContainer::GetActivePage() const
1537 size_t i
, page_count
= m_pages
.GetCount();
1538 for (i
= 0; i
< page_count
; ++i
)
1540 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1548 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1550 if (idx
>= m_pages
.GetCount())
1553 return m_pages
[idx
].window
;
1556 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1558 const size_t page_count
= m_pages
.GetCount();
1559 for ( size_t i
= 0; i
< page_count
; ++i
)
1561 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1562 if (page
.window
== wnd
)
1568 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1570 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1572 return m_pages
[idx
];
1575 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1577 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1579 return m_pages
[idx
];
1582 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1587 size_t wxAuiTabContainer::GetPageCount() const
1589 return m_pages
.GetCount();
1592 void wxAuiTabContainer::AddButton(int id
,
1594 const wxBitmap
& normal_bitmap
,
1595 const wxBitmap
& disabled_bitmap
)
1597 wxAuiTabContainerButton button
;
1599 button
.bitmap
= normal_bitmap
;
1600 button
.dis_bitmap
= disabled_bitmap
;
1601 button
.location
= location
;
1602 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1604 m_buttons
.Add(button
);
1607 void wxAuiTabContainer::RemoveButton(int id
)
1609 size_t i
, button_count
= m_buttons
.GetCount();
1611 for (i
= 0; i
< button_count
; ++i
)
1613 if (m_buttons
.Item(i
).id
== id
)
1615 m_buttons
.RemoveAt(i
);
1623 size_t wxAuiTabContainer::GetTabOffset() const
1625 return m_tab_offset
;
1628 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1630 m_tab_offset
= offset
;
1636 // Render() renders the tab catalog to the specified DC
1637 // It is a virtual function and can be overridden to
1638 // provide custom drawing capabilities
1639 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1641 if (!raw_dc
|| !raw_dc
->IsOk())
1646 // use the same layout direction as the window DC uses to ensure that the
1647 // text is rendered correctly
1648 dc
.SetLayoutDirection(raw_dc
->GetLayoutDirection());
1652 size_t page_count
= m_pages
.GetCount();
1653 size_t button_count
= m_buttons
.GetCount();
1655 // create off-screen bitmap
1656 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1657 dc
.SelectObject(bmp
);
1662 // find out if size of tabs is larger than can be
1663 // afforded on screen
1664 int total_width
= 0;
1665 int visible_width
= 0;
1666 for (i
= 0; i
< page_count
; ++i
)
1668 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1670 // determine if a close button is on this tab
1671 bool close_button
= false;
1672 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1673 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1675 close_button
= true;
1680 wxSize size
= m_art
->GetTabSize(dc
,
1686 wxAUI_BUTTON_STATE_NORMAL
:
1687 wxAUI_BUTTON_STATE_HIDDEN
,
1690 if (i
+1 < page_count
)
1691 total_width
+= x_extent
;
1693 total_width
+= size
.x
;
1695 if (i
>= m_tab_offset
)
1697 if (i
+1 < page_count
)
1698 visible_width
+= x_extent
;
1700 visible_width
+= size
.x
;
1704 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1706 // show left/right buttons
1707 for (i
= 0; i
< button_count
; ++i
)
1709 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1710 if (button
.id
== wxAUI_BUTTON_LEFT
||
1711 button
.id
== wxAUI_BUTTON_RIGHT
)
1713 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1719 // hide left/right buttons
1720 for (i
= 0; i
< button_count
; ++i
)
1722 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1723 if (button
.id
== wxAUI_BUTTON_LEFT
||
1724 button
.id
== wxAUI_BUTTON_RIGHT
)
1726 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1731 // determine whether left button should be enabled
1732 for (i
= 0; i
< button_count
; ++i
)
1734 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1735 if (button
.id
== wxAUI_BUTTON_LEFT
)
1737 if (m_tab_offset
== 0)
1738 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1740 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1742 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1744 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1745 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1747 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1754 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1757 int left_buttons_width
= 0;
1758 int right_buttons_width
= 0;
1762 // draw the buttons on the right side
1763 offset
= m_rect
.x
+ m_rect
.width
;
1764 for (i
= 0; i
< button_count
; ++i
)
1766 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1768 if (button
.location
!= wxRIGHT
)
1770 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1773 wxRect button_rect
= m_rect
;
1774 button_rect
.SetY(1);
1775 button_rect
.SetWidth(offset
);
1777 m_art
->DrawButton(dc
,
1785 offset
-= button
.rect
.GetWidth();
1786 right_buttons_width
+= button
.rect
.GetWidth();
1793 // draw the buttons on the left side
1795 for (i
= 0; i
< button_count
; ++i
)
1797 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1799 if (button
.location
!= wxLEFT
)
1801 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1804 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1806 m_art
->DrawButton(dc
,
1814 offset
+= button
.rect
.GetWidth();
1815 left_buttons_width
+= button
.rect
.GetWidth();
1818 offset
= left_buttons_width
;
1821 offset
+= m_art
->GetIndentSize();
1824 // prepare the tab-close-button array
1825 // make sure tab button entries which aren't used are marked as hidden
1826 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1827 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1829 // make sure there are enough tab button entries to accommodate all tabs
1830 while (m_tab_close_buttons
.GetCount() < page_count
)
1832 wxAuiTabContainerButton tempbtn
;
1833 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1834 tempbtn
.location
= wxCENTER
;
1835 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1836 m_tab_close_buttons
.Add(tempbtn
);
1840 // buttons before the tab offset must be set to hidden
1841 for (i
= 0; i
< m_tab_offset
; ++i
)
1843 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1849 size_t active
= 999;
1850 int active_offset
= 0;
1854 wxRect rect
= m_rect
;
1856 rect
.height
= m_rect
.height
;
1858 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1860 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1861 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1863 // determine if a close button is on this tab
1864 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1865 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1867 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1869 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1870 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1871 tab_button
.location
= wxCENTER
;
1876 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1880 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1882 if (rect
.width
<= 0)
1889 tab_button
.cur_state
,
1897 active_offset
= offset
;
1905 // make sure to deactivate buttons which are off the screen to the right
1906 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1908 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1912 // draw the active tab again so it stands in the foreground
1913 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1915 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1917 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1919 rect
.x
= active_offset
;
1924 tab_button
.cur_state
,
1931 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1932 m_rect
.GetWidth(), m_rect
.GetHeight(),
1936 // Is the tab visible?
1937 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1939 if (!dc
|| !dc
->IsOk())
1943 size_t page_count
= m_pages
.GetCount();
1944 size_t button_count
= m_buttons
.GetCount();
1946 // Hasn't been rendered yet; assume it's visible
1947 if (m_tab_close_buttons
.GetCount() < page_count
)
1950 // First check if both buttons are disabled - if so, there's no need to
1951 // check further for visibility.
1952 int arrowButtonVisibleCount
= 0;
1953 for (i
= 0; i
< button_count
; ++i
)
1955 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1956 if (button
.id
== wxAUI_BUTTON_LEFT
||
1957 button
.id
== wxAUI_BUTTON_RIGHT
)
1959 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1960 arrowButtonVisibleCount
++;
1964 // Tab must be visible
1965 if (arrowButtonVisibleCount
== 0)
1968 // If tab is less than the given offset, it must be invisible by definition
1969 if (tabPage
< tabOffset
)
1973 int left_buttons_width
= 0;
1974 int right_buttons_width
= 0;
1978 // calculate size of the buttons on the right side
1979 offset
= m_rect
.x
+ m_rect
.width
;
1980 for (i
= 0; i
< button_count
; ++i
)
1982 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1984 if (button
.location
!= wxRIGHT
)
1986 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1989 offset
-= button
.rect
.GetWidth();
1990 right_buttons_width
+= button
.rect
.GetWidth();
1995 // calculate size of the buttons on the left side
1996 for (i
= 0; i
< button_count
; ++i
)
1998 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
2000 if (button
.location
!= wxLEFT
)
2002 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
2005 offset
+= button
.rect
.GetWidth();
2006 left_buttons_width
+= button
.rect
.GetWidth();
2009 offset
= left_buttons_width
;
2012 offset
+= m_art
->GetIndentSize();
2016 wxRect rect
= m_rect
;
2018 rect
.height
= m_rect
.height
;
2020 // See if the given page is visible at the given tab offset (effectively scroll position)
2021 for (i
= tabOffset
; i
< page_count
; ++i
)
2023 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2024 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
2027 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
2029 if (rect
.width
<= 0)
2030 return false; // haven't found the tab, and we've run out of space, so return false
2033 wxSize size
= m_art
->GetTabSize(*dc
,
2038 tab_button
.cur_state
,
2043 if (i
== (size_t) tabPage
)
2045 // If not all of the tab is visible, and supposing there's space to display it all,
2046 // we could do better so we return false.
2047 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
2054 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2055 // further looping in calling code.
2059 // Make the tab visible if it wasn't already
2060 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
2063 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2066 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2068 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2078 // TabHitTest() tests if a tab was hit, passing the window pointer
2079 // back if that condition was fulfilled. The function returns
2080 // true if a tab was hit, otherwise false
2081 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2083 if (!m_rect
.Contains(x
,y
))
2086 wxAuiTabContainerButton
* btn
= NULL
;
2087 if (ButtonHitTest(x
, y
, &btn
) && !(btn
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2089 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2093 size_t i
, page_count
= m_pages
.GetCount();
2095 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2097 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2098 if (page
.rect
.Contains(x
,y
))
2109 // ButtonHitTest() tests if a button was hit. The function returns
2110 // true if a button was hit, otherwise false
2111 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2112 wxAuiTabContainerButton
** hit
) const
2114 if (!m_rect
.Contains(x
,y
))
2117 size_t i
, button_count
;
2120 button_count
= m_buttons
.GetCount();
2121 for (i
= 0; i
< button_count
; ++i
)
2123 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2124 if (button
.rect
.Contains(x
,y
) &&
2125 !(button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
))
2133 button_count
= m_tab_close_buttons
.GetCount();
2134 for (i
= 0; i
< button_count
; ++i
)
2136 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2137 if (button
.rect
.Contains(x
,y
) &&
2138 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2139 wxAUI_BUTTON_STATE_DISABLED
)))
2152 // the utility function ShowWnd() is the same as show,
2153 // except it handles wxAuiMDIChildFrame windows as well,
2154 // as the Show() method on this class is "unplugged"
2155 static void ShowWnd(wxWindow
* wnd
, bool show
)
2158 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2160 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2171 // DoShowHide() this function shows the active window, then
2172 // hides all of the other windows (in that order)
2173 void wxAuiTabContainer::DoShowHide()
2175 wxAuiNotebookPageArray
& pages
= GetPages();
2176 size_t i
, page_count
= pages
.GetCount();
2178 // show new active page first
2179 for (i
= 0; i
< page_count
; ++i
)
2181 wxAuiNotebookPage
& page
= pages
.Item(i
);
2184 ShowWnd(page
.window
, true);
2189 // hide all other pages
2190 for (i
= 0; i
< page_count
; ++i
)
2192 wxAuiNotebookPage
& page
= pages
.Item(i
);
2194 ShowWnd(page
.window
, false);
2203 // -- wxAuiTabCtrl class implementation --
2207 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2208 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2209 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2210 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2211 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2212 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick
)
2213 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2214 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2215 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2216 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2217 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2218 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2219 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2220 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2221 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2222 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2223 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2224 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost
)
2228 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2232 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2234 SetName(wxT("wxAuiTabCtrl"));
2235 m_click_pt
= wxDefaultPosition
;
2236 m_is_dragging
= false;
2237 m_hover_button
= NULL
;
2238 m_pressed_button
= NULL
;
2241 wxAuiTabCtrl::~wxAuiTabCtrl()
2245 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2249 dc
.SetFont(GetFont());
2251 if (GetPageCount() > 0)
2255 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2259 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2261 wxSize s
= evt
.GetSize();
2262 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2266 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2269 m_click_pt
= wxDefaultPosition
;
2270 m_is_dragging
= false;
2272 m_pressed_button
= NULL
;
2276 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2278 int new_selection
= GetIdxFromWindow(wnd
);
2280 // wxAuiNotebooks always want to receive this event
2281 // even if the tab is already active, because they may
2282 // have multiple tab controls
2283 if (new_selection
!= GetActivePage() ||
2284 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2286 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2287 e
.SetSelection(new_selection
);
2288 e
.SetOldSelection(GetActivePage());
2289 e
.SetEventObject(this);
2290 GetEventHandler()->ProcessEvent(e
);
2293 m_click_pt
.x
= evt
.m_x
;
2294 m_click_pt
.y
= evt
.m_y
;
2300 m_pressed_button
= m_hover_button
;
2301 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2307 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
2311 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2313 if (GetCapture() == this)
2318 m_is_dragging
= false;
2320 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2321 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2322 evt
.SetOldSelection(evt
.GetSelection());
2323 evt
.SetEventObject(this);
2324 GetEventHandler()->ProcessEvent(evt
);
2329 if (m_pressed_button
)
2331 // make sure we're still clicking the button
2332 wxAuiTabContainerButton
* button
= NULL
;
2333 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
) ||
2334 button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
)
2337 if (button
!= m_pressed_button
)
2339 m_pressed_button
= NULL
;
2346 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2348 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2349 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2350 evt
.SetInt(m_pressed_button
->id
);
2351 evt
.SetEventObject(this);
2352 GetEventHandler()->ProcessEvent(evt
);
2355 m_pressed_button
= NULL
;
2358 m_click_pt
= wxDefaultPosition
;
2359 m_is_dragging
= false;
2363 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2365 wxWindow
* wnd
= NULL
;
2366 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2369 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2370 e
.SetEventObject(this);
2371 e
.SetSelection(GetIdxFromWindow(wnd
));
2372 GetEventHandler()->ProcessEvent(e
);
2375 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2377 wxWindow
* wnd
= NULL
;
2378 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2381 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2382 e
.SetEventObject(this);
2383 e
.SetSelection(GetIdxFromWindow(wnd
));
2384 GetEventHandler()->ProcessEvent(e
);
2387 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2389 wxWindow
* wnd
= NULL
;
2390 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2393 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2394 e
.SetEventObject(this);
2395 e
.SetSelection(GetIdxFromWindow(wnd
));
2396 GetEventHandler()->ProcessEvent(e
);
2399 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2401 wxWindow
* wnd
= NULL
;
2402 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2405 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2406 e
.SetEventObject(this);
2407 e
.SetSelection(GetIdxFromWindow(wnd
));
2408 GetEventHandler()->ProcessEvent(e
);
2411 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent
& evt
)
2414 wxAuiTabContainerButton
* button
;
2415 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
) && !ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2417 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
2418 e
.SetEventObject(this);
2419 GetEventHandler()->ProcessEvent(e
);
2423 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2425 wxPoint pos
= evt
.GetPosition();
2427 // check if the mouse is hovering above a button
2428 wxAuiTabContainerButton
* button
;
2429 if (ButtonHitTest(pos
.x
, pos
.y
, &button
) && !(button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2431 if (m_hover_button
&& button
!= m_hover_button
)
2433 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2434 m_hover_button
= NULL
;
2439 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2441 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2444 m_hover_button
= button
;
2452 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2453 m_hover_button
= NULL
;
2460 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2465 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2466 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2467 evt
.SetOldSelection(evt
.GetSelection());
2468 evt
.SetEventObject(this);
2469 GetEventHandler()->ProcessEvent(evt
);
2474 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2475 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2477 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2478 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2480 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2481 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2482 evt
.SetOldSelection(evt
.GetSelection());
2483 evt
.SetEventObject(this);
2484 GetEventHandler()->ProcessEvent(evt
);
2486 m_is_dragging
= true;
2490 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2494 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2495 m_hover_button
= NULL
;
2501 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2503 int button
= event
.GetInt();
2505 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2507 if (button
== wxAUI_BUTTON_LEFT
)
2509 if (GetTabOffset() > 0)
2511 SetTabOffset(GetTabOffset()-1);
2518 SetTabOffset(GetTabOffset()+1);
2523 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2525 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2529 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2530 e
.SetSelection(idx
);
2531 e
.SetOldSelection(GetActivePage());
2532 e
.SetEventObject(this);
2533 GetEventHandler()->ProcessEvent(e
);
2542 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2547 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2552 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2554 if (GetActivePage() == -1)
2560 // We can't leave tab processing to the system; on Windows, tabs and keys
2561 // get eaten by the system and not processed properly if we specify both
2562 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2563 // we don't key arrow key events.
2565 int key
= event
.GetKeyCode();
2567 if (key
== WXK_NUMPAD_PAGEUP
)
2569 if (key
== WXK_NUMPAD_PAGEDOWN
)
2571 if (key
== WXK_NUMPAD_HOME
)
2573 if (key
== WXK_NUMPAD_END
)
2575 if (key
== WXK_NUMPAD_LEFT
)
2577 if (key
== WXK_NUMPAD_RIGHT
)
2580 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2582 bool bCtrlDown
= event
.ControlDown();
2583 bool bShiftDown
= event
.ShiftDown();
2585 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2586 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2587 bool bFromTab
= (key
== WXK_TAB
);
2589 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2596 wxNavigationKeyEvent keyEvent
;
2597 keyEvent
.SetDirection(bForward
);
2598 keyEvent
.SetWindowChange(bWindowChange
);
2599 keyEvent
.SetFromTab(bFromTab
);
2600 keyEvent
.SetEventObject(nb
);
2602 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2604 // Not processed? Do an explicit tab into the page.
2605 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2612 if (m_pages
.GetCount() < 2)
2620 int forwardKey
, backwardKey
;
2621 if (GetLayoutDirection() == wxLayout_RightToLeft
)
2623 forwardKey
= WXK_LEFT
;
2624 backwardKey
= WXK_RIGHT
;
2628 forwardKey
= WXK_RIGHT
;
2629 backwardKey
= WXK_LEFT
;
2632 if (key
== forwardKey
)
2634 if (m_pages
.GetCount() > 1)
2636 if (GetActivePage() == -1)
2638 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2639 newPage
= GetActivePage() + 1;
2642 else if (key
== backwardKey
)
2644 if (m_pages
.GetCount() > 1)
2646 if (GetActivePage() == -1)
2647 newPage
= (int) (m_pages
.GetCount() - 1);
2648 else if (GetActivePage() > 0)
2649 newPage
= GetActivePage() - 1;
2652 else if (key
== WXK_HOME
)
2656 else if (key
== WXK_END
)
2658 newPage
= (int) (m_pages
.GetCount() - 1);
2665 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2666 e
.SetSelection(newPage
);
2667 e
.SetOldSelection(newPage
);
2668 e
.SetEventObject(this);
2669 this->GetEventHandler()->ProcessEvent(e
);
2675 // wxTabFrame is an interesting case. It's important that all child pages
2676 // of the multi-notebook control are all actually children of that control
2677 // (and not grandchildren). wxTabFrame facilitates this. There is one
2678 // instance of wxTabFrame for each tab control inside the multi-notebook.
2679 // It's important to know that wxTabFrame is not a real window, but it merely
2680 // used to capture the dimensions/positioning of the internal tab control and
2681 // it's managed page windows
2683 class wxTabFrame
: public wxWindow
2690 m_rect
= wxRect(0,0,200,200);
2691 m_tab_ctrl_height
= 20;
2699 void SetTabCtrlHeight(int h
)
2701 m_tab_ctrl_height
= h
;
2705 void DoSetSize(int x
, int y
,
2706 int width
, int height
,
2707 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2709 m_rect
= wxRect(x
, y
, width
, height
);
2713 void DoGetClientSize(int* x
, int* y
) const
2720 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2727 if (m_tabs
->IsFrozen() || m_tabs
->GetParent()->IsFrozen())
2730 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2731 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2733 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2734 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2735 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2737 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2739 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2740 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2741 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2743 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2744 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2749 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2750 size_t i
, page_count
= pages
.GetCount();
2752 for (i
= 0; i
< page_count
; ++i
)
2754 int height
= m_rect
.height
- m_tab_ctrl_height
;
2757 // avoid passing negative height to wxWindow::SetSize(), this
2758 // results in assert failures/GTK+ warnings
2762 wxAuiNotebookPage
& page
= pages
.Item(i
);
2763 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2765 page
.window
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, height
);
2767 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2769 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2770 m_rect
.width
, height
);
2772 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2773 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2776 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2778 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2779 wnd
->ApplyMDIChildFrameRect();
2786 void DoGetSize(int* x
, int* y
) const
2789 *x
= m_rect
.GetWidth();
2791 *y
= m_rect
.GetHeight();
2802 wxAuiTabCtrl
* m_tabs
;
2803 int m_tab_ctrl_height
;
2807 const int wxAuiBaseTabCtrlId
= 5380;
2810 // -- wxAuiNotebook class implementation --
2812 #define EVT_AUI_RANGE(id1, id2, event, func) \
2813 wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func))
2815 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2816 EVT_SIZE(wxAuiNotebook::OnSize
)
2817 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2818 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2819 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2820 wxAuiNotebook::OnTabClicked
)
2821 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2822 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2823 wxAuiNotebook::OnTabBeginDrag
)
2824 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2825 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2826 wxAuiNotebook::OnTabEndDrag
)
2827 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2828 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2829 wxAuiNotebook::OnTabDragMotion
)
2830 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2831 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2832 wxAuiNotebook::OnTabButton
)
2833 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2834 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2835 wxAuiNotebook::OnTabMiddleDown
)
2836 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2837 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2838 wxAuiNotebook::OnTabMiddleUp
)
2839 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2840 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2841 wxAuiNotebook::OnTabRightDown
)
2842 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2843 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2844 wxAuiNotebook::OnTabRightUp
)
2845 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2846 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
,
2847 wxAuiNotebook::OnTabBgDClick
)
2848 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2850 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2851 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2853 // Avoid clash with container event handler functions
2854 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2858 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2860 wxAuiNotebook::wxAuiNotebook()
2863 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2865 m_tab_ctrl_height
= 20;
2866 m_requested_bmp_size
= wxDefaultSize
;
2867 m_requested_tabctrl_height
= -1;
2870 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2874 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2877 m_requested_bmp_size
= wxDefaultSize
;
2878 m_requested_tabctrl_height
= -1;
2879 InitNotebook(style
);
2882 bool wxAuiNotebook::Create(wxWindow
* parent
,
2888 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2891 InitNotebook(style
);
2896 // InitNotebook() contains common initialization
2897 // code called by all constructors
2898 void wxAuiNotebook::InitNotebook(long style
)
2900 WX_INIT_CONTROL_CONTAINER();
2901 // SetCanFocus(false);
2903 SetName(wxT("wxAuiNotebook"));
2905 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2907 m_flags
= (unsigned int)style
;
2908 m_tab_ctrl_height
= 20;
2910 m_normal_font
= *wxNORMAL_FONT
;
2911 m_selected_font
= *wxNORMAL_FONT
;
2912 m_selected_font
.SetWeight(wxBOLD
);
2914 SetArtProvider(new wxAuiDefaultTabArt
);
2916 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2917 m_dummy_wnd
->SetSize(200, 200);
2918 m_dummy_wnd
->Show(false);
2920 m_mgr
.SetManagedWindow(this);
2921 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2922 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2924 m_mgr
.AddPane(m_dummy_wnd
,
2925 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2930 wxAuiNotebook::~wxAuiNotebook()
2932 // Indicate we're deleting pages
2935 while ( GetPageCount() > 0 )
2941 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2943 m_tabs
.SetArtProvider(art
);
2945 // Update the height and do nothing else if it did something but otherwise
2946 // (i.e. if the new art provider uses the same height as the old one) we
2947 // need to manually set the art provider for all tabs ourselves.
2948 if ( !UpdateTabCtrlHeight() )
2950 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2951 const size_t pane_count
= all_panes
.GetCount();
2952 for (size_t i
= 0; i
< pane_count
; ++i
)
2954 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2955 if (pane
.name
== wxT("dummy"))
2957 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2958 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2959 tabctrl
->SetArtProvider(art
->Clone());
2964 // SetTabCtrlHeight() is the highest-level override of the
2965 // tab height. A call to this function effectively enforces a
2966 // specified tab ctrl height, overriding all other considerations,
2967 // such as text or bitmap height. It overrides any call to
2968 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2969 // any previous call and returns to the default behaviour
2971 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2973 m_requested_tabctrl_height
= height
;
2975 // if window is already initialized, recalculate the tab height
2978 UpdateTabCtrlHeight();
2983 // SetUniformBitmapSize() ensures that all tabs will have
2984 // the same height, even if some tabs don't have bitmaps
2985 // Passing wxDefaultSize to this function will instruct
2986 // the control to use dynamic tab height-- so when a tab
2987 // with a large bitmap is added, the tab ctrl's height will
2988 // automatically increase to accommodate the bitmap
2990 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2992 m_requested_bmp_size
= size
;
2994 // if window is already initialized, recalculate the tab height
2997 UpdateTabCtrlHeight();
3001 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
3002 // to be used internally
3003 bool wxAuiNotebook::UpdateTabCtrlHeight()
3005 // get the tab ctrl height we will use
3006 int height
= CalculateTabCtrlHeight();
3008 // if the tab control height needs to change, update
3009 // all of our tab controls with the new height
3010 if (m_tab_ctrl_height
== height
)
3013 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
3015 m_tab_ctrl_height
= height
;
3017 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3018 size_t i
, pane_count
= all_panes
.GetCount();
3019 for (i
= 0; i
< pane_count
; ++i
)
3021 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3022 if (pane
.name
== wxT("dummy"))
3024 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
3025 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
3026 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
3027 tabctrl
->SetArtProvider(art
->Clone());
3028 tab_frame
->DoSizing();
3034 void wxAuiNotebook::UpdateHintWindowSize()
3036 wxSize size
= CalculateNewSplitSize();
3038 // the placeholder hint window should be set to this size
3039 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
3043 info
.BestSize(size
);
3044 m_dummy_wnd
->SetSize(size
);
3049 // calculates the size of the new split
3050 wxSize
wxAuiNotebook::CalculateNewSplitSize()
3052 // count number of tab controls
3053 int tab_ctrl_count
= 0;
3054 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3055 size_t i
, pane_count
= all_panes
.GetCount();
3056 for (i
= 0; i
< pane_count
; ++i
)
3058 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3059 if (pane
.name
== wxT("dummy"))
3064 wxSize new_split_size
;
3066 // if there is only one tab control, the first split
3067 // should happen around the middle
3068 if (tab_ctrl_count
< 2)
3070 new_split_size
= GetClientSize();
3071 new_split_size
.x
/= 2;
3072 new_split_size
.y
/= 2;
3076 // this is in place of a more complicated calculation
3077 // that needs to be implemented
3078 new_split_size
= wxSize(180,180);
3081 return new_split_size
;
3084 int wxAuiNotebook::CalculateTabCtrlHeight()
3086 // if a fixed tab ctrl height is specified,
3087 // just return that instead of calculating a
3089 if (m_requested_tabctrl_height
!= -1)
3090 return m_requested_tabctrl_height
;
3092 // find out new best tab height
3093 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
3095 return art
->GetBestTabCtrlSize(this,
3097 m_requested_bmp_size
);
3101 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
3103 return m_tabs
.GetArtProvider();
3106 void wxAuiNotebook::SetWindowStyleFlag(long style
)
3108 wxControl::SetWindowStyleFlag(style
);
3110 m_flags
= (unsigned int)style
;
3112 // if the control is already initialized
3113 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
3115 // let all of the tab children know about the new style
3117 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3118 size_t i
, pane_count
= all_panes
.GetCount();
3119 for (i
= 0; i
< pane_count
; ++i
)
3121 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3122 if (pane
.name
== wxT("dummy"))
3124 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3125 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
3126 tabctrl
->SetFlags(m_flags
);
3127 tabframe
->DoSizing();
3135 bool wxAuiNotebook::AddPage(wxWindow
* page
,
3136 const wxString
& caption
,
3138 const wxBitmap
& bitmap
)
3140 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
3143 bool wxAuiNotebook::InsertPage(size_t page_idx
,
3145 const wxString
& caption
,
3147 const wxBitmap
& bitmap
)
3149 wxASSERT_MSG(page
, wxT("page pointer must be non-NULL"));
3153 page
->Reparent(this);
3155 wxAuiNotebookPage info
;
3157 info
.caption
= caption
;
3158 info
.bitmap
= bitmap
;
3159 info
.active
= false;
3161 // if there are currently no tabs, the first added
3162 // tab must be active
3163 if (m_tabs
.GetPageCount() == 0)
3166 m_tabs
.InsertPage(page
, info
, page_idx
);
3168 // if that was the first page added, even if
3169 // select is false, it must become the "current page"
3170 // (though no select events will be fired)
3171 if (!select
&& m_tabs
.GetPageCount() == 1)
3173 //m_curpage = GetPageIndex(page);
3175 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3176 if (page_idx
>= active_tabctrl
->GetPageCount())
3177 active_tabctrl
->AddPage(page
, info
);
3179 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3181 UpdateTabCtrlHeight();
3183 active_tabctrl
->DoShowHide();
3185 // adjust selected index
3186 if(m_curpage
>= (int) page_idx
)
3191 SetSelectionToWindow(page
);
3198 // DeletePage() removes a tab from the multi-notebook,
3199 // and destroys the window as well
3200 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3202 if (page_idx
>= m_tabs
.GetPageCount())
3205 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3207 // hide the window in advance, as this will
3209 ShowWnd(wnd
, false);
3211 if (!RemovePage(page_idx
))
3215 // actually destroy the window now
3216 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3218 // delete the child frame with pending delete, as is
3219 // customary with frame windows
3220 if (!wxPendingDelete
.Member(wnd
))
3221 wxPendingDelete
.Append(wnd
);
3234 // RemovePage() removes a tab from the multi-notebook,
3235 // but does not destroy the window
3236 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3238 // save active window pointer
3239 wxWindow
* active_wnd
= NULL
;
3241 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3243 // save pointer of window being deleted
3244 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3245 wxWindow
* new_active
= NULL
;
3247 // make sure we found the page
3251 // find out which onscreen tab ctrl owns this tab
3254 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3257 bool is_curpage
= (m_curpage
== (int)page_idx
);
3258 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3261 // remove the tab from main catalog
3262 if (!m_tabs
.RemovePage(wnd
))
3265 // remove the tab from the onscreen tab ctrl
3266 ctrl
->RemovePage(wnd
);
3268 if (is_active_in_split
)
3270 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3272 if (ctrl_idx
>= ctrl_new_page_count
)
3273 ctrl_idx
= ctrl_new_page_count
-1;
3275 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3277 // set new page as active in the tab split
3278 ctrl
->SetActivePage(ctrl_idx
);
3280 // if the page deleted was the current page for the
3281 // entire tab control, then record the window
3282 // pointer of the new active page for activation
3285 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3291 // we are not deleting the active page, so keep it the same
3292 new_active
= active_wnd
;
3298 // we haven't yet found a new page to active,
3299 // so select the next page from the main tab
3302 if (page_idx
< m_tabs
.GetPageCount())
3304 new_active
= m_tabs
.GetPage(page_idx
).window
;
3307 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3309 new_active
= m_tabs
.GetPage(0).window
;
3314 RemoveEmptyTabFrames();
3316 m_curpage
= wxNOT_FOUND
;
3318 // set new active pane unless we're being destroyed anyhow
3319 if (new_active
&& !m_isBeingDeleted
)
3320 SetSelectionToWindow(new_active
);
3325 // GetPageIndex() returns the index of the page, or -1 if the
3326 // page could not be located in the notebook
3327 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3329 return m_tabs
.GetIdxFromWindow(page_wnd
);
3334 // SetPageText() changes the tab caption of the specified page
3335 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3337 if (page_idx
>= m_tabs
.GetPageCount())
3340 // update our own tab catalog
3341 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3342 page_info
.caption
= text
;
3344 // update what's on screen
3347 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3349 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3350 info
.caption
= text
;
3358 // returns the page caption
3359 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3361 if (page_idx
>= m_tabs
.GetPageCount())
3362 return wxEmptyString
;
3364 // update our own tab catalog
3365 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3366 return page_info
.caption
;
3369 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3371 if (page_idx
>= m_tabs
.GetPageCount())
3374 // update our own tab catalog
3375 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3376 page_info
.bitmap
= bitmap
;
3378 // tab height might have changed
3379 UpdateTabCtrlHeight();
3381 // update what's on screen
3384 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3386 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3387 info
.bitmap
= bitmap
;
3395 // returns the page bitmap
3396 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3398 if (page_idx
>= m_tabs
.GetPageCount())
3401 // update our own tab catalog
3402 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3403 return page_info
.bitmap
;
3406 // GetSelection() returns the index of the currently active page
3407 int wxAuiNotebook::GetSelection() const
3412 // SetSelection() sets the currently active page
3413 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3415 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3419 // don't change the page unless necessary;
3420 // however, clicking again on a tab should give it the focus.
3421 if ((int)new_page
== m_curpage
)
3425 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3427 if (FindFocus() != ctrl
)
3433 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3434 evt
.SetSelection(new_page
);
3435 evt
.SetOldSelection(m_curpage
);
3436 evt
.SetEventObject(this);
3437 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3439 int old_curpage
= m_curpage
;
3440 m_curpage
= new_page
;
3442 // program allows the page change
3443 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3444 (void)GetEventHandler()->ProcessEvent(evt
);
3449 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3451 m_tabs
.SetActivePage(wnd
);
3453 ctrl
->SetActivePage(ctrl_idx
);
3457 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3460 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3461 size_t i
, pane_count
= all_panes
.GetCount();
3462 for (i
= 0; i
< pane_count
; ++i
)
3464 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3465 if (pane
.name
== wxT("dummy"))
3467 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3468 if (tabctrl
!= ctrl
)
3469 tabctrl
->SetSelectedFont(m_normal_font
);
3471 tabctrl
->SetSelectedFont(m_selected_font
);
3475 // Set the focus to the page if we're not currently focused on the tab.
3476 // This is Firefox-like behaviour.
3477 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3487 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3489 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3490 wxCHECK_RET( idx
!= wxNOT_FOUND
, wxT("invalid notebook page") );
3493 // since a tab was clicked, let the parent know that we received
3494 // the focus, even if we will assign that focus immediately
3495 // to the child tab in the SetSelection call below
3496 // (the child focus event will also let wxAuiManager, if any,
3497 // know that the notebook control has been activated)
3499 wxWindow
* parent
= GetParent();
3502 wxChildFocusEvent
eventFocus(this);
3503 parent
->GetEventHandler()->ProcessEvent(eventFocus
);
3510 // GetPageCount() returns the total number of
3511 // pages managed by the multi-notebook
3512 size_t wxAuiNotebook::GetPageCount() const
3514 return m_tabs
.GetPageCount();
3517 // GetPage() returns the wxWindow pointer of the
3519 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3521 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3523 return m_tabs
.GetWindowFromIdx(page_idx
);
3526 // DoSizing() performs all sizing operations in each tab control
3527 void wxAuiNotebook::DoSizing()
3529 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3530 size_t i
, pane_count
= all_panes
.GetCount();
3531 for (i
= 0; i
< pane_count
; ++i
)
3533 if (all_panes
.Item(i
).name
== wxT("dummy"))
3536 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3537 tabframe
->DoSizing();
3541 // GetActiveTabCtrl() returns the active tab control. It is
3542 // called to determine which control gets new windows being added
3543 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3545 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3550 // find the tab ctrl with the current page
3551 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3558 // no current page, just find the first tab ctrl
3559 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3560 size_t i
, pane_count
= all_panes
.GetCount();
3561 for (i
= 0; i
< pane_count
; ++i
)
3563 if (all_panes
.Item(i
).name
== wxT("dummy"))
3566 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3567 return tabframe
->m_tabs
;
3570 // If there is no tabframe at all, create one
3571 wxTabFrame
* tabframe
= new wxTabFrame
;
3572 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3573 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3577 wxNO_BORDER
|wxWANTS_CHARS
);
3578 tabframe
->m_tabs
->SetFlags(m_flags
);
3579 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3580 m_mgr
.AddPane(tabframe
,
3581 wxAuiPaneInfo().Center().CaptionVisible(false));
3585 return tabframe
->m_tabs
;
3588 // FindTab() finds the tab control that currently contains the window as well
3589 // as the index of the window in the tab control. It returns true if the
3590 // window was found, otherwise false.
3591 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3593 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3594 size_t i
, pane_count
= all_panes
.GetCount();
3595 for (i
= 0; i
< pane_count
; ++i
)
3597 if (all_panes
.Item(i
).name
== wxT("dummy"))
3600 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3602 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3605 *ctrl
= tabframe
->m_tabs
;
3614 void wxAuiNotebook::Split(size_t page
, int direction
)
3616 wxSize cli_size
= GetClientSize();
3618 // get the page's window pointer
3619 wxWindow
* wnd
= GetPage(page
);
3623 // notebooks with 1 or less pages can't be split
3624 if (GetPageCount() < 2)
3627 // find out which tab control the page currently belongs to
3628 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3631 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3633 if (!src_tabs
|| src_idx
== -1)
3636 // choose a split size
3638 if (GetPageCount() > 2)
3640 split_size
= CalculateNewSplitSize();
3644 // because there are two panes, always split them
3646 split_size
= GetClientSize();
3652 // create a new tab frame
3653 wxTabFrame
* new_tabs
= new wxTabFrame
;
3654 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3655 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3656 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3660 wxNO_BORDER
|wxWANTS_CHARS
);
3661 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3662 new_tabs
->m_tabs
->SetFlags(m_flags
);
3663 dest_tabs
= new_tabs
->m_tabs
;
3665 // create a pane info structure with the information
3666 // about where the pane should be added
3667 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3670 if (direction
== wxLEFT
)
3673 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3675 else if (direction
== wxRIGHT
)
3678 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3680 else if (direction
== wxTOP
)
3683 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3685 else if (direction
== wxBOTTOM
)
3688 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3691 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3694 // remove the page from the source tabs
3695 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3696 page_info
.active
= false;
3697 src_tabs
->RemovePage(page_info
.window
);
3698 if (src_tabs
->GetPageCount() > 0)
3700 src_tabs
->SetActivePage((size_t)0);
3701 src_tabs
->DoShowHide();
3702 src_tabs
->Refresh();
3706 // add the page to the destination tabs
3707 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3709 if (src_tabs
->GetPageCount() == 0)
3711 RemoveEmptyTabFrames();
3715 dest_tabs
->DoShowHide();
3716 dest_tabs
->Refresh();
3718 // force the set selection function reset the selection
3721 // set the active page to the one we just split off
3722 SetSelectionToPage(page_info
);
3724 UpdateHintWindowSize();
3728 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3730 UpdateHintWindowSize();
3735 void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent
& evt
)
3737 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3738 wxASSERT(ctrl
!= NULL
);
3740 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3741 wxASSERT(wnd
!= NULL
);
3743 SetSelectionToWindow(wnd
);
3746 void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent
& WXUNUSED(evt
))
3748 // notify owner that the tabbar background has been double-clicked
3749 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
3750 e
.SetEventObject(this);
3751 GetEventHandler()->ProcessEvent(e
);
3754 void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent
&)
3759 void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent
& evt
)
3761 wxPoint screen_pt
= ::wxGetMousePosition();
3762 wxPoint client_pt
= ScreenToClient(screen_pt
);
3765 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3766 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3768 if (dest_tabs
== src_tabs
)
3772 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3775 // always hide the hint for inner-tabctrl drag
3778 // if tab moving is not allowed, leave
3779 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3784 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3785 wxWindow
* dest_location_tab
;
3787 // this is an inner-tab drag/reposition
3788 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3790 int src_idx
= evt
.GetSelection();
3791 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3793 // prevent jumpy drag
3794 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3795 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3796 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3798 m_last_drag_x
= pt
.x
;
3803 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3804 dest_tabs
->MovePage(src_tab
, dest_idx
);
3805 dest_tabs
->SetActivePage((size_t)dest_idx
);
3806 dest_tabs
->DoShowHide();
3807 dest_tabs
->Refresh();
3808 m_last_drag_x
= pt
.x
;
3816 // if external drag is allowed, check if the tab is being dragged
3817 // over a different wxAuiNotebook control
3818 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3820 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3822 // if we aren't over any window, stop here
3826 // make sure we are not over the hint window
3827 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3831 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3833 tab_ctrl
= tab_ctrl
->GetParent();
3838 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3842 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3843 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3844 m_mgr
.ShowHint(hint_rect
);
3853 // we are either over a hint window, or not over a tab
3854 // window, and there is no where to drag to, so exit
3861 // if there are less than two panes, split can't happen, so leave
3862 if (m_tabs
.GetPageCount() < 2)
3865 // if tab moving is not allowed, leave
3866 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3872 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3878 wxRect hint_rect
= dest_tabs
->GetRect();
3879 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3880 m_mgr
.ShowHint(hint_rect
);
3884 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3890 void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent
& evt
)
3895 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3896 wxCHECK_RET( src_tabs
, wxT("no source object?") );
3898 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3900 // get the mouse position, which will be used to determine the drop point
3901 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3902 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3906 // check for an external move
3907 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3909 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3913 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3915 tab_ctrl
= tab_ctrl
->GetParent();
3920 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3924 // find out from the destination control
3925 // if it's ok to drop this tab here
3926 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3927 e
.SetSelection(evt
.GetSelection());
3928 e
.SetOldSelection(evt
.GetSelection());
3929 e
.SetEventObject(this);
3930 e
.SetDragSource(this);
3931 e
.Veto(); // dropping must be explicitly approved by control owner
3933 nb
->GetEventHandler()->ProcessEvent(e
);
3937 // no answer or negative answer
3943 int src_idx
= evt
.GetSelection();
3944 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3946 // Check that it's not an impossible parent relationship
3948 while (p
&& !p
->IsTopLevel())
3957 // get main index of the page
3958 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3959 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no source page?") );
3962 // make a copy of the page info
3963 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3965 // remove the page from the source notebook
3966 RemovePage(main_idx
);
3968 // reparent the page
3969 src_page
->Reparent(nb
);
3972 // found out the insert idx
3973 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3974 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3976 wxWindow
* target
= NULL
;
3977 int insert_idx
= -1;
3978 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3981 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3985 // add the page to the new notebook
3986 if (insert_idx
== -1)
3987 insert_idx
= dest_tabs
->GetPageCount();
3988 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3989 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3992 dest_tabs
->DoShowHide();
3993 dest_tabs
->Refresh();
3995 // set the selection in the destination tab control
3996 nb
->SetSelectionToPage(page_info
);
3998 // notify owner that the tab has been dragged
3999 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
4000 e2
.SetSelection(evt
.GetSelection());
4001 e2
.SetOldSelection(evt
.GetSelection());
4002 e2
.SetEventObject(this);
4003 GetEventHandler()->ProcessEvent(e2
);
4013 // only perform a tab split if it's allowed
4014 wxAuiTabCtrl
* dest_tabs
= NULL
;
4016 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
4018 // If the pointer is in an existing tab frame, do a tab insert
4019 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
4020 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
4021 int insert_idx
= -1;
4024 dest_tabs
= tab_frame
->m_tabs
;
4026 if (dest_tabs
== src_tabs
)
4030 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
4031 wxWindow
* target
= NULL
;
4032 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
4035 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
4041 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
4046 // there is no suitable drop location here, exit out
4050 // If there is no tabframe at all, create one
4051 wxTabFrame
* new_tabs
= new wxTabFrame
;
4052 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
4053 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
4054 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
4058 wxNO_BORDER
|wxWANTS_CHARS
);
4059 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
4060 new_tabs
->m_tabs
->SetFlags(m_flags
);
4062 m_mgr
.AddPane(new_tabs
,
4063 wxAuiPaneInfo().Bottom().CaptionVisible(false),
4066 dest_tabs
= new_tabs
->m_tabs
;
4071 // remove the page from the source tabs
4072 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
4073 page_info
.active
= false;
4074 src_tabs
->RemovePage(page_info
.window
);
4075 if (src_tabs
->GetPageCount() > 0)
4077 src_tabs
->SetActivePage((size_t)0);
4078 src_tabs
->DoShowHide();
4079 src_tabs
->Refresh();
4084 // add the page to the destination tabs
4085 if (insert_idx
== -1)
4086 insert_idx
= dest_tabs
->GetPageCount();
4087 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
4089 if (src_tabs
->GetPageCount() == 0)
4091 RemoveEmptyTabFrames();
4095 dest_tabs
->DoShowHide();
4096 dest_tabs
->Refresh();
4098 // force the set selection function reset the selection
4101 // set the active page to the one we just split off
4102 SetSelectionToPage(page_info
);
4104 UpdateHintWindowSize();
4107 // notify owner that the tab has been dragged
4108 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
4109 e
.SetSelection(evt
.GetSelection());
4110 e
.SetOldSelection(evt
.GetSelection());
4111 e
.SetEventObject(this);
4112 GetEventHandler()->ProcessEvent(e
);
4117 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
4119 // if we've just removed the last tab from the source
4120 // tab set, the remove the tab control completely
4121 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4122 size_t i
, pane_count
= all_panes
.GetCount();
4123 for (i
= 0; i
< pane_count
; ++i
)
4125 if (all_panes
.Item(i
).name
== wxT("dummy"))
4128 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4129 if (tabframe
->m_tab_rect
.Contains(pt
))
4130 return tabframe
->m_tabs
;
4136 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
4138 // if we've just removed the last tab from the source
4139 // tab set, the remove the tab control completely
4140 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4141 size_t i
, pane_count
= all_panes
.GetCount();
4142 for (i
= 0; i
< pane_count
; ++i
)
4144 if (all_panes
.Item(i
).name
== wxT("dummy"))
4147 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4148 if (tabframe
->m_tabs
== tab_ctrl
)
4157 void wxAuiNotebook::RemoveEmptyTabFrames()
4159 // if we've just removed the last tab from the source
4160 // tab set, the remove the tab control completely
4161 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
4162 size_t i
, pane_count
= all_panes
.GetCount();
4163 for (i
= 0; i
< pane_count
; ++i
)
4165 if (all_panes
.Item(i
).name
== wxT("dummy"))
4168 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4169 if (tab_frame
->m_tabs
->GetPageCount() == 0)
4171 m_mgr
.DetachPane(tab_frame
);
4173 // use pending delete because sometimes during
4174 // window closing, refreshs are pending
4175 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
4176 wxPendingDelete
.Append(tab_frame
->m_tabs
);
4178 tab_frame
->m_tabs
= NULL
;
4185 // check to see if there is still a center pane;
4186 // if there isn't, make a frame the center pane
4187 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4188 pane_count
= panes
.GetCount();
4189 wxWindow
* first_good
= NULL
;
4190 bool center_found
= false;
4191 for (i
= 0; i
< pane_count
; ++i
)
4193 if (panes
.Item(i
).name
== wxT("dummy"))
4195 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4196 center_found
= true;
4198 first_good
= panes
.Item(i
).window
;
4201 if (!center_found
&& first_good
)
4203 m_mgr
.GetPane(first_good
).Centre();
4206 if (!m_isBeingDeleted
)
4210 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4214 // if we're dragging a tab, don't change the current selection.
4215 // This code prevents a bug that used to happen when the hint window
4216 // was hidden. In the bug, the focus would return to the notebook
4217 // child, which would then enter this handler and call
4218 // SetSelection, which is not desired turn tab dragging.
4220 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4221 size_t i
, pane_count
= all_panes
.GetCount();
4222 for (i
= 0; i
< pane_count
; ++i
)
4224 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4225 if (pane
.name
== wxT("dummy"))
4227 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4228 if (tabframe
->m_tabs
->IsDragging())
4233 // change the tab selection to the child
4234 // which was focused
4235 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4236 if (idx
!= -1 && idx
!= m_curpage
)
4242 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4244 if ( event
.IsWindowChange() ) {
4246 // FIXME: the problem with this is that if we have a split notebook,
4247 // we selection may go all over the place.
4248 AdvanceSelection(event
.GetDirection());
4251 // we get this event in 3 cases
4253 // a) one of our pages might have generated it because the user TABbed
4254 // out from it in which case we should propagate the event upwards and
4255 // our parent will take care of setting the focus to prev/next sibling
4259 // b) the parent panel wants to give the focus to us so that we
4260 // forward it to our selected page. We can't deal with this in
4261 // OnSetFocus() because we don't know which direction the focus came
4262 // from in this case and so can't choose between setting the focus to
4263 // first or last panel child
4267 // c) we ourselves (see MSWTranslateMessage) generated the event
4269 wxWindow
* const parent
= GetParent();
4271 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4272 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4273 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4275 if ( isFromParent
|| isFromSelf
)
4277 // no, it doesn't come from child, case (b) or (c): forward to a
4278 // page but only if direction is backwards (TAB) or from ourselves,
4279 if ( GetSelection() != wxNOT_FOUND
&&
4280 (!event
.GetDirection() || isFromSelf
) )
4282 // so that the page knows that the event comes from it's parent
4283 // and is being propagated downwards
4284 event
.SetEventObject(this);
4286 wxWindow
*page
= GetPage(GetSelection());
4287 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4291 //else: page manages focus inside it itself
4293 else // otherwise set the focus to the notebook itself
4300 // it comes from our child, case (a), pass to the parent, but only
4301 // if the direction is forwards. Otherwise set the focus to the
4302 // notebook itself. The notebook is always the 'first' control of a
4304 if ( !event
.GetDirection() )
4310 event
.SetCurrentFocus(this);
4311 parent
->GetEventHandler()->ProcessEvent(event
);
4317 void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent
& evt
)
4319 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4321 int button_id
= evt
.GetInt();
4323 if (button_id
== wxAUI_BUTTON_CLOSE
)
4325 int selection
= evt
.GetSelection();
4327 if (selection
== -1)
4329 // if the close button is to the right, use the active
4330 // page selection to determine which page to close
4331 selection
= tabs
->GetActivePage();
4334 if (selection
!= -1)
4336 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4338 // ask owner if it's ok to close the tab
4339 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4340 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4341 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4342 e
.SetSelection(idx
);
4343 e
.SetOldSelection(evt
.GetSelection());
4344 e
.SetEventObject(this);
4345 GetEventHandler()->ProcessEvent(e
);
4351 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4358 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4359 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no page to delete?") );
4361 DeletePage(main_idx
);
4364 // notify owner that the tab has been closed
4365 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4366 e2
.SetSelection(idx
);
4367 e2
.SetEventObject(this);
4368 GetEventHandler()->ProcessEvent(e2
);
4374 void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent
& evt
)
4376 // patch event through to owner
4377 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4378 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4380 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4381 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4382 e
.SetEventObject(this);
4383 GetEventHandler()->ProcessEvent(e
);
4386 void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent
& evt
)
4388 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4389 // click should act like a tab close action. However, first
4390 // give the owner an opportunity to handle the middle up event
4391 // for custom action
4393 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4394 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4396 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4397 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4398 e
.SetEventObject(this);
4399 if (GetEventHandler()->ProcessEvent(e
))
4404 // check if we are supposed to close on middle-up
4405 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4408 // simulate the user pressing the close button on the tab
4409 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4413 void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent
& evt
)
4415 // patch event through to owner
4416 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4417 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4419 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4420 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4421 e
.SetEventObject(this);
4422 GetEventHandler()->ProcessEvent(e
);
4425 void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent
& evt
)
4427 // patch event through to owner
4428 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4429 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4431 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4432 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4433 e
.SetEventObject(this);
4434 GetEventHandler()->ProcessEvent(e
);
4437 // Sets the normal font
4438 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4440 m_normal_font
= font
;
4441 GetArtProvider()->SetNormalFont(font
);
4444 // Sets the selected tab font
4445 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4447 m_selected_font
= font
;
4448 GetArtProvider()->SetSelectedFont(font
);
4451 // Sets the measuring font
4452 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4454 GetArtProvider()->SetMeasuringFont(font
);
4457 // Sets the tab font
4458 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4460 wxControl::SetFont(font
);
4462 wxFont
normalFont(font
);
4463 wxFont
selectedFont(normalFont
);
4464 selectedFont
.SetWeight(wxBOLD
);
4466 SetNormalFont(normalFont
);
4467 SetSelectedFont(selectedFont
);
4468 SetMeasuringFont(selectedFont
);
4473 // Gets the tab control height
4474 int wxAuiNotebook::GetTabCtrlHeight() const
4476 return m_tab_ctrl_height
;
4479 // Gets the height of the notebook for a given page height
4480 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4482 UpdateTabCtrlHeight();
4484 int tabCtrlHeight
= GetTabCtrlHeight();
4485 int decorHeight
= 2;
4486 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4489 // Advances the selection, generation page selection events
4490 void wxAuiNotebook::AdvanceSelection(bool forward
)
4492 if (GetPageCount() <= 1)
4495 int currentSelection
= GetSelection();
4499 if (currentSelection
== (int) (GetPageCount() - 1))
4501 else if (currentSelection
== -1)
4502 currentSelection
= 0;
4504 currentSelection
++;
4508 if (currentSelection
<= 0)
4511 currentSelection
--;
4514 SetSelection(currentSelection
);
4517 // Shows the window menu
4518 bool wxAuiNotebook::ShowWindowMenu()
4520 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4522 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4526 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4527 e
.SetSelection(idx
);
4528 e
.SetOldSelection(tabCtrl
->GetActivePage());
4529 e
.SetEventObject(tabCtrl
);
4530 GetEventHandler()->ProcessEvent(e
);
4538 void wxAuiNotebook::Thaw()