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
) 
  52 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
) 
  53 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
) 
  54 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxEvent
) 
  60 // these functions live in dockart.cpp -- they'll eventually 
  61 // be moved to a new utility cpp file 
  63 wxColor 
wxAuiStepColour(const wxColor
& c
, int percent
); 
  65 wxBitmap 
wxAuiBitmapFromBits(const unsigned char bits
[], int w
, int h
, 
  66                              const wxColour
& color
); 
  68 wxString 
wxAuiChopText(wxDC
& dc
, const wxString
& text
, int max_size
); 
  70 static void DrawButtons(wxDC
& dc
, 
  73                         const wxColour
& bkcolour
, 
  78     if (button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
  84     if (button_state 
== wxAUI_BUTTON_STATE_HOVER 
|| 
  85         button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
  87         dc
.SetBrush(wxBrush(wxAuiStepColour(bkcolour
, 120))); 
  88         dc
.SetPen(wxPen(wxAuiStepColour(bkcolour
, 75))); 
  90         // draw the background behind the button 
  91         dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15); 
  94     // draw the button itself 
  95     dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true); 
  98 static void IndentPressedBitmap(wxRect
* rect
, int button_state
) 
 100     if (button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
 109 // -- GUI helper classes and functions -- 
 111 class wxAuiCommandCapture 
: public wxEvtHandler
 
 115     wxAuiCommandCapture() { m_last_id 
= 0; } 
 116     int GetCommandId() const { return m_last_id
; } 
 118     bool ProcessEvent(wxEvent
& evt
) 
 120         if (evt
.GetEventType() == wxEVT_COMMAND_MENU_SELECTED
) 
 122             m_last_id 
= evt
.GetId(); 
 126         if (GetNextHandler()) 
 127             return GetNextHandler()->ProcessEvent(evt
); 
 139 #if defined( __WXMAC__ ) 
 140  static unsigned char close_bits
[]={ 
 141      0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3, 
 142      0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3, 
 143      0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF }; 
 144 #elif defined( __WXGTK__) 
 145  static unsigned char close_bits
[]={ 
 146      0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8, 
 147      0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef, 
 148      0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 
 150  static unsigned char close_bits
[]={ 
 151      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xf3, 0xcf, 0xf9, 
 152      0x9f, 0xfc, 0x3f, 0xfe, 0x3f, 0xfe, 0x9f, 0xfc, 0xcf, 0xf9, 0xe7, 0xf3, 
 153      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
 156 static unsigned char left_bits
[] = { 
 157    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, 
 158    0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe, 
 159    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
 161 static unsigned char right_bits
[] = { 
 162    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff, 
 163    0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff, 
 164    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
 166 static unsigned char list_bits
[] = { 
 167    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
 168    0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, 
 169    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
 176 // -- wxAuiDefaultTabArt class implementation -- 
 178 wxAuiDefaultTabArt::wxAuiDefaultTabArt() 
 180     m_normal_font 
= *wxNORMAL_FONT
; 
 181     m_selected_font 
= *wxNORMAL_FONT
; 
 182     m_selected_font
.SetWeight(wxBOLD
); 
 183     m_measuring_font 
= m_selected_font
; 
 185     m_fixed_tab_width 
= 100; 
 186     m_tab_ctrl_height 
= 0; 
 189     wxBrush toolbarbrush
; 
 190     toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground 
); 
 191     wxColor base_colour 
= toolbarbrush
.GetColour(); 
 193     wxColor base_colour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
 196     // the base_colour is too pale to use as our base colour, 
 197     // so darken it a bit -- 
 198     if ((255-base_colour
.Red()) + 
 199         (255-base_colour
.Green()) + 
 200         (255-base_colour
.Blue()) < 60) 
 202         base_colour 
= wxAuiStepColour(base_colour
, 92); 
 205     m_base_colour 
= base_colour
; 
 206     wxColor border_colour 
= wxAuiStepColour(base_colour
, 75); 
 208     m_border_pen 
= wxPen(border_colour
); 
 209     m_base_colour_pen 
= wxPen(m_base_colour
); 
 210     m_base_colour_brush 
= wxBrush(m_base_colour
); 
 212     m_active_close_bmp 
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
); 
 213     m_disabled_close_bmp 
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128)); 
 215     m_active_left_bmp 
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
); 
 216     m_disabled_left_bmp 
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128)); 
 218     m_active_right_bmp 
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
); 
 219     m_disabled_right_bmp 
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128)); 
 221     m_active_windowlist_bmp 
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
); 
 222     m_disabled_windowlist_bmp 
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128)); 
 227 wxAuiDefaultTabArt::~wxAuiDefaultTabArt() 
 231 wxAuiTabArt
* wxAuiDefaultTabArt::Clone() 
 233     return static_cast<wxAuiTabArt
*>(new wxAuiDefaultTabArt
); 
 236 void wxAuiDefaultTabArt::SetFlags(unsigned int flags
) 
 241 void wxAuiDefaultTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
, 
 244     m_fixed_tab_width 
= 100; 
 246     int tot_width 
= (int)tab_ctrl_size
.x 
- GetIndentSize() - 4; 
 248     if (m_flags 
& wxAUI_NB_CLOSE_BUTTON
) 
 249         tot_width 
-= m_active_close_bmp
.GetWidth(); 
 250     if (m_flags 
& wxAUI_NB_WINDOWLIST_BUTTON
) 
 251         tot_width 
-= m_active_windowlist_bmp
.GetWidth(); 
 255         m_fixed_tab_width 
= tot_width
/(int)tab_count
; 
 259     if (m_fixed_tab_width 
< 100) 
 260         m_fixed_tab_width 
= 100; 
 262     if (m_fixed_tab_width 
> tot_width
/2) 
 263         m_fixed_tab_width 
= tot_width
/2; 
 265     if (m_fixed_tab_width 
> 220) 
 266         m_fixed_tab_width 
= 220; 
 268     m_tab_ctrl_height 
= tab_ctrl_size
.y
; 
 272 void wxAuiDefaultTabArt::DrawBackground(wxDC
& dc
, 
 273                                         wxWindow
* WXUNUSED(wnd
), 
 277     wxRect 
r(rect
.x
, rect
.y
, rect
.width
+2, rect
.height
-3); 
 278     wxColor top_color 
= wxAuiStepColour(m_base_colour
, 90); 
 279     wxColor bottom_color 
= wxAuiStepColour(m_base_colour
, 170); 
 280     dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
); 
 283     int y 
= rect
.GetHeight(); 
 284     int w 
= rect
.GetWidth(); 
 285     dc
.SetPen(m_border_pen
); 
 286     dc
.SetBrush(m_base_colour_brush
); 
 287     dc
.DrawRectangle(-1, y
-4, w
+2, 4); 
 291 // DrawTab() draws an individual tab. 
 294 // in_rect  - rectangle the tab should be confined to 
 295 // caption  - tab's caption 
 296 // active   - whether or not the tab is active 
 297 // out_rect - actual output rectangle 
 298 // x_extent - the advance x; where the next tab should start 
 300 void wxAuiDefaultTabArt::DrawTab(wxDC
& dc
, 
 302                                  const wxAuiNotebookPage
& page
, 
 303                                  const wxRect
& in_rect
, 
 304                                  int close_button_state
, 
 305                                  wxRect
* out_tab_rect
, 
 306                                  wxRect
* out_button_rect
, 
 309     wxCoord normal_textx
, normal_texty
; 
 310     wxCoord selected_textx
, selected_texty
; 
 311     wxCoord textx
, texty
; 
 313     // if the caption is empty, measure some temporary text 
 314     wxString caption 
= page
.caption
; 
 318     dc
.SetFont(m_selected_font
); 
 319     dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
); 
 321     dc
.SetFont(m_normal_font
); 
 322     dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
); 
 324     // figure out the size of the tab 
 325     wxSize tab_size 
= GetTabSize(dc
, 
 333     wxCoord tab_height 
= m_tab_ctrl_height 
- 3; 
 334     wxCoord tab_width 
= tab_size
.x
; 
 335     wxCoord tab_x 
= in_rect
.x
; 
 336     wxCoord tab_y 
= in_rect
.y 
+ in_rect
.height 
- tab_height
; 
 339     caption 
= page
.caption
; 
 342     // select pen, brush and font for the tab to be drawn 
 346         dc
.SetFont(m_selected_font
); 
 347         textx 
= selected_textx
; 
 348         texty 
= selected_texty
; 
 352         dc
.SetFont(m_normal_font
); 
 353         textx 
= normal_textx
; 
 354         texty 
= normal_texty
; 
 358     // create points that will make the tab outline 
 360     int clip_width 
= tab_width
; 
 361     if (tab_x 
+ clip_width 
> in_rect
.x 
+ in_rect
.width
) 
 362         clip_width 
= (in_rect
.x 
+ in_rect
.width
) - tab_x
; 
 365     wxPoint clip_points[6]; 
 366     clip_points[0] = wxPoint(tab_x,              tab_y+tab_height-3); 
 367     clip_points[1] = wxPoint(tab_x,              tab_y+2); 
 368     clip_points[2] = wxPoint(tab_x+2,            tab_y); 
 369     clip_points[3] = wxPoint(tab_x+clip_width-1, tab_y); 
 370     clip_points[4] = wxPoint(tab_x+clip_width+1, tab_y+2); 
 371     clip_points[5] = wxPoint(tab_x+clip_width+1, tab_y+tab_height-3); 
 373     // FIXME: these ports don't provide wxRegion ctor from array of points 
 374 #if !defined(__WXDFB__) && !defined(__WXCOCOA__) 
 375     // set the clipping region for the tab -- 
 376     wxRegion clipping_region(WXSIZEOF(clip_points), clip_points); 
 377     dc.SetClippingRegion(clipping_region); 
 378 #endif // !wxDFB && !wxCocoa 
 380     // since the above code above doesn't play well with WXDFB or WXCOCOA, 
 381     // we'll just use a rectangle for the clipping region for now -- 
 382     dc
.SetClippingRegion(tab_x
, tab_y
, clip_width
+1, tab_height
-3); 
 385     wxPoint border_points
[6]; 
 386     border_points
[0] = wxPoint(tab_x
,             tab_y
+tab_height
-4); 
 387     border_points
[1] = wxPoint(tab_x
,             tab_y
+2); 
 388     border_points
[2] = wxPoint(tab_x
+2,           tab_y
); 
 389     border_points
[3] = wxPoint(tab_x
+tab_width
-2, tab_y
); 
 390     border_points
[4] = wxPoint(tab_x
+tab_width
,   tab_y
+2); 
 391     border_points
[5] = wxPoint(tab_x
+tab_width
,   tab_y
+tab_height
-4); 
 394     int drawn_tab_yoff 
= border_points
[1].y
; 
 395     int drawn_tab_height 
= border_points
[0].y 
- border_points
[1].y
; 
 402         // draw base background color 
 403         wxRect 
r(tab_x
, tab_y
, tab_width
, tab_height
); 
 404         dc
.SetPen(m_base_colour_pen
); 
 405         dc
.SetBrush(m_base_colour_brush
); 
 406         dc
.DrawRectangle(r
.x
+1, r
.y
+1, r
.width
-1, r
.height
-4); 
 408         // this white helps fill out the gradient at the top of the tab 
 409         dc
.SetPen(*wxWHITE_PEN
); 
 410         dc
.SetBrush(*wxWHITE_BRUSH
); 
 411         dc
.DrawRectangle(r
.x
+2, r
.y
+1, r
.width
-3, r
.height
-4); 
 413         // these two points help the rounded corners appear more antialiased 
 414         dc
.SetPen(m_base_colour_pen
); 
 415         dc
.DrawPoint(r
.x
+2, r
.y
+1); 
 416         dc
.DrawPoint(r
.x
+r
.width
-2, r
.y
+1); 
 418         // set rectangle down a bit for gradient drawing 
 419         r
.SetHeight(r
.GetHeight()/2); 
 425         // draw gradient background 
 426         wxColor top_color 
= *wxWHITE
; 
 427         wxColor bottom_color 
= m_base_colour
; 
 428         dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
); 
 434         wxRect 
