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_CHANGING
)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
)
55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
)
57 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
58 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
59 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
65 // these functions live in dockart.cpp -- they'll eventually
66 // be moved to a new utility cpp file
68 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
70 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
71 const wxColour
& color
);
73 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
75 static void DrawButtons(wxDC
& dc
,
78 const wxColour
& bkcolour
,
83 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
89 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
90 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
92 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
93 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
95 // draw the background behind the button
96 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
99 // draw the button itself
100 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
103 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
105 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
114 // -- GUI helper classes and functions --
116 class wxAuiCommandCapture
: public wxEvtHandler
120 wxAuiCommandCapture() { m_last_id
= 0; }
121 int GetCommandId() const { return m_last_id
; }
123 bool ProcessEvent(wxEvent
& evt
)
125 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
127 m_last_id
= evt
.GetId();
131 if (GetNextHandler())
132 return GetNextHandler()->ProcessEvent(evt
);
144 #if defined( __WXMAC__ )
145 static unsigned char close_bits
[]={
146 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
147 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
148 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
149 #elif defined( __WXGTK__)
150 static unsigned char close_bits
[]={
151 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
152 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
153 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
155 static unsigned char close_bits
[]={
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
157 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
161 static unsigned char left_bits
[] = {
162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
163 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
166 static unsigned char right_bits
[] = {
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
168 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
171 static unsigned char list_bits
[] = {
172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
173 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
181 // -- wxAuiDefaultTabArt class implementation --
183 wxAuiDefaultTabArt
::wxAuiDefaultTabArt()
185 m_normal_font
= *wxNORMAL_FONT
;
186 m_selected_font
= *wxNORMAL_FONT
;
187 m_selected_font
.SetWeight(wxBOLD
);
188 m_measuring_font
= m_selected_font
;
190 m_fixed_tab_width
= 100;
191 m_tab_ctrl_height
= 0;
194 wxBrush toolbarbrush
;
195 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
196 wxColor base_colour
= toolbarbrush
.GetColour();
198 wxColor base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
201 // the base_colour is too pale to use as our base colour,
202 // so darken it a bit --
203 if ((255-base_colour
.Red()) +
204 (255-base_colour
.Green()) +
205 (255-base_colour
.Blue()) < 60)
207 base_colour
= wxAuiStepColour(base_colour
, 92);
210 m_base_colour
= base_colour
;
211 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
213 m_border_pen
= wxPen(border_colour
);
214 m_base_colour_pen
= wxPen(m_base_colour
);
215 m_base_colour_brush
= wxBrush(m_base_colour
);
217 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
218 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
220 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
221 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
223 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
224 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
226 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
227 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
232 wxAuiDefaultTabArt
::~wxAuiDefaultTabArt()
236 wxAuiTabArt
* wxAuiDefaultTabArt
::Clone()
238 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
239 art
->SetNormalFont(m_normal_font
);
240 art
->SetSelectedFont(m_selected_font
);
241 art
->SetMeasuringFont(m_measuring_font
);
246 void wxAuiDefaultTabArt
::SetFlags(unsigned int flags
)
251 void wxAuiDefaultTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
254 m_fixed_tab_width
= 100;
256 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
258 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
259 tot_width
-= m_active_close_bmp
.GetWidth();
260 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
261 tot_width
-= m_active_windowlist_bmp
.GetWidth();
265 m_fixed_tab_width
= tot_width
/(int)tab_count
;
269 if (m_fixed_tab_width
< 100)
270 m_fixed_tab_width
= 100;
272 if (m_fixed_tab_width
> tot_width
/2)
273 m_fixed_tab_width
= tot_width
/2;
275 if (m_fixed_tab_width
> 220)
276 m_fixed_tab_width
= 220;
278 m_tab_ctrl_height
= tab_ctrl_size
.y
;
282 void wxAuiDefaultTabArt
::DrawBackground(wxDC
& dc
,
283 wxWindow
* WXUNUSED(wnd
),
287 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
288 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
289 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
290 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
293 int y
= rect
.GetHeight();
294 int w
= rect
.GetWidth();
295 dc
.SetPen(m_border_pen
);
296 dc
.SetBrush(m_base_colour_brush
);
297 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
301 // DrawTab() draws an individual tab.
304 // in_rect - rectangle the tab should be confined to
305 // caption - tab's caption
306 // active - whether or not the tab is active
307 // out_rect - actual output rectangle
308 // x_extent - the advance x; where the next tab should start
310 void wxAuiDefaultTabArt
::DrawTab(wxDC
& dc
,
312 const wxAuiNotebookPage
& page
,
313 const wxRect
& in_rect
,
314 int close_button_state
,
315 wxRect
* out_tab_rect
,
316 wxRect
* out_button_rect
,
319 wxCoord normal_textx
, normal_texty
;
320 wxCoord selected_textx
, selected_texty
;
323 // if the caption is empty, measure some temporary text
324 wxString caption
= page
.caption
;
328 dc
.SetFont(m_selected_font
);
329 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
331 dc
.SetFont(m_normal_font
);
332 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
334 // figure out the size of the tab
335 wxSize tab_size
= GetTabSize(dc
,
343 wxCoord tab_height
= m_tab_ctrl_height
- 3;
344 wxCoord tab_width
= tab_size
.x
;
345 wxCoord tab_x
= in_rect
.x
;
346 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
349 caption
= page
.caption
;
352 // select pen, brush and font for the tab to be drawn
356 dc
.SetFont(m_selected_font
);
357 texty
= selected_texty
;
361 dc
.SetFont(m_normal_font
);
362 texty
= normal_texty
;
366 // create points that will make the tab outline
368 int clip_width
= tab_width
;
369 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
370 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
373 wxPoint clip_points[6];
374 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
375 clip_points[1] = wxPoint(tab_x, tab_y+2);
376 clip_points[2] = wxPoint(tab_x+2, tab_y);
377 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
378 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
379 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
381 // FIXME: these ports don't provide wxRegion ctor from array of points
382 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
383 // set the clipping region for the tab --
384 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
385 dc.SetClippingRegion(clipping_region);
386 #endif // !wxDFB && !wxCocoa
388 // since the above code above doesn't play well with WXDFB or WXCOCOA,
389 // we'll just use a rectangle for the clipping region for now --
390 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
393 wxPoint border_points
[6];
394 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
395 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
396 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
397 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
398 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
399 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
402 int drawn_tab_yoff
= border_points
[1].y
;
403 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
410 // draw base background color
411 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
412 dc
.SetPen(m_base_colour_pen
);
413 dc
.SetBrush(m_base_colour_brush
);
414 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
416 // this white helps fill out the gradient at the top of the tab
417 dc
.SetPen(*wxWHITE_PEN
);
418 dc
.SetBrush(*wxWHITE_BRUSH
);
419 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
421 // these two points help the rounded corners appear more antialiased
422 dc
.SetPen(m_base_colour_pen
);
423 dc
.DrawPoint(r
.x
+2, r
.y
+1);
424 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
426 // set rectangle down a bit for gradient drawing
427 r
.SetHeight(r
.GetHeight()/2);
433 // draw gradient background
434 wxColor top_color
= *wxWHITE
;
435 wxColor bottom_color
= m_base_colour
;
436 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
442 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
444 // start the gradent up a bit and leave the inside border inset
445 // by a pixel for a 3D look. Only the top half of the inactive
446 // tab will have a slight gradient
453 // -- draw top gradient fill for glossy look
454 wxColor top_color
= m_base_colour
;
455 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
456 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
461 // -- draw bottom fill for glossy look
462 top_color
= m_base_colour
;
463 bottom_color
= m_base_colour
;
464 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
468 dc
.SetPen(m_border_pen
);
469 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
470 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
472 // there are two horizontal grey lines at the bottom of the tab control,
473 // this gets rid of the top one of those lines in the tab control
476 dc
.SetPen(m_base_colour_pen
);
477 dc
.DrawLine(border_points
[0].x
+1,
484 int text_offset
= tab_x
+ 8;
485 int close_button_width
= 0;
486 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
488 close_button_width
= m_active_close_bmp
.GetWidth();
491 int bitmap_offset
= 0;
492 if (page
.bitmap
.IsOk())
494 bitmap_offset
= tab_x
+ 8;
497 dc
.DrawBitmap(page
.bitmap
,
499 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
502 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
503 text_offset
+= 3; // bitmap padding
508 text_offset
= tab_x
+ 8;
512 wxString draw_text
= wxAuiChopText(dc
,
514 tab_width
- (text_offset
-tab_x
) - close_button_width
);
517 dc
.DrawText(draw_text
,
519 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
521 // draw focus rectangle
522 if (page
.active
&& (wnd
->FindFocus() == wnd
))
524 wxRect
focusRectText(text_offset
, (drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1),
525 selected_textx
, selected_texty
);
528 wxRect focusRectBitmap
;
530 if (page
.bitmap
.IsOk())
531 focusRectBitmap
= wxRect(bitmap_offset
, drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
532 page
.bitmap
.GetWidth(), page
.bitmap
.GetHeight());
534 if (page
.bitmap
.IsOk() && draw_text
.IsEmpty())
535 focusRect
= focusRectBitmap
;
536 else if (!page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
537 focusRect
= focusRectText
;
538 else if (page
.bitmap
.IsOk() && !draw_text
.IsEmpty())
539 focusRect
= focusRectText
.Union(focusRectBitmap
);
541 focusRect
.Inflate(2, 2);
543 wxRendererNative
::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
546 // draw close button if necessary
547 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
549 wxBitmap bmp
= m_disabled_close_bmp
;
551 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
552 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
554 bmp
= m_active_close_bmp
;
557 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
558 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
561 IndentPressedBitmap(&rect
, close_button_state
);
562 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
564 *out_button_rect
= rect
;
567 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
569 dc
.DestroyClippingRegion();
572 int wxAuiDefaultTabArt
::GetIndentSize()
577 wxSize wxAuiDefaultTabArt
::GetTabSize(wxDC
& dc
,
578 wxWindow
* WXUNUSED(wnd
),
579 const wxString
& caption
,
580 const wxBitmap
& bitmap
,
581 bool WXUNUSED(active
),
582 int close_button_state
,
585 wxCoord measured_textx
, measured_texty
, tmp
;
587 dc
.SetFont(m_measuring_font
);
588 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
590 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
592 // add padding around the text
593 wxCoord tab_width
= measured_textx
;
594 wxCoord tab_height
= measured_texty
;
596 // if the close button is showing, add space for it
597 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
598 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
600 // if there's a bitmap, add space for it
603 tab_width
+= bitmap
.GetWidth();
604 tab_width
+= 3; // right side bitmap padding
605 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
612 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
614 tab_width
= m_fixed_tab_width
;
617 *x_extent
= tab_width
;
619 return wxSize(tab_width
, tab_height
);
623 void wxAuiDefaultTabArt
::DrawButton(wxDC
& dc
,
624 wxWindow
* WXUNUSED(wnd
),
625 const wxRect
& in_rect
,
636 case wxAUI_BUTTON_CLOSE
:
637 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
638 bmp
= m_disabled_close_bmp
;
640 bmp
= m_active_close_bmp
;
642 case wxAUI_BUTTON_LEFT
:
643 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
644 bmp
= m_disabled_left_bmp
;
646 bmp
= m_active_left_bmp
;
648 case wxAUI_BUTTON_RIGHT
:
649 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
650 bmp
= m_disabled_right_bmp
;
652 bmp
= m_active_right_bmp
;
654 case wxAUI_BUTTON_WINDOWLIST
:
655 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
656 bmp
= m_disabled_windowlist_bmp
;
658 bmp
= m_active_windowlist_bmp
;
668 if (orientation
== wxLEFT
)
670 rect
.SetX(in_rect
.x
);
671 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
672 rect
.SetWidth(bmp
.GetWidth());
673 rect
.SetHeight(bmp
.GetHeight());
677 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
678 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
679 bmp
.GetWidth(), bmp
.GetHeight());
682 IndentPressedBitmap(&rect
, button_state
);
683 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
688 int wxAuiDefaultTabArt
::ShowDropDown(wxWindow
* wnd
,
689 const wxAuiNotebookPageArray
& pages
,
694 size_t i
, count
= pages
.GetCount();
695 for (i
= 0; i
< count
; ++i
)
697 const wxAuiNotebookPage
& page
= pages
.Item(i
);
698 wxString caption
= page
.caption
;
700 // if there is no caption, make it a space. This will prevent
701 // an assert in the menu code.
702 if (caption
.IsEmpty())
705 menuPopup
.AppendCheckItem(1000+i
, caption
);
708 if (active_idx
!= -1)
710 menuPopup
.Check(1000+active_idx
, true);
713 // find out where to put the popup menu of window items
714 wxPoint pt
= ::wxGetMousePosition();
715 pt
= wnd
->ScreenToClient(pt
);
717 // find out the screen coordinate at the bottom of the tab ctrl
718 wxRect cli_rect
= wnd
->GetClientRect();
719 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
721 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
722 wnd
->PushEventHandler(cc
);
723 wnd
->PopupMenu(&menuPopup
, pt
);
724 int command
= cc
->GetCommandId();
725 wnd
->PopEventHandler(true);
733 int wxAuiDefaultTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
734 const wxAuiNotebookPageArray
& pages
,
735 const wxSize
& required_bmp_size
)
738 dc
.SetFont(m_measuring_font
);
740 // sometimes a standard bitmap size needs to be enforced, especially
741 // if some tabs have bitmaps and others don't. This is important because
742 // it prevents the tab control from resizing when tabs are added.
743 wxBitmap measure_bmp
;
744 if (required_bmp_size
.IsFullySpecified())
746 measure_bmp
.Create(required_bmp_size
.x
,
747 required_bmp_size
.y
);
752 size_t i
, page_count
= pages
.GetCount();
753 for (i
= 0; i
< page_count
; ++i
)
755 wxAuiNotebookPage
& page
= pages
.Item(i
);
758 if (measure_bmp
.IsOk())
763 // we don't use the caption text because we don't
764 // want tab heights to be different in the case
765 // of a very short piece of text on one tab and a very
766 // tall piece of text on another tab
768 wxSize s
= GetTabSize(dc
,
773 wxAUI_BUTTON_STATE_HIDDEN
,
776 max_y
= wxMax(max_y
, s
.y
);
782 void wxAuiDefaultTabArt
::SetNormalFont(const wxFont
& font
)
784 m_normal_font
= font
;
787 void wxAuiDefaultTabArt
::SetSelectedFont(const wxFont
& font
)
789 m_selected_font
= font
;
792 void wxAuiDefaultTabArt
::SetMeasuringFont(const wxFont
& font
)
794 m_measuring_font
= font
;
798 // -- wxAuiSimpleTabArt class implementation --
800 wxAuiSimpleTabArt
::wxAuiSimpleTabArt()
802 m_normal_font
= *wxNORMAL_FONT
;
803 m_selected_font
= *wxNORMAL_FONT
;
804 m_selected_font
.SetWeight(wxBOLD
);
805 m_measuring_font
= m_selected_font
;
808 m_fixed_tab_width
= 100;
810 wxColour base_colour
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
812 wxColour background_colour
= base_colour
;
813 wxColour normaltab_colour
= base_colour
;
814 wxColour selectedtab_colour
= *wxWHITE
;
816 m_bkbrush
= wxBrush(background_colour
);
817 m_normal_bkbrush
= wxBrush(normaltab_colour
);
818 m_normal_bkpen
= wxPen(normaltab_colour
);
819 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
820 m_selected_bkpen
= wxPen(selectedtab_colour
);
822 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
823 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
825 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
826 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
828 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
829 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
831 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
832 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
836 wxAuiSimpleTabArt
::~wxAuiSimpleTabArt()
840 wxAuiTabArt
* wxAuiSimpleTabArt
::Clone()
842 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
846 void wxAuiSimpleTabArt
::SetFlags(unsigned int flags
)
851 void wxAuiSimpleTabArt
::SetSizingInfo(const wxSize
& tab_ctrl_size
,
854 m_fixed_tab_width
= 100;
856 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
858 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
859 tot_width
-= m_active_close_bmp
.GetWidth();
860 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
861 tot_width
-= m_active_windowlist_bmp
.GetWidth();
865 m_fixed_tab_width
= tot_width
/(int)tab_count
;
869 if (m_fixed_tab_width
< 100)
870 m_fixed_tab_width
= 100;
872 if (m_fixed_tab_width
> tot_width
/2)
873 m_fixed_tab_width
= tot_width
/2;
875 if (m_fixed_tab_width
> 220)
876 m_fixed_tab_width
= 220;
879 void wxAuiSimpleTabArt
::DrawBackground(wxDC
& dc
,
880 wxWindow
* WXUNUSED(wnd
),
884 dc
.SetBrush(m_bkbrush
);
885 dc
.SetPen(*wxTRANSPARENT_PEN
);
886 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
889 dc
.SetPen(*wxGREY_PEN
);
890 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
894 // DrawTab() draws an individual tab.
897 // in_rect - rectangle the tab should be confined to
898 // caption - tab's caption
899 // active - whether or not the tab is active
900 // out_rect - actual output rectangle
901 // x_extent - the advance x; where the next tab should start
903 void wxAuiSimpleTabArt
::DrawTab(wxDC
& dc
,
905 const wxAuiNotebookPage
& page
,
906 const wxRect
& in_rect
,
907 int close_button_state
,
908 wxRect
* out_tab_rect
,
909 wxRect
* out_button_rect
,
912 wxCoord normal_textx
, normal_texty
;
913 wxCoord selected_textx
, selected_texty
;
914 wxCoord textx
, texty
;
916 // if the caption is empty, measure some temporary text
917 wxString caption
= page
.caption
;
921 dc
.SetFont(m_selected_font
);
922 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
924 dc
.SetFont(m_normal_font
);
925 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
927 // figure out the size of the tab
928 wxSize tab_size
= GetTabSize(dc
,
936 wxCoord tab_height
= tab_size
.y
;
937 wxCoord tab_width
= tab_size
.x
;
938 wxCoord tab_x
= in_rect
.x
;
939 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
941 caption
= page
.caption
;
943 // select pen, brush and font for the tab to be drawn
947 dc
.SetPen(m_selected_bkpen
);
948 dc
.SetBrush(m_selected_bkbrush
);
949 dc
.SetFont(m_selected_font
);
950 textx
= selected_textx
;
951 texty
= selected_texty
;
955 dc
.SetPen(m_normal_bkpen
);
956 dc
.SetBrush(m_normal_bkbrush
);
957 dc
.SetFont(m_normal_font
);
958 textx
= normal_textx
;
959 texty
= normal_texty
;
967 points
[0].y
= tab_y
+ tab_height
- 1;
968 points
[1].x
= tab_x
+ tab_height
- 3;
969 points
[1].y
= tab_y
+ 2;
970 points
[2].x
= tab_x
+ tab_height
+ 3;
972 points
[3].x
= tab_x
+ tab_width
- 2;
974 points
[4].x
= tab_x
+ tab_width
;
975 points
[4].y
= tab_y
+ 2;
976 points
[5].x
= tab_x
+ tab_width
;
977 points
[5].y
= tab_y
+ tab_height
- 1;
978 points
[6] = points
[0];
980 dc
.SetClippingRegion(in_rect
);
982 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
984 dc
.SetPen(*wxGREY_PEN
);
986 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
987 dc
.DrawLines(WXSIZEOF(points
), points
);
992 int close_button_width
= 0;
993 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
995 close_button_width
= m_active_close_bmp
.GetWidth();
996 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
1000 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
1003 // set minimum text offset
1004 if (text_offset
< tab_x
+ tab_height
)
1005 text_offset
= tab_x
+ tab_height
;
1007 // chop text if necessary
1008 wxString draw_text
= wxAuiChopText(dc
,
1010 tab_width
- (text_offset
-tab_x
) - close_button_width
);
1013 dc
.DrawText(draw_text
,
1015 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
1018 // draw focus rectangle
1019 if (page
.active
&& (wnd
->FindFocus() == wnd
))
1021 wxRect
focusRect(text_offset
, ((tab_y
+ tab_height
)/2 - (texty
/2) + 1),
1022 selected_textx
, selected_texty
);
1024 focusRect
.Inflate(2, 2);
1026 wxRendererNative
::Get().DrawFocusRect(wnd
, dc
, focusRect
, 0);
1029 // draw close button if necessary
1030 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1034 bmp
= m_active_close_bmp
;
1036 bmp
= m_disabled_close_bmp
;
1038 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1039 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1042 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1044 *out_button_rect
= rect
;
1048 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1050 dc
.DestroyClippingRegion();
1053 int wxAuiSimpleTabArt
::GetIndentSize()
1058 wxSize wxAuiSimpleTabArt
::GetTabSize(wxDC
& dc
,
1059 wxWindow
* WXUNUSED(wnd
),
1060 const wxString
& caption
,
1061 const wxBitmap
& WXUNUSED(bitmap
),
1062 bool WXUNUSED(active
),
1063 int close_button_state
,
1066 wxCoord measured_textx
, measured_texty
;
1068 dc
.SetFont(m_measuring_font
);
1069 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1071 wxCoord tab_height
= measured_texty
+ 4;
1072 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1074 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1075 tab_width
+= m_active_close_bmp
.GetWidth();
1077 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1079 tab_width
= m_fixed_tab_width
;
1082 *x_extent
= tab_width
- (tab_height
/2) - 1;
1084 return wxSize(tab_width
, tab_height
);
1088 void wxAuiSimpleTabArt
::DrawButton(wxDC
& dc
,
1089 wxWindow
* WXUNUSED(wnd
),
1090 const wxRect
& in_rect
,
1101 case wxAUI_BUTTON_CLOSE
:
1102 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1103 bmp
= m_disabled_close_bmp
;
1105 bmp
= m_active_close_bmp
;
1107 case wxAUI_BUTTON_LEFT
:
1108 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1109 bmp
= m_disabled_left_bmp
;
1111 bmp
= m_active_left_bmp
;
1113 case wxAUI_BUTTON_RIGHT
:
1114 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1115 bmp
= m_disabled_right_bmp
;
1117 bmp
= m_active_right_bmp
;
1119 case wxAUI_BUTTON_WINDOWLIST
:
1120 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1121 bmp
= m_disabled_windowlist_bmp
;
1123 bmp
= m_active_windowlist_bmp
;
1132 if (orientation
== wxLEFT
)
1134 rect
.SetX(in_rect
.x
);
1135 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1136 rect
.SetWidth(bmp
.GetWidth());
1137 rect
.SetHeight(bmp
.GetHeight());
1141 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1142 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1143 bmp
.GetWidth(), bmp
.GetHeight());
1147 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1152 int wxAuiSimpleTabArt
::ShowDropDown(wxWindow
* wnd
,
1153 const wxAuiNotebookPageArray
& pages
,
1158 size_t i
, count
= pages
.GetCount();
1159 for (i
= 0; i
< count
; ++i
)
1161 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1162 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1165 if (active_idx
!= -1)
1167 menuPopup
.Check(1000+active_idx
, true);
1170 // find out where to put the popup menu of window
1171 // items. Subtract 100 for now to center the menu
1172 // a bit, until a better mechanism can be implemented
1173 wxPoint pt
= ::wxGetMousePosition();
1174 pt
= wnd
->ScreenToClient(pt
);
1180 // find out the screen coordinate at the bottom of the tab ctrl
1181 wxRect cli_rect
= wnd
->GetClientRect();
1182 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1184 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1185 wnd
->PushEventHandler(cc
);
1186 wnd
->PopupMenu(&menuPopup
, pt
);
1187 int command
= cc
->GetCommandId();
1188 wnd
->PopEventHandler(true);
1190 if (command
>= 1000)
1191 return command
-1000;
1196 int wxAuiSimpleTabArt
::GetBestTabCtrlSize(wxWindow
* wnd
,
1197 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1198 const wxSize
& WXUNUSED(required_bmp_size
))
1201 dc
.SetFont(m_measuring_font
);
1203 wxSize s
= GetTabSize(dc
,
1208 wxAUI_BUTTON_STATE_HIDDEN
,
1213 void wxAuiSimpleTabArt
::SetNormalFont(const wxFont
& font
)
1215 m_normal_font
= font
;
1218 void wxAuiSimpleTabArt
::SetSelectedFont(const wxFont
& font
)
1220 m_selected_font
= font
;
1223 void wxAuiSimpleTabArt
::SetMeasuringFont(const wxFont
& font
)
1225 m_measuring_font
= font
;
1231 // -- wxAuiTabContainer class implementation --
1234 // wxAuiTabContainer is a class which contains information about each
1235 // tab. It also can render an entire tab control to a specified DC.
1236 // It's not a window class itself, because this code will be used by
1237 // the wxFrameMananger, where it is disadvantageous to have separate
1238 // windows for each tab control in the case of "docked tabs"
1240 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1241 // which can be used as a tab control in the normal sense.
1244 wxAuiTabContainer
::wxAuiTabContainer()
1248 m_art
= new wxAuiDefaultTabArt
;
1250 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1251 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1252 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1253 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1256 wxAuiTabContainer
::~wxAuiTabContainer()
1261 void wxAuiTabContainer
::SetArtProvider(wxAuiTabArt
* art
)
1268 m_art
->SetFlags(m_flags
);
1272 wxAuiTabArt
* wxAuiTabContainer
::GetArtProvider() const
1277 void wxAuiTabContainer
::SetFlags(unsigned int flags
)
1281 // check for new close button settings
1282 RemoveButton(wxAUI_BUTTON_LEFT
);
1283 RemoveButton(wxAUI_BUTTON_RIGHT
);
1284 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1285 RemoveButton(wxAUI_BUTTON_CLOSE
);
1288 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1290 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1291 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1294 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1296 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1299 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1301 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1306 m_art
->SetFlags(m_flags
);
1310 unsigned int wxAuiTabContainer
::GetFlags() const
1316 void wxAuiTabContainer
::SetNormalFont(const wxFont
& font
)
1318 m_art
->SetNormalFont(font
);
1321 void wxAuiTabContainer
::SetSelectedFont(const wxFont
& font
)
1323 m_art
->SetSelectedFont(font
);
1326 void wxAuiTabContainer
::SetMeasuringFont(const wxFont
& font
)
1328 m_art
->SetMeasuringFont(font
);
1331 void wxAuiTabContainer
::SetRect(const wxRect
& rect
)
1337 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1341 bool wxAuiTabContainer
::AddPage(wxWindow
* page
,
1342 const wxAuiNotebookPage
& info
)
1344 wxAuiNotebookPage page_info
;
1346 page_info
.window
= page
;
1348 m_pages
.Add(page_info
);
1350 // let the art provider know how many pages we have
1353 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1359 bool wxAuiTabContainer
::InsertPage(wxWindow
* page
,
1360 const wxAuiNotebookPage
& info
,
1363 wxAuiNotebookPage page_info
;
1365 page_info
.window
= page
;
1367 if (idx
>= m_pages
.GetCount())
1368 m_pages
.Add(page_info
);
1370 m_pages
.Insert(page_info
, idx
);
1372 // let the art provider know how many pages we have
1375 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1381 bool wxAuiTabContainer
::MovePage(wxWindow
* page
,
1384 int idx
= GetIdxFromWindow(page
);
1388 // get page entry, make a copy of it
1389 wxAuiNotebookPage p
= GetPage(idx
);
1391 // remove old page entry
1394 // insert page where it should be
1395 InsertPage(page
, p
, new_idx
);
1400 bool wxAuiTabContainer
::RemovePage(wxWindow
* wnd
)
1402 size_t i
, page_count
= m_pages
.GetCount();
1403 for (i
= 0; i
< page_count
; ++i
)
1405 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1406 if (page
.window
== wnd
)
1408 m_pages
.RemoveAt(i
);
1410 // let the art provider know how many pages we have
1413 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1423 bool wxAuiTabContainer
::SetActivePage(wxWindow
* wnd
)
1427 size_t i
, page_count
= m_pages
.GetCount();
1428 for (i
= 0; i
< page_count
; ++i
)
1430 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1431 if (page
.window
== wnd
)
1438 page
.active
= false;
1445 void wxAuiTabContainer
::SetNoneActive()
1447 size_t i
, page_count
= m_pages
.GetCount();
1448 for (i
= 0; i
< page_count
; ++i
)
1450 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1451 page
.active
= false;
1455 bool wxAuiTabContainer
::SetActivePage(size_t page
)
1457 if (page
>= m_pages
.GetCount())
1460 return SetActivePage(m_pages
.Item(page
).window
);
1463 int wxAuiTabContainer
::GetActivePage() const
1465 size_t i
, page_count
= m_pages
.GetCount();
1466 for (i
= 0; i
< page_count
; ++i
)
1468 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1476 wxWindow
* wxAuiTabContainer
::GetWindowFromIdx(size_t idx
) const
1478 if (idx
>= m_pages
.GetCount())
1481 return m_pages
[idx
].window
;
1484 int wxAuiTabContainer
::GetIdxFromWindow(wxWindow
* wnd
) const
1486 const size_t page_count
= m_pages
.GetCount();
1487 for ( size_t i
= 0; i
< page_count
; ++i
)
1489 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1490 if (page
.window
== wnd
)
1496 wxAuiNotebookPage
& wxAuiTabContainer
::GetPage(size_t idx
)
1498 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1500 return m_pages
[idx
];
1503 const wxAuiNotebookPage
& wxAuiTabContainer
::GetPage(size_t idx
) const
1505 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1507 return m_pages
[idx
];
1510 wxAuiNotebookPageArray
& wxAuiTabContainer
::GetPages()
1515 size_t wxAuiTabContainer
::GetPageCount() const
1517 return m_pages
.GetCount();
1520 void wxAuiTabContainer
::AddButton(int id
,
1522 const wxBitmap
& normal_bitmap
,
1523 const wxBitmap
& disabled_bitmap
)
1525 wxAuiTabContainerButton button
;
1527 button
.bitmap
= normal_bitmap
;
1528 button
.dis_bitmap
= disabled_bitmap
;
1529 button
.location
= location
;
1530 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1532 m_buttons
.Add(button
);
1535 void wxAuiTabContainer
::RemoveButton(int id
)
1537 size_t i
, button_count
= m_buttons
.GetCount();
1539 for (i
= 0; i
< button_count
; ++i
)
1541 if (m_buttons
.Item(i
).id
== id
)
1543 m_buttons
.RemoveAt(i
);
1551 size_t wxAuiTabContainer
::GetTabOffset() const
1553 return m_tab_offset
;
1556 void wxAuiTabContainer
::SetTabOffset(size_t offset
)
1558 m_tab_offset
= offset
;
1564 // Render() renders the tab catalog to the specified DC
1565 // It is a virtual function and can be overridden to
1566 // provide custom drawing capabilities
1567 void wxAuiTabContainer
::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1569 if (!raw_dc
|| !raw_dc
->IsOk())
1575 size_t page_count
= m_pages
.GetCount();
1576 size_t button_count
= m_buttons
.GetCount();
1578 // create off-screen bitmap
1579 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1580 dc
.SelectObject(bmp
);
1585 // find out if size of tabs is larger than can be
1586 // afforded on screen
1587 int total_width
= 0;
1588 int visible_width
= 0;
1589 for (i
= 0; i
< page_count
; ++i
)
1591 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1593 // determine if a close button is on this tab
1594 bool close_button
= false;
1595 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1596 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1598 close_button
= true;
1603 wxSize size
= m_art
->GetTabSize(dc
,
1609 wxAUI_BUTTON_STATE_NORMAL
:
1610 wxAUI_BUTTON_STATE_HIDDEN
,
1613 if (i
+1 < page_count
)
1614 total_width
+= x_extent
;
1616 total_width
+= size
.x
;
1618 if (i
>= m_tab_offset
)
1620 if (i
+1 < page_count
)
1621 visible_width
+= x_extent
;
1623 visible_width
+= size
.x
;
1627 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1629 // show left/right buttons
1630 for (i
= 0; i
< button_count
; ++i
)
1632 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1633 if (button
.id
== wxAUI_BUTTON_LEFT
||
1634 button
.id
== wxAUI_BUTTON_RIGHT
)
1636 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1642 // hide left/right buttons
1643 for (i
= 0; i
< button_count
; ++i
)
1645 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1646 if (button
.id
== wxAUI_BUTTON_LEFT
||
1647 button
.id
== wxAUI_BUTTON_RIGHT
)
1649 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1654 // determine whether left button should be enabled
1655 for (i
= 0; i
< button_count
; ++i
)
1657 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1658 if (button
.id
== wxAUI_BUTTON_LEFT
)
1660 if (m_tab_offset
== 0)
1661 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1663 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1665 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1667 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1668 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1670 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1677 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1680 int left_buttons_width
= 0;
1681 int right_buttons_width
= 0;
1685 // draw the buttons on the right side
1686 offset
= m_rect
.x
+ m_rect
.width
;
1687 for (i
= 0; i
< button_count
; ++i
)
1689 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1691 if (button
.location
!= wxRIGHT
)
1693 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1696 wxRect button_rect
= m_rect
;
1697 button_rect
.SetY(1);
1698 button_rect
.SetWidth(offset
);
1700 m_art
->DrawButton(dc
,
1708 offset
-= button
.rect
.GetWidth();
1709 right_buttons_width
+= button
.rect
.GetWidth();
1716 // draw the buttons on the left side
1718 for (i
= 0; i
< button_count
; ++i
)
1720 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1722 if (button
.location
!= wxLEFT
)
1724 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1727 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1729 m_art
->DrawButton(dc
,
1737 offset
+= button
.rect
.GetWidth();
1738 left_buttons_width
+= button
.rect
.GetWidth();
1741 offset
= left_buttons_width
;
1744 offset
+= m_art
->GetIndentSize();
1747 // prepare the tab-close-button array
1748 // make sure tab button entries which aren't used are marked as hidden
1749 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1750 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1752 // make sure there are enough tab button entries to accommodate all tabs
1753 while (m_tab_close_buttons
.GetCount() < page_count
)
1755 wxAuiTabContainerButton tempbtn
;
1756 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1757 tempbtn
.location
= wxCENTER
;
1758 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1759 m_tab_close_buttons
.Add(tempbtn
);
1763 // buttons before the tab offset must be set to hidden
1764 for (i
= 0; i
< m_tab_offset
; ++i
)
1766 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1772 size_t active
= 999;
1773 int active_offset
= 0;
1777 wxRect rect
= m_rect
;
1779 rect
.height
= m_rect
.height
;
1781 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1783 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1784 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1786 // determine if a close button is on this tab
1787 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1788 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1790 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1792 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1793 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1794 tab_button
.location
= wxCENTER
;
1799 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1803 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1805 if (rect
.width
<= 0)
1812 tab_button
.cur_state
,
1820 active_offset
= offset
;
1828 // make sure to deactivate buttons which are off the screen to the right
1829 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1831 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1835 // draw the active tab again so it stands in the foreground
1836 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1838 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1840 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1842 rect
.x
= active_offset
;
1847 tab_button
.cur_state
,
1854 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1855 m_rect
.GetWidth(), m_rect
.GetHeight(),
1859 // Is the tab visible?
1860 bool wxAuiTabContainer
::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
)
1862 if (!dc
|| !dc
->IsOk())
1866 size_t page_count
= m_pages
.GetCount();
1867 size_t button_count
= m_buttons
.GetCount();
1869 // Hasn't been rendered yet; assume it's visible
1870 if (m_tab_close_buttons
.GetCount() < page_count
)
1873 // First check if both buttons are disabled - if so, there's no need to
1874 // check further for visibility.
1875 int arrowButtonVisibleCount
= 0;
1876 for (i
= 0; i
< button_count
; ++i
)
1878 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1879 if (button
.id
== wxAUI_BUTTON_LEFT
||
1880 button
.id
== wxAUI_BUTTON_RIGHT
)
1882 if ((button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
) == 0)
1883 arrowButtonVisibleCount
++;
1887 // Tab must be visible
1888 if (arrowButtonVisibleCount
== 0)
1891 // If tab is less than the given offset, it must be invisible by definition
1892 if (tabPage
< tabOffset
)
1896 int left_buttons_width
= 0;
1897 int right_buttons_width
= 0;
1901 // calculate size of the buttons on the right side
1902 offset
= m_rect
.x
+ m_rect
.width
;
1903 for (i
= 0; i
< button_count
; ++i
)
1905 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1907 if (button
.location
!= wxRIGHT
)
1909 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1912 offset
-= button
.rect
.GetWidth();
1913 right_buttons_width
+= button
.rect
.GetWidth();
1918 // calculate size of the buttons on the left side
1919 for (i
= 0; i
< button_count
; ++i
)
1921 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1923 if (button
.location
!= wxLEFT
)
1925 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1928 offset
+= button
.rect
.GetWidth();
1929 left_buttons_width
+= button
.rect
.GetWidth();
1932 offset
= left_buttons_width
;
1935 offset
+= m_art
->GetIndentSize();
1939 wxRect rect
= m_rect
;
1941 rect
.height
= m_rect
.height
;
1943 // See if the given page is visible at the given tab offset (effectively scroll position)
1944 for (i
= tabOffset
; i
< page_count
; ++i
)
1946 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1947 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1949 // determine if a close button is on this tab
1950 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1951 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1953 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1955 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1956 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1957 tab_button
.location
= wxCENTER
;
1962 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1966 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1968 if (rect
.width
<= 0)
1969 return false; // haven't found the tab, and we've run out of space, so return false
1972 wxSize size
= m_art
->GetTabSize(*dc
,
1977 tab_button
.cur_state
,
1982 if (i
== (size_t) tabPage
)
1984 // If not all of the tab is visible, and supposing there's space to display it all,
1985 // we could do better so we return false.
1986 if (((m_rect
.width
- right_buttons_width
- offset
- 2) <= 0) && ((m_rect
.width
- right_buttons_width
- left_buttons_width
) > x_extent
))
1993 // Shouldn't really get here, but if it does, assume the tab is visible to prevent
1994 // further looping in calling code.
1998 // Make the tab visible if it wasn't already
1999 void wxAuiTabContainer
::MakeTabVisible(int tabPage
, wxWindow
* win
)
2002 if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
))
2005 for (i
= 0; i
< (int) m_pages
.GetCount(); i
++)
2007 if (IsTabVisible(tabPage
, i
, & dc
, win
))
2017 // TabHitTest() tests if a tab was hit, passing the window pointer
2018 // back if that condition was fulfilled. The function returns
2019 // true if a tab was hit, otherwise false
2020 bool wxAuiTabContainer
::TabHitTest(int x
, int y
, wxWindow
** hit
) const
2022 if (!m_rect
.Contains(x
,y
))
2025 wxAuiTabContainerButton
* btn
= NULL
;
2026 if (ButtonHitTest(x
, y
, &btn
))
2028 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
2032 size_t i
, page_count
= m_pages
.GetCount();
2034 for (i
= m_tab_offset
; i
< page_count
; ++i
)
2036 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
2037 if (page
.rect
.Contains(x
,y
))
2048 // ButtonHitTest() tests if a button was hit. The function returns
2049 // true if a button was hit, otherwise false
2050 bool wxAuiTabContainer
::ButtonHitTest(int x
, int y
,
2051 wxAuiTabContainerButton
** hit
) const
2053 if (!m_rect
.Contains(x
,y
))
2056 size_t i
, button_count
;
2059 button_count
= m_buttons
.GetCount();
2060 for (i
= 0; i
< button_count
; ++i
)
2062 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
2063 if (button
.rect
.Contains(x
,y
) &&
2064 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2065 wxAUI_BUTTON_STATE_DISABLED
)))
2073 button_count
= m_tab_close_buttons
.GetCount();
2074 for (i
= 0; i
< button_count
; ++i
)
2076 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
2077 if (button
.rect
.Contains(x
,y
) &&
2078 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
2079 wxAUI_BUTTON_STATE_DISABLED
)))
2092 // the utility function ShowWnd() is the same as show,
2093 // except it handles wxAuiMDIChildFrame windows as well,
2094 // as the Show() method on this class is "unplugged"
2095 static void ShowWnd(wxWindow
* wnd
, bool show
)
2097 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2099 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
2109 // DoShowHide() this function shows the active window, then
2110 // hides all of the other windows (in that order)
2111 void wxAuiTabContainer
::DoShowHide()
2113 wxAuiNotebookPageArray
& pages
= GetPages();
2114 size_t i
, page_count
= pages
.GetCount();
2116 // show new active page first
2117 for (i
= 0; i
< page_count
; ++i
)
2119 wxAuiNotebookPage
& page
= pages
.Item(i
);
2122 ShowWnd(page
.window
, true);
2127 // hide all other pages
2128 for (i
= 0; i
< page_count
; ++i
)
2130 wxAuiNotebookPage
& page
= pages
.Item(i
);
2132 ShowWnd(page
.window
, false);
2141 // -- wxAuiTabCtrl class implementation --
2145 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
2146 EVT_PAINT(wxAuiTabCtrl
::OnPaint
)
2147 EVT_ERASE_BACKGROUND(wxAuiTabCtrl
::OnEraseBackground
)
2148 EVT_SIZE(wxAuiTabCtrl
::OnSize
)
2149 EVT_LEFT_DOWN(wxAuiTabCtrl
::OnLeftDown
)
2150 EVT_LEFT_DCLICK(wxAuiTabCtrl
::OnLeftDown
)
2151 EVT_LEFT_UP(wxAuiTabCtrl
::OnLeftUp
)
2152 EVT_MIDDLE_DOWN(wxAuiTabCtrl
::OnMiddleDown
)
2153 EVT_MIDDLE_UP(wxAuiTabCtrl
::OnMiddleUp
)
2154 EVT_RIGHT_DOWN(wxAuiTabCtrl
::OnRightDown
)
2155 EVT_RIGHT_UP(wxAuiTabCtrl
::OnRightUp
)
2156 EVT_MOTION(wxAuiTabCtrl
::OnMotion
)
2157 EVT_LEAVE_WINDOW(wxAuiTabCtrl
::OnLeaveWindow
)
2158 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl
::OnButton
)
2159 EVT_SET_FOCUS(wxAuiTabCtrl
::OnSetFocus
)
2160 EVT_KILL_FOCUS(wxAuiTabCtrl
::OnKillFocus
)
2161 EVT_CHAR(wxAuiTabCtrl
::OnChar
)
2165 wxAuiTabCtrl
::wxAuiTabCtrl(wxWindow
* parent
,
2169 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2171 SetName(wxT("wxAuiTabCtrl"));
2172 m_click_pt
= wxDefaultPosition
;
2173 m_is_dragging
= false;
2174 m_hover_button
= NULL
;
2175 m_pressed_button
= NULL
;
2178 wxAuiTabCtrl
::~wxAuiTabCtrl()
2182 void wxAuiTabCtrl
::OnPaint(wxPaintEvent
&)
2186 dc
.SetFont(GetFont());
2188 if (GetPageCount() > 0)
2192 void wxAuiTabCtrl
::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2196 void wxAuiTabCtrl
::OnSize(wxSizeEvent
& evt
)
2198 wxSize s
= evt
.GetSize();
2199 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2203 void wxAuiTabCtrl
::OnLeftDown(wxMouseEvent
& evt
)
2206 m_click_pt
= wxDefaultPosition
;
2207 m_is_dragging
= false;
2209 m_pressed_button
= NULL
;
2213 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2215 int new_selection
= GetIdxFromWindow(wnd
);
2217 // wxAuiNotebooks always want to receive this event
2218 // even if the tab is already active, because they may
2219 // have multiple tab controls
2220 if (new_selection
!= GetActivePage() ||
2221 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2223 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2224 e
.SetSelection(new_selection
);
2225 e
.SetOldSelection(GetActivePage());
2226 e
.SetEventObject(this);
2227 GetEventHandler()->ProcessEvent(e
);
2230 m_click_pt
.x
= evt
.m_x
;
2231 m_click_pt
.y
= evt
.m_y
;
2237 m_pressed_button
= m_hover_button
;
2238 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2244 void wxAuiTabCtrl
::OnLeftUp(wxMouseEvent
& evt
)
2246 if (GetCapture() == this)
2251 m_is_dragging
= false;
2253 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2254 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2255 evt
.SetOldSelection(evt
.GetSelection());
2256 evt
.SetEventObject(this);
2257 GetEventHandler()->ProcessEvent(evt
);
2262 if (m_pressed_button
)
2264 // make sure we're still clicking the button
2265 wxAuiTabContainerButton
* button
= NULL
;
2266 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2269 if (button
!= m_pressed_button
)
2271 m_pressed_button
= NULL
;
2278 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2280 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2281 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2282 evt
.SetInt(m_pressed_button
->id
);
2283 evt
.SetEventObject(this);
2284 GetEventHandler()->ProcessEvent(evt
);
2287 m_pressed_button
= NULL
;
2290 m_click_pt
= wxDefaultPosition
;
2291 m_is_dragging
= false;
2295 void wxAuiTabCtrl
::OnMiddleUp(wxMouseEvent
& evt
)
2297 wxWindow
* wnd
= NULL
;
2298 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2301 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2302 e
.SetEventObject(this);
2303 e
.SetSelection(GetIdxFromWindow(wnd
));
2304 GetEventHandler()->ProcessEvent(e
);
2307 void wxAuiTabCtrl
::OnMiddleDown(wxMouseEvent
& evt
)
2309 wxWindow
* wnd
= NULL
;
2310 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2313 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2314 e
.SetEventObject(this);
2315 e
.SetSelection(GetIdxFromWindow(wnd
));
2316 GetEventHandler()->ProcessEvent(e
);
2319 void wxAuiTabCtrl
::OnRightUp(wxMouseEvent
& evt
)
2321 wxWindow
* wnd
= NULL
;
2322 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2325 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2326 e
.SetEventObject(this);
2327 e
.SetSelection(GetIdxFromWindow(wnd
));
2328 GetEventHandler()->ProcessEvent(e
);
2331 void wxAuiTabCtrl
::OnRightDown(wxMouseEvent
& evt
)
2333 wxWindow
* wnd
= NULL
;
2334 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2337 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2338 e
.SetEventObject(this);
2339 e
.SetSelection(GetIdxFromWindow(wnd
));
2340 GetEventHandler()->ProcessEvent(e
);
2343 void wxAuiTabCtrl
::OnMotion(wxMouseEvent
& evt
)
2345 wxPoint pos
= evt
.GetPosition();
2347 // check if the mouse is hovering above a button
2348 wxAuiTabContainerButton
* button
;
2349 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2351 if (m_hover_button
&& button
!= m_hover_button
)
2353 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2354 m_hover_button
= NULL
;
2359 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2361 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2364 m_hover_button
= button
;
2372 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2373 m_hover_button
= NULL
;
2380 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2385 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2386 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2387 evt
.SetOldSelection(evt
.GetSelection());
2388 evt
.SetEventObject(this);
2389 GetEventHandler()->ProcessEvent(evt
);
2394 int drag_x_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_X
);
2395 int drag_y_threshold
= wxSystemSettings
::GetMetric(wxSYS_DRAG_Y
);
2397 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2398 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2400 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2401 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2402 evt
.SetOldSelection(evt
.GetSelection());
2403 evt
.SetEventObject(this);
2404 GetEventHandler()->ProcessEvent(evt
);
2406 m_is_dragging
= true;
2410 void wxAuiTabCtrl
::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2414 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2415 m_hover_button
= NULL
;
2421 void wxAuiTabCtrl
::OnButton(wxAuiNotebookEvent
& event
)
2423 int button
= event
.GetInt();
2425 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2427 if (button
== wxAUI_BUTTON_LEFT
)
2429 if (GetTabOffset() > 0)
2431 SetTabOffset(GetTabOffset()-1);
2438 SetTabOffset(GetTabOffset()+1);
2443 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2445 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2449 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2450 e
.SetSelection(idx
);
2451 e
.SetOldSelection(GetActivePage());
2452 e
.SetEventObject(this);
2453 GetEventHandler()->ProcessEvent(e
);
2462 void wxAuiTabCtrl
::OnSetFocus(wxFocusEvent
& WXUNUSED(event
))
2467 void wxAuiTabCtrl
::OnKillFocus(wxFocusEvent
& WXUNUSED(event
))
2472 void wxAuiTabCtrl
::OnChar(wxKeyEvent
& event
)
2474 if (GetActivePage() == -1)
2480 // We can't leave tab processing to the system; on Windows, tabs and keys
2481 // get eaten by the system and not processed properly if we specify both
2482 // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL,
2483 // we don't key arrow key events.
2485 int key
= event
.GetKeyCode();
2487 if (key
== WXK_NUMPAD_PAGEUP
)
2489 if (key
== WXK_NUMPAD_PAGEDOWN
)
2491 if (key
== WXK_NUMPAD_HOME
)
2493 if (key
== WXK_NUMPAD_END
)
2495 if (key
== WXK_NUMPAD_LEFT
)
2497 if (key
== WXK_NUMPAD_RIGHT
)
2500 if (key
== WXK_TAB
|| key
== WXK_PAGEUP
|| key
== WXK_PAGEDOWN
)
2502 bool bCtrlDown
= event
.ControlDown();
2503 bool bShiftDown
= event
.ShiftDown();
2505 bool bForward
= (key
== WXK_TAB
&& !bShiftDown
) || (key
== WXK_PAGEDOWN
);
2506 bool bWindowChange
= (key
== WXK_PAGEUP
) || (key
== WXK_PAGEDOWN
) || bCtrlDown
;
2507 bool bFromTab
= (key
== WXK_TAB
);
2509 wxAuiNotebook
* nb
= wxDynamicCast(GetParent(), wxAuiNotebook
);
2516 wxNavigationKeyEvent keyEvent
;
2517 keyEvent
.SetDirection(bForward
);
2518 keyEvent
.SetWindowChange(bWindowChange
);
2519 keyEvent
.SetFromTab(bFromTab
);
2520 keyEvent
.SetEventObject(nb
);
2522 if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
))
2524 // Not processed? Do an explicit tab into the page.
2525 wxWindow
* win
= GetWindowFromIdx(GetActivePage());
2532 if (m_pages
.GetCount() < 2)
2540 if (key
== WXK_RIGHT
)
2542 if (m_pages
.GetCount() > 1)
2544 if (GetActivePage() == -1)
2546 else if (GetActivePage() < (int) (m_pages
.GetCount() - 1))
2547 newPage
= GetActivePage() + 1;
2550 else if (key
== WXK_LEFT
)
2552 if (m_pages
.GetCount() > 1)
2554 if (GetActivePage() == -1)
2555 newPage
= (int) (m_pages
.GetCount() - 1);
2556 else if (GetActivePage() > 0)
2557 newPage
= GetActivePage() - 1;
2560 else if (key
== WXK_HOME
)
2564 else if (key
== WXK_END
)
2566 newPage
= (int) (m_pages
.GetCount() - 1);
2573 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2574 e
.SetSelection(newPage
);
2575 e
.SetOldSelection(newPage
);
2576 e
.SetEventObject(this);
2577 this->GetEventHandler()->ProcessEvent(e
);
2583 // wxTabFrame is an interesting case. It's important that all child pages
2584 // of the multi-notebook control are all actually children of that control
2585 // (and not grandchildren). wxTabFrame facilitates this. There is one
2586 // instance of wxTabFrame for each tab control inside the multi-notebook.
2587 // It's important to know that wxTabFrame is not a real window, but it merely
2588 // used to capture the dimensions/positioning of the internal tab control and
2589 // it's managed page windows
2591 class wxTabFrame
: public wxWindow
2598 m_rect
= wxRect(0,0,200,200);
2599 m_tab_ctrl_height
= 20;
2607 void SetTabCtrlHeight(int h
)
2609 m_tab_ctrl_height
= h
;
2613 void DoSetSize(int x
, int y
,
2614 int width
, int height
,
2615 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2617 m_rect
= wxRect(x
, y
, width
, height
);
2621 void DoGetClientSize(int* x
, int* y
) const
2628 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2635 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2636 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2637 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2641 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2642 size_t i
, page_count
= pages
.GetCount();
2644 for (i
= 0; i
< page_count
; ++i
)
2646 wxAuiNotebookPage
& page
= pages
.Item(i
);
2647 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2648 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2650 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2652 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2653 wnd
->ApplyMDIChildFrameRect();
2659 void DoGetSize(int* x
, int* y
) const
2662 *x
= m_rect
.GetWidth();
2664 *y
= m_rect
.GetHeight();
2675 wxAuiTabCtrl
* m_tabs
;
2676 int m_tab_ctrl_height
;
2680 const int wxAuiBaseTabCtrlId
= 5380;
2683 // -- wxAuiNotebook class implementation --
2685 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2686 EVT_SIZE(wxAuiNotebook
::OnSize
)
2687 EVT_CHILD_FOCUS(wxAuiNotebook
::OnChildFocusNotebook
)
2688 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2689 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2690 wxAuiNotebook
::OnTabClicked
)
2691 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2692 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2693 wxAuiNotebook
::OnTabBeginDrag
)
2694 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2695 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2696 wxAuiNotebook
::OnTabEndDrag
)
2697 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2698 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2699 wxAuiNotebook
::OnTabDragMotion
)
2700 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2701 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2702 wxAuiNotebook
::OnTabButton
)
2703 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2704 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2705 wxAuiNotebook
::OnTabMiddleDown
)
2706 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2707 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2708 wxAuiNotebook
::OnTabMiddleUp
)
2709 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2710 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2711 wxAuiNotebook
::OnTabRightDown
)
2712 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2713 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2714 wxAuiNotebook
::OnTabRightUp
)
2715 EVT_NAVIGATION_KEY(wxAuiNotebook
::OnNavigationKeyNotebook
)
2717 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
2718 WX_EVENT_TABLE_CONTROL_CONTAINER(wxAuiNotebook
)
2720 // Avoid clash with container event handler functions
2721 EVT_SET_FOCUS(wxAuiNotebook
::OnFocus
)
2725 WX_DELEGATE_TO_CONTROL_CONTAINER(wxAuiNotebook
, wxControl
)
2727 wxAuiNotebook
::wxAuiNotebook()
2730 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2732 m_tab_ctrl_height
= 20;
2733 m_requested_bmp_size
= wxDefaultSize
;
2734 m_requested_tabctrl_height
= -1;
2737 wxAuiNotebook
::wxAuiNotebook(wxWindow
*parent
,
2741 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2744 m_requested_bmp_size
= wxDefaultSize
;
2745 m_requested_tabctrl_height
= -1;
2746 InitNotebook(style
);
2749 bool wxAuiNotebook
::Create(wxWindow
* parent
,
2755 if (!wxControl
::Create(parent
, id
, pos
, size
, style
))
2758 InitNotebook(style
);
2763 // InitNotebook() contains common initialization
2764 // code called by all constructors
2765 void wxAuiNotebook
::InitNotebook(long style
)
2767 WX_INIT_CONTROL_CONTAINER();
2768 // SetCanFocus(false);
2770 SetName(wxT("wxAuiNotebook"));
2772 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2774 m_flags
= (unsigned int)style
;
2775 m_tab_ctrl_height
= 20;
2777 m_normal_font
= *wxNORMAL_FONT
;
2778 m_selected_font
= *wxNORMAL_FONT
;
2779 m_selected_font
.SetWeight(wxBOLD
);
2781 SetArtProvider(new wxAuiDefaultTabArt
);
2783 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2784 m_dummy_wnd
->SetSize(200, 200);
2785 m_dummy_wnd
->Show(false);
2787 m_mgr
.SetManagedWindow(this);
2788 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2789 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2791 m_mgr
.AddPane(m_dummy_wnd
,
2792 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2797 wxAuiNotebook
::~wxAuiNotebook()
2802 void wxAuiNotebook
::SetArtProvider(wxAuiTabArt
* art
)
2804 m_tabs
.SetArtProvider(art
);
2806 UpdateTabCtrlHeight();
2809 // SetTabCtrlHeight() is the highest-level override of the
2810 // tab height. A call to this function effectively enforces a
2811 // specified tab ctrl height, overriding all other considerations,
2812 // such as text or bitmap height. It overrides any call to
2813 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2814 // any previous call and returns to the default behavior
2816 void wxAuiNotebook
::SetTabCtrlHeight(int height
)
2818 m_requested_tabctrl_height
= height
;
2820 // if window is already initialized, recalculate the tab height
2823 UpdateTabCtrlHeight();
2828 // SetUniformBitmapSize() ensures that all tabs will have
2829 // the same height, even if some tabs don't have bitmaps
2830 // Passing wxDefaultSize to this function will instruct
2831 // the control to use dynamic tab height-- so when a tab
2832 // with a large bitmap is added, the tab ctrl's height will
2833 // automatically increase to accommodate the bitmap
2835 void wxAuiNotebook
::SetUniformBitmapSize(const wxSize
& size
)
2837 m_requested_bmp_size
= size
;
2839 // if window is already initialized, recalculate the tab height
2842 UpdateTabCtrlHeight();
2846 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2847 // to be used interally
2848 void wxAuiNotebook
::UpdateTabCtrlHeight()
2850 // get the tab ctrl height we will use
2851 int height
= CalculateTabCtrlHeight();
2853 // if the tab control height needs to change, update
2854 // all of our tab controls with the new height
2855 if (m_tab_ctrl_height
!= height
)
2857 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2859 m_tab_ctrl_height
= height
;
2861 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2862 size_t i
, pane_count
= all_panes
.GetCount();
2863 for (i
= 0; i
< pane_count
; ++i
)
2865 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2866 if (pane
.name
== wxT("dummy"))
2868 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2869 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2870 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2871 tabctrl
->SetArtProvider(art
->Clone());
2872 tab_frame
->DoSizing();
2877 void wxAuiNotebook
::UpdateHintWindowSize()
2879 wxSize size
= CalculateNewSplitSize();
2881 // the placeholder hint window should be set to this size
2882 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2886 info
.BestSize(size
);
2887 m_dummy_wnd
->SetSize(size
);
2892 // calculates the size of the new split
2893 wxSize wxAuiNotebook
::CalculateNewSplitSize()
2895 // count number of tab controls
2896 int tab_ctrl_count
= 0;
2897 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2898 size_t i
, pane_count
= all_panes
.GetCount();
2899 for (i
= 0; i
< pane_count
; ++i
)
2901 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2902 if (pane
.name
== wxT("dummy"))
2907 wxSize new_split_size
;
2909 // if there is only one tab control, the first split
2910 // should happen around the middle
2911 if (tab_ctrl_count
< 2)
2913 new_split_size
= GetClientSize();
2914 new_split_size
.x
/= 2;
2915 new_split_size
.y
/= 2;
2919 // this is in place of a more complicated calculation
2920 // that needs to be implemented
2921 new_split_size
= wxSize(180,180);
2924 return new_split_size
;
2927 int wxAuiNotebook
::CalculateTabCtrlHeight()
2929 // if a fixed tab ctrl height is specified,
2930 // just return that instead of calculating a
2932 if (m_requested_tabctrl_height
!= -1)
2933 return m_requested_tabctrl_height
;
2935 // find out new best tab height
2936 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2938 return art
->GetBestTabCtrlSize(this,
2940 m_requested_bmp_size
);
2944 wxAuiTabArt
* wxAuiNotebook
::GetArtProvider() const
2946 return m_tabs
.GetArtProvider();
2949 void wxAuiNotebook
::SetWindowStyleFlag(long style
)
2951 wxControl
::SetWindowStyleFlag(style
);
2953 m_flags
= (unsigned int)style
;
2955 // if the control is already initialized
2956 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2958 // let all of the tab children know about the new style
2960 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2961 size_t i
, pane_count
= all_panes
.GetCount();
2962 for (i
= 0; i
< pane_count
; ++i
)
2964 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2965 if (pane
.name
== wxT("dummy"))
2967 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2968 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2969 tabctrl
->SetFlags(m_flags
);
2970 tabframe
->DoSizing();
2978 bool wxAuiNotebook
::AddPage(wxWindow
* page
,
2979 const wxString
& caption
,
2981 const wxBitmap
& bitmap
)
2983 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2986 bool wxAuiNotebook
::InsertPage(size_t page_idx
,
2988 const wxString
& caption
,
2990 const wxBitmap
& bitmap
)
2992 page
->Reparent(this);
2994 wxAuiNotebookPage info
;
2996 info
.caption
= caption
;
2997 info
.bitmap
= bitmap
;
2998 info
.active
= false;
3000 // if there are currently no tabs, the first added
3001 // tab must be active
3002 if (m_tabs
.GetPageCount() == 0)
3005 m_tabs
.InsertPage(page
, info
, page_idx
);
3007 // if that was the first page added, even if
3008 // select is false, it must become the "current page"
3009 // (though no select events will be fired)
3010 if (!select
&& m_tabs
.GetPageCount() == 1)
3012 //m_curpage = GetPageIndex(page);
3014 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
3015 if (page_idx
>= active_tabctrl
->GetPageCount())
3016 active_tabctrl
->AddPage(page
, info
);
3018 active_tabctrl
->InsertPage(page
, info
, page_idx
);
3020 UpdateTabCtrlHeight();
3022 active_tabctrl
->DoShowHide();
3024 // adjust selected index
3025 if(m_curpage
>= (int) page_idx
)
3030 SetSelectionToWindow(page
);
3037 // DeletePage() removes a tab from the multi-notebook,
3038 // and destroys the window as well
3039 bool wxAuiNotebook
::DeletePage(size_t page_idx
)
3041 if (page_idx
>= m_tabs
.GetPageCount())
3044 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3046 // hide the window in advance, as this will
3048 ShowWnd(wnd
, false);
3050 if (!RemovePage(page_idx
))
3053 // actually destroy the window now
3054 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3056 // delete the child frame with pending delete, as is
3057 // customary with frame windows
3058 if (!wxPendingDelete
.Member(wnd
))
3059 wxPendingDelete
.Append(wnd
);
3071 // RemovePage() removes a tab from the multi-notebook,
3072 // but does not destroy the window
3073 bool wxAuiNotebook
::RemovePage(size_t page_idx
)
3075 // save active window pointer
3076 wxWindow
* active_wnd
= NULL
;
3078 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
3080 // save pointer of window being deleted
3081 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
3082 wxWindow
* new_active
= NULL
;
3084 // make sure we found the page
3088 // find out which onscreen tab ctrl owns this tab
3091 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
3094 bool is_curpage
= (m_curpage
== (int)page_idx
);
3095 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
3098 // remove the tab from main catalog
3099 if (!m_tabs
.RemovePage(wnd
))
3102 // remove the tab from the onscreen tab ctrl
3103 ctrl
->RemovePage(wnd
);
3105 if (is_active_in_split
)
3107 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
3109 if (ctrl_idx
>= ctrl_new_page_count
)
3110 ctrl_idx
= ctrl_new_page_count
-1;
3112 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
3114 // set new page as active in the tab split
3115 ctrl
->SetActivePage(ctrl_idx
);
3117 // if the page deleted was the current page for the
3118 // entire tab control, then record the window
3119 // pointer of the new active page for activation
3122 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
3128 // we are not deleting the active page, so keep it the same
3129 new_active
= active_wnd
;
3135 // we haven't yet found a new page to active,
3136 // so select the next page from the main tab
3139 if (page_idx
< m_tabs
.GetPageCount())
3141 new_active
= m_tabs
.GetPage(page_idx
).window
;
3144 if (!new_active
&& m_tabs
.GetPageCount() > 0)
3146 new_active
= m_tabs
.GetPage(0).window
;
3151 RemoveEmptyTabFrames();
3153 // set new active pane
3157 SetSelectionToWindow(new_active
);
3163 // GetPageIndex() returns the index of the page, or -1 if the
3164 // page could not be located in the notebook
3165 int wxAuiNotebook
::GetPageIndex(wxWindow
* page_wnd
) const
3167 return m_tabs
.GetIdxFromWindow(page_wnd
);
3172 // SetPageText() changes the tab caption of the specified page
3173 bool wxAuiNotebook
::SetPageText(size_t page_idx
, const wxString
& text
)
3175 if (page_idx
>= m_tabs
.GetPageCount())
3178 // update our own tab catalog
3179 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3180 page_info
.caption
= text
;
3182 // update what's on screen
3185 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3187 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3188 info
.caption
= text
;
3196 // returns the page caption
3197 wxString wxAuiNotebook
::GetPageText(size_t page_idx
) const
3199 if (page_idx
>= m_tabs
.GetPageCount())
3200 return wxEmptyString
;
3202 // update our own tab catalog
3203 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3204 return page_info
.caption
;
3207 bool wxAuiNotebook
::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
3209 if (page_idx
>= m_tabs
.GetPageCount())
3212 // update our own tab catalog
3213 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3214 page_info
.bitmap
= bitmap
;
3216 // tab height might have changed
3217 UpdateTabCtrlHeight();
3219 // update what's on screen
3222 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
3224 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
3225 info
.bitmap
= bitmap
;
3233 // returns the page bitmap
3234 wxBitmap wxAuiNotebook
::GetPageBitmap(size_t page_idx
) const
3236 if (page_idx
>= m_tabs
.GetPageCount())
3239 // update our own tab catalog
3240 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
3241 return page_info
.bitmap
;
3244 // GetSelection() returns the index of the currently active page
3245 int wxAuiNotebook
::GetSelection() const
3250 // SetSelection() sets the currently active page
3251 size_t wxAuiNotebook
::SetSelection(size_t new_page
)
3253 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
3257 // don't change the page unless necessary;
3258 // however, clicking again on a tab should give it the focus.
3259 if ((int)new_page
== m_curpage
)
3263 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3265 if (FindFocus() != ctrl
)
3271 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
3272 evt
.SetSelection(new_page
);
3273 evt
.SetOldSelection(m_curpage
);
3274 evt
.SetEventObject(this);
3275 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
3277 int old_curpage
= m_curpage
;
3278 m_curpage
= new_page
;
3280 // program allows the page change
3281 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
3282 (void)GetEventHandler()->ProcessEvent(evt
);
3287 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
3289 m_tabs
.SetActivePage(wnd
);
3291 ctrl
->SetActivePage(ctrl_idx
);
3295 ctrl
->MakeTabVisible(ctrl_idx
, ctrl
);
3298 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3299 size_t i
, pane_count
= all_panes
.GetCount();
3300 for (i
= 0; i
< pane_count
; ++i
)
3302 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3303 if (pane
.name
== wxT("dummy"))
3305 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
3306 if (tabctrl
!= ctrl
)
3307 tabctrl
->SetSelectedFont(m_normal_font
);
3309 tabctrl
->SetSelectedFont(m_selected_font
);
3313 // Set the focus to the page if we're not currently focused on the tab.
3314 // This is Firefox-like behaviour.
3315 if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)
3325 void wxAuiNotebook
::SetSelectionToWindow(wxWindow
*win
)
3327 const int idx
= m_tabs
.GetIdxFromWindow(win
);
3328 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
3333 // GetPageCount() returns the total number of
3334 // pages managed by the multi-notebook
3335 size_t wxAuiNotebook
::GetPageCount() const
3337 return m_tabs
.GetPageCount();
3340 // GetPage() returns the wxWindow pointer of the
3342 wxWindow
* wxAuiNotebook
::GetPage(size_t page_idx
) const
3344 wxASSERT(page_idx
< m_tabs
.GetPageCount());
3346 return m_tabs
.GetWindowFromIdx(page_idx
);
3349 // DoSizing() performs all sizing operations in each tab control
3350 void wxAuiNotebook
::DoSizing()
3352 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3353 size_t i
, pane_count
= all_panes
.GetCount();
3354 for (i
= 0; i
< pane_count
; ++i
)
3356 if (all_panes
.Item(i
).name
== wxT("dummy"))
3359 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3360 tabframe
->DoSizing();
3364 // GetActiveTabCtrl() returns the active tab control. It is
3365 // called to determine which control gets new windows being added
3366 wxAuiTabCtrl
* wxAuiNotebook
::GetActiveTabCtrl()
3368 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3373 // find the tab ctrl with the current page
3374 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3381 // no current page, just find the first tab ctrl
3382 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3383 size_t i
, pane_count
= all_panes
.GetCount();
3384 for (i
= 0; i
< pane_count
; ++i
)
3386 if (all_panes
.Item(i
).name
== wxT("dummy"))
3389 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3390 return tabframe
->m_tabs
;
3393 // If there is no tabframe at all, create one
3394 wxTabFrame
* tabframe
= new wxTabFrame
;
3395 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3396 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3400 wxNO_BORDER
|wxWANTS_CHARS
);
3401 tabframe
->m_tabs
->SetFlags(m_flags
);
3402 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3403 m_mgr
.AddPane(tabframe
,
3404 wxAuiPaneInfo().Center().CaptionVisible(false));
3408 return tabframe
->m_tabs
;
3411 // FindTab() finds the tab control that currently contains the window as well
3412 // as the index of the window in the tab control. It returns true if the
3413 // window was found, otherwise false.
3414 bool wxAuiNotebook
::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3416 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3417 size_t i
, pane_count
= all_panes
.GetCount();
3418 for (i
= 0; i
< pane_count
; ++i
)
3420 if (all_panes
.Item(i
).name
== wxT("dummy"))
3423 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3425 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3428 *ctrl
= tabframe
->m_tabs
;
3437 void wxAuiNotebook
::Split(size_t page
, int direction
)
3439 wxSize cli_size
= GetClientSize();
3441 // get the page's window pointer
3442 wxWindow
* wnd
= GetPage(page
);
3446 // notebooks with 1 or less pages can't be split
3447 if (GetPageCount() < 2)
3450 // find out which tab control the page currently belongs to
3451 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3454 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3456 if (!src_tabs
|| src_idx
== -1)
3459 // choose a split size
3461 if (GetPageCount() > 2)
3463 split_size
= CalculateNewSplitSize();
3467 // because there are two panes, always split them
3469 split_size
= GetClientSize();
3475 // create a new tab frame
3476 wxTabFrame
* new_tabs
= new wxTabFrame
;
3477 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3478 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3479 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3483 wxNO_BORDER
|wxWANTS_CHARS
);
3484 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3485 new_tabs
->m_tabs
->SetFlags(m_flags
);
3486 dest_tabs
= new_tabs
->m_tabs
;
3488 // create a pane info structure with the information
3489 // about where the pane should be added
3490 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3493 if (direction
== wxLEFT
)
3496 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3498 else if (direction
== wxRIGHT
)
3501 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3503 else if (direction
== wxTOP
)
3506 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3508 else if (direction
== wxBOTTOM
)
3511 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3514 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3517 // remove the page from the source tabs
3518 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3519 page_info
.active
= false;
3520 src_tabs
->RemovePage(page_info
.window
);
3521 if (src_tabs
->GetPageCount() > 0)
3523 src_tabs
->SetActivePage((size_t)0);
3524 src_tabs
->DoShowHide();
3525 src_tabs
->Refresh();
3529 // add the page to the destination tabs
3530 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3532 if (src_tabs
->GetPageCount() == 0)
3534 RemoveEmptyTabFrames();
3538 dest_tabs
->DoShowHide();
3539 dest_tabs
->Refresh();
3541 // force the set selection function reset the selection
3544 // set the active page to the one we just split off
3545 SetSelectionToPage(page_info
);
3547 UpdateHintWindowSize();
3551 void wxAuiNotebook
::OnSize(wxSizeEvent
& evt
)
3553 UpdateHintWindowSize();
3558 void wxAuiNotebook
::OnTabClicked(wxCommandEvent
& command_evt
)
3560 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3562 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3563 wxASSERT(ctrl
!= NULL
);
3565 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3566 wxASSERT(wnd
!= NULL
);
3568 SetSelectionToWindow(wnd
);
3571 void wxAuiNotebook
::OnTabBeginDrag(wxCommandEvent
&)
3576 void wxAuiNotebook
::OnTabDragMotion(wxCommandEvent
& evt
)
3578 wxPoint screen_pt
= ::wxGetMousePosition();
3579 wxPoint client_pt
= ScreenToClient(screen_pt
);
3582 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3583 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3585 if (dest_tabs
== src_tabs
)
3589 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3592 // always hide the hint for inner-tabctrl drag
3595 // if tab moving is not allowed, leave
3596 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3601 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3602 wxWindow
* dest_location_tab
;
3604 // this is an inner-tab drag/reposition
3605 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3607 int src_idx
= evt
.GetSelection();
3608 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3610 // prevent jumpy drag
3611 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3612 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3613 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3615 m_last_drag_x
= pt
.x
;
3620 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3621 dest_tabs
->MovePage(src_tab
, dest_idx
);
3622 dest_tabs
->SetActivePage((size_t)dest_idx
);
3623 dest_tabs
->DoShowHide();
3624 dest_tabs
->Refresh();
3625 m_last_drag_x
= pt
.x
;
3633 // if external drag is allowed, check if the tab is being dragged
3634 // over a different wxAuiNotebook control
3635 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3637 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3639 // if we aren't over any window, stop here
3643 // make sure we are not over the hint window
3644 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3648 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3650 tab_ctrl
= tab_ctrl
->GetParent();
3655 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3659 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3660 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3661 m_mgr
.ShowHint(hint_rect
);
3670 // we are either over a hint window, or not over a tab
3671 // window, and there is no where to drag to, so exit
3678 // if there are less than two panes, split can't happen, so leave
3679 if (m_tabs
.GetPageCount() < 2)
3682 // if tab moving is not allowed, leave
3683 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3689 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3695 wxRect hint_rect
= dest_tabs
->GetRect();
3696 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3697 m_mgr
.ShowHint(hint_rect
);
3701 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3707 void wxAuiNotebook
::OnTabEndDrag(wxCommandEvent
& command_evt
)
3709 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3714 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3715 wxCHECK_RET( src_tabs
, _T("no source object?") );
3717 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3719 // get the mouse position, which will be used to determine the drop point
3720 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3721 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3725 // check for an external move
3726 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3728 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3732 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3734 tab_ctrl
= tab_ctrl
->GetParent();
3739 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3743 // find out from the destination control
3744 // if it's ok to drop this tab here
3745 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3746 e
.SetSelection(evt
.GetSelection());
3747 e
.SetOldSelection(evt
.GetSelection());
3748 e
.SetEventObject(this);
3749 e
.SetDragSource(this);
3750 e
.Veto(); // dropping must be explicitly approved by control owner
3752 nb
->GetEventHandler()->ProcessEvent(e
);
3756 // no answer or negative answer
3762 int src_idx
= evt
.GetSelection();
3763 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3765 // Check that it's not an impossible parent relationship
3767 while (p
&& !p
->IsTopLevel())
3776 // get main index of the page
3777 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3778 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3781 // make a copy of the page info
3782 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3784 // remove the page from the source notebook
3785 RemovePage(main_idx
);
3787 // reparent the page
3788 src_page
->Reparent(nb
);
3791 // found out the insert idx
3792 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3793 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3795 wxWindow
* target
= NULL
;
3796 int insert_idx
= -1;
3797 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3800 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3804 // add the page to the new notebook
3805 if (insert_idx
== -1)
3806 insert_idx
= dest_tabs
->GetPageCount();
3807 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3808 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3811 dest_tabs
->DoShowHide();
3812 dest_tabs
->Refresh();
3814 // set the selection in the destination tab control
3815 nb
->SetSelectionToPage(page_info
);
3825 // only perform a tab split if it's allowed
3826 wxAuiTabCtrl
* dest_tabs
= NULL
;
3828 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3830 // If the pointer is in an existing tab frame, do a tab insert
3831 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3832 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3833 int insert_idx
= -1;
3836 dest_tabs
= tab_frame
->m_tabs
;
3838 if (dest_tabs
== src_tabs
)
3842 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3843 wxWindow
* target
= NULL
;
3844 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3847 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3853 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3858 // there is no suitable drop location here, exit out
3862 // If there is no tabframe at all, create one
3863 wxTabFrame
* new_tabs
= new wxTabFrame
;
3864 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3865 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3866 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3870 wxNO_BORDER
|wxWANTS_CHARS
);
3871 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3872 new_tabs
->m_tabs
->SetFlags(m_flags
);
3874 m_mgr
.AddPane(new_tabs
,
3875 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3878 dest_tabs
= new_tabs
->m_tabs
;
3883 // remove the page from the source tabs
3884 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3885 page_info
.active
= false;
3886 src_tabs
->RemovePage(page_info
.window
);
3887 if (src_tabs
->GetPageCount() > 0)
3889 src_tabs
->SetActivePage((size_t)0);
3890 src_tabs
->DoShowHide();
3891 src_tabs
->Refresh();
3896 // add the page to the destination tabs
3897 if (insert_idx
== -1)
3898 insert_idx
= dest_tabs
->GetPageCount();
3899 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3901 if (src_tabs
->GetPageCount() == 0)
3903 RemoveEmptyTabFrames();
3907 dest_tabs
->DoShowHide();
3908 dest_tabs
->Refresh();
3910 // force the set selection function reset the selection
3913 // set the active page to the one we just split off
3914 SetSelectionToPage(page_info
);
3916 UpdateHintWindowSize();
3922 wxAuiTabCtrl
* wxAuiNotebook
::GetTabCtrlFromPoint(const wxPoint
& pt
)
3924 // if we've just removed the last tab from the source
3925 // tab set, the remove the tab control completely
3926 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3927 size_t i
, pane_count
= all_panes
.GetCount();
3928 for (i
= 0; i
< pane_count
; ++i
)
3930 if (all_panes
.Item(i
).name
== wxT("dummy"))
3933 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3934 if (tabframe
->m_tab_rect
.Contains(pt
))
3935 return tabframe
->m_tabs
;
3941 wxWindow
* wxAuiNotebook
::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3943 // if we've just removed the last tab from the source
3944 // tab set, the remove the tab control completely
3945 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3946 size_t i
, pane_count
= all_panes
.GetCount();
3947 for (i
= 0; i
< pane_count
; ++i
)
3949 if (all_panes
.Item(i
).name
== wxT("dummy"))
3952 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3953 if (tabframe
->m_tabs
== tab_ctrl
)
3962 void wxAuiNotebook
::RemoveEmptyTabFrames()
3964 // if we've just removed the last tab from the source
3965 // tab set, the remove the tab control completely
3966 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3967 size_t i
, pane_count
= all_panes
.GetCount();
3968 for (i
= 0; i
< pane_count
; ++i
)
3970 if (all_panes
.Item(i
).name
== wxT("dummy"))
3973 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3974 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3976 m_mgr
.DetachPane(tab_frame
);
3978 // use pending delete because sometimes during
3979 // window closing, refreshs are pending
3980 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3981 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3983 tab_frame
->m_tabs
= NULL
;
3990 // check to see if there is still a center pane;
3991 // if there isn't, make a frame the center pane
3992 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3993 pane_count
= panes
.GetCount();
3994 wxWindow
* first_good
= NULL
;
3995 bool center_found
= false;
3996 for (i
= 0; i
< pane_count
; ++i
)
3998 if (panes
.Item(i
).name
== wxT("dummy"))
4000 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
4001 center_found
= true;
4003 first_good
= panes
.Item(i
).window
;
4006 if (!center_found
&& first_good
)
4008 m_mgr
.GetPane(first_good
).Centre();
4014 void wxAuiNotebook
::OnChildFocusNotebook(wxChildFocusEvent
& evt
)
4016 // if we're dragging a tab, don't change the current selection.
4017 // This code prevents a bug that used to happen when the hint window
4018 // was hidden. In the bug, the focus would return to the notebook
4019 // child, which would then enter this handler and call
4020 // SetSelection, which is not desired turn tab dragging.
4022 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
4023 size_t i
, pane_count
= all_panes
.GetCount();
4024 for (i
= 0; i
< pane_count
; ++i
)
4026 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
4027 if (pane
.name
== wxT("dummy"))
4029 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
4030 if (tabframe
->m_tabs
->IsDragging())
4035 // change the tab selection to the child
4036 // which was focused
4037 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
4038 if (idx
!= -1 && idx
!= m_curpage
)
4044 void wxAuiNotebook
::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
)
4046 if ( event
.IsWindowChange() ) {
4048 // FIXME: the problem with this is that if we have a split notebook,
4049 // we selection may go all over the place.
4050 AdvanceSelection(event
.GetDirection());
4053 // we get this event in 3 cases
4055 // a) one of our pages might have generated it because the user TABbed
4056 // out from it in which case we should propagate the event upwards and
4057 // our parent will take care of setting the focus to prev/next sibling
4061 // b) the parent panel wants to give the focus to us so that we
4062 // forward it to our selected page. We can't deal with this in
4063 // OnSetFocus() because we don't know which direction the focus came
4064 // from in this case and so can't choose between setting the focus to
4065 // first or last panel child
4069 // c) we ourselves (see MSWTranslateMessage) generated the event
4071 wxWindow
* const parent
= GetParent();
4073 // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE
4074 const bool isFromParent
= event
.GetEventObject() == (wxObject
*) parent
;
4075 const bool isFromSelf
= event
.GetEventObject() == (wxObject
*) this;
4077 if ( isFromParent
|| isFromSelf
)
4079 // no, it doesn't come from child, case (b) or (c): forward to a
4080 // page but only if direction is backwards (TAB) or from ourselves,
4081 if ( GetSelection() != wxNOT_FOUND
&&
4082 (!event
.GetDirection() || isFromSelf
) )
4084 // so that the page knows that the event comes from it's parent
4085 // and is being propagated downwards
4086 event
.SetEventObject(this);
4088 wxWindow
*page
= GetPage(GetSelection());
4089 if ( !page
->GetEventHandler()->ProcessEvent(event
) )
4093 //else: page manages focus inside it itself
4095 else // otherwise set the focus to the notebook itself
4102 // it comes from our child, case (a), pass to the parent, but only
4103 // if the direction is forwards. Otherwise set the focus to the
4104 // notebook itself. The notebook is always the 'first' control of a
4106 if ( !event
.GetDirection() )
4112 event
.SetCurrentFocus(this);
4113 parent
->GetEventHandler()->ProcessEvent(event
);
4119 void wxAuiNotebook
::OnTabButton(wxCommandEvent
& command_evt
)
4121 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
4122 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4124 int button_id
= evt
.GetInt();
4126 if (button_id
== wxAUI_BUTTON_CLOSE
)
4128 int selection
= evt
.GetSelection();
4130 if (selection
== -1)
4132 // if the close button is to the right, use the active
4133 // page selection to determine which page to close
4134 selection
= GetSelection();
4137 if (selection
!= -1)
4139 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
4141 // ask owner if it's ok to close the tab
4142 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
4143 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
4144 e
.SetOldSelection(evt
.GetSelection());
4145 e
.SetEventObject(this);
4146 GetEventHandler()->ProcessEvent(e
);
4151 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
4157 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
4158 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
4160 DeletePage(main_idx
);
4167 void wxAuiNotebook
::OnTabMiddleDown(wxCommandEvent
& evt
)
4169 // patch event through to owner
4170 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4171 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4173 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
4174 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4175 e
.SetEventObject(this);
4176 GetEventHandler()->ProcessEvent(e
);
4179 void wxAuiNotebook
::OnTabMiddleUp(wxCommandEvent
& evt
)
4181 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
4182 // click should act like a tab close action. However, first
4183 // give the owner an opportunity to handle the middle up event
4184 // for custom action
4186 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4187 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4189 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
4190 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4191 e
.SetEventObject(this);
4192 if (GetEventHandler()->ProcessEvent(e
))
4197 // check if we are supposed to close on middle-up
4198 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
4201 // simulate the user pressing the close button on the tab
4202 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
4206 void wxAuiNotebook
::OnTabRightDown(wxCommandEvent
& evt
)
4208 // patch event through to owner
4209 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4210 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4212 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
4213 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4214 e
.SetEventObject(this);
4215 GetEventHandler()->ProcessEvent(e
);
4218 void wxAuiNotebook
::OnTabRightUp(wxCommandEvent
& evt
)
4220 // patch event through to owner
4221 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
4222 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
4224 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
4225 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
4226 e
.SetEventObject(this);
4227 GetEventHandler()->ProcessEvent(e
);
4230 // Sets the normal font
4231 void wxAuiNotebook
::SetNormalFont(const wxFont
& font
)
4233 m_normal_font
= font
;
4234 GetArtProvider()->SetNormalFont(font
);
4237 // Sets the selected tab font
4238 void wxAuiNotebook
::SetSelectedFont(const wxFont
& font
)
4240 m_selected_font
= font
;
4241 GetArtProvider()->SetSelectedFont(font
);
4244 // Sets the measuring font
4245 void wxAuiNotebook
::SetMeasuringFont(const wxFont
& font
)
4247 GetArtProvider()->SetMeasuringFont(font
);
4250 // Sets the tab font
4251 bool wxAuiNotebook
::SetFont(const wxFont
& font
)
4253 wxControl
::SetFont(font
);
4255 wxFont
normalFont(font
);
4256 wxFont
selectedFont(normalFont
);
4257 selectedFont
.SetWeight(wxBOLD
);
4259 SetNormalFont(normalFont
);
4260 SetSelectedFont(selectedFont
);
4261 SetMeasuringFont(selectedFont
);
4266 // Gets the tab control height
4267 int wxAuiNotebook
::GetTabCtrlHeight() const
4269 return m_tab_ctrl_height
;
4272 // Gets the height of the notebook for a given page height
4273 int wxAuiNotebook
::GetHeightForPageHeight(int pageHeight
)
4275 UpdateTabCtrlHeight();
4277 int tabCtrlHeight
= GetTabCtrlHeight();
4278 int decorHeight
= 2;
4279 return tabCtrlHeight
+ pageHeight
+ decorHeight
;
4282 // Advances the selection, generation page selection events
4283 void wxAuiNotebook
::AdvanceSelection(bool forward
)
4285 if (GetPageCount() <= 1)
4288 int currentSelection
= GetSelection();
4292 if (currentSelection
== (int) (GetPageCount() - 1))
4294 else if (currentSelection
== -1)
4295 currentSelection
= 0;
4297 currentSelection
++;
4301 if (currentSelection
<= 0)
4304 currentSelection
--;
4307 SetSelection(currentSelection
);
4310 // Shows the window menu
4311 bool wxAuiNotebook
::ShowWindowMenu()
4313 wxAuiTabCtrl
* tabCtrl
= GetActiveTabCtrl();
4315 int idx
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage());
4319 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId());
4320 e
.SetSelection(idx
);
4321 e
.SetOldSelection(tabCtrl
->GetActivePage());
4322 e
.SetEventObject(tabCtrl
);
4323 GetEventHandler()->ProcessEvent(e
);