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/mac/carbon/private.h"
40 #include "wx/arrimpl.cpp"
41 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
42 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
)
56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
)
57 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
)
58 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
)
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 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 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 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 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 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 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;
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 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
240 art
->SetNormalFont(m_normal_font
);
241 art
->SetSelectedFont(m_selected_font
);
242 art
->SetMeasuringFont(m_measuring_font
);
247 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
252 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
255 m_fixed_tab_width
= 100;
257 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
259 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
260 tot_width
-= m_active_close_bmp
.GetWidth();
261 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
262 tot_width
-= m_active_windowlist_bmp
.GetWidth();
266 m_fixed_tab_width
= tot_width
/(int)tab_count
;
270 if (m_fixed_tab_width
< 100)
271 m_fixed_tab_width
= 100;
273 if (m_fixed_tab_width
> tot_width
/2)
274 m_fixed_tab_width
= tot_width
/2;
276 if (m_fixed_tab_width
> 220)
277 m_fixed_tab_width
= 220;
279 m_tab_ctrl_height
= tab_ctrl_size
.y
;
283 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
284 wxWindow
* WXUNUSED(wnd
),
289 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
290 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
293 if (m_flags
&wxAUI_NB_BOTTOM
)
294 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
);
295 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
296 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
297 else //for wxAUI_NB_TOP
298 r
= wxRect(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
300 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
305 dc
.SetPen(m_border_pen
);
306 int y
= rect
.GetHeight();
307 int w
= rect
.GetWidth();
309 if (m_flags
&wxAUI_NB_BOTTOM
)
311 dc
.SetBrush(wxBrush(bottom_color
));
312 dc
.DrawRectangle(-1, 0, w
+2, 4);
314 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
315 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
316 else //for wxAUI_NB_TOP
318 dc
.SetBrush(m_base_colour_brush
);
319 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
324 // DrawTab() draws an individual tab.
327 // in_rect - rectangle the tab should be confined to
328 // caption - tab's caption
329 // active - whether or not the tab is active
330 // out_rect - actual output rectangle
331 // x_extent - the advance x; where the next tab should start
333 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
335 const wxAuiNotebookPage
& page
,
336 const wxRect
& in_rect
,
337 int close_button_state
,
338 wxRect
* out_tab_rect
,
339 wxRect
* out_button_rect
,
342 wxCoord normal_textx
, normal_texty
;
343 wxCoord selected_textx
, selected_texty
;
346 // if the caption is empty, measure some temporary text
347 wxString caption
= page
.caption
;
351 dc
.SetFont(m_selected_font
);
352 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
354 dc
.SetFont(m_normal_font
);
355 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
357 // figure out the size of the tab
358 wxSize tab_size
= GetTabSize(dc
,
366 wxCoord tab_height
= m_tab_ctrl_height
- 3;
367 wxCoord tab_width
= tab_size
.x
;
368 wxCoord tab_x
= in_rect
.x
;
369 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
372 caption
= page
.caption
;
375 // select pen, brush and font for the tab to be drawn
379 dc
.SetFont(m_selected_font
);
380 texty
= selected_texty
;
384 dc
.SetFont(m_normal_font
);
385 texty
= normal_texty
;
389 // create points that will make the tab outline
391 int clip_width
= tab_width
;
392 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
393 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
396 wxPoint clip_points[6];
397 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
398 clip_points[1] = wxPoint(tab_x, tab_y+2);
399 clip_points[2] = wxPoint(tab_x+2, tab_y);
400 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
401 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
402 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
404 // FIXME: these ports don't provide wxRegion ctor from array of points
405 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
406 // set the clipping region for the tab --
407 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
408 dc.SetClippingRegion(clipping_region);
409 #endif // !wxDFB && !wxCocoa
411 // since the above code above doesn't play well with WXDFB or WXCOCOA,
412 // we'll just use a rectangle for the clipping region for now --
413 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
416 wxPoint border_points
[6];
417 if (m_flags
&wxAUI_NB_BOTTOM
)
419 border_points
[0] = wxPoint(tab_x
, tab_y
);
420 border_points
[1] = wxPoint(tab_x
, tab_y
+tab_height
-6);
421 border_points
[2] = wxPoint(tab_x
+2, tab_y
+tab_height
-4);
422 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
+tab_height
-4);
423 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-6);
424 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
);
426 else //if (m_flags & wxAUI_NB_TOP) {}
428 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
429 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
430 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
431 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
432 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
433 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
435 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
436 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
438 int drawn_tab_yoff
= border_points
[1].y
;
439 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
446 // draw base background color
447 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
448 dc
.SetPen(m_base_colour_pen
);
449 dc
.SetBrush(m_base_colour_brush
);
450 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
452 // this white helps fill out the gradient at the top of the tab
453 dc
.SetPen(*wxWHITE_PEN
);
454 dc
.SetBrush(*wxWHITE_BRUSH
);
455 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
457 // these two points help the rounded corners appear more antialiased
458 dc
.SetPen(m_base_colour_pen
);
459 dc
.DrawPoint(r
.x
+2, r
.y
+1);
460 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
462 // set rectangle down a bit for gradient drawing
463 r
.SetHeight(r
.GetHeight()/2);
469 // draw gradient background
470 wxColor top_color
= *wxWHITE
;
471 wxColor bottom_color
= m_base_colour
;
472 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
478 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
480 // start the gradent up a bit and leave the inside border inset
481 // by a pixel for a 3D look. Only the top half of the inactive
482 // tab will have a slight gradient
489 // -- draw top gradient fill for glossy look
490 wxColor top_color
= m_base_colour
;
491 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
492 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
497 // -- draw bottom fill for glossy look
498 top_color
= m_base_colour
;
499 bottom_color
= m_base_colour
;
500 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
504 dc
.SetPen(m_border_pen
);
505 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
506 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
508 // there are two horizontal grey lines at the bottom of the tab control,
509 // this gets rid of the top one of those lines in the tab control
512 if (m_flags
&wxAUI_NB_BOTTOM
)
513 dc
.SetPen(wxPen(wxColour(wxAuiStepColour(m_base_colour
, 170))));
514 // TODO: else if (m_flags &wxAUI_NB_LEFT) {}
515 // TODO: else if (m_flags &wxAUI_NB_RIGHT) {}
516 else //for wxAUI_NB_TOP
517 dc
.SetPen(m_base_colour_pen
);
518 dc
.DrawLine(border_points
[0].x
+1,
525 int text_offset
= tab_x
+ 8;
526 int close_button_width
= 0;
527 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
529 close_button_width
= m_active_close_bmp
.GetWidth();
532 int bitmap_offset
= 0;
533 if (page
.bitmap
.IsOk())
535 bitmap_offset
= tab_x
+ 8;
538 dc
.DrawBitmap(page
.bitmap
,
540 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
543 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
544 text_offset
+= 3; // bitmap padding
549 text_offset
= tab_x
+ 8;
553 wxString draw_text
= wxAuiChopText(dc
,
555 tab_width
- (text_offset
-tab_x
) - close_button_width
);
558 dc
.DrawText(draw_text
,
560 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
562 // draw focus rectangle
563 if (page
.active
&& (wnd
->FindFocus() == wnd
))
565 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
566 selected_textx
, selected_texty
);
569 wxRect focusRectBitmap
;
571 if (page
.bitmap
.IsOk())
572 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
573 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
575 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
576 focusRect
= focusRectBitmap
;
577 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
578 focusRect
= focusRectText
;
579 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
580 focusRect
= focusRectText
.Union(focusRectBitmap
);
582 focusRect
.Inflate(2, 2);
584 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
587 // draw close button if necessary
588 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
590 wxBitmap bmp
= m_disabled_close_bmp
;
592 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
593 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
595 bmp
= m_active_close_bmp
;
598 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
599 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
602 IndentPressedBitmap(&rect
, close_button_state
);
603 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
605 *out_button_rect
= rect
;
608 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
610 dc
.DestroyClippingRegion();
613 int wxAuiDefaultTabArt::GetIndentSize()
618 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
619 wxWindow
* WXUNUSED(wnd
),
620 const wxString
& caption
,
621 const wxBitmap
& bitmap
,
622 bool WXUNUSED(active
),
623 int close_button_state
,
626 wxCoord measured_textx
, measured_texty
, tmp
;
628 dc
.SetFont(m_measuring_font
);
629 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
631 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
633 // add padding around the text
634 wxCoord tab_width
= measured_textx
;
635 wxCoord tab_height
= measured_texty
;
637 // if the close button is showing, add space for it
638 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
639 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
641 // if there's a bitmap, add space for it
644 tab_width
+= bitmap
.GetWidth();
645 tab_width
+= 3; // right side bitmap padding
646 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
653 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
655 tab_width
= m_fixed_tab_width
;
658 *x_extent
= tab_width
;
660 return wxSize(tab_width
, tab_height
);
664 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
665 wxWindow
* WXUNUSED(wnd
),
666 const wxRect
& in_rect
,
677 case wxAUI_BUTTON_CLOSE
:
678 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
679 bmp
= m_disabled_close_bmp
;
681 bmp
= m_active_close_bmp
;
683 case wxAUI_BUTTON_LEFT
:
684 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
685 bmp
= m_disabled_left_bmp
;
687 bmp
= m_active_left_bmp
;
689 case wxAUI_BUTTON_RIGHT
:
690 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
691 bmp
= m_disabled_right_bmp
;
693 bmp
= m_active_right_bmp
;
695 case wxAUI_BUTTON_WINDOWLIST
:
696 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
697 bmp
= m_disabled_windowlist_bmp
;
699 bmp
= m_active_windowlist_bmp
;
709 if (orientation
== wxLEFT
)
711 rect
.SetX(in_rect
.x
);
712 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
713 rect
.SetWidth(bmp
.GetWidth());
714 rect
.SetHeight(bmp
.GetHeight());
718 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
719 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
720 bmp
.GetWidth(), bmp
.GetHeight());
723 IndentPressedBitmap(&rect
, button_state
);
724 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
729 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
730 const wxAuiNotebookPageArray
& pages
,
735 size_t i
, count
= pages
.GetCount();
736 for (i
= 0; i
< count
; ++i
)
738 const wxAuiNotebookPage
& page
= pages
.Item(i
);
739 wxString caption
= page
.caption
;
741 // if there is no caption, make it a space. This will prevent
742 // an assert in the menu code.
743 if (caption
.IsEmpty())
746 menuPopup
.AppendCheckItem(1000+i
, caption
);
749 if (active_idx
!= -1)
751 menuPopup
.Check(1000+active_idx
, true);
754 // find out where to put the popup menu of window items
755 wxPoint pt
= ::wxGetMousePosition();
756 pt
= wnd
->ScreenToClient(pt
);
758 // find out the screen coordinate at the bottom of the tab ctrl
759 wxRect cli_rect
= wnd
->GetClientRect();
760 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
762 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
763 wnd
->PushEventHandler(cc
);
764 wnd
->PopupMenu(&menuPopup
, pt
);
765 int command
= cc
->GetCommandId();
766 wnd
->PopEventHandler(true);
774 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
775 const wxAuiNotebookPageArray
& pages
,
776 const wxSize
& required_bmp_size
)
779 dc
.SetFont(m_measuring_font
);
781 // sometimes a standard bitmap size needs to be enforced, especially
782 // if some tabs have bitmaps and others don't. This is important because
783 // it prevents the tab control from resizing when tabs are added.
784 wxBitmap measure_bmp
;
785 if (required_bmp_size
.IsFullySpecified())
787 measure_bmp
.Create(required_bmp_size
.x
,
788 required_bmp_size
.y
);
793 size_t i
, page_count
= pages
.GetCount();
794 for (i
= 0; i
< page_count
; ++i
)
796 wxAuiNotebookPage
& page
= pages
.Item(i
);
799 if (measure_bmp
.IsOk())
804 // we don't use the caption text because we don't
805 // want tab heights to be different in the case
806 // of a very short piece of text on one tab and a very
807 // tall piece of text on another tab
809 wxSize s
= GetTabSize(dc
,
814 wxAUI_BUTTON_STATE_HIDDEN
,
817 max_y
= wxMax(max_y
, s
.y
);
823 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
825 m_normal_font
= font
;
828 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
830 m_selected_font
= font
;
833 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
835 m_measuring_font
= font
;
839 // -- wxAuiSimpleTabArt class implementation --
841 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
843 m_normal_font
= *wxNORMAL_FONT
;
844 m_selected_font
= *wxNORMAL_FONT
;
845 m_selected_font
.SetWeight(wxBOLD
);
846 m_measuring_font
= m_selected_font
;
849 m_fixed_tab_width
= 100;
851 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
853 wxColour background_colour
= base_colour
;
854 wxColour normaltab_colour
= base_colour
;
855 wxColour selectedtab_colour
= *wxWHITE
;
857 m_bkbrush
= wxBrush(background_colour
);
858 m_normal_bkbrush
= wxBrush(normaltab_colour
);
859 m_normal_bkpen
= wxPen(normaltab_colour
);
860 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
861 m_selected_bkpen
= wxPen(selectedtab_colour
);
863 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
864 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
866 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
867 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
869 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
870 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
872 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
873 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
877 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
881 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
883 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
887 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
892 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
895 m_fixed_tab_width
= 100;
897 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
899 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
900 tot_width
-= m_active_close_bmp
.GetWidth();
901 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
902 tot_width
-= m_active_windowlist_bmp
.GetWidth();
906 m_fixed_tab_width
= tot_width
/(int)tab_count
;
910 if (m_fixed_tab_width
< 100)
911 m_fixed_tab_width
= 100;
913 if (m_fixed_tab_width
> tot_width
/2)
914 m_fixed_tab_width
= tot_width
/2;
916 if (m_fixed_tab_width
> 220)
917 m_fixed_tab_width
= 220;
920 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
921 wxWindow
* WXUNUSED(wnd
),
925 dc
.SetBrush(m_bkbrush
);
926 dc
.SetPen(*wxTRANSPARENT_PEN
);
927 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
930 dc
.SetPen(*wxGREY_PEN
);
931 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
935 // DrawTab() draws an individual tab.
938 // in_rect - rectangle the tab should be confined to
939 // caption - tab's caption
940 // active - whether or not the tab is active
941 // out_rect - actual output rectangle
942 // x_extent - the advance x; where the next tab should start
944 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
946 const wxAuiNotebookPage
& page
,
947 const wxRect
& in_rect
,
948 int close_button_state
,
949 wxRect
* out_tab_rect
,
950 wxRect
* out_button_rect
,
953 wxCoord normal_textx
, normal_texty
;
954 wxCoord selected_textx
, selected_texty
;
955 wxCoord textx
, texty
;
957 // if the caption is empty, measure some temporary text
958 wxString caption
= page
.caption
;
962 dc
.SetFont(m_selected_font
);
963 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
965 dc
.SetFont(m_normal_font
);
966 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
968 // figure out the size of the tab
969 wxSize tab_size
= GetTabSize(dc
,
977 wxCoord tab_height
= tab_size
.y
;
978 wxCoord tab_width
= tab_size
.x
;
979 wxCoord tab_x
= in_rect
.x
;
980 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
982 caption
= page
.caption
;
984 // select pen, brush and font for the tab to be drawn
988 dc
.SetPen(m_selected_bkpen
);
989 dc
.SetBrush(m_selected_bkbrush
);
990 dc
.SetFont(m_selected_font
);
991 textx
= selected_textx
;
992 texty
= selected_texty
;
996 dc
.SetPen(m_normal_bkpen
);
997 dc
.SetBrush(m_normal_bkbrush
);
998 dc
.SetFont(m_normal_font
);
999 textx
= normal_textx
;
1000 texty
= normal_texty
;
1007 points
[0].x
= tab_x
;
1008 points
[0].y
= tab_y
+ tab_height
- 1;
1009 points
[1].x
= tab_x
+ tab_height
- 3;
1010 points
[1].y
= tab_y
+ 2;
1011 points
[2].x
= tab_x
+ tab_height
+ 3;
1012 points
[2].y
= tab_y
;
1013 points
[3].x
= tab_x
+ tab_width
- 2;
1014 points
[3].y
= tab_y
;
1015 points
[4].x
= tab_x
+ tab_width
;
1016 points
[4].y
= tab_y
+ 2;
1017 points
[5].x
= tab_x
+ tab_width
;
1018 points
[5].y
= tab_y
+ tab_height
- 1;
1019 points
[6] = points
[0];
1021 dc
.SetClippingRegion(in_rect
);
1023 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
1025 dc
.SetPen(*wxGREY_PEN
);
1027 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
1028 dc
.DrawLines(WXSIZEOF(points
), points
);
1033 int close_button_width
= 0;
1034 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1036 close_button_width
= m_active_close_bmp
.GetWidth();
1037 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1041 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1044 // set minimum text offset
1045 if (text_offset
< tab_x
+ tab_height
)
1046 text_offset
= tab_x
+ tab_height
;
1048 // chop text if necessary
1049 wxString draw_text
= wxAuiChopText(dc
,
1051 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1054 dc
.DrawText(draw_text
,
1056 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1059 // draw focus rectangle
1060 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1062 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1063 selected_textx
, selected_texty
);
1065 focusRect
.Inflate(2, 2);
1067 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1070 // draw close button if necessary
1071 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1075 bmp
= m_active_close_bmp
;
1077 bmp
= m_disabled_close_bmp
;
1079 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1080 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1083 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1085 *out_button_rect
= rect
;
1089 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1091 dc
.DestroyClippingRegion();
1094 int wxAuiSimpleTabArt::GetIndentSize()
1099 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1100 wxWindow
* WXUNUSED(wnd
),
1101 const wxString
& caption
,
1102 const wxBitmap
& WXUNUSED(bitmap
),
1103 bool WXUNUSED(active
),
1104 int close_button_state
,
1107 wxCoord measured_textx
, measured_texty
;
1109 dc
.SetFont(m_measuring_font
);
1110 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1112 wxCoord tab_height
= measured_texty
+ 4;
1113 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1115 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1116 tab_width
+= m_active_close_bmp
.GetWidth();
1118 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1120 tab_width
= m_fixed_tab_width
;
1123 *x_extent
= tab_width
- (tab_height
/2) - 1;
1125 return wxSize(tab_width
, tab_height
);
1129 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1130 wxWindow
* WXUNUSED(wnd
),
1131 const wxRect
& in_rect
,
1142 case wxAUI_BUTTON_CLOSE
:
1143 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1144 bmp
= m_disabled_close_bmp
;
1146 bmp
= m_active_close_bmp
;
1148 case wxAUI_BUTTON_LEFT
:
1149 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1150 bmp
= m_disabled_left_bmp
;
1152 bmp
= m_active_left_bmp
;
1154 case wxAUI_BUTTON_RIGHT
:
1155 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1156 bmp
= m_disabled_right_bmp
;
1158 bmp
= m_active_right_bmp
;
1160 case wxAUI_BUTTON_WINDOWLIST
:
1161 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1162 bmp
= m_disabled_windowlist_bmp
;
1164 bmp
= m_active_windowlist_bmp
;
1173 if (orientation
== wxLEFT
)
1175 rect
.SetX(in_rect
.x
);
1176 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1177 rect
.SetWidth(bmp
.GetWidth());
1178 rect
.SetHeight(bmp
.GetHeight());
1182 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1183 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1184 bmp
.GetWidth(), bmp
.GetHeight());
1188 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1193 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1194 const wxAuiNotebookPageArray
& pages
,
1199 size_t i
, count
= pages
.GetCount();
1200 for (i
= 0; i
< count
; ++i
)
1202 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1203 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1206 if (active_idx
!= -1)
1208 menuPopup
.Check(1000+active_idx
, true);
1211 // find out where to put the popup menu of window
1212 // items. Subtract 100 for now to center the menu
1213 // a bit, until a better mechanism can be implemented
1214 wxPoint pt
= ::wxGetMousePosition();
1215 pt
= wnd
->ScreenToClient(pt
);
1221 // find out the screen coordinate at the bottom of the tab ctrl
1222 wxRect cli_rect
= wnd
->GetClientRect();
1223 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1225 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1226 wnd
->PushEventHandler(cc
);
1227 wnd
->PopupMenu(&menuPopup
, pt
);
1228 int command
= cc
->GetCommandId();
1229 wnd
->PopEventHandler(true);
1231 if (command
>= 1000)
1232 return command
-1000;
1237 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1238 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1239 const wxSize
& WXUNUSED(required_bmp_size
))
1242 dc
.SetFont(m_measuring_font
);
1244 wxSize s
= GetTabSize(dc
,
1249 wxAUI_BUTTON_STATE_HIDDEN
,
1254 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1256 m_normal_font
= font
;
1259 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1261 m_selected_font
= font
;
1264 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1266 m_measuring_font
= font
;
1272 // -- wxAuiTabContainer class implementation --
1275 // wxAuiTabContainer is a class which contains information about each
1276 // tab. It also can render an entire tab control to a specified DC.
1277 // It's not a window class itself, because this code will be used by
1278 // the wxFrameMananger, where it is disadvantageous to have separate
1279 // windows for each tab control in the case of "docked tabs"
1281 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1282 // which can be used as a tab control in the normal sense.
1285 wxAuiTabContainer::wxAuiTabContainer()
1289 m_art
= new wxAuiDefaultTabArt
;
1291 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1292 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1293 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1294 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1297 wxAuiTabContainer::~wxAuiTabContainer()
1302 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1309 m_art
->SetFlags(m_flags
);
1313 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1318 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1322 // check for new close button settings
1323 RemoveButton(wxAUI_BUTTON_LEFT
);
1324 RemoveButton(wxAUI_BUTTON_RIGHT
);
1325 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1326 RemoveButton(wxAUI_BUTTON_CLOSE
);
1329 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1331 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1332 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1335 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1337 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1340 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1342 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1347 m_art
->SetFlags(m_flags
);
1351 unsigned int wxAuiTabContainer::GetFlags() const
1357 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1359 m_art
->SetNormalFont(font
);
1362 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1364 m_art
->SetSelectedFont(font
);
1367 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1369 m_art
->SetMeasuringFont(font
);
1372 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1378 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1382 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1383 const wxAuiNotebookPage
& info
)
1385 wxAuiNotebookPage page_info
;
1387 page_info
.window
= page
;
1389 m_pages
.Add(page_info
);
1391 // let the art provider know how many pages we have
1394 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1400 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1401 const wxAuiNotebookPage
& info
,
1404 wxAuiNotebookPage page_info
;
1406 page_info
.window
= page
;
1408 if (idx
>= m_pages
.GetCount())
1409 m_pages
.Add(page_info
);
1411 m_pages
.Insert(page_info
, idx
);
1413 // let the art provider know how many pages we have
1416 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1422 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1425 int idx
= GetIdxFromWindow(page
);
1429 // get page entry, make a copy of it
1430 wxAuiNotebookPage p
= GetPage(idx
);
1432 // remove old page entry
1435 // insert page where it should be
1436 InsertPage(page
, p
, new_idx
);
1441 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1443 size_t i
, page_count
= m_pages
.GetCount();
1444 for (i
= 0; i
< page_count
; ++i
)
1446 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1447 if (page
.window
== wnd
)
1449 m_pages
.RemoveAt(i
);
1451 // let the art provider know how many pages we have
1454 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1464 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1468 size_t i
, page_count
= m_pages
.GetCount();
1469 for (i
= 0; i
< page_count
; ++i
)
1471 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1472 if (page
.window
== wnd
)
1479 page
.active
= false;
1486 void wxAuiTabContainer::SetNoneActive()
1488 size_t i
, page_count
= m_pages
.GetCount();
1489 for (i
= 0; i
< page_count
; ++i
)
1491 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1492 page
.active
= false;
1496 bool wxAuiTabContainer::SetActivePage(size_t page
)
1498 if (page
>= m_pages
.GetCount())
1501 return SetActivePage(m_pages
.Item(page
).window
);
1504 int wxAuiTabContainer::GetActivePage() const
1506 size_t i
, page_count
= m_pages
.GetCount();
1507 for (i
= 0; i
< page_count
; ++i
)
1509 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1517 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1519 if (idx
>= m_pages
.GetCount())
1522 return m_pages
[idx
].window
;
1525 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1527 const size_t page_count
= m_pages
.GetCount();
1528 for ( size_t i
= 0; i
< page_count
; ++i
)
1530 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1531 if (page
.window
== wnd
)
1537 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1539 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1541 return m_pages
[idx
];
1544 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1546 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1548 return m_pages
[idx
];
1551 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1556 size_t wxAuiTabContainer::GetPageCount() const
1558 return m_pages
.GetCount();
1561 void wxAuiTabContainer::AddButton(int id
,
1563 const wxBitmap
& normal_bitmap
,
1564 const wxBitmap
& disabled_bitmap
)
1566 wxAuiTabContainerButton button
;
1568 button
.bitmap
= normal_bitmap
;
1569 button
.dis_bitmap
= disabled_bitmap
;
1570 button
.location
= location
;
1571 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1573 m_buttons
.Add(button
);
1576 void wxAuiTabContainer::RemoveButton(int id
)
1578 size_t i
, button_count
= m_buttons
.GetCount();
1580 for (i
= 0; i
< button_count
; ++i
)
1582 if (m_buttons
.Item(i
).id
== id
)
1584 m_buttons
.RemoveAt(i
);
1592 size_t wxAuiTabContainer::GetTabOffset() const
1594 return m_tab_offset
;
1597 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1599 m_tab_offset
= offset
;
1605 // Render() renders the tab catalog to the specified DC
1606 // It is a virtual function and can be overridden to
1607 // provide custom drawing capabilities
1608 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1610 if (!raw_dc
|| !raw_dc
->IsOk())
1616 size_t page_count
= m_pages
.GetCount();
1617 size_t button_count
= m_buttons
.GetCount();
1619 // create off-screen bitmap
1620 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1621 dc
.SelectObject(bmp
);
1626 // find out if size of tabs is larger than can be
1627 // afforded on screen
1628 int total_width
= 0;
1629 int visible_width
= 0;
1630 for (i
= 0; i
< page_count
; ++i
)
1632 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1634 // determine if a close button is on this tab
1635 bool close_button
= false;
1636 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1637 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1639 close_button
= true;
1644 wxSize size
= m_art
->GetTabSize(dc
,
1650 wxAUI_BUTTON_STATE_NORMAL
:
1651 wxAUI_BUTTON_STATE_HIDDEN
,
1654 if (i
+1 < page_count
)
1655 total_width
+= x_extent
;
1657 total_width
+= size
.x
;
1659 if (i
>= m_tab_offset
)
1661 if (i
+1 < page_count
)
1662 visible_width
+= x_extent
;
1664 visible_width
+= size
.x
;
1668 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1670 // show left/right buttons
1671 for (i
= 0; i
< button_count
; ++i
)
1673 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1674 if (button
.id
== wxAUI_BUTTON_LEFT
||
1675 button
.id
== wxAUI_BUTTON_RIGHT
)
1677 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1683 // hide left/right buttons
1684 for (i
= 0; i
< button_count
; ++i
)
1686 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1687 if (button
.id
== wxAUI_BUTTON_LEFT
||
1688 button
.id
== wxAUI_BUTTON_RIGHT
)
1690 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1695 // determine whether left button should be enabled
1696 for (i
= 0; i
< button_count
; ++i
)
1698 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1699 if (button
.id
== wxAUI_BUTTON_LEFT
)
1701 if (m_tab_offset
== 0)
1702 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1704 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1706 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1708 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1709 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1711 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1718 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1721 int left_buttons_width
= 0;
1722 int right_buttons_width
= 0;
1726 // draw the buttons on the right side
1727 offset
= m_rect
.x
+ m_rect
.width
;
1728 for (i
= 0; i
< button_count
; ++i
)
1730 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1732 if (button
.location
!= wxRIGHT
)
1734 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1737 wxRect button_rect
= m_rect
;
1738 button_rect
.SetY(1);
1739 button_rect
.SetWidth(offset
);
1741 m_art
->DrawButton(dc
,
1749 offset
-= button
.rect
.GetWidth();
1750 right_buttons_width
+= button
.rect
.GetWidth();
1757 // draw the buttons on the left side
1759 for (i
= 0; i
< button_count
; ++i
)
1761 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1763 if (button
.location
!= wxLEFT
)
1765 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1768 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1770 m_art
->DrawButton(dc
,
1778 offset
+= button
.rect
.GetWidth();
1779 left_buttons_width
+= button
.rect
.GetWidth();
1782 offset
= left_buttons_width
;
1785 offset
+= m_art
->GetIndentSize();
1788 // prepare the tab-close-button array
1789 // make sure tab button entries which aren't used are marked as hidden
1790 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1791 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1793 // make sure there are enough tab button entries to accommodate all tabs
1794 while (m_tab_close_buttons
.GetCount() < page_count
)
1796 wxAuiTabContainerButton tempbtn
;
1797 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1798 tempbtn
.location
= wxCENTER
;
1799 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1800 m_tab_close_buttons
.Add(tempbtn
);
1804 // buttons before the tab offset must be set to hidden
1805 for (i
= 0; i
< m_tab_offset
; ++i
)
1807 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1813 size_t active
= 999;
1814 int active_offset
= 0;
1818 wxRect rect
= m_rect
;
1820 rect
.height
= m_rect
.height
;
1822 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1824 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1825 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1827 // determine if a close button is on this tab
1828 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1829 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1831 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1833 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1834 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1835 tab_button
.location
= wxCENTER
;
1840 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1844 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1846 if (rect
.width
<= 0)
1853 tab_button
.cur_state
,
1861 active_offset
= offset
;
1869 // make sure to deactivate buttons which are off the screen to the right
1870 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1872 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1876 // draw the active tab again so it stands in the foreground
1877 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1879 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1881 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1883 rect
.x
= active_offset
;
1888 tab_button
.cur_state
,
1895 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1896 m_rect
.GetWidth(), m_rect
.GetHeight(),
1900 // Is the tab visible?
1901 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1903 if (!dc
|| !dc
->IsOk())
1907 size_t page_count
= m_pages
.GetCount();
1908 size_t button_count
= m_buttons
.GetCount();
1910 // Hasn't been rendered yet; assume it's visible
1911 if (m_tab_close_buttons
.GetCount() < page_count
)
1914 // First check if both buttons are disabled - if so, there's no need to
1915 // check further for visibility.
1916 int arrowButtonVisibleCount
= 0;
1917 for (i
= 0; i
< button_count
; ++i
)
1919 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1920 if (button
.id
== wxAUI_BUTTON_LEFT
||
1921 button
.id
== wxAUI_BUTTON_RIGHT
)
1923 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1924 arrowButtonVisibleCount
++;
1928 // Tab must be visible
1929 if (arrowButtonVisibleCount
== 0)
1932 // If tab is less than the given offset, it must be invisible by definition
1933 if (tabPage
< tabOffset
)
1937 int left_buttons_width
= 0;
1938 int right_buttons_width
= 0;
1942 // calculate size of the buttons on the right side
1943 offset
= m_rect
.x
+ m_rect
.width
;
1944 for (i
= 0; i
< button_count
; ++i
)
1946 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1948 if (button
.location
!= wxRIGHT
)
1950 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1953 offset
-= button
.rect
.GetWidth();
1954 right_buttons_width
+= button
.rect
.GetWidth();
1959 // calculate size of the buttons on the left side
1960 for (i
= 0; i
< button_count
; ++i
)
1962 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1964 if (button
.location
!= wxLEFT
)
1966 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1969 offset
+= button
.rect
.GetWidth();
1970 left_buttons_width
+= button
.rect
.GetWidth();
1973 offset
= left_buttons_width
;
1976 offset
+= m_art
->GetIndentSize();
1980 wxRect rect
= m_rect
;
1982 rect
.height
= m_rect
.height
;
1984 // See if the given page is visible at the given tab offset (effectively scroll position)
1985 for (i
= tabOffset
; i
< page_count
; ++i
)
1987 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1988 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1991 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1993 if (rect
.width
<= 0)
1994 return false; // haven't found the tab, and we've run out of space, so return false
1997 wxSize size
= m_art
->GetTabSize(*dc
,
2002 tab_button
.cur_state
,
2007 if (i
== (size_t) tabPage
)
2009 // If not all of the tab is visible, and supposing there's space to display it all,
2010 // we could do better so we return false.
2011 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
2018 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
2019 // further looping in calling code.
2023 // Make the tab visible if it wasn't already
2024 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
2027 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2030 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2032 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2042 // TabHitTest() tests if a tab was hit, passing the window pointer
2043 // back if that condition was fulfilled. The function returns
2044 // true if a tab was hit, otherwise false
2045 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2047 if (!m_rect
.Contains(x
,y
))
2050 wxAuiTabContainerButton
* btn
= NULL
;
2051 if (ButtonHitTest(x
, y
, &btn
))
2053 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2057 size_t i
, page_count
= m_pages
.GetCount();
2059 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2061 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2062 if (page
.rect
.Contains(x
,y
))
2073 // ButtonHitTest() tests if a button was hit. The function returns
2074 // true if a button was hit, otherwise false
2075 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2076 wxAuiTabContainerButton
** hit
) const
2078 if (!m_rect
.Contains(x
,y
))
2081 size_t i
, button_count
;
2084 button_count
= m_buttons
.GetCount();
2085 for (i
= 0; i
< button_count
; ++i
)
2087 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2088 if (button
.rect
.Contains(x
,y
) &&
2089 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2090 wxAUI_BUTTON_STATE_DISABLED
)))
2098 button_count
= m_tab_close_buttons
.GetCount();
2099 for (i
= 0; i
< button_count
; ++i
)
2101 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2102 if (button
.rect
.Contains(x
,y
) &&
2103 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2104 wxAUI_BUTTON_STATE_DISABLED
)))
2117 // the utility function ShowWnd() is the same as show,
2118 // except it handles wxAuiMDIChildFrame windows as well,
2119 // as the Show() method on this class is "unplugged"
2120 static void ShowWnd(wxWindow
* wnd
, bool show
)
2123 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2125 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2136 // DoShowHide() this function shows the active window, then
2137 // hides all of the other windows (in that order)
2138 void wxAuiTabContainer::DoShowHide()
2140 wxAuiNotebookPageArray
& pages
= GetPages();
2141 size_t i
, page_count
= pages
.GetCount();
2143 // show new active page first
2144 for (i
= 0; i
< page_count
; ++i
)
2146 wxAuiNotebookPage
& page
= pages
.Item(i
);
2149 ShowWnd(page
.window
, true);
2154 // hide all other pages
2155 for (i
= 0; i
< page_count
; ++i
)
2157 wxAuiNotebookPage
& page
= pages
.Item(i
);
2159 ShowWnd(page
.window
, false);
2168 // -- wxAuiTabCtrl class implementation --
2172 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2173 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2174 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2175 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2176 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2177 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick
)
2178 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2179 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2180 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2181 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2182 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2183 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2184 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2185 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2186 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2187 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2188 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2192 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2196 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2198 SetName(wxT("wxAuiTabCtrl"));
2199 m_click_pt
= wxDefaultPosition
;
2200 m_is_dragging
= false;
2201 m_hover_button
= NULL
;
2202 m_pressed_button
= NULL
;
2205 wxAuiTabCtrl::~wxAuiTabCtrl()
2209 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2213 dc
.SetFont(GetFont());
2215 if (GetPageCount() > 0)
2219 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2223 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2225 wxSize s
= evt
.GetSize();
2226 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2230 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2233 m_click_pt
= wxDefaultPosition
;
2234 m_is_dragging
= false;
2236 m_pressed_button
= NULL
;
2240 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2242 int new_selection
= GetIdxFromWindow(wnd
);
2244 // wxAuiNotebooks always want to receive this event
2245 // even if the tab is already active, because they may
2246 // have multiple tab controls
2247 if (new_selection
!= GetActivePage() ||
2248 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2250 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2251 e
.SetSelection(new_selection
);
2252 e
.SetOldSelection(GetActivePage());
2253 e
.SetEventObject(this);
2254 GetEventHandler()->ProcessEvent(e
);
2257 m_click_pt
.x
= evt
.m_x
;
2258 m_click_pt
.y
= evt
.m_y
;
2264 m_pressed_button
= m_hover_button
;
2265 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2271 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2273 if (GetCapture() == this)
2278 m_is_dragging
= false;
2280 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2281 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2282 evt
.SetOldSelection(evt
.GetSelection());
2283 evt
.SetEventObject(this);
2284 GetEventHandler()->ProcessEvent(evt
);
2289 if (m_pressed_button
)
2291 // make sure we're still clicking the button
2292 wxAuiTabContainerButton
* button
= NULL
;
2293 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2296 if (button
!= m_pressed_button
)
2298 m_pressed_button
= NULL
;
2305 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2307 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2308 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2309 evt
.SetInt(m_pressed_button
->id
);
2310 evt
.SetEventObject(this);
2311 GetEventHandler()->ProcessEvent(evt
);
2314 m_pressed_button
= NULL
;
2317 m_click_pt
= wxDefaultPosition
;
2318 m_is_dragging
= false;
2322 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2324 wxWindow
* wnd
= NULL
;
2325 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2328 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2329 e
.SetEventObject(this);
2330 e
.SetSelection(GetIdxFromWindow(wnd
));
2331 GetEventHandler()->ProcessEvent(e
);
2334 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2336 wxWindow
* wnd
= NULL
;
2337 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2340 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2341 e
.SetEventObject(this);
2342 e
.SetSelection(GetIdxFromWindow(wnd
));
2343 GetEventHandler()->ProcessEvent(e
);
2346 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2348 wxWindow
* wnd
= NULL
;
2349 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2352 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2353 e
.SetEventObject(this);
2354 e
.SetSelection(GetIdxFromWindow(wnd
));
2355 GetEventHandler()->ProcessEvent(e
);
2358 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2360 wxWindow
* wnd
= NULL
;
2361 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2364 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2365 e
.SetEventObject(this);
2366 e
.SetSelection(GetIdxFromWindow(wnd
));
2367 GetEventHandler()->ProcessEvent(e
);
2370 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent
& evt
)
2373 wxAuiTabContainerButton
* button
;
2374 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
) && !ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2376 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
2377 e
.SetEventObject(this);
2378 GetEventHandler()->ProcessEvent(e
);
2382 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2384 wxPoint pos
= evt
.GetPosition();
2386 // check if the mouse is hovering above a button
2387 wxAuiTabContainerButton
* button
;
2388 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2390 if (m_hover_button
&& button
!= m_hover_button
)
2392 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2393 m_hover_button
= NULL
;
2398 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2400 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2403 m_hover_button
= button
;
2411 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2412 m_hover_button
= NULL
;
2419 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2424 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2425 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2426 evt
.SetOldSelection(evt
.GetSelection());
2427 evt
.SetEventObject(this);
2428 GetEventHandler()->ProcessEvent(evt
);
2433 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2434 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2436 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2437 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2439 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2440 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2441 evt
.SetOldSelection(evt
.GetSelection());
2442 evt
.SetEventObject(this);
2443 GetEventHandler()->ProcessEvent(evt
);
2445 m_is_dragging
= true;
2449 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2453 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2454 m_hover_button
= NULL
;
2460 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2462 int button
= event
.GetInt();
2464 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2466 if (button
== wxAUI_BUTTON_LEFT
)
2468 if (GetTabOffset() > 0)
2470 SetTabOffset(GetTabOffset()-1);
2477 SetTabOffset(GetTabOffset()+1);
2482 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2484 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2488 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2489 e
.SetSelection(idx
);
2490 e
.SetOldSelection(GetActivePage());
2491 e
.SetEventObject(this);
2492 GetEventHandler()->ProcessEvent(e
);
2501 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2506 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2511 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2513 if (GetActivePage() == -1)
2519 // We can't leave tab processing to the system; on Windows, tabs and keys
2520 // get eaten by the system and not processed properly if we specify both
2521 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2522 // we don't key arrow key events.
2524 int key
= event
.GetKeyCode();
2526 if (key
== WXK_NUMPAD_PAGEUP
)
2528 if (key
== WXK_NUMPAD_PAGEDOWN
)
2530 if (key
== WXK_NUMPAD_HOME
)
2532 if (key
== WXK_NUMPAD_END
)
2534 if (key
== WXK_NUMPAD_LEFT
)
2536 if (key
== WXK_NUMPAD_RIGHT
)
2539 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2541 bool bCtrlDown
= event
.ControlDown();
2542 bool bShiftDown
= event
.ShiftDown();
2544 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2545 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2546 bool bFromTab
= (key
== WXK_TAB
);
2548 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2555 wxNavigationKeyEvent keyEvent
;
2556 keyEvent
.SetDirection(bForward
);
2557 keyEvent
.SetWindowChange(bWindowChange
);
2558 keyEvent
.SetFromTab(bFromTab
);
2559 keyEvent
.SetEventObject(nb
);
2561 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2563 // Not processed? Do an explicit tab into the page.
2564 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2571 if (m_pages
.GetCount() < 2)
2579 if (key
== WXK_RIGHT
)
2581 if (m_pages
.GetCount() > 1)
2583 if (GetActivePage() == -1)
2585 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2586 newPage
= GetActivePage() + 1;
2589 else if (key
== WXK_LEFT
)
2591 if (m_pages
.GetCount() > 1)
2593 if (GetActivePage() == -1)
2594 newPage
= (int) (m_pages
.GetCount() - 1);
2595 else if (GetActivePage() > 0)
2596 newPage
= GetActivePage() - 1;
2599 else if (key
== WXK_HOME
)
2603 else if (key
== WXK_END
)
2605 newPage
= (int) (m_pages
.GetCount() - 1);
2612 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2613 e
.SetSelection(newPage
);
2614 e
.SetOldSelection(newPage
);
2615 e
.SetEventObject(this);
2616 this->GetEventHandler()->ProcessEvent(e
);
2622 // wxTabFrame is an interesting case. It's important that all child pages
2623 // of the multi-notebook control are all actually children of that control
2624 // (and not grandchildren). wxTabFrame facilitates this. There is one
2625 // instance of wxTabFrame for each tab control inside the multi-notebook.
2626 // It's important to know that wxTabFrame is not a real window, but it merely
2627 // used to capture the dimensions/positioning of the internal tab control and
2628 // it's managed page windows
2630 class wxTabFrame
: public wxWindow
2637 m_rect
= wxRect(0,0,200,200);
2638 m_tab_ctrl_height
= 20;
2646 void SetTabCtrlHeight(int h
)
2648 m_tab_ctrl_height
= h
;
2652 void DoSetSize(int x
, int y
,
2653 int width
, int height
,
2654 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2656 m_rect
= wxRect(x
, y
, width
, height
);
2660 void DoGetClientSize(int* x
, int* y
) const
2667 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2674 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2675 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2677 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2678 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
+ m_rect
.height
- m_tab_ctrl_height
, m_rect
.width
, m_tab_ctrl_height
);
2679 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2681 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2683 m_tab_rect
= wxRect (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2684 m_tabs
->SetSize (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2685 m_tabs
->SetRect (wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2687 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2688 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2693 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2694 size_t i
, page_count
= pages
.GetCount();
2696 for (i
= 0; i
< page_count
; ++i
)
2698 wxAuiNotebookPage
& page
= pages
.Item(i
);
2699 if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
)
2701 page
.window
->SetSize(m_rect
.x
, m_rect
.y
,
2702 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2704 else //TODO: if (GetFlags() & wxAUI_NB_TOP)
2706 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2707 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2709 // TODO: else if (GetFlags() & wxAUI_NB_LEFT){}
2710 // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){}
2713 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2715 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2716 wnd
->ApplyMDIChildFrameRect();
2723 void DoGetSize(int* x
, int* y
) const
2726 *x
= m_rect
.GetWidth();
2728 *y
= m_rect
.GetHeight();
2739 wxAuiTabCtrl
* m_tabs
;
2740 int m_tab_ctrl_height
;
2744 const int wxAuiBaseTabCtrlId
= 5380;
2747 // -- wxAuiNotebook class implementation --
2749 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2750 EVT_SIZE(wxAuiNotebook::OnSize
)
2751 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2752 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2753 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2754 wxAuiNotebook::OnTabClicked
)
2755 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2756 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2757 wxAuiNotebook::OnTabBeginDrag
)
2758 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2759 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2760 wxAuiNotebook::OnTabEndDrag
)
2761 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2762 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2763 wxAuiNotebook::OnTabDragMotion
)
2764 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2765 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2766 wxAuiNotebook::OnTabButton
)
2767 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2768 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2769 wxAuiNotebook::OnTabMiddleDown
)
2770 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2771 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2772 wxAuiNotebook::OnTabMiddleUp
)
2773 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2774 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2775 wxAuiNotebook::OnTabRightDown
)
2776 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2777 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2778 wxAuiNotebook::OnTabRightUp
)
2779 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2780 wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
,
2781 wxAuiNotebook::OnTabBgDClick
)
2782 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2784 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2785 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2787 // Avoid clash with container event handler functions
2788 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2792 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2794 wxAuiNotebook::wxAuiNotebook()
2797 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2799 m_tab_ctrl_height
= 20;
2800 m_requested_bmp_size
= wxDefaultSize
;
2801 m_requested_tabctrl_height
= -1;
2804 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2808 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2811 m_requested_bmp_size
= wxDefaultSize
;
2812 m_requested_tabctrl_height
= -1;
2813 InitNotebook(style
);
2816 bool wxAuiNotebook::Create(wxWindow
* parent
,
2822 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2825 InitNotebook(style
);
2830 // InitNotebook() contains common initialization
2831 // code called by all constructors
2832 void wxAuiNotebook::InitNotebook(long style
)
2834 WX_INIT_CONTROL_CONTAINER();
2835 // SetCanFocus(false);
2837 SetName(wxT("wxAuiNotebook"));
2839 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2841 m_flags
= (unsigned int)style
;
2842 m_tab_ctrl_height
= 20;
2844 m_normal_font
= *wxNORMAL_FONT
;
2845 m_selected_font
= *wxNORMAL_FONT
;
2846 m_selected_font
.SetWeight(wxBOLD
);
2848 SetArtProvider(new wxAuiDefaultTabArt
);
2850 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2851 m_dummy_wnd
->SetSize(200, 200);
2852 m_dummy_wnd
->Show(false);
2854 m_mgr
.SetManagedWindow(this);
2855 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2856 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2858 m_mgr
.AddPane(m_dummy_wnd
,
2859 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2864 wxAuiNotebook::~wxAuiNotebook()
2866 // Indicate we're deleting pages
2867 m_isBeingDeleted
= true;
2869 while ( GetPageCount() > 0 )
2875 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2877 m_tabs
.SetArtProvider(art
);
2879 UpdateTabCtrlHeight();
2882 // SetTabCtrlHeight() is the highest-level override of the
2883 // tab height. A call to this function effectively enforces a
2884 // specified tab ctrl height, overriding all other considerations,
2885 // such as text or bitmap height. It overrides any call to
2886 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2887 // any previous call and returns to the default behavior
2889 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2891 m_requested_tabctrl_height
= height
;
2893 // if window is already initialized, recalculate the tab height
2896 UpdateTabCtrlHeight();
2901 // SetUniformBitmapSize() ensures that all tabs will have
2902 // the same height, even if some tabs don't have bitmaps
2903 // Passing wxDefaultSize to this function will instruct
2904 // the control to use dynamic tab height-- so when a tab
2905 // with a large bitmap is added, the tab ctrl's height will
2906 // automatically increase to accommodate the bitmap
2908 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2910 m_requested_bmp_size
= size
;
2912 // if window is already initialized, recalculate the tab height
2915 UpdateTabCtrlHeight();
2919 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2920 // to be used interally
2921 void wxAuiNotebook::UpdateTabCtrlHeight()
2923 // get the tab ctrl height we will use
2924 int height
= CalculateTabCtrlHeight();
2926 // if the tab control height needs to change, update
2927 // all of our tab controls with the new height
2928 if (m_tab_ctrl_height
!= height
)
2930 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2932 m_tab_ctrl_height
= height
;
2934 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2935 size_t i
, pane_count
= all_panes
.GetCount();
2936 for (i
= 0; i
< pane_count
; ++i
)
2938 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2939 if (pane
.name
== wxT("dummy"))
2941 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2942 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2943 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2944 tabctrl
->SetArtProvider(art
->Clone());
2945 tab_frame
->DoSizing();
2950 void wxAuiNotebook::UpdateHintWindowSize()
2952 wxSize size
= CalculateNewSplitSize();
2954 // the placeholder hint window should be set to this size
2955 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2959 info
.BestSize(size
);
2960 m_dummy_wnd
->SetSize(size
);
2965 // calculates the size of the new split
2966 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2968 // count number of tab controls
2969 int tab_ctrl_count
= 0;
2970 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2971 size_t i
, pane_count
= all_panes
.GetCount();
2972 for (i
= 0; i
< pane_count
; ++i
)
2974 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2975 if (pane
.name
== wxT("dummy"))
2980 wxSize new_split_size
;
2982 // if there is only one tab control, the first split
2983 // should happen around the middle
2984 if (tab_ctrl_count
< 2)
2986 new_split_size
= GetClientSize();
2987 new_split_size
.x
/= 2;
2988 new_split_size
.y
/= 2;
2992 // this is in place of a more complicated calculation
2993 // that needs to be implemented
2994 new_split_size
= wxSize(180,180);
2997 return new_split_size
;
3000 int wxAuiNotebook::CalculateTabCtrlHeight()
3002 // if a fixed tab ctrl height is specified,
3003 // just return that instead of calculating a
3005 if (m_requested_tabctrl_height
!= -1)
3006 return m_requested_tabctrl_height
;
3008 // find out new best tab height
3009 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
3011 return art
->GetBestTabCtrlSize(this,
3013 m_requested_bmp_size
);
3017 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
3019 return m_tabs
.GetArtProvider();
3022 void wxAuiNotebook::SetWindowStyleFlag(long style
)
3024 wxControl::SetWindowStyleFlag(style
);
3026 m_flags
= (unsigned int)style
;
3028 // if the control is already initialized
3029 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
3031 // let all of the tab children know about the new style
3033 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3034 size_t i
, pane_count
= all_panes
.GetCount();
3035 for (i
= 0; i
< pane_count
; ++i
)
3037 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3038 if (pane
.name
== wxT("dummy"))
3040 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3041 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
3042 tabctrl
->SetFlags(m_flags
);
3043 tabframe
->DoSizing();
3051 bool wxAuiNotebook::AddPage(wxWindow
* page
,
3052 const wxString
& caption
,
3054 const wxBitmap
& bitmap
)
3056 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
3059 bool wxAuiNotebook::InsertPage(size_t page_idx
,
3061 const wxString
& caption
,
3063 const wxBitmap
& bitmap
)
3065 wxASSERT_MSG(page
, wxT("page pointer must be non-NULL"));
3069 page
->Reparent(this);
3071 wxAuiNotebookPage info
;
3073 info
.caption
= caption
;
3074 info
.bitmap
= bitmap
;
3075 info
.active
= false;
3077 // if there are currently no tabs, the first added
3078 // tab must be active
3079 if (m_tabs
.GetPageCount() == 0)
3082 m_tabs
.InsertPage(page
, info
, page_idx
);
3084 // if that was the first page added, even if
3085 // select is false, it must become the "current page"
3086 // (though no select events will be fired)
3087 if (!select
&& m_tabs
.GetPageCount() == 1)
3089 //m_curpage = GetPageIndex(page);
3091 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3092 if (page_idx
>= active_tabctrl
->GetPageCount())
3093 active_tabctrl
->AddPage(page
, info
);
3095 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3097 UpdateTabCtrlHeight();
3099 active_tabctrl
->DoShowHide();
3101 // adjust selected index
3102 if(m_curpage
>= (int) page_idx
)
3107 SetSelectionToWindow(page
);
3114 // DeletePage() removes a tab from the multi-notebook,
3115 // and destroys the window as well
3116 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3118 if (page_idx
>= m_tabs
.GetPageCount())
3121 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3123 // hide the window in advance, as this will
3125 ShowWnd(wnd
, false);
3127 if (!RemovePage(page_idx
))
3131 // actually destroy the window now
3132 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3134 // delete the child frame with pending delete, as is
3135 // customary with frame windows
3136 if (!wxPendingDelete
.Member(wnd
))
3137 wxPendingDelete
.Append(wnd
);
3150 // RemovePage() removes a tab from the multi-notebook,
3151 // but does not destroy the window
3152 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3154 // save active window pointer
3155 wxWindow
* active_wnd
= NULL
;
3157 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3159 // save pointer of window being deleted
3160 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3161 wxWindow
* new_active
= NULL
;
3163 // make sure we found the page
3167 // find out which onscreen tab ctrl owns this tab
3170 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3173 bool is_curpage
= (m_curpage
== (int)page_idx
);
3174 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3177 // remove the tab from main catalog
3178 if (!m_tabs
.RemovePage(wnd
))
3181 // remove the tab from the onscreen tab ctrl
3182 ctrl
->RemovePage(wnd
);
3184 if (is_active_in_split
)
3186 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3188 if (ctrl_idx
>= ctrl_new_page_count
)
3189 ctrl_idx
= ctrl_new_page_count
-1;
3191 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3193 // set new page as active in the tab split
3194 ctrl
->SetActivePage(ctrl_idx
);
3196 // if the page deleted was the current page for the
3197 // entire tab control, then record the window
3198 // pointer of the new active page for activation
3201 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3207 // we are not deleting the active page, so keep it the same
3208 new_active
= active_wnd
;
3214 // we haven't yet found a new page to active,
3215 // so select the next page from the main tab
3218 if (page_idx
< m_tabs
.GetPageCount())
3220 new_active
= m_tabs
.GetPage(page_idx
).window
;
3223 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3225 new_active
= m_tabs
.GetPage(0).window
;
3230 RemoveEmptyTabFrames();
3232 // set new active pane
3233 if (new_active
&& !m_isBeingDeleted
)
3236 SetSelectionToWindow(new_active
);
3242 // GetPageIndex() returns the index of the page, or -1 if the
3243 // page could not be located in the notebook
3244 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3246 return m_tabs
.GetIdxFromWindow(page_wnd
);
3251 // SetPageText() changes the tab caption of the specified page
3252 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3254 if (page_idx
>= m_tabs
.GetPageCount())
3257 // update our own tab catalog
3258 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3259 page_info
.caption
= text
;
3261 // update what's on screen
3264 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3266 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3267 info
.caption
= text
;
3275 // returns the page caption
3276 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3278 if (page_idx
>= m_tabs
.GetPageCount())
3279 return wxEmptyString
;
3281 // update our own tab catalog
3282 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3283 return page_info
.caption
;
3286 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3288 if (page_idx
>= m_tabs
.GetPageCount())
3291 // update our own tab catalog
3292 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3293 page_info
.bitmap
= bitmap
;
3295 // tab height might have changed
3296 UpdateTabCtrlHeight();
3298 // update what's on screen
3301 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3303 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3304 info
.bitmap
= bitmap
;
3312 // returns the page bitmap
3313 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3315 if (page_idx
>= m_tabs
.GetPageCount())
3318 // update our own tab catalog
3319 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3320 return page_info
.bitmap
;
3323 // GetSelection() returns the index of the currently active page
3324 int wxAuiNotebook::GetSelection() const
3329 // SetSelection() sets the currently active page
3330 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3332 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3336 // don't change the page unless necessary;
3337 // however, clicking again on a tab should give it the focus.
3338 if ((int)new_page
== m_curpage
)
3342 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3344 if (FindFocus() != ctrl
)
3350 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3351 evt
.SetSelection(new_page
);
3352 evt
.SetOldSelection(m_curpage
);
3353 evt
.SetEventObject(this);
3354 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3356 int old_curpage
= m_curpage
;
3357 m_curpage
= new_page
;
3359 // program allows the page change
3360 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3361 (void)GetEventHandler()->ProcessEvent(evt
);
3366 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3368 m_tabs
.SetActivePage(wnd
);
3370 ctrl
->SetActivePage(ctrl_idx
);
3374 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3377 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3378 size_t i
, pane_count
= all_panes
.GetCount();
3379 for (i
= 0; i
< pane_count
; ++i
)
3381 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3382 if (pane
.name
== wxT("dummy"))
3384 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3385 if (tabctrl
!= ctrl
)
3386 tabctrl
->SetSelectedFont(m_normal_font
);
3388 tabctrl
->SetSelectedFont(m_selected_font
);
3392 // Set the focus to the page if we're not currently focused on the tab.
3393 // This is Firefox-like behaviour.
3394 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3404 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3406 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3407 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
3412 // GetPageCount() returns the total number of
3413 // pages managed by the multi-notebook
3414 size_t wxAuiNotebook::GetPageCount() const
3416 return m_tabs
.GetPageCount();
3419 // GetPage() returns the wxWindow pointer of the
3421 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3423 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3425 return m_tabs
.GetWindowFromIdx(page_idx
);
3428 // DoSizing() performs all sizing operations in each tab control
3429 void wxAuiNotebook::DoSizing()
3431 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3432 size_t i
, pane_count
= all_panes
.GetCount();
3433 for (i
= 0; i
< pane_count
; ++i
)
3435 if (all_panes
.Item(i
).name
== wxT("dummy"))
3438 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3439 tabframe
->DoSizing();
3443 // GetActiveTabCtrl() returns the active tab control. It is
3444 // called to determine which control gets new windows being added
3445 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3447 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3452 // find the tab ctrl with the current page
3453 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3460 // no current page, just find the first tab ctrl
3461 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3462 size_t i
, pane_count
= all_panes
.GetCount();
3463 for (i
= 0; i
< pane_count
; ++i
)
3465 if (all_panes
.Item(i
).name
== wxT("dummy"))
3468 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3469 return tabframe
->m_tabs
;
3472 // If there is no tabframe at all, create one
3473 wxTabFrame
* tabframe
= new wxTabFrame
;
3474 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3475 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3479 wxNO_BORDER
|wxWANTS_CHARS
);
3480 tabframe
->m_tabs
->SetFlags(m_flags
);
3481 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3482 m_mgr
.AddPane(tabframe
,
3483 wxAuiPaneInfo().Center().CaptionVisible(false));
3487 return tabframe
->m_tabs
;
3490 // FindTab() finds the tab control that currently contains the window as well
3491 // as the index of the window in the tab control. It returns true if the
3492 // window was found, otherwise false.
3493 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3495 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3496 size_t i
, pane_count
= all_panes
.GetCount();
3497 for (i
= 0; i
< pane_count
; ++i
)
3499 if (all_panes
.Item(i
).name
== wxT("dummy"))
3502 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3504 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3507 *ctrl
= tabframe
->m_tabs
;
3516 void wxAuiNotebook::Split(size_t page
, int direction
)
3518 wxSize cli_size
= GetClientSize();
3520 // get the page's window pointer
3521 wxWindow
* wnd
= GetPage(page
);
3525 // notebooks with 1 or less pages can't be split
3526 if (GetPageCount() < 2)
3529 // find out which tab control the page currently belongs to
3530 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3533 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3535 if (!src_tabs
|| src_idx
== -1)
3538 // choose a split size
3540 if (GetPageCount() > 2)
3542 split_size
= CalculateNewSplitSize();
3546 // because there are two panes, always split them
3548 split_size
= GetClientSize();
3554 // create a new tab frame
3555 wxTabFrame
* new_tabs
= new wxTabFrame
;
3556 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3557 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3558 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3562 wxNO_BORDER
|wxWANTS_CHARS
);
3563 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3564 new_tabs
->m_tabs
->SetFlags(m_flags
);
3565 dest_tabs
= new_tabs
->m_tabs
;
3567 // create a pane info structure with the information
3568 // about where the pane should be added
3569 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3572 if (direction
== wxLEFT
)
3575 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3577 else if (direction
== wxRIGHT
)
3580 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3582 else if (direction
== wxTOP
)
3585 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3587 else if (direction
== wxBOTTOM
)
3590 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3593 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3596 // remove the page from the source tabs
3597 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3598 page_info
.active
= false;
3599 src_tabs
->RemovePage(page_info
.window
);
3600 if (src_tabs
->GetPageCount() > 0)
3602 src_tabs
->SetActivePage((size_t)0);
3603 src_tabs
->DoShowHide();
3604 src_tabs
->Refresh();
3608 // add the page to the destination tabs
3609 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3611 if (src_tabs
->GetPageCount() == 0)
3613 RemoveEmptyTabFrames();
3617 dest_tabs
->DoShowHide();
3618 dest_tabs
->Refresh();
3620 // force the set selection function reset the selection
3623 // set the active page to the one we just split off
3624 SetSelectionToPage(page_info
);
3626 UpdateHintWindowSize();
3630 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3632 UpdateHintWindowSize();
3637 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3639 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3641 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3642 wxASSERT(ctrl
!= NULL
);
3644 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3645 wxASSERT(wnd
!= NULL
);
3647 SetSelectionToWindow(wnd
);
3650 void wxAuiNotebook::OnTabBgDClick(wxCommandEvent
& WXUNUSED(evt
))
3652 // notify owner that the tabbar background has been double-clicked
3653 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK
, m_windowId
);
3654 e
.SetEventObject(this);
3655 GetEventHandler()->ProcessEvent(e
);
3658 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3663 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3665 wxPoint screen_pt
= ::wxGetMousePosition();
3666 wxPoint client_pt
= ScreenToClient(screen_pt
);
3669 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3670 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3672 if (dest_tabs
== src_tabs
)
3676 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3679 // always hide the hint for inner-tabctrl drag
3682 // if tab moving is not allowed, leave
3683 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3688 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3689 wxWindow
* dest_location_tab
;
3691 // this is an inner-tab drag/reposition
3692 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3694 int src_idx
= evt
.GetSelection();
3695 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3697 // prevent jumpy drag
3698 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3699 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3700 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3702 m_last_drag_x
= pt
.x
;
3707 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3708 dest_tabs
->MovePage(src_tab
, dest_idx
);
3709 dest_tabs
->SetActivePage((size_t)dest_idx
);
3710 dest_tabs
->DoShowHide();
3711 dest_tabs
->Refresh();
3712 m_last_drag_x
= pt
.x
;
3720 // if external drag is allowed, check if the tab is being dragged
3721 // over a different wxAuiNotebook control
3722 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3724 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3726 // if we aren't over any window, stop here
3730 // make sure we are not over the hint window
3731 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3735 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3737 tab_ctrl
= tab_ctrl
->GetParent();
3742 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3746 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3747 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3748 m_mgr
.ShowHint(hint_rect
);
3757 // we are either over a hint window, or not over a tab
3758 // window, and there is no where to drag to, so exit
3765 // if there are less than two panes, split can't happen, so leave
3766 if (m_tabs
.GetPageCount() < 2)
3769 // if tab moving is not allowed, leave
3770 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3776 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3782 wxRect hint_rect
= dest_tabs
->GetRect();
3783 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3784 m_mgr
.ShowHint(hint_rect
);
3788 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3794 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3796 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3801 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3802 wxCHECK_RET( src_tabs
, _T("no source object?") );
3804 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3806 // get the mouse position, which will be used to determine the drop point
3807 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3808 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3812 // check for an external move
3813 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3815 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3819 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3821 tab_ctrl
= tab_ctrl
->GetParent();
3826 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3830 // find out from the destination control
3831 // if it's ok to drop this tab here
3832 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3833 e
.SetSelection(evt
.GetSelection());
3834 e
.SetOldSelection(evt
.GetSelection());
3835 e
.SetEventObject(this);
3836 e
.SetDragSource(this);
3837 e
.Veto(); // dropping must be explicitly approved by control owner
3839 nb
->GetEventHandler()->ProcessEvent(e
);
3843 // no answer or negative answer
3849 int src_idx
= evt
.GetSelection();
3850 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3852 // Check that it's not an impossible parent relationship
3854 while (p
&& !p
->IsTopLevel())
3863 // get main index of the page
3864 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3865 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3868 // make a copy of the page info
3869 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3871 // remove the page from the source notebook
3872 RemovePage(main_idx
);
3874 // reparent the page
3875 src_page
->Reparent(nb
);
3878 // found out the insert idx
3879 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3880 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3882 wxWindow
* target
= NULL
;
3883 int insert_idx
= -1;
3884 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3887 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3891 // add the page to the new notebook
3892 if (insert_idx
== -1)
3893 insert_idx
= dest_tabs
->GetPageCount();
3894 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3895 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3898 dest_tabs
->DoShowHide();
3899 dest_tabs
->Refresh();
3901 // set the selection in the destination tab control
3902 nb
->SetSelectionToPage(page_info
);
3904 // notify owner that the tab has been dragged
3905 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3906 e2
.SetSelection(evt
.GetSelection());
3907 e2
.SetOldSelection(evt
.GetSelection());
3908 e2
.SetEventObject(this);
3909 GetEventHandler()->ProcessEvent(e2
);
3919 // only perform a tab split if it's allowed
3920 wxAuiTabCtrl
* dest_tabs
= NULL
;
3922 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3924 // If the pointer is in an existing tab frame, do a tab insert
3925 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3926 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3927 int insert_idx
= -1;
3930 dest_tabs
= tab_frame
->m_tabs
;
3932 if (dest_tabs
== src_tabs
)
3936 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3937 wxWindow
* target
= NULL
;
3938 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3941 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3947 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3952 // there is no suitable drop location here, exit out
3956 // If there is no tabframe at all, create one
3957 wxTabFrame
* new_tabs
= new wxTabFrame
;
3958 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3959 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3960 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3964 wxNO_BORDER
|wxWANTS_CHARS
);
3965 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3966 new_tabs
->m_tabs
->SetFlags(m_flags
);
3968 m_mgr
.AddPane(new_tabs
,
3969 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3972 dest_tabs
= new_tabs
->m_tabs
;
3977 // remove the page from the source tabs
3978 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3979 page_info
.active
= false;
3980 src_tabs
->RemovePage(page_info
.window
);
3981 if (src_tabs
->GetPageCount() > 0)
3983 src_tabs
->SetActivePage((size_t)0);
3984 src_tabs
->DoShowHide();
3985 src_tabs
->Refresh();
3990 // add the page to the destination tabs
3991 if (insert_idx
== -1)
3992 insert_idx
= dest_tabs
->GetPageCount();
3993 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3995 if (src_tabs
->GetPageCount() == 0)
3997 RemoveEmptyTabFrames();
4001 dest_tabs
->DoShowHide();
4002 dest_tabs
->Refresh();
4004 // force the set selection function reset the selection
4007 // set the active page to the one we just split off
4008 SetSelectionToPage(page_info
);
4010 UpdateHintWindowSize();
4013 // notify owner that the tab has been dragged
4014 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
4015 e
.SetSelection(evt
.GetSelection());
4016 e
.SetOldSelection(evt
.GetSelection());
4017 e
.SetEventObject(this);
4018 GetEventHandler()->ProcessEvent(e
);
4023 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
4025 // if we've just removed the last tab from the source
4026 // tab set, the remove the tab control completely
4027 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4028 size_t i
, pane_count
= all_panes
.GetCount();
4029 for (i
= 0; i
< pane_count
; ++i
)
4031 if (all_panes
.Item(i
).name
== wxT("dummy"))
4034 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4035 if (tabframe
->m_tab_rect
.Contains(pt
))
4036 return tabframe
->m_tabs
;
4042 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
4044 // if we've just removed the last tab from the source
4045 // tab set, the remove the tab control completely
4046 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4047 size_t i
, pane_count
= all_panes
.GetCount();
4048 for (i
= 0; i
< pane_count
; ++i
)
4050 if (all_panes
.Item(i
).name
== wxT("dummy"))
4053 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4054 if (tabframe
->m_tabs
== tab_ctrl
)
4063 void wxAuiNotebook::RemoveEmptyTabFrames()
4065 // if we've just removed the last tab from the source
4066 // tab set, the remove the tab control completely
4067 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
4068 size_t i
, pane_count
= all_panes
.GetCount();
4069 for (i
= 0; i
< pane_count
; ++i
)
4071 if (all_panes
.Item(i
).name
== wxT("dummy"))
4074 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
4075 if (tab_frame
->m_tabs
->GetPageCount() == 0)
4077 m_mgr
.DetachPane(tab_frame
);
4079 // use pending delete because sometimes during
4080 // window closing, refreshs are pending
4081 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
4082 wxPendingDelete
.Append(tab_frame
->m_tabs
);
4084 tab_frame
->m_tabs
= NULL
;
4091 // check to see if there is still a center pane;
4092 // if there isn't, make a frame the center pane
4093 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4094 pane_count
= panes
.GetCount();
4095 wxWindow
* first_good
= NULL
;
4096 bool center_found
= false;
4097 for (i
= 0; i
< pane_count
; ++i
)
4099 if (panes
.Item(i
).name
== wxT("dummy"))
4101 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4102 center_found
= true;
4104 first_good
= panes
.Item(i
).window
;
4107 if (!center_found
&& first_good
)
4109 m_mgr
.GetPane(first_good
).Centre();
4112 if (!m_isBeingDeleted
)
4116 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4118 // if we're dragging a tab, don't change the current selection.
4119 // This code prevents a bug that used to happen when the hint window
4120 // was hidden. In the bug, the focus would return to the notebook
4121 // child, which would then enter this handler and call
4122 // SetSelection, which is not desired turn tab dragging.
4124 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4125 size_t i
, pane_count
= all_panes
.GetCount();
4126 for (i
= 0; i
< pane_count
; ++i
)
4128 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4129 if (pane
.name
== wxT("dummy"))
4131 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4132 if (tabframe
->m_tabs
->IsDragging())
4137 // change the tab selection to the child
4138 // which was focused
4139 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4140 if (idx
!= -1 && idx
!= m_curpage
)
4146 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4148 if ( event
.IsWindowChange() ) {
4150 // FIXME: the problem with this is that if we have a split notebook,
4151 // we selection may go all over the place.
4152 AdvanceSelection(event
.GetDirection());
4155 // we get this event in 3 cases
4157 // a) one of our pages might have generated it because the user TABbed
4158 // out from it in which case we should propagate the event upwards and
4159 // our parent will take care of setting the focus to prev/next sibling
4163 // b) the parent panel wants to give the focus to us so that we
4164 // forward it to our selected page. We can't deal with this in
4165 // OnSetFocus() because we don't know which direction the focus came
4166 // from in this case and so can't choose between setting the focus to
4167 // first or last panel child
4171 // c) we ourselves (see MSWTranslateMessage) generated the event
4173 wxWindow
* const parent
= GetParent();
4175 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4176 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4177 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4179 if ( isFromParent
|| isFromSelf
)
4181 // no, it doesn't come from child, case (b) or (c): forward to a
4182 // page but only if direction is backwards (TAB) or from ourselves,
4183 if ( GetSelection() != wxNOT_FOUND
&&
4184 (!event
.GetDirection() || isFromSelf
) )
4186 // so that the page knows that the event comes from it's parent
4187 // and is being propagated downwards
4188 event
.SetEventObject(this);
4190 wxWindow
*page
= GetPage(GetSelection());
4191 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4195 //else: page manages focus inside it itself
4197 else // otherwise set the focus to the notebook itself
4204 // it comes from our child, case (a), pass to the parent, but only
4205 // if the direction is forwards. Otherwise set the focus to the
4206 // notebook itself. The notebook is always the 'first' control of a
4208 if ( !event
.GetDirection() )
4214 event
.SetCurrentFocus(this);
4215 parent
->GetEventHandler()->ProcessEvent(event
);
4221 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
4223 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
4224 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4226 int button_id
= evt
.GetInt();
4228 if (button_id
== wxAUI_BUTTON_CLOSE
)
4230 int selection
= evt
.GetSelection();
4232 if (selection
== -1)
4234 // if the close button is to the right, use the active
4235 // page selection to determine which page to close
4236 selection
= GetSelection();
4239 if (selection
!= -1)
4241 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4243 // ask owner if it's ok to close the tab
4244 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4245 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4246 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4247 e
.SetSelection(idx
);
4248 e
.SetOldSelection(evt
.GetSelection());
4249 e
.SetEventObject(this);
4250 GetEventHandler()->ProcessEvent(e
);
4256 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4263 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4264 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
4266 DeletePage(main_idx
);
4269 // notify owner that the tab has been closed
4270 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4271 e2
.SetSelection(idx
);
4272 e2
.SetEventObject(this);
4273 GetEventHandler()->ProcessEvent(e2
);
4279 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
4281 // patch event through to owner
4282 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4283 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4285 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4286 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4287 e
.SetEventObject(this);
4288 GetEventHandler()->ProcessEvent(e
);
4291 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
4293 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4294 // click should act like a tab close action. However, first
4295 // give the owner an opportunity to handle the middle up event
4296 // for custom action
4298 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4299 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4301 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4302 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4303 e
.SetEventObject(this);
4304 if (GetEventHandler()->ProcessEvent(e
))
4309 // check if we are supposed to close on middle-up
4310 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4313 // simulate the user pressing the close button on the tab
4314 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4318 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
4320 // patch event through to owner
4321 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4322 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4324 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4325 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4326 e
.SetEventObject(this);
4327 GetEventHandler()->ProcessEvent(e
);
4330 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
4332 // patch event through to owner
4333 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4334 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4336 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4337 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4338 e
.SetEventObject(this);
4339 GetEventHandler()->ProcessEvent(e
);
4342 // Sets the normal font
4343 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4345 m_normal_font
= font
;
4346 GetArtProvider()->SetNormalFont(font
);
4349 // Sets the selected tab font
4350 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4352 m_selected_font
= font
;
4353 GetArtProvider()->SetSelectedFont(font
);
4356 // Sets the measuring font
4357 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4359 GetArtProvider()->SetMeasuringFont(font
);
4362 // Sets the tab font
4363 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4365 wxControl::SetFont(font
);
4367 wxFont
normalFont(font
);
4368 wxFont
selectedFont(normalFont
);
4369 selectedFont
.SetWeight(wxBOLD
);
4371 SetNormalFont(normalFont
);
4372 SetSelectedFont(selectedFont
);
4373 SetMeasuringFont(selectedFont
);
4378 // Gets the tab control height
4379 int wxAuiNotebook::GetTabCtrlHeight() const
4381 return m_tab_ctrl_height
;
4384 // Gets the height of the notebook for a given page height
4385 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4387 UpdateTabCtrlHeight();
4389 int tabCtrlHeight
= GetTabCtrlHeight();
4390 int decorHeight
= 2;
4391 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4394 // Advances the selection, generation page selection events
4395 void wxAuiNotebook::AdvanceSelection(bool forward
)
4397 if (GetPageCount() <= 1)
4400 int currentSelection
= GetSelection();
4404 if (currentSelection
== (int) (GetPageCount() - 1))
4406 else if (currentSelection
== -1)
4407 currentSelection
= 0;
4409 currentSelection
++;
4413 if (currentSelection
<= 0)
4416 currentSelection
--;
4419 SetSelection(currentSelection
);
4422 // Shows the window menu
4423 bool wxAuiNotebook::ShowWindowMenu()
4425 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4427 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4431 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4432 e
.SetSelection(idx
);
4433 e
.SetOldSelection(tabCtrl
->GetActivePage());
4434 e
.SetEventObject(tabCtrl
);
4435 GetEventHandler()->ProcessEvent(e
);