r(tab_x
, tab_y
+1, tab_width
, tab_height
-3); 
 436         // start the gradent up a bit and leave the inside border inset 
 437         // by a pixel for a 3D look.  Only the top half of the inactive 
 438         // tab will have a slight gradient 
 445         // -- draw top gradient fill for glossy look 
 446         wxColor top_color 
= m_base_colour
; 
 447         wxColor bottom_color 
= wxAuiStepColour(top_color
, 160); 
 448         dc
.GradientFillLinear(r
, bottom_color
, top_color
, wxNORTH
); 
 453         // -- draw bottom fill for glossy look 
 454         top_color 
= m_base_colour
; 
 455         bottom_color 
= m_base_colour
; 
 456         dc
.GradientFillLinear(r
, top_color
, bottom_color
, wxSOUTH
); 
 460     dc
.SetPen(m_border_pen
); 
 461     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 462     dc
.DrawPolygon(WXSIZEOF(border_points
), border_points
); 
 464     // there are two horizontal grey lines at the bottom of the tab control, 
 465     // this gets rid of the top one of those lines in the tab control 
 468         wxColor start_color 
= m_base_colour
; 
 469         dc
.SetPen(m_base_colour_pen
); 
 470         dc
.DrawLine(border_points
[0].x
+1, 
 477     int text_offset 
= tab_x 
+ 8; 
 478     int close_button_width 
= 0; 
 479     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
 481         close_button_width 
= m_active_close_bmp
.GetWidth(); 
 485     if (page
.bitmap
.IsOk()) 
 487         int bitmap_offset 
= tab_x 
+ 8; 
 490         dc
.DrawBitmap(page
.bitmap
, 
 492                       drawn_tab_yoff 
+ (drawn_tab_height
/2) - (page
.bitmap
.GetHeight()/2), 
 495         text_offset 
= bitmap_offset 
+ page
.bitmap
.GetWidth(); 
 496         text_offset 
+= 3; // bitmap padding 
 500         text_offset 
= tab_x 
+ 8; 
 504     wxString draw_text 
= wxAuiChopText(dc
, 
 506                           tab_width 
- (text_offset
-tab_x
) - close_button_width
); 
 509     dc
.DrawText(draw_text
, 
 511                 drawn_tab_yoff 
+ (drawn_tab_height
)/2 - (texty
/2) - 1); 
 516     // draw close button if necessary 
 517     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
 519         wxBitmap bmp 
= m_disabled_close_bmp
; 
 521         if (close_button_state 
== wxAUI_BUTTON_STATE_HOVER 
|| 
 522             close_button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
 524             bmp 
= m_active_close_bmp
; 
 527         wxRect 
rect(tab_x 
+ tab_width 
- close_button_width 
- 1, 
 528                     tab_y 
+ (tab_height
/2) - (bmp
.GetHeight()/2), 
 531         IndentPressedBitmap(&rect
, close_button_state
); 
 532         dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true); 
 534         *out_button_rect 
= rect
; 
 537     *out_tab_rect 
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
); 
 539     dc
.DestroyClippingRegion(); 
 542 int wxAuiDefaultTabArt::GetIndentSize() 
 547 wxSize 
wxAuiDefaultTabArt::GetTabSize(wxDC
& dc
, 
 548                                       wxWindow
* WXUNUSED(wnd
), 
 549                                       const wxString
& caption
, 
 550                                       const wxBitmap
& bitmap
, 
 551                                       bool WXUNUSED(active
), 
 552                                       int close_button_state
, 
 555     wxCoord measured_textx
, measured_texty
, tmp
; 
 557     dc
.SetFont(m_measuring_font
); 
 558     dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
); 
 560     dc
.GetTextExtent(wxT("ABCDEFXj"), &tmp
, &measured_texty
); 
 562     // add padding around the text 
 563     wxCoord tab_width 
= measured_textx
; 
 564     wxCoord tab_height 
= measured_texty
; 
 566     // if the close button is showing, add space for it 
 567     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
 568         tab_width 
+= m_active_close_bmp
.GetWidth() + 3; 
 570     // if there's a bitmap, add space for it 
 573         tab_width 
+= bitmap
.GetWidth(); 
 574         tab_width 
+= 3; // right side bitmap padding 
 575         tab_height 
= wxMax(tab_height
, bitmap
.GetHeight()); 
 582     if (m_flags 
& wxAUI_NB_TAB_FIXED_WIDTH
) 
 584         tab_width 
= m_fixed_tab_width
; 
 587     *x_extent 
= tab_width
; 
 589     return wxSize(tab_width
, tab_height
); 
 593 void wxAuiDefaultTabArt::DrawButton(wxDC
& dc
, 
 594                                     wxWindow
* WXUNUSED(wnd
), 
 595                                     const wxRect
& in_rect
, 
 606         case wxAUI_BUTTON_CLOSE
: 
 607             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
 608                 bmp 
= m_disabled_close_bmp
; 
 610                 bmp 
= m_active_close_bmp
; 
 612         case wxAUI_BUTTON_LEFT
: 
 613             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
 614                 bmp 
= m_disabled_left_bmp
; 
 616                 bmp 
= m_active_left_bmp
; 
 618         case wxAUI_BUTTON_RIGHT
: 
 619             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
 620                 bmp 
= m_disabled_right_bmp
; 
 622                 bmp 
= m_active_right_bmp
; 
 624         case wxAUI_BUTTON_WINDOWLIST
: 
 625             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
 626                 bmp 
= m_disabled_windowlist_bmp
; 
 628                 bmp 
= m_active_windowlist_bmp
; 
 638     if (orientation 
== wxLEFT
) 
 640         rect
.SetX(in_rect
.x
); 
 641         rect
.SetY(((in_rect
.y 
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2)); 
 642         rect
.SetWidth(bmp
.GetWidth()); 
 643         rect
.SetHeight(bmp
.GetHeight()); 
 647         rect 
= wxRect(in_rect
.x 
+ in_rect
.width 
- bmp
.GetWidth(), 
 648                       ((in_rect
.y 
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2), 
 649                       bmp
.GetWidth(), bmp
.GetHeight()); 
 652     IndentPressedBitmap(&rect
, button_state
); 
 653     dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true); 
 659 int wxAuiDefaultTabArt::ShowDropDown(wxWindow
* wnd
, 
 660                                      const wxAuiNotebookPageArray
& pages
, 
 665     size_t i
, count 
= pages
.GetCount(); 
 666     for (i 
= 0; i 
< count
; ++i
) 
 668         const wxAuiNotebookPage
& page 
= pages
.Item(i
); 
 669         wxString caption 
= page
.caption
; 
 671         // if there is no caption, make it a space.  This will prevent 
 672         // an assert in the menu code. 
 673         if (caption
.IsEmpty()) 
 676         menuPopup
.AppendCheckItem(1000+i
, caption
); 
 679     if (active_idx 
!= -1) 
 681         menuPopup
.Check(1000+active_idx
, true); 
 684     // find out where to put the popup menu of window items 
 685     wxPoint pt 
= ::wxGetMousePosition(); 
 686     pt 
= wnd
->ScreenToClient(pt
); 
 688     // find out the screen coordinate at the bottom of the tab ctrl 
 689     wxRect cli_rect 
= wnd
->GetClientRect(); 
 690     pt
.y 
= cli_rect
.y 
+ cli_rect
.height
; 
 692     wxAuiCommandCapture
* cc 
= new wxAuiCommandCapture
; 
 693     wnd
->PushEventHandler(cc
); 
 694     wnd
->PopupMenu(&menuPopup
, pt
); 
 695     int command 
= cc
->GetCommandId(); 
 696     wnd
->PopEventHandler(true); 
 704 int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow
* wnd
, 
 705                                            const wxAuiNotebookPageArray
& pages
, 
 706                                            const wxSize
& required_bmp_size
) 
 709     dc
.SetFont(m_measuring_font
); 
 711     // sometimes a standard bitmap size needs to be enforced, especially 
 712     // if some tabs have bitmaps and others don't.  This is important because 
 713     // it prevents the tab control from resizing when tabs are added. 
 714     wxBitmap measure_bmp
; 
 715     if (required_bmp_size
.IsFullySpecified()) 
 717         measure_bmp
.Create(required_bmp_size
.x
, 
 718                            required_bmp_size
.y
); 
 723     size_t i
, page_count 
= pages
.GetCount(); 
 724     for (i 
= 0; i 
< page_count
; ++i
) 
 726         wxAuiNotebookPage
& page 
= pages
.Item(i
); 
 729         if (measure_bmp
.IsOk()) 
 734         // we don't use the caption text because we don't 
 735         // want tab heights to be different in the case 
 736         // of a very short piece of text on one tab and a very 
 737         // tall piece of text on another tab 
 739         wxSize s 
= GetTabSize(dc
, 
 744                               wxAUI_BUTTON_STATE_HIDDEN
, 
 747         max_y 
= wxMax(max_y
, s
.y
); 
 753 void wxAuiDefaultTabArt::SetNormalFont(const wxFont
& font
) 
 755     m_normal_font 
= font
; 
 758 void wxAuiDefaultTabArt::SetSelectedFont(const wxFont
& font
) 
 760     m_selected_font 
= font
; 
 763 void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont
& font
) 
 765     m_measuring_font 
= font
; 
 769 // -- wxAuiSimpleTabArt class implementation -- 
 771 wxAuiSimpleTabArt::wxAuiSimpleTabArt() 
 773     m_normal_font 
= *wxNORMAL_FONT
; 
 774     m_selected_font 
= *wxNORMAL_FONT
; 
 775     m_selected_font
.SetWeight(wxBOLD
); 
 776     m_measuring_font 
= m_selected_font
; 
 779     m_fixed_tab_width 
= 100; 
 781     wxColour base_colour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
 783     wxColour background_colour 
= base_colour
; 
 784     wxColour normaltab_colour 
= base_colour
; 
 785     wxColour selectedtab_colour 
= *wxWHITE
; 
 787     m_bkbrush 
= wxBrush(background_colour
); 
 788     m_normal_bkbrush 
= wxBrush(normaltab_colour
); 
 789     m_normal_bkpen 
= wxPen(normaltab_colour
); 
 790     m_selected_bkbrush 
= wxBrush(selectedtab_colour
); 
 791     m_selected_bkpen 
= wxPen(selectedtab_colour
); 
 793     m_active_close_bmp 
= wxAuiBitmapFromBits(close_bits
, 16, 16, *wxBLACK
); 
 794     m_disabled_close_bmp 
= wxAuiBitmapFromBits(close_bits
, 16, 16, wxColour(128,128,128)); 
 796     m_active_left_bmp 
= wxAuiBitmapFromBits(left_bits
, 16, 16, *wxBLACK
); 
 797     m_disabled_left_bmp 
= wxAuiBitmapFromBits(left_bits
, 16, 16, wxColour(128,128,128)); 
 799     m_active_right_bmp 
= wxAuiBitmapFromBits(right_bits
, 16, 16, *wxBLACK
); 
 800     m_disabled_right_bmp 
= wxAuiBitmapFromBits(right_bits
, 16, 16, wxColour(128,128,128)); 
 802     m_active_windowlist_bmp 
= wxAuiBitmapFromBits(list_bits
, 16, 16, *wxBLACK
); 
 803     m_disabled_windowlist_bmp 
= wxAuiBitmapFromBits(list_bits
, 16, 16, wxColour(128,128,128)); 
 807 wxAuiSimpleTabArt::~wxAuiSimpleTabArt() 
 811 wxAuiTabArt
* wxAuiSimpleTabArt::Clone() 
 813     return static_cast<wxAuiTabArt
*>(new wxAuiSimpleTabArt
); 
 817 void wxAuiSimpleTabArt::SetFlags(unsigned int flags
) 
 822 void wxAuiSimpleTabArt::SetSizingInfo(const wxSize
& tab_ctrl_size
, 
 825     m_fixed_tab_width 
= 100; 
 827     int tot_width 
= (int)tab_ctrl_size
.x 
- GetIndentSize() - 4; 
 829     if (m_flags 
& wxAUI_NB_CLOSE_BUTTON
) 
 830         tot_width 
-= m_active_close_bmp
.GetWidth(); 
 831     if (m_flags 
& wxAUI_NB_WINDOWLIST_BUTTON
) 
 832         tot_width 
-= m_active_windowlist_bmp
.GetWidth(); 
 836         m_fixed_tab_width 
= tot_width
/(int)tab_count
; 
 840     if (m_fixed_tab_width 
< 100) 
 841         m_fixed_tab_width 
= 100; 
 843     if (m_fixed_tab_width 
> tot_width
/2) 
 844         m_fixed_tab_width 
= tot_width
/2; 
 846     if (m_fixed_tab_width 
> 220) 
 847         m_fixed_tab_width 
= 220; 
 850 void wxAuiSimpleTabArt::DrawBackground(wxDC
& dc
, 
 851                                        wxWindow
* WXUNUSED(wnd
), 
 855     dc
.SetBrush(m_bkbrush
); 
 856     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 857     dc
.DrawRectangle(-1, -1, rect
.GetWidth()+2, rect
.GetHeight()+2); 
 860     dc
.SetPen(*wxGREY_PEN
); 
 861     dc
.DrawLine(0, rect
.GetHeight()-1, rect
.GetWidth(), rect
.GetHeight()-1); 
 865 // DrawTab() draws an individual tab. 
 868 // in_rect  - rectangle the tab should be confined to 
 869 // caption  - tab's caption 
 870 // active   - whether or not the tab is active 
 871 // out_rect - actual output rectangle 
 872 // x_extent - the advance x; where the next tab should start 
 874 void wxAuiSimpleTabArt::DrawTab(wxDC
& dc
, 
 876                                 const wxAuiNotebookPage
& page
, 
 877                                 const wxRect
& in_rect
, 
 878                                 int close_button_state
, 
 879                                 wxRect
* out_tab_rect
, 
 880                                 wxRect
* out_button_rect
, 
 883     wxCoord normal_textx
, normal_texty
; 
 884     wxCoord selected_textx
, selected_texty
; 
 885     wxCoord textx
, texty
; 
 887     // if the caption is empty, measure some temporary text 
 888     wxString caption 
= page
.caption
; 
 892     dc
.SetFont(m_selected_font
); 
 893     dc
.GetTextExtent(caption
, &selected_textx
, &selected_texty
); 
 895     dc
.SetFont(m_normal_font
); 
 896     dc
.GetTextExtent(caption
, &normal_textx
, &normal_texty
); 
 898     // figure out the size of the tab 
 899     wxSize tab_size 
= GetTabSize(dc
, 
 907     wxCoord tab_height 
= tab_size
.y
; 
 908     wxCoord tab_width 
= tab_size
.x
; 
 909     wxCoord tab_x 
= in_rect
.x
; 
 910     wxCoord tab_y 
= in_rect
.y 
+ in_rect
.height 
- tab_height
; 
 912     caption 
= page
.caption
; 
 914     // select pen, brush and font for the tab to be drawn 
 918         dc
.SetPen(m_selected_bkpen
); 
 919         dc
.SetBrush(m_selected_bkbrush
); 
 920         dc
.SetFont(m_selected_font
); 
 921         textx 
= selected_textx
; 
 922         texty 
= selected_texty
; 
 926         dc
.SetPen(m_normal_bkpen
); 
 927         dc
.SetBrush(m_normal_bkbrush
); 
 928         dc
.SetFont(m_normal_font
); 
 929         textx 
= normal_textx
; 
 930         texty 
= normal_texty
; 
 938     points
[0].y 
= tab_y 
+ tab_height 
- 1; 
 939     points
[1].x 
= tab_x 
+ tab_height 
- 3; 
 940     points
[1].y 
= tab_y 
+ 2; 
 941     points
[2].x 
= tab_x 
+ tab_height 
+ 3; 
 943     points
[3].x 
= tab_x 
+ tab_width 
- 2; 
 945     points
[4].x 
= tab_x 
+ tab_width
; 
 946     points
[4].y 
= tab_y 
+ 2; 
 947     points
[5].x 
= tab_x 
+ tab_width
; 
 948     points
[5].y 
= tab_y 
+ tab_height 
- 1; 
 949     points
[6] = points
[0]; 
 951     dc
.SetClippingRegion(in_rect
); 
 953     dc
.DrawPolygon(WXSIZEOF(points
) - 1, points
); 
 955     dc
.SetPen(*wxGREY_PEN
); 
 957     //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points); 
 958     dc
.DrawLines(WXSIZEOF(points
), points
); 
 963     int close_button_width 
= 0; 
 964     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
 966         close_button_width 
= m_active_close_bmp
.GetWidth(); 
 967         text_offset 
= tab_x 
+ (tab_height
/2) + ((tab_width
-close_button_width
)/2) - (textx
/2); 
 971         text_offset 
= tab_x 
+ (tab_height
/3) + (tab_width
/2) - (textx
/2); 
 974     // set minimum text offset 
 975     if (text_offset 
< tab_x 
+ tab_height
) 
 976         text_offset 
= tab_x 
+ tab_height
; 
 978     // chop text if necessary 
 979     wxString draw_text 
= wxAuiChopText(dc
, 
 981                           tab_width 
- (text_offset
-tab_x
) - close_button_width
); 
 984     dc
.DrawText(draw_text
, 
 986                  (tab_y 
+ tab_height
)/2 - (texty
/2) + 1); 
 989     // draw close button if necessary 
 990     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
 994             bmp 
= m_active_close_bmp
; 
 996             bmp 
= m_disabled_close_bmp
; 
 998         wxRect 
rect(tab_x 
+ tab_width 
- close_button_width 
- 1, 
 999                     tab_y 
+ (tab_height
/2) - (bmp
.GetHeight()/2) + 1, 
1002         DrawButtons(dc
, rect
, bmp
, *wxWHITE
, close_button_state
); 
1004         *out_button_rect 
= rect
; 
1008     *out_tab_rect 
= wxRect(tab_x
, tab_y
, tab_width
, tab_height
); 
1010     dc
.DestroyClippingRegion(); 
1013 int wxAuiSimpleTabArt::GetIndentSize() 
1018 wxSize 
wxAuiSimpleTabArt::GetTabSize(wxDC
& dc
, 
1019                                      wxWindow
* WXUNUSED(wnd
), 
1020                                      const wxString
& caption
, 
1021                                      const wxBitmap
& WXUNUSED(bitmap
), 
1022                                      bool WXUNUSED(active
), 
1023                                      int close_button_state
, 
1026     wxCoord measured_textx
, measured_texty
; 
1028     dc
.SetFont(m_measuring_font
); 
1029     dc
.GetTextExtent(caption
, &measured_textx
, &measured_texty
); 
1031     wxCoord tab_height 
= measured_texty 
+ 4; 
1032     wxCoord tab_width 
= measured_textx 
+ tab_height 
+ 5; 
1034     if (close_button_state 
!= wxAUI_BUTTON_STATE_HIDDEN
) 
1035         tab_width 
+= m_active_close_bmp
.GetWidth(); 
1037     if (m_flags 
& wxAUI_NB_TAB_FIXED_WIDTH
) 
1039         tab_width 
= m_fixed_tab_width
; 
1042     *x_extent 
= tab_width 
- (tab_height
/2) - 1; 
1044     return wxSize(tab_width
, tab_height
); 
1048 void wxAuiSimpleTabArt::DrawButton(wxDC
& dc
, 
1049                                    wxWindow
* WXUNUSED(wnd
), 
1050                                    const wxRect
& in_rect
, 
1061         case wxAUI_BUTTON_CLOSE
: 
1062             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
1063                 bmp 
= m_disabled_close_bmp
; 
1065                 bmp 
= m_active_close_bmp
; 
1067         case wxAUI_BUTTON_LEFT
: 
1068             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
1069                 bmp 
= m_disabled_left_bmp
; 
1071                 bmp 
= m_active_left_bmp
; 
1073         case wxAUI_BUTTON_RIGHT
: 
1074             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
1075                 bmp 
= m_disabled_right_bmp
; 
1077                 bmp 
= m_active_right_bmp
; 
1079         case wxAUI_BUTTON_WINDOWLIST
: 
1080             if (button_state 
& wxAUI_BUTTON_STATE_DISABLED
) 
1081                 bmp 
= m_disabled_windowlist_bmp
; 
1083                 bmp 
= m_active_windowlist_bmp
; 
1092     if (orientation 
== wxLEFT
) 
1094         rect
.SetX(in_rect
.x
); 
1095         rect
.SetY(((in_rect
.y 
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2)); 
1096         rect
.SetWidth(bmp
.GetWidth()); 
1097         rect
.SetHeight(bmp
.GetHeight()); 
1101         rect 
= wxRect(in_rect
.x 
+ in_rect
.width 
- bmp
.GetWidth(), 
1102                       ((in_rect
.y 
+ in_rect
.height
)/2) - (bmp
.GetHeight()/2), 
1103                       bmp
.GetWidth(), bmp
.GetHeight()); 
1107     DrawButtons(dc
, rect
, bmp
, *wxWHITE
, button_state
); 
1113 int wxAuiSimpleTabArt::ShowDropDown(wxWindow
* wnd
, 
1114                                     const wxAuiNotebookPageArray
& pages
, 
1119     size_t i
, count 
= pages
.GetCount(); 
1120     for (i 
= 0; i 
< count
; ++i
) 
1122         const wxAuiNotebookPage
& page 
= pages
.Item(i
); 
1123         menuPopup
.AppendCheckItem(1000+i
, page
.caption
); 
1126     if (active_idx 
!= -1) 
1128         menuPopup
.Check(1000+active_idx
, true); 
1131     // find out where to put the popup menu of window 
1132     // items.  Subtract 100 for now to center the menu 
1133     // a bit, until a better mechanism can be implemented 
1134     wxPoint pt 
= ::wxGetMousePosition(); 
1135     pt 
= wnd
->ScreenToClient(pt
); 
1141     // find out the screen coordinate at the bottom of the tab ctrl 
1142     wxRect cli_rect 
= wnd
->GetClientRect(); 
1143     pt
.y 
= cli_rect
.y 
+ cli_rect
.height
; 
1145     wxAuiCommandCapture
* cc 
= new wxAuiCommandCapture
; 
1146     wnd
->PushEventHandler(cc
); 
1147     wnd
->PopupMenu(&menuPopup
, pt
); 
1148     int command 
= cc
->GetCommandId(); 
1149     wnd
->PopEventHandler(true); 
1151     if (command 
>= 1000) 
1152         return command
-1000; 
1157 int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow
* wnd
, 
1158                                           const wxAuiNotebookPageArray
& WXUNUSED(pages
), 
1159                                           const wxSize
& WXUNUSED(required_bmp_size
)) 
1162     dc
.SetFont(m_measuring_font
); 
1164     wxSize s 
= GetTabSize(dc
, 
1169                           wxAUI_BUTTON_STATE_HIDDEN
, 
1174 void wxAuiSimpleTabArt::SetNormalFont(const wxFont
& font
) 
1176     m_normal_font 
= font
; 
1179 void wxAuiSimpleTabArt::SetSelectedFont(const wxFont
& font
) 
1181     m_selected_font 
= font
; 
1184 void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont
& font
) 
1186     m_measuring_font 
= font
; 
1192 // -- wxAuiTabContainer class implementation -- 
1195 // wxAuiTabContainer is a class which contains information about each 
1196 // tab.  It also can render an entire tab control to a specified DC. 
1197 // It's not a window class itself, because this code will be used by 
1198 // the wxFrameMananger, where it is disadvantageous to have separate 
1199 // windows for each tab control in the case of "docked tabs" 
1201 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window 
1202 // which can be used as a tab control in the normal sense. 
1205 wxAuiTabContainer::wxAuiTabContainer() 
1209     m_art 
= new wxAuiDefaultTabArt
; 
1211     AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
); 
1212     AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
); 
1213     AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
); 
1214     AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
); 
1217 wxAuiTabContainer::~wxAuiTabContainer() 
1222 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
) 
1229         m_art
->SetFlags(m_flags
); 
1233 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const 
1238 void wxAuiTabContainer::SetFlags(unsigned int flags
) 
1242     // check for new close button settings 
1243     RemoveButton(wxAUI_BUTTON_LEFT
); 
1244     RemoveButton(wxAUI_BUTTON_RIGHT
); 
1245     RemoveButton(wxAUI_BUTTON_WINDOWLIST
); 
1246     RemoveButton(wxAUI_BUTTON_CLOSE
); 
1249     if (flags 
& wxAUI_NB_SCROLL_BUTTONS
) 
1251         AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
); 
1252         AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
); 
1255     if (flags 
& wxAUI_NB_WINDOWLIST_BUTTON
) 
1257         AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
); 
1260     if (flags 
& wxAUI_NB_CLOSE_BUTTON
) 
1262         AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
); 
1267         m_art
->SetFlags(m_flags
); 
1271 unsigned int wxAuiTabContainer::GetFlags() const 
1277 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
) 
1279     m_art
->SetNormalFont(font
); 
1282 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
) 
1284     m_art
->SetSelectedFont(font
); 
1287 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
) 
1289     m_art
->SetMeasuringFont(font
); 
1292 void wxAuiTabContainer::SetRect(const wxRect
& rect
) 
1298         m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount()); 
1302 bool wxAuiTabContainer::AddPage(wxWindow
* page
, 
1303                                 const wxAuiNotebookPage
& info
) 
1305     wxAuiNotebookPage page_info
; 
1307     page_info
.window 
= page
; 
1309     m_pages
.Add(page_info
); 
1311     // let the art provider know how many pages we have 
1314         m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
1320 bool wxAuiTabContainer::InsertPage(wxWindow
* page
, 
1321                                    const wxAuiNotebookPage
& info
, 
1324     wxAuiNotebookPage page_info
; 
1326     page_info
.window 
= page
; 
1328     if (idx 
>= m_pages
.GetCount()) 
1329         m_pages
.Add(page_info
); 
1331         m_pages
.Insert(page_info
, idx
); 
1333     // let the art provider know how many pages we have 
1336         m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
1342 bool wxAuiTabContainer::MovePage(wxWindow
* page
, 
1345     int idx 
= GetIdxFromWindow(page
); 
1349     // get page entry, make a copy of it 
1350     wxAuiNotebookPage p 
= GetPage(idx
); 
1352     // remove old page entry 
1355     // insert page where it should be 
1356     InsertPage(page
, p
, new_idx
); 
1361 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
) 
1363     size_t i
, page_count 
= m_pages
.GetCount(); 
1364     for (i 
= 0; i 
< page_count
; ++i
) 
1366         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1367         if (page
.window 
== wnd
) 
1369             m_pages
.RemoveAt(i
); 
1371             // let the art provider know how many pages we have 
1374                 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
1384 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
) 
1388     size_t i
, page_count 
= m_pages
.GetCount(); 
1389     for (i 
= 0; i 
< page_count
; ++i
) 
1391         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1392         if (page
.window 
== wnd
) 
1399             page
.active 
= false; 
1406 void wxAuiTabContainer::SetNoneActive() 
1408     size_t i
, page_count 
= m_pages
.GetCount(); 
1409     for (i 
= 0; i 
< page_count
; ++i
) 
1411         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1412         page
.active 
= false; 
1416 bool wxAuiTabContainer::SetActivePage(size_t page
) 
1418     if (page 
>= m_pages
.GetCount()) 
1421     return SetActivePage(m_pages
.Item(page
).window
); 
1424 int wxAuiTabContainer::GetActivePage() const 
1426     size_t i
, page_count 
= m_pages
.GetCount(); 
1427     for (i 
= 0; i 
< page_count
; ++i
) 
1429         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1437 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const 
1439     if (idx 
>= m_pages
.GetCount()) 
1442     return m_pages
[idx
].window
; 
1445 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const 
1447     const size_t page_count 
= m_pages
.GetCount(); 
1448     for ( size_t i 
= 0; i 
< page_count
; ++i 
) 
1450         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1451         if (page
.window 
== wnd
) 
1457 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) 
1459     wxASSERT_MSG(idx 
< m_pages
.GetCount(), wxT("Invalid Page index")); 
1461     return m_pages
[idx
]; 
1464 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const 
1466     wxASSERT_MSG(idx 
< m_pages
.GetCount(), wxT("Invalid Page index")); 
1468     return m_pages
[idx
]; 
1471 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages() 
1476 size_t wxAuiTabContainer::GetPageCount() const 
1478     return m_pages
.GetCount(); 
1481 void wxAuiTabContainer::AddButton(int id
, 
1483                                   const wxBitmap
& normal_bitmap
, 
1484                                   const wxBitmap
& disabled_bitmap
) 
1486     wxAuiTabContainerButton button
; 
1488     button
.bitmap 
= normal_bitmap
; 
1489     button
.dis_bitmap 
= disabled_bitmap
; 
1490     button
.location 
= location
; 
1491     button
.cur_state 
= wxAUI_BUTTON_STATE_NORMAL
; 
1493     m_buttons
.Add(button
); 
1496 void wxAuiTabContainer::RemoveButton(int id
) 
1498     size_t i
, button_count 
= m_buttons
.GetCount(); 
1500     for (i 
= 0; i 
< button_count
; ++i
) 
1502         if (m_buttons
.Item(i
).id 
== id
) 
1504             m_buttons
.RemoveAt(i
); 
1512 size_t wxAuiTabContainer::GetTabOffset() const 
1514     return m_tab_offset
; 
1517 void wxAuiTabContainer::SetTabOffset(size_t offset
) 
1519     m_tab_offset 
= offset
; 
1525 // Render() renders the tab catalog to the specified DC 
1526 // It is a virtual function and can be overridden to 
1527 // provide custom drawing capabilities 
1528 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
) 
1530     if (!raw_dc 
|| !raw_dc
->IsOk()) 
1536     size_t page_count 
= m_pages
.GetCount(); 
1537     size_t button_count 
= m_buttons
.GetCount(); 
1539     // create off-screen bitmap 
1540     bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight()); 
1541     dc
.SelectObject(bmp
); 
1546     // find out if size of tabs is larger than can be 
1547     // afforded on screen 
1548     int total_width 
= 0; 
1549     int visible_width 
= 0; 
1550     for (i 
= 0; i 
< page_count
; ++i
) 
1552         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1554         // determine if a close button is on this tab 
1555         bool close_button 
= false; 
1556         if ((m_flags 
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 || 
1557             ((m_flags 
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
)) 
1559             close_button 
= true; 
1564         wxSize size 
= m_art
->GetTabSize(dc
, 
1570                               wxAUI_BUTTON_STATE_NORMAL 
: 
1571                               wxAUI_BUTTON_STATE_HIDDEN
, 
1574         if (i
+1 < page_count
) 
1575             total_width 
+= x_extent
; 
1577             total_width 
+= size
.x
; 
1579         if (i 
>= m_tab_offset
) 
1581             if (i
+1 < page_count
) 
1582                 visible_width 
+= x_extent
; 
1584                 visible_width 
+= size
.x
; 
1588     if (total_width 
> m_rect
.GetWidth() || m_tab_offset 
!= 0) 
1590         // show left/right buttons 
1591         for (i 
= 0; i 
< button_count
; ++i
) 
1593             wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
1594             if (button
.id 
== wxAUI_BUTTON_LEFT 
|| 
1595                 button
.id 
== wxAUI_BUTTON_RIGHT
) 
1597                 button
.cur_state 
&= ~wxAUI_BUTTON_STATE_HIDDEN
; 
1603         // hide left/right buttons 
1604         for (i 
= 0; i 
< button_count
; ++i
) 
1606             wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
1607             if (button
.id 
== wxAUI_BUTTON_LEFT 
|| 
1608                 button
.id 
== wxAUI_BUTTON_RIGHT
) 
1610                 button
.cur_state 
|= wxAUI_BUTTON_STATE_HIDDEN
; 
1615     // determine whether left button should be enabled 
1616     for (i 
= 0; i 
< button_count
; ++i
) 
1618         wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
1619         if (button
.id 
== wxAUI_BUTTON_LEFT
) 
1621             if (m_tab_offset 
== 0) 
1622                 button
.cur_state 
|= wxAUI_BUTTON_STATE_DISABLED
; 
1624                 button
.cur_state 
&= ~wxAUI_BUTTON_STATE_DISABLED
; 
1626         if (button
.id 
== wxAUI_BUTTON_RIGHT
) 
1628             if (visible_width 
< m_rect
.GetWidth() - ((int)button_count
*16)) 
1629                 button
.cur_state 
|= wxAUI_BUTTON_STATE_DISABLED
; 
1631                 button
.cur_state 
&= ~wxAUI_BUTTON_STATE_DISABLED
; 
1638     m_art
->DrawBackground(dc
, wnd
, m_rect
); 
1641     int left_buttons_width 
= 0; 
1642     int right_buttons_width 
= 0; 
1646     // draw the buttons on the right side 
1647     offset 
= m_rect
.x 
+ m_rect
.width
; 
1648     for (i 
= 0; i 
< button_count
; ++i
) 
1650         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
1652         if (button
.location 
!= wxRIGHT
) 
1654         if (button
.cur_state 
& wxAUI_BUTTON_STATE_HIDDEN
) 
1657         wxRect button_rect 
= m_rect
; 
1658         button_rect
.SetY(1); 
1659         button_rect
.SetWidth(offset
); 
1661         m_art
->DrawButton(dc
, 
1669         offset 
-= button
.rect
.GetWidth(); 
1670         right_buttons_width 
+= button
.rect
.GetWidth(); 
1677     // draw the buttons on the left side 
1679     for (i 
= 0; i 
< button_count
; ++i
) 
1681         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
1683         if (button
.location 
!= wxLEFT
) 
1685         if (button
.cur_state 
& wxAUI_BUTTON_STATE_HIDDEN
) 
1688         wxRect 
button_rect(offset
, 1, 1000, m_rect
.height
); 
1690         m_art
->DrawButton(dc
, 
1698         offset 
+= button
.rect
.GetWidth(); 
1699         left_buttons_width 
+= button
.rect
.GetWidth(); 
1702     offset 
= left_buttons_width
; 
1705         offset 
+= m_art
->GetIndentSize(); 
1708     // prepare the tab-close-button array 
1709     // make sure tab button entries which aren't used are marked as hidden 
1710     for (i 
= page_count
; i 
< m_tab_close_buttons
.GetCount(); ++i
) 
1711         m_tab_close_buttons
.Item(i
).cur_state 
= wxAUI_BUTTON_STATE_HIDDEN
; 
1713     // make sure there are enough tab button entries to accommodate all tabs 
1714     while (m_tab_close_buttons
.GetCount() < page_count
) 
1716         wxAuiTabContainerButton tempbtn
; 
1717         tempbtn
.id 
= wxAUI_BUTTON_CLOSE
; 
1718         tempbtn
.location 
= wxCENTER
; 
1719         tempbtn
.cur_state 
= wxAUI_BUTTON_STATE_HIDDEN
; 
1720         m_tab_close_buttons
.Add(tempbtn
); 
1724     // buttons before the tab offset must be set to hidden 
1725     for (i 
= 0; i 
< m_tab_offset
; ++i
) 
1727         m_tab_close_buttons
.Item(i
).cur_state 
= wxAUI_BUTTON_STATE_HIDDEN
; 
1733     size_t active 
= 999; 
1734     int active_offset 
= 0; 
1738     wxRect rect 
= m_rect
; 
1740     rect
.height 
= m_rect
.height
; 
1742     for (i 
= m_tab_offset
; i 
< page_count
; ++i
) 
1744         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1745         wxAuiTabContainerButton
& tab_button 
= m_tab_close_buttons
.Item(i
); 
1747         // determine if a close button is on this tab 
1748         bool close_button 
= false; 
1749         if ((m_flags 
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 || 
1750             ((m_flags 
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
)) 
1752             close_button 
= true; 
1753             if (tab_button
.cur_state 
== wxAUI_BUTTON_STATE_HIDDEN
) 
1755                 tab_button
.id 
= wxAUI_BUTTON_CLOSE
; 
1756                 tab_button
.cur_state 
= wxAUI_BUTTON_STATE_NORMAL
; 
1757                 tab_button
.location 
= wxCENTER
; 
1762             tab_button
.cur_state 
= wxAUI_BUTTON_STATE_HIDDEN
; 
1766         rect
.width 
= m_rect
.width 
- right_buttons_width 
- offset 
- 2; 
1768         if (rect
.width 
<= 0) 
1775                        tab_button
.cur_state
, 
1783             active_offset 
= offset
; 
1791     // make sure to deactivate buttons which are off the screen to the right 
1792     for (++i
; i 
< m_tab_close_buttons
.GetCount(); ++i
) 
1794         m_tab_close_buttons
.Item(i
).cur_state 
= wxAUI_BUTTON_STATE_HIDDEN
; 
1798     // draw the active tab again so it stands in the foreground 
1799     if (active 
>= m_tab_offset 
&& active 
< m_pages
.GetCount()) 
1801         wxAuiNotebookPage
& page 
= m_pages
.Item(active
); 
1803         wxAuiTabContainerButton
& tab_button 
= m_tab_close_buttons
.Item(active
); 
1805         // determine if a close button is on this tab 
1806         bool close_button 
= false; 
1807         if ((m_flags 
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 || 
1808             ((m_flags 
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
)) 
1810             close_button 
= true; 
1813         rect
.x 
= active_offset
; 
1818                        tab_button
.cur_state
, 
1825     raw_dc
->Blit(m_rect
.x
, m_rect
.y
, 
1826                  m_rect
.GetWidth(), m_rect
.GetHeight(), 
1831 // TabHitTest() tests if a tab was hit, passing the window pointer 
1832 // back if that condition was fulfilled.  The function returns 
1833 // true if a tab was hit, otherwise false 
1834 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const 
1836     if (!m_rect
.Contains(x
,y
)) 
1839     wxAuiTabContainerButton
* btn 
= NULL
; 
1840     if (ButtonHitTest(x
, y
, &btn
)) 
1842         if (m_buttons
.Index(*btn
) != wxNOT_FOUND
) 
1846     size_t i
, page_count 
= m_pages
.GetCount(); 
1848     for (i 
= m_tab_offset
; i 
< page_count
; ++i
) 
1850         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
1851         if (page
.rect
.Contains(x
,y
)) 
1862 // ButtonHitTest() tests if a button was hit. The function returns 
1863 // true if a button was hit, otherwise false 
1864 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
, 
1865                                       wxAuiTabContainerButton
** hit
) const 
1867     if (!m_rect
.Contains(x
,y
)) 
1870     size_t i
, button_count
; 
1873     button_count 
= m_buttons
.GetCount(); 
1874     for (i 
= 0; i 
< button_count
; ++i
) 
1876         wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
1877         if (button
.rect
.Contains(x
,y
) && 
1878             !(button
.cur_state 
& (wxAUI_BUTTON_STATE_HIDDEN 
| 
1879                                    wxAUI_BUTTON_STATE_DISABLED
))) 
1887     button_count 
= m_tab_close_buttons
.GetCount(); 
1888     for (i 
= 0; i 
< button_count
; ++i
) 
1890         wxAuiTabContainerButton
& button 
= m_tab_close_buttons
.Item(i
); 
1891         if (button
.rect
.Contains(x
,y
) && 
1892             !(button
.cur_state 
& (wxAUI_BUTTON_STATE_HIDDEN 
| 
1893                                    wxAUI_BUTTON_STATE_DISABLED
))) 
1906 // the utility function ShowWnd() is the same as show, 
1907 // except it handles wxAuiMDIChildFrame windows as well, 
1908 // as the Show() method on this class is "unplugged" 
1909 static void ShowWnd(wxWindow
* wnd
, bool show
) 
1911     if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
))) 
1913         wxAuiMDIChildFrame
* cf 
= (wxAuiMDIChildFrame
*)wnd
; 
1923 // DoShowHide() this function shows the active window, then 
1924 // hides all of the other windows (in that order) 
1925 void wxAuiTabContainer::DoShowHide() 
1927     wxAuiNotebookPageArray
& pages 
= GetPages(); 
1928     size_t i
, page_count 
= pages
.GetCount(); 
1930     // show new active page first 
1931     for (i 
= 0; i 
< page_count
; ++i
) 
1933         wxAuiNotebookPage
& page 
= pages
.Item(i
); 
1936             ShowWnd(page
.window
, true); 
1941     // hide all other pages 
1942     for (i 
= 0; i 
< page_count
; ++i
) 
1944         wxAuiNotebookPage
& page 
= pages
.Item(i
); 
1946             ShowWnd(page
.window
, false); 
1955 // -- wxAuiTabCtrl class implementation -- 
1959 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
) 
1960     EVT_PAINT(wxAuiTabCtrl::OnPaint
) 
1961     EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
) 
1962     EVT_SIZE(wxAuiTabCtrl::OnSize
) 
1963     EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
) 
1964     EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown
) 
1965     EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
) 
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         wxAuiNotebookEvent 
evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, m_windowId
); 
2058         evt
.SetSelection(GetIdxFromWindow(m_click_tab
)); 
2059         evt
.SetOldSelection(evt
.GetSelection()); 
2060         evt
.SetEventObject(this); 
2061         GetEventHandler()->ProcessEvent(evt
); 
2065     if (m_pressed_button
) 
2067         // make sure we're still clicking the button 
2068         wxAuiTabContainerButton
* button 
= NULL
; 
2069         if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
)) 
2072         if (button 
!= m_pressed_button
) 
2074             m_pressed_button 
= NULL
; 
2081         if (!(m_pressed_button
->cur_state 
& wxAUI_BUTTON_STATE_DISABLED
)) 
2083             wxAuiNotebookEvent 
evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, m_windowId
); 
2084             evt
.SetInt(m_pressed_button
->id
); 
2085             evt
.SetEventObject(this); 
2086             GetEventHandler()->ProcessEvent(evt
); 
2089         m_pressed_button 
= NULL
; 
2092     m_click_pt 
= wxDefaultPosition
; 
2093     m_is_dragging 
= false; 
2097 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
) 
2099     wxPoint pos 
= evt
.GetPosition(); 
2101     // check if the mouse is hovering above a button 
2102     wxAuiTabContainerButton
* button
; 
2103     if (ButtonHitTest(pos
.x
, pos
.y
, &button
)) 
2105         if (m_hover_button 
&& button 
!= m_hover_button
) 
2107             m_hover_button
->cur_state 
= wxAUI_BUTTON_STATE_NORMAL
; 
2108             m_hover_button 
= NULL
; 
2113         if (button
->cur_state 
!= wxAUI_BUTTON_STATE_HOVER
) 
2115             button
->cur_state 
= wxAUI_BUTTON_STATE_HOVER
; 
2118             m_hover_button 
= button
; 
2126             m_hover_button
->cur_state 
= wxAUI_BUTTON_STATE_NORMAL
; 
2127             m_hover_button 
= NULL
; 
2134     if (!evt
.LeftIsDown() || m_click_pt 
== wxDefaultPosition
) 
2139         wxAuiNotebookEvent 
evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, m_windowId
); 
2140         evt
.SetSelection(GetIdxFromWindow(m_click_tab
)); 
2141         evt
.SetOldSelection(evt
.GetSelection()); 
2142         evt
.SetEventObject(this); 
2143         GetEventHandler()->ProcessEvent(evt
); 
2148     int drag_x_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
); 
2149     int drag_y_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
); 
2151     if (abs(pos
.x 
- m_click_pt
.x
) > drag_x_threshold 
|| 
2152         abs(pos
.y 
- m_click_pt
.y
) > drag_y_threshold
) 
2154         wxAuiNotebookEvent 
evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
); 
2155         evt
.SetSelection(GetIdxFromWindow(m_click_tab
)); 
2156         evt
.SetOldSelection(evt
.GetSelection()); 
2157         evt
.SetEventObject(this); 
2158         GetEventHandler()->ProcessEvent(evt
); 
2160         m_is_dragging 
= true; 
2164 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
)) 
2168         m_hover_button
->cur_state 
= wxAUI_BUTTON_STATE_NORMAL
; 
2169         m_hover_button 
= NULL
; 
2175 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
) 
2177     int button 
= event
.GetInt(); 
2179     if (button 
== wxAUI_BUTTON_LEFT 
|| button 
== wxAUI_BUTTON_RIGHT
) 
2181         if (button 
== wxAUI_BUTTON_LEFT
) 
2183             if (GetTabOffset() > 0) 
2185                 SetTabOffset(GetTabOffset()-1); 
2192             SetTabOffset(GetTabOffset()+1); 
2197      else if (button 
== wxAUI_BUTTON_WINDOWLIST
) 
2199         int idx 
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage()); 
2203             wxAuiNotebookEvent 
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
2204             e
.SetSelection(idx
); 
2205             e
.SetOldSelection(GetActivePage()); 
2206             e
.SetEventObject(this); 
2207             GetEventHandler()->ProcessEvent(e
); 
2216 // wxTabFrame is an interesting case.  It's important that all child pages 
2217 // of the multi-notebook control are all actually children of that control 
2218 // (and not grandchildren).  wxTabFrame facilitates this.  There is one 
2219 // instance of wxTabFrame for each tab control inside the multi-notebook. 
2220 // It's important to know that wxTabFrame is not a real window, but it merely 
2221 // used to capture the dimensions/positioning of the internal tab control and 
2222 // it's managed page windows 
2224 class wxTabFrame 
: public wxWindow
 
