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_DRAG_DONE
)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
)
56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
)
57 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
)
59 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
60 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
61 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
67 // these functions live in dockart.cpp -- they'll eventually
68 // be moved to a new utility cpp file
70 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
72 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
73 const wxColour
& color
);
75 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
77 static void DrawButtons(wxDC
& dc
,
80 const wxColour
& bkcolour
,
85 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
91 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
92 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
94 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
95 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
97 // draw the background behind the button
98 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
101 // draw the button itself
102 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
105 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
107 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
116 // -- GUI helper classes and functions --
118 class wxAuiCommandCapture
: public wxEvtHandler
122 wxAuiCommandCapture() { m_last_id
= 0; }
123 int GetCommandId() const { return m_last_id
; }
125 bool ProcessEvent(wxEvent
& evt
)
127 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
129 m_last_id
= evt
.GetId();
133 if (GetNextHandler())
134 return GetNextHandler()->ProcessEvent(evt
);
146 #if defined( __WXMAC__ )
147 static unsigned char close_bits
[]={
148 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
149 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
150 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
151 #elif defined( __WXGTK__)
152 static unsigned char close_bits
[]={
153 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
154 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
155 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
157 static unsigned char close_bits
[]={
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
159 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
160 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
163 static unsigned char left_bits
[] = {
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
165 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
168 static unsigned char right_bits
[] = {
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
170 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
173 static unsigned char list_bits
[] = {
174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
175 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
183 // -- wxAuiDefaultTabArt class implementation --
185 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
187 m_normal_font
= *wxNORMAL_FONT
;
188 m_selected_font
= *wxNORMAL_FONT
;
189 m_selected_font
.SetWeight(wxBOLD
);
190 m_measuring_font
= m_selected_font
;
192 m_fixed_tab_width
= 100;
193 m_tab_ctrl_height
= 0;
196 wxBrush toolbarbrush
;
197 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
198 wxColor base_colour
= toolbarbrush
.GetColour();
200 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
203 // the base_colour is too pale to use as our base colour,
204 // so darken it a bit --
205 if ((255-base_colour
.Red()) +
206 (255-base_colour
.Green()) +
207 (255-base_colour
.Blue()) < 60)
209 base_colour
= wxAuiStepColour(base_colour
, 92);
212 m_base_colour
= base_colour
;
213 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
215 m_border_pen
= wxPen(border_colour
);
216 m_base_colour_pen
= wxPen(m_base_colour
);
217 m_base_colour_brush
= wxBrush(m_base_colour
);
219 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
220 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
222 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
223 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
225 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
226 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
228 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
229 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
234 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
238 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
240 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
241 art
->SetNormalFont(m_normal_font
);
242 art
->SetSelectedFont(m_selected_font
);
243 art
->SetMeasuringFont(m_measuring_font
);
248 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
253 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
256 m_fixed_tab_width
= 100;
258 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
260 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
261 tot_width
-= m_active_close_bmp
.GetWidth();
262 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
263 tot_width
-= m_active_windowlist_bmp
.GetWidth();
267 m_fixed_tab_width
= tot_width
/(int)tab_count
;
271 if (m_fixed_tab_width
< 100)
272 m_fixed_tab_width
= 100;
274 if (m_fixed_tab_width
> tot_width
/2)
275 m_fixed_tab_width
= tot_width
/2;
277 if (m_fixed_tab_width
> 220)
278 m_fixed_tab_width
= 220;
280 m_tab_ctrl_height
= tab_ctrl_size
.y
;
284 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
285 wxWindow
* WXUNUSED(wnd
),
289 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
290 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
291 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
292 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
295 int y
= rect
.GetHeight();
296 int w
= rect
.GetWidth();
297 dc
.SetPen(m_border_pen
);
298 dc
.SetBrush(m_base_colour_brush
);
299 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
303 // DrawTab() draws an individual tab.
306 // in_rect - rectangle the tab should be confined to
307 // caption - tab's caption
308 // active - whether or not the tab is active
309 // out_rect - actual output rectangle
310 // x_extent - the advance x; where the next tab should start
312 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
314 const wxAuiNotebookPage
& page
,
315 const wxRect
& in_rect
,
316 int close_button_state
,
317 wxRect
* out_tab_rect
,
318 wxRect
* out_button_rect
,
321 wxCoord normal_textx
, normal_texty
;
322 wxCoord selected_textx
, selected_texty
;
325 // if the caption is empty, measure some temporary text
326 wxString caption
= page
.caption
;
330 dc
.SetFont(m_selected_font
);
331 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
333 dc
.SetFont(m_normal_font
);
334 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
336 // figure out the size of the tab
337 wxSize tab_size
= GetTabSize(dc
,
345 wxCoord tab_height
= m_tab_ctrl_height
- 3;
346 wxCoord tab_width
= tab_size
.x
;
347 wxCoord tab_x
= in_rect
.x
;
348 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
351 caption
= page
.caption
;
354 // select pen, brush and font for the tab to be drawn
358 dc
.SetFont(m_selected_font
);
359 texty
= selected_texty
;
363 dc
.SetFont(m_normal_font
);
364 texty
= normal_texty
;
368 // create points that will make the tab outline
370 int clip_width
= tab_width
;
371 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
372 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
375 wxPoint clip_points[6];
376 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
377 clip_points[1] = wxPoint(tab_x, tab_y+2);
378 clip_points[2] = wxPoint(tab_x+2, tab_y);
379 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
380 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
381 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
383 // FIXME: these ports don't provide wxRegion ctor from array of points
384 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
385 // set the clipping region for the tab --
386 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
387 dc.SetClippingRegion(clipping_region);
388 #endif // !wxDFB && !wxCocoa
390 // since the above code above doesn't play well with WXDFB or WXCOCOA,
391 // we'll just use a rectangle for the clipping region for now --
392 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
395 wxPoint border_points
[6];
396 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
397 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
398 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
399 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
400 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
401 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
404 int drawn_tab_yoff
= border_points
[1].y
;
405 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
412 // draw base background color
413 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
414 dc
.SetPen(m_base_colour_pen
);
415 dc
.SetBrush(m_base_colour_brush
);
416 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
418 // this white helps fill out the gradient at the top of the tab
419 dc
.SetPen(*wxWHITE_PEN
);
420 dc
.SetBrush(*wxWHITE_BRUSH
);
421 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
423 // these two points help the rounded corners appear more antialiased
424 dc
.SetPen(m_base_colour_pen
);
425 dc
.DrawPoint(r
.x
+2, r
.y
+1);
426 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
428 // set rectangle down a bit for gradient drawing
429 r
.SetHeight(r
.GetHeight()/2);
435 // draw gradient background
436 wxColor top_color
= *wxWHITE
;
437 wxColor bottom_color
= m_base_colour
;
438 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
444 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
446 // start the gradent up a bit and leave the inside border inset
447 // by a pixel for a 3D look. Only the top half of the inactive
448 // tab will have a slight gradient
455 // -- draw top gradient fill for glossy look
456 wxColor top_color
= m_base_colour
;
457 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
458 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
463 // -- draw bottom fill for glossy look
464 top_color
= m_base_colour
;
465 bottom_color
= m_base_colour
;
466 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
470 dc
.SetPen(m_border_pen
);
471 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
472 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
474 // there are two horizontal grey lines at the bottom of the tab control,
475 // this gets rid of the top one of those lines in the tab control
478 dc
.SetPen(m_base_colour_pen
);
479 dc
.DrawLine(border_points
[0].x
+1,
486 int text_offset
= tab_x
+ 8;
487 int close_button_width
= 0;
488 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
490 close_button_width
= m_active_close_bmp
.GetWidth();
493 int bitmap_offset
= 0;
494 if (page
.bitmap
.IsOk())
496 bitmap_offset
= tab_x
+ 8;
499 dc
.DrawBitmap(page
.bitmap
,
501 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
504 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
505 text_offset
+= 3; // bitmap padding
510 text_offset
= tab_x
+ 8;
514 wxString draw_text
= wxAuiChopText(dc
,
516 tab_width
- (text_offset
-tab_x
) - close_button_width
);
519 dc
.DrawText(draw_text
,
521 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
523 // draw focus rectangle
524 if (page
.active
&& (wnd
->FindFocus() == wnd
))
526 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
527 selected_textx
, selected_texty
);
530 wxRect focusRectBitmap
;
532 if (page
.bitmap
.IsOk())
533 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
534 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
536 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
537 focusRect
= focusRectBitmap
;
538 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
539 focusRect
= focusRectText
;
540 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
541 focusRect
= focusRectText
.Union(focusRectBitmap
);
543 focusRect
.Inflate(2, 2);
545 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
548 // draw close button if necessary
549 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
551 wxBitmap bmp
= m_disabled_close_bmp
;
553 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
554 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
556 bmp
= m_active_close_bmp
;
559 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
560 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
563 IndentPressedBitmap(&rect
, close_button_state
);
564 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
566 *out_button_rect
= rect
;
569 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
571 dc
.DestroyClippingRegion();
574 int wxAuiDefaultTabArt::GetIndentSize()
579 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
580 wxWindow
* WXUNUSED(wnd
),
581 const wxString
& caption
,
582 const wxBitmap
& bitmap
,
583 bool WXUNUSED(active
),
584 int close_button_state
,
587 wxCoord measured_textx
, measured_texty
, tmp
;
589 dc
.SetFont(m_measuring_font
);
590 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
592 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
594 // add padding around the text
595 wxCoord tab_width
= measured_textx
;
596 wxCoord tab_height
= measured_texty
;
598 // if the close button is showing, add space for it
599 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
600 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
602 // if there's a bitmap, add space for it
605 tab_width
+= bitmap
.GetWidth();
606 tab_width
+= 3; // right side bitmap padding
607 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
614 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
616 tab_width
= m_fixed_tab_width
;
619 *x_extent
= tab_width
;
621 return wxSize(tab_width
, tab_height
);
625 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
626 wxWindow
* WXUNUSED(wnd
),
627 const wxRect
& in_rect
,
638 case wxAUI_BUTTON_CLOSE
:
639 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
640 bmp
= m_disabled_close_bmp
;
642 bmp
= m_active_close_bmp
;
644 case wxAUI_BUTTON_LEFT
:
645 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
646 bmp
= m_disabled_left_bmp
;
648 bmp
= m_active_left_bmp
;
650 case wxAUI_BUTTON_RIGHT
:
651 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
652 bmp
= m_disabled_right_bmp
;
654 bmp
= m_active_right_bmp
;
656 case wxAUI_BUTTON_WINDOWLIST
:
657 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
658 bmp
= m_disabled_windowlist_bmp
;
660 bmp
= m_active_windowlist_bmp
;
670 if (orientation
== wxLEFT
)
672 rect
.SetX(in_rect
.x
);
673 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
674 rect
.SetWidth(bmp
.GetWidth());
675 rect
.SetHeight(bmp
.GetHeight());
679 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
680 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
681 bmp
.GetWidth(), bmp
.GetHeight());
684 IndentPressedBitmap(&rect
, button_state
);
685 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
690 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
691 const wxAuiNotebookPageArray
& pages
,
696 size_t i
, count
= pages
.GetCount();
697 for (i
= 0; i
< count
; ++i
)
699 const wxAuiNotebookPage
& page
= pages
.Item(i
);
700 wxString caption
= page
.caption
;
702 // if there is no caption, make it a space. This will prevent
703 // an assert in the menu code.
704 if (caption
.IsEmpty())
707 menuPopup
.AppendCheckItem(1000+i
, caption
);
710 if (active_idx
!= -1)
712 menuPopup
.Check(1000+active_idx
, true);
715 // find out where to put the popup menu of window items
716 wxPoint pt
= ::wxGetMousePosition();
717 pt
= wnd
->ScreenToClient(pt
);
719 // find out the screen coordinate at the bottom of the tab ctrl
720 wxRect cli_rect
= wnd
->GetClientRect();
721 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
723 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
724 wnd
->PushEventHandler(cc
);
725 wnd
->PopupMenu(&menuPopup
, pt
);
726 int command
= cc
->GetCommandId();
727 wnd
->PopEventHandler(true);
735 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
736 const wxAuiNotebookPageArray
& pages
,
737 const wxSize
& required_bmp_size
)
740 dc
.SetFont(m_measuring_font
);
742 // sometimes a standard bitmap size needs to be enforced, especially
743 // if some tabs have bitmaps and others don't. This is important because
744 // it prevents the tab control from resizing when tabs are added.
745 wxBitmap measure_bmp
;
746 if (required_bmp_size
.IsFullySpecified())
748 measure_bmp
.Create(required_bmp_size
.x
,
749 required_bmp_size
.y
);
754 size_t i
, page_count
= pages
.GetCount();
755 for (i
= 0; i
< page_count
; ++i
)
757 wxAuiNotebookPage
& page
= pages
.Item(i
);
760 if (measure_bmp
.IsOk())
765 // we don't use the caption text because we don't
766 // want tab heights to be different in the case
767 // of a very short piece of text on one tab and a very
768 // tall piece of text on another tab
770 wxSize s
= GetTabSize(dc
,
775 wxAUI_BUTTON_STATE_HIDDEN
,
778 max_y
= wxMax(max_y
, s
.y
);
784 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
786 m_normal_font
= font
;
789 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
791 m_selected_font
= font
;
794 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
796 m_measuring_font
= font
;
800 // -- wxAuiSimpleTabArt class implementation --
802 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
804 m_normal_font
= *wxNORMAL_FONT
;
805 m_selected_font
= *wxNORMAL_FONT
;
806 m_selected_font
.SetWeight(wxBOLD
);
807 m_measuring_font
= m_selected_font
;
810 m_fixed_tab_width
= 100;
812 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
814 wxColour background_colour
= base_colour
;
815 wxColour normaltab_colour
= base_colour
;
816 wxColour selectedtab_colour
= *wxWHITE
;
818 m_bkbrush
= wxBrush(background_colour
);
819 m_normal_bkbrush
= wxBrush(normaltab_colour
);
820 m_normal_bkpen
= wxPen(normaltab_colour
);
821 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
822 m_selected_bkpen
= wxPen(selectedtab_colour
);
824 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
825 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
827 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
828 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
830 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
831 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
833 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
834 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
838 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
842 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
844 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
848 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
853 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
856 m_fixed_tab_width
= 100;
858 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
860 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
861 tot_width
-= m_active_close_bmp
.GetWidth();
862 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
863 tot_width
-= m_active_windowlist_bmp
.GetWidth();
867 m_fixed_tab_width
= tot_width
/(int)tab_count
;
871 if (m_fixed_tab_width
< 100)
872 m_fixed_tab_width
= 100;
874 if (m_fixed_tab_width
> tot_width
/2)
875 m_fixed_tab_width
= tot_width
/2;
877 if (m_fixed_tab_width
> 220)
878 m_fixed_tab_width
= 220;
881 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
882 wxWindow
* WXUNUSED(wnd
),
886 dc
.SetBrush(m_bkbrush
);
887 dc
.SetPen(*wxTRANSPARENT_PEN
);
888 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
891 dc
.SetPen(*wxGREY_PEN
);
892 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
896 // DrawTab() draws an individual tab.
899 // in_rect - rectangle the tab should be confined to
900 // caption - tab's caption
901 // active - whether or not the tab is active
902 // out_rect - actual output rectangle
903 // x_extent - the advance x; where the next tab should start
905 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
907 const wxAuiNotebookPage
& page
,
908 const wxRect
& in_rect
,
909 int close_button_state
,
910 wxRect
* out_tab_rect
,
911 wxRect
* out_button_rect
,
914 wxCoord normal_textx
, normal_texty
;
915 wxCoord selected_textx
, selected_texty
;
916 wxCoord textx
, texty
;
918 // if the caption is empty, measure some temporary text
919 wxString caption
= page
.caption
;
923 dc
.SetFont(m_selected_font
);
924 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
926 dc
.SetFont(m_normal_font
);
927 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
929 // figure out the size of the tab
930 wxSize tab_size
= GetTabSize(dc
,
938 wxCoord tab_height
= tab_size
.y
;
939 wxCoord tab_width
= tab_size
.x
;
940 wxCoord tab_x
= in_rect
.x
;
941 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
943 caption
= page
.caption
;
945 // select pen, brush and font for the tab to be drawn
949 dc
.SetPen(m_selected_bkpen
);
950 dc
.SetBrush(m_selected_bkbrush
);
951 dc
.SetFont(m_selected_font
);
952 textx
= selected_textx
;
953 texty
= selected_texty
;
957 dc
.SetPen(m_normal_bkpen
);
958 dc
.SetBrush(m_normal_bkbrush
);
959 dc
.SetFont(m_normal_font
);
960 textx
= normal_textx
;
961 texty
= normal_texty
;
969 points
[0].y
= tab_y
+ tab_height
- 1;
970 points
[1].x
= tab_x
+ tab_height
- 3;
971 points
[1].y
= tab_y
+ 2;
972 points
[2].x
= tab_x
+ tab_height
+ 3;
974 points
[3].x
= tab_x
+ tab_width
- 2;
976 points
[4].x
= tab_x
+ tab_width
;
977 points
[4].y
= tab_y
+ 2;
978 points
[5].x
= tab_x
+ tab_width
;
979 points
[5].y
= tab_y
+ tab_height
- 1;
980 points
[6] = points
[0];
982 dc
.SetClippingRegion(in_rect
);
984 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
986 dc
.SetPen(*wxGREY_PEN
);
988 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
989 dc
.DrawLines(WXSIZEOF(points
), points
);
994 int close_button_width
= 0;
995 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
997 close_button_width
= m_active_close_bmp
.GetWidth();
998 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1002 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1005 // set minimum text offset
1006 if (text_offset
< tab_x
+ tab_height
)
1007 text_offset
= tab_x
+ tab_height
;
1009 // chop text if necessary
1010 wxString draw_text
= wxAuiChopText(dc
,
1012 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1015 dc
.DrawText(draw_text
,
1017 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1020 // draw focus rectangle
1021 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1023 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1024 selected_textx
, selected_texty
);
1026 focusRect
.Inflate(2, 2);
1028 wxRendererNative::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1031 // draw close button if necessary
1032 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1036 bmp
= m_active_close_bmp
;
1038 bmp
= m_disabled_close_bmp
;
1040 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1041 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1044 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1046 *out_button_rect
= rect
;
1050 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1052 dc
.DestroyClippingRegion();
1055 int wxAuiSimpleTabArt::GetIndentSize()
1060 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1061 wxWindow
* WXUNUSED(wnd
),
1062 const wxString
& caption
,
1063 const wxBitmap
& WXUNUSED(bitmap
),
1064 bool WXUNUSED(active
),
1065 int close_button_state
,
1068 wxCoord measured_textx
, measured_texty
;
1070 dc
.SetFont(m_measuring_font
);
1071 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1073 wxCoord tab_height
= measured_texty
+ 4;
1074 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1076 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1077 tab_width
+= m_active_close_bmp
.GetWidth();
1079 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1081 tab_width
= m_fixed_tab_width
;
1084 *x_extent
= tab_width
- (tab_height
/2) - 1;
1086 return wxSize(tab_width
, tab_height
);
1090 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1091 wxWindow
* WXUNUSED(wnd
),
1092 const wxRect
& in_rect
,
1103 case wxAUI_BUTTON_CLOSE
:
1104 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1105 bmp
= m_disabled_close_bmp
;
1107 bmp
= m_active_close_bmp
;
1109 case wxAUI_BUTTON_LEFT
:
1110 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1111 bmp
= m_disabled_left_bmp
;
1113 bmp
= m_active_left_bmp
;
1115 case wxAUI_BUTTON_RIGHT
:
1116 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1117 bmp
= m_disabled_right_bmp
;
1119 bmp
= m_active_right_bmp
;
1121 case wxAUI_BUTTON_WINDOWLIST
:
1122 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1123 bmp
= m_disabled_windowlist_bmp
;
1125 bmp
= m_active_windowlist_bmp
;
1134 if (orientation
== wxLEFT
)
1136 rect
.SetX(in_rect
.x
);
1137 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1138 rect
.SetWidth(bmp
.GetWidth());
1139 rect
.SetHeight(bmp
.GetHeight());
1143 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1144 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1145 bmp
.GetWidth(), bmp
.GetHeight());
1149 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1154 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1155 const wxAuiNotebookPageArray
& pages
,
1160 size_t i
, count
= pages
.GetCount();
1161 for (i
= 0; i
< count
; ++i
)
1163 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1164 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1167 if (active_idx
!= -1)
1169 menuPopup
.Check(1000+active_idx
, true);
1172 // find out where to put the popup menu of window
1173 // items. Subtract 100 for now to center the menu
1174 // a bit, until a better mechanism can be implemented
1175 wxPoint pt
= ::wxGetMousePosition();
1176 pt
= wnd
->ScreenToClient(pt
);
1182 // find out the screen coordinate at the bottom of the tab ctrl
1183 wxRect cli_rect
= wnd
->GetClientRect();
1184 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1186 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1187 wnd
->PushEventHandler(cc
);
1188 wnd
->PopupMenu(&menuPopup
, pt
);
1189 int command
= cc
->GetCommandId();
1190 wnd
->PopEventHandler(true);
1192 if (command
>= 1000)
1193 return command
-1000;
1198 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1199 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1200 const wxSize
& WXUNUSED(required_bmp_size
))
1203 dc
.SetFont(m_measuring_font
);
1205 wxSize s
= GetTabSize(dc
,
1210 wxAUI_BUTTON_STATE_HIDDEN
,
1215 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1217 m_normal_font
= font
;
1220 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1222 m_selected_font
= font
;
1225 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1227 m_measuring_font
= font
;
1233 // -- wxAuiTabContainer class implementation --
1236 // wxAuiTabContainer is a class which contains information about each
1237 // tab. It also can render an entire tab control to a specified DC.
1238 // It's not a window class itself, because this code will be used by
1239 // the wxFrameMananger, where it is disadvantageous to have separate
1240 // windows for each tab control in the case of "docked tabs"
1242 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1243 // which can be used as a tab control in the normal sense.
1246 wxAuiTabContainer::wxAuiTabContainer()
1250 m_art
= new wxAuiDefaultTabArt
;
1252 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1253 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1254 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1255 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1258 wxAuiTabContainer::~wxAuiTabContainer()
1263 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1270 m_art
->SetFlags(m_flags
);
1274 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1279 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1283 // check for new close button settings
1284 RemoveButton(wxAUI_BUTTON_LEFT
);
1285 RemoveButton(wxAUI_BUTTON_RIGHT
);
1286 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1287 RemoveButton(wxAUI_BUTTON_CLOSE
);
1290 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1292 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1293 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1296 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1298 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1301 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1303 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1308 m_art
->SetFlags(m_flags
);
1312 unsigned int wxAuiTabContainer::GetFlags() const
1318 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1320 m_art
->SetNormalFont(font
);
1323 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1325 m_art
->SetSelectedFont(font
);
1328 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1330 m_art
->SetMeasuringFont(font
);
1333 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1339 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1343 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1344 const wxAuiNotebookPage
& info
)
1346 wxAuiNotebookPage page_info
;
1348 page_info
.window
= page
;
1350 m_pages
.Add(page_info
);
1352 // let the art provider know how many pages we have
1355 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1361 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1362 const wxAuiNotebookPage
& info
,
1365 wxAuiNotebookPage page_info
;
1367 page_info
.window
= page
;
1369 if (idx
>= m_pages
.GetCount())
1370 m_pages
.Add(page_info
);
1372 m_pages
.Insert(page_info
, idx
);
1374 // let the art provider know how many pages we have
1377 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1383 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1386 int idx
= GetIdxFromWindow(page
);
1390 // get page entry, make a copy of it
1391 wxAuiNotebookPage p
= GetPage(idx
);
1393 // remove old page entry
1396 // insert page where it should be
1397 InsertPage(page
, p
, new_idx
);
1402 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1404 size_t i
, page_count
= m_pages
.GetCount();
1405 for (i
= 0; i
< page_count
; ++i
)
1407 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1408 if (page
.window
== wnd
)
1410 m_pages
.RemoveAt(i
);
1412 // let the art provider know how many pages we have
1415 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1425 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1429 size_t i
, page_count
= m_pages
.GetCount();
1430 for (i
= 0; i
< page_count
; ++i
)
1432 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1433 if (page
.window
== wnd
)
1440 page
.active
= false;
1447 void wxAuiTabContainer::SetNoneActive()
1449 size_t i
, page_count
= m_pages
.GetCount();
1450 for (i
= 0; i
< page_count
; ++i
)
1452 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1453 page
.active
= false;
1457 bool wxAuiTabContainer::SetActivePage(size_t page
)
1459 if (page
>= m_pages
.GetCount())
1462 return SetActivePage(m_pages
.Item(page
).window
);
1465 int wxAuiTabContainer::GetActivePage() const
1467 size_t i
, page_count
= m_pages
.GetCount();
1468 for (i
= 0; i
< page_count
; ++i
)
1470 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1478 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1480 if (idx
>= m_pages
.GetCount())
1483 return m_pages
[idx
].window
;
1486 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1488 const size_t page_count
= m_pages
.GetCount();
1489 for ( size_t i
= 0; i
< page_count
; ++i
)
1491 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1492 if (page
.window
== wnd
)
1498 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1500 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1502 return m_pages
[idx
];
1505 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1507 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1509 return m_pages
[idx
];
1512 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1517 size_t wxAuiTabContainer::GetPageCount() const
1519 return m_pages
.GetCount();
1522 void wxAuiTabContainer::AddButton(int id
,
1524 const wxBitmap
& normal_bitmap
,
1525 const wxBitmap
& disabled_bitmap
)
1527 wxAuiTabContainerButton button
;
1529 button
.bitmap
= normal_bitmap
;
1530 button
.dis_bitmap
= disabled_bitmap
;
1531 button
.location
= location
;
1532 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1534 m_buttons
.Add(button
);
1537 void wxAuiTabContainer::RemoveButton(int id
)
1539 size_t i
, button_count
= m_buttons
.GetCount();
1541 for (i
= 0; i
< button_count
; ++i
)
1543 if (m_buttons
.Item(i
).id
== id
)
1545 m_buttons
.RemoveAt(i
);
1553 size_t wxAuiTabContainer::GetTabOffset() const
1555 return m_tab_offset
;
1558 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1560 m_tab_offset
= offset
;
1566 // Render() renders the tab catalog to the specified DC
1567 // It is a virtual function and can be overridden to
1568 // provide custom drawing capabilities
1569 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1571 if (!raw_dc
|| !raw_dc
->IsOk())
1577 size_t page_count
= m_pages
.GetCount();
1578 size_t button_count
= m_buttons
.GetCount();
1580 // create off-screen bitmap
1581 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1582 dc
.SelectObject(bmp
);
1587 // find out if size of tabs is larger than can be
1588 // afforded on screen
1589 int total_width
= 0;
1590 int visible_width
= 0;
1591 for (i
= 0; i
< page_count
; ++i
)
1593 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1595 // determine if a close button is on this tab
1596 bool close_button
= false;
1597 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1598 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1600 close_button
= true;
1605 wxSize size
= m_art
->GetTabSize(dc
,
1611 wxAUI_BUTTON_STATE_NORMAL
:
1612 wxAUI_BUTTON_STATE_HIDDEN
,
1615 if (i
+1 < page_count
)
1616 total_width
+= x_extent
;
1618 total_width
+= size
.x
;
1620 if (i
>= m_tab_offset
)
1622 if (i
+1 < page_count
)
1623 visible_width
+= x_extent
;
1625 visible_width
+= size
.x
;
1629 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1631 // show left/right buttons
1632 for (i
= 0; i
< button_count
; ++i
)
1634 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1635 if (button
.id
== wxAUI_BUTTON_LEFT
||
1636 button
.id
== wxAUI_BUTTON_RIGHT
)
1638 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1644 // hide left/right buttons
1645 for (i
= 0; i
< button_count
; ++i
)
1647 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1648 if (button
.id
== wxAUI_BUTTON_LEFT
||
1649 button
.id
== wxAUI_BUTTON_RIGHT
)
1651 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1656 // determine whether left button should be enabled
1657 for (i
= 0; i
< button_count
; ++i
)
1659 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1660 if (button
.id
== wxAUI_BUTTON_LEFT
)
1662 if (m_tab_offset
== 0)
1663 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1665 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1667 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1669 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1670 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1672 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1679 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1682 int left_buttons_width
= 0;
1683 int right_buttons_width
= 0;
1687 // draw the buttons on the right side
1688 offset
= m_rect
.x
+ m_rect
.width
;
1689 for (i
= 0; i
< button_count
; ++i
)
1691 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1693 if (button
.location
!= wxRIGHT
)
1695 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1698 wxRect button_rect
= m_rect
;
1699 button_rect
.SetY(1);
1700 button_rect
.SetWidth(offset
);
1702 m_art
->DrawButton(dc
,
1710 offset
-= button
.rect
.GetWidth();
1711 right_buttons_width
+= button
.rect
.GetWidth();
1718 // draw the buttons on the left side
1720 for (i
= 0; i
< button_count
; ++i
)
1722 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1724 if (button
.location
!= wxLEFT
)
1726 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1729 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1731 m_art
->DrawButton(dc
,
1739 offset
+= button
.rect
.GetWidth();
1740 left_buttons_width
+= button
.rect
.GetWidth();
1743 offset
= left_buttons_width
;
1746 offset
+= m_art
->GetIndentSize();
1749 // prepare the tab-close-button array
1750 // make sure tab button entries which aren't used are marked as hidden
1751 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1752 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1754 // make sure there are enough tab button entries to accommodate all tabs
1755 while (m_tab_close_buttons
.GetCount() < page_count
)
1757 wxAuiTabContainerButton tempbtn
;
1758 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1759 tempbtn
.location
= wxCENTER
;
1760 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1761 m_tab_close_buttons
.Add(tempbtn
);
1765 // buttons before the tab offset must be set to hidden
1766 for (i
= 0; i
< m_tab_offset
; ++i
)
1768 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1774 size_t active
= 999;
1775 int active_offset
= 0;
1779 wxRect rect
= m_rect
;
1781 rect
.height
= m_rect
.height
;
1783 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1785 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1786 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1788 // determine if a close button is on this tab
1789 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1790 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1792 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1794 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1795 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1796 tab_button
.location
= wxCENTER
;
1801 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1805 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1807 if (rect
.width
<= 0)
1814 tab_button
.cur_state
,
1822 active_offset
= offset
;
1830 // make sure to deactivate buttons which are off the screen to the right
1831 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1833 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1837 // draw the active tab again so it stands in the foreground
1838 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1840 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1842 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1844 rect
.x
= active_offset
;
1849 tab_button
.cur_state
,
1856 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1857 m_rect
.GetWidth(), m_rect
.GetHeight(),
1861 // Is the tab visible?
1862 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1864 if (!dc
|| !dc
->IsOk())
1868 size_t page_count
= m_pages
.GetCount();
1869 size_t button_count
= m_buttons
.GetCount();
1871 // Hasn't been rendered yet; assume it's visible
1872 if (m_tab_close_buttons
.GetCount() < page_count
)
1875 // First check if both buttons are disabled - if so, there's no need to
1876 // check further for visibility.
1877 int arrowButtonVisibleCount
= 0;
1878 for (i
= 0; i
< button_count
; ++i
)
1880 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1881 if (button
.id
== wxAUI_BUTTON_LEFT
||
1882 button
.id
== wxAUI_BUTTON_RIGHT
)
1884 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1885 arrowButtonVisibleCount
++;
1889 // Tab must be visible
1890 if (arrowButtonVisibleCount
== 0)
1893 // If tab is less than the given offset, it must be invisible by definition
1894 if (tabPage
< tabOffset
)
1898 int left_buttons_width
= 0;
1899 int right_buttons_width
= 0;
1903 // calculate size of the buttons on the right side
1904 offset
= m_rect
.x
+ m_rect
.width
;
1905 for (i
= 0; i
< button_count
; ++i
)
1907 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1909 if (button
.location
!= wxRIGHT
)
1911 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1914 offset
-= button
.rect
.GetWidth();
1915 right_buttons_width
+= button
.rect
.GetWidth();
1920 // calculate size of the buttons on the left side
1921 for (i
= 0; i
< button_count
; ++i
)
1923 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1925 if (button
.location
!= wxLEFT
)
1927 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1930 offset
+= button
.rect
.GetWidth();
1931 left_buttons_width
+= button
.rect
.GetWidth();
1934 offset
= left_buttons_width
;
1937 offset
+= m_art
->GetIndentSize();
1941 wxRect rect
= m_rect
;
1943 rect
.height
= m_rect
.height
;
1945 // See if the given page is visible at the given tab offset (effectively scroll position)
1946 for (i
= tabOffset
; i
< page_count
; ++i
)
1948 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1949 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1951 // determine if a close button is on this tab
1952 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1953 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1955 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1957 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1958 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1959 tab_button
.location
= wxCENTER
;
1964 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1968 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1970 if (rect
.width
<= 0)
1971 return false; // haven't found the tab, and we've run out of space, so return false
1974 wxSize size
= m_art
->GetTabSize(*dc
,
1979 tab_button
.cur_state
,
1984 if (i
== (size_t) tabPage
)
1986 // If not all of the tab is visible, and supposing there's space to display it all,
1987 // we could do better so we return false.
1988 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
1995 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
1996 // further looping in calling code.
2000 // Make the tab visible if it wasn't already
2001 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
2004 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2007 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2009 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2019 // TabHitTest() tests if a tab was hit, passing the window pointer
2020 // back if that condition was fulfilled. The function returns
2021 // true if a tab was hit, otherwise false
2022 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2024 if (!m_rect
.Contains(x
,y
))
2027 wxAuiTabContainerButton
* btn
= NULL
;
2028 if (ButtonHitTest(x
, y
, &btn
))
2030 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2034 size_t i
, page_count
= m_pages
.GetCount();
2036 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2038 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2039 if (page
.rect
.Contains(x
,y
))
2050 // ButtonHitTest() tests if a button was hit. The function returns
2051 // true if a button was hit, otherwise false
2052 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2053 wxAuiTabContainerButton
** hit
) const
2055 if (!m_rect
.Contains(x
,y
))
2058 size_t i
, button_count
;
2061 button_count
= m_buttons
.GetCount();
2062 for (i
= 0; i
< button_count
; ++i
)
2064 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2065 if (button
.rect
.Contains(x
,y
) &&
2066 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2067 wxAUI_BUTTON_STATE_DISABLED
)))
2075 button_count
= m_tab_close_buttons
.GetCount();
2076 for (i
= 0; i
< button_count
; ++i
)
2078 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2079 if (button
.rect
.Contains(x
,y
) &&
2080 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2081 wxAUI_BUTTON_STATE_DISABLED
)))
2094 // the utility function ShowWnd() is the same as show,
2095 // except it handles wxAuiMDIChildFrame windows as well,
2096 // as the Show() method on this class is "unplugged"
2097 static void ShowWnd(wxWindow
* wnd
, bool show
)
2100 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2102 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2113 // DoShowHide() this function shows the active window, then
2114 // hides all of the other windows (in that order)
2115 void wxAuiTabContainer::DoShowHide()
2117 wxAuiNotebookPageArray
& pages
= GetPages();
2118 size_t i
, page_count
= pages
.GetCount();
2120 // show new active page first
2121 for (i
= 0; i
< page_count
; ++i
)
2123 wxAuiNotebookPage
& page
= pages
.Item(i
);
2126 ShowWnd(page
.window
, true);
2131 // hide all other pages
2132 for (i
= 0; i
< page_count
; ++i
)
2134 wxAuiNotebookPage
& page
= pages
.Item(i
);
2136 ShowWnd(page
.window
, false);
2145 // -- wxAuiTabCtrl class implementation --
2149 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2150 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2151 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2152 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2153 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2154 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
2155 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2156 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2157 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2158 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2159 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2160 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2161 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2162 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2163 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2164 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2165 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2169 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2173 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2175 SetName(wxT("wxAuiTabCtrl"));
2176 m_click_pt
= wxDefaultPosition
;
2177 m_is_dragging
= false;
2178 m_hover_button
= NULL
;
2179 m_pressed_button
= NULL
;
2182 wxAuiTabCtrl::~wxAuiTabCtrl()
2186 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2190 dc
.SetFont(GetFont());
2192 if (GetPageCount() > 0)
2196 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2200 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2202 wxSize s
= evt
.GetSize();
2203 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2207 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2210 m_click_pt
= wxDefaultPosition
;
2211 m_is_dragging
= false;
2213 m_pressed_button
= NULL
;
2217 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2219 int new_selection
= GetIdxFromWindow(wnd
);
2221 // wxAuiNotebooks always want to receive this event
2222 // even if the tab is already active, because they may
2223 // have multiple tab controls
2224 if (new_selection
!= GetActivePage() ||
2225 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2227 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2228 e
.SetSelection(new_selection
);
2229 e
.SetOldSelection(GetActivePage());
2230 e
.SetEventObject(this);
2231 GetEventHandler()->ProcessEvent(e
);
2234 m_click_pt
.x
= evt
.m_x
;
2235 m_click_pt
.y
= evt
.m_y
;
2241 m_pressed_button
= m_hover_button
;
2242 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2248 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2250 if (GetCapture() == this)
2255 m_is_dragging
= false;
2257 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2258 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2259 evt
.SetOldSelection(evt
.GetSelection());
2260 evt
.SetEventObject(this);
2261 GetEventHandler()->ProcessEvent(evt
);
2266 if (m_pressed_button
)
2268 // make sure we're still clicking the button
2269 wxAuiTabContainerButton
* button
= NULL
;
2270 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2273 if (button
!= m_pressed_button
)
2275 m_pressed_button
= NULL
;
2282 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2284 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2285 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2286 evt
.SetInt(m_pressed_button
->id
);
2287 evt
.SetEventObject(this);
2288 GetEventHandler()->ProcessEvent(evt
);
2291 m_pressed_button
= NULL
;
2294 m_click_pt
= wxDefaultPosition
;
2295 m_is_dragging
= false;
2299 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2301 wxWindow
* wnd
= NULL
;
2302 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2305 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2306 e
.SetEventObject(this);
2307 e
.SetSelection(GetIdxFromWindow(wnd
));
2308 GetEventHandler()->ProcessEvent(e
);
2311 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2313 wxWindow
* wnd
= NULL
;
2314 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2317 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2318 e
.SetEventObject(this);
2319 e
.SetSelection(GetIdxFromWindow(wnd
));
2320 GetEventHandler()->ProcessEvent(e
);
2323 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2325 wxWindow
* wnd
= NULL
;
2326 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2329 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2330 e
.SetEventObject(this);
2331 e
.SetSelection(GetIdxFromWindow(wnd
));
2332 GetEventHandler()->ProcessEvent(e
);
2335 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2337 wxWindow
* wnd
= NULL
;
2338 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2341 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2342 e
.SetEventObject(this);
2343 e
.SetSelection(GetIdxFromWindow(wnd
));
2344 GetEventHandler()->ProcessEvent(e
);
2347 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2349 wxPoint pos
= evt
.GetPosition();
2351 // check if the mouse is hovering above a button
2352 wxAuiTabContainerButton
* button
;
2353 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2355 if (m_hover_button
&& button
!= m_hover_button
)
2357 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2358 m_hover_button
= NULL
;
2363 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2365 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2368 m_hover_button
= button
;
2376 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2377 m_hover_button
= NULL
;
2384 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2389 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2390 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2391 evt
.SetOldSelection(evt
.GetSelection());
2392 evt
.SetEventObject(this);
2393 GetEventHandler()->ProcessEvent(evt
);
2398 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2399 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2401 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2402 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2404 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2405 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2406 evt
.SetOldSelection(evt
.GetSelection());
2407 evt
.SetEventObject(this);
2408 GetEventHandler()->ProcessEvent(evt
);
2410 m_is_dragging
= true;
2414 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2418 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2419 m_hover_button
= NULL
;
2425 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2427 int button
= event
.GetInt();
2429 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2431 if (button
== wxAUI_BUTTON_LEFT
)
2433 if (GetTabOffset() > 0)
2435 SetTabOffset(GetTabOffset()-1);
2442 SetTabOffset(GetTabOffset()+1);
2447 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2449 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2453 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2454 e
.SetSelection(idx
);
2455 e
.SetOldSelection(GetActivePage());
2456 e
.SetEventObject(this);
2457 GetEventHandler()->ProcessEvent(e
);
2466 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2471 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2476 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2478 if (GetActivePage() == -1)
2484 // We can't leave tab processing to the system; on Windows, tabs and keys
2485 // get eaten by the system and not processed properly if we specify both
2486 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2487 // we don't key arrow key events.
2489 int key
= event
.GetKeyCode();
2491 if (key
== WXK_NUMPAD_PAGEUP
)
2493 if (key
== WXK_NUMPAD_PAGEDOWN
)
2495 if (key
== WXK_NUMPAD_HOME
)
2497 if (key
== WXK_NUMPAD_END
)
2499 if (key
== WXK_NUMPAD_LEFT
)
2501 if (key
== WXK_NUMPAD_RIGHT
)
2504 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2506 bool bCtrlDown
= event
.ControlDown();
2507 bool bShiftDown
= event
.ShiftDown();
2509 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2510 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2511 bool bFromTab
= (key
== WXK_TAB
);
2513 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2520 wxNavigationKeyEvent keyEvent
;
2521 keyEvent
.SetDirection(bForward
);
2522 keyEvent
.SetWindowChange(bWindowChange
);
2523 keyEvent
.SetFromTab(bFromTab
);
2524 keyEvent
.SetEventObject(nb
);
2526 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2528 // Not processed? Do an explicit tab into the page.
2529 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2536 if (m_pages
.GetCount() < 2)
2544 if (key
== WXK_RIGHT
)
2546 if (m_pages
.GetCount() > 1)
2548 if (GetActivePage() == -1)
2550 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2551 newPage
= GetActivePage() + 1;
2554 else if (key
== WXK_LEFT
)
2556 if (m_pages
.GetCount() > 1)
2558 if (GetActivePage() == -1)
2559 newPage
= (int) (m_pages
.GetCount() - 1);
2560 else if (GetActivePage() > 0)
2561 newPage
= GetActivePage() - 1;
2564 else if (key
== WXK_HOME
)
2568 else if (key
== WXK_END
)
2570 newPage
= (int) (m_pages
.GetCount() - 1);
2577 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2578 e
.SetSelection(newPage
);
2579 e
.SetOldSelection(newPage
);
2580 e
.SetEventObject(this);
2581 this->GetEventHandler()->ProcessEvent(e
);
2587 // wxTabFrame is an interesting case. It's important that all child pages
2588 // of the multi-notebook control are all actually children of that control
2589 // (and not grandchildren). wxTabFrame facilitates this. There is one
2590 // instance of wxTabFrame for each tab control inside the multi-notebook.
2591 // It's important to know that wxTabFrame is not a real window, but it merely
2592 // used to capture the dimensions/positioning of the internal tab control and
2593 // it's managed page windows
2595 class wxTabFrame
: public wxWindow
2602 m_rect
= wxRect(0,0,200,200);
2603 m_tab_ctrl_height
= 20;
2611 void SetTabCtrlHeight(int h
)
2613 m_tab_ctrl_height
= h
;
2617 void DoSetSize(int x
, int y
,
2618 int width
, int height
,
2619 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2621 m_rect
= wxRect(x
, y
, width
, height
);
2625 void DoGetClientSize(int* x
, int* y
) const
2632 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2639 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2640 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2641 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2645 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2646 size_t i
, page_count
= pages
.GetCount();
2648 for (i
= 0; i
< page_count
; ++i
)
2650 wxAuiNotebookPage
& page
= pages
.Item(i
);
2651 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2652 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2655 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2657 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2658 wnd
->ApplyMDIChildFrameRect();
2665 void DoGetSize(int* x
, int* y
) const
2668 *x
= m_rect
.GetWidth();
2670 *y
= m_rect
.GetHeight();
2681 wxAuiTabCtrl
* m_tabs
;
2682 int m_tab_ctrl_height
;
2686 const int wxAuiBaseTabCtrlId
= 5380;
2689 // -- wxAuiNotebook class implementation --
2691 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2692 EVT_SIZE(wxAuiNotebook::OnSize
)
2693 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2694 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2695 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2696 wxAuiNotebook::OnTabClicked
)
2697 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2698 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2699 wxAuiNotebook::OnTabBeginDrag
)
2700 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2701 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2702 wxAuiNotebook::OnTabEndDrag
)
2703 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2704 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2705 wxAuiNotebook::OnTabDragMotion
)
2706 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2707 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2708 wxAuiNotebook::OnTabButton
)
2709 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2710 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2711 wxAuiNotebook::OnTabMiddleDown
)
2712 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2713 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2714 wxAuiNotebook::OnTabMiddleUp
)
2715 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2716 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2717 wxAuiNotebook::OnTabRightDown
)
2718 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2719 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2720 wxAuiNotebook::OnTabRightUp
)
2721 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2723 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2724 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2726 // Avoid clash with container event handler functions
2727 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2731 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2733 wxAuiNotebook::wxAuiNotebook()
2736 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2738 m_tab_ctrl_height
= 20;
2739 m_requested_bmp_size
= wxDefaultSize
;
2740 m_requested_tabctrl_height
= -1;
2743 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2747 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2750 m_requested_bmp_size
= wxDefaultSize
;
2751 m_requested_tabctrl_height
= -1;
2752 InitNotebook(style
);
2755 bool wxAuiNotebook::Create(wxWindow
* parent
,
2761 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2764 InitNotebook(style
);
2769 // InitNotebook() contains common initialization
2770 // code called by all constructors
2771 void wxAuiNotebook::InitNotebook(long style
)
2773 WX_INIT_CONTROL_CONTAINER();
2774 // SetCanFocus(false);
2776 SetName(wxT("wxAuiNotebook"));
2778 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2780 m_flags
= (unsigned int)style
;
2781 m_tab_ctrl_height
= 20;
2783 m_normal_font
= *wxNORMAL_FONT
;
2784 m_selected_font
= *wxNORMAL_FONT
;
2785 m_selected_font
.SetWeight(wxBOLD
);
2787 SetArtProvider(new wxAuiDefaultTabArt
);
2789 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2790 m_dummy_wnd
->SetSize(200, 200);
2791 m_dummy_wnd
->Show(false);
2793 m_mgr
.SetManagedWindow(this);
2794 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2795 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2797 m_mgr
.AddPane(m_dummy_wnd
,
2798 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2803 wxAuiNotebook::~wxAuiNotebook()
2805 while ( GetPageCount() > 0 )
2811 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2813 m_tabs
.SetArtProvider(art
);
2815 UpdateTabCtrlHeight();
2818 // SetTabCtrlHeight() is the highest-level override of the
2819 // tab height. A call to this function effectively enforces a
2820 // specified tab ctrl height, overriding all other considerations,
2821 // such as text or bitmap height. It overrides any call to
2822 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2823 // any previous call and returns to the default behavior
2825 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2827 m_requested_tabctrl_height
= height
;
2829 // if window is already initialized, recalculate the tab height
2832 UpdateTabCtrlHeight();
2837 // SetUniformBitmapSize() ensures that all tabs will have
2838 // the same height, even if some tabs don't have bitmaps
2839 // Passing wxDefaultSize to this function will instruct
2840 // the control to use dynamic tab height-- so when a tab
2841 // with a large bitmap is added, the tab ctrl's height will
2842 // automatically increase to accommodate the bitmap
2844 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2846 m_requested_bmp_size
= size
;
2848 // if window is already initialized, recalculate the tab height
2851 UpdateTabCtrlHeight();
2855 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2856 // to be used interally
2857 void wxAuiNotebook::UpdateTabCtrlHeight()
2859 // get the tab ctrl height we will use
2860 int height
= CalculateTabCtrlHeight();
2862 // if the tab control height needs to change, update
2863 // all of our tab controls with the new height
2864 if (m_tab_ctrl_height
!= height
)
2866 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2868 m_tab_ctrl_height
= height
;
2870 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2871 size_t i
, pane_count
= all_panes
.GetCount();
2872 for (i
= 0; i
< pane_count
; ++i
)
2874 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2875 if (pane
.name
== wxT("dummy"))
2877 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2878 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2879 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2880 tabctrl
->SetArtProvider(art
->Clone());
2881 tab_frame
->DoSizing();
2886 void wxAuiNotebook::UpdateHintWindowSize()
2888 wxSize size
= CalculateNewSplitSize();
2890 // the placeholder hint window should be set to this size
2891 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2895 info
.BestSize(size
);
2896 m_dummy_wnd
->SetSize(size
);
2901 // calculates the size of the new split
2902 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2904 // count number of tab controls
2905 int tab_ctrl_count
= 0;
2906 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2907 size_t i
, pane_count
= all_panes
.GetCount();
2908 for (i
= 0; i
< pane_count
; ++i
)
2910 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2911 if (pane
.name
== wxT("dummy"))
2916 wxSize new_split_size
;
2918 // if there is only one tab control, the first split
2919 // should happen around the middle
2920 if (tab_ctrl_count
< 2)
2922 new_split_size
= GetClientSize();
2923 new_split_size
.x
/= 2;
2924 new_split_size
.y
/= 2;
2928 // this is in place of a more complicated calculation
2929 // that needs to be implemented
2930 new_split_size
= wxSize(180,180);
2933 return new_split_size
;
2936 int wxAuiNotebook::CalculateTabCtrlHeight()
2938 // if a fixed tab ctrl height is specified,
2939 // just return that instead of calculating a
2941 if (m_requested_tabctrl_height
!= -1)
2942 return m_requested_tabctrl_height
;
2944 // find out new best tab height
2945 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2947 return art
->GetBestTabCtrlSize(this,
2949 m_requested_bmp_size
);
2953 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2955 return m_tabs
.GetArtProvider();
2958 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2960 wxControl::SetWindowStyleFlag(style
);
2962 m_flags
= (unsigned int)style
;
2964 // if the control is already initialized
2965 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2967 // let all of the tab children know about the new style
2969 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2970 size_t i
, pane_count
= all_panes
.GetCount();
2971 for (i
= 0; i
< pane_count
; ++i
)
2973 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2974 if (pane
.name
== wxT("dummy"))
2976 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2977 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2978 tabctrl
->SetFlags(m_flags
);
2979 tabframe
->DoSizing();
2987 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2988 const wxString
& caption
,
2990 const wxBitmap
& bitmap
)
2992 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2995 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2997 const wxString
& caption
,
2999 const wxBitmap
& bitmap
)
3001 page
->Reparent(this);
3003 wxAuiNotebookPage info
;
3005 info
.caption
= caption
;
3006 info
.bitmap
= bitmap
;
3007 info
.active
= false;
3009 // if there are currently no tabs, the first added
3010 // tab must be active
3011 if (m_tabs
.GetPageCount() == 0)
3014 m_tabs
.InsertPage(page
, info
, page_idx
);
3016 // if that was the first page added, even if
3017 // select is false, it must become the "current page"
3018 // (though no select events will be fired)
3019 if (!select
&& m_tabs
.GetPageCount() == 1)
3021 //m_curpage = GetPageIndex(page);
3023 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3024 if (page_idx
>= active_tabctrl
->GetPageCount())
3025 active_tabctrl
->AddPage(page
, info
);
3027 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3029 UpdateTabCtrlHeight();
3031 active_tabctrl
->DoShowHide();
3033 // adjust selected index
3034 if(m_curpage
>= (int) page_idx
)
3039 SetSelectionToWindow(page
);
3046 // DeletePage() removes a tab from the multi-notebook,
3047 // and destroys the window as well
3048 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3050 if (page_idx
>= m_tabs
.GetPageCount())
3053 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3055 // hide the window in advance, as this will
3057 ShowWnd(wnd
, false);
3059 if (!RemovePage(page_idx
))
3063 // actually destroy the window now
3064 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3066 // delete the child frame with pending delete, as is
3067 // customary with frame windows
3068 if (!wxPendingDelete
.Member(wnd
))
3069 wxPendingDelete
.Append(wnd
);
3082 // RemovePage() removes a tab from the multi-notebook,
3083 // but does not destroy the window
3084 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3086 // save active window pointer
3087 wxWindow
* active_wnd
= NULL
;
3089 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3091 // save pointer of window being deleted
3092 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3093 wxWindow
* new_active
= NULL
;
3095 // make sure we found the page
3099 // find out which onscreen tab ctrl owns this tab
3102 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3105 bool is_curpage
= (m_curpage
== (int)page_idx
);
3106 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3109 // remove the tab from main catalog
3110 if (!m_tabs
.RemovePage(wnd
))
3113 // remove the tab from the onscreen tab ctrl
3114 ctrl
->RemovePage(wnd
);
3116 if (is_active_in_split
)
3118 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3120 if (ctrl_idx
>= ctrl_new_page_count
)
3121 ctrl_idx
= ctrl_new_page_count
-1;
3123 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3125 // set new page as active in the tab split
3126 ctrl
->SetActivePage(ctrl_idx
);
3128 // if the page deleted was the current page for the
3129 // entire tab control, then record the window
3130 // pointer of the new active page for activation
3133 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3139 // we are not deleting the active page, so keep it the same
3140 new_active
= active_wnd
;
3146 // we haven't yet found a new page to active,
3147 // so select the next page from the main tab
3150 if (page_idx
< m_tabs
.GetPageCount())
3152 new_active
= m_tabs
.GetPage(page_idx
).window
;
3155 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3157 new_active
= m_tabs
.GetPage(0).window
;
3162 RemoveEmptyTabFrames();
3164 // set new active pane
3168 SetSelectionToWindow(new_active
);
3174 // GetPageIndex() returns the index of the page, or -1 if the
3175 // page could not be located in the notebook
3176 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3178 return m_tabs
.GetIdxFromWindow(page_wnd
);
3183 // SetPageText() changes the tab caption of the specified page
3184 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3186 if (page_idx
>= m_tabs
.GetPageCount())
3189 // update our own tab catalog
3190 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3191 page_info
.caption
= text
;
3193 // update what's on screen
3196 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3198 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3199 info
.caption
= text
;
3207 // returns the page caption
3208 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3210 if (page_idx
>= m_tabs
.GetPageCount())
3211 return wxEmptyString
;
3213 // update our own tab catalog
3214 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3215 return page_info
.caption
;
3218 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3220 if (page_idx
>= m_tabs
.GetPageCount())
3223 // update our own tab catalog
3224 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3225 page_info
.bitmap
= bitmap
;
3227 // tab height might have changed
3228 UpdateTabCtrlHeight();
3230 // update what's on screen
3233 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3235 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3236 info
.bitmap
= bitmap
;
3244 // returns the page bitmap
3245 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3247 if (page_idx
>= m_tabs
.GetPageCount())
3250 // update our own tab catalog
3251 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3252 return page_info
.bitmap
;
3255 // GetSelection() returns the index of the currently active page
3256 int wxAuiNotebook::GetSelection() const
3261 // SetSelection() sets the currently active page
3262 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3264 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3268 // don't change the page unless necessary;
3269 // however, clicking again on a tab should give it the focus.
3270 if ((int)new_page
== m_curpage
)
3274 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3276 if (FindFocus() != ctrl
)
3282 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3283 evt
.SetSelection(new_page
);
3284 evt
.SetOldSelection(m_curpage
);
3285 evt
.SetEventObject(this);
3286 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3288 int old_curpage
= m_curpage
;
3289 m_curpage
= new_page
;
3291 // program allows the page change
3292 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3293 (void)GetEventHandler()->ProcessEvent(evt
);
3298 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3300 m_tabs
.SetActivePage(wnd
);
3302 ctrl
->SetActivePage(ctrl_idx
);
3306 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3309 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3310 size_t i
, pane_count
= all_panes
.GetCount();
3311 for (i
= 0; i
< pane_count
; ++i
)
3313 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3314 if (pane
.name
== wxT("dummy"))
3316 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3317 if (tabctrl
!= ctrl
)
3318 tabctrl
->SetSelectedFont(m_normal_font
);
3320 tabctrl
->SetSelectedFont(m_selected_font
);
3324 // Set the focus to the page if we're not currently focused on the tab.
3325 // This is Firefox-like behaviour.
3326 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3336 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3338 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3339 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
3344 // GetPageCount() returns the total number of
3345 // pages managed by the multi-notebook
3346 size_t wxAuiNotebook::GetPageCount() const
3348 return m_tabs
.GetPageCount();
3351 // GetPage() returns the wxWindow pointer of the
3353 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3355 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3357 return m_tabs
.GetWindowFromIdx(page_idx
);
3360 // DoSizing() performs all sizing operations in each tab control
3361 void wxAuiNotebook::DoSizing()
3363 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3364 size_t i
, pane_count
= all_panes
.GetCount();
3365 for (i
= 0; i
< pane_count
; ++i
)
3367 if (all_panes
.Item(i
).name
== wxT("dummy"))
3370 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3371 tabframe
->DoSizing();
3375 // GetActiveTabCtrl() returns the active tab control. It is
3376 // called to determine which control gets new windows being added
3377 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3379 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3384 // find the tab ctrl with the current page
3385 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3392 // no current page, just find the first tab ctrl
3393 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3394 size_t i
, pane_count
= all_panes
.GetCount();
3395 for (i
= 0; i
< pane_count
; ++i
)
3397 if (all_panes
.Item(i
).name
== wxT("dummy"))
3400 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3401 return tabframe
->m_tabs
;
3404 // If there is no tabframe at all, create one
3405 wxTabFrame
* tabframe
= new wxTabFrame
;
3406 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3407 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3411 wxNO_BORDER
|wxWANTS_CHARS
);
3412 tabframe
->m_tabs
->SetFlags(m_flags
);
3413 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3414 m_mgr
.AddPane(tabframe
,
3415 wxAuiPaneInfo().Center().CaptionVisible(false));
3419 return tabframe
->m_tabs
;
3422 // FindTab() finds the tab control that currently contains the window as well
3423 // as the index of the window in the tab control. It returns true if the
3424 // window was found, otherwise false.
3425 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3427 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3428 size_t i
, pane_count
= all_panes
.GetCount();
3429 for (i
= 0; i
< pane_count
; ++i
)
3431 if (all_panes
.Item(i
).name
== wxT("dummy"))
3434 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3436 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3439 *ctrl
= tabframe
->m_tabs
;
3448 void wxAuiNotebook::Split(size_t page
, int direction
)
3450 wxSize cli_size
= GetClientSize();
3452 // get the page's window pointer
3453 wxWindow
* wnd
= GetPage(page
);
3457 // notebooks with 1 or less pages can't be split
3458 if (GetPageCount() < 2)
3461 // find out which tab control the page currently belongs to
3462 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3465 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3467 if (!src_tabs
|| src_idx
== -1)
3470 // choose a split size
3472 if (GetPageCount() > 2)
3474 split_size
= CalculateNewSplitSize();
3478 // because there are two panes, always split them
3480 split_size
= GetClientSize();
3486 // create a new tab frame
3487 wxTabFrame
* new_tabs
= new wxTabFrame
;
3488 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3489 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3490 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3494 wxNO_BORDER
|wxWANTS_CHARS
);
3495 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3496 new_tabs
->m_tabs
->SetFlags(m_flags
);
3497 dest_tabs
= new_tabs
->m_tabs
;
3499 // create a pane info structure with the information
3500 // about where the pane should be added
3501 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3504 if (direction
== wxLEFT
)
3507 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3509 else if (direction
== wxRIGHT
)
3512 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3514 else if (direction
== wxTOP
)
3517 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3519 else if (direction
== wxBOTTOM
)
3522 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3525 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3528 // remove the page from the source tabs
3529 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3530 page_info
.active
= false;
3531 src_tabs
->RemovePage(page_info
.window
);
3532 if (src_tabs
->GetPageCount() > 0)
3534 src_tabs
->SetActivePage((size_t)0);
3535 src_tabs
->DoShowHide();
3536 src_tabs
->Refresh();
3540 // add the page to the destination tabs
3541 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3543 if (src_tabs
->GetPageCount() == 0)
3545 RemoveEmptyTabFrames();
3549 dest_tabs
->DoShowHide();
3550 dest_tabs
->Refresh();
3552 // force the set selection function reset the selection
3555 // set the active page to the one we just split off
3556 SetSelectionToPage(page_info
);
3558 UpdateHintWindowSize();
3562 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3564 UpdateHintWindowSize();
3569 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3571 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3573 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3574 wxASSERT(ctrl
!= NULL
);
3576 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3577 wxASSERT(wnd
!= NULL
);
3579 SetSelectionToWindow(wnd
);
3582 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3587 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3589 wxPoint screen_pt
= ::wxGetMousePosition();
3590 wxPoint client_pt
= ScreenToClient(screen_pt
);
3593 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3594 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3596 if (dest_tabs
== src_tabs
)
3600 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3603 // always hide the hint for inner-tabctrl drag
3606 // if tab moving is not allowed, leave
3607 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3612 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3613 wxWindow
* dest_location_tab
;
3615 // this is an inner-tab drag/reposition
3616 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3618 int src_idx
= evt
.GetSelection();
3619 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3621 // prevent jumpy drag
3622 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3623 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3624 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3626 m_last_drag_x
= pt
.x
;
3631 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3632 dest_tabs
->MovePage(src_tab
, dest_idx
);
3633 dest_tabs
->SetActivePage((size_t)dest_idx
);
3634 dest_tabs
->DoShowHide();
3635 dest_tabs
->Refresh();
3636 m_last_drag_x
= pt
.x
;
3644 // if external drag is allowed, check if the tab is being dragged
3645 // over a different wxAuiNotebook control
3646 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3648 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3650 // if we aren't over any window, stop here
3654 // make sure we are not over the hint window
3655 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3659 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3661 tab_ctrl
= tab_ctrl
->GetParent();
3666 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3670 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3671 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3672 m_mgr
.ShowHint(hint_rect
);
3681 // we are either over a hint window, or not over a tab
3682 // window, and there is no where to drag to, so exit
3689 // if there are less than two panes, split can't happen, so leave
3690 if (m_tabs
.GetPageCount() < 2)
3693 // if tab moving is not allowed, leave
3694 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3700 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3706 wxRect hint_rect
= dest_tabs
->GetRect();
3707 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3708 m_mgr
.ShowHint(hint_rect
);
3712 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3718 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3720 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3725 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3726 wxCHECK_RET( src_tabs
, _T("no source object?") );
3728 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3730 // get the mouse position, which will be used to determine the drop point
3731 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3732 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3736 // check for an external move
3737 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3739 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3743 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3745 tab_ctrl
= tab_ctrl
->GetParent();
3750 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3754 // find out from the destination control
3755 // if it's ok to drop this tab here
3756 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3757 e
.SetSelection(evt
.GetSelection());
3758 e
.SetOldSelection(evt
.GetSelection());
3759 e
.SetEventObject(this);
3760 e
.SetDragSource(this);
3761 e
.Veto(); // dropping must be explicitly approved by control owner
3763 nb
->GetEventHandler()->ProcessEvent(e
);
3767 // no answer or negative answer
3773 int src_idx
= evt
.GetSelection();
3774 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3776 // Check that it's not an impossible parent relationship
3778 while (p
&& !p
->IsTopLevel())
3787 // get main index of the page
3788 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3789 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3792 // make a copy of the page info
3793 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3795 // remove the page from the source notebook
3796 RemovePage(main_idx
);
3798 // reparent the page
3799 src_page
->Reparent(nb
);
3802 // found out the insert idx
3803 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3804 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3806 wxWindow
* target
= NULL
;
3807 int insert_idx
= -1;
3808 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3811 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3815 // add the page to the new notebook
3816 if (insert_idx
== -1)
3817 insert_idx
= dest_tabs
->GetPageCount();
3818 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3819 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3822 dest_tabs
->DoShowHide();
3823 dest_tabs
->Refresh();
3825 // set the selection in the destination tab control
3826 nb
->SetSelectionToPage(page_info
);
3828 // notify owner that the tab has been dragged
3829 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3830 e2
.SetSelection(evt
.GetSelection());
3831 e2
.SetOldSelection(evt
.GetSelection());
3832 e2
.SetEventObject(this);
3833 GetEventHandler()->ProcessEvent(e2
);
3843 // only perform a tab split if it's allowed
3844 wxAuiTabCtrl
* dest_tabs
= NULL
;
3846 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3848 // If the pointer is in an existing tab frame, do a tab insert
3849 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3850 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3851 int insert_idx
= -1;
3854 dest_tabs
= tab_frame
->m_tabs
;
3856 if (dest_tabs
== src_tabs
)
3860 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3861 wxWindow
* target
= NULL
;
3862 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3865 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3871 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3876 // there is no suitable drop location here, exit out
3880 // If there is no tabframe at all, create one
3881 wxTabFrame
* new_tabs
= new wxTabFrame
;
3882 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3883 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3884 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3888 wxNO_BORDER
|wxWANTS_CHARS
);
3889 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3890 new_tabs
->m_tabs
->SetFlags(m_flags
);
3892 m_mgr
.AddPane(new_tabs
,
3893 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3896 dest_tabs
= new_tabs
->m_tabs
;
3901 // remove the page from the source tabs
3902 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3903 page_info
.active
= false;
3904 src_tabs
->RemovePage(page_info
.window
);
3905 if (src_tabs
->GetPageCount() > 0)
3907 src_tabs
->SetActivePage((size_t)0);
3908 src_tabs
->DoShowHide();
3909 src_tabs
->Refresh();
3914 // add the page to the destination tabs
3915 if (insert_idx
== -1)
3916 insert_idx
= dest_tabs
->GetPageCount();
3917 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3919 if (src_tabs
->GetPageCount() == 0)
3921 RemoveEmptyTabFrames();
3925 dest_tabs
->DoShowHide();
3926 dest_tabs
->Refresh();
3928 // force the set selection function reset the selection
3931 // set the active page to the one we just split off
3932 SetSelectionToPage(page_info
);
3934 UpdateHintWindowSize();
3937 // notify owner that the tab has been dragged
3938 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3939 e
.SetSelection(evt
.GetSelection());
3940 e
.SetOldSelection(evt
.GetSelection());
3941 e
.SetEventObject(this);
3942 GetEventHandler()->ProcessEvent(e
);
3947 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3949 // if we've just removed the last tab from the source
3950 // tab set, the remove the tab control completely
3951 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3952 size_t i
, pane_count
= all_panes
.GetCount();
3953 for (i
= 0; i
< pane_count
; ++i
)
3955 if (all_panes
.Item(i
).name
== wxT("dummy"))
3958 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3959 if (tabframe
->m_tab_rect
.Contains(pt
))
3960 return tabframe
->m_tabs
;
3966 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3968 // if we've just removed the last tab from the source
3969 // tab set, the remove the tab control completely
3970 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3971 size_t i
, pane_count
= all_panes
.GetCount();
3972 for (i
= 0; i
< pane_count
; ++i
)
3974 if (all_panes
.Item(i
).name
== wxT("dummy"))
3977 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3978 if (tabframe
->m_tabs
== tab_ctrl
)
3987 void wxAuiNotebook::RemoveEmptyTabFrames()
3989 // if we've just removed the last tab from the source
3990 // tab set, the remove the tab control completely
3991 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3992 size_t i
, pane_count
= all_panes
.GetCount();
3993 for (i
= 0; i
< pane_count
; ++i
)
3995 if (all_panes
.Item(i
).name
== wxT("dummy"))
3998 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3999 if (tab_frame
->m_tabs
->GetPageCount() == 0)
4001 m_mgr
.DetachPane(tab_frame
);
4003 // use pending delete because sometimes during
4004 // window closing, refreshs are pending
4005 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
4006 wxPendingDelete
.Append(tab_frame
->m_tabs
);
4008 tab_frame
->m_tabs
= NULL
;
4015 // check to see if there is still a center pane;
4016 // if there isn't, make a frame the center pane
4017 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4018 pane_count
= panes
.GetCount();
4019 wxWindow
* first_good
= NULL
;
4020 bool center_found
= false;
4021 for (i
= 0; i
< pane_count
; ++i
)
4023 if (panes
.Item(i
).name
== wxT("dummy"))
4025 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4026 center_found
= true;
4028 first_good
= panes
.Item(i
).window
;
4031 if (!center_found
&& first_good
)
4033 m_mgr
.GetPane(first_good
).Centre();
4039 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4041 // if we're dragging a tab, don't change the current selection.
4042 // This code prevents a bug that used to happen when the hint window
4043 // was hidden. In the bug, the focus would return to the notebook
4044 // child, which would then enter this handler and call
4045 // SetSelection, which is not desired turn tab dragging.
4047 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4048 size_t i
, pane_count
= all_panes
.GetCount();
4049 for (i
= 0; i
< pane_count
; ++i
)
4051 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4052 if (pane
.name
== wxT("dummy"))
4054 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4055 if (tabframe
->m_tabs
->IsDragging())
4060 // change the tab selection to the child
4061 // which was focused
4062 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4063 if (idx
!= -1 && idx
!= m_curpage
)
4069 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4071 if ( event
.IsWindowChange() ) {
4073 // FIXME: the problem with this is that if we have a split notebook,
4074 // we selection may go all over the place.
4075 AdvanceSelection(event
.GetDirection());
4078 // we get this event in 3 cases
4080 // a) one of our pages might have generated it because the user TABbed
4081 // out from it in which case we should propagate the event upwards and
4082 // our parent will take care of setting the focus to prev/next sibling
4086 // b) the parent panel wants to give the focus to us so that we
4087 // forward it to our selected page. We can't deal with this in
4088 // OnSetFocus() because we don't know which direction the focus came
4089 // from in this case and so can't choose between setting the focus to
4090 // first or last panel child
4094 // c) we ourselves (see MSWTranslateMessage) generated the event
4096 wxWindow
* const parent
= GetParent();
4098 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4099 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4100 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4102 if ( isFromParent
|| isFromSelf
)
4104 // no, it doesn't come from child, case (b) or (c): forward to a
4105 // page but only if direction is backwards (TAB) or from ourselves,
4106 if ( GetSelection() != wxNOT_FOUND
&&
4107 (!event
.GetDirection() || isFromSelf
) )
4109 // so that the page knows that the event comes from it's parent
4110 // and is being propagated downwards
4111 event
.SetEventObject(this);
4113 wxWindow
*page
= GetPage(GetSelection());
4114 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4118 //else: page manages focus inside it itself
4120 else // otherwise set the focus to the notebook itself
4127 // it comes from our child, case (a), pass to the parent, but only
4128 // if the direction is forwards. Otherwise set the focus to the
4129 // notebook itself. The notebook is always the 'first' control of a
4131 if ( !event
.GetDirection() )
4137 event
.SetCurrentFocus(this);
4138 parent
->GetEventHandler()->ProcessEvent(event
);
4144 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
4146 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
4147 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4149 int button_id
= evt
.GetInt();
4151 if (button_id
== wxAUI_BUTTON_CLOSE
)
4153 int selection
= evt
.GetSelection();
4155 if (selection
== -1)
4157 // if the close button is to the right, use the active
4158 // page selection to determine which page to close
4159 selection
= GetSelection();
4162 if (selection
!= -1)
4164 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4166 // ask owner if it's ok to close the tab
4167 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4168 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4169 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4170 e
.SetSelection(idx
);
4171 e
.SetOldSelection(evt
.GetSelection());
4172 e
.SetEventObject(this);
4173 GetEventHandler()->ProcessEvent(e
);
4179 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4186 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4187 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
4189 DeletePage(main_idx
);
4192 // notify owner that the tab has been closed
4193 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4194 e2
.SetSelection(idx
);
4195 e2
.SetEventObject(this);
4196 GetEventHandler()->ProcessEvent(e2
);
4202 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
4204 // patch event through to owner
4205 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4206 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4208 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4209 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4210 e
.SetEventObject(this);
4211 GetEventHandler()->ProcessEvent(e
);
4214 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
4216 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4217 // click should act like a tab close action. However, first
4218 // give the owner an opportunity to handle the middle up event
4219 // for custom action
4221 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4222 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4224 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4225 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4226 e
.SetEventObject(this);
4227 if (GetEventHandler()->ProcessEvent(e
))
4232 // check if we are supposed to close on middle-up
4233 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4236 // simulate the user pressing the close button on the tab
4237 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4241 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
4243 // patch event through to owner
4244 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4245 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4247 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4248 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4249 e
.SetEventObject(this);
4250 GetEventHandler()->ProcessEvent(e
);
4253 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
4255 // patch event through to owner
4256 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4257 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4259 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4260 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4261 e
.SetEventObject(this);
4262 GetEventHandler()->ProcessEvent(e
);
4265 // Sets the normal font
4266 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4268 m_normal_font
= font
;
4269 GetArtProvider()->SetNormalFont(font
);
4272 // Sets the selected tab font
4273 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4275 m_selected_font
= font
;
4276 GetArtProvider()->SetSelectedFont(font
);
4279 // Sets the measuring font
4280 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4282 GetArtProvider()->SetMeasuringFont(font
);
4285 // Sets the tab font
4286 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4288 wxControl::SetFont(font
);
4290 wxFont
normalFont(font
);
4291 wxFont
selectedFont(normalFont
);
4292 selectedFont
.SetWeight(wxBOLD
);
4294 SetNormalFont(normalFont
);
4295 SetSelectedFont(selectedFont
);
4296 SetMeasuringFont(selectedFont
);
4301 // Gets the tab control height
4302 int wxAuiNotebook::GetTabCtrlHeight() const
4304 return m_tab_ctrl_height
;
4307 // Gets the height of the notebook for a given page height
4308 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4310 UpdateTabCtrlHeight();
4312 int tabCtrlHeight
= GetTabCtrlHeight();
4313 int decorHeight
= 2;
4314 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4317 // Advances the selection, generation page selection events
4318 void wxAuiNotebook::AdvanceSelection(bool forward
)
4320 if (GetPageCount() <= 1)
4323 int currentSelection
= GetSelection();
4327 if (currentSelection
== (int) (GetPageCount() - 1))
4329 else if (currentSelection
== -1)
4330 currentSelection
= 0;
4332 currentSelection
++;
4336 if (currentSelection
<= 0)
4339 currentSelection
--;
4342 SetSelection(currentSelection
);
4345 // Shows the window menu
4346 bool wxAuiNotebook::ShowWindowMenu()
4348 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4350 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4354 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4355 e
.SetSelection(idx
);
4356 e
.SetOldSelection(tabCtrl
->GetActivePage());
4357 e
.SetEventObject(tabCtrl
);
4358 GetEventHandler()->ProcessEvent(e
);