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"
35 #include "wx/mac/carbon/private.h"
38 #include "wx/arrimpl.cpp"
39 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
)
40 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
)
42 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
)
43 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
)
44 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
)
45 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
)
46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
)
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
)
50 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
)
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
)
56 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
)
57 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
)
58 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
)
64 // these functions live in dockart.cpp -- they'll eventually
65 // be moved to a new utility cpp file
67 wxColor
wxAuiStepColour(const wxColor
& c
, int percent
);
69 wxBitmap
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
,
70 const wxColour
& color
);
72 wxString
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
);
74 static void DrawButtons(wxDC
& dc
,
77 const wxColour
& bkcolour
,
82 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
88 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
89 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
91 dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120)));
92 dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75)));
94 // draw the background behind the button
95 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
98 // draw the button itself
99 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
102 static void IndentPressedBitmap(wxRect
* rect
, int button_state
)
104 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
113 // -- GUI helper classes and functions --
115 class wxAuiCommandCapture
: public wxEvtHandler
119 wxAuiCommandCapture() { m_last_id
= 0; }
120 int GetCommandId() const { return m_last_id
; }
122 bool ProcessEvent(wxEvent
& evt
)
124 if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
)
126 m_last_id
= evt
.GetId();
130 if (GetNextHandler())
131 return GetNextHandler()->ProcessEvent(evt
);
143 #if defined( __WXMAC__ )
144 static unsigned char close_bits
[]={
145 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
146 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
147 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
148 #elif defined( __WXGTK__)
149 static unsigned char close_bits
[]={
150 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
151 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
152 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
154 static unsigned char close_bits
[]={
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9,
156 0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
160 static unsigned char left_bits
[] = {
161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe,
162 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe,
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
165 static unsigned char right_bits
[] = {
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff,
167 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff,
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
170 static unsigned char list_bits
[] = {
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
180 // -- wxAuiDefaultTabArt class implementation --
182 wxAuiDefaultTabArt::wxAuiDefaultTabArt()
184 m_normal_font
= *wxNORMAL_FONT
;
185 m_selected_font
= *wxNORMAL_FONT
;
186 m_selected_font
.SetWeight(wxBOLD
);
187 m_measuring_font
= m_selected_font
;
189 m_fixed_tab_width
= 100;
190 m_tab_ctrl_height
= 0;
193 wxBrush toolbarbrush
;
194 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
195 wxColor base_colour
= toolbarbrush
.GetColour();
197 wxColor base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
200 // the base_colour is too pale to use as our base colour,
201 // so darken it a bit --
202 if ((255-base_colour
.Red()) +
203 (255-base_colour
.Green()) +
204 (255-base_colour
.Blue()) < 60)
206 base_colour
= wxAuiStepColour(base_colour
, 92);
209 m_base_colour
= base_colour
;
210 wxColor border_colour
= wxAuiStepColour(base_colour
, 75);
212 m_border_pen
= wxPen(border_colour
);
213 m_base_colour_pen
= wxPen(m_base_colour
);
214 m_base_colour_brush
= wxBrush(m_base_colour
);
216 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
217 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
219 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
220 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
222 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
223 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
225 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
226 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
231 wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
235 wxAuiTabArt
* wxAuiDefaultTabArt::Clone()
237 wxAuiDefaultTabArt
* art
= new wxAuiDefaultTabArt
;
238 art
->SetNormalFont(m_normal_font
);
239 art
->SetSelectedFont(m_selected_font
);
240 art
->SetMeasuringFont(m_measuring_font
);
245 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
)
250 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
253 m_fixed_tab_width
= 100;
255 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
257 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
258 tot_width
-= m_active_close_bmp
.GetWidth();
259 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
260 tot_width
-= m_active_windowlist_bmp
.GetWidth();
264 m_fixed_tab_width
= tot_width
/(int)tab_count
;
268 if (m_fixed_tab_width
< 100)
269 m_fixed_tab_width
= 100;
271 if (m_fixed_tab_width
> tot_width
/2)
272 m_fixed_tab_width
= tot_width
/2;
274 if (m_fixed_tab_width
> 220)
275 m_fixed_tab_width
= 220;
277 m_tab_ctrl_height
= tab_ctrl_size
.y
;
281 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
,
282 wxWindow
* WXUNUSED(wnd
),
286 wxRect
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3);
287 wxColor top_color
= wxAuiStepColour(m_base_colour
, 90);
288 wxColor bottom_color
= wxAuiStepColour(m_base_colour
, 170);
289 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
292 int y
= rect
.GetHeight();
293 int w
= rect
.GetWidth();
294 dc
.SetPen(m_border_pen
);
295 dc
.SetBrush(m_base_colour_brush
);
296 dc
.DrawRectangle(-1, y
-4, w
+2, 4);
300 // DrawTab() draws an individual tab.
303 // in_rect - rectangle the tab should be confined to
304 // caption - tab's caption
305 // active - whether or not the tab is active
306 // out_rect - actual output rectangle
307 // x_extent - the advance x; where the next tab should start
309 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
,
311 const wxAuiNotebookPage
& page
,
312 const wxRect
& in_rect
,
313 int close_button_state
,
314 wxRect
* out_tab_rect
,
315 wxRect
* out_button_rect
,
318 wxCoord normal_textx
, normal_texty
;
319 wxCoord selected_textx
, selected_texty
;
322 // if the caption is empty, measure some temporary text
323 wxString caption
= page
.caption
;
327 dc
.SetFont(m_selected_font
);
328 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
330 dc
.SetFont(m_normal_font
);
331 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
333 // figure out the size of the tab
334 wxSize tab_size
= GetTabSize(dc
,
342 wxCoord tab_height
= m_tab_ctrl_height
- 3;
343 wxCoord tab_width
= tab_size
.x
;
344 wxCoord tab_x
= in_rect
.x
;
345 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
348 caption
= page
.caption
;
351 // select pen, brush and font for the tab to be drawn
355 dc
.SetFont(m_selected_font
);
356 texty
= selected_texty
;
360 dc
.SetFont(m_normal_font
);
361 texty
= normal_texty
;
365 // create points that will make the tab outline
367 int clip_width
= tab_width
;
368 if (tab_x
+ clip_width
> in_rect
.x
+ in_rect
.width
)
369 clip_width
= (in_rect
.x
+ in_rect
.width
) - tab_x
;
372 wxPoint clip_points[6];
373 clip_points[0] = wxPoint(tab_x, tab_y+tab_height-3);
374 clip_points[1] = wxPoint(tab_x, tab_y+2);
375 clip_points[2] = wxPoint(tab_x+2, tab_y);
376 clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y);
377 clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2);
378 clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3);
380 // FIXME: these ports don't provide wxRegion ctor from array of points
381 #if !defined(__WXDFB__) && !defined(__WXCOCOA__)
382 // set the clipping region for the tab --
383 wxRegion clipping_region(WXSIZEOF(clip_points), clip_points);
384 dc.SetClippingRegion(clipping_region);
385 #endif // !wxDFB && !wxCocoa
387 // since the above code above doesn't play well with WXDFB or WXCOCOA,
388 // we'll just use a rectangle for the clipping region for now --
389 dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3);
392 wxPoint border_points
[6];
393 border_points
[0] = wxPoint(tab_x
, tab_y
+tab_height
-4);
394 border_points
[1] = wxPoint(tab_x
, tab_y
+2);
395 border_points
[2] = wxPoint(tab_x
+2, tab_y
);
396 border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
);
397 border_points
[4] = wxPoint(tab_x
+tab_width
, tab_y
+2);
398 border_points
[5] = wxPoint(tab_x
+tab_width
, tab_y
+tab_height
-4);
401 int drawn_tab_yoff
= border_points
[1].y
;
402 int drawn_tab_height
= border_points
[0].y
- border_points
[1].y
;
409 // draw base background color
410 wxRect
r(tab_x
, tab_y
, tab_width
, tab_height
);
411 dc
.SetPen(m_base_colour_pen
);
412 dc
.SetBrush(m_base_colour_brush
);
413 dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4);
415 // this white helps fill out the gradient at the top of the tab
416 dc
.SetPen(*wxWHITE_PEN
);
417 dc
.SetBrush(*wxWHITE_BRUSH
);
418 dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4);
420 // these two points help the rounded corners appear more antialiased
421 dc
.SetPen(m_base_colour_pen
);
422 dc
.DrawPoint(r
.x
+2, r
.y
+1);
423 dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1);
425 // set rectangle down a bit for gradient drawing
426 r
.SetHeight(r
.GetHeight()/2);
432 // draw gradient background
433 wxColor top_color
= *wxWHITE
;
434 wxColor bottom_color
= m_base_colour
;
435 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
441 wxRect
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3);
443 // start the gradent up a bit and leave the inside border inset
444 // by a pixel for a 3D look. Only the top half of the inactive
445 // tab will have a slight gradient
452 // -- draw top gradient fill for glossy look
453 wxColor top_color
= m_base_colour
;
454 wxColor bottom_color
= wxAuiStepColour(top_color
, 160);
455 dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
);
460 // -- draw bottom fill for glossy look
461 top_color
= m_base_colour
;
462 bottom_color
= m_base_colour
;
463 dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
);
467 dc
.SetPen(m_border_pen
);
468 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
469 dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
);
471 // there are two horizontal grey lines at the bottom of the tab control,
472 // this gets rid of the top one of those lines in the tab control
475 dc
.SetPen(m_base_colour_pen
);
476 dc
.DrawLine(border_points
[0].x
+1,
483 int text_offset
= tab_x
+ 8;
484 int close_button_width
= 0;
485 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
487 close_button_width
= m_active_close_bmp
.GetWidth();
491 if (page
.bitmap
.IsOk())
493 int bitmap_offset
= tab_x
+ 8;
496 dc
.DrawBitmap(page
.bitmap
,
498 drawn_tab_yoff
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2),
501 text_offset
= bitmap_offset
+ page
.bitmap
.GetWidth();
502 text_offset
+= 3; // bitmap padding
506 text_offset
= tab_x
+ 8;
510 wxString draw_text
= wxAuiChopText(dc
,
512 tab_width
- (text_offset
-tab_x
) - close_button_width
);
515 dc
.DrawText(draw_text
,
517 drawn_tab_yoff
+ (drawn_tab_height
)/2 - (texty
/2) - 1);
522 // draw close button if necessary
523 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
525 wxBitmap bmp
= m_disabled_close_bmp
;
527 if (close_button_state
== wxAUI_BUTTON_STATE_HOVER
||
528 close_button_state
== wxAUI_BUTTON_STATE_PRESSED
)
530 bmp
= m_active_close_bmp
;
533 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
534 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2),
537 IndentPressedBitmap(&rect
, close_button_state
);
538 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
540 *out_button_rect
= rect
;
543 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
545 dc
.DestroyClippingRegion();
548 int wxAuiDefaultTabArt::GetIndentSize()
553 wxSize
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
,
554 wxWindow
* WXUNUSED(wnd
),
555 const wxString
& caption
,
556 const wxBitmap
& bitmap
,
557 bool WXUNUSED(active
),
558 int close_button_state
,
561 wxCoord measured_textx
, measured_texty
, tmp
;
563 dc
.SetFont(m_measuring_font
);
564 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
566 dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
);
568 // add padding around the text
569 wxCoord tab_width
= measured_textx
;
570 wxCoord tab_height
= measured_texty
;
572 // if the close button is showing, add space for it
573 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
574 tab_width
+= m_active_close_bmp
.GetWidth() + 3;
576 // if there's a bitmap, add space for it
579 tab_width
+= bitmap
.GetWidth();
580 tab_width
+= 3; // right side bitmap padding
581 tab_height
= wxMax(tab_height
, bitmap
.GetHeight());
588 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
590 tab_width
= m_fixed_tab_width
;
593 *x_extent
= tab_width
;
595 return wxSize(tab_width
, tab_height
);
599 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
,
600 wxWindow
* WXUNUSED(wnd
),
601 const wxRect
& in_rect
,
612 case wxAUI_BUTTON_CLOSE
:
613 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
614 bmp
= m_disabled_close_bmp
;
616 bmp
= m_active_close_bmp
;
618 case wxAUI_BUTTON_LEFT
:
619 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
620 bmp
= m_disabled_left_bmp
;
622 bmp
= m_active_left_bmp
;
624 case wxAUI_BUTTON_RIGHT
:
625 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
626 bmp
= m_disabled_right_bmp
;
628 bmp
= m_active_right_bmp
;
630 case wxAUI_BUTTON_WINDOWLIST
:
631 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
632 bmp
= m_disabled_windowlist_bmp
;
634 bmp
= m_active_windowlist_bmp
;
644 if (orientation
== wxLEFT
)
646 rect
.SetX(in_rect
.x
);
647 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
648 rect
.SetWidth(bmp
.GetWidth());
649 rect
.SetHeight(bmp
.GetHeight());
653 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
654 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
655 bmp
.GetWidth(), bmp
.GetHeight());
658 IndentPressedBitmap(&rect
, button_state
);
659 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);
665 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
,
666 const wxAuiNotebookPageArray
& pages
,
671 size_t i
, count
= pages
.GetCount();
672 for (i
= 0; i
< count
; ++i
)
674 const wxAuiNotebookPage
& page
= pages
.Item(i
);
675 wxString caption
= page
.caption
;
677 // if there is no caption, make it a space. This will prevent
678 // an assert in the menu code.
679 if (caption
.IsEmpty())
682 menuPopup
.AppendCheckItem(1000+i
, caption
);
685 if (active_idx
!= -1)
687 menuPopup
.Check(1000+active_idx
, true);
690 // find out where to put the popup menu of window items
691 wxPoint pt
= ::wxGetMousePosition();
692 pt
= wnd
->ScreenToClient(pt
);
694 // find out the screen coordinate at the bottom of the tab ctrl
695 wxRect cli_rect
= wnd
->GetClientRect();
696 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
698 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
699 wnd
->PushEventHandler(cc
);
700 wnd
->PopupMenu(&menuPopup
, pt
);
701 int command
= cc
->GetCommandId();
702 wnd
->PopEventHandler(true);
710 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
711 const wxAuiNotebookPageArray
& pages
,
712 const wxSize
& required_bmp_size
)
715 dc
.SetFont(m_measuring_font
);
717 // sometimes a standard bitmap size needs to be enforced, especially
718 // if some tabs have bitmaps and others don't. This is important because
719 // it prevents the tab control from resizing when tabs are added.
720 wxBitmap measure_bmp
;
721 if (required_bmp_size
.IsFullySpecified())
723 measure_bmp
.Create(required_bmp_size
.x
,
724 required_bmp_size
.y
);
729 size_t i
, page_count
= pages
.GetCount();
730 for (i
= 0; i
< page_count
; ++i
)
732 wxAuiNotebookPage
& page
= pages
.Item(i
);
735 if (measure_bmp
.IsOk())
740 // we don't use the caption text because we don't
741 // want tab heights to be different in the case
742 // of a very short piece of text on one tab and a very
743 // tall piece of text on another tab
745 wxSize s
= GetTabSize(dc
,
750 wxAUI_BUTTON_STATE_HIDDEN
,
753 max_y
= wxMax(max_y
, s
.y
);
759 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
)
761 m_normal_font
= font
;
764 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
)
766 m_selected_font
= font
;
769 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
)
771 m_measuring_font
= font
;
775 // -- wxAuiSimpleTabArt class implementation --
777 wxAuiSimpleTabArt::wxAuiSimpleTabArt()
779 m_normal_font
= *wxNORMAL_FONT
;
780 m_selected_font
= *wxNORMAL_FONT
;
781 m_selected_font
.SetWeight(wxBOLD
);
782 m_measuring_font
= m_selected_font
;
785 m_fixed_tab_width
= 100;
787 wxColour base_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
789 wxColour background_colour
= base_colour
;
790 wxColour normaltab_colour
= base_colour
;
791 wxColour selectedtab_colour
= *wxWHITE
;
793 m_bkbrush
= wxBrush(background_colour
);
794 m_normal_bkbrush
= wxBrush(normaltab_colour
);
795 m_normal_bkpen
= wxPen(normaltab_colour
);
796 m_selected_bkbrush
= wxBrush(selectedtab_colour
);
797 m_selected_bkpen
= wxPen(selectedtab_colour
);
799 m_active_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
);
800 m_disabled_close_bmp
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128));
802 m_active_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
);
803 m_disabled_left_bmp
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128));
805 m_active_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
);
806 m_disabled_right_bmp
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128));
808 m_active_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
);
809 m_disabled_windowlist_bmp
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128));
813 wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
817 wxAuiTabArt
* wxAuiSimpleTabArt::Clone()
819 return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
);
823 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
)
828 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
,
831 m_fixed_tab_width
= 100;
833 int tot_width
= (int)tab_ctrl_size
.x
- GetIndentSize() - 4;
835 if (m_flags
& wxAUI_NB_CLOSE_BUTTON
)
836 tot_width
-= m_active_close_bmp
.GetWidth();
837 if (m_flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
838 tot_width
-= m_active_windowlist_bmp
.GetWidth();
842 m_fixed_tab_width
= tot_width
/(int)tab_count
;
846 if (m_fixed_tab_width
< 100)
847 m_fixed_tab_width
= 100;
849 if (m_fixed_tab_width
> tot_width
/2)
850 m_fixed_tab_width
= tot_width
/2;
852 if (m_fixed_tab_width
> 220)
853 m_fixed_tab_width
= 220;
856 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
,
857 wxWindow
* WXUNUSED(wnd
),
861 dc
.SetBrush(m_bkbrush
);
862 dc
.SetPen(*wxTRANSPARENT_PEN
);
863 dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2);
866 dc
.SetPen(*wxGREY_PEN
);
867 dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1);
871 // DrawTab() draws an individual tab.
874 // in_rect - rectangle the tab should be confined to
875 // caption - tab's caption
876 // active - whether or not the tab is active
877 // out_rect - actual output rectangle
878 // x_extent - the advance x; where the next tab should start
880 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
,
882 const wxAuiNotebookPage
& page
,
883 const wxRect
& in_rect
,
884 int close_button_state
,
885 wxRect
* out_tab_rect
,
886 wxRect
* out_button_rect
,
889 wxCoord normal_textx
, normal_texty
;
890 wxCoord selected_textx
, selected_texty
;
891 wxCoord textx
, texty
;
893 // if the caption is empty, measure some temporary text
894 wxString caption
= page
.caption
;
898 dc
.SetFont(m_selected_font
);
899 dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
);
901 dc
.SetFont(m_normal_font
);
902 dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
);
904 // figure out the size of the tab
905 wxSize tab_size
= GetTabSize(dc
,
913 wxCoord tab_height
= tab_size
.y
;
914 wxCoord tab_width
= tab_size
.x
;
915 wxCoord tab_x
= in_rect
.x
;
916 wxCoord tab_y
= in_rect
.y
+ in_rect
.height
- tab_height
;
918 caption
= page
.caption
;
920 // select pen, brush and font for the tab to be drawn
924 dc
.SetPen(m_selected_bkpen
);
925 dc
.SetBrush(m_selected_bkbrush
);
926 dc
.SetFont(m_selected_font
);
927 textx
= selected_textx
;
928 texty
= selected_texty
;
932 dc
.SetPen(m_normal_bkpen
);
933 dc
.SetBrush(m_normal_bkbrush
);
934 dc
.SetFont(m_normal_font
);
935 textx
= normal_textx
;
936 texty
= normal_texty
;
944 points
[0].y
= tab_y
+ tab_height
- 1;
945 points
[1].x
= tab_x
+ tab_height
- 3;
946 points
[1].y
= tab_y
+ 2;
947 points
[2].x
= tab_x
+ tab_height
+ 3;
949 points
[3].x
= tab_x
+ tab_width
- 2;
951 points
[4].x
= tab_x
+ tab_width
;
952 points
[4].y
= tab_y
+ 2;
953 points
[5].x
= tab_x
+ tab_width
;
954 points
[5].y
= tab_y
+ tab_height
- 1;
955 points
[6] = points
[0];
957 dc
.SetClippingRegion(in_rect
);
959 dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
);
961 dc
.SetPen(*wxGREY_PEN
);
963 //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
964 dc
.DrawLines(WXSIZEOF(points
), points
);
969 int close_button_width
= 0;
970 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
972 close_button_width
= m_active_close_bmp
.GetWidth();
973 text_offset
= tab_x
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2);
977 text_offset
= tab_x
+ (tab_height
/3) + (tab_width
/2) - (textx
/2);
980 // set minimum text offset
981 if (text_offset
< tab_x
+ tab_height
)
982 text_offset
= tab_x
+ tab_height
;
984 // chop text if necessary
985 wxString draw_text
= wxAuiChopText(dc
,
987 tab_width
- (text_offset
-tab_x
) - close_button_width
);
990 dc
.DrawText(draw_text
,
992 (tab_y
+ tab_height
)/2 - (texty
/2) + 1);
995 // draw close button if necessary
996 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1000 bmp
= m_active_close_bmp
;
1002 bmp
= m_disabled_close_bmp
;
1004 wxRect
rect(tab_x
+ tab_width
- close_button_width
- 1,
1005 tab_y
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1,
1008 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
);
1010 *out_button_rect
= rect
;
1014 *out_tab_rect
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
);
1016 dc
.DestroyClippingRegion();
1019 int wxAuiSimpleTabArt::GetIndentSize()
1024 wxSize
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
,
1025 wxWindow
* WXUNUSED(wnd
),
1026 const wxString
& caption
,
1027 const wxBitmap
& WXUNUSED(bitmap
),
1028 bool WXUNUSED(active
),
1029 int close_button_state
,
1032 wxCoord measured_textx
, measured_texty
;
1034 dc
.SetFont(m_measuring_font
);
1035 dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
);
1037 wxCoord tab_height
= measured_texty
+ 4;
1038 wxCoord tab_width
= measured_textx
+ tab_height
+ 5;
1040 if (close_button_state
!= wxAUI_BUTTON_STATE_HIDDEN
)
1041 tab_width
+= m_active_close_bmp
.GetWidth();
1043 if (m_flags
& wxAUI_NB_TAB_FIXED_WIDTH
)
1045 tab_width
= m_fixed_tab_width
;
1048 *x_extent
= tab_width
- (tab_height
/2) - 1;
1050 return wxSize(tab_width
, tab_height
);
1054 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
,
1055 wxWindow
* WXUNUSED(wnd
),
1056 const wxRect
& in_rect
,
1067 case wxAUI_BUTTON_CLOSE
:
1068 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1069 bmp
= m_disabled_close_bmp
;
1071 bmp
= m_active_close_bmp
;
1073 case wxAUI_BUTTON_LEFT
:
1074 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1075 bmp
= m_disabled_left_bmp
;
1077 bmp
= m_active_left_bmp
;
1079 case wxAUI_BUTTON_RIGHT
:
1080 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1081 bmp
= m_disabled_right_bmp
;
1083 bmp
= m_active_right_bmp
;
1085 case wxAUI_BUTTON_WINDOWLIST
:
1086 if (button_state
& wxAUI_BUTTON_STATE_DISABLED
)
1087 bmp
= m_disabled_windowlist_bmp
;
1089 bmp
= m_active_windowlist_bmp
;
1098 if (orientation
== wxLEFT
)
1100 rect
.SetX(in_rect
.x
);
1101 rect
.SetY(((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2));
1102 rect
.SetWidth(bmp
.GetWidth());
1103 rect
.SetHeight(bmp
.GetHeight());
1107 rect
= wxRect(in_rect
.x
+ in_rect
.width
- bmp
.GetWidth(),
1108 ((in_rect
.y
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2),
1109 bmp
.GetWidth(), bmp
.GetHeight());
1113 DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
);
1119 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
,
1120 const wxAuiNotebookPageArray
& pages
,
1125 size_t i
, count
= pages
.GetCount();
1126 for (i
= 0; i
< count
; ++i
)
1128 const wxAuiNotebookPage
& page
= pages
.Item(i
);
1129 menuPopup
.AppendCheckItem(1000+i
, page
.caption
);
1132 if (active_idx
!= -1)
1134 menuPopup
.Check(1000+active_idx
, true);
1137 // find out where to put the popup menu of window
1138 // items. Subtract 100 for now to center the menu
1139 // a bit, until a better mechanism can be implemented
1140 wxPoint pt
= ::wxGetMousePosition();
1141 pt
= wnd
->ScreenToClient(pt
);
1147 // find out the screen coordinate at the bottom of the tab ctrl
1148 wxRect cli_rect
= wnd
->GetClientRect();
1149 pt
.y
= cli_rect
.y
+ cli_rect
.height
;
1151 wxAuiCommandCapture
* cc
= new wxAuiCommandCapture
;
1152 wnd
->PushEventHandler(cc
);
1153 wnd
->PopupMenu(&menuPopup
, pt
);
1154 int command
= cc
->GetCommandId();
1155 wnd
->PopEventHandler(true);
1157 if (command
>= 1000)
1158 return command
-1000;
1163 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
,
1164 const wxAuiNotebookPageArray
& WXUNUSED(pages
),
1165 const wxSize
& WXUNUSED(required_bmp_size
))
1168 dc
.SetFont(m_measuring_font
);
1170 wxSize s
= GetTabSize(dc
,
1175 wxAUI_BUTTON_STATE_HIDDEN
,
1180 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
)
1182 m_normal_font
= font
;
1185 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
)
1187 m_selected_font
= font
;
1190 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
)
1192 m_measuring_font
= font
;
1198 // -- wxAuiTabContainer class implementation --
1201 // wxAuiTabContainer is a class which contains information about each
1202 // tab. It also can render an entire tab control to a specified DC.
1203 // It's not a window class itself, because this code will be used by
1204 // the wxFrameMananger, where it is disadvantageous to have separate
1205 // windows for each tab control in the case of "docked tabs"
1207 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
1208 // which can be used as a tab control in the normal sense.
1211 wxAuiTabContainer::wxAuiTabContainer()
1215 m_art
= new wxAuiDefaultTabArt
;
1217 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1218 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1219 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1220 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1223 wxAuiTabContainer::~wxAuiTabContainer()
1228 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
)
1235 m_art
->SetFlags(m_flags
);
1239 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const
1244 void wxAuiTabContainer::SetFlags(unsigned int flags
)
1248 // check for new close button settings
1249 RemoveButton(wxAUI_BUTTON_LEFT
);
1250 RemoveButton(wxAUI_BUTTON_RIGHT
);
1251 RemoveButton(wxAUI_BUTTON_WINDOWLIST
);
1252 RemoveButton(wxAUI_BUTTON_CLOSE
);
1255 if (flags
& wxAUI_NB_SCROLL_BUTTONS
)
1257 AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
);
1258 AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
);
1261 if (flags
& wxAUI_NB_WINDOWLIST_BUTTON
)
1263 AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
);
1266 if (flags
& wxAUI_NB_CLOSE_BUTTON
)
1268 AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
);
1273 m_art
->SetFlags(m_flags
);
1277 unsigned int wxAuiTabContainer::GetFlags() const
1283 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
)
1285 m_art
->SetNormalFont(font
);
1288 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
)
1290 m_art
->SetSelectedFont(font
);
1293 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
)
1295 m_art
->SetMeasuringFont(font
);
1298 void wxAuiTabContainer::SetRect(const wxRect
& rect
)
1304 m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount());
1308 bool wxAuiTabContainer::AddPage(wxWindow
* page
,
1309 const wxAuiNotebookPage
& info
)
1311 wxAuiNotebookPage page_info
;
1313 page_info
.window
= page
;
1315 m_pages
.Add(page_info
);
1317 // let the art provider know how many pages we have
1320 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1326 bool wxAuiTabContainer::InsertPage(wxWindow
* page
,
1327 const wxAuiNotebookPage
& info
,
1330 wxAuiNotebookPage page_info
;
1332 page_info
.window
= page
;
1334 if (idx
>= m_pages
.GetCount())
1335 m_pages
.Add(page_info
);
1337 m_pages
.Insert(page_info
, idx
);
1339 // let the art provider know how many pages we have
1342 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1348 bool wxAuiTabContainer::MovePage(wxWindow
* page
,
1351 int idx
= GetIdxFromWindow(page
);
1355 // get page entry, make a copy of it
1356 wxAuiNotebookPage p
= GetPage(idx
);
1358 // remove old page entry
1361 // insert page where it should be
1362 InsertPage(page
, p
, new_idx
);
1367 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
)
1369 size_t i
, page_count
= m_pages
.GetCount();
1370 for (i
= 0; i
< page_count
; ++i
)
1372 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1373 if (page
.window
== wnd
)
1375 m_pages
.RemoveAt(i
);
1377 // let the art provider know how many pages we have
1380 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount());
1390 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
)
1394 size_t i
, page_count
= m_pages
.GetCount();
1395 for (i
= 0; i
< page_count
; ++i
)
1397 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1398 if (page
.window
== wnd
)
1405 page
.active
= false;
1412 void wxAuiTabContainer::SetNoneActive()
1414 size_t i
, page_count
= m_pages
.GetCount();
1415 for (i
= 0; i
< page_count
; ++i
)
1417 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1418 page
.active
= false;
1422 bool wxAuiTabContainer::SetActivePage(size_t page
)
1424 if (page
>= m_pages
.GetCount())
1427 return SetActivePage(m_pages
.Item(page
).window
);
1430 int wxAuiTabContainer::GetActivePage() const
1432 size_t i
, page_count
= m_pages
.GetCount();
1433 for (i
= 0; i
< page_count
; ++i
)
1435 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1443 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const
1445 if (idx
>= m_pages
.GetCount())
1448 return m_pages
[idx
].window
;
1451 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const
1453 const size_t page_count
= m_pages
.GetCount();
1454 for ( size_t i
= 0; i
< page_count
; ++i
)
1456 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1457 if (page
.window
== wnd
)
1463 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
)
1465 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1467 return m_pages
[idx
];
1470 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const
1472 wxASSERT_MSG(idx
< m_pages
.GetCount(), wxT("Invalid Page index"));
1474 return m_pages
[idx
];
1477 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages()
1482 size_t wxAuiTabContainer::GetPageCount() const
1484 return m_pages
.GetCount();
1487 void wxAuiTabContainer::AddButton(int id
,
1489 const wxBitmap
& normal_bitmap
,
1490 const wxBitmap
& disabled_bitmap
)
1492 wxAuiTabContainerButton button
;
1494 button
.bitmap
= normal_bitmap
;
1495 button
.dis_bitmap
= disabled_bitmap
;
1496 button
.location
= location
;
1497 button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1499 m_buttons
.Add(button
);
1502 void wxAuiTabContainer::RemoveButton(int id
)
1504 size_t i
, button_count
= m_buttons
.GetCount();
1506 for (i
= 0; i
< button_count
; ++i
)
1508 if (m_buttons
.Item(i
).id
== id
)
1510 m_buttons
.RemoveAt(i
);
1518 size_t wxAuiTabContainer::GetTabOffset() const
1520 return m_tab_offset
;
1523 void wxAuiTabContainer::SetTabOffset(size_t offset
)
1525 m_tab_offset
= offset
;
1531 // Render() renders the tab catalog to the specified DC
1532 // It is a virtual function and can be overridden to
1533 // provide custom drawing capabilities
1534 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
)
1536 if (!raw_dc
|| !raw_dc
->IsOk())
1542 size_t page_count
= m_pages
.GetCount();
1543 size_t button_count
= m_buttons
.GetCount();
1545 // create off-screen bitmap
1546 bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight());
1547 dc
.SelectObject(bmp
);
1552 // find out if size of tabs is larger than can be
1553 // afforded on screen
1554 int total_width
= 0;
1555 int visible_width
= 0;
1556 for (i
= 0; i
< page_count
; ++i
)
1558 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1560 // determine if a close button is on this tab
1561 bool close_button
= false;
1562 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1563 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1565 close_button
= true;
1570 wxSize size
= m_art
->GetTabSize(dc
,
1576 wxAUI_BUTTON_STATE_NORMAL
:
1577 wxAUI_BUTTON_STATE_HIDDEN
,
1580 if (i
+1 < page_count
)
1581 total_width
+= x_extent
;
1583 total_width
+= size
.x
;
1585 if (i
>= m_tab_offset
)
1587 if (i
+1 < page_count
)
1588 visible_width
+= x_extent
;
1590 visible_width
+= size
.x
;
1594 if (total_width
> m_rect
.GetWidth() || m_tab_offset
!= 0)
1596 // show left/right buttons
1597 for (i
= 0; i
< button_count
; ++i
)
1599 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1600 if (button
.id
== wxAUI_BUTTON_LEFT
||
1601 button
.id
== wxAUI_BUTTON_RIGHT
)
1603 button
.cur_state
&= ~wxAUI_BUTTON_STATE_HIDDEN
;
1609 // hide left/right buttons
1610 for (i
= 0; i
< button_count
; ++i
)
1612 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1613 if (button
.id
== wxAUI_BUTTON_LEFT
||
1614 button
.id
== wxAUI_BUTTON_RIGHT
)
1616 button
.cur_state
|= wxAUI_BUTTON_STATE_HIDDEN
;
1621 // determine whether left button should be enabled
1622 for (i
= 0; i
< button_count
; ++i
)
1624 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1625 if (button
.id
== wxAUI_BUTTON_LEFT
)
1627 if (m_tab_offset
== 0)
1628 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1630 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1632 if (button
.id
== wxAUI_BUTTON_RIGHT
)
1634 if (visible_width
< m_rect
.GetWidth() - ((int)button_count
*16))
1635 button
.cur_state
|= wxAUI_BUTTON_STATE_DISABLED
;
1637 button
.cur_state
&= ~wxAUI_BUTTON_STATE_DISABLED
;
1644 m_art
->DrawBackground(dc
, wnd
, m_rect
);
1647 int left_buttons_width
= 0;
1648 int right_buttons_width
= 0;
1652 // draw the buttons on the right side
1653 offset
= m_rect
.x
+ m_rect
.width
;
1654 for (i
= 0; i
< button_count
; ++i
)
1656 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1658 if (button
.location
!= wxRIGHT
)
1660 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1663 wxRect button_rect
= m_rect
;
1664 button_rect
.SetY(1);
1665 button_rect
.SetWidth(offset
);
1667 m_art
->DrawButton(dc
,
1675 offset
-= button
.rect
.GetWidth();
1676 right_buttons_width
+= button
.rect
.GetWidth();
1683 // draw the buttons on the left side
1685 for (i
= 0; i
< button_count
; ++i
)
1687 wxAuiTabContainerButton
& button
= m_buttons
.Item(button_count
- i
- 1);
1689 if (button
.location
!= wxLEFT
)
1691 if (button
.cur_state
& wxAUI_BUTTON_STATE_HIDDEN
)
1694 wxRect
button_rect(offset
, 1, 1000, m_rect
.height
);
1696 m_art
->DrawButton(dc
,
1704 offset
+= button
.rect
.GetWidth();
1705 left_buttons_width
+= button
.rect
.GetWidth();
1708 offset
= left_buttons_width
;
1711 offset
+= m_art
->GetIndentSize();
1714 // prepare the tab-close-button array
1715 // make sure tab button entries which aren't used are marked as hidden
1716 for (i
= page_count
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1717 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1719 // make sure there are enough tab button entries to accommodate all tabs
1720 while (m_tab_close_buttons
.GetCount() < page_count
)
1722 wxAuiTabContainerButton tempbtn
;
1723 tempbtn
.id
= wxAUI_BUTTON_CLOSE
;
1724 tempbtn
.location
= wxCENTER
;
1725 tempbtn
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1726 m_tab_close_buttons
.Add(tempbtn
);
1730 // buttons before the tab offset must be set to hidden
1731 for (i
= 0; i
< m_tab_offset
; ++i
)
1733 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1739 size_t active
= 999;
1740 int active_offset
= 0;
1744 wxRect rect
= m_rect
;
1746 rect
.height
= m_rect
.height
;
1748 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1750 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1751 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(i
);
1753 // determine if a close button is on this tab
1754 if ((m_flags
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 ||
1755 ((m_flags
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
))
1757 if (tab_button
.cur_state
== wxAUI_BUTTON_STATE_HIDDEN
)
1759 tab_button
.id
= wxAUI_BUTTON_CLOSE
;
1760 tab_button
.cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
1761 tab_button
.location
= wxCENTER
;
1766 tab_button
.cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1770 rect
.width
= m_rect
.width
- right_buttons_width
- offset
- 2;
1772 if (rect
.width
<= 0)
1779 tab_button
.cur_state
,
1787 active_offset
= offset
;
1795 // make sure to deactivate buttons which are off the screen to the right
1796 for (++i
; i
< m_tab_close_buttons
.GetCount(); ++i
)
1798 m_tab_close_buttons
.Item(i
).cur_state
= wxAUI_BUTTON_STATE_HIDDEN
;
1802 // draw the active tab again so it stands in the foreground
1803 if (active
>= m_tab_offset
&& active
< m_pages
.GetCount())
1805 wxAuiNotebookPage
& page
= m_pages
.Item(active
);
1807 wxAuiTabContainerButton
& tab_button
= m_tab_close_buttons
.Item(active
);
1809 rect
.x
= active_offset
;
1814 tab_button
.cur_state
,
1821 raw_dc
->Blit(m_rect
.x
, m_rect
.y
,
1822 m_rect
.GetWidth(), m_rect
.GetHeight(),
1827 // TabHitTest() tests if a tab was hit, passing the window pointer
1828 // back if that condition was fulfilled. The function returns
1829 // true if a tab was hit, otherwise false
1830 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const
1832 if (!m_rect
.Contains(x
,y
))
1835 wxAuiTabContainerButton
* btn
= NULL
;
1836 if (ButtonHitTest(x
, y
, &btn
))
1838 if (m_buttons
.Index(*btn
) != wxNOT_FOUND
)
1842 size_t i
, page_count
= m_pages
.GetCount();
1844 for (i
= m_tab_offset
; i
< page_count
; ++i
)
1846 wxAuiNotebookPage
& page
= m_pages
.Item(i
);
1847 if (page
.rect
.Contains(x
,y
))
1858 // ButtonHitTest() tests if a button was hit. The function returns
1859 // true if a button was hit, otherwise false
1860 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
,
1861 wxAuiTabContainerButton
** hit
) const
1863 if (!m_rect
.Contains(x
,y
))
1866 size_t i
, button_count
;
1869 button_count
= m_buttons
.GetCount();
1870 for (i
= 0; i
< button_count
; ++i
)
1872 wxAuiTabContainerButton
& button
= m_buttons
.Item(i
);
1873 if (button
.rect
.Contains(x
,y
) &&
1874 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1875 wxAUI_BUTTON_STATE_DISABLED
)))
1883 button_count
= m_tab_close_buttons
.GetCount();
1884 for (i
= 0; i
< button_count
; ++i
)
1886 wxAuiTabContainerButton
& button
= m_tab_close_buttons
.Item(i
);
1887 if (button
.rect
.Contains(x
,y
) &&
1888 !(button
.cur_state
& (wxAUI_BUTTON_STATE_HIDDEN
|
1889 wxAUI_BUTTON_STATE_DISABLED
)))
1902 // the utility function ShowWnd() is the same as show,
1903 // except it handles wxAuiMDIChildFrame windows as well,
1904 // as the Show() method on this class is "unplugged"
1905 static void ShowWnd(wxWindow
* wnd
, bool show
)
1907 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
1909 wxAuiMDIChildFrame
* cf
= (wxAuiMDIChildFrame
*)wnd
;
1919 // DoShowHide() this function shows the active window, then
1920 // hides all of the other windows (in that order)
1921 void wxAuiTabContainer::DoShowHide()
1923 wxAuiNotebookPageArray
& pages
= GetPages();
1924 size_t i
, page_count
= pages
.GetCount();
1926 // show new active page first
1927 for (i
= 0; i
< page_count
; ++i
)
1929 wxAuiNotebookPage
& page
= pages
.Item(i
);
1932 ShowWnd(page
.window
, true);
1937 // hide all other pages
1938 for (i
= 0; i
< page_count
; ++i
)
1940 wxAuiNotebookPage
& page
= pages
.Item(i
);
1942 ShowWnd(page
.window
, false);
1951 // -- wxAuiTabCtrl class implementation --
1955 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
)
1956 EVT_PAINT(wxAuiTabCtrl::OnPaint
)
1957 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
)
1958 EVT_SIZE(wxAuiTabCtrl::OnSize
)
1959 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
)
1960 EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
)
1961 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
)
1962 EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
)
1963 EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
)
1964 EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
)
1965 EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
)
1966 EVT_MOTION(wxAuiTabCtrl::OnMotion
)
1967 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
)
1968 EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
)
1972 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
,
1976 long style
) : wxControl(parent
, id
, pos
, size
, style
)
1978 m_click_pt
= wxDefaultPosition
;
1979 m_is_dragging
= false;
1980 m_hover_button
= NULL
;
1981 m_pressed_button
= NULL
;
1984 wxAuiTabCtrl::~wxAuiTabCtrl()
1988 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&)
1992 dc
.SetFont(GetFont());
1994 if (GetPageCount() > 0)
1998 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
2002 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
)
2004 wxSize s
= evt
.GetSize();
2005 wxRect
r(0, 0, s
.GetWidth(), s
.GetHeight());
2009 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
)
2012 m_click_pt
= wxDefaultPosition
;
2013 m_is_dragging
= false;
2015 m_pressed_button
= NULL
;
2019 if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2021 int new_selection
= GetIdxFromWindow(wnd
);
2023 // wxAuiNotebooks always want to receive this event
2024 // even if the tab is already active, because they may
2025 // have multiple tab controls
2026 if (new_selection
!= GetActivePage() ||
2027 GetParent()->IsKindOf(CLASSINFO(wxAuiNotebook
)))
2029 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2030 e
.SetSelection(new_selection
);
2031 e
.SetOldSelection(GetActivePage());
2032 e
.SetEventObject(this);
2033 GetEventHandler()->ProcessEvent(e
);
2036 m_click_pt
.x
= evt
.m_x
;
2037 m_click_pt
.y
= evt
.m_y
;
2043 m_pressed_button
= m_hover_button
;
2044 m_pressed_button
->cur_state
= wxAUI_BUTTON_STATE_PRESSED
;
2050 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
)
2052 if (GetCapture() == this)
2057 m_is_dragging
= false;
2059 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
);
2060 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2061 evt
.SetOldSelection(evt
.GetSelection());
2062 evt
.SetEventObject(this);
2063 GetEventHandler()->ProcessEvent(evt
);
2068 if (m_pressed_button
)
2070 // make sure we're still clicking the button
2071 wxAuiTabContainerButton
* button
= NULL
;
2072 if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
))
2075 if (button
!= m_pressed_button
)
2077 m_pressed_button
= NULL
;
2084 if (!(m_pressed_button
->cur_state
& wxAUI_BUTTON_STATE_DISABLED
))
2086 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
);
2087 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2088 evt
.SetInt(m_pressed_button
->id
);
2089 evt
.SetEventObject(this);
2090 GetEventHandler()->ProcessEvent(evt
);
2093 m_pressed_button
= NULL
;
2096 m_click_pt
= wxDefaultPosition
;
2097 m_is_dragging
= false;
2101 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
)
2103 wxWindow
* wnd
= NULL
;
2104 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2107 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
2108 e
.SetEventObject(this);
2109 e
.SetSelection(GetIdxFromWindow(wnd
));
2110 GetEventHandler()->ProcessEvent(e
);
2113 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
)
2115 wxWindow
* wnd
= NULL
;
2116 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2119 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
2120 e
.SetEventObject(this);
2121 e
.SetSelection(GetIdxFromWindow(wnd
));
2122 GetEventHandler()->ProcessEvent(e
);
2125 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
)
2127 wxWindow
* wnd
= NULL
;
2128 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2131 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
2132 e
.SetEventObject(this);
2133 e
.SetSelection(GetIdxFromWindow(wnd
));
2134 GetEventHandler()->ProcessEvent(e
);
2137 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
)
2139 wxWindow
* wnd
= NULL
;
2140 if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
))
2143 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
2144 e
.SetEventObject(this);
2145 e
.SetSelection(GetIdxFromWindow(wnd
));
2146 GetEventHandler()->ProcessEvent(e
);
2149 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
)
2151 wxPoint pos
= evt
.GetPosition();
2153 // check if the mouse is hovering above a button
2154 wxAuiTabContainerButton
* button
;
2155 if (ButtonHitTest(pos
.x
, pos
.y
, &button
))
2157 if (m_hover_button
&& button
!= m_hover_button
)
2159 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2160 m_hover_button
= NULL
;
2165 if (button
->cur_state
!= wxAUI_BUTTON_STATE_HOVER
)
2167 button
->cur_state
= wxAUI_BUTTON_STATE_HOVER
;
2170 m_hover_button
= button
;
2178 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2179 m_hover_button
= NULL
;
2186 if (!evt
.LeftIsDown() || m_click_pt
== wxDefaultPosition
)
2191 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
);
2192 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2193 evt
.SetOldSelection(evt
.GetSelection());
2194 evt
.SetEventObject(this);
2195 GetEventHandler()->ProcessEvent(evt
);
2200 int drag_x_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
);
2201 int drag_y_threshold
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
);
2203 if (abs(pos
.x
- m_click_pt
.x
) > drag_x_threshold
||
2204 abs(pos
.y
- m_click_pt
.y
) > drag_y_threshold
)
2206 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
);
2207 evt
.SetSelection(GetIdxFromWindow(m_click_tab
));
2208 evt
.SetOldSelection(evt
.GetSelection());
2209 evt
.SetEventObject(this);
2210 GetEventHandler()->ProcessEvent(evt
);
2212 m_is_dragging
= true;
2216 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
))
2220 m_hover_button
->cur_state
= wxAUI_BUTTON_STATE_NORMAL
;
2221 m_hover_button
= NULL
;
2227 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
)
2229 int button
= event
.GetInt();
2231 if (button
== wxAUI_BUTTON_LEFT
|| button
== wxAUI_BUTTON_RIGHT
)
2233 if (button
== wxAUI_BUTTON_LEFT
)
2235 if (GetTabOffset() > 0)
2237 SetTabOffset(GetTabOffset()-1);
2244 SetTabOffset(GetTabOffset()+1);
2249 else if (button
== wxAUI_BUTTON_WINDOWLIST
)
2251 int idx
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage());
2255 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2256 e
.SetSelection(idx
);
2257 e
.SetOldSelection(GetActivePage());
2258 e
.SetEventObject(this);
2259 GetEventHandler()->ProcessEvent(e
);
2268 // wxTabFrame is an interesting case. It's important that all child pages
2269 // of the multi-notebook control are all actually children of that control
2270 // (and not grandchildren). wxTabFrame facilitates this. There is one
2271 // instance of wxTabFrame for each tab control inside the multi-notebook.
2272 // It's important to know that wxTabFrame is not a real window, but it merely
2273 // used to capture the dimensions/positioning of the internal tab control and
2274 // it's managed page windows
2276 class wxTabFrame
: public wxWindow
2283 m_rect
= wxRect(0,0,200,200);
2284 m_tab_ctrl_height
= 20;
2292 void SetTabCtrlHeight(int h
)
2294 m_tab_ctrl_height
= h
;
2298 void DoSetSize(int x
, int y
,
2299 int width
, int height
,
2300 int WXUNUSED(sizeFlags
= wxSIZE_AUTO
))
2302 m_rect
= wxRect(x
, y
, width
, height
);
2306 void DoGetClientSize(int* x
, int* y
) const
2313 bool Show( bool WXUNUSED(show
= true) ) { return false; }
2320 m_tab_rect
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2321 m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
);
2322 m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
));
2326 wxAuiNotebookPageArray
& pages
= m_tabs
->GetPages();
2327 size_t i
, page_count
= pages
.GetCount();
2329 for (i
= 0; i
< page_count
; ++i
)
2331 wxAuiNotebookPage
& page
= pages
.Item(i
);
2332 page
.window
->SetSize(m_rect
.x
, m_rect
.y
+ m_tab_ctrl_height
,
2333 m_rect
.width
, m_rect
.height
- m_tab_ctrl_height
);
2335 if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2337 wxAuiMDIChildFrame
* wnd
= (wxAuiMDIChildFrame
*)page
.window
;
2338 wnd
->ApplyMDIChildFrameRect();
2344 void DoGetSize(int* x
, int* y
) const
2347 *x
= m_rect
.GetWidth();
2349 *y
= m_rect
.GetHeight();
2360 wxAuiTabCtrl
* m_tabs
;
2361 int m_tab_ctrl_height
;
2365 const int wxAuiBaseTabCtrlId
= 5380;
2368 // -- wxAuiNotebook class implementation --
2370 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
)
2371 EVT_SIZE(wxAuiNotebook::OnSize
)
2372 EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
)
2373 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2374 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
,
2375 wxAuiNotebook::OnTabClicked
)
2376 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2377 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
,
2378 wxAuiNotebook::OnTabBeginDrag
)
2379 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2380 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
,
2381 wxAuiNotebook::OnTabEndDrag
)
2382 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2383 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
,
2384 wxAuiNotebook::OnTabDragMotion
)
2385 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2386 wxEVT_COMMAND_AUINOTEBOOK_BUTTON
,
2387 wxAuiNotebook::OnTabButton
)
2388 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2389 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
,
2390 wxAuiNotebook::OnTabMiddleDown
)
2391 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2392 wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
,
2393 wxAuiNotebook::OnTabMiddleUp
)
2394 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2395 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
,
2396 wxAuiNotebook::OnTabRightDown
)
2397 EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500,
2398 wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
,
2399 wxAuiNotebook::OnTabRightUp
)
2402 wxAuiNotebook::wxAuiNotebook()
2405 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2407 m_tab_ctrl_height
= 20;
2408 m_requested_bmp_size
= wxDefaultSize
;
2409 m_requested_tabctrl_height
= -1;
2412 wxAuiNotebook::wxAuiNotebook(wxWindow
*parent
,
2416 long style
) : wxControl(parent
, id
, pos
, size
, style
)
2419 m_requested_bmp_size
= wxDefaultSize
;
2420 m_requested_tabctrl_height
= -1;
2421 InitNotebook(style
);
2424 bool wxAuiNotebook::Create(wxWindow
* parent
,
2430 if (!wxControl::Create(parent
, id
, pos
, size
, style
))
2433 InitNotebook(style
);
2438 // InitNotebook() contains common initialization
2439 // code called by all constructors
2440 void wxAuiNotebook::InitNotebook(long style
)
2443 m_tab_id_counter
= wxAuiBaseTabCtrlId
;
2445 m_flags
= (unsigned int)style
;
2446 m_tab_ctrl_height
= 20;
2448 m_normal_font
= *wxNORMAL_FONT
;
2449 m_selected_font
= *wxNORMAL_FONT
;
2450 m_selected_font
.SetWeight(wxBOLD
);
2452 SetArtProvider(new wxAuiDefaultTabArt
);
2454 m_dummy_wnd
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0));
2455 m_dummy_wnd
->SetSize(200, 200);
2456 m_dummy_wnd
->Show(false);
2458 m_mgr
.SetManagedWindow(this);
2459 m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
);
2460 m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint
2462 m_mgr
.AddPane(m_dummy_wnd
,
2463 wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false));
2468 wxAuiNotebook::~wxAuiNotebook()
2473 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
)
2475 m_tabs
.SetArtProvider(art
);
2477 UpdateTabCtrlHeight();
2480 // SetTabCtrlHeight() is the highest-level override of the
2481 // tab height. A call to this function effectively enforces a
2482 // specified tab ctrl height, overriding all other considerations,
2483 // such as text or bitmap height. It overrides any call to
2484 // SetUniformBitmapSize(). Specifying a height of -1 reverts
2485 // any previous call and returns to the default behavior
2487 void wxAuiNotebook::SetTabCtrlHeight(int height
)
2489 m_requested_tabctrl_height
= height
;
2491 // if window is already initialized, recalculate the tab height
2494 UpdateTabCtrlHeight();
2499 // SetUniformBitmapSize() ensures that all tabs will have
2500 // the same height, even if some tabs don't have bitmaps
2501 // Passing wxDefaultSize to this function will instruct
2502 // the control to use dynamic tab height-- so when a tab
2503 // with a large bitmap is added, the tab ctrl's height will
2504 // automatically increase to accommodate the bitmap
2506 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
)
2508 m_requested_bmp_size
= size
;
2510 // if window is already initialized, recalculate the tab height
2513 UpdateTabCtrlHeight();
2517 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant
2518 // to be used interally
2519 void wxAuiNotebook::UpdateTabCtrlHeight()
2521 // get the tab ctrl height we will use
2522 int height
= CalculateTabCtrlHeight();
2524 // if the tab control height needs to change, update
2525 // all of our tab controls with the new height
2526 if (m_tab_ctrl_height
!= height
)
2528 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2530 m_tab_ctrl_height
= height
;
2532 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2533 size_t i
, pane_count
= all_panes
.GetCount();
2534 for (i
= 0; i
< pane_count
; ++i
)
2536 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2537 if (pane
.name
== wxT("dummy"))
2539 wxTabFrame
* tab_frame
= (wxTabFrame
*)pane
.window
;
2540 wxAuiTabCtrl
* tabctrl
= tab_frame
->m_tabs
;
2541 tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
);
2542 tabctrl
->SetArtProvider(art
->Clone());
2543 tab_frame
->DoSizing();
2548 void wxAuiNotebook::UpdateHintWindowSize()
2550 wxSize size
= CalculateNewSplitSize();
2552 // the placeholder hint window should be set to this size
2553 wxAuiPaneInfo
& info
= m_mgr
.GetPane(wxT("dummy"));
2557 info
.BestSize(size
);
2558 m_dummy_wnd
->SetSize(size
);
2563 // calculates the size of the new split
2564 wxSize
wxAuiNotebook::CalculateNewSplitSize()
2566 // count number of tab controls
2567 int tab_ctrl_count
= 0;
2568 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2569 size_t i
, pane_count
= all_panes
.GetCount();
2570 for (i
= 0; i
< pane_count
; ++i
)
2572 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2573 if (pane
.name
== wxT("dummy"))
2578 wxSize new_split_size
;
2580 // if there is only one tab control, the first split
2581 // should happen around the middle
2582 if (tab_ctrl_count
< 2)
2584 new_split_size
= GetClientSize();
2585 new_split_size
.x
/= 2;
2586 new_split_size
.y
/= 2;
2590 // this is in place of a more complicated calculation
2591 // that needs to be implemented
2592 new_split_size
= wxSize(180,180);
2595 return new_split_size
;
2598 int wxAuiNotebook::CalculateTabCtrlHeight()
2600 // if a fixed tab ctrl height is specified,
2601 // just return that instead of calculating a
2603 if (m_requested_tabctrl_height
!= -1)
2604 return m_requested_tabctrl_height
;
2606 // find out new best tab height
2607 wxAuiTabArt
* art
= m_tabs
.GetArtProvider();
2609 return art
->GetBestTabCtrlSize(this,
2611 m_requested_bmp_size
);
2615 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const
2617 return m_tabs
.GetArtProvider();
2620 void wxAuiNotebook::SetWindowStyleFlag(long style
)
2622 wxControl::SetWindowStyleFlag(style
);
2624 m_flags
= (unsigned int)style
;
2626 // if the control is already initialized
2627 if (m_mgr
.GetManagedWindow() == (wxWindow
*)this)
2629 // let all of the tab children know about the new style
2631 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2632 size_t i
, pane_count
= all_panes
.GetCount();
2633 for (i
= 0; i
< pane_count
; ++i
)
2635 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2636 if (pane
.name
== wxT("dummy"))
2638 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
2639 wxAuiTabCtrl
* tabctrl
= tabframe
->m_tabs
;
2640 tabctrl
->SetFlags(m_flags
);
2641 tabframe
->DoSizing();
2649 bool wxAuiNotebook::AddPage(wxWindow
* page
,
2650 const wxString
& caption
,
2652 const wxBitmap
& bitmap
)
2654 return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
);
2657 bool wxAuiNotebook::InsertPage(size_t page_idx
,
2659 const wxString
& caption
,
2661 const wxBitmap
& bitmap
)
2663 wxAuiNotebookPage info
;
2665 info
.caption
= caption
;
2666 info
.bitmap
= bitmap
;
2667 info
.active
= false;
2669 // if there are currently no tabs, the first added
2670 // tab must be active
2671 if (m_tabs
.GetPageCount() == 0)
2674 m_tabs
.InsertPage(page
, info
, page_idx
);
2676 // if that was the first page added, even if
2677 // select is false, it must become the "current page"
2678 // (though no select events will be fired)
2679 if (!select
&& m_tabs
.GetPageCount() == 1)
2681 //m_curpage = GetPageIndex(page);
2683 wxAuiTabCtrl
* active_tabctrl
= GetActiveTabCtrl();
2684 if (page_idx
>= active_tabctrl
->GetPageCount())
2685 active_tabctrl
->AddPage(page
, info
);
2687 active_tabctrl
->InsertPage(page
, info
, page_idx
);
2689 UpdateTabCtrlHeight();
2691 active_tabctrl
->DoShowHide();
2695 SetSelectionToWindow(page
);
2702 // DeletePage() removes a tab from the multi-notebook,
2703 // and destroys the window as well
2704 bool wxAuiNotebook::DeletePage(size_t page_idx
)
2706 if (page_idx
>= m_tabs
.GetPageCount())
2709 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2711 // hide the window in advance, as this will
2713 ShowWnd(wnd
, false);
2715 if (!RemovePage(page_idx
))
2718 // actually destroy the window now
2719 if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
2721 // delete the child frame with pending delete, as is
2722 // customary with frame windows
2723 if (!wxPendingDelete
.Member(wnd
))
2724 wxPendingDelete
.Append(wnd
);
2736 // RemovePage() removes a tab from the multi-notebook,
2737 // but does not destroy the window
2738 bool wxAuiNotebook::RemovePage(size_t page_idx
)
2740 // save active window pointer
2741 wxWindow
* active_wnd
= NULL
;
2743 active_wnd
= m_tabs
.GetWindowFromIdx(m_curpage
);
2745 // save pointer of window being deleted
2746 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(page_idx
);
2747 wxWindow
* new_active
= NULL
;
2749 // make sure we found the page
2753 // find out which onscreen tab ctrl owns this tab
2756 if (!FindTab(wnd
, &ctrl
, &ctrl_idx
))
2759 bool is_curpage
= (m_curpage
== (int)page_idx
);
2760 bool is_active_in_split
= ctrl
->GetPage(ctrl_idx
).active
;
2763 // remove the tab from main catalog
2764 if (!m_tabs
.RemovePage(wnd
))
2767 // remove the tab from the onscreen tab ctrl
2768 ctrl
->RemovePage(wnd
);
2770 if (is_active_in_split
)
2772 int ctrl_new_page_count
= (int)ctrl
->GetPageCount();
2774 if (ctrl_idx
>= ctrl_new_page_count
)
2775 ctrl_idx
= ctrl_new_page_count
-1;
2777 if (ctrl_idx
>= 0 && ctrl_idx
< (int)ctrl
->GetPageCount())
2779 // set new page as active in the tab split
2780 ctrl
->SetActivePage(ctrl_idx
);
2782 // if the page deleted was the current page for the
2783 // entire tab control, then record the window
2784 // pointer of the new active page for activation
2787 new_active
= ctrl
->GetWindowFromIdx(ctrl_idx
);
2793 // we are not deleting the active page, so keep it the same
2794 new_active
= active_wnd
;
2800 // we haven't yet found a new page to active,
2801 // so select the next page from the main tab
2804 if (page_idx
< m_tabs
.GetPageCount())
2806 new_active
= m_tabs
.GetPage(page_idx
).window
;
2809 if (!new_active
&& m_tabs
.GetPageCount() > 0)
2811 new_active
= m_tabs
.GetPage(0).window
;
2816 RemoveEmptyTabFrames();
2818 // set new active pane
2822 SetSelectionToWindow(new_active
);
2828 // GetPageIndex() returns the index of the page, or -1 if the
2829 // page could not be located in the notebook
2830 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const
2832 return m_tabs
.GetIdxFromWindow(page_wnd
);
2837 // SetPageText() changes the tab caption of the specified page
2838 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
)
2840 if (page_idx
>= m_tabs
.GetPageCount())
2843 // update our own tab catalog
2844 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2845 page_info
.caption
= text
;
2847 // update what's on screen
2850 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2852 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2853 info
.caption
= text
;
2861 // returns the page caption
2862 wxString
wxAuiNotebook::GetPageText(size_t page_idx
) const
2864 if (page_idx
>= m_tabs
.GetPageCount())
2865 return wxEmptyString
;
2867 // update our own tab catalog
2868 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2869 return page_info
.caption
;
2872 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
)
2874 if (page_idx
>= m_tabs
.GetPageCount())
2877 // update our own tab catalog
2878 wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2879 page_info
.bitmap
= bitmap
;
2881 // tab height might have changed
2882 UpdateTabCtrlHeight();
2884 // update what's on screen
2887 if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
))
2889 wxAuiNotebookPage
& info
= ctrl
->GetPage(ctrl_idx
);
2890 info
.bitmap
= bitmap
;
2898 // returns the page bitmap
2899 wxBitmap
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const
2901 if (page_idx
>= m_tabs
.GetPageCount())
2904 // update our own tab catalog
2905 const wxAuiNotebookPage
& page_info
= m_tabs
.GetPage(page_idx
);
2906 return page_info
.bitmap
;
2909 // GetSelection() returns the index of the currently active page
2910 int wxAuiNotebook::GetSelection() const
2915 // SetSelection() sets the currently active page
2916 size_t wxAuiNotebook::SetSelection(size_t new_page
)
2918 // don't change the page unless necessary
2919 if ((int)new_page
== m_curpage
)
2922 wxWindow
* wnd
= m_tabs
.GetWindowFromIdx(new_page
);
2926 wxAuiNotebookEvent
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
);
2927 evt
.SetSelection(new_page
);
2928 evt
.SetOldSelection(m_curpage
);
2929 evt
.SetEventObject(this);
2930 if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed())
2932 int old_curpage
= m_curpage
;
2933 m_curpage
= new_page
;
2935 // program allows the page change
2936 evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
);
2937 (void)GetEventHandler()->ProcessEvent(evt
);
2942 if (FindTab(wnd
, &ctrl
, &ctrl_idx
))
2944 m_tabs
.SetActivePage(wnd
);
2946 ctrl
->SetActivePage(ctrl_idx
);
2953 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
2954 size_t i
, pane_count
= all_panes
.GetCount();
2955 for (i
= 0; i
< pane_count
; ++i
)
2957 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
2958 if (pane
.name
== wxT("dummy"))
2960 wxAuiTabCtrl
* tabctrl
= ((wxTabFrame
*)pane
.window
)->m_tabs
;
2961 if (tabctrl
!= ctrl
)
2962 tabctrl
->SetSelectedFont(m_normal_font
);
2964 tabctrl
->SetSelectedFont(m_selected_font
);
2977 void wxAuiNotebook::SetSelectionToWindow(wxWindow
*win
)
2979 const int idx
= m_tabs
.GetIdxFromWindow(win
);
2980 wxCHECK_RET( idx
!= wxNOT_FOUND
, _T("invalid notebook page") );
2985 // GetPageCount() returns the total number of
2986 // pages managed by the multi-notebook
2987 size_t wxAuiNotebook::GetPageCount() const
2989 return m_tabs
.GetPageCount();
2992 // GetPage() returns the wxWindow pointer of the
2994 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const
2996 wxASSERT(page_idx
< m_tabs
.GetPageCount());
2998 return m_tabs
.GetWindowFromIdx(page_idx
);
3001 // DoSizing() performs all sizing operations in each tab control
3002 void wxAuiNotebook::DoSizing()
3004 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3005 size_t i
, pane_count
= all_panes
.GetCount();
3006 for (i
= 0; i
< pane_count
; ++i
)
3008 if (all_panes
.Item(i
).name
== wxT("dummy"))
3011 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3012 tabframe
->DoSizing();
3016 // GetActiveTabCtrl() returns the active tab control. It is
3017 // called to determine which control gets new windows being added
3018 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl()
3020 if (m_curpage
>= 0 && m_curpage
< (int)m_tabs
.GetPageCount())
3025 // find the tab ctrl with the current page
3026 if (FindTab(m_tabs
.GetPage(m_curpage
).window
,
3033 // no current page, just find the first tab ctrl
3034 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3035 size_t i
, pane_count
= all_panes
.GetCount();
3036 for (i
= 0; i
< pane_count
; ++i
)
3038 if (all_panes
.Item(i
).name
== wxT("dummy"))
3041 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3042 return tabframe
->m_tabs
;
3045 // If there is no tabframe at all, create one
3046 wxTabFrame
* tabframe
= new wxTabFrame
;
3047 tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
);
3048 tabframe
->m_tabs
= new wxAuiTabCtrl(this,
3053 tabframe
->m_tabs
->SetFlags(m_flags
);
3054 tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3055 m_mgr
.AddPane(tabframe
,
3056 wxAuiPaneInfo().Center().CaptionVisible(false));
3060 return tabframe
->m_tabs
;
3063 // FindTab() finds the tab control that currently contains the window as well
3064 // as the index of the window in the tab control. It returns true if the
3065 // window was found, otherwise false.
3066 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
)
3068 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3069 size_t i
, pane_count
= all_panes
.GetCount();
3070 for (i
= 0; i
< pane_count
; ++i
)
3072 if (all_panes
.Item(i
).name
== wxT("dummy"))
3075 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3077 int page_idx
= tabframe
->m_tabs
->GetIdxFromWindow(page
);
3080 *ctrl
= tabframe
->m_tabs
;
3089 void wxAuiNotebook::Split(size_t page
, int direction
)
3091 wxSize cli_size
= GetClientSize();
3093 // get the page's window pointer
3094 wxWindow
* wnd
= GetPage(page
);
3098 // notebooks with 1 or less pages can't be split
3099 if (GetPageCount() < 2)
3102 // find out which tab control the page currently belongs to
3103 wxAuiTabCtrl
*src_tabs
, *dest_tabs
;
3106 if (!FindTab(wnd
, &src_tabs
, &src_idx
))
3108 if (!src_tabs
|| src_idx
== -1)
3111 // choose a split size
3113 if (GetPageCount() > 2)
3115 split_size
= CalculateNewSplitSize();
3119 // because there are two panes, always split them
3121 split_size
= GetClientSize();
3127 // create a new tab frame
3128 wxTabFrame
* new_tabs
= new wxTabFrame
;
3129 new_tabs
->m_rect
= wxRect(wxPoint(0,0), split_size
);
3130 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3131 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3136 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3137 new_tabs
->m_tabs
->SetFlags(m_flags
);
3138 dest_tabs
= new_tabs
->m_tabs
;
3140 // create a pane info structure with the information
3141 // about where the pane should be added
3142 wxAuiPaneInfo pane_info
= wxAuiPaneInfo().Bottom().CaptionVisible(false);
3145 if (direction
== wxLEFT
)
3148 mouse_pt
= wxPoint(0, cli_size
.y
/2);
3150 else if (direction
== wxRIGHT
)
3153 mouse_pt
= wxPoint(cli_size
.x
, cli_size
.y
/2);
3155 else if (direction
== wxTOP
)
3158 mouse_pt
= wxPoint(cli_size
.x
/2, 0);
3160 else if (direction
== wxBOTTOM
)
3163 mouse_pt
= wxPoint(cli_size
.x
/2, cli_size
.y
);
3166 m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
);
3169 // remove the page from the source tabs
3170 wxAuiNotebookPage page_info
= src_tabs
->GetPage(src_idx
);
3171 page_info
.active
= false;
3172 src_tabs
->RemovePage(page_info
.window
);
3173 if (src_tabs
->GetPageCount() > 0)
3175 src_tabs
->SetActivePage((size_t)0);
3176 src_tabs
->DoShowHide();
3177 src_tabs
->Refresh();
3181 // add the page to the destination tabs
3182 dest_tabs
->InsertPage(page_info
.window
, page_info
, 0);
3184 if (src_tabs
->GetPageCount() == 0)
3186 RemoveEmptyTabFrames();
3190 dest_tabs
->DoShowHide();
3191 dest_tabs
->Refresh();
3193 // force the set selection function reset the selection
3196 // set the active page to the one we just split off
3197 SetSelectionToPage(page_info
);
3199 UpdateHintWindowSize();
3203 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
)
3205 UpdateHintWindowSize();
3210 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
)
3212 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3214 wxAuiTabCtrl
* ctrl
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3215 wxASSERT(ctrl
!= NULL
);
3217 wxWindow
* wnd
= ctrl
->GetWindowFromIdx(evt
.GetSelection());
3218 wxASSERT(wnd
!= NULL
);
3220 SetSelectionToWindow(wnd
);
3223 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&)
3228 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
)
3230 wxPoint screen_pt
= ::wxGetMousePosition();
3231 wxPoint client_pt
= ScreenToClient(screen_pt
);
3234 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3235 wxAuiTabCtrl
* dest_tabs
= GetTabCtrlFromPoint(client_pt
);
3237 if (dest_tabs
== src_tabs
)
3241 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3244 // always hide the hint for inner-tabctrl drag
3247 // if tab moving is not allowed, leave
3248 if (!(m_flags
& wxAUI_NB_TAB_MOVE
))
3253 wxPoint pt
= dest_tabs
->ScreenToClient(screen_pt
);
3254 wxWindow
* dest_location_tab
;
3256 // this is an inner-tab drag/reposition
3257 if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
))
3259 int src_idx
= evt
.GetSelection();
3260 int dest_idx
= dest_tabs
->GetIdxFromWindow(dest_location_tab
);
3262 // prevent jumpy drag
3263 if ((src_idx
== dest_idx
) || dest_idx
== -1 ||
3264 (src_idx
> dest_idx
&& m_last_drag_x
<= pt
.x
) ||
3265 (src_idx
< dest_idx
&& m_last_drag_x
>= pt
.x
))
3267 m_last_drag_x
= pt
.x
;
3272 wxWindow
* src_tab
= dest_tabs
->GetWindowFromIdx(src_idx
);
3273 dest_tabs
->MovePage(src_tab
, dest_idx
);
3274 dest_tabs
->SetActivePage((size_t)dest_idx
);
3275 dest_tabs
->DoShowHide();
3276 dest_tabs
->Refresh();
3277 m_last_drag_x
= pt
.x
;
3285 // if external drag is allowed, check if the tab is being dragged
3286 // over a different wxAuiNotebook control
3287 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3289 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(screen_pt
);
3291 // if we aren't over any window, stop here
3295 // make sure we are not over the hint window
3296 if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
)))
3300 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3302 tab_ctrl
= tab_ctrl
->GetParent();
3307 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3311 wxRect hint_rect
= tab_ctrl
->GetClientRect();
3312 tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3313 m_mgr
.ShowHint(hint_rect
);
3322 // we are either over a hint window, or not over a tab
3323 // window, and there is no where to drag to, so exit
3330 // if there are less than two panes, split can't happen, so leave
3331 if (m_tabs
.GetPageCount() < 2)
3334 // if tab moving is not allowed, leave
3335 if (!(m_flags
& wxAUI_NB_TAB_SPLIT
))
3341 src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
));
3347 wxRect hint_rect
= dest_tabs
->GetRect();
3348 ClientToScreen(&hint_rect
.x
, &hint_rect
.y
);
3349 m_mgr
.ShowHint(hint_rect
);
3353 m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
);
3359 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
)
3361 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3366 wxAuiTabCtrl
* src_tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3367 wxCHECK_RET( src_tabs
, _T("no source object?") );
3369 src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
));
3371 // get the mouse position, which will be used to determine the drop point
3372 wxPoint mouse_screen_pt
= ::wxGetMousePosition();
3373 wxPoint mouse_client_pt
= ScreenToClient(mouse_screen_pt
);
3377 // check for an external move
3378 if (m_flags
& wxAUI_NB_TAB_EXTERNAL_MOVE
)
3380 wxWindow
* tab_ctrl
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3384 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
)))
3386 tab_ctrl
= tab_ctrl
->GetParent();
3391 wxAuiNotebook
* nb
= (wxAuiNotebook
*)tab_ctrl
->GetParent();
3395 // find out from the destination control
3396 // if it's ok to drop this tab here
3397 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
);
3398 e
.SetSelection(evt
.GetSelection());
3399 e
.SetOldSelection(evt
.GetSelection());
3400 e
.SetEventObject(this);
3401 e
.SetDragSource(this);
3402 e
.Veto(); // dropping must be explicitly approved by control owner
3404 nb
->GetEventHandler()->ProcessEvent(e
);
3408 // no answer or negative answer
3414 int src_idx
= evt
.GetSelection();
3415 wxWindow
* src_page
= src_tabs
->GetWindowFromIdx(src_idx
);
3417 // Check that it's not an impossible parent relationship
3419 while (p
&& !p
->IsTopLevel())
3428 // get main index of the page
3429 int main_idx
= m_tabs
.GetIdxFromWindow(src_page
);
3430 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no source page?") );
3433 // make a copy of the page info
3434 wxAuiNotebookPage page_info
= m_tabs
.GetPage(main_idx
);
3436 // remove the page from the source notebook
3437 RemovePage(main_idx
);
3439 // reparent the page
3440 src_page
->Reparent(nb
);
3443 // found out the insert idx
3444 wxAuiTabCtrl
* dest_tabs
= (wxAuiTabCtrl
*)tab_ctrl
;
3445 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3447 wxWindow
* target
= NULL
;
3448 int insert_idx
= -1;
3449 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3452 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3456 // add the page to the new notebook
3457 if (insert_idx
== -1)
3458 insert_idx
= dest_tabs
->GetPageCount();
3459 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3460 nb
->m_tabs
.AddPage(page_info
.window
, page_info
);
3463 dest_tabs
->DoShowHide();
3464 dest_tabs
->Refresh();
3466 // set the selection in the destination tab control
3467 nb
->SetSelectionToPage(page_info
);
3477 // only perform a tab split if it's allowed
3478 wxAuiTabCtrl
* dest_tabs
= NULL
;
3480 if ((m_flags
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2)
3482 // If the pointer is in an existing tab frame, do a tab insert
3483 wxWindow
* hit_wnd
= ::wxFindWindowAtPoint(mouse_screen_pt
);
3484 wxTabFrame
* tab_frame
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
);
3485 int insert_idx
= -1;
3488 dest_tabs
= tab_frame
->m_tabs
;
3490 if (dest_tabs
== src_tabs
)
3494 wxPoint pt
= dest_tabs
->ScreenToClient(mouse_screen_pt
);
3495 wxWindow
* target
= NULL
;
3496 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
);
3499 insert_idx
= dest_tabs
->GetIdxFromWindow(target
);
3505 wxRect rect
= m_mgr
.CalculateHintRect(m_dummy_wnd
,
3510 // there is no suitable drop location here, exit out
3514 // If there is no tabframe at all, create one
3515 wxTabFrame
* new_tabs
= new wxTabFrame
;
3516 new_tabs
->m_rect
= wxRect(wxPoint(0,0), CalculateNewSplitSize());
3517 new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
);
3518 new_tabs
->m_tabs
= new wxAuiTabCtrl(this,
3523 new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone());
3524 new_tabs
->m_tabs
->SetFlags(m_flags
);
3526 m_mgr
.AddPane(new_tabs
,
3527 wxAuiPaneInfo().Bottom().CaptionVisible(false),
3530 dest_tabs
= new_tabs
->m_tabs
;
3535 // remove the page from the source tabs
3536 wxAuiNotebookPage page_info
= src_tabs
->GetPage(evt
.GetSelection());
3537 page_info
.active
= false;
3538 src_tabs
->RemovePage(page_info
.window
);
3539 if (src_tabs
->GetPageCount() > 0)
3541 src_tabs
->SetActivePage((size_t)0);
3542 src_tabs
->DoShowHide();
3543 src_tabs
->Refresh();
3548 // add the page to the destination tabs
3549 if (insert_idx
== -1)
3550 insert_idx
= dest_tabs
->GetPageCount();
3551 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
);
3553 if (src_tabs
->GetPageCount() == 0)
3555 RemoveEmptyTabFrames();
3559 dest_tabs
->DoShowHide();
3560 dest_tabs
->Refresh();
3562 // force the set selection function reset the selection
3565 // set the active page to the one we just split off
3566 SetSelectionToPage(page_info
);
3568 UpdateHintWindowSize();
3574 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
)
3576 // if we've just removed the last tab from the source
3577 // tab set, the remove the tab control completely
3578 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3579 size_t i
, pane_count
= all_panes
.GetCount();
3580 for (i
= 0; i
< pane_count
; ++i
)
3582 if (all_panes
.Item(i
).name
== wxT("dummy"))
3585 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3586 if (tabframe
->m_tab_rect
.Contains(pt
))
3587 return tabframe
->m_tabs
;
3593 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
)
3595 // if we've just removed the last tab from the source
3596 // tab set, the remove the tab control completely
3597 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3598 size_t i
, pane_count
= all_panes
.GetCount();
3599 for (i
= 0; i
< pane_count
; ++i
)
3601 if (all_panes
.Item(i
).name
== wxT("dummy"))
3604 wxTabFrame
* tabframe
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3605 if (tabframe
->m_tabs
== tab_ctrl
)
3614 void wxAuiNotebook::RemoveEmptyTabFrames()
3616 // if we've just removed the last tab from the source
3617 // tab set, the remove the tab control completely
3618 wxAuiPaneInfoArray all_panes
= m_mgr
.GetAllPanes();
3619 size_t i
, pane_count
= all_panes
.GetCount();
3620 for (i
= 0; i
< pane_count
; ++i
)
3622 if (all_panes
.Item(i
).name
== wxT("dummy"))
3625 wxTabFrame
* tab_frame
= (wxTabFrame
*)all_panes
.Item(i
).window
;
3626 if (tab_frame
->m_tabs
->GetPageCount() == 0)
3628 m_mgr
.DetachPane(tab_frame
);
3630 // use pending delete because sometimes during
3631 // window closing, refreshs are pending
3632 if (!wxPendingDelete
.Member(tab_frame
->m_tabs
))
3633 wxPendingDelete
.Append(tab_frame
->m_tabs
);
3635 tab_frame
->m_tabs
= NULL
;
3642 // check to see if there is still a center pane;
3643 // if there isn't, make a frame the center pane
3644 wxAuiPaneInfoArray panes
= m_mgr
.GetAllPanes();
3645 pane_count
= panes
.GetCount();
3646 wxWindow
* first_good
= NULL
;
3647 bool center_found
= false;
3648 for (i
= 0; i
< pane_count
; ++i
)
3650 if (panes
.Item(i
).name
== wxT("dummy"))
3652 if (panes
.Item(i
).dock_direction
== wxAUI_DOCK_CENTRE
)
3653 center_found
= true;
3655 first_good
= panes
.Item(i
).window
;
3658 if (!center_found
&& first_good
)
3660 m_mgr
.GetPane(first_good
).Centre();
3666 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
)
3668 // if we're dragging a tab, don't change the current selection.
3669 // This code prevents a bug that used to happen when the hint window
3670 // was hidden. In the bug, the focus would return to the notebook
3671 // child, which would then enter this handler and call
3672 // SetSelection, which is not desired turn tab dragging.
3674 wxAuiPaneInfoArray
& all_panes
= m_mgr
.GetAllPanes();
3675 size_t i
, pane_count
= all_panes
.GetCount();
3676 for (i
= 0; i
< pane_count
; ++i
)
3678 wxAuiPaneInfo
& pane
= all_panes
.Item(i
);
3679 if (pane
.name
== wxT("dummy"))
3681 wxTabFrame
* tabframe
= (wxTabFrame
*)pane
.window
;
3682 if (tabframe
->m_tabs
->IsDragging())
3687 // change the tab selection to the child
3688 // which was focused
3689 int idx
= m_tabs
.GetIdxFromWindow(evt
.GetWindow());
3690 if (idx
!= -1 && idx
!= m_curpage
)
3697 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
)
3699 wxAuiNotebookEvent
& evt
= (wxAuiNotebookEvent
&)command_evt
;
3700 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3702 int button_id
= evt
.GetInt();
3704 if (button_id
== wxAUI_BUTTON_CLOSE
)
3706 int selection
= evt
.GetSelection();
3708 if (selection
== -1)
3710 // if the close button is to the right, use the active
3711 // page selection to determine which page to close
3712 selection
= GetSelection();
3715 if (selection
!= -1)
3717 wxWindow
* close_wnd
= tabs
->GetWindowFromIdx(selection
);
3719 // ask owner if it's ok to close the tab
3720 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
);
3721 e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
));
3722 e
.SetOldSelection(evt
.GetSelection());
3723 e
.SetEventObject(this);
3724 GetEventHandler()->ProcessEvent(e
);
3729 if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
)))
3735 int main_idx
= m_tabs
.GetIdxFromWindow(close_wnd
);
3736 wxCHECK_RET( main_idx
!= wxNOT_FOUND
, _T("no page to delete?") );
3738 DeletePage(main_idx
);
3745 void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent
& evt
)
3747 // patch event through to owner
3748 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3749 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3751 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
);
3752 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3753 e
.SetEventObject(this);
3754 GetEventHandler()->ProcessEvent(e
);
3757 void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent
& evt
)
3759 // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
3760 // click should act like a tab close action. However, first
3761 // give the owner an opportunity to handle the middle up event
3762 // for custom action
3764 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3765 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3767 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
);
3768 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3769 e
.SetEventObject(this);
3770 if (GetEventHandler()->ProcessEvent(e
))
3775 // check if we are supposed to close on middle-up
3776 if ((m_flags
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0)
3779 // simulate the user pressing the close button on the tab
3780 evt
.SetInt(wxAUI_BUTTON_CLOSE
);
3784 void wxAuiNotebook::OnTabRightDown(wxCommandEvent
& evt
)
3786 // patch event through to owner
3787 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3788 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3790 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
);
3791 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3792 e
.SetEventObject(this);
3793 GetEventHandler()->ProcessEvent(e
);
3796 void wxAuiNotebook::OnTabRightUp(wxCommandEvent
& evt
)
3798 // patch event through to owner
3799 wxAuiTabCtrl
* tabs
= (wxAuiTabCtrl
*)evt
.GetEventObject();
3800 wxWindow
* wnd
= tabs
->GetWindowFromIdx(evt
.GetSelection());
3802 wxAuiNotebookEvent
e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
);
3803 e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
));
3804 e
.SetEventObject(this);
3805 GetEventHandler()->ProcessEvent(e
);
3808 // Sets the normal font
3809 void wxAuiNotebook::SetNormalFont(const wxFont
& font
)
3811 m_normal_font
= font
;
3812 GetArtProvider()->SetNormalFont(font
);
3815 // Sets the selected tab font
3816 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
)
3818 m_selected_font
= font
;
3819 GetArtProvider()->SetSelectedFont(font
);
3822 // Sets the measuring font
3823 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
)
3825 GetArtProvider()->SetMeasuringFont(font
);
3828 // Sets the tab font
3829 bool wxAuiNotebook::SetFont(const wxFont
& font
)
3831 wxControl::SetFont(font
);
3833 wxFont
normalFont(font
);
3834 wxFont
selectedFont(normalFont
);
3835 selectedFont
.SetWeight(wxBOLD
);
3837 SetNormalFont(normalFont
);
3838 SetSelectedFont(selectedFont
);
3839 SetMeasuringFont(selectedFont
);
3844 // Gets the tab control height
3845 int wxAuiNotebook::GetTabCtrlHeight() const
3847 return m_tab_ctrl_height
;
3850 // Gets the height of the notebook for a given page height
3851 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
)
3853 UpdateTabCtrlHeight();
3855 int tabCtrlHeight
= GetTabCtrlHeight();
3856 int decorHeight
= 2;
3857 return tabCtrlHeight
+ pageHeight
+ decorHeight
;