2231         m_rect 
= wxRect(0,0,200,200); 
2232         m_tab_ctrl_height 
= 20; 
2240     void SetTabCtrlHeight(int h
) 
2242         m_tab_ctrl_height 
= h
; 
2245     void DoSetSize(int x
, int y
, 
2246                    int width
, int height
, 
2247                    int WXUNUSED(sizeFlags 
= wxSIZE_AUTO
)) 
2249         m_rect 
= wxRect(x
, y
, width
, height
); 
2253     void DoGetClientSize(int* x
, int* y
) const 
2259     bool Show( bool WXUNUSED(show 
= true) ) { return false; } 
2266         m_tab_rect 
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
); 
2267         m_tabs
->SetSize(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tab_ctrl_height
); 
2268         m_tabs
->SetRect(wxRect(0, 0, m_rect
.width
, m_tab_ctrl_height
)); 
2272         wxAuiNotebookPageArray
& pages 
= m_tabs
->GetPages(); 
2273         size_t i
, page_count 
= pages
.GetCount(); 
2275         for (i 
= 0; i 
< page_count
; ++i
) 
2277             wxAuiNotebookPage
& page 
= pages
.Item(i
); 
2278             page
.window
->SetSize(m_rect
.x
, m_rect
.y 
+ m_tab_ctrl_height
, 
2279                                  m_rect
.width
, m_rect
.height 
- m_tab_ctrl_height
); 
2281             if (page
.window
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
))) 
2283                 wxAuiMDIChildFrame
* wnd 
= (wxAuiMDIChildFrame
*)page
.window
; 
2284                 wnd
->ApplyMDIChildFrameRect(); 
2289     void DoGetSize(int* x
, int* y
) const 
2292             *x 
= m_rect
.GetWidth(); 
2294             *y 
= m_rect
.GetHeight(); 
2306     wxAuiTabCtrl
* m_tabs
; 
2307     int m_tab_ctrl_height
; 
2311 const int wxAuiBaseTabCtrlId 
= 5380; 
2314 // -- wxAuiNotebook class implementation -- 
2316 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
) 
2317     EVT_SIZE(wxAuiNotebook::OnSize
) 
2318     EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocus
) 
2319     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
2320                       wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, 
2321                       wxAuiNotebook::OnTabClicked
) 
2322     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
2323                       wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG
, 
2324                       wxAuiNotebook::OnTabBeginDrag
) 
2325     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
2326                       wxEVT_COMMAND_AUINOTEBOOK_END_DRAG
, 
2327                       wxAuiNotebook::OnTabEndDrag
) 
2328     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
2329                       wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION
, 
2330                       wxAuiNotebook::OnTabDragMotion
) 
2331     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
2332                       wxEVT_COMMAND_AUINOTEBOOK_BUTTON
, 
2333                       wxAuiNotebook::OnTabButton
) 
2336 wxAuiNotebook::wxAuiNotebook() 
2339     m_tab_id_counter 
= wxAuiBaseTabCtrlId
; 
2341     m_tab_ctrl_height 
= 20; 
2342     m_requested_bmp_size 
= wxDefaultSize
; 
2343     m_requested_tabctrl_height 
= -1; 
2346 wxAuiNotebook::wxAuiNotebook(wxWindow 
*parent
, 
2350                              long style
) : wxControl(parent
, id
, pos
, size
, style
) 
2353     m_requested_bmp_size 
= wxDefaultSize
; 
2354     m_requested_tabctrl_height 
= -1; 
2355     InitNotebook(style
); 
2358 bool wxAuiNotebook::Create(wxWindow
* parent
, 
2364     if (!wxControl::Create(parent
, id
, pos
, size
, style
)) 
2367     InitNotebook(style
); 
2372 // InitNotebook() contains common initialization 
2373 // code called by all constructors 
2374 void wxAuiNotebook::InitNotebook(long style
) 
2377     m_tab_id_counter 
= wxAuiBaseTabCtrlId
; 
2379     m_flags 
= (unsigned int)style
; 
2380     m_tab_ctrl_height 
= 20; 
2382     m_normal_font 
= *wxNORMAL_FONT
; 
2383     m_selected_font 
= *wxNORMAL_FONT
; 
2384     m_selected_font
.SetWeight(wxBOLD
); 
2386     SetArtProvider(new wxAuiDefaultTabArt
); 
2388     m_dummy_wnd 
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0)); 
2389     m_dummy_wnd
->SetSize(200, 200); 
2390     m_dummy_wnd
->Show(false); 
2392     m_mgr
.SetManagedWindow(this); 
2393     m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
); 
2394     m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint 
2396     m_mgr
.AddPane(m_dummy_wnd
, 
2397               wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false)); 
2402 wxAuiNotebook::~wxAuiNotebook() 
2407 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
) 
2409     m_tabs
.SetArtProvider(art
); 
2411     UpdateTabCtrlHeight(); 
2414 // SetTabCtrlHeight() is the highest-level override of the 
2415 // tab height.  A call to this function effectively enforces a 
2416 // specified tab ctrl height, overriding all other considerations, 
2417 // such as text or bitmap height.  It overrides any call to 
2418 // SetUniformBitmapSize().  Specifying a height of -1 reverts 
2419 // any previous call and returns to the default behavior 
2421 void wxAuiNotebook::SetTabCtrlHeight(int height
) 
2423     m_requested_tabctrl_height 
= height
; 
2425     // if window is already initialized, recalculate the tab height 
2428         UpdateTabCtrlHeight(); 
2433 // SetUniformBitmapSize() ensures that all tabs will have 
2434 // the same height, even if some tabs don't have bitmaps 
2435 // Passing wxDefaultSize to this function will instruct 
2436 // the control to use dynamic tab height-- so when a tab 
2437 // with a large bitmap is added, the tab ctrl's height will 
2438 // automatically increase to accommodate the bitmap 
2440 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
) 
2442     m_requested_bmp_size 
= size
; 
2444     // if window is already initialized, recalculate the tab height 
2447         UpdateTabCtrlHeight(); 
2451 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant 
2452 // to be used interally 
2453 void wxAuiNotebook::UpdateTabCtrlHeight() 
2455     // get the tab ctrl height we will use 
2456     int height 
= CalculateTabCtrlHeight(); 
2458     // if the tab control height needs to change, update 
2459     // all of our tab controls with the new height 
2460     if (m_tab_ctrl_height 
!= height
) 
2462         wxAuiTabArt
* art 
= m_tabs
.GetArtProvider(); 
2464         m_tab_ctrl_height 
= height
; 
2466         wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2467         size_t i
, pane_count 
= all_panes
.GetCount(); 
2468         for (i 
= 0; i 
< pane_count
; ++i
) 
2470             wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
2471             if (pane
.name 
== wxT("dummy")) 
2473             wxTabFrame
* tab_frame 
= (wxTabFrame
*)pane
.window
; 
2474             wxAuiTabCtrl
* tabctrl 
= tab_frame
->m_tabs
; 
2475             tab_frame
->SetTabCtrlHeight(m_tab_ctrl_height
); 
2476             tabctrl
->SetArtProvider(art
->Clone()); 
2477             tab_frame
->DoSizing(); 
2482 void wxAuiNotebook::UpdateHintWindowSize() 
2484     wxSize size 
= CalculateNewSplitSize(); 
2486     // the placeholder hint window should be set to this size 
2487     wxAuiPaneInfo
& info 
= m_mgr
.GetPane(wxT("dummy")); 
2491         info
.BestSize(size
); 
2492         m_dummy_wnd
->SetSize(size
); 
2497 // calculates the size of the new split 
2498 wxSize 
wxAuiNotebook::CalculateNewSplitSize() 
2500     // count number of tab controls 
2501     int tab_ctrl_count 
= 0; 
2502     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2503     size_t i
, pane_count 
= all_panes
.GetCount(); 
2504     for (i 
= 0; i 
< pane_count
; ++i
) 
2506         wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
2507         if (pane
.name 
== wxT("dummy")) 
2512     wxSize new_split_size
; 
2514     // if there is only one tab control, the first split 
2515     // should happen around the middle 
2516     if (tab_ctrl_count 
< 2) 
2518         new_split_size 
= GetClientSize(); 
2519         new_split_size
.x 
/= 2; 
2520         new_split_size
.y 
/= 2; 
2524         // this is in place of a more complicated calculation 
2525         // that needs to be implemented 
2526         new_split_size 
= wxSize(180,180); 
2529     return new_split_size
; 
2532 int wxAuiNotebook::CalculateTabCtrlHeight() 
2534     // if a fixed tab ctrl height is specified, 
2535     // just return that instead of calculating a 
2537     if (m_requested_tabctrl_height 
!= -1) 
2538         return m_requested_tabctrl_height
; 
2540     // find out new best tab height 
2541     wxAuiTabArt
* art 
= m_tabs
.GetArtProvider(); 
2543     return art
->GetBestTabCtrlSize(this, 
2545                                    m_requested_bmp_size
); 
2549 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const 
2551     return m_tabs
.GetArtProvider(); 
2554 void wxAuiNotebook::SetWindowStyleFlag(long style
) 
2556     wxControl::SetWindowStyleFlag(style
); 
2558     m_flags 
= (unsigned int)style
; 
2560     // if the control is already initialized 
2561     if (m_mgr
.GetManagedWindow() == (wxWindow
*)this) 
2563         // let all of the tab children know about the new style 
2565         wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2566         size_t i
, pane_count 
= all_panes
.GetCount(); 
2567         for (i 
= 0; i 
< pane_count
; ++i
) 
2569             wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
2570             if (pane
.name 
== wxT("dummy")) 
2572             wxTabFrame
* tabframe 
= (wxTabFrame
*)pane
.window
; 
2573             wxAuiTabCtrl
* tabctrl 
= tabframe
->m_tabs
; 
2574             tabctrl
->SetFlags(m_flags
); 
2575             tabframe
->DoSizing(); 
2583 bool wxAuiNotebook::AddPage(wxWindow
* page
, 
2584                             const wxString
& caption
, 
2586                             const wxBitmap
& bitmap
) 
2588     return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
); 
2591 bool wxAuiNotebook::InsertPage(size_t page_idx
, 
2593                                const wxString
& caption
, 
2595                                const wxBitmap
& bitmap
) 
2597     wxAuiNotebookPage info
; 
2599     info
.caption 
= caption
; 
2600     info
.bitmap 
= bitmap
; 
2601     info
.active 
= false; 
2603     // if there are currently no tabs, the first added 
2604     // tab must be active 
2605     if (m_tabs
.GetPageCount() == 0) 
2608     m_tabs
.InsertPage(page
, info
, page_idx
); 
2610     // if that was the first page added, even if 
2611     // select is false, it must become the "current page" 
2612     // (though no select events will be fired) 
2613     if (!select 
&& m_tabs
.GetPageCount() == 1) 
2615         //m_curpage = GetPageIndex(page); 
2617     wxAuiTabCtrl
* active_tabctrl 
= GetActiveTabCtrl(); 
2618     if (page_idx 
>= active_tabctrl
->GetPageCount()) 
2619         active_tabctrl
->AddPage(page
, info
); 
2621         active_tabctrl
->InsertPage(page
, info
, page_idx
); 
2623     UpdateTabCtrlHeight(); 
2625     active_tabctrl
->DoShowHide(); 
2629         SetSelectionToWindow(page
); 
2636 // DeletePage() removes a tab from the multi-notebook, 
2637 // and destroys the window as well 
2638 bool wxAuiNotebook::DeletePage(size_t page_idx
) 
2640     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(page_idx
); 
2642     if (!RemovePage(page_idx
)) 
2645     // actually destroy the window now 
2646     if (wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
))) 
2648         // delete the child frame with pending delete, as is 
2649         // customary with frame windows 
2650         if (!wxPendingDelete
.Member(wnd
)) 
2651             wxPendingDelete
.Append(wnd
); 
2663 // RemovePage() removes a tab from the multi-notebook, 
2664 // but does not destroy the window 
2665 bool wxAuiNotebook::RemovePage(size_t page_idx
) 
2667     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(page_idx
); 
2668     wxWindow
* new_active 
= NULL
; 
2670     // find out which onscreen tab ctrl owns this tab 
2673     if (!FindTab(wnd
, &ctrl
, &ctrl_idx
)) 
2676     // find a new page and set it as active 
2677     int new_idx 
= ctrl_idx
+1; 
2678     if (new_idx 
>= (int)ctrl
->GetPageCount()) 
2679         new_idx 
= ctrl_idx
-1; 
2681     if (new_idx 
>= 0 && new_idx 
< (int)ctrl
->GetPageCount()) 
2683         new_active 
= ctrl
->GetWindowFromIdx(new_idx
); 
2687         // set the active page to the first page that 
2688         // isn't the one being deleted 
2689         size_t i
, page_count 
= m_tabs
.GetPageCount(); 
2690         for (i 
= 0; i 
< page_count
; ++i
) 
2692             wxWindow
* w 
= m_tabs
.GetWindowFromIdx(i
); 
2695                 new_active 
= m_tabs
.GetWindowFromIdx(i
); 
2701     // remove the tab from main catalog 
2702     if (!m_tabs
.RemovePage(wnd
)) 
2705     // remove the tab from the onscreen tab ctrl 
2706     ctrl
->RemovePage(wnd
); 
2709     RemoveEmptyTabFrames(); 
2711     // set new active pane 
2715         SetSelectionToWindow(new_active
); 
2721 // GetPageIndex() returns the index of the page, or -1 if the 
2722 // page could not be located in the notebook 
2723 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const 
2725     return m_tabs
.GetIdxFromWindow(page_wnd
); 
2730 // SetPageText() changes the tab caption of the specified page 
2731 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
) 
2733     if (page_idx 
>= m_tabs
.GetPageCount()) 
2736     // update our own tab catalog 
2737     wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2738     page_info
.caption 
= text
; 
2740     // update what's on screen 
2743     if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
)) 
2745         wxAuiNotebookPage
& info 
= ctrl
->GetPage(ctrl_idx
); 
2746         info
.caption 
= text
; 
2754 // returns the page caption 
2755 wxString 
wxAuiNotebook::GetPageText(size_t page_idx
) const 
2757     if (page_idx 
>= m_tabs
.GetPageCount()) 
2758         return wxEmptyString
; 
2760     // update our own tab catalog 
2761     const wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2762     return page_info
.caption
; 
2765 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
) 
2767     if (page_idx 
>= m_tabs
.GetPageCount()) 
2770     // update our own tab catalog 
2771     wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2772     page_info
.bitmap 
= bitmap
; 
2774     // tab height might have changed 
2775     UpdateTabCtrlHeight(); 
2777     // update what's on screen 
2780     if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
)) 
2782         wxAuiNotebookPage
& info 
= ctrl
->GetPage(ctrl_idx
); 
2783         info
.bitmap 
= bitmap
; 
2791 // returns the page bitmap 
2792 wxBitmap 
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const 
2794     if (page_idx 
>= m_tabs
.GetPageCount()) 
2797     // update our own tab catalog 
2798     const wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2799     return page_info
.bitmap
; 
2802 // GetSelection() returns the index of the currently active page 
2803 int wxAuiNotebook::GetSelection() const 
2808 // SetSelection() sets the currently active page 
2809 size_t wxAuiNotebook::SetSelection(size_t new_page
) 
2811     // don't change the page unless necessary 
2812     if ((int)new_page 
== m_curpage
) 
2815     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(new_page
); 
2819     wxAuiNotebookEvent 
evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
2820     evt
.SetSelection(new_page
); 
2821     evt
.SetOldSelection(m_curpage
); 
2822     evt
.SetEventObject(this); 
2823     if (!GetEventHandler()->ProcessEvent(evt
) || evt
.IsAllowed()) 
2825         int old_curpage 
= m_curpage
; 
2826         m_curpage 
= new_page
; 
2828         // program allows the page change 
2829         evt
.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED
); 
2830         (void)GetEventHandler()->ProcessEvent(evt
); 
2835         if (FindTab(wnd
, &ctrl
, &ctrl_idx
)) 
2837             m_tabs
.SetActivePage(wnd
); 
2839             ctrl
->SetActivePage(ctrl_idx
); 
2846             wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2847             size_t i
, pane_count 
= all_panes
.GetCount(); 
2848             for (i 
= 0; i 
< pane_count
; ++i
) 
2850                 wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
2851                 if (pane
.name 
== wxT("dummy")) 
2853                 wxAuiTabCtrl
* tabctrl 
= ((wxTabFrame
*)pane
.window
)->m_tabs
; 
2854                 if (tabctrl 
!= ctrl
) 
2855                     tabctrl
->SetSelectedFont(m_normal_font
); 
2857                     tabctrl
->SetSelectedFont(m_selected_font
); 
2870 void wxAuiNotebook::SetSelectionToWindow(wxWindow 
*win
) 
2872     const int idx 
= m_tabs
.GetIdxFromWindow(win
); 
2873     wxCHECK_RET( idx 
!= wxNOT_FOUND
, _T("invalid notebook page") ); 
2878 // GetPageCount() returns the total number of 
2879 // pages managed by the multi-notebook 
2880 size_t wxAuiNotebook::GetPageCount() const 
2882     return m_tabs
.GetPageCount(); 
2885 // GetPage() returns the wxWindow pointer of the 
2887 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const 
2889     wxASSERT(page_idx 
< m_tabs
.GetPageCount()); 
2891     return m_tabs
.GetWindowFromIdx(page_idx
); 
2894 // DoSizing() performs all sizing operations in each tab control 
2895 void wxAuiNotebook::DoSizing() 
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         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2904         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2905         tabframe
->DoSizing(); 
2909 // GetActiveTabCtrl() returns the active tab control.  It is 
2910 // called to determine which control gets new windows being added 
2911 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl() 
2913     if (m_curpage 
>= 0 && m_curpage 
< (int)m_tabs
.GetPageCount()) 
2918         // find the tab ctrl with the current page 
2919         if (FindTab(m_tabs
.GetPage(m_curpage
).window
, 
2926     // no current page, just find the first tab ctrl 
2927     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2928     size_t i
, pane_count 
= all_panes
.GetCount(); 
2929     for (i 
= 0; i 
< pane_count
; ++i
) 
2931         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2934         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2935         return tabframe
->m_tabs
; 
2938     // If there is no tabframe at all, create one 
2939     wxTabFrame
* tabframe 
= new wxTabFrame
; 
2940     tabframe
->SetTabCtrlHeight(m_tab_ctrl_height
); 
2941     tabframe
->m_tabs 
= new wxAuiTabCtrl(this, 
2946     tabframe
->m_tabs
->SetFlags(m_flags
); 
2947     tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
2948     m_mgr
.AddPane(tabframe
, 
2949                   wxAuiPaneInfo().Center().CaptionVisible(false)); 
2953     return tabframe
->m_tabs
; 
2956 // FindTab() finds the tab control that currently contains the window as well 
2957 // as the index of the window in the tab control.  It returns true if the 
2958 // window was found, otherwise false. 
2959 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
) 
2961     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2962     size_t i
, pane_count 
= all_panes
.GetCount(); 
2963     for (i 
= 0; i 
< pane_count
; ++i
) 
2965         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2968         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2970         int page_idx 
= tabframe
->m_tabs
->GetIdxFromWindow(page
); 
2973             *ctrl 
= tabframe
->m_tabs
; 
2982 void wxAuiNotebook::Split(size_t page
, int direction
) 
2984     wxSize cli_size 
= GetClientSize(); 
2986     // get the page's window pointer 
2987     wxWindow
* wnd 
= GetPage(page
); 
2991     // notebooks with 1 or less pages can't be split 
2992     if (GetPageCount() < 2) 
2995     // find out which tab control the page currently belongs to 
2996     wxAuiTabCtrl 
*src_tabs
, *dest_tabs
; 
2999     if (!FindTab(wnd
, &src_tabs
, &src_idx
)) 
3001     if (!src_tabs 
|| src_idx 
== -1) 
3004     // choose a split size 
3006     if (GetPageCount() > 2) 
3008         split_size 
= CalculateNewSplitSize(); 
3012         // because there are two panes, always split them 
3014         split_size 
= GetClientSize(); 
3020     // create a new tab frame 
3021     wxTabFrame
* new_tabs 
= new wxTabFrame
; 
3022     new_tabs
->m_rect 
= wxRect(wxPoint(0,0), split_size
); 
3023     new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
); 
3024     new_tabs
->m_tabs 
= new wxAuiTabCtrl(this, 
3029     new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
3030     new_tabs
->m_tabs
->SetFlags(m_flags
); 
3031     dest_tabs 
= new_tabs
->m_tabs
; 
3033     // create a pane info structure with the information 
3034     // about where the pane should be added 
3035     wxAuiPaneInfo pane_info 
= wxAuiPaneInfo().Bottom().CaptionVisible(false); 
3038     if (direction 
== wxLEFT
) 
3041         mouse_pt 
= wxPoint(0, cli_size
.y
/2); 
3043      else if (direction 
== wxRIGHT
) 
3046         mouse_pt 
= wxPoint(cli_size
.x
, cli_size
.y
/2); 
3048      else if (direction 
== wxTOP
) 
3051         mouse_pt 
= wxPoint(cli_size
.x
/2, 0); 
3053      else if (direction 
== wxBOTTOM
) 
3056         mouse_pt 
= wxPoint(cli_size
.x
/2, cli_size
.y
); 
3059     m_mgr
.AddPane(new_tabs
, pane_info
, mouse_pt
); 
3062     // remove the page from the source tabs 
3063     wxAuiNotebookPage page_info 
= src_tabs
->GetPage(src_idx
); 
3064     page_info
.active 
= false; 
3065     src_tabs
->RemovePage(page_info
.window
); 
3066     if (src_tabs
->GetPageCount() > 0) 
3068         src_tabs
->SetActivePage((size_t)0); 
3069         src_tabs
->DoShowHide(); 
3070         src_tabs
->Refresh(); 
3074     // add the page to the destination tabs 
3075     dest_tabs
->InsertPage(page_info
.window
, page_info
, 0); 
3077     if (src_tabs
->GetPageCount() == 0) 
3079         RemoveEmptyTabFrames(); 
3083     dest_tabs
->DoShowHide(); 
3084     dest_tabs
->Refresh(); 
3086     // force the set selection function reset the selection 
3089     // set the active page to the one we just split off 
3090     SetSelectionToPage(page_info
); 
3092     UpdateHintWindowSize(); 
3096 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
) 
3098     UpdateHintWindowSize(); 
3103 void wxAuiNotebook::OnTabClicked(wxCommandEvent
& command_evt
) 
3105     wxAuiNotebookEvent
& evt 
= (wxAuiNotebookEvent
&)command_evt
; 
3107     wxAuiTabCtrl
* ctrl 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3108     wxASSERT(ctrl 
!= NULL
); 
3110     wxWindow
* wnd 
= ctrl
->GetWindowFromIdx(evt
.GetSelection()); 
3111     wxASSERT(wnd 
!= NULL
); 
3113     SetSelectionToWindow(wnd
); 
3116 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent
&) 
3121 void wxAuiNotebook::OnTabDragMotion(wxCommandEvent
& evt
) 
3123     wxPoint screen_pt 
= ::wxGetMousePosition(); 
3124     wxPoint client_pt 
= ScreenToClient(screen_pt
); 
3127     wxAuiTabCtrl
* src_tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3128     wxAuiTabCtrl
* dest_tabs 
= GetTabCtrlFromPoint(client_pt
); 
3130     if (dest_tabs 
== src_tabs
) 
3134             src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
)); 
3137         // always hide the hint for inner-tabctrl drag 
3140         // if tab moving is not allowed, leave 
3141         if (!(m_flags 
& wxAUI_NB_TAB_MOVE
)) 
3146         wxPoint pt 
= dest_tabs
->ScreenToClient(screen_pt
); 
3147         wxWindow
* dest_location_tab
; 
3149         // this is an inner-tab drag/reposition 
3150         if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
)) 
3152             int src_idx 
= evt
.GetSelection(); 
3153             int dest_idx 
= dest_tabs
->GetIdxFromWindow(dest_location_tab
); 
3155             // prevent jumpy drag 
3156             if ((src_idx 
== dest_idx
) || dest_idx 
== -1 || 
3157                 (src_idx 
> dest_idx 
&& m_last_drag_x 
<= pt
.x
) || 
3158                 (src_idx 
< dest_idx 
&& m_last_drag_x 
>= pt
.x
)) 
3160                 m_last_drag_x 
= pt
.x
; 
3165             wxWindow
* src_tab 
= dest_tabs
->GetWindowFromIdx(src_idx
); 
3166             dest_tabs
->MovePage(src_tab
, dest_idx
); 
3167             dest_tabs
->SetActivePage((size_t)dest_idx
); 
3168             dest_tabs
->DoShowHide(); 
3169             dest_tabs
->Refresh(); 
3170             m_last_drag_x 
= pt
.x
; 
3178     // if external drag is allowed, check if the tab is being dragged 
3179     // over a different wxAuiNotebook control 
3180     if (m_flags 
& wxAUI_NB_TAB_EXTERNAL_MOVE
) 
3182         wxWindow
* tab_ctrl 
= ::wxFindWindowAtPoint(screen_pt
); 
3184         // if we aren't over any window, stop here 
3188         // make sure we are not over the hint window 
3189         if (!tab_ctrl
->IsKindOf(CLASSINFO(wxFrame
))) 
3193                 if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
))) 
3195                 tab_ctrl 
= tab_ctrl
->GetParent(); 
3200                 wxAuiNotebook
* nb 
= (wxAuiNotebook
*)tab_ctrl
->GetParent(); 
3204                     wxRect hint_rect 
= tab_ctrl
->GetClientRect(); 
3205                     tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
); 
3206                     m_mgr
.ShowHint(hint_rect
); 
3215                 // we are either over a hint window, or not over a tab 
3216                 // window, and there is no where to drag to, so exit 
3223     // if there are less than two panes, split can't happen, so leave 
3224     if (m_tabs
.GetPageCount() < 2) 
3227     // if tab moving is not allowed, leave 
3228     if (!(m_flags 
& wxAUI_NB_TAB_SPLIT
)) 
3234         src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
)); 
3240         wxRect hint_rect 
= dest_tabs
->GetRect(); 
3241         ClientToScreen(&hint_rect
.x
, &hint_rect
.y
); 
3242         m_mgr
.ShowHint(hint_rect
); 
3246         m_mgr
.DrawHintRect(m_dummy_wnd
, client_pt
, zero
); 
3252 void wxAuiNotebook::OnTabEndDrag(wxCommandEvent
& command_evt
) 
3254     wxAuiNotebookEvent
& evt 
= (wxAuiNotebookEvent
&)command_evt
; 
3259     wxAuiTabCtrl
* src_tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3260     wxCHECK_RET( src_tabs
, _T("no source object?") ); 
3262     src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
)); 
3264     // get the mouse position, which will be used to determine the drop point 
3265     wxPoint mouse_screen_pt 
= ::wxGetMousePosition(); 
3266     wxPoint mouse_client_pt 
= ScreenToClient(mouse_screen_pt
); 
3270     // check for an external move 
3271     if (m_flags 
& wxAUI_NB_TAB_EXTERNAL_MOVE
) 
3273         wxWindow
* tab_ctrl 
= ::wxFindWindowAtPoint(mouse_screen_pt
); 
3277             if (tab_ctrl
->IsKindOf(CLASSINFO(wxAuiTabCtrl
))) 
3279             tab_ctrl 
= tab_ctrl
->GetParent(); 
3284             wxAuiNotebook
* nb 
= (wxAuiNotebook
*)tab_ctrl
->GetParent(); 
3288                 // find out from the destination control 
3289                 // if it's ok to drop this tab here 
3290                 wxAuiNotebookEvent 
e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND
, m_windowId
); 
3291                 e
.SetSelection(evt
.GetSelection()); 
3292                 e
.SetOldSelection(evt
.GetSelection()); 
3293                 e
.SetEventObject(this); 
3294                 e
.SetDragSource(this); 
3295                 e
.Veto(); // dropping must be explicitly approved by control owner 
3297                 nb
->GetEventHandler()->ProcessEvent(e
); 
3301                     // no answer or negative answer 
3307                 int src_idx 
= evt
.GetSelection(); 
3308                 wxWindow
* src_page 
= src_tabs
->GetWindowFromIdx(src_idx
); 
3310                 // get main index of the page 
3311                 int main_idx 
= m_tabs
.GetIdxFromWindow(src_page
); 
3312                 wxCHECK_RET( main_idx 
!= wxNOT_FOUND
, _T("no source page?") ); 
3315                 // make a copy of the page info 
3316                 wxAuiNotebookPage page_info 
= m_tabs
.GetPage(main_idx
); 
3318                 // remove the page from the source notebook 
3319                 RemovePage(main_idx
); 
3321                 // reparent the page 
3322                 src_page
->Reparent(nb
); 
3325                 // found out the insert idx 
3326                 wxAuiTabCtrl
* dest_tabs 
= (wxAuiTabCtrl
*)tab_ctrl
; 
3327                 wxPoint pt 
= dest_tabs
->ScreenToClient(mouse_screen_pt
); 
3329                 wxWindow
* target 
= NULL
; 
3330                 int insert_idx 
= -1; 
3331                 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
); 
3334                     insert_idx 
= dest_tabs
->GetIdxFromWindow(target
); 
3338                 // add the page to the new notebook 
3339                 if (insert_idx 
== -1) 
3340                     insert_idx 
= dest_tabs
->GetPageCount(); 
3341                 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
); 
3342                 nb
->m_tabs
.AddPage(page_info
.window
, page_info
); 
3345                 dest_tabs
->DoShowHide(); 
3346                 dest_tabs
->Refresh(); 
3348                 // set the selection in the destination tab control 
3349                 nb
->SetSelectionToPage(page_info
); 
3359     // only perform a tab split if it's allowed 
3360     wxAuiTabCtrl
* dest_tabs 
= NULL
; 
3362     if ((m_flags 
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2) 
3364         // If the pointer is in an existing tab frame, do a tab insert 
3365         wxWindow
* hit_wnd 
= ::wxFindWindowAtPoint(mouse_screen_pt
); 
3366         wxTabFrame
* tab_frame 
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
); 
3367         int insert_idx 
= -1; 
3370             dest_tabs 
= tab_frame
->m_tabs
; 
3372             if (dest_tabs 
== src_tabs
) 
3376             wxPoint pt 
= dest_tabs
->ScreenToClient(mouse_screen_pt
); 
3377             wxWindow
* target 
= NULL
; 
3378             dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
); 
3381                 insert_idx 
= dest_tabs
->GetIdxFromWindow(target
); 
3387             wxRect rect 
= m_mgr
.CalculateHintRect(m_dummy_wnd
, 
3392                 // there is no suitable drop location here, exit out 
3396             // If there is no tabframe at all, create one 
3397             wxTabFrame
* new_tabs 
= new wxTabFrame
; 
3398             new_tabs
->m_rect 
= wxRect(wxPoint(0,0), CalculateNewSplitSize()); 
3399             new_tabs
->SetTabCtrlHeight(m_tab_ctrl_height
); 
3400             new_tabs
->m_tabs 
= new wxAuiTabCtrl(this, 
3405             new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
3406             new_tabs
->m_tabs
->SetFlags(m_flags
); 
3408             m_mgr
.AddPane(new_tabs
, 
3409                           wxAuiPaneInfo().Bottom().CaptionVisible(false), 
3412             dest_tabs 
= new_tabs
->m_tabs
; 
3417         // remove the page from the source tabs 
3418         wxAuiNotebookPage page_info 
= src_tabs
->GetPage(evt
.GetSelection()); 
3419         page_info
.active 
= false; 
3420         src_tabs
->RemovePage(page_info
.window
); 
3421         if (src_tabs
->GetPageCount() > 0) 
3423             src_tabs
->SetActivePage((size_t)0); 
3424             src_tabs
->DoShowHide(); 
3425             src_tabs
->Refresh(); 
3430         // add the page to the destination tabs 
3431         if (insert_idx 
== -1) 
3432             insert_idx 
= dest_tabs
->GetPageCount(); 
3433         dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
); 
3435         if (src_tabs
->GetPageCount() == 0) 
3437             RemoveEmptyTabFrames(); 
3441         dest_tabs
->DoShowHide(); 
3442         dest_tabs
->Refresh(); 
3444         // force the set selection function reset the selection 
3447         // set the active page to the one we just split off 
3448         SetSelectionToPage(page_info
); 
3450         UpdateHintWindowSize(); 
3456 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
) 
3458     // if we've just removed the last tab from the source 
3459     // tab set, the remove the tab control completely 
3460     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
3461     size_t i
, pane_count 
= all_panes
.GetCount(); 
3462     for (i 
= 0; i 
< pane_count
; ++i
) 
3464         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
3467         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
3468         if (tabframe
->m_tab_rect
.Contains(pt
)) 
3469             return tabframe
->m_tabs
; 
3475 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
) 
3477     // if we've just removed the last tab from the source 
3478     // tab set, the remove the tab control completely 
3479     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
3480     size_t i
, pane_count 
= all_panes
.GetCount(); 
3481     for (i 
= 0; i 
< pane_count
; ++i
) 
3483         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
3486         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
3487         if (tabframe
->m_tabs 
== tab_ctrl
) 
3496 void wxAuiNotebook::RemoveEmptyTabFrames() 
3498     // if we've just removed the last tab from the source 
3499     // tab set, the remove the tab control completely 
3500     wxAuiPaneInfoArray all_panes 
= m_mgr
.GetAllPanes(); 
3501     size_t i
, pane_count 
= all_panes
.GetCount(); 
3502     for (i 
= 0; i 
< pane_count
; ++i
) 
3504         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
3507         wxTabFrame
* tab_frame 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
3508         if (tab_frame
->m_tabs
->GetPageCount() == 0) 
3510             m_mgr
.DetachPane(tab_frame
); 
3512             // use pending delete because sometimes during 
3513             // window closing, refreshs are pending 
3514             if (!wxPendingDelete
.Member(tab_frame
->m_tabs
)) 
3515                 wxPendingDelete
.Append(tab_frame
->m_tabs
); 
3516             //tab_frame->m_tabs->Destroy(); 
3523     // check to see if there is still a center pane; 
3524     // if there isn't, make a frame the center pane 
3525     wxAuiPaneInfoArray panes 
= m_mgr
.GetAllPanes(); 
3526     pane_count 
= panes
.GetCount(); 
3527     wxWindow
* first_good 
= NULL
; 
3528     bool center_found 
= false; 
3529     for (i 
= 0; i 
< pane_count
; ++i
) 
3531         if (panes
.Item(i
).name 
== wxT("dummy")) 
3533         if (panes
.Item(i
).dock_direction 
== wxAUI_DOCK_CENTRE
) 
3534             center_found 
= true; 
3536             first_good 
= panes
.Item(i
).window
; 
3539     if (!center_found 
&& first_good
) 
3541         m_mgr
.GetPane(first_good
).Centre(); 
3547 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent
& evt
) 
3549     int idx 
= m_tabs
.GetIdxFromWindow(evt
.GetWindow()); 
3550     if (idx 
!= -1 && idx 
!= m_curpage
) 
3557 void wxAuiNotebook::OnTabButton(wxCommandEvent
& command_evt
) 
3559     wxAuiNotebookEvent
& evt 
= (wxAuiNotebookEvent
&)command_evt
; 
3560     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3562     int button_id 
= evt
.GetInt(); 
3564     if (button_id 
== wxAUI_BUTTON_CLOSE
) 
3566         int selection 
= tabs
->GetActivePage(); 
3568         if (selection 
!= -1) 
3570             wxWindow
* close_wnd 
= tabs
->GetWindowFromIdx(selection
); 
3573             // ask owner if it's ok to close the tab 
3574             wxAuiNotebookEvent 
e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
); 
3575             e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
)); 
3576             e
.SetOldSelection(evt
.GetSelection()); 
3577             e
.SetEventObject(this); 
3578             GetEventHandler()->ProcessEvent(e
); 
3583             if (close_wnd
->IsKindOf(CLASSINFO(wxAuiMDIChildFrame
))) 
3589                 int main_idx 
= m_tabs
.GetIdxFromWindow(close_wnd
); 
3590                 wxCHECK_RET( main_idx 
!= wxNOT_FOUND
, _T("no page to delete?") ); 
3592                 DeletePage(main_idx
);