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 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
73 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
74 const wxColour
& color
);
76 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
78 static void DrawButtons(wxDC
& dc
,
81 const wxColour
& bkcolour
,
86 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
93 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
95 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
96 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
98 // draw the background behind the button
99 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
102 // draw the button itself
103 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
106 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
108 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
117 // -- GUI helper classes and functions --
119 class wxAuiCommandCapture
: public wxEvtHandler
123 wxAuiCommandCapture() { m_last_id
= 0; }
124 int GetCommandId() const { return m_last_id
; }
126 bool ProcessEvent(wxEvent
& evt
)
128 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
130 m_last_id
= evt
.GetId();
134 if (GetNextHandler())
135 return GetNextHandler()->ProcessEvent(evt
);
147 #if defined( __WXMAC__ )
148 static const unsigned char close_bits
[]={
149 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
150 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
151 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
152 #elif defined( __WXGTK__)
153 static const unsigned char close_bits
[]={
154 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
155 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
156 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
158 static const unsigned char close_bits
[]={
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
160 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
164 static const unsigned char left_bits
[] = {
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
166 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
169 static const unsigned char right_bits
[] = {
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
171 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
174 static const unsigned char list_bits
[] = {
175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
176 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
177 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
184 // -- wxAuiDefaultTabArt class implementation --
186 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
188 m_normal_font
= *wxNORMAL_FONT
;
189 m_selected_font
= *wxNORMAL_FONT
;
190 m_selected_font
.SetWeight(wxBOLD
);
191 m_measuring_font
= m_selected_font
;
193 m_fixed_tab_width
= 100;
194 m_tab_ctrl_height
= 0;
196 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
197 wxColor base_colour
= wxColour( wxMacCreateCGColorFromHITheme(kThemeBrushToolbarBackground
));
199 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
202 // the base_colour is too pale to use as our base colour,
203 // so darken it a bit --
204 if ((255-base_colour
.Red()) +
205 (255-base_colour
.Green()) +
206 (255-base_colour
.Blue()) < 60)
208 base_colour
= wxAuiStepColour(base_colour
, 92);
211 m_base_colour
= base_colour
;
212 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
214 m_border_pen
= wxPen(border_colour
);
215 m_base_colour_pen
= wxPen(m_base_colour
);
216 m_base_colour_brush
= wxBrush(m_base_colour
);
218 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
219 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
221 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
222 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
224 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
225 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
227 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
228 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
233 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
237 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
239 return new wxAuiDefaultTabArt(*this);
242 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
247 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
250 m_fixed_tab_width
= 100;
252 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
254 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
255 tot_width
-= m_active_close_bmp
.GetWidth();
256 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
257 tot_width
-= m_active_windowlist_bmp
.GetWidth();
261 m_fixed_tab_width
= tot_width
/(int)tab_count
;
265 if (m_fixed_tab_width
< 100)
266 m_fixed_tab_width
= 100;
268 if (m_fixed_tab_width
> tot_width
/2)
269 m_fixed_tab_width
= tot_width
/2;
271 if (m_fixed_tab_width
> 220)
272 m_fixed_tab_width
= 220;
274 m_tab_ctrl_height
= tab_ctrl_size
.y
;
278 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
279 wxWindow
* WXUNUSED(wnd
),
284 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
285 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
288 if (m_flags
&wxAUI_NB_BOTTOM
)
289 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
);
290 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
291 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
292 else //for wxAUI_NB_TOP
293 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
295 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
300 dc
.SetPen(m_border_pen
);
301 int y
= rect
.GetHeight();
302 int w
= rect
.GetWidth();
304 if (m_flags
&wxAUI_NB_BOTTOM
)
306 dc
.SetBrush(wxBrush(bottom_color
));
307 dc
.DrawRectangle(-1, 0, w
+2, 4);
309 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
310 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
311 else //for wxAUI_NB_TOP
313 dc
.SetBrush(m_base_colour_brush
);
314 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
319 // DrawTab() draws an individual tab.
322 // in_rect - rectangle the tab should be confined to
323 // caption - tab's caption
324 // active - whether or not the tab is active
325 // out_rect - actual output rectangle
326 // x_extent - the advance x; where the next tab should start
328 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
330 const wxAuiNotebookPage
& page
,
331 const wxRect
& in_rect
,
332 int close_button_state
,
333 wxRect
* out_tab_rect
,
334 wxRect
* out_button_rect
,
337 wxCoord normal_textx
, normal_texty
;
338 wxCoord selected_textx
, selected_texty
;
341 // if the caption is empty, measure some temporary text
342 wxString caption
= page
.caption
;
346 dc
.SetFont(m_selected_font
);
347 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
349 dc
.SetFont(m_normal_font
);
350 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
352 // figure out the size of the tab
353 wxSize tab_size
= GetTabSize(dc
,
361 wxCoord tab_height
= m_tab_ctrl_height
- 3;
362 wxCoord tab_width
= tab_size
.x
;
363 wxCoord tab_x
= in_rect
.x
;
364 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
367 caption
= page
.caption
;
370 // select pen, brush and font for the tab to be drawn
374 dc
.SetFont(m_selected_font
);
375 texty
= selected_texty
;
379 dc
.SetFont(m_normal_font
);
380 texty
= normal_texty
;
384 // create points that will make the tab outline
386 int clip_width
= tab_width
;
387 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
388 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
391 wxPoint clip_points[6];
392 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
393 clip_points[1] = wxPoint(tab_x, tab_y+2);
394 clip_points[2] = wxPoint(tab_x+2, tab_y);
395 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
396 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
397 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
399 // FIXME: these ports don't provide wxRegion ctor from array of points
400 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
401 // set the clipping region for the tab --
402 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
403 dc.SetClippingRegion(clipping_region);
404 #endif // !wxDFB && !wxCocoa
406 // since the above code above doesn't play well with WXDFB or WXCOCOA,
407 // we'll just use a rectangle for the clipping region for now --
408 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
411 wxPoint border_points
[6];
412 if (m_flags
&wxAUI_NB_BOTTOM
)
414 border_points
[0] = wxPoint(tab_x
, tab_y
);
415 border_points
[1] = wxPoint(tab_x
, tab_y
+tab_height
-6);
416 border_points
[2] = wxPoint(tab_x
+2, tab_y
+tab_height
-4);
417 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
+tab_height
-4);
418 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-6);
419 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
);
421 else //if (m_flags & wxAUI_NB_TOP) {}
423 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
424 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
425 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
426 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
427 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
428 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
430 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
431 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
433 int drawn_tab_yoff
= border_points
[1].y
;
434 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
441 // draw base background color
442 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
443 dc
.SetPen(m_base_colour_pen
);
444 dc
.SetBrush(m_base_colour_brush
);
445 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
447 // this white helps fill out the gradient at the top of the tab
448 dc
.SetPen(*wxWHITE_PEN
);
449 dc
.SetBrush(*wxWHITE_BRUSH
);
450 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
452 // these two points help the rounded corners appear more antialiased
453 dc
.SetPen(m_base_colour_pen
);
454 dc
.DrawPoint(r
.x
+2, r
.y
+1);
455 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
457 // set rectangle down a bit for gradient drawing
458 r
.SetHeight(r
.GetHeight()/2);
464 // draw gradient background
465 wxColor top_color
= *wxWHITE
;
466 wxColor bottom_color
= m_base_colour
;
467 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
473 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
475 // start the gradent up a bit and leave the inside border inset
476 // by a pixel for a 3D look. Only the top half of the inactive
477 // tab will have a slight gradient
484 // -- draw top gradient fill for glossy look
485 wxColor top_color
= m_base_colour
;
486 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
487 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
492 // -- draw bottom fill for glossy look
493 top_color
= m_base_colour
;
494 bottom_color
= m_base_colour
;
495 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
499 dc
.SetPen(m_border_pen
);
500 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
501 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
503 // there are two horizontal grey lines at the bottom of the tab control,
504 // this gets rid of the top one of those lines in the tab control
507 if (m_flags
&wxAUI_NB_BOTTOM
)
508 dc
.SetPen(wxPen(wxColour(wxAuiStepColour(m_base_colour
, 170))));
509 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
510 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
511 else //for wxAUI_NB_TOP
512 dc
.SetPen(m_base_colour_pen
);
513 dc
.DrawLine(border_points
[0].x
+1,
520 int text_offset
= tab_x
+ 8;
521 int close_button_width
= 0;
522 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
524 close_button_width
= m_active_close_bmp
.GetWidth();
527 int bitmap_offset
= 0;
528 if (page
.bitmap
.IsOk())
530 bitmap_offset
= tab_x
+ 8;
533 dc
.DrawBitmap(page
.bitmap
,
535 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
538 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
539 text_offset
+= 3; // bitmap padding
544 text_offset
= tab_x
+ 8;
548 wxString draw_text
= wxAuiChopText(dc
,
550 tab_width
- (text_offset
-tab_x
) - close_button_width
);
553 dc
.DrawText(draw_text
,
555 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
557 // draw focus rectangle
558 if (page
.active
&& (wnd
->FindFocus() == wnd
))
560 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
561 selected_textx
, selected_texty
);
564 wxRect focusRectBitmap
;
566 if (page
.bitmap
.IsOk())
567 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
568 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
570 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
571 focusRect
= focusRectBitmap
;
572 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
573 focusRect
= focusRectText
;
574 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
575 focusRect
= focusRectText
.Union(focusRectBitmap
);
577 focusRect
.Inflate(2, 2);
579 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
582 // draw close button if necessary
583 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
585 wxBitmap bmp
= m_disabled_close_bmp
;
587 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
588 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
590 bmp
= m_active_close_bmp
;
593 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
594 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
597 IndentPressedBitmap(&rect
, close_button_state
);
598 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
600 *out_button_rect
= rect
;
603 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
605 dc
.DestroyClippingRegion();
608 int wxAuiDefaultTabArt::GetIndentSize()
613 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
614 wxWindow
* WXUNUSED(wnd
),
615 const wxString
& caption
,
616 const wxBitmap
& bitmap
,
617 bool WXUNUSED(active
),
618 int close_button_state
,
621 wxCoord measured_textx
, measured_texty
, tmp
;
623 dc
.SetFont(m_measuring_font
);
624 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
626 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
628 // add padding around the text
629 wxCoord tab_width
= measured_textx
;
630 wxCoord tab_height
= measured_texty
;
632 // if the close button is showing, add space for it
633 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
634 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
636 // if there's a bitmap, add space for it
639 tab_width
+= bitmap
.GetWidth();
640 tab_width
+= 3; // right side bitmap padding
641 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
648 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
650 tab_width
= m_fixed_tab_width
;
653 *x_extent
= tab_width
;
655 return wxSize(tab_width
, tab_height
);
659 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
660 wxWindow
* WXUNUSED(wnd
),
661 const wxRect
& in_rect
,
672 case wxAUI_BUTTON_CLOSE
:
673 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
674 bmp
= m_disabled_close_bmp
;
676 bmp
= m_active_close_bmp
;
678 case wxAUI_BUTTON_LEFT
:
679 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
680 bmp
= m_disabled_left_bmp
;
682 bmp
= m_active_left_bmp
;
684 case wxAUI_BUTTON_RIGHT
:
685 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
686 bmp
= m_disabled_right_bmp
;
688 bmp
= m_active_right_bmp
;
690 case wxAUI_BUTTON_WINDOWLIST
:
691 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
692 bmp
= m_disabled_windowlist_bmp
;
694 bmp
= m_active_windowlist_bmp
;
704 if (orientation
== wxLEFT
)
706 rect
.SetX(in_rect
.x
);
707 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
708 rect
.SetWidth(bmp
.GetWidth());
709 rect
.SetHeight(bmp
.GetHeight());
713 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
714 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
715 bmp
.GetWidth(), bmp
.GetHeight());
718 IndentPressedBitmap(&rect
, button_state
);
719 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
724 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
725 const wxAuiNotebookPageArray
& pages
,
730 size_t i
, count
= pages
.GetCount();
731 for (i
= 0; i
< count
; ++i
)
733 const wxAuiNotebookPage
& page
= pages
.Item(i
);
734 wxString caption
= page
.caption
;
736 // if there is no caption, make it a space. This will prevent
737 // an assert in the menu code.
738 if (caption
.IsEmpty())
741 wxMenuItem
* item
= new wxMenuItem(NULL
, 1000+i
, caption
);
742 if (page
.bitmap
.IsOk())
743 item
->SetBitmap(page
.bitmap
);
744 menuPopup
.Append(item
);
747 // find out where to put the popup menu of window items
748 wxPoint pt
= ::wxGetMousePosition();
749 pt
= wnd
->ScreenToClient(pt
);
751 // find out the screen coordinate at the bottom of the tab ctrl
752 wxRect cli_rect
= wnd
->GetClientRect();
753 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
755 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
756 wnd
->PushEventHandler(cc
);
757 wnd
->PopupMenu(&menuPopup
, pt
);
758 int command
= cc
->GetCommandId();
759 wnd
->PopEventHandler(true);
767 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
768 const wxAuiNotebookPageArray
& pages
,
769 const wxSize
& required_bmp_size
)
772 dc
.SetFont(m_measuring_font
);
774 // sometimes a standard bitmap size needs to be enforced, especially
775 // if some tabs have bitmaps and others don't. This is important because
776 // it prevents the tab control from resizing when tabs are added.
777 wxBitmap measure_bmp
;
778 if (required_bmp_size
.IsFullySpecified())
780 measure_bmp
.Create(required_bmp_size
.x
,
781 required_bmp_size
.y
);
786 size_t i
, page_count
= pages
.GetCount();
787 for (i
= 0; i
< page_count
; ++i
)
789 wxAuiNotebookPage
& page
= pages
.Item(i
);
792 if (measure_bmp
.IsOk())
797 // we don't use the caption text because we don't
798 // want tab heights to be different in the case
799 // of a very short piece of text on one tab and a very
800 // tall piece of text on another tab
802 wxSize s
= GetTabSize(dc
,
807 wxAUI_BUTTON_STATE_HIDDEN
,
810 max_y
= wxMax(max_y
, s
.y
);
816 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
818 m_normal_font
= font
;
821 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
823 m_selected_font
= font
;
826 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
828 m_measuring_font
= font
;
832 // -- wxAuiSimpleTabArt class implementation --
834 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
836 m_normal_font
= *wxNORMAL_FONT
;
837 m_selected_font
= *wxNORMAL_FONT
;
838 m_selected_font
.SetWeight(wxBOLD
);
839 m_measuring_font
= m_selected_font
;
842 m_fixed_tab_width
= 100;
844 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
846 wxColour background_colour
= base_colour
;
847 wxColour normaltab_colour
= base_colour
;
848 wxColour selectedtab_colour
= *wxWHITE
;
850 m_bkbrush
= wxBrush(background_colour
);
851 m_normal_bkbrush
= wxBrush(normaltab_colour
);
852 m_normal_bkpen
= wxPen(normaltab_colour
);
853 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
854 m_selected_bkpen
= wxPen(selectedtab_colour
);
856 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
857 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
859 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
860 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
862 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
863 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
865 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
866 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
870 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
874 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
876 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
880 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
885 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
888 m_fixed_tab_width
= 100;
890 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
892 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
893 tot_width
-= m_active_close_bmp
.GetWidth();
894 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
895 tot_width
-= m_active_windowlist_bmp
.GetWidth();
899 m_fixed_tab_width
= tot_width
/(int)tab_count
;
903 if (m_fixed_tab_width
< 100)
904 m_fixed_tab_width
= 100;
906 if (m_fixed_tab_width
> tot_width
/2)
907 m_fixed_tab_width
= tot_width
/2;
909 if (m_fixed_tab_width
> 220)
910 m_fixed_tab_width
= 220;
913 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
914 wxWindow
* WXUNUSED(wnd
),
918 dc
.SetBrush(m_bkbrush
);
919 dc
.SetPen(*wxTRANSPARENT_PEN
);
920 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
923 dc
.SetPen(*wxGREY_PEN
);
924 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
928 // DrawTab() draws an individual tab.
931 // in_rect - rectangle the tab should be confined to
932 // caption - tab's caption
933 // active - whether or not the tab is active
934 // out_rect - actual output rectangle
935 // x_extent - the advance x; where the next tab should start
937 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
939 const wxAuiNotebookPage
& page
,
940 const wxRect
& in_rect
,
941 int close_button_state
,
942 wxRect
* out_tab_rect
,
943 wxRect
* out_button_rect
,
946 wxCoord normal_textx
, normal_texty
;
947 wxCoord selected_textx
, selected_texty
;
948 wxCoord textx
, texty
;
950 // if the caption is empty, measure some temporary text
951 wxString caption
= page
.caption
;
955 dc
.SetFont(m_selected_font
);
956 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
958 dc
.SetFont(m_normal_font
);
959 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
961 // figure out the size of the tab
962 wxSize tab_size
= GetTabSize(dc
,
970 wxCoord tab_height
= tab_size
.y
;
971 wxCoord tab_width
= tab_size
.x
;
972 wxCoord tab_x
= in_rect
.x
;
973 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
975 caption
= page
.caption
;
977 // select pen, brush and font for the tab to be drawn
981 dc
.SetPen(m_selected_bkpen
);
982 dc
.SetBrush(m_selected_bkbrush
);
983 dc
.SetFont(m_selected_font
);
984 textx
= selected_textx
;
985 texty
= selected_texty
;
989 dc
.SetPen(m_normal_bkpen
);
990 dc
.SetBrush(m_normal_bkbrush
);
991 dc
.SetFont(m_normal_font
);
992 textx
= normal_textx
;
993 texty
= normal_texty
;
1000 points
[0].x
= tab_x
;
1001 points
[0].y
= tab_y
+ tab_height
- 1;
1002 points
[1].x
= tab_x
+ tab_height
- 3;
1003 points
[1].y
= tab_y
+ 2;
1004 points
[2].x
= tab_x
+ tab_height
+ 3;
1005 points
[2].y
= tab_y
;
1006 points
[3].x
= tab_x
+ tab_width
- 2;
1007 points
[3].y
= tab_y
;
1008 points
[4].x
= tab_x
+ tab_width
;
1009 points
[4].y
= tab_y
+ 2;
1010 points
[5].x
= tab_x
+ tab_width
;
1011 points
[5].y
= tab_y
+ tab_height
- 1;
1012 points
[6] = points
[0];
1014 dc
.SetClippingRegion(in_rect
);
1016 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
1018 dc
.SetPen(*wxGREY_PEN
);
1020 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1021 dc
.DrawLines(WXSIZEOF(points
), points
);
1026 int close_button_width
= 0;
1027 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1029 close_button_width
= m_active_close_bmp
.GetWidth();
1030 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1034 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1037 // set minimum text offset
1038 if (text_offset
< tab_x
+ tab_height
)
1039 text_offset
= tab_x
+ tab_height
;
1041 // chop text if necessary
1042 wxString draw_text
= wxAuiChopText(dc
,
1044 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1047 dc
.DrawText(draw_text
,
1049 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1052 // draw focus rectangle
1053 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1055 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1056 selected_textx
, selected_texty
);
1058 focusRect
.Inflate(2, 2);
1060 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1063 // draw close button if necessary
1064 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1068 bmp
= m_active_close_bmp
;
1070 bmp
= m_disabled_close_bmp
;
1072 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1073 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1076 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1078 *out_button_rect
= rect
;
1082 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1084 dc
.DestroyClippingRegion();
1087 int wxAuiSimpleTabArt::GetIndentSize()
1092 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1093 wxWindow
* WXUNUSED(wnd
),
1094 const wxString
& caption
,
1095 const wxBitmap
& WXUNUSED(bitmap
),
1096 bool WXUNUSED(active
),
1097 int close_button_state
,
1100 wxCoord measured_textx
, measured_texty
;
1102 dc
.SetFont(m_measuring_font
);
1103 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1105 wxCoord tab_height
= measured_texty
+ 4;
1106 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1108 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1109 tab_width
+= m_active_close_bmp
.GetWidth();
1111 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1113 tab_width
= m_fixed_tab_width
;
1116 *x_extent
= tab_width
- (tab_height
/2) - 1;
1118 return wxSize(tab_width
, tab_height
);
1122 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1123 wxWindow
* WXUNUSED(wnd
),
1124 const wxRect
& in_rect
,
1135 case wxAUI_BUTTON_CLOSE
:
1136 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1137 bmp
= m_disabled_close_bmp
;
1139 bmp
= m_active_close_bmp
;
1141 case wxAUI_BUTTON_LEFT
:
1142 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1143 bmp
= m_disabled_left_bmp
;
1145 bmp
= m_active_left_bmp
;
1147 case wxAUI_BUTTON_RIGHT
:
1148 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1149 bmp
= m_disabled_right_bmp
;
1151 bmp
= m_active_right_bmp
;
1153 case wxAUI_BUTTON_WINDOWLIST
:
1154 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1155 bmp
= m_disabled_windowlist_bmp
;
1157 bmp
= m_active_windowlist_bmp
;
1166 if (orientation
== wxLEFT
)
1168 rect
.SetX(in_rect
.x
);
1169 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1170 rect
.SetWidth(bmp
.GetWidth());
1171 rect
.SetHeight(bmp
.GetHeight());
1175 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1176 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1177 bmp
.GetWidth(), bmp
.GetHeight());
1181 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1186 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1187 const wxAuiNotebookPageArray
& pages
,
1192 size_t i
, count
= pages
.GetCount();
1193 for (i
= 0; i
< count
; ++i
)
1195 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1196 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1199 if (active_idx
!= -1)
1201 menuPopup
.Check(1000+active_idx
, true);
1204 // find out where to put the popup menu of window
1205 // items. Subtract 100 for now to center the menu
1206 // a bit, until a better mechanism can be implemented
1207 wxPoint pt
= ::wxGetMousePosition();
1208 pt
= wnd
->ScreenToClient(pt
);
1214 // find out the screen coordinate at the bottom of the tab ctrl
1215 wxRect cli_rect
= wnd
->GetClientRect();
1216 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1218 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1219 wnd
->PushEventHandler(cc
);
1220 wnd
->PopupMenu(&menuPopup
, pt
);
1221 int command
= cc
->GetCommandId();
1222 wnd
->PopEventHandler(true);
1224 if (command
>= 1000)
1225 return command
-1000;
1230 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1231 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1232 const wxSize
& WXUNUSED(required_bmp_size
))
1235 dc
.SetFont(m_measuring_font
);
1237 wxSize s
= GetTabSize(dc
,
1242 wxAUI_BUTTON_STATE_HIDDEN
,
1247 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1249 m_normal_font
= font
;
1252 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1254 m_selected_font
= font
;
1257 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1259 m_measuring_font
= font
;
1265 // -- wxAuiTabContainer class implementation --
1268 // wxAuiTabContainer is a class which contains information about each
1269 // tab. It also can render an entire tab control to a specified DC.
1270 // It's not a window class itself, because this code will be used by
1271 // the wxFrameMananger, where it is disadvantageous to have separate
1272 // windows for each tab control in the case of "docked tabs"
1274 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1275 // which can be used as a tab control in the normal sense.
1278 wxAuiTabContainer::wxAuiTabContainer()
1282 m_art
= new wxAuiDefaultTabArt
;
1284 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1285 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1286 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1287 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1290 wxAuiTabContainer::~wxAuiTabContainer()
1295 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1302 m_art
->SetFlags(m_flags
);
1306 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1311 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1315 // check for new close button settings
1316 RemoveButton(wxAUI_BUTTON_LEFT
);
1317 RemoveButton(wxAUI_BUTTON_RIGHT
);
1318 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1319 RemoveButton(wxAUI_BUTTON_CLOSE
);
1322 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1324 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1325 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1328 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1330 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1333 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1335 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1340 m_art
->SetFlags(m_flags
);
1344 unsigned int wxAuiTabContainer::GetFlags() const
1350 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1352 m_art
->SetNormalFont(font
);
1355 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1357 m_art
->SetSelectedFont(font
);
1360 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1362 m_art
->SetMeasuringFont(font
);
1365 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1371 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1375 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1376 const wxAuiNotebookPage
& info
)
1378 wxAuiNotebookPage page_info
;
1380 page_info
.window
= page
;
1382 m_pages
.Add(page_info
);
1384 // let the art provider know how many pages we have
1387 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1393 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1394 const wxAuiNotebookPage
& info
,
1397 wxAuiNotebookPage page_info
;
1399 page_info
.window
= page
;
1401 if (idx
>= m_pages
.GetCount())
1402 m_pages
.Add(page_info
);
1404 m_pages
.Insert(page_info
, idx
);
1406 // let the art provider know how many pages we have
1409 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1415 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1418 int idx
= GetIdxFromWindow(page
);
1422 // get page entry, make a copy of it
1423 wxAuiNotebookPage p
= GetPage(idx
);
1425 // remove old page entry
1428 // insert page where it should be
1429 InsertPage(page
, p
, new_idx
);
1434 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1436 size_t i
, page_count
= m_pages
.GetCount();
1437 for (i
= 0; i
< page_count
; ++i
)
1439 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1440 if (page
.window
== wnd
)
1442 m_pages
.RemoveAt(i
);
1444 // let the art provider know how many pages we have
1447 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1457 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1461 size_t i
, page_count
= m_pages
.GetCount();
1462 for (i
= 0; i
< page_count
; ++i
)
1464 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1465 if (page
.window
== wnd
)
1472 page
.active
= false;
1479 void wxAuiTabContainer::SetNoneActive()
1481 size_t i
, page_count
= m_pages
.GetCount();
1482 for (i
= 0; i
< page_count
; ++i
)
1484 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1485 page
.active
= false;
1489 bool wxAuiTabContainer::SetActivePage(size_t page
)
1491 if (page
>= m_pages
.GetCount())
1494 return SetActivePage(m_pages
.Item(page
).window
);
1497 int wxAuiTabContainer::GetActivePage() const
1499 size_t i
, page_count
= m_pages
.GetCount();
1500 for (i
= 0; i
< page_count
; ++i
)
1502 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1510 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1512 if (idx
>= m_pages
.GetCount())
1515 return m_pages
[idx
].window
;
1518 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1520 const size_t page_count
= m_pages
.GetCount();
1521 for ( size_t i
= 0; i
< page_count
; ++i
)
1523 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1524 if (page
.window
== wnd
)
1530 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1532 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1534 return m_pages
[idx
];
1537 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1539 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1541 return m_pages
[idx
];
1544 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1549 size_t wxAuiTabContainer::GetPageCount() const
1551 return m_pages
.GetCount();
1554 void wxAuiTabContainer::AddButton(int id
,
1556 const wxBitmap
& normal_bitmap
,
1557 const wxBitmap
& disabled_bitmap
)
1559 wxAuiTabContainerButton button
;
1561 button
.bitmap
= normal_bitmap
;
1562 button
.dis_bitmap
= disabled_bitmap
;
1563 button
.location
= location
;
1564 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1566 m_buttons
.Add(button
);
1569 void wxAuiTabContainer::RemoveButton(int id
)
1571 size_t i
, button_count
= m_buttons
.GetCount();
1573 for (i
= 0; i
< button_count
; ++i
)
1575 if (m_buttons
.Item(i
).id
== id
)
1577 m_buttons
.RemoveAt(i
);
1585 size_t wxAuiTabContainer::GetTabOffset() const
1587 return m_tab_offset
;
1590 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1592 m_tab_offset
= offset
;
1598 // Render() renders the tab catalog to the specified DC
1599 // It is a virtual function and can be overridden to
1600 // provide custom drawing capabilities
1601 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1603 if (!raw_dc
|| !raw_dc
->IsOk())
1608 // use the same layout direction as the window DC uses to ensure that the
1609 // text is rendered correctly
1610 dc
.SetLayoutDirection(raw_dc
->GetLayoutDirection());
1614 size_t page_count
= m_pages
.GetCount();
1615 size_t button_count
= m_buttons
.GetCount();
1617 // create off-screen bitmap
1618 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1619 dc
.SelectObject(bmp
);
1624 // find out if size of tabs is larger than can be
1625 // afforded on screen
1626 int total_width
= 0;
1627 int visible_width
= 0;
1628 for (i
= 0; i
< page_count
; ++i
)
1630 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1632 // determine if a close button is on this tab
1633 bool close_button
= false;
1634 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1635 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1637 close_button
= true;
1642 wxSize size
= m_art
->GetTabSize(dc
,
1648 wxAUI_BUTTON_STATE_NORMAL
:
1649 wxAUI_BUTTON_STATE_HIDDEN
,
1652 if (i
+1 < page_count
)
1653 total_width
+= x_extent
;
1655 total_width
+= size
.x
;
1657 if (i
>= m_tab_offset
)
1659 if (i
+1 < page_count
)
1660 visible_width
+= x_extent
;
1662 visible_width
+= size
.x
;
1666 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1668 // show left/right buttons
1669 for (i
= 0; i
< button_count
; ++i
)
1671 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1672 if (button
.id
== wxAUI_BUTTON_LEFT
||
1673 button
.id
== wxAUI_BUTTON_RIGHT
)
1675 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1681 // hide left/right buttons
1682 for (i
= 0; i
< button_count
; ++i
)
1684 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1685 if (button
.id
== wxAUI_BUTTON_LEFT
||
1686 button
.id
== wxAUI_BUTTON_RIGHT
)
1688 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1693 // determine whether left button should be enabled
1694 for (i
= 0; i
< button_count
; ++i
)
1696 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1697 if (button
.id
== wxAUI_BUTTON_LEFT
)
1699 if (m_tab_offset
== 0)
1700 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1702 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1704 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1706 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1707 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1709 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1716 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1719 int left_buttons_width
= 0;
1720 int right_buttons_width
= 0;
1724 // draw the buttons on the right side
1725 offset
= m_rect
.x
+ m_rect
.width
;
1726 for (i
= 0; i
< button_count
; ++i
)
1728 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1730 if (button
.location
!= wxRIGHT
)
1732 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1735 wxRect button_rect
= m_rect
;
1736 button_rect
.SetY(1);
1737 button_rect
.SetWidth(offset
);
1739 m_art
->DrawButton(dc
,
1747 offset
-= button
.rect
.GetWidth();
1748 right_buttons_width
+= button
.rect
.GetWidth();
1755 // draw the buttons on the left side
1757 for (i
= 0; i
< button_count
; ++i
)
1759 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1761 if (button
.location
!= wxLEFT
)
1763 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1766 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1768 m_art
->DrawButton(dc
,
1776 offset
+= button
.rect
.GetWidth();
1777 left_buttons_width
+= button
.rect
.GetWidth();
1780 offset
= left_buttons_width
;
1783 offset
+= m_art
->GetIndentSize();
1786 // prepare the tab-close-button array
1787 // make sure tab button entries which aren't used are marked as hidden
1788 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1789 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1791 // make sure there are enough tab button entries to accommodate all tabs
1792 while (m_tab_close_buttons
.GetCount() < page_count
)
1794 wxAuiTabContainerButton tempbtn
;
1795 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1796 tempbtn
.location
= wxCENTER
;
1797 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1798 m_tab_close_buttons
.Add(tempbtn
);
1802 // buttons before the tab offset must be set to hidden
1803 for (i
= 0; i
< m_tab_offset
; ++i
)
1805 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1811 size_t active
= 999;
1812 int active_offset
= 0;
1816 wxRect rect
= m_rect
;
1818 rect
.height
= m_rect
.height
;
1820 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1822 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1823 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1825 // determine if a close button is on this tab
1826 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1827 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1829 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1831 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1832 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1833 tab_button
.location
= wxCENTER
;
1838 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1842 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1844 if (rect
.width
<= 0)
1851 tab_button
.cur_state
,
1859 active_offset
= offset
;
1867 // make sure to deactivate buttons which are off the screen to the right
1868 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1870 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1874 // draw the active tab again so it stands in the foreground
1875 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1877 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1879 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1881 rect
.x
= active_offset
;
1886 tab_button
.cur_state
,
1893 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1894 m_rect
.GetWidth(), m_rect
.GetHeight(),
1898 // Is the tab visible?
1899 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1901 if (!dc
|| !dc
->IsOk())
1905 size_t page_count
= m_pages
.GetCount();
1906 size_t button_count
= m_buttons
.GetCount();
1908 // Hasn't been rendered yet; assume it's visible
1909 if (m_tab_close_buttons
.GetCount() < page_count
)
1912 // First check if both buttons are disabled - if so, there's no need to
1913 // check further for visibility.
1914 int arrowButtonVisibleCount
= 0;
1915 for (i
= 0; i
< button_count
; ++i
)
1917 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1918 if (button
.id
== wxAUI_BUTTON_LEFT
||
1919 button
.id
== wxAUI_BUTTON_RIGHT
)
1921 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1922 arrowButtonVisibleCount
++;
1926 // Tab must be visible
1927 if (arrowButtonVisibleCount
== 0)
1930 // If tab is less than the given offset, it must be invisible by definition
1931 if (tabPage
< tabOffset
)
1935 int left_buttons_width
= 0;
1936 int right_buttons_width
= 0;
1940 // calculate size of the buttons on the right side
1941 offset
= m_rect
.x
+ m_rect
.width
;
1942 for (i
= 0; i
< button_count
; ++i
)
1944 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1946 if (button
.location
!= wxRIGHT
)
1948 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1951 offset
-= button
.rect
.GetWidth();
1952 right_buttons_width
+= button
.rect
.GetWidth();
1957 // calculate size of the buttons on the left side
1958 for (i
= 0; i
< button_count
; ++i
)
1960 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1962 if (button
.location
!= wxLEFT
)
1964 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1967 offset
+= button
.rect
.GetWidth();
1968 left_buttons_width
+= button
.rect
.GetWidth();
1971 offset
= left_buttons_width
;
1974 offset
+= m_art
->GetIndentSize();
1978 wxRect rect
= m_rect
;
1980 rect
.height
= m_rect
.height
;
1982 // See if the given page is visible at the given tab offset (effectively scroll position)
1983 for (i
= tabOffset
; i
< page_count
; ++i
)
1985 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1986 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1989 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1991 if (rect
.width
<= 0)
1992 return false; // haven't found the tab, and we've run out of space, so return false
1995 wxSize size
= m_art
->GetTabSize(*dc
,
2000 tab_button
.cur_state
,
2005 if (i
== (size_t) tabPage
)
2007 // If not all of the tab is visible, and supposing there's space to display it all,
2008 // we could do better so we return false.
2009 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
2016 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2017 // further looping in calling code.
2021 // Make the tab visible if it wasn't already
2022 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
2025 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2028 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2030 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2040 // TabHitTest() tests if a tab was hit, passing the window pointer
2041 // back if that condition was fulfilled. The function returns
2042 // true if a tab was hit, otherwise false
2043 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2045 if (!m_rect
.Contains(x
,y
))
2048 wxAuiTabContainerButton
* btn
= NULL
;
2049 if (ButtonHitTest(x
, y
, &btn
) && !(btn
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2051 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2055 size_t i
, page_count
= m_pages
.GetCount();
2057 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2059 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2060 if (page
.rect
.Contains(x
,y
))
2071 // ButtonHitTest() tests if a button was hit. The function returns
2072 // true if a button was hit, otherwise false
2073 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2074 wxAuiTabContainerButton
** hit
) const
2076 if (!m_rect
.Contains(x
,y
))
2079 size_t i
, button_count
;
2082 button_count
= m_buttons
.GetCount();
2083 for (i
= 0; i
< button_count
; ++i
)
2085 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2086 if (button
.rect
.Contains(x
,y
) &&
2087 !(button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
))
2095 button_count
= m_tab_close_buttons
.GetCount();
2096 for (i
= 0; i
< button_count
; ++i
)
2098 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2099 if (button
.rect
.Contains(x
,y
) &&
2100 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2101 wxAUI_BUTTON_STATE_DISABLED
)))
2114 // the utility function ShowWnd() is the same as show,
2115 // except it handles wxAuiMDIChildFrame windows as well,
2116 // as the Show() method on this class is "unplugged"
2117 static void ShowWnd(wxWindow
* wnd
, bool show
)
2120 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2122 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2133 // DoShowHide() this function shows the active window, then
2134 // hides all of the other windows (in that order)
2135 void wxAuiTabContainer::DoShowHide()
2137 wxAuiNotebookPageArray
& pages
= GetPages();
2138 size_t i
, page_count
= pages
.GetCount();
2140 // show new active page first
2141 for (i
= 0; i
< page_count
; ++i
)
2143 wxAuiNotebookPage
& page
= pages
.Item(i
);
2146 ShowWnd(page
.window
, true);
2151 // hide all other pages
2152 for (i
= 0; i
< page_count
; ++i
)
2154 wxAuiNotebookPage
& page
= pages
.Item(i
);
2156 ShowWnd(page
.window
, false);
2165 // -- wxAuiTabCtrl class implementation --
2169 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2170 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2171 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2172 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2173 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2174 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick
)
2175 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2176 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2177 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2178 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2179 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2180 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2181 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2182 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2183 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2184 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2185 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2186 EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost
)
2190 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2194 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2196 SetName(wxT("wxAuiTabCtrl"));
2197 m_click_pt
= wxDefaultPosition
;
2198 m_is_dragging
= false;
2199 m_hover_button
= NULL
;
2200 m_pressed_button
= NULL
;
2203 wxAuiTabCtrl::~wxAuiTabCtrl()
2207 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2211 dc
.SetFont(GetFont());
2213 if (GetPageCount() > 0)
2217 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2221 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2223 wxSize s
= evt
.GetSize();
2224 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2228 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2231 m_click_pt
= wxDefaultPosition
;
2232 m_is_dragging
= false;
2234 m_pressed_button
= NULL
;
2238 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2240 int new_selection
= GetIdxFromWindow(wnd
);
2242 // wxAuiNotebooks always want to receive this event
2243 // even if the tab is already active, because they may
2244 // have multiple tab controls
2245 if (new_selection
!= GetActivePage() ||
2246 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2248 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2249 e
.SetSelection(new_selection
);
2250 e
.SetOldSelection(GetActivePage());
2251 e
.SetEventObject(this);
2252 GetEventHandler()->ProcessEvent(e
);
2255 m_click_pt
.x
= evt
.m_x
;
2256 m_click_pt
.y
= evt
.m_y
;
2262 m_pressed_button
= m_hover_button
;
2263 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2269 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
2273 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2275 if (GetCapture() == this)
2280 m_is_dragging
= false;
2282 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2283 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2284 evt
.SetOldSelection(evt
.GetSelection());
2285 evt
.SetEventObject(this);
2286 GetEventHandler()->ProcessEvent(evt
);
2291 if (m_pressed_button
)
2293 // make sure we're still clicking the button
2294 wxAuiTabContainerButton
* button
= NULL
;
2295 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
) ||
2296 button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
)
2299 if (button
!= m_pressed_button
)
2301 m_pressed_button
= NULL
;
2308 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2310 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2311 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2312 evt
.SetInt(m_pressed_button
->id
);
2313 evt
.SetEventObject(this);
2314 GetEventHandler()->ProcessEvent(evt
);
2317 m_pressed_button
= NULL
;
2320 m_click_pt
= wxDefaultPosition
;
2321 m_is_dragging
= false;
2325 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2327 wxWindow
* wnd
= NULL
;
2328 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2331 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2332 e
.SetEventObject(this);
2333 e
.SetSelection(GetIdxFromWindow(wnd
));
2334 GetEventHandler()->ProcessEvent(e
);
2337 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2339 wxWindow
* wnd
= NULL
;
2340 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2343 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2344 e
.SetEventObject(this);
2345 e
.SetSelection(GetIdxFromWindow(wnd
));
2346 GetEventHandler()->ProcessEvent(e
);
2349 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2351 wxWindow
* wnd
= NULL
;
2352 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2355 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2356 e
.SetEventObject(this);
2357 e
.SetSelection(GetIdxFromWindow(wnd
));
2358 GetEventHandler()->ProcessEvent(e
);
2361 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2363 wxWindow
* wnd
= NULL
;
2364 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2367 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2368 e
.SetEventObject(this);
2369 e
.SetSelection(GetIdxFromWindow(wnd
));
2370 GetEventHandler()->ProcessEvent(e
);
2373 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent
& evt
)
2376 wxAuiTabContainerButton
* button
;
2377 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
) && !ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2379 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
2380 e
.SetEventObject(this);
2381 GetEventHandler()->ProcessEvent(e
);
2385 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2387 wxPoint pos
= evt
.GetPosition();
2389 // check if the mouse is hovering above a button
2390 wxAuiTabContainerButton
* button
;
2391 if (ButtonHitTest(pos
.x
, pos
.y
, &button
) && !(button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2393 if (m_hover_button
&& button
!= m_hover_button
)
2395 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2396 m_hover_button
= NULL
;
2401 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2403 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2406 m_hover_button
= button
;
2414 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2415 m_hover_button
= NULL
;
2422 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2427 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2428 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2429 evt
.SetOldSelection(evt
.GetSelection());
2430 evt
.SetEventObject(this);
2431 GetEventHandler()->ProcessEvent(evt
);
2436 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2437 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2439 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2440 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2442 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2443 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2444 evt
.SetOldSelection(evt
.GetSelection());
2445 evt
.SetEventObject(this);
2446 GetEventHandler()->ProcessEvent(evt
);
2448 m_is_dragging
= true;
2452 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2456 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2457 m_hover_button
= NULL
;
2463 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2465 int button
= event
.GetInt();
2467 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2469 if (button
== wxAUI_BUTTON_LEFT
)
2471 if (GetTabOffset() > 0)
2473 SetTabOffset(GetTabOffset()-1);
2480 SetTabOffset(GetTabOffset()+1);
2485 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2487 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2491 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2492 e
.SetSelection(idx
);
2493 e
.SetOldSelection(GetActivePage());
2494 e
.SetEventObject(this);
2495 GetEventHandler()->ProcessEvent(e
);
2504 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2509 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2514 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2516 if (GetActivePage() == -1)
2522 // We can't leave tab processing to the system; on Windows, tabs and keys
2523 // get eaten by the system and not processed properly if we specify both
2524 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2525 // we don't key arrow key events.
2527 int key
= event
.GetKeyCode();
2529 if (key
== WXK_NUMPAD_PAGEUP
)
2531 if (key
== WXK_NUMPAD_PAGEDOWN
)
2533 if (key
== WXK_NUMPAD_HOME
)
2535 if (key
== WXK_NUMPAD_END
)
2537 if (key
== WXK_NUMPAD_LEFT
)
2539 if (key
== WXK_NUMPAD_RIGHT
)
2542 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2544 bool bCtrlDown
= event
.ControlDown();
2545 bool bShiftDown
= event
.ShiftDown();
2547 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2548 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2549 bool bFromTab
= (key
== WXK_TAB
);
2551 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2558 wxNavigationKeyEvent keyEvent
;
2559 keyEvent
.SetDirection(bForward
);
2560 keyEvent
.SetWindowChange(bWindowChange
);
2561 keyEvent
.SetFromTab(bFromTab
);
2562 keyEvent
.SetEventObject(nb
);
2564 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2566 // Not processed? Do an explicit tab into the page.
2567 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2574 if (m_pages
.GetCount() < 2)
2582 int forwardKey
, backwardKey
;
2583 if (GetLayoutDirection() == wxLayout_RightToLeft
)
2585 forwardKey
= WXK_LEFT
;
2586 backwardKey
= WXK_RIGHT
;
2590 forwardKey
= WXK_RIGHT
;
2591 backwardKey
= WXK_LEFT
;
2594 if (key
== forwardKey
)
2596 if (m_pages
.GetCount() > 1)
2598 if (GetActivePage() == -1)
2600 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2601 newPage
= GetActivePage() + 1;
2604 else if (key
== backwardKey
)
2606 if (m_pages
.GetCount() > 1)
2608 if (GetActivePage() == -1)
2609 newPage
= (int) (m_pages
.GetCount() - 1);
2610 else if (GetActivePage() > 0)
2611 newPage
= GetActivePage() - 1;
2614 else if (key
== WXK_HOME
)
2618 else if (key
== WXK_END
)
2620 newPage
= (int) (m_pages
.GetCount() - 1);
2627 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2628 e
.SetSelection(newPage
);
2629 e
.SetOldSelection(newPage
);
2630 e
.SetEventObject(this);
2631 this->GetEventHandler()->ProcessEvent(e
);
2637 // wxTabFrame is an interesting case. It's important that all child pages
2638 // of the multi-notebook control are all actually children of that control
2639 // (and not grandchildren). wxTabFrame facilitates this. There is one
2640 // instance of wxTabFrame for each tab control inside the multi-notebook.
2641 // It's important to know that wxTabFrame is not a real window, but it merely
2642 // used to capture the dimensions/positioning of the internal tab control and
2643 // it's managed page windows
2645 class wxTabFrame
: public wxWindow
2652 m_rect
= wxRect(0,0,200,200);
2653 m_tab_ctrl_height
= 20;
2661 void SetTabCtrlHeight(int h
)
2663 m_tab_ctrl_height
= h
;
2667 void DoSetSize(int x
, int y
,
2668 int width
, int height
,
2669 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2671 m_rect
= wxRect(x
, y
, width
, height
);
2675 void DoGetClientSize(int* x
, int* y
) const
2682 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2689 if (m_tabs
->IsFrozen() || m_tabs
->GetParent()->IsFrozen())
2692 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2693 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2695 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2696 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2697 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2699 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2701 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2702 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2703 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2705 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2706 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2711 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2712 size_t i
, page_count
= pages
.GetCount();
2714 for (i
= 0; i
< page_count
; ++i
)
2716 int height
= m_rect
.height
- m_tab_ctrl_height
;
2719 // avoid passing negative height to wxWindow::SetSize(), this
2720 // results in assert failures/GTK+ warnings
2724 wxAuiNotebookPage
& page
= pages
.Item(i
);
2725 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2727 page
.window
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, height
);
2729 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2731 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2732 m_rect
.width
, height
);
2734 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2735 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2738 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2740 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2741 wnd
->ApplyMDIChildFrameRect();
2748 void DoGetSize(int* x
, int* y
) const
2751 *x
= m_rect
.GetWidth();
2753 *y
= m_rect
.GetHeight();
2764 wxAuiTabCtrl
* m_tabs
;
2765 int m_tab_ctrl_height
;
2769 const int wxAuiBaseTabCtrlId
= 5380;
2772 // -- wxAuiNotebook class implementation --
2774 #define EVT_AUI_RANGE(id1, id2, event, func) \
2775 wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func))
2777 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2778 EVT_SIZE(wxAuiNotebook::OnSize
)
2779 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2780 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2781 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2782 wxAuiNotebook::OnTabClicked
)
2783 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2784 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2785 wxAuiNotebook::OnTabBeginDrag
)
2786 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2787 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2788 wxAuiNotebook::OnTabEndDrag
)
2789 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2790 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2791 wxAuiNotebook::OnTabDragMotion
)
2792 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2793 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2794 wxAuiNotebook::OnTabButton
)
2795 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2796 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2797 wxAuiNotebook::OnTabMiddleDown
)
2798 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2799 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2800 wxAuiNotebook::OnTabMiddleUp
)
2801 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2802 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2803 wxAuiNotebook::OnTabRightDown
)
2804 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2805 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2806 wxAuiNotebook::OnTabRightUp
)
2807 EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2808 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
,
2809 wxAuiNotebook::OnTabBgDClick
)
2810 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2812 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2813 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2815 // Avoid clash with container event handler functions
2816 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2820 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2822 wxAuiNotebook::wxAuiNotebook()
2825 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2827 m_tab_ctrl_height
= 20;
2828 m_requested_bmp_size
= wxDefaultSize
;
2829 m_requested_tabctrl_height
= -1;
2832 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2836 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2839 m_requested_bmp_size
= wxDefaultSize
;
2840 m_requested_tabctrl_height
= -1;
2841 InitNotebook(style
);
2844 bool wxAuiNotebook::Create(wxWindow
* parent
,
2850 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2853 InitNotebook(style
);
2858 // InitNotebook() contains common initialization
2859 // code called by all constructors
2860 void wxAuiNotebook::InitNotebook(long style
)
2862 WX_INIT_CONTROL_CONTAINER();
2863 // SetCanFocus(false);
2865 SetName(wxT("wxAuiNotebook"));
2867 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2869 m_flags
= (unsigned int)style
;
2870 m_tab_ctrl_height
= 20;
2872 m_normal_font
= *wxNORMAL_FONT
;
2873 m_selected_font
= *wxNORMAL_FONT
;
2874 m_selected_font
.SetWeight(wxBOLD
);
2876 SetArtProvider(new wxAuiDefaultTabArt
);
2878 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2879 m_dummy_wnd
->SetSize(200, 200);
2880 m_dummy_wnd
->Show(false);
2882 m_mgr
.SetManagedWindow(this);
2883 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2884 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2886 m_mgr
.AddPane(m_dummy_wnd
,
2887 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2892 wxAuiNotebook::~wxAuiNotebook()
2894 // Indicate we're deleting pages
2897 while ( GetPageCount() > 0 )
2903 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2905 m_tabs
.SetArtProvider(art
);
2907 // Update the height and do nothing else if it did something but otherwise
2908 // (i.e. if the new art provider uses the same height as the old one) we
2909 // need to manually set the art provider for all tabs ourselves.
2910 if ( !UpdateTabCtrlHeight() )
2912 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2913 const size_t pane_count
= all_panes
.GetCount();
2914 for (size_t i
= 0; i
< pane_count
; ++i
)
2916 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2917 if (pane
.name
== wxT("dummy"))
2919 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2920 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2921 tabctrl
->SetArtProvider(art
->Clone());
2926 // SetTabCtrlHeight() is the highest-level override of the
2927 // tab height. A call to this function effectively enforces a
2928 // specified tab ctrl height, overriding all other considerations,
2929 // such as text or bitmap height. It overrides any call to
2930 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2931 // any previous call and returns to the default behavior
2933 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2935 m_requested_tabctrl_height
= height
;
2937 // if window is already initialized, recalculate the tab height
2940 UpdateTabCtrlHeight();
2945 // SetUniformBitmapSize() ensures that all tabs will have
2946 // the same height, even if some tabs don't have bitmaps
2947 // Passing wxDefaultSize to this function will instruct
2948 // the control to use dynamic tab height-- so when a tab
2949 // with a large bitmap is added, the tab ctrl's height will
2950 // automatically increase to accommodate the bitmap
2952 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2954 m_requested_bmp_size
= size
;
2956 // if window is already initialized, recalculate the tab height
2959 UpdateTabCtrlHeight();
2963 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2964 // to be used internally
2965 bool wxAuiNotebook::UpdateTabCtrlHeight()
2967 // get the tab ctrl height we will use
2968 int height
= CalculateTabCtrlHeight();
2970 // if the tab control height needs to change, update
2971 // all of our tab controls with the new height
2972 if (m_tab_ctrl_height
== height
)
2975 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2977 m_tab_ctrl_height
= height
;
2979 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2980 size_t i
, pane_count
= all_panes
.GetCount();
2981 for (i
= 0; i
< pane_count
; ++i
)
2983 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2984 if (pane
.name
== wxT("dummy"))
2986 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2987 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2988 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2989 tabctrl
->SetArtProvider(art
->Clone());
2990 tab_frame
->DoSizing();
2996 void wxAuiNotebook::UpdateHintWindowSize()
2998 wxSize size
= CalculateNewSplitSize();
3000 // the placeholder hint window should be set to this size
3001 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
3005 info
.BestSize(size
);
3006 m_dummy_wnd
->SetSize(size
);
3011 // calculates the size of the new split
3012 wxSize
wxAuiNotebook::CalculateNewSplitSize()
3014 // count number of tab controls
3015 int tab_ctrl_count
= 0;
3016 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3017 size_t i
, pane_count
= all_panes
.GetCount();
3018 for (i
= 0; i
< pane_count
; ++i
)
3020 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3021 if (pane
.name
== wxT("dummy"))
3026 wxSize new_split_size
;
3028 // if there is only one tab control, the first split
3029 // should happen around the middle
3030 if (tab_ctrl_count
< 2)
3032 new_split_size
= GetClientSize();
3033 new_split_size
.x
/= 2;
3034 new_split_size
.y
/= 2;
3038 // this is in place of a more complicated calculation
3039 // that needs to be implemented
3040 new_split_size
= wxSize(180,180);
3043 return new_split_size
;
3046 int wxAuiNotebook::CalculateTabCtrlHeight()
3048 // if a fixed tab ctrl height is specified,
3049 // just return that instead of calculating a
3051 if (m_requested_tabctrl_height
!= -1)
3052 return m_requested_tabctrl_height
;
3054 // find out new best tab height
3055 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
3057 return art
->GetBestTabCtrlSize(this,
3059 m_requested_bmp_size
);
3063 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
3065 return m_tabs
.GetArtProvider();
3068 void wxAuiNotebook::SetWindowStyleFlag(long style
)
3070 wxControl::SetWindowStyleFlag(style
);
3072 m_flags
= (unsigned int)style
;
3074 // if the control is already initialized
3075 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
3077 // let all of the tab children know about the new style
3079 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3080 size_t i
, pane_count
= all_panes
.GetCount();
3081 for (i
= 0; i
< pane_count
; ++i
)
3083 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3084 if (pane
.name
== wxT("dummy"))
3086 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3087 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
3088 tabctrl
->SetFlags(m_flags
);
3089 tabframe
->DoSizing();
3097 bool wxAuiNotebook::AddPage(wxWindow
* page
,
3098 const wxString
& caption
,
3100 const wxBitmap
& bitmap
)
3102 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
3105 bool wxAuiNotebook::InsertPage(size_t page_idx
,
3107 const wxString
& caption
,
3109 const wxBitmap
& bitmap
)
3111 wxASSERT_MSG(page
, wxT("page pointer must be non-NULL"));
3115 page
->Reparent(this);
3117 wxAuiNotebookPage info
;
3119 info
.caption
= caption
;
3120 info
.bitmap
= bitmap
;
3121 info
.active
= false;
3123 // if there are currently no tabs, the first added
3124 // tab must be active
3125 if (m_tabs
.GetPageCount() == 0)
3128 m_tabs
.InsertPage(page
, info
, page_idx
);
3130 // if that was the first page added, even if
3131 // select is false, it must become the "current page"
3132 // (though no select events will be fired)
3133 if (!select
&& m_tabs
.GetPageCount() == 1)
3135 //m_curpage = GetPageIndex(page);
3137 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3138 if (page_idx
>= active_tabctrl
->GetPageCount())
3139 active_tabctrl
->AddPage(page
, info
);
3141 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3143 UpdateTabCtrlHeight();
3145 active_tabctrl
->DoShowHide();
3147 // adjust selected index
3148 if(m_curpage
>= (int) page_idx
)
3153 SetSelectionToWindow(page
);
3160 // DeletePage() removes a tab from the multi-notebook,
3161 // and destroys the window as well
3162 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3164 if (page_idx
>= m_tabs
.GetPageCount())
3167 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3169 // hide the window in advance, as this will
3171 ShowWnd(wnd
, false);
3173 if (!RemovePage(page_idx
))
3177 // actually destroy the window now
3178 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3180 // delete the child frame with pending delete, as is
3181 // customary with frame windows
3182 if (!wxPendingDelete
.Member(wnd
))
3183 wxPendingDelete
.Append(wnd
);
3196 // RemovePage() removes a tab from the multi-notebook,
3197 // but does not destroy the window
3198 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3200 // save active window pointer
3201 wxWindow
* active_wnd
= NULL
;
3203 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3205 // save pointer of window being deleted
3206 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3207 wxWindow
* new_active
= NULL
;
3209 // make sure we found the page
3213 // find out which onscreen tab ctrl owns this tab
3216 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3219 bool is_curpage
= (m_curpage
== (int)page_idx
);
3220 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3223 // remove the tab from main catalog
3224 if (!m_tabs
.RemovePage(wnd
))
3227 // remove the tab from the onscreen tab ctrl
3228 ctrl
->RemovePage(wnd
);
3230 if (is_active_in_split
)
3232 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3234 if (ctrl_idx
>= ctrl_new_page_count
)
3235 ctrl_idx
= ctrl_new_page_count
-1;
3237 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3239 // set new page as active in the tab split
3240 ctrl
->SetActivePage(ctrl_idx
);
3242 // if the page deleted was the current page for the
3243 // entire tab control, then record the window
3244 // pointer of the new active page for activation
3247 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3253 // we are not deleting the active page, so keep it the same
3254 new_active
= active_wnd
;
3260 // we haven't yet found a new page to active,
3261 // so select the next page from the main tab
3264 if (page_idx
< m_tabs
.GetPageCount())
3266 new_active
= m_tabs
.GetPage(page_idx
).window
;
3269 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3271 new_active
= m_tabs
.GetPage(0).window
;
3276 RemoveEmptyTabFrames();
3278 m_curpage
= wxNOT_FOUND
;
3280 // set new active pane unless we're being destroyed anyhow
3281 if (new_active
&& !m_isBeingDeleted
)
3282 SetSelectionToWindow(new_active
);
3287 // GetPageIndex() returns the index of the page, or -1 if the
3288 // page could not be located in the notebook
3289 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3291 return m_tabs
.GetIdxFromWindow(page_wnd
);
3296 // SetPageText() changes the tab caption of the specified page
3297 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3299 if (page_idx
>= m_tabs
.GetPageCount())
3302 // update our own tab catalog
3303 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3304 page_info
.caption
= text
;
3306 // update what's on screen
3309 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3311 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3312 info
.caption
= text
;
3320 // returns the page caption
3321 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3323 if (page_idx
>= m_tabs
.GetPageCount())
3324 return wxEmptyString
;
3326 // update our own tab catalog
3327 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3328 return page_info
.caption
;
3331 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3333 if (page_idx
>= m_tabs
.GetPageCount())
3336 // update our own tab catalog
3337 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3338 page_info
.bitmap
= bitmap
;
3340 // tab height might have changed
3341 UpdateTabCtrlHeight();
3343 // update what's on screen
3346 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3348 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3349 info
.bitmap
= bitmap
;
3357 // returns the page bitmap
3358 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3360 if (page_idx
>= m_tabs
.GetPageCount())
3363 // update our own tab catalog
3364 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3365 return page_info
.bitmap
;
3368 // GetSelection() returns the index of the currently active page
3369 int wxAuiNotebook::GetSelection() const
3374 // SetSelection() sets the currently active page
3375 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3377 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3381 // don't change the page unless necessary;
3382 // however, clicking again on a tab should give it the focus.
3383 if ((int)new_page
== m_curpage
)
3387 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3389 if (FindFocus() != ctrl
)
3395 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3396 evt
.SetSelection(new_page
);
3397 evt
.SetOldSelection(m_curpage
);
3398 evt
.SetEventObject(this);
3399 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3401 int old_curpage
= m_curpage
;
3402 m_curpage
= new_page
;
3404 // program allows the page change
3405 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3406 (void)GetEventHandler()->ProcessEvent(evt
);
3411 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3413 m_tabs
.SetActivePage(wnd
);
3415 ctrl
->SetActivePage(ctrl_idx
);
3419 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3422 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3423 size_t i
, pane_count
= all_panes
.GetCount();
3424 for (i
= 0; i
< pane_count
; ++i
)
3426 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3427 if (pane
.name
== wxT("dummy"))
3429 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3430 if (tabctrl
!= ctrl
)
3431 tabctrl
->SetSelectedFont(m_normal_font
);
3433 tabctrl
->SetSelectedFont(m_selected_font
);
3437 // Set the focus to the page if we're not currently focused on the tab.
3438 // This is Firefox-like behaviour.
3439 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3449 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3451 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3452 wxCHECK_RET( idx
!= wxNOT_FOUND
, wxT("invalid notebook page") );
3455 // since a tab was clicked, let the parent know that we received
3456 // the focus, even if we will assign that focus immediately
3457 // to the child tab in the SetSelection call below
3458 // (the child focus event will also let wxAuiManager, if any,
3459 // know that the notebook control has been activated)
3461 wxWindow
* parent
= GetParent();
3464 wxChildFocusEvent
eventFocus(this);
3465 parent
->GetEventHandler()->ProcessEvent(eventFocus
);
3472 // GetPageCount() returns the total number of
3473 // pages managed by the multi-notebook
3474 size_t wxAuiNotebook::GetPageCount() const
3476 return m_tabs
.GetPageCount();
3479 // GetPage() returns the wxWindow pointer of the
3481 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3483 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3485 return m_tabs
.GetWindowFromIdx(page_idx
);
3488 // DoSizing() performs all sizing operations in each tab control
3489 void wxAuiNotebook::DoSizing()
3491 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3492 size_t i
, pane_count
= all_panes
.GetCount();
3493 for (i
= 0; i
< pane_count
; ++i
)
3495 if (all_panes
.Item(i
).name
== wxT("dummy"))
3498 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3499 tabframe
->DoSizing();
3503 // GetActiveTabCtrl() returns the active tab control. It is
3504 // called to determine which control gets new windows being added
3505 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3507 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3512 // find the tab ctrl with the current page
3513 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3520 // no current page, just find the first tab ctrl
3521 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3522 size_t i
, pane_count
= all_panes
.GetCount();
3523 for (i
= 0; i
< pane_count
; ++i
)
3525 if (all_panes
.Item(i
).name
== wxT("dummy"))
3528 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3529 return tabframe
->m_tabs
;
3532 // If there is no tabframe at all, create one
3533 wxTabFrame
* tabframe
= new wxTabFrame
;
3534 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3535 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3539 wxNO_BORDER
|wxWANTS_CHARS
);
3540 tabframe
->m_tabs
->SetFlags(m_flags
);
3541 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3542 m_mgr
.AddPane(tabframe
,
3543 wxAuiPaneInfo().Center().CaptionVisible(false));
3547 return tabframe
->m_tabs
;
3550 // FindTab() finds the tab control that currently contains the window as well
3551 // as the index of the window in the tab control. It returns true if the
3552 // window was found, otherwise false.
3553 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3555 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3556 size_t i
, pane_count
= all_panes
.GetCount();
3557 for (i
= 0; i
< pane_count
; ++i
)
3559 if (all_panes
.Item(i
).name
== wxT("dummy"))
3562 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3564 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3567 *ctrl
= tabframe
->m_tabs
;
3576 void wxAuiNotebook::Split(size_t page
, int direction
)
3578 wxSize cli_size
= GetClientSize();
3580 // get the page's window pointer
3581 wxWindow
* wnd
= GetPage(page
);
3585 // notebooks with 1 or less pages can't be split
3586 if (GetPageCount() < 2)
3589 // find out which tab control the page currently belongs to
3590 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3593 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3595 if (!src_tabs
|| src_idx
== -1)
3598 // choose a split size
3600 if (GetPageCount() > 2)
3602 split_size
= CalculateNewSplitSize();
3606 // because there are two panes, always split them
3608 split_size
= GetClientSize();
3614 // create a new tab frame
3615 wxTabFrame
* new_tabs
= new wxTabFrame
;
3616 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3617 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3618 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3622 wxNO_BORDER
|wxWANTS_CHARS
);
3623 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3624 new_tabs
->m_tabs
->SetFlags(m_flags
);
3625 dest_tabs
= new_tabs
->m_tabs
;
3627 // create a pane info structure with the information
3628 // about where the pane should be added
3629 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3632 if (direction
== wxLEFT
)
3635 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3637 else if (direction
== wxRIGHT
)
3640 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3642 else if (direction
== wxTOP
)
3645 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3647 else if (direction
== wxBOTTOM
)
3650 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3653 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3656 // remove the page from the source tabs
3657 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3658 page_info
.active
= false;
3659 src_tabs
->RemovePage(page_info
.window
);
3660 if (src_tabs
->GetPageCount() > 0)
3662 src_tabs
->SetActivePage((size_t)0);
3663 src_tabs
->DoShowHide();
3664 src_tabs
->Refresh();
3668 // add the page to the destination tabs
3669 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3671 if (src_tabs
->GetPageCount() == 0)
3673 RemoveEmptyTabFrames();
3677 dest_tabs
->DoShowHide();
3678 dest_tabs
->Refresh();
3680 // force the set selection function reset the selection
3683 // set the active page to the one we just split off
3684 SetSelectionToPage(page_info
);
3686 UpdateHintWindowSize();
3690 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3692 UpdateHintWindowSize();
3697 void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent
& evt
)
3699 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3700 wxASSERT(ctrl
!= NULL
);
3702 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3703 wxASSERT(wnd
!= NULL
);
3705 SetSelectionToWindow(wnd
);
3708 void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent
& WXUNUSED(evt
))
3710 // notify owner that the tabbar background has been double-clicked
3711 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
3712 e
.SetEventObject(this);
3713 GetEventHandler()->ProcessEvent(e
);
3716 void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent
&)
3721 void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent
& evt
)
3723 wxPoint screen_pt
= ::wxGetMousePosition();
3724 wxPoint client_pt
= ScreenToClient(screen_pt
);
3727 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3728 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3730 if (dest_tabs
== src_tabs
)
3734 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3737 // always hide the hint for inner-tabctrl drag
3740 // if tab moving is not allowed, leave
3741 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3746 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3747 wxWindow
* dest_location_tab
;
3749 // this is an inner-tab drag/reposition
3750 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3752 int src_idx
= evt
.GetSelection();
3753 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3755 // prevent jumpy drag
3756 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3757 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3758 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3760 m_last_drag_x
= pt
.x
;
3765 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3766 dest_tabs
->MovePage(src_tab
, dest_idx
);
3767 dest_tabs
->SetActivePage((size_t)dest_idx
);
3768 dest_tabs
->DoShowHide();
3769 dest_tabs
->Refresh();
3770 m_last_drag_x
= pt
.x
;
3778 // if external drag is allowed, check if the tab is being dragged
3779 // over a different wxAuiNotebook control
3780 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3782 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3784 // if we aren't over any window, stop here
3788 // make sure we are not over the hint window
3789 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3793 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3795 tab_ctrl
= tab_ctrl
->GetParent();
3800 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3804 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3805 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3806 m_mgr
.ShowHint(hint_rect
);
3815 // we are either over a hint window, or not over a tab
3816 // window, and there is no where to drag to, so exit
3823 // if there are less than two panes, split can't happen, so leave
3824 if (m_tabs
.GetPageCount() < 2)
3827 // if tab moving is not allowed, leave
3828 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3834 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3840 wxRect hint_rect
= dest_tabs
->GetRect();
3841 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3842 m_mgr
.ShowHint(hint_rect
);
3846 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3852 void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent
& evt
)
3857 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3858 wxCHECK_RET( src_tabs
, wxT("no source object?") );
3860 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3862 // get the mouse position, which will be used to determine the drop point
3863 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3864 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3868 // check for an external move
3869 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3871 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3875 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3877 tab_ctrl
= tab_ctrl
->GetParent();
3882 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3886 // find out from the destination control
3887 // if it's ok to drop this tab here
3888 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3889 e
.SetSelection(evt
.GetSelection());
3890 e
.SetOldSelection(evt
.GetSelection());
3891 e
.SetEventObject(this);
3892 e
.SetDragSource(this);
3893 e
.Veto(); // dropping must be explicitly approved by control owner
3895 nb
->GetEventHandler()->ProcessEvent(e
);
3899 // no answer or negative answer
3905 int src_idx
= evt
.GetSelection();
3906 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3908 // Check that it's not an impossible parent relationship
3910 while (p
&& !p
->IsTopLevel())
3919 // get main index of the page
3920 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3921 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no source page?") );
3924 // make a copy of the page info
3925 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3927 // remove the page from the source notebook
3928 RemovePage(main_idx
);
3930 // reparent the page
3931 src_page
->Reparent(nb
);
3934 // found out the insert idx
3935 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3936 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3938 wxWindow
* target
= NULL
;
3939 int insert_idx
= -1;
3940 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3943 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3947 // add the page to the new notebook
3948 if (insert_idx
== -1)
3949 insert_idx
= dest_tabs
->GetPageCount();
3950 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3951 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3954 dest_tabs
->DoShowHide();
3955 dest_tabs
->Refresh();
3957 // set the selection in the destination tab control
3958 nb
->SetSelectionToPage(page_info
);
3960 // notify owner that the tab has been dragged
3961 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3962 e2
.SetSelection(evt
.GetSelection());
3963 e2
.SetOldSelection(evt
.GetSelection());
3964 e2
.SetEventObject(this);
3965 GetEventHandler()->ProcessEvent(e2
);
3975 // only perform a tab split if it's allowed
3976 wxAuiTabCtrl
* dest_tabs
= NULL
;
3978 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3980 // If the pointer is in an existing tab frame, do a tab insert
3981 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3982 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3983 int insert_idx
= -1;
3986 dest_tabs
= tab_frame
->m_tabs
;
3988 if (dest_tabs
== src_tabs
)
3992 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3993 wxWindow
* target
= NULL
;
3994 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3997 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
4003 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
4008 // there is no suitable drop location here, exit out
4012 // If there is no tabframe at all, create one
4013 wxTabFrame
* new_tabs
= new wxTabFrame
;
4014 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
4015 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
4016 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
4020 wxNO_BORDER
|wxWANTS_CHARS
);
4021 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
4022 new_tabs
->m_tabs
->SetFlags(m_flags
);
4024 m_mgr
.AddPane(new_tabs
,
4025 wxAuiPaneInfo().Bottom().CaptionVisible(false),
4028 dest_tabs
= new_tabs
->m_tabs
;
4033 // remove the page from the source tabs
4034 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
4035 page_info
.active
= false;
4036 src_tabs
->RemovePage(page_info
.window
);
4037 if (src_tabs
->GetPageCount() > 0)
4039 src_tabs
->SetActivePage((size_t)0);
4040 src_tabs
->DoShowHide();
4041 src_tabs
->Refresh();
4046 // add the page to the destination tabs
4047 if (insert_idx
== -1)
4048 insert_idx
= dest_tabs
->GetPageCount();
4049 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
4051 if (src_tabs
->GetPageCount() == 0)
4053 RemoveEmptyTabFrames();
4057 dest_tabs
->DoShowHide();
4058 dest_tabs
->Refresh();
4060 // force the set selection function reset the selection
4063 // set the active page to the one we just split off
4064 SetSelectionToPage(page_info
);
4066 UpdateHintWindowSize();
4069 // notify owner that the tab has been dragged
4070 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
4071 e
.SetSelection(evt
.GetSelection());
4072 e
.SetOldSelection(evt
.GetSelection());
4073 e
.SetEventObject(this);
4074 GetEventHandler()->ProcessEvent(e
);
4079 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
4081 // if we've just removed the last tab from the source
4082 // tab set, the remove the tab control completely
4083 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4084 size_t i
, pane_count
= all_panes
.GetCount();
4085 for (i
= 0; i
< pane_count
; ++i
)
4087 if (all_panes
.Item(i
).name
== wxT("dummy"))
4090 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4091 if (tabframe
->m_tab_rect
.Contains(pt
))
4092 return tabframe
->m_tabs
;
4098 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
4100 // if we've just removed the last tab from the source
4101 // tab set, the remove the tab control completely
4102 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4103 size_t i
, pane_count
= all_panes
.GetCount();
4104 for (i
= 0; i
< pane_count
; ++i
)
4106 if (all_panes
.Item(i
).name
== wxT("dummy"))
4109 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4110 if (tabframe
->m_tabs
== tab_ctrl
)
4119 void wxAuiNotebook::RemoveEmptyTabFrames()
4121 // if we've just removed the last tab from the source
4122 // tab set, the remove the tab control completely
4123 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
4124 size_t i
, pane_count
= all_panes
.GetCount();
4125 for (i
= 0; i
< pane_count
; ++i
)
4127 if (all_panes
.Item(i
).name
== wxT("dummy"))
4130 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4131 if (tab_frame
->m_tabs
->GetPageCount() == 0)
4133 m_mgr
.DetachPane(tab_frame
);
4135 // use pending delete because sometimes during
4136 // window closing, refreshs are pending
4137 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
4138 wxPendingDelete
.Append(tab_frame
->m_tabs
);
4140 tab_frame
->m_tabs
= NULL
;
4147 // check to see if there is still a center pane;
4148 // if there isn't, make a frame the center pane
4149 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4150 pane_count
= panes
.GetCount();
4151 wxWindow
* first_good
= NULL
;
4152 bool center_found
= false;
4153 for (i
= 0; i
< pane_count
; ++i
)
4155 if (panes
.Item(i
).name
== wxT("dummy"))
4157 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4158 center_found
= true;
4160 first_good
= panes
.Item(i
).window
;
4163 if (!center_found
&& first_good
)
4165 m_mgr
.GetPane(first_good
).Centre();
4168 if (!m_isBeingDeleted
)
4172 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4176 // if we're dragging a tab, don't change the current selection.
4177 // This code prevents a bug that used to happen when the hint window
4178 // was hidden. In the bug, the focus would return to the notebook
4179 // child, which would then enter this handler and call
4180 // SetSelection, which is not desired turn tab dragging.
4182 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4183 size_t i
, pane_count
= all_panes
.GetCount();
4184 for (i
= 0; i
< pane_count
; ++i
)
4186 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4187 if (pane
.name
== wxT("dummy"))
4189 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4190 if (tabframe
->m_tabs
->IsDragging())
4195 // change the tab selection to the child
4196 // which was focused
4197 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4198 if (idx
!= -1 && idx
!= m_curpage
)
4204 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4206 if ( event
.IsWindowChange() ) {
4208 // FIXME: the problem with this is that if we have a split notebook,
4209 // we selection may go all over the place.
4210 AdvanceSelection(event
.GetDirection());
4213 // we get this event in 3 cases
4215 // a) one of our pages might have generated it because the user TABbed
4216 // out from it in which case we should propagate the event upwards and
4217 // our parent will take care of setting the focus to prev/next sibling
4221 // b) the parent panel wants to give the focus to us so that we
4222 // forward it to our selected page. We can't deal with this in
4223 // OnSetFocus() because we don't know which direction the focus came
4224 // from in this case and so can't choose between setting the focus to
4225 // first or last panel child
4229 // c) we ourselves (see MSWTranslateMessage) generated the event
4231 wxWindow
* const parent
= GetParent();
4233 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4234 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4235 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4237 if ( isFromParent
|| isFromSelf
)
4239 // no, it doesn't come from child, case (b) or (c): forward to a
4240 // page but only if direction is backwards (TAB) or from ourselves,
4241 if ( GetSelection() != wxNOT_FOUND
&&
4242 (!event
.GetDirection() || isFromSelf
) )
4244 // so that the page knows that the event comes from it's parent
4245 // and is being propagated downwards
4246 event
.SetEventObject(this);
4248 wxWindow
*page
= GetPage(GetSelection());
4249 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4253 //else: page manages focus inside it itself
4255 else // otherwise set the focus to the notebook itself
4262 // it comes from our child, case (a), pass to the parent, but only
4263 // if the direction is forwards. Otherwise set the focus to the
4264 // notebook itself. The notebook is always the 'first' control of a
4266 if ( !event
.GetDirection() )
4272 event
.SetCurrentFocus(this);
4273 parent
->GetEventHandler()->ProcessEvent(event
);
4279 void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent
& evt
)
4281 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4283 int button_id
= evt
.GetInt();
4285 if (button_id
== wxAUI_BUTTON_CLOSE
)
4287 int selection
= evt
.GetSelection();
4289 if (selection
== -1)
4291 // if the close button is to the right, use the active
4292 // page selection to determine which page to close
4293 selection
= tabs
->GetActivePage();
4296 if (selection
!= -1)
4298 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4300 // ask owner if it's ok to close the tab
4301 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4302 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4303 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4304 e
.SetSelection(idx
);
4305 e
.SetOldSelection(evt
.GetSelection());
4306 e
.SetEventObject(this);
4307 GetEventHandler()->ProcessEvent(e
);
4313 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4320 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4321 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, wxT("no page to delete?") );
4323 DeletePage(main_idx
);
4326 // notify owner that the tab has been closed
4327 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4328 e2
.SetSelection(idx
);
4329 e2
.SetEventObject(this);
4330 GetEventHandler()->ProcessEvent(e2
);
4336 void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent
& evt
)
4338 // patch event through to owner
4339 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4340 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4342 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4343 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4344 e
.SetEventObject(this);
4345 GetEventHandler()->ProcessEvent(e
);
4348 void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent
& evt
)
4350 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4351 // click should act like a tab close action. However, first
4352 // give the owner an opportunity to handle the middle up event
4353 // for custom action
4355 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4356 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4358 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4359 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4360 e
.SetEventObject(this);
4361 if (GetEventHandler()->ProcessEvent(e
))
4366 // check if we are supposed to close on middle-up
4367 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4370 // simulate the user pressing the close button on the tab
4371 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4375 void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent
& evt
)
4377 // patch event through to owner
4378 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4379 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4381 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4382 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4383 e
.SetEventObject(this);
4384 GetEventHandler()->ProcessEvent(e
);
4387 void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent
& evt
)
4389 // patch event through to owner
4390 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4391 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4393 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4394 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4395 e
.SetEventObject(this);
4396 GetEventHandler()->ProcessEvent(e
);
4399 // Sets the normal font
4400 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4402 m_normal_font
= font
;
4403 GetArtProvider()->SetNormalFont(font
);
4406 // Sets the selected tab font
4407 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4409 m_selected_font
= font
;
4410 GetArtProvider()->SetSelectedFont(font
);
4413 // Sets the measuring font
4414 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4416 GetArtProvider()->SetMeasuringFont(font
);
4419 // Sets the tab font
4420 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4422 wxControl::SetFont(font
);
4424 wxFont
normalFont(font
);
4425 wxFont
selectedFont(normalFont
);
4426 selectedFont
.SetWeight(wxBOLD
);
4428 SetNormalFont(normalFont
);
4429 SetSelectedFont(selectedFont
);
4430 SetMeasuringFont(selectedFont
);
4435 // Gets the tab control height
4436 int wxAuiNotebook::GetTabCtrlHeight() const
4438 return m_tab_ctrl_height
;
4441 // Gets the height of the notebook for a given page height
4442 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4444 UpdateTabCtrlHeight();
4446 int tabCtrlHeight
= GetTabCtrlHeight();
4447 int decorHeight
= 2;
4448 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4451 // Advances the selection, generation page selection events
4452 void wxAuiNotebook::AdvanceSelection(bool forward
)
4454 if (GetPageCount() <= 1)
4457 int currentSelection
= GetSelection();
4461 if (currentSelection
== (int) (GetPageCount() - 1))
4463 else if (currentSelection
== -1)
4464 currentSelection
= 0;
4466 currentSelection
++;
4470 if (currentSelection
<= 0)
4473 currentSelection
--;
4476 SetSelection(currentSelection
);
4479 // Shows the window menu
4480 bool wxAuiNotebook::ShowWindowMenu()
4482 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4484 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4488 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4489 e
.SetSelection(idx
);
4490 e
.SetOldSelection(tabCtrl
->GetActivePage());
4491 e
.SetEventObject(tabCtrl
);
4492 GetEventHandler()->ProcessEvent(e
);
4500 void wxAuiNotebook::Thaw()