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
);
1952 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1954 if (rect
.width
<= 0)
1955 return false; // haven't found the tab, and we've run out of space, so return false
1958 wxSize size
= m_art
->GetTabSize(*dc
,
1963 tab_button
.cur_state
,
1968 if (i
== (size_t) tabPage
)
1970 // If not all of the tab is visible, and supposing there's space to display it all,
1971 // we could do better so we return false.
1972 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
1979 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
1980 // further looping in calling code.
1984 // Make the tab visible if it wasn't already
1985 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
)
1988 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
1991 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
1993 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2003 // TabHitTest() tests if a tab was hit, passing the window pointer
2004 // back if that condition was fulfilled. The function returns
2005 // true if a tab was hit, otherwise false
2006 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2008 if (!m_rect
.Contains(x
,y
))
2011 wxAuiTabContainerButton
* btn
= NULL
;
2012 if (ButtonHitTest(x
, y
, &btn
))
2014 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2018 size_t i
, page_count
= m_pages
.GetCount();
2020 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2022 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2023 if (page
.rect
.Contains(x
,y
))
2034 // ButtonHitTest() tests if a button was hit. The function returns
2035 // true if a button was hit, otherwise false
2036 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
2037 wxAuiTabContainerButton
** hit
) const
2039 if (!m_rect
.Contains(x
,y
))
2042 size_t i
, button_count
;
2045 button_count
= m_buttons
.GetCount();
2046 for (i
= 0; i
< button_count
; ++i
)
2048 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2049 if (button
.rect
.Contains(x
,y
) &&
2050 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2051 wxAUI_BUTTON_STATE_DISABLED
)))
2059 button_count
= m_tab_close_buttons
.GetCount();
2060 for (i
= 0; i
< button_count
; ++i
)
2062 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2063 if (button
.rect
.Contains(x
,y
) &&
2064 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2065 wxAUI_BUTTON_STATE_DISABLED
)))
2078 // the utility function ShowWnd() is the same as show,
2079 // except it handles wxAuiMDIChildFrame windows as well,
2080 // as the Show() method on this class is "unplugged"
2081 static void ShowWnd(wxWindow
* wnd
, bool show
)
2084 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2086 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2097 // DoShowHide() this function shows the active window, then
2098 // hides all of the other windows (in that order)
2099 void wxAuiTabContainer::DoShowHide()
2101 wxAuiNotebookPageArray
& pages
= GetPages();
2102 size_t i
, page_count
= pages
.GetCount();
2104 // show new active page first
2105 for (i
= 0; i
< page_count
; ++i
)
2107 wxAuiNotebookPage
& page
= pages
.Item(i
);
2110 ShowWnd(page
.window
, true);
2115 // hide all other pages
2116 for (i
= 0; i
< page_count
; ++i
)
2118 wxAuiNotebookPage
& page
= pages
.Item(i
);
2120 ShowWnd(page
.window
, false);
2129 // -- wxAuiTabCtrl class implementation --
2133 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2134 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
2135 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
2136 EVT_SIZE(wxAuiTabCtrl::OnSize
)
2137 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
2138 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
2139 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
2140 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
2141 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
2142 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
2143 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
2144 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
2145 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
2146 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
2147 EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
)
2148 EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
)
2149 EVT_CHAR(wxAuiTabCtrl::OnChar
)
2153 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
2157 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2159 SetName(wxT("wxAuiTabCtrl"));
2160 m_click_pt
= wxDefaultPosition
;
2161 m_is_dragging
= false;
2162 m_hover_button
= NULL
;
2163 m_pressed_button
= NULL
;
2166 wxAuiTabCtrl::~wxAuiTabCtrl()
2170 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
2174 dc
.SetFont(GetFont());
2176 if (GetPageCount() > 0)
2180 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2184 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2186 wxSize s
= evt
.GetSize();
2187 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2191 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2194 m_click_pt
= wxDefaultPosition
;
2195 m_is_dragging
= false;
2197 m_pressed_button
= NULL
;
2201 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2203 int new_selection
= GetIdxFromWindow(wnd
);
2205 // wxAuiNotebooks always want to receive this event
2206 // even if the tab is already active, because they may
2207 // have multiple tab controls
2208 if (new_selection
!= GetActivePage() ||
2209 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2211 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2212 e
.SetSelection(new_selection
);
2213 e
.SetOldSelection(GetActivePage());
2214 e
.SetEventObject(this);
2215 GetEventHandler()->ProcessEvent(e
);
2218 m_click_pt
.x
= evt
.m_x
;
2219 m_click_pt
.y
= evt
.m_y
;
2225 m_pressed_button
= m_hover_button
;
2226 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2232 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2234 if (GetCapture() == this)
2239 m_is_dragging
= false;
2241 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2242 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2243 evt
.SetOldSelection(evt
.GetSelection());
2244 evt
.SetEventObject(this);
2245 GetEventHandler()->ProcessEvent(evt
);
2250 if (m_pressed_button
)
2252 // make sure we're still clicking the button
2253 wxAuiTabContainerButton
* button
= NULL
;
2254 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2257 if (button
!= m_pressed_button
)
2259 m_pressed_button
= NULL
;
2266 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2268 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2269 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2270 evt
.SetInt(m_pressed_button
->id
);
2271 evt
.SetEventObject(this);
2272 GetEventHandler()->ProcessEvent(evt
);
2275 m_pressed_button
= NULL
;
2278 m_click_pt
= wxDefaultPosition
;
2279 m_is_dragging
= false;
2283 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2285 wxWindow
* wnd
= NULL
;
2286 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2289 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2290 e
.SetEventObject(this);
2291 e
.SetSelection(GetIdxFromWindow(wnd
));
2292 GetEventHandler()->ProcessEvent(e
);
2295 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2297 wxWindow
* wnd
= NULL
;
2298 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2301 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2302 e
.SetEventObject(this);
2303 e
.SetSelection(GetIdxFromWindow(wnd
));
2304 GetEventHandler()->ProcessEvent(e
);
2307 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2309 wxWindow
* wnd
= NULL
;
2310 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2313 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2314 e
.SetEventObject(this);
2315 e
.SetSelection(GetIdxFromWindow(wnd
));
2316 GetEventHandler()->ProcessEvent(e
);
2319 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2321 wxWindow
* wnd
= NULL
;
2322 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2325 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2326 e
.SetEventObject(this);
2327 e
.SetSelection(GetIdxFromWindow(wnd
));
2328 GetEventHandler()->ProcessEvent(e
);
2331 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2333 wxPoint pos
= evt
.GetPosition();
2335 // check if the mouse is hovering above a button
2336 wxAuiTabContainerButton
* button
;
2337 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2339 if (m_hover_button
&& button
!= m_hover_button
)
2341 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2342 m_hover_button
= NULL
;
2347 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2349 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2352 m_hover_button
= button
;
2360 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2361 m_hover_button
= NULL
;
2368 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2373 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2374 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2375 evt
.SetOldSelection(evt
.GetSelection());
2376 evt
.SetEventObject(this);
2377 GetEventHandler()->ProcessEvent(evt
);
2382 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2383 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2385 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2386 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2388 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2389 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2390 evt
.SetOldSelection(evt
.GetSelection());
2391 evt
.SetEventObject(this);
2392 GetEventHandler()->ProcessEvent(evt
);
2394 m_is_dragging
= true;
2398 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2402 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2403 m_hover_button
= NULL
;
2409 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2411 int button
= event
.GetInt();
2413 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2415 if (button
== wxAUI_BUTTON_LEFT
)
2417 if (GetTabOffset() > 0)
2419 SetTabOffset(GetTabOffset()-1);
2426 SetTabOffset(GetTabOffset()+1);
2431 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2433 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2437 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2438 e
.SetSelection(idx
);
2439 e
.SetOldSelection(GetActivePage());
2440 e
.SetEventObject(this);
2441 GetEventHandler()->ProcessEvent(e
);
2450 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2455 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2460 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
)
2462 if (GetActivePage() == -1)
2468 // We can't leave tab processing to the system; on Windows, tabs and keys
2469 // get eaten by the system and not processed properly if we specify both
2470 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2471 // we don't key arrow key events.
2473 int key
= event
.GetKeyCode();
2475 if (key
== WXK_NUMPAD_PAGEUP
)
2477 if (key
== WXK_NUMPAD_PAGEDOWN
)
2479 if (key
== WXK_NUMPAD_HOME
)
2481 if (key
== WXK_NUMPAD_END
)
2483 if (key
== WXK_NUMPAD_LEFT
)
2485 if (key
== WXK_NUMPAD_RIGHT
)
2488 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2490 bool bCtrlDown
= event
.ControlDown();
2491 bool bShiftDown
= event
.ShiftDown();
2493 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2494 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2495 bool bFromTab
= (key
== WXK_TAB
);
2497 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2504 wxNavigationKeyEvent keyEvent
;
2505 keyEvent
.SetDirection(bForward
);
2506 keyEvent
.SetWindowChange(bWindowChange
);
2507 keyEvent
.SetFromTab(bFromTab
);
2508 keyEvent
.SetEventObject(nb
);
2510 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2512 // Not processed? Do an explicit tab into the page.
2513 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2520 if (m_pages
.GetCount() < 2)
2528 if (key
== WXK_RIGHT
)
2530 if (m_pages
.GetCount() > 1)
2532 if (GetActivePage() == -1)
2534 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2535 newPage
= GetActivePage() + 1;
2538 else if (key
== WXK_LEFT
)
2540 if (m_pages
.GetCount() > 1)
2542 if (GetActivePage() == -1)
2543 newPage
= (int) (m_pages
.GetCount() - 1);
2544 else if (GetActivePage() > 0)
2545 newPage
= GetActivePage() - 1;
2548 else if (key
== WXK_HOME
)
2552 else if (key
== WXK_END
)
2554 newPage
= (int) (m_pages
.GetCount() - 1);
2561 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2562 e
.SetSelection(newPage
);
2563 e
.SetOldSelection(newPage
);
2564 e
.SetEventObject(this);
2565 this->GetEventHandler()->ProcessEvent(e
);
2571 // wxTabFrame is an interesting case. It's important that all child pages
2572 // of the multi-notebook control are all actually children of that control
2573 // (and not grandchildren). wxTabFrame facilitates this. There is one
2574 // instance of wxTabFrame for each tab control inside the multi-notebook.
2575 // It's important to know that wxTabFrame is not a real window, but it merely
2576 // used to capture the dimensions/positioning of the internal tab control and
2577 // it's managed page windows
2579 class wxTabFrame
: public wxWindow
2586 m_rect
= wxRect(0,0,200,200);
2587 m_tab_ctrl_height
= 20;
2595 void SetTabCtrlHeight(int h
)
2597 m_tab_ctrl_height
= h
;
2601 void DoSetSize(int x
, int y
,
2602 int width
, int height
,
2603 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2605 m_rect
= wxRect(x
, y
, width
, height
);
2609 void DoGetClientSize(int* x
, int* y
) const
2616 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2623 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2624 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2625 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2629 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2630 size_t i
, page_count
= pages
.GetCount();
2632 for (i
= 0; i
< page_count
; ++i
)
2634 wxAuiNotebookPage
& page
= pages
.Item(i
);
2635 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2636 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2639 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2641 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2642 wnd
->ApplyMDIChildFrameRect();
2649 void DoGetSize(int* x
, int* y
) const
2652 *x
= m_rect
.GetWidth();
2654 *y
= m_rect
.GetHeight();
2665 wxAuiTabCtrl
* m_tabs
;
2666 int m_tab_ctrl_height
;
2670 const int wxAuiBaseTabCtrlId
= 5380;
2673 // -- wxAuiNotebook class implementation --
2675 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2676 EVT_SIZE(wxAuiNotebook::OnSize
)
2677 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
)
2678 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2679 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2680 wxAuiNotebook::OnTabClicked
)
2681 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2682 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2683 wxAuiNotebook::OnTabBeginDrag
)
2684 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2685 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2686 wxAuiNotebook::OnTabEndDrag
)
2687 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2688 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2689 wxAuiNotebook::OnTabDragMotion
)
2690 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2691 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2692 wxAuiNotebook::OnTabButton
)
2693 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2694 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2695 wxAuiNotebook::OnTabMiddleDown
)
2696 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2697 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2698 wxAuiNotebook::OnTabMiddleUp
)
2699 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2700 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2701 wxAuiNotebook::OnTabRightDown
)
2702 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2703 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2704 wxAuiNotebook::OnTabRightUp
)
2705 EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
)
2707 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2708 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2710 // Avoid clash with container event handler functions
2711 EVT_SET_FOCUS(wxAuiNotebook::OnFocus
)
2715 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2717 wxAuiNotebook::wxAuiNotebook()
2720 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2722 m_tab_ctrl_height
= 20;
2723 m_requested_bmp_size
= wxDefaultSize
;
2724 m_requested_tabctrl_height
= -1;
2727 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2731 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2734 m_requested_bmp_size
= wxDefaultSize
;
2735 m_requested_tabctrl_height
= -1;
2736 InitNotebook(style
);
2739 bool wxAuiNotebook::Create(wxWindow
* parent
,
2745 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2748 InitNotebook(style
);
2753 // InitNotebook() contains common initialization
2754 // code called by all constructors
2755 void wxAuiNotebook::InitNotebook(long style
)
2757 WX_INIT_CONTROL_CONTAINER();
2758 // SetCanFocus(false);
2760 SetName(wxT("wxAuiNotebook"));
2762 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2764 m_flags
= (unsigned int)style
;
2765 m_tab_ctrl_height
= 20;
2767 m_normal_font
= *wxNORMAL_FONT
;
2768 m_selected_font
= *wxNORMAL_FONT
;
2769 m_selected_font
.SetWeight(wxBOLD
);
2771 SetArtProvider(new wxAuiDefaultTabArt
);
2773 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2774 m_dummy_wnd
->SetSize(200, 200);
2775 m_dummy_wnd
->Show(false);
2777 m_mgr
.SetManagedWindow(this);
2778 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2779 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2781 m_mgr
.AddPane(m_dummy_wnd
,
2782 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2787 wxAuiNotebook::~wxAuiNotebook()
2789 while ( GetPageCount() > 0 )
2795 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2797 m_tabs
.SetArtProvider(art
);
2799 UpdateTabCtrlHeight();
2802 // SetTabCtrlHeight() is the highest-level override of the
2803 // tab height. A call to this function effectively enforces a
2804 // specified tab ctrl height, overriding all other considerations,
2805 // such as text or bitmap height. It overrides any call to
2806 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2807 // any previous call and returns to the default behavior
2809 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2811 m_requested_tabctrl_height
= height
;
2813 // if window is already initialized, recalculate the tab height
2816 UpdateTabCtrlHeight();
2821 // SetUniformBitmapSize() ensures that all tabs will have
2822 // the same height, even if some tabs don't have bitmaps
2823 // Passing wxDefaultSize to this function will instruct
2824 // the control to use dynamic tab height-- so when a tab
2825 // with a large bitmap is added, the tab ctrl's height will
2826 // automatically increase to accommodate the bitmap
2828 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2830 m_requested_bmp_size
= size
;
2832 // if window is already initialized, recalculate the tab height
2835 UpdateTabCtrlHeight();
2839 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2840 // to be used interally
2841 void wxAuiNotebook::UpdateTabCtrlHeight()
2843 // get the tab ctrl height we will use
2844 int height
= CalculateTabCtrlHeight();
2846 // if the tab control height needs to change, update
2847 // all of our tab controls with the new height
2848 if (m_tab_ctrl_height
!= height
)
2850 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2852 m_tab_ctrl_height
= height
;
2854 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2855 size_t i
, pane_count
= all_panes
.GetCount();
2856 for (i
= 0; i
< pane_count
; ++i
)
2858 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2859 if (pane
.name
== wxT("dummy"))
2861 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2862 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2863 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2864 tabctrl
->SetArtProvider(art
->Clone());
2865 tab_frame
->DoSizing();
2870 void wxAuiNotebook::UpdateHintWindowSize()
2872 wxSize size
= CalculateNewSplitSize();
2874 // the placeholder hint window should be set to this size
2875 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2879 info
.BestSize(size
);
2880 m_dummy_wnd
->SetSize(size
);
2885 // calculates the size of the new split
2886 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2888 // count number of tab controls
2889 int tab_ctrl_count
= 0;
2890 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2891 size_t i
, pane_count
= all_panes
.GetCount();
2892 for (i
= 0; i
< pane_count
; ++i
)
2894 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2895 if (pane
.name
== wxT("dummy"))
2900 wxSize new_split_size
;
2902 // if there is only one tab control, the first split
2903 // should happen around the middle
2904 if (tab_ctrl_count
< 2)
2906 new_split_size
= GetClientSize();
2907 new_split_size
.x
/= 2;
2908 new_split_size
.y
/= 2;
2912 // this is in place of a more complicated calculation
2913 // that needs to be implemented
2914 new_split_size
= wxSize(180,180);
2917 return new_split_size
;
2920 int wxAuiNotebook::CalculateTabCtrlHeight()
2922 // if a fixed tab ctrl height is specified,
2923 // just return that instead of calculating a
2925 if (m_requested_tabctrl_height
!= -1)
2926 return m_requested_tabctrl_height
;
2928 // find out new best tab height
2929 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2931 return art
->GetBestTabCtrlSize(this,
2933 m_requested_bmp_size
);
2937 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2939 return m_tabs
.GetArtProvider();
2942 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2944 wxControl::SetWindowStyleFlag(style
);
2946 m_flags
= (unsigned int)style
;
2948 // if the control is already initialized
2949 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2951 // let all of the tab children know about the new style
2953 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2954 size_t i
, pane_count
= all_panes
.GetCount();
2955 for (i
= 0; i
< pane_count
; ++i
)
2957 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2958 if (pane
.name
== wxT("dummy"))
2960 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2961 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2962 tabctrl
->SetFlags(m_flags
);
2963 tabframe
->DoSizing();
2971 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2972 const wxString
& caption
,
2974 const wxBitmap
& bitmap
)
2976 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2979 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2981 const wxString
& caption
,
2983 const wxBitmap
& bitmap
)
2985 page
->Reparent(this);
2987 wxAuiNotebookPage info
;
2989 info
.caption
= caption
;
2990 info
.bitmap
= bitmap
;
2991 info
.active
= false;
2993 // if there are currently no tabs, the first added
2994 // tab must be active
2995 if (m_tabs
.GetPageCount() == 0)
2998 m_tabs
.InsertPage(page
, info
, page_idx
);
3000 // if that was the first page added, even if
3001 // select is false, it must become the "current page"
3002 // (though no select events will be fired)
3003 if (!select
&& m_tabs
.GetPageCount() == 1)
3005 //m_curpage = GetPageIndex(page);
3007 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3008 if (page_idx
>= active_tabctrl
->GetPageCount())
3009 active_tabctrl
->AddPage(page
, info
);
3011 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3013 UpdateTabCtrlHeight();
3015 active_tabctrl
->DoShowHide();
3017 // adjust selected index
3018 if(m_curpage
>= (int) page_idx
)
3023 SetSelectionToWindow(page
);
3030 // DeletePage() removes a tab from the multi-notebook,
3031 // and destroys the window as well
3032 bool wxAuiNotebook::DeletePage(size_t page_idx
)
3034 if (page_idx
>= m_tabs
.GetPageCount())
3037 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3039 // hide the window in advance, as this will
3041 ShowWnd(wnd
, false);
3043 if (!RemovePage(page_idx
))
3047 // actually destroy the window now
3048 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3050 // delete the child frame with pending delete, as is
3051 // customary with frame windows
3052 if (!wxPendingDelete
.Member(wnd
))
3053 wxPendingDelete
.Append(wnd
);
3066 // RemovePage() removes a tab from the multi-notebook,
3067 // but does not destroy the window
3068 bool wxAuiNotebook::RemovePage(size_t page_idx
)
3070 // save active window pointer
3071 wxWindow
* active_wnd
= NULL
;
3073 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3075 // save pointer of window being deleted
3076 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3077 wxWindow
* new_active
= NULL
;
3079 // make sure we found the page
3083 // find out which onscreen tab ctrl owns this tab
3086 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3089 bool is_curpage
= (m_curpage
== (int)page_idx
);
3090 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3093 // remove the tab from main catalog
3094 if (!m_tabs
.RemovePage(wnd
))
3097 // remove the tab from the onscreen tab ctrl
3098 ctrl
->RemovePage(wnd
);
3100 if (is_active_in_split
)
3102 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3104 if (ctrl_idx
>= ctrl_new_page_count
)
3105 ctrl_idx
= ctrl_new_page_count
-1;
3107 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3109 // set new page as active in the tab split
3110 ctrl
->SetActivePage(ctrl_idx
);
3112 // if the page deleted was the current page for the
3113 // entire tab control, then record the window
3114 // pointer of the new active page for activation
3117 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3123 // we are not deleting the active page, so keep it the same
3124 new_active
= active_wnd
;
3130 // we haven't yet found a new page to active,
3131 // so select the next page from the main tab
3134 if (page_idx
< m_tabs
.GetPageCount())
3136 new_active
= m_tabs
.GetPage(page_idx
).window
;
3139 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3141 new_active
= m_tabs
.GetPage(0).window
;
3146 RemoveEmptyTabFrames();
3148 // set new active pane
3152 SetSelectionToWindow(new_active
);
3158 // GetPageIndex() returns the index of the page, or -1 if the
3159 // page could not be located in the notebook
3160 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
3162 return m_tabs
.GetIdxFromWindow(page_wnd
);
3167 // SetPageText() changes the tab caption of the specified page
3168 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
3170 if (page_idx
>= m_tabs
.GetPageCount())
3173 // update our own tab catalog
3174 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3175 page_info
.caption
= text
;
3177 // update what's on screen
3180 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3182 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3183 info
.caption
= text
;
3191 // returns the page caption
3192 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
3194 if (page_idx
>= m_tabs
.GetPageCount())
3195 return wxEmptyString
;
3197 // update our own tab catalog
3198 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3199 return page_info
.caption
;
3202 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3204 if (page_idx
>= m_tabs
.GetPageCount())
3207 // update our own tab catalog
3208 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3209 page_info
.bitmap
= bitmap
;
3211 // tab height might have changed
3212 UpdateTabCtrlHeight();
3214 // update what's on screen
3217 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3219 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3220 info
.bitmap
= bitmap
;
3228 // returns the page bitmap
3229 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
3231 if (page_idx
>= m_tabs
.GetPageCount())
3234 // update our own tab catalog
3235 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3236 return page_info
.bitmap
;
3239 // GetSelection() returns the index of the currently active page
3240 int wxAuiNotebook::GetSelection() const
3245 // SetSelection() sets the currently active page
3246 size_t wxAuiNotebook::SetSelection(size_t new_page
)
3248 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3252 // don't change the page unless necessary;
3253 // however, clicking again on a tab should give it the focus.
3254 if ((int)new_page
== m_curpage
)
3258 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3260 if (FindFocus() != ctrl
)
3266 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3267 evt
.SetSelection(new_page
);
3268 evt
.SetOldSelection(m_curpage
);
3269 evt
.SetEventObject(this);
3270 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3272 int old_curpage
= m_curpage
;
3273 m_curpage
= new_page
;
3275 // program allows the page change
3276 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3277 (void)GetEventHandler()->ProcessEvent(evt
);
3282 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3284 m_tabs
.SetActivePage(wnd
);
3286 ctrl
->SetActivePage(ctrl_idx
);
3290 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3293 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3294 size_t i
, pane_count
= all_panes
.GetCount();
3295 for (i
= 0; i
< pane_count
; ++i
)
3297 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3298 if (pane
.name
== wxT("dummy"))
3300 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3301 if (tabctrl
!= ctrl
)
3302 tabctrl
->SetSelectedFont(m_normal_font
);
3304 tabctrl
->SetSelectedFont(m_selected_font
);
3308 // Set the focus to the page if we're not currently focused on the tab.
3309 // This is Firefox-like behaviour.
3310 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3320 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
3322 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3323 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
3328 // GetPageCount() returns the total number of
3329 // pages managed by the multi-notebook
3330 size_t wxAuiNotebook::GetPageCount() const
3332 return m_tabs
.GetPageCount();
3335 // GetPage() returns the wxWindow pointer of the
3337 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
3339 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3341 return m_tabs
.GetWindowFromIdx(page_idx
);
3344 // DoSizing() performs all sizing operations in each tab control
3345 void wxAuiNotebook::DoSizing()
3347 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3348 size_t i
, pane_count
= all_panes
.GetCount();
3349 for (i
= 0; i
< pane_count
; ++i
)
3351 if (all_panes
.Item(i
).name
== wxT("dummy"))
3354 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3355 tabframe
->DoSizing();
3359 // GetActiveTabCtrl() returns the active tab control. It is
3360 // called to determine which control gets new windows being added
3361 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3363 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3368 // find the tab ctrl with the current page
3369 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3376 // no current page, just find the first tab ctrl
3377 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3378 size_t i
, pane_count
= all_panes
.GetCount();
3379 for (i
= 0; i
< pane_count
; ++i
)
3381 if (all_panes
.Item(i
).name
== wxT("dummy"))
3384 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3385 return tabframe
->m_tabs
;
3388 // If there is no tabframe at all, create one
3389 wxTabFrame
* tabframe
= new wxTabFrame
;
3390 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3391 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3395 wxNO_BORDER
|wxWANTS_CHARS
);
3396 tabframe
->m_tabs
->SetFlags(m_flags
);
3397 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3398 m_mgr
.AddPane(tabframe
,
3399 wxAuiPaneInfo().Center().CaptionVisible(false));
3403 return tabframe
->m_tabs
;
3406 // FindTab() finds the tab control that currently contains the window as well
3407 // as the index of the window in the tab control. It returns true if the
3408 // window was found, otherwise false.
3409 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3411 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3412 size_t i
, pane_count
= all_panes
.GetCount();
3413 for (i
= 0; i
< pane_count
; ++i
)
3415 if (all_panes
.Item(i
).name
== wxT("dummy"))
3418 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3420 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3423 *ctrl
= tabframe
->m_tabs
;
3432 void wxAuiNotebook::Split(size_t page
, int direction
)
3434 wxSize cli_size
= GetClientSize();
3436 // get the page's window pointer
3437 wxWindow
* wnd
= GetPage(page
);
3441 // notebooks with 1 or less pages can't be split
3442 if (GetPageCount() < 2)
3445 // find out which tab control the page currently belongs to
3446 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3449 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3451 if (!src_tabs
|| src_idx
== -1)
3454 // choose a split size
3456 if (GetPageCount() > 2)
3458 split_size
= CalculateNewSplitSize();
3462 // because there are two panes, always split them
3464 split_size
= GetClientSize();
3470 // create a new tab frame
3471 wxTabFrame
* new_tabs
= new wxTabFrame
;
3472 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3473 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3474 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3478 wxNO_BORDER
|wxWANTS_CHARS
);
3479 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3480 new_tabs
->m_tabs
->SetFlags(m_flags
);
3481 dest_tabs
= new_tabs
->m_tabs
;
3483 // create a pane info structure with the information
3484 // about where the pane should be added
3485 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3488 if (direction
== wxLEFT
)
3491 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3493 else if (direction
== wxRIGHT
)
3496 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3498 else if (direction
== wxTOP
)
3501 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3503 else if (direction
== wxBOTTOM
)
3506 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3509 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3512 // remove the page from the source tabs
3513 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3514 page_info
.active
= false;
3515 src_tabs
->RemovePage(page_info
.window
);
3516 if (src_tabs
->GetPageCount() > 0)
3518 src_tabs
->SetActivePage((size_t)0);
3519 src_tabs
->DoShowHide();
3520 src_tabs
->Refresh();
3524 // add the page to the destination tabs
3525 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3527 if (src_tabs
->GetPageCount() == 0)
3529 RemoveEmptyTabFrames();
3533 dest_tabs
->DoShowHide();
3534 dest_tabs
->Refresh();
3536 // force the set selection function reset the selection
3539 // set the active page to the one we just split off
3540 SetSelectionToPage(page_info
);
3542 UpdateHintWindowSize();
3546 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3548 UpdateHintWindowSize();
3553 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3555 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3557 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3558 wxASSERT(ctrl
!= NULL
);
3560 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3561 wxASSERT(wnd
!= NULL
);
3563 SetSelectionToWindow(wnd
);
3566 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3571 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3573 wxPoint screen_pt
= ::wxGetMousePosition();
3574 wxPoint client_pt
= ScreenToClient(screen_pt
);
3577 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3578 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3580 if (dest_tabs
== src_tabs
)
3584 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3587 // always hide the hint for inner-tabctrl drag
3590 // if tab moving is not allowed, leave
3591 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3596 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3597 wxWindow
* dest_location_tab
;
3599 // this is an inner-tab drag/reposition
3600 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3602 int src_idx
= evt
.GetSelection();
3603 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3605 // prevent jumpy drag
3606 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3607 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3608 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3610 m_last_drag_x
= pt
.x
;
3615 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3616 dest_tabs
->MovePage(src_tab
, dest_idx
);
3617 dest_tabs
->SetActivePage((size_t)dest_idx
);
3618 dest_tabs
->DoShowHide();
3619 dest_tabs
->Refresh();
3620 m_last_drag_x
= pt
.x
;
3628 // if external drag is allowed, check if the tab is being dragged
3629 // over a different wxAuiNotebook control
3630 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3632 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3634 // if we aren't over any window, stop here
3638 // make sure we are not over the hint window
3639 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3643 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3645 tab_ctrl
= tab_ctrl
->GetParent();
3650 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3654 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3655 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3656 m_mgr
.ShowHint(hint_rect
);
3665 // we are either over a hint window, or not over a tab
3666 // window, and there is no where to drag to, so exit
3673 // if there are less than two panes, split can't happen, so leave
3674 if (m_tabs
.GetPageCount() < 2)
3677 // if tab moving is not allowed, leave
3678 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3684 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3690 wxRect hint_rect
= dest_tabs
->GetRect();
3691 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3692 m_mgr
.ShowHint(hint_rect
);
3696 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3702 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3704 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3709 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3710 wxCHECK_RET( src_tabs
, _T("no source object?") );
3712 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3714 // get the mouse position, which will be used to determine the drop point
3715 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3716 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3720 // check for an external move
3721 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3723 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3727 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3729 tab_ctrl
= tab_ctrl
->GetParent();
3734 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3738 // find out from the destination control
3739 // if it's ok to drop this tab here
3740 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3741 e
.SetSelection(evt
.GetSelection());
3742 e
.SetOldSelection(evt
.GetSelection());
3743 e
.SetEventObject(this);
3744 e
.SetDragSource(this);
3745 e
.Veto(); // dropping must be explicitly approved by control owner
3747 nb
->GetEventHandler()->ProcessEvent(e
);
3751 // no answer or negative answer
3757 int src_idx
= evt
.GetSelection();
3758 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3760 // Check that it's not an impossible parent relationship
3762 while (p
&& !p
->IsTopLevel())
3771 // get main index of the page
3772 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3773 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3776 // make a copy of the page info
3777 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3779 // remove the page from the source notebook
3780 RemovePage(main_idx
);
3782 // reparent the page
3783 src_page
->Reparent(nb
);
3786 // found out the insert idx
3787 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3788 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3790 wxWindow
* target
= NULL
;
3791 int insert_idx
= -1;
3792 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3795 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3799 // add the page to the new notebook
3800 if (insert_idx
== -1)
3801 insert_idx
= dest_tabs
->GetPageCount();
3802 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3803 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3806 dest_tabs
->DoShowHide();
3807 dest_tabs
->Refresh();
3809 // set the selection in the destination tab control
3810 nb
->SetSelectionToPage(page_info
);
3812 // notify owner that the tab has been dragged
3813 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3814 e2
.SetSelection(evt
.GetSelection());
3815 e2
.SetOldSelection(evt
.GetSelection());
3816 e2
.SetEventObject(this);
3817 GetEventHandler()->ProcessEvent(e2
);
3827 // only perform a tab split if it's allowed
3828 wxAuiTabCtrl
* dest_tabs
= NULL
;
3830 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3832 // If the pointer is in an existing tab frame, do a tab insert
3833 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3834 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3835 int insert_idx
= -1;
3838 dest_tabs
= tab_frame
->m_tabs
;
3840 if (dest_tabs
== src_tabs
)
3844 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3845 wxWindow
* target
= NULL
;
3846 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3849 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3855 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3860 // there is no suitable drop location here, exit out
3864 // If there is no tabframe at all, create one
3865 wxTabFrame
* new_tabs
= new wxTabFrame
;
3866 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3867 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3868 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3872 wxNO_BORDER
|wxWANTS_CHARS
);
3873 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3874 new_tabs
->m_tabs
->SetFlags(m_flags
);
3876 m_mgr
.AddPane(new_tabs
,
3877 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3880 dest_tabs
= new_tabs
->m_tabs
;
3885 // remove the page from the source tabs
3886 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3887 page_info
.active
= false;
3888 src_tabs
->RemovePage(page_info
.window
);
3889 if (src_tabs
->GetPageCount() > 0)
3891 src_tabs
->SetActivePage((size_t)0);
3892 src_tabs
->DoShowHide();
3893 src_tabs
->Refresh();
3898 // add the page to the destination tabs
3899 if (insert_idx
== -1)
3900 insert_idx
= dest_tabs
->GetPageCount();
3901 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3903 if (src_tabs
->GetPageCount() == 0)
3905 RemoveEmptyTabFrames();
3909 dest_tabs
->DoShowHide();
3910 dest_tabs
->Refresh();
3912 // force the set selection function reset the selection
3915 // set the active page to the one we just split off
3916 SetSelectionToPage(page_info
);
3918 UpdateHintWindowSize();
3921 // notify owner that the tab has been dragged
3922 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE
, m_windowId
);
3923 e
.SetSelection(evt
.GetSelection());
3924 e
.SetOldSelection(evt
.GetSelection());
3925 e
.SetEventObject(this);
3926 GetEventHandler()->ProcessEvent(e
);
3931 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3933 // if we've just removed the last tab from the source
3934 // tab set, the remove the tab control completely
3935 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3936 size_t i
, pane_count
= all_panes
.GetCount();
3937 for (i
= 0; i
< pane_count
; ++i
)
3939 if (all_panes
.Item(i
).name
== wxT("dummy"))
3942 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3943 if (tabframe
->m_tab_rect
.Contains(pt
))
3944 return tabframe
->m_tabs
;
3950 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3952 // if we've just removed the last tab from the source
3953 // tab set, the remove the tab control completely
3954 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3955 size_t i
, pane_count
= all_panes
.GetCount();
3956 for (i
= 0; i
< pane_count
; ++i
)
3958 if (all_panes
.Item(i
).name
== wxT("dummy"))
3961 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3962 if (tabframe
->m_tabs
== tab_ctrl
)
3971 void wxAuiNotebook::RemoveEmptyTabFrames()
3973 // if we've just removed the last tab from the source
3974 // tab set, the remove the tab control completely
3975 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3976 size_t i
, pane_count
= all_panes
.GetCount();
3977 for (i
= 0; i
< pane_count
; ++i
)
3979 if (all_panes
.Item(i
).name
== wxT("dummy"))
3982 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3983 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3985 m_mgr
.DetachPane(tab_frame
);
3987 // use pending delete because sometimes during
3988 // window closing, refreshs are pending
3989 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3990 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3992 tab_frame
->m_tabs
= NULL
;
3999 // check to see if there is still a center pane;
4000 // if there isn't, make a frame the center pane
4001 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
4002 pane_count
= panes
.GetCount();
4003 wxWindow
* first_good
= NULL
;
4004 bool center_found
= false;
4005 for (i
= 0; i
< pane_count
; ++i
)
4007 if (panes
.Item(i
).name
== wxT("dummy"))
4009 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4010 center_found
= true;
4012 first_good
= panes
.Item(i
).window
;
4015 if (!center_found
&& first_good
)
4017 m_mgr
.GetPane(first_good
).Centre();
4023 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4025 // if we're dragging a tab, don't change the current selection.
4026 // This code prevents a bug that used to happen when the hint window
4027 // was hidden. In the bug, the focus would return to the notebook
4028 // child, which would then enter this handler and call
4029 // SetSelection, which is not desired turn tab dragging.
4031 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4032 size_t i
, pane_count
= all_panes
.GetCount();
4033 for (i
= 0; i
< pane_count
; ++i
)
4035 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4036 if (pane
.name
== wxT("dummy"))
4038 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4039 if (tabframe
->m_tabs
->IsDragging())
4044 // change the tab selection to the child
4045 // which was focused
4046 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4047 if (idx
!= -1 && idx
!= m_curpage
)
4053 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4055 if ( event
.IsWindowChange() ) {
4057 // FIXME: the problem with this is that if we have a split notebook,
4058 // we selection may go all over the place.
4059 AdvanceSelection(event
.GetDirection());
4062 // we get this event in 3 cases
4064 // a) one of our pages might have generated it because the user TABbed
4065 // out from it in which case we should propagate the event upwards and
4066 // our parent will take care of setting the focus to prev/next sibling
4070 // b) the parent panel wants to give the focus to us so that we
4071 // forward it to our selected page. We can't deal with this in
4072 // OnSetFocus() because we don't know which direction the focus came
4073 // from in this case and so can't choose between setting the focus to
4074 // first or last panel child
4078 // c) we ourselves (see MSWTranslateMessage) generated the event
4080 wxWindow
* const parent
= GetParent();
4082 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4083 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4084 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4086 if ( isFromParent
|| isFromSelf
)
4088 // no, it doesn't come from child, case (b) or (c): forward to a
4089 // page but only if direction is backwards (TAB) or from ourselves,
4090 if ( GetSelection() != wxNOT_FOUND
&&
4091 (!event
.GetDirection() || isFromSelf
) )
4093 // so that the page knows that the event comes from it's parent
4094 // and is being propagated downwards
4095 event
.SetEventObject(this);
4097 wxWindow
*page
= GetPage(GetSelection());
4098 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4102 //else: page manages focus inside it itself
4104 else // otherwise set the focus to the notebook itself
4111 // it comes from our child, case (a), pass to the parent, but only
4112 // if the direction is forwards. Otherwise set the focus to the
4113 // notebook itself. The notebook is always the 'first' control of a
4115 if ( !event
.GetDirection() )
4121 event
.SetCurrentFocus(this);
4122 parent
->GetEventHandler()->ProcessEvent(event
);
4128 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
4130 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
4131 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4133 int button_id
= evt
.GetInt();
4135 if (button_id
== wxAUI_BUTTON_CLOSE
)
4137 int selection
= evt
.GetSelection();
4139 if (selection
== -1)
4141 // if the close button is to the right, use the active
4142 // page selection to determine which page to close
4143 selection
= GetSelection();
4146 if (selection
!= -1)
4148 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4150 // ask owner if it's ok to close the tab
4151 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4152 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4153 const int idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4154 e
.SetSelection(idx
);
4155 e
.SetOldSelection(evt
.GetSelection());
4156 e
.SetEventObject(this);
4157 GetEventHandler()->ProcessEvent(e
);
4163 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4170 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4171 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
4173 DeletePage(main_idx
);
4176 // notify owner that the tab has been closed
4177 wxAuiNotebookEvent
e2(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
);
4178 e2
.SetSelection(idx
);
4179 e2
.SetEventObject(this);
4180 GetEventHandler()->ProcessEvent(e2
);
4186 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
4188 // patch event through to owner
4189 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4190 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4192 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4193 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4194 e
.SetEventObject(this);
4195 GetEventHandler()->ProcessEvent(e
);
4198 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
4200 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4201 // click should act like a tab close action. However, first
4202 // give the owner an opportunity to handle the middle up event
4203 // for custom action
4205 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4206 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4208 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4209 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4210 e
.SetEventObject(this);
4211 if (GetEventHandler()->ProcessEvent(e
))
4216 // check if we are supposed to close on middle-up
4217 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4220 // simulate the user pressing the close button on the tab
4221 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4225 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
4227 // patch event through to owner
4228 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4229 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4231 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4232 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4233 e
.SetEventObject(this);
4234 GetEventHandler()->ProcessEvent(e
);
4237 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
4239 // patch event through to owner
4240 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4241 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4243 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4244 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4245 e
.SetEventObject(this);
4246 GetEventHandler()->ProcessEvent(e
);
4249 // Sets the normal font
4250 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
4252 m_normal_font
= font
;
4253 GetArtProvider()->SetNormalFont(font
);
4256 // Sets the selected tab font
4257 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
4259 m_selected_font
= font
;
4260 GetArtProvider()->SetSelectedFont(font
);
4263 // Sets the measuring font
4264 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
4266 GetArtProvider()->SetMeasuringFont(font
);
4269 // Sets the tab font
4270 bool wxAuiNotebook::SetFont(const wxFont
& font
)
4272 wxControl::SetFont(font
);
4274 wxFont
normalFont(font
);
4275 wxFont
selectedFont(normalFont
);
4276 selectedFont
.SetWeight(wxBOLD
);
4278 SetNormalFont(normalFont
);
4279 SetSelectedFont(selectedFont
);
4280 SetMeasuringFont(selectedFont
);
4285 // Gets the tab control height
4286 int wxAuiNotebook::GetTabCtrlHeight() const
4288 return m_tab_ctrl_height
;
4291 // Gets the height of the notebook for a given page height
4292 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
4294 UpdateTabCtrlHeight();
4296 int tabCtrlHeight
= GetTabCtrlHeight();
4297 int decorHeight
= 2;
4298 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4301 // Advances the selection, generation page selection events
4302 void wxAuiNotebook::AdvanceSelection(bool forward
)
4304 if (GetPageCount() <= 1)
4307 int currentSelection
= GetSelection();
4311 if (currentSelection
== (int) (GetPageCount() - 1))
4313 else if (currentSelection
== -1)
4314 currentSelection
= 0;
4316 currentSelection
++;
4320 if (currentSelection
<= 0)
4323 currentSelection
--;
4326 SetSelection(currentSelection
);
4329 // Shows the window menu
4330 bool wxAuiNotebook::ShowWindowMenu()
4332 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4334 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4338 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4339 e
.SetSelection(idx
);
4340 e
.SetOldSelection(tabCtrl
->GetActivePage());
4341 e
.SetEventObject(tabCtrl
);
4342 GetEventHandler()->ProcessEvent(e
);