1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/aui/auibook.cpp 
   3 // Purpose:     wxaui: wx advanced user interface - notebook 
   4 // Author:      Benjamin I. Williams 
   5 // Modified by: Jens Lody 
   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" 
  27     #include "wx/dcclient.h" 
  28     #include "wx/dcmemory.h" 
  31 #include "wx/aui/tabmdi.h" 
  34 #include "wx/osx/private.h" 
  37 #include "wx/arrimpl.cpp" 
  38 WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray
) 
  39 WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray
) 
  41 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CLOSE
, wxAuiNotebookEvent
); 
  42 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CLOSED
, wxAuiNotebookEvent
); 
  43 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, wxAuiNotebookEvent
); 
  44 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_PAGE_CHANGED
, wxAuiNotebookEvent
); 
  45 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BUTTON
, wxAuiNotebookEvent
); 
  46 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BEGIN_DRAG
, wxAuiNotebookEvent
); 
  47 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_END_DRAG
, wxAuiNotebookEvent
); 
  48 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_CANCEL_DRAG
, wxAuiNotebookEvent
); 
  49 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_DRAG_MOTION
, wxAuiNotebookEvent
); 
  50 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_ALLOW_DND
, wxAuiNotebookEvent
); 
  51 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_BG_DCLICK
, wxAuiNotebookEvent
); 
  52 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_DRAG_DONE
, wxAuiNotebookEvent
); 
  53 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP
, wxAuiNotebookEvent
); 
  54 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
, wxAuiNotebookEvent
); 
  55 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP
, wxAuiNotebookEvent
); 
  56 wxDEFINE_EVENT(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN
, wxAuiNotebookEvent
); 
  58 IMPLEMENT_CLASS(wxAuiNotebook
, wxControl
) 
  59 IMPLEMENT_CLASS(wxAuiTabCtrl
, wxControl
) 
  60 IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent
, wxBookCtrlEvent
) 
  63 // -- wxAuiTabContainer class implementation -- 
  66 // wxAuiTabContainer is a class which contains information about each 
  67 // tab.  It also can render an entire tab control to a specified DC. 
  68 // It's not a window class itself, because this code will be used by 
  69 // the wxFrameMananger, where it is disadvantageous to have separate 
  70 // windows for each tab control in the case of "docked tabs" 
  72 // A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window 
  73 // which can be used as a tab control in the normal sense. 
  76 wxAuiTabContainer::wxAuiTabContainer() 
  80     m_art 
= new wxAuiDefaultTabArt
; 
  82     AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
); 
  83     AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
); 
  84     AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
); 
  85     AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
); 
  88 wxAuiTabContainer::~wxAuiTabContainer() 
  93 void wxAuiTabContainer::SetArtProvider(wxAuiTabArt
* art
) 
 100         m_art
->SetFlags(m_flags
); 
 104 wxAuiTabArt
* wxAuiTabContainer::GetArtProvider() const 
 109 void wxAuiTabContainer::SetFlags(unsigned int flags
) 
 113     // check for new close button settings 
 114     RemoveButton(wxAUI_BUTTON_LEFT
); 
 115     RemoveButton(wxAUI_BUTTON_RIGHT
); 
 116     RemoveButton(wxAUI_BUTTON_WINDOWLIST
); 
 117     RemoveButton(wxAUI_BUTTON_CLOSE
); 
 120     if (flags 
& wxAUI_NB_SCROLL_BUTTONS
) 
 122         AddButton(wxAUI_BUTTON_LEFT
, wxLEFT
); 
 123         AddButton(wxAUI_BUTTON_RIGHT
, wxRIGHT
); 
 126     if (flags 
& wxAUI_NB_WINDOWLIST_BUTTON
) 
 128         AddButton(wxAUI_BUTTON_WINDOWLIST
, wxRIGHT
); 
 131     if (flags 
& wxAUI_NB_CLOSE_BUTTON
) 
 133         AddButton(wxAUI_BUTTON_CLOSE
, wxRIGHT
); 
 138         m_art
->SetFlags(m_flags
); 
 142 unsigned int wxAuiTabContainer::GetFlags() const 
 148 void wxAuiTabContainer::SetNormalFont(const wxFont
& font
) 
 150     m_art
->SetNormalFont(font
); 
 153 void wxAuiTabContainer::SetSelectedFont(const wxFont
& font
) 
 155     m_art
->SetSelectedFont(font
); 
 158 void wxAuiTabContainer::SetMeasuringFont(const wxFont
& font
) 
 160     m_art
->SetMeasuringFont(font
); 
 163 void wxAuiTabContainer::SetColour(const wxColour
& colour
) 
 165     m_art
->SetColour(colour
); 
 168 void wxAuiTabContainer::SetActiveColour(const wxColour
& colour
) 
 170     m_art
->SetActiveColour(colour
); 
 173 void wxAuiTabContainer::SetRect(const wxRect
& rect
) 
 179         m_art
->SetSizingInfo(rect
.GetSize(), m_pages
.GetCount()); 
 183 bool wxAuiTabContainer::AddPage(wxWindow
* page
, 
 184                                 const wxAuiNotebookPage
& info
) 
 186     wxAuiNotebookPage page_info
; 
 188     page_info
.window 
= page
; 
 190     m_pages
.Add(page_info
); 
 192     // let the art provider know how many pages we have 
 195         m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
 201 bool wxAuiTabContainer::InsertPage(wxWindow
* page
, 
 202                                    const wxAuiNotebookPage
& info
, 
 205     wxAuiNotebookPage page_info
; 
 207     page_info
.window 
= page
; 
 209     if (idx 
>= m_pages
.GetCount()) 
 210         m_pages
.Add(page_info
); 
 212         m_pages
.Insert(page_info
, idx
); 
 214     // let the art provider know how many pages we have 
 217         m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
 223 bool wxAuiTabContainer::MovePage(wxWindow
* page
, 
 226     int idx 
= GetIdxFromWindow(page
); 
 230     // get page entry, make a copy of it 
 231     wxAuiNotebookPage p 
= GetPage(idx
); 
 233     // remove old page entry 
 236     // insert page where it should be 
 237     InsertPage(page
, p
, new_idx
); 
 242 bool wxAuiTabContainer::RemovePage(wxWindow
* wnd
) 
 244     size_t i
, page_count 
= m_pages
.GetCount(); 
 245     for (i 
= 0; i 
< page_count
; ++i
) 
 247         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 248         if (page
.window 
== wnd
) 
 252             // let the art provider know how many pages we have 
 255                 m_art
->SetSizingInfo(m_rect
.GetSize(), m_pages
.GetCount()); 
 265 bool wxAuiTabContainer::SetActivePage(wxWindow
* wnd
) 
 269     size_t i
, page_count 
= m_pages
.GetCount(); 
 270     for (i 
= 0; i 
< page_count
; ++i
) 
 272         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 273         if (page
.window 
== wnd
) 
 287 void wxAuiTabContainer::SetNoneActive() 
 289     size_t i
, page_count 
= m_pages
.GetCount(); 
 290     for (i 
= 0; i 
< page_count
; ++i
) 
 292         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 297 bool wxAuiTabContainer::SetActivePage(size_t page
) 
 299     if (page 
>= m_pages
.GetCount()) 
 302     return SetActivePage(m_pages
.Item(page
).window
); 
 305 int wxAuiTabContainer::GetActivePage() const 
 307     size_t i
, page_count 
= m_pages
.GetCount(); 
 308     for (i 
= 0; i 
< page_count
; ++i
) 
 310         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 318 wxWindow
* wxAuiTabContainer::GetWindowFromIdx(size_t idx
) const 
 320     if (idx 
>= m_pages
.GetCount()) 
 323     return m_pages
[idx
].window
; 
 326 int wxAuiTabContainer::GetIdxFromWindow(wxWindow
* wnd
) const 
 328     const size_t page_count 
= m_pages
.GetCount(); 
 329     for ( size_t i 
= 0; i 
< page_count
; ++i 
) 
 331         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 332         if (page
.window 
== wnd
) 
 338 wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) 
 340     wxASSERT_MSG(idx 
< m_pages
.GetCount(), wxT("Invalid Page index")); 
 345 const wxAuiNotebookPage
& wxAuiTabContainer::GetPage(size_t idx
) const 
 347     wxASSERT_MSG(idx 
< m_pages
.GetCount(), wxT("Invalid Page index")); 
 352 wxAuiNotebookPageArray
& wxAuiTabContainer::GetPages() 
 357 size_t wxAuiTabContainer::GetPageCount() const 
 359     return m_pages
.GetCount(); 
 362 void wxAuiTabContainer::AddButton(int id
, 
 364                                   const wxBitmap
& normalBitmap
, 
 365                                   const wxBitmap
& disabledBitmap
) 
 367     wxAuiTabContainerButton button
; 
 369     button
.bitmap 
= normalBitmap
; 
 370     button
.disBitmap 
= disabledBitmap
; 
 371     button
.location 
= location
; 
 372     button
.curState 
= wxAUI_BUTTON_STATE_NORMAL
; 
 374     m_buttons
.Add(button
); 
 377 void wxAuiTabContainer::RemoveButton(int id
) 
 379     size_t i
, button_count 
= m_buttons
.GetCount(); 
 381     for (i 
= 0; i 
< button_count
; ++i
) 
 383         if (m_buttons
.Item(i
).id 
== id
) 
 385             m_buttons
.RemoveAt(i
); 
 393 size_t wxAuiTabContainer::GetTabOffset() const 
 398 void wxAuiTabContainer::SetTabOffset(size_t offset
) 
 400     m_tabOffset 
= offset
; 
 406 // Render() renders the tab catalog to the specified DC 
 407 // It is a virtual function and can be overridden to 
 408 // provide custom drawing capabilities 
 409 void wxAuiTabContainer::Render(wxDC
* raw_dc
, wxWindow
* wnd
) 
 411     if (!raw_dc 
|| !raw_dc
->IsOk()) 
 416     // use the same layout direction as the window DC uses to ensure that the 
 417     // text is rendered correctly 
 418     dc
.SetLayoutDirection(raw_dc
->GetLayoutDirection()); 
 422     size_t page_count 
= m_pages
.GetCount(); 
 423     size_t button_count 
= m_buttons
.GetCount(); 
 425     // create off-screen bitmap 
 426     bmp
.Create(m_rect
.GetWidth(), m_rect
.GetHeight(),*raw_dc
); 
 427     dc
.SelectObject(bmp
); 
 432     // find out if size of tabs is larger than can be 
 433     // afforded on screen 
 435     int visible_width 
= 0; 
 436     for (i 
= 0; i 
< page_count
; ++i
) 
 438         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 440         // determine if a close button is on this tab 
 441         bool close_button 
= false; 
 442         if ((m_flags 
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 || 
 443             ((m_flags 
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
)) 
 450         wxSize size 
= m_art
->GetTabSize(dc
, 
 456                               wxAUI_BUTTON_STATE_NORMAL 
: 
 457                               wxAUI_BUTTON_STATE_HIDDEN
, 
 460         if (i
+1 < page_count
) 
 461             total_width 
+= x_extent
; 
 463             total_width 
+= size
.x
; 
 465         if (i 
>= m_tabOffset
) 
 467             if (i
+1 < page_count
) 
 468                 visible_width 
+= x_extent
; 
 470                 visible_width 
+= size
.x
; 
 474     if (total_width 
> m_rect
.GetWidth() || m_tabOffset 
!= 0) 
 476         // show left/right buttons 
 477         for (i 
= 0; i 
< button_count
; ++i
) 
 479             wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
 480             if (button
.id 
== wxAUI_BUTTON_LEFT 
|| 
 481                 button
.id 
== wxAUI_BUTTON_RIGHT
) 
 483                 button
.curState 
&= ~wxAUI_BUTTON_STATE_HIDDEN
; 
 489         // hide left/right buttons 
 490         for (i 
= 0; i 
< button_count
; ++i
) 
 492             wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
 493             if (button
.id 
== wxAUI_BUTTON_LEFT 
|| 
 494                 button
.id 
== wxAUI_BUTTON_RIGHT
) 
 496                 button
.curState 
|= wxAUI_BUTTON_STATE_HIDDEN
; 
 501     // determine whether left button should be enabled 
 502     for (i 
= 0; i 
< button_count
; ++i
) 
 504         wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
 505         if (button
.id 
== wxAUI_BUTTON_LEFT
) 
 507             if (m_tabOffset 
== 0) 
 508                 button
.curState 
|= wxAUI_BUTTON_STATE_DISABLED
; 
 510                 button
.curState 
&= ~wxAUI_BUTTON_STATE_DISABLED
; 
 512         if (button
.id 
== wxAUI_BUTTON_RIGHT
) 
 514             if (visible_width 
< m_rect
.GetWidth() - ((int)button_count
*16)) 
 515                 button
.curState 
|= wxAUI_BUTTON_STATE_DISABLED
; 
 517                 button
.curState 
&= ~wxAUI_BUTTON_STATE_DISABLED
; 
 524     m_art
->DrawBackground(dc
, wnd
, m_rect
); 
 527     int left_buttons_width 
= 0; 
 528     int right_buttons_width 
= 0; 
 530     // draw the buttons on the right side 
 531     int offset 
= m_rect
.x 
+ m_rect
.width
; 
 532     for (i 
= 0; i 
< button_count
; ++i
) 
 534         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
 536         if (button
.location 
!= wxRIGHT
) 
 538         if (button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN
) 
 541         wxRect button_rect 
= m_rect
; 
 543         button_rect
.SetWidth(offset
); 
 545         m_art
->DrawButton(dc
, 
 553         offset 
-= button
.rect
.GetWidth(); 
 554         right_buttons_width 
+= button
.rect
.GetWidth(); 
 561     // draw the buttons on the left side 
 563     for (i 
= 0; i 
< button_count
; ++i
) 
 565         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
 567         if (button
.location 
!= wxLEFT
) 
 569         if (button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN
) 
 572         wxRect 
button_rect(offset
, 1, 1000, m_rect
.height
); 
 574         m_art
->DrawButton(dc
, 
 582         offset 
+= button
.rect
.GetWidth(); 
 583         left_buttons_width 
+= button
.rect
.GetWidth(); 
 586     offset 
= left_buttons_width
; 
 589         offset 
+= m_art
->GetIndentSize(); 
 592     // prepare the tab-close-button array 
 593     // make sure tab button entries which aren't used are marked as hidden 
 594     for (i 
= page_count
; i 
< m_tabCloseButtons
.GetCount(); ++i
) 
 595         m_tabCloseButtons
.Item(i
).curState 
= wxAUI_BUTTON_STATE_HIDDEN
; 
 597     // make sure there are enough tab button entries to accommodate all tabs 
 598     while (m_tabCloseButtons
.GetCount() < page_count
) 
 600         wxAuiTabContainerButton tempbtn
; 
 601         tempbtn
.id 
= wxAUI_BUTTON_CLOSE
; 
 602         tempbtn
.location 
= wxCENTER
; 
 603         tempbtn
.curState 
= wxAUI_BUTTON_STATE_HIDDEN
; 
 604         m_tabCloseButtons
.Add(tempbtn
); 
 608     // buttons before the tab offset must be set to hidden 
 609     for (i 
= 0; i 
< m_tabOffset
; ++i
) 
 611         m_tabCloseButtons
.Item(i
).curState 
= wxAUI_BUTTON_STATE_HIDDEN
; 
 618     int active_offset 
= 0; 
 622     wxRect rect 
= m_rect
; 
 624     rect
.height 
= m_rect
.height
; 
 626     for (i 
= m_tabOffset
; i 
< page_count
; ++i
) 
 628         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 629         wxAuiTabContainerButton
& tab_button 
= m_tabCloseButtons
.Item(i
); 
 631         // determine if a close button is on this tab 
 632         if ((m_flags 
& wxAUI_NB_CLOSE_ON_ALL_TABS
) != 0 || 
 633             ((m_flags 
& wxAUI_NB_CLOSE_ON_ACTIVE_TAB
) != 0 && page
.active
)) 
 635             if (tab_button
.curState 
== wxAUI_BUTTON_STATE_HIDDEN
) 
 637                 tab_button
.id 
= wxAUI_BUTTON_CLOSE
; 
 638                 tab_button
.curState 
= wxAUI_BUTTON_STATE_NORMAL
; 
 639                 tab_button
.location 
= wxCENTER
; 
 644             tab_button
.curState 
= wxAUI_BUTTON_STATE_HIDDEN
; 
 648         rect
.width 
= m_rect
.width 
- right_buttons_width 
- offset 
- 2; 
 665             active_offset 
= offset
; 
 673     // make sure to deactivate buttons which are off the screen to the right 
 674     for (++i
; i 
< m_tabCloseButtons
.GetCount(); ++i
) 
 676         m_tabCloseButtons
.Item(i
).curState 
= wxAUI_BUTTON_STATE_HIDDEN
; 
 680     // draw the active tab again so it stands in the foreground 
 681     if (active 
>= m_tabOffset 
&& active 
< m_pages
.GetCount()) 
 683         wxAuiNotebookPage
& page 
= m_pages
.Item(active
); 
 685         wxAuiTabContainerButton
& tab_button 
= m_tabCloseButtons
.Item(active
); 
 687         rect
.x 
= active_offset
; 
 699     raw_dc
->Blit(m_rect
.x
, m_rect
.y
, 
 700                  m_rect
.GetWidth(), m_rect
.GetHeight(), 
 704 // Is the tab visible? 
 705 bool wxAuiTabContainer::IsTabVisible(int tabPage
, int tabOffset
, wxDC
* dc
, wxWindow
* wnd
) 
 707     if (!dc 
|| !dc
->IsOk()) 
 711     size_t page_count 
= m_pages
.GetCount(); 
 712     size_t button_count 
= m_buttons
.GetCount(); 
 714     // Hasn't been rendered yet; assume it's visible 
 715     if (m_tabCloseButtons
.GetCount() < page_count
) 
 718     // First check if both buttons are disabled - if so, there's no need to 
 719     // check further for visibility. 
 720     int arrowButtonVisibleCount 
= 0; 
 721     for (i 
= 0; i 
< button_count
; ++i
) 
 723         wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
 724         if (button
.id 
== wxAUI_BUTTON_LEFT 
|| 
 725             button
.id 
== wxAUI_BUTTON_RIGHT
) 
 727             if ((button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN
) == 0) 
 728                 arrowButtonVisibleCount 
++; 
 732     // Tab must be visible 
 733     if (arrowButtonVisibleCount 
== 0) 
 736     // If tab is less than the given offset, it must be invisible by definition 
 737     if (tabPage 
< tabOffset
) 
 741     int left_buttons_width 
= 0; 
 742     int right_buttons_width 
= 0; 
 744     // calculate size of the buttons on the right side 
 745     int offset 
= m_rect
.x 
+ m_rect
.width
; 
 746     for (i 
= 0; i 
< button_count
; ++i
) 
 748         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
 750         if (button
.location 
!= wxRIGHT
) 
 752         if (button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN
) 
 755         offset 
-= button
.rect
.GetWidth(); 
 756         right_buttons_width 
+= button
.rect
.GetWidth(); 
 761     // calculate size of the buttons on the left side 
 762     for (i 
= 0; i 
< button_count
; ++i
) 
 764         wxAuiTabContainerButton
& button 
= m_buttons
.Item(button_count 
- i 
- 1); 
 766         if (button
.location 
!= wxLEFT
) 
 768         if (button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN
) 
 771         offset 
+= button
.rect
.GetWidth(); 
 772         left_buttons_width 
+= button
.rect
.GetWidth(); 
 775     offset 
= left_buttons_width
; 
 778         offset 
+= m_art
->GetIndentSize(); 
 782     wxRect rect 
= m_rect
; 
 784     rect
.height 
= m_rect
.height
; 
 786     // See if the given page is visible at the given tab offset (effectively scroll position) 
 787     for (i 
= tabOffset
; i 
< page_count
; ++i
) 
 789         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 790         wxAuiTabContainerButton
& tab_button 
= m_tabCloseButtons
.Item(i
); 
 793         rect
.width 
= m_rect
.width 
- right_buttons_width 
- offset 
- 2; 
 796             return false; // haven't found the tab, and we've run out of space, so return false 
 799         m_art
->GetTabSize(*dc
, 
 809         if (i 
== (size_t) tabPage
) 
 811             // If not all of the tab is visible, and supposing there's space to display it all, 
 812             // we could do better so we return false. 
 813             if (((m_rect
.width 
- right_buttons_width 
- offset 
- 2) <= 0) && ((m_rect
.width 
- right_buttons_width 
- left_buttons_width
) > x_extent
)) 
 820     // Shouldn't really get here, but if it does, assume the tab is visible to prevent 
 821     // further looping in calling code. 
 825 // Make the tab visible if it wasn't already 
 826 void wxAuiTabContainer::MakeTabVisible(int tabPage
, wxWindow
* win
) 
 829     if (!IsTabVisible(tabPage
, GetTabOffset(), & dc
, win
)) 
 832         for (i 
= 0; i 
< (int) m_pages
.GetCount(); i
++) 
 834             if (IsTabVisible(tabPage
, i
, & dc
, win
)) 
 844 // TabHitTest() tests if a tab was hit, passing the window pointer 
 845 // back if that condition was fulfilled.  The function returns 
 846 // true if a tab was hit, otherwise false 
 847 bool wxAuiTabContainer::TabHitTest(int x
, int y
, wxWindow
** hit
) const 
 849     if (!m_rect
.Contains(x
,y
)) 
 852     wxAuiTabContainerButton
* btn 
= NULL
; 
 853     if (ButtonHitTest(x
, y
, &btn
) && !(btn
->curState 
& wxAUI_BUTTON_STATE_DISABLED
)) 
 855         if (m_buttons
.Index(*btn
) != wxNOT_FOUND
) 
 859     size_t i
, page_count 
= m_pages
.GetCount(); 
 861     for (i 
= m_tabOffset
; i 
< page_count
; ++i
) 
 863         wxAuiNotebookPage
& page 
= m_pages
.Item(i
); 
 864         if (page
.rect
.Contains(x
,y
)) 
 875 // ButtonHitTest() tests if a button was hit. The function returns 
 876 // true if a button was hit, otherwise false 
 877 bool wxAuiTabContainer::ButtonHitTest(int x
, int y
, 
 878                                       wxAuiTabContainerButton
** hit
) const 
 880     if (!m_rect
.Contains(x
,y
)) 
 883     size_t i
, button_count
; 
 886     button_count 
= m_buttons
.GetCount(); 
 887     for (i 
= 0; i 
< button_count
; ++i
) 
 889         wxAuiTabContainerButton
& button 
= m_buttons
.Item(i
); 
 890         if (button
.rect
.Contains(x
,y
) && 
 891             !(button
.curState 
& wxAUI_BUTTON_STATE_HIDDEN 
)) 
 899     button_count 
= m_tabCloseButtons
.GetCount(); 
 900     for (i 
= 0; i 
< button_count
; ++i
) 
 902         wxAuiTabContainerButton
& button 
= m_tabCloseButtons
.Item(i
); 
 903         if (button
.rect
.Contains(x
,y
) && 
 904             !(button
.curState 
& (wxAUI_BUTTON_STATE_HIDDEN 
| 
 905                                    wxAUI_BUTTON_STATE_DISABLED
))) 
 918 // the utility function ShowWnd() is the same as show, 
 919 // except it handles wxAuiMDIChildFrame windows as well, 
 920 // as the Show() method on this class is "unplugged" 
 921 static void ShowWnd(wxWindow
* wnd
, bool show
) 
 924     if (wxDynamicCast(wnd
, wxAuiMDIChildFrame
)) 
 926         wxAuiMDIChildFrame
* cf 
= (wxAuiMDIChildFrame
*)wnd
; 
 937 // DoShowHide() this function shows the active window, then 
 938 // hides all of the other windows (in that order) 
 939 void wxAuiTabContainer::DoShowHide() 
 941     wxAuiNotebookPageArray
& pages 
= GetPages(); 
 942     size_t i
, page_count 
= pages
.GetCount(); 
 944     // show new active page first 
 945     for (i 
= 0; i 
< page_count
; ++i
) 
 947         wxAuiNotebookPage
& page 
= pages
.Item(i
); 
 950             ShowWnd(page
.window
, true); 
 955     // hide all other pages 
 956     for (i 
= 0; i 
< page_count
; ++i
) 
 958         wxAuiNotebookPage
& page 
= pages
.Item(i
); 
 960             ShowWnd(page
.window
, false); 
 969 // -- wxAuiTabCtrl class implementation -- 
 973 BEGIN_EVENT_TABLE(wxAuiTabCtrl
, wxControl
) 
 974     EVT_PAINT(wxAuiTabCtrl::OnPaint
) 
 975     EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground
) 
 976     EVT_SIZE(wxAuiTabCtrl::OnSize
) 
 977     EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown
) 
 978     EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDClick
) 
 979     EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp
) 
 980     EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown
) 
 981     EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp
) 
 982     EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown
) 
 983     EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp
) 
 984     EVT_MOTION(wxAuiTabCtrl::OnMotion
) 
 985     EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow
) 
 986     EVT_AUINOTEBOOK_BUTTON(wxID_ANY
, wxAuiTabCtrl::OnButton
) 
 987     EVT_SET_FOCUS(wxAuiTabCtrl::OnSetFocus
) 
 988     EVT_KILL_FOCUS(wxAuiTabCtrl::OnKillFocus
) 
 989     EVT_CHAR(wxAuiTabCtrl::OnChar
) 
 990     EVT_MOUSE_CAPTURE_LOST(wxAuiTabCtrl::OnCaptureLost
) 
 994 wxAuiTabCtrl::wxAuiTabCtrl(wxWindow
* parent
, 
 998                            long style
) : wxControl(parent
, id
, pos
, size
, style
) 
1000     SetName(wxT("wxAuiTabCtrl")); 
1001     m_clickPt 
= wxDefaultPosition
; 
1002     m_isDragging 
= false; 
1003     m_hoverButton 
= NULL
; 
1004     m_pressedButton 
= NULL
; 
1007 wxAuiTabCtrl::~wxAuiTabCtrl() 
1011 void wxAuiTabCtrl::OnPaint(wxPaintEvent
&) 
1015     dc
.SetFont(GetFont()); 
1017     if (GetPageCount() > 0) 
1021 void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
)) 
1025 void wxAuiTabCtrl::OnSize(wxSizeEvent
& evt
) 
1027     wxSize s 
= evt
.GetSize(); 
1028     wxRect 
r(0, 0, s
.GetWidth(), s
.GetHeight()); 
1032 void wxAuiTabCtrl::OnLeftDown(wxMouseEvent
& evt
) 
1035     m_clickPt 
= wxDefaultPosition
; 
1036     m_isDragging 
= false; 
1038     m_pressedButton 
= NULL
; 
1042     if (TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1044         int new_selection 
= GetIdxFromWindow(wnd
); 
1046         // wxAuiNotebooks always want to receive this event 
1047         // even if the tab is already active, because they may 
1048         // have multiple tab controls 
1049         if ((new_selection 
!= GetActivePage() || 
1050             wxDynamicCast(GetParent(), wxAuiNotebook
)) && !m_hoverButton
) 
1052             wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
1053             e
.SetSelection(new_selection
); 
1054             e
.SetOldSelection(GetActivePage()); 
1055             e
.SetEventObject(this); 
1056             GetEventHandler()->ProcessEvent(e
); 
1059         m_clickPt
.x 
= evt
.m_x
; 
1060         m_clickPt
.y 
= evt
.m_y
; 
1066         m_pressedButton 
= m_hoverButton
; 
1067         m_pressedButton
->curState 
= wxAUI_BUTTON_STATE_PRESSED
; 
1073 void wxAuiTabCtrl::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
1077         m_isDragging 
= false; 
1079         wxAuiNotebookEvent 
evt(wxEVT_AUINOTEBOOK_CANCEL_DRAG
, m_windowId
); 
1080         evt
.SetSelection(GetIdxFromWindow(m_clickTab
)); 
1081         evt
.SetOldSelection(evt
.GetSelection()); 
1082         evt
.SetEventObject(this); 
1083         GetEventHandler()->ProcessEvent(evt
); 
1087 void wxAuiTabCtrl::OnLeftUp(wxMouseEvent
& evt
) 
1089     if (GetCapture() == this) 
1094         m_isDragging 
= false; 
1096         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_END_DRAG
, m_windowId
); 
1097         e
.SetSelection(GetIdxFromWindow(m_clickTab
)); 
1098         e
.SetOldSelection(e
.GetSelection()); 
1099         e
.SetEventObject(this); 
1100         GetEventHandler()->ProcessEvent(e
); 
1105     if (m_pressedButton
) 
1107         // make sure we're still clicking the button 
1108         wxAuiTabContainerButton
* button 
= NULL
; 
1109         if (!ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
) || 
1110             button
->curState 
& wxAUI_BUTTON_STATE_DISABLED
) 
1113         if (button 
!= m_pressedButton
) 
1115             m_pressedButton 
= NULL
; 
1122         if (!(m_pressedButton
->curState 
& wxAUI_BUTTON_STATE_DISABLED
)) 
1124             wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_BUTTON
, m_windowId
); 
1125             e
.SetSelection(GetIdxFromWindow(m_clickTab
)); 
1126             e
.SetInt(m_pressedButton
->id
); 
1127             e
.SetEventObject(this); 
1128             GetEventHandler()->ProcessEvent(e
); 
1131         m_pressedButton 
= NULL
; 
1134     m_clickPt 
= wxDefaultPosition
; 
1135     m_isDragging 
= false; 
1139 void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent
& evt
) 
1141     wxWindow
* wnd 
= NULL
; 
1142     if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1145     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
); 
1146     e
.SetEventObject(this); 
1147     e
.SetSelection(GetIdxFromWindow(wnd
)); 
1148     GetEventHandler()->ProcessEvent(e
); 
1151 void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent
& evt
) 
1153     wxWindow
* wnd 
= NULL
; 
1154     if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1157     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
); 
1158     e
.SetEventObject(this); 
1159     e
.SetSelection(GetIdxFromWindow(wnd
)); 
1160     GetEventHandler()->ProcessEvent(e
); 
1163 void wxAuiTabCtrl::OnRightUp(wxMouseEvent
& evt
) 
1165     wxWindow
* wnd 
= NULL
; 
1166     if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1169     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
); 
1170     e
.SetEventObject(this); 
1171     e
.SetSelection(GetIdxFromWindow(wnd
)); 
1172     GetEventHandler()->ProcessEvent(e
); 
1175 void wxAuiTabCtrl::OnRightDown(wxMouseEvent
& evt
) 
1177     wxWindow
* wnd 
= NULL
; 
1178     if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1181     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
); 
1182     e
.SetEventObject(this); 
1183     e
.SetSelection(GetIdxFromWindow(wnd
)); 
1184     GetEventHandler()->ProcessEvent(e
); 
1187 void wxAuiTabCtrl::OnLeftDClick(wxMouseEvent
& evt
) 
1190     wxAuiTabContainerButton
* button
; 
1191     if (!TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
) && !ButtonHitTest(evt
.m_x
, evt
.m_y
, &button
)) 
1193         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_BG_DCLICK
, m_windowId
); 
1194         e
.SetEventObject(this); 
1195         GetEventHandler()->ProcessEvent(e
); 
1199 void wxAuiTabCtrl::OnMotion(wxMouseEvent
& evt
) 
1201     wxPoint pos 
= evt
.GetPosition(); 
1203     // check if the mouse is hovering above a button 
1204     wxAuiTabContainerButton
* button
; 
1205     if (ButtonHitTest(pos
.x
, pos
.y
, &button
) && !(button
->curState 
& wxAUI_BUTTON_STATE_DISABLED
)) 
1207         if (m_hoverButton 
&& button 
!= m_hoverButton
) 
1209             m_hoverButton
->curState 
= wxAUI_BUTTON_STATE_NORMAL
; 
1210             m_hoverButton 
= NULL
; 
1215         if (button
->curState 
!= wxAUI_BUTTON_STATE_HOVER
) 
1217             button
->curState 
= wxAUI_BUTTON_STATE_HOVER
; 
1221             m_hoverButton 
= button
; 
1229             m_hoverButton
->curState 
= wxAUI_BUTTON_STATE_NORMAL
; 
1230             m_hoverButton 
= NULL
; 
1237     wxWindow
* wnd 
= NULL
; 
1238     if (evt
.Moving() && TabHitTest(evt
.m_x
, evt
.m_y
, &wnd
)) 
1240         wxString 
tooltip(m_pages
[GetIdxFromWindow(wnd
)].tooltip
); 
1242         // If the text changes, set it else, keep old, to avoid 
1243         // 'moving tooltip' effect 
1244         if (GetToolTipText() != tooltip
) 
1245             SetToolTip(tooltip
); 
1249 #endif // wxUSE_TOOLTIPS 
1251     if (!evt
.LeftIsDown() || m_clickPt 
== wxDefaultPosition
) 
1256         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_DRAG_MOTION
, m_windowId
); 
1257         e
.SetSelection(GetIdxFromWindow(m_clickTab
)); 
1258         e
.SetOldSelection(e
.GetSelection()); 
1259         e
.SetEventObject(this); 
1260         GetEventHandler()->ProcessEvent(e
); 
1265     int drag_x_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
); 
1266     int drag_y_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
); 
1268     if (abs(pos
.x 
- m_clickPt
.x
) > drag_x_threshold 
|| 
1269         abs(pos
.y 
- m_clickPt
.y
) > drag_y_threshold
) 
1271         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_BEGIN_DRAG
, m_windowId
); 
1272         e
.SetSelection(GetIdxFromWindow(m_clickTab
)); 
1273         e
.SetOldSelection(e
.GetSelection()); 
1274         e
.SetEventObject(this); 
1275         GetEventHandler()->ProcessEvent(e
); 
1277         m_isDragging 
= true; 
1281 void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
)) 
1285         m_hoverButton
->curState 
= wxAUI_BUTTON_STATE_NORMAL
; 
1286         m_hoverButton 
= NULL
; 
1292 void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent
& event
) 
1294     int button 
= event
.GetInt(); 
1296     if (button 
== wxAUI_BUTTON_LEFT 
|| button 
== wxAUI_BUTTON_RIGHT
) 
1298         if (button 
== wxAUI_BUTTON_LEFT
) 
1300             if (GetTabOffset() > 0) 
1302                 SetTabOffset(GetTabOffset()-1); 
1309             SetTabOffset(GetTabOffset()+1); 
1314     else if (button 
== wxAUI_BUTTON_WINDOWLIST
) 
1316         int idx 
= GetArtProvider()->ShowDropDown(this, m_pages
, GetActivePage()); 
1320             wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
1321             e
.SetSelection(idx
); 
1322             e
.SetOldSelection(GetActivePage()); 
1323             e
.SetEventObject(this); 
1324             GetEventHandler()->ProcessEvent(e
); 
1333 void wxAuiTabCtrl::OnSetFocus(wxFocusEvent
& WXUNUSED(event
)) 
1338 void wxAuiTabCtrl::OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) 
1343 void wxAuiTabCtrl::OnChar(wxKeyEvent
& event
) 
1345     if (GetActivePage() == -1) 
1351     // We can't leave tab processing to the system; on Windows, tabs and keys 
1352     // get eaten by the system and not processed properly if we specify both 
1353     // wxTAB_TRAVERSAL and wxWANTS_CHARS. And if we specify just wxTAB_TRAVERSAL, 
1354     // we don't key arrow key events. 
1356     int key 
= event
.GetKeyCode(); 
1358     if (key 
== WXK_NUMPAD_PAGEUP
) 
1360     if (key 
== WXK_NUMPAD_PAGEDOWN
) 
1362     if (key 
== WXK_NUMPAD_HOME
) 
1364     if (key 
== WXK_NUMPAD_END
) 
1366     if (key 
== WXK_NUMPAD_LEFT
) 
1368     if (key 
== WXK_NUMPAD_RIGHT
) 
1371     if (key 
== WXK_TAB 
|| key 
== WXK_PAGEUP 
|| key 
== WXK_PAGEDOWN
) 
1373         bool bCtrlDown 
= event
.ControlDown(); 
1374         bool bShiftDown 
= event
.ShiftDown(); 
1376         bool bForward 
= (key 
== WXK_TAB 
&& !bShiftDown
) || (key 
== WXK_PAGEDOWN
); 
1377         bool bWindowChange 
= (key 
== WXK_PAGEUP
) || (key 
== WXK_PAGEDOWN
) || bCtrlDown
; 
1378         bool bFromTab 
= (key 
== WXK_TAB
); 
1380         wxAuiNotebook
* nb 
= wxDynamicCast(GetParent(), wxAuiNotebook
); 
1387         wxNavigationKeyEvent keyEvent
; 
1388         keyEvent
.SetDirection(bForward
); 
1389         keyEvent
.SetWindowChange(bWindowChange
); 
1390         keyEvent
.SetFromTab(bFromTab
); 
1391         keyEvent
.SetEventObject(nb
); 
1393         if (!nb
->GetEventHandler()->ProcessEvent(keyEvent
)) 
1395             // Not processed? Do an explicit tab into the page. 
1396             wxWindow
* win 
= GetWindowFromIdx(GetActivePage()); 
1403     if (m_pages
.GetCount() < 2) 
1411     int forwardKey
, backwardKey
; 
1412     if (GetLayoutDirection() == wxLayout_RightToLeft
) 
1414         forwardKey 
= WXK_LEFT
; 
1415         backwardKey 
= WXK_RIGHT
; 
1419         forwardKey 
= WXK_RIGHT
; 
1420         backwardKey 
= WXK_LEFT
; 
1423     if (key 
== forwardKey
) 
1425         if (m_pages
.GetCount() > 1) 
1427             if (GetActivePage() == -1) 
1429             else if (GetActivePage() < (int) (m_pages
.GetCount() - 1)) 
1430                 newPage 
= GetActivePage() + 1; 
1433     else if (key 
== backwardKey
) 
1435         if (m_pages
.GetCount() > 1) 
1437             if (GetActivePage() == -1) 
1438                 newPage 
= (int) (m_pages
.GetCount() - 1); 
1439             else if (GetActivePage() > 0) 
1440                 newPage 
= GetActivePage() - 1; 
1443     else if (key 
== WXK_HOME
) 
1447     else if (key 
== WXK_END
) 
1449         newPage 
= (int) (m_pages
.GetCount() - 1); 
1456         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
1457         e
.SetSelection(newPage
); 
1458         e
.SetOldSelection(newPage
); 
1459         e
.SetEventObject(this); 
1460         this->GetEventHandler()->ProcessEvent(e
); 
1466 // wxTabFrame is an interesting case.  It's important that all child pages 
1467 // of the multi-notebook control are all actually children of that control 
1468 // (and not grandchildren).  wxTabFrame facilitates this.  There is one 
1469 // instance of wxTabFrame for each tab control inside the multi-notebook. 
1470 // It's important to know that wxTabFrame is not a real window, but it merely 
1471 // used to capture the dimensions/positioning of the internal tab control and 
1472 // it's managed page windows 
1474 class wxTabFrame 
: public wxWindow
 
1481         m_rect 
= wxRect(0,0,200,200); 
1482         m_tabCtrlHeight 
= 20; 
1490     void SetTabCtrlHeight(int h
) 
1492         m_tabCtrlHeight 
= h
; 
1496     void DoSetSize(int x
, int y
, 
1497                    int width
, int height
, 
1498                    int WXUNUSED(sizeFlags 
= wxSIZE_AUTO
)) 
1500         m_rect 
= wxRect(x
, y
, width
, height
); 
1504     void DoGetClientSize(int* x
, int* y
) const 
1511     bool Show( bool WXUNUSED(show 
= true) ) { return false; } 
1518         if (m_tabs
->IsFrozen() || m_tabs
->GetParent()->IsFrozen()) 
1521         m_tab_rect 
= wxRect(m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tabCtrlHeight
); 
1522         if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
) 
1524             m_tab_rect 
= wxRect (m_rect
.x
, m_rect
.y 
+ m_rect
.height 
- m_tabCtrlHeight
, m_rect
.width
, m_tabCtrlHeight
); 
1525             m_tabs
->SetSize     (m_rect
.x
, m_rect
.y 
+ m_rect
.height 
- m_tabCtrlHeight
, m_rect
.width
, m_tabCtrlHeight
); 
1526             m_tabs
->SetRect     (wxRect(0, 0, m_rect
.width
, m_tabCtrlHeight
)); 
1528         else //TODO: if (GetFlags() & wxAUI_NB_TOP) 
1530             m_tab_rect 
= wxRect (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tabCtrlHeight
); 
1531             m_tabs
->SetSize     (m_rect
.x
, m_rect
.y
, m_rect
.width
, m_tabCtrlHeight
); 
1532             m_tabs
->SetRect     (wxRect(0, 0,        m_rect
.width
, m_tabCtrlHeight
)); 
1534         // TODO: else if (GetFlags() & wxAUI_NB_LEFT){} 
1535         // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){} 
1540         wxAuiNotebookPageArray
& pages 
= m_tabs
->GetPages(); 
1541         size_t i
, page_count 
= pages
.GetCount(); 
1543         for (i 
= 0; i 
< page_count
; ++i
) 
1545             wxAuiNotebookPage
& page 
= pages
.Item(i
); 
1546             int border_space 
= m_tabs
->GetArtProvider()->GetAdditionalBorderSpace(page
.window
); 
1548             int height 
= m_rect
.height 
- m_tabCtrlHeight 
- border_space
; 
1551                 // avoid passing negative height to wxWindow::SetSize(), this 
1552                 // results in assert failures/GTK+ warnings 
1556             if (m_tabs
->GetFlags() & wxAUI_NB_BOTTOM
) 
1558                 page
.window
->SetSize(m_rect
.x 
+ border_space
, 
1559                                      m_rect
.y 
+ border_space
, 
1560                                      m_rect
.width 
- 2 * border_space
, 
1563             else //TODO: if (GetFlags() & wxAUI_NB_TOP) 
1565                 page
.window
->SetSize(m_rect
.x 
+ border_space
, 
1566                                      m_rect
.y 
+ m_tabCtrlHeight
, 
1567                                      m_rect
.width 
- 2 * border_space
, 
1570             // TODO: else if (GetFlags() & wxAUI_NB_LEFT){} 
1571             // TODO: else if (GetFlags() & wxAUI_NB_RIGHT){} 
1574             if (wxDynamicCast(page
.window
, wxAuiMDIChildFrame
)) 
1576                 wxAuiMDIChildFrame
* wnd 
= (wxAuiMDIChildFrame
*)page
.window
; 
1577                 wnd
->ApplyMDIChildFrameRect(); 
1584     void DoGetSize(int* x
, int* y
) const 
1587             *x 
= m_rect
.GetWidth(); 
1589             *y 
= m_rect
.GetHeight(); 
1600     wxAuiTabCtrl
* m_tabs
; 
1601     int m_tabCtrlHeight
; 
1605 const int wxAuiBaseTabCtrlId 
= 5380; 
1608 // -- wxAuiNotebook class implementation -- 
1610 #define EVT_AUI_RANGE(id1, id2, event, func) \ 
1611     wx__DECLARE_EVT2(event, id1, id2, wxAuiNotebookEventHandler(func)) 
1613 BEGIN_EVENT_TABLE(wxAuiNotebook
, wxControl
) 
1614     EVT_SIZE(wxAuiNotebook::OnSize
) 
1615     EVT_CHILD_FOCUS(wxAuiNotebook::OnChildFocusNotebook
) 
1616     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1617                       wxEVT_AUINOTEBOOK_PAGE_CHANGING
, 
1618                       wxAuiNotebook::OnTabClicked
) 
1619     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1620                       wxEVT_AUINOTEBOOK_BEGIN_DRAG
, 
1621                       wxAuiNotebook::OnTabBeginDrag
) 
1622     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1623                       wxEVT_AUINOTEBOOK_END_DRAG
, 
1624                       wxAuiNotebook::OnTabEndDrag
) 
1625     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1626                       wxEVT_AUINOTEBOOK_CANCEL_DRAG
, 
1627                       wxAuiNotebook::OnTabCancelDrag
) 
1628     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1629                       wxEVT_AUINOTEBOOK_DRAG_MOTION
, 
1630                       wxAuiNotebook::OnTabDragMotion
) 
1631     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1632                       wxEVT_AUINOTEBOOK_BUTTON
, 
1633                       wxAuiNotebook::OnTabButton
) 
1634     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1635                       wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
, 
1636                       wxAuiNotebook::OnTabMiddleDown
) 
1637     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1638                       wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP
, 
1639                       wxAuiNotebook::OnTabMiddleUp
) 
1640     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1641                       wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN
, 
1642                       wxAuiNotebook::OnTabRightDown
) 
1643     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1644                       wxEVT_AUINOTEBOOK_TAB_RIGHT_UP
, 
1645                       wxAuiNotebook::OnTabRightUp
) 
1646     EVT_AUI_RANGE(wxAuiBaseTabCtrlId
, wxAuiBaseTabCtrlId
+500, 
1647                       wxEVT_AUINOTEBOOK_BG_DCLICK
, 
1648                       wxAuiNotebook::OnTabBgDClick
) 
1649     EVT_NAVIGATION_KEY(wxAuiNotebook::OnNavigationKeyNotebook
) 
1652 void wxAuiNotebook::Init() 
1655     m_tabIdCounter 
= wxAuiBaseTabCtrlId
; 
1657     m_tabCtrlHeight 
= 20; 
1658     m_requestedBmpSize 
= wxDefaultSize
; 
1659     m_requestedTabCtrlHeight 
= -1; 
1662 bool wxAuiNotebook::Create(wxWindow
* parent
, 
1668     if (!wxControl::Create(parent
, id
, pos
, size
, style
)) 
1671     InitNotebook(style
); 
1676 // InitNotebook() contains common initialization 
1677 // code called by all constructors 
1678 void wxAuiNotebook::InitNotebook(long style
) 
1680     SetName(wxT("wxAuiNotebook")); 
1682     m_tabIdCounter 
= wxAuiBaseTabCtrlId
; 
1684     m_flags 
= (unsigned int)style
; 
1685     m_tabCtrlHeight 
= 20; 
1687     m_normalFont 
= *wxNORMAL_FONT
; 
1688     m_selectedFont 
= *wxNORMAL_FONT
; 
1689     m_selectedFont
.SetWeight(wxBOLD
); 
1691     SetArtProvider(new wxAuiDefaultTabArt
); 
1693     m_dummyWnd 
= new wxWindow(this, wxID_ANY
, wxPoint(0,0), wxSize(0,0)); 
1694     m_dummyWnd
->SetSize(200, 200); 
1695     m_dummyWnd
->Show(false); 
1697     m_mgr
.SetManagedWindow(this); 
1698     m_mgr
.SetFlags(wxAUI_MGR_DEFAULT
); 
1699     m_mgr
.SetDockSizeConstraint(1.0, 1.0); // no dock size constraint 
1701     m_mgr
.AddPane(m_dummyWnd
, 
1702               wxAuiPaneInfo().Name(wxT("dummy")).Bottom().CaptionVisible(false).Show(false)); 
1707 wxAuiNotebook::~wxAuiNotebook() 
1709     // Indicate we're deleting pages 
1712     while ( GetPageCount() > 0 ) 
1718 void wxAuiNotebook::SetArtProvider(wxAuiTabArt
* art
) 
1720     m_tabs
.SetArtProvider(art
); 
1722     // Update the height and do nothing else if it did something but otherwise 
1723     // (i.e. if the new art provider uses the same height as the old one) we 
1724     // need to manually set the art provider for all tabs ourselves. 
1725     if ( !UpdateTabCtrlHeight() ) 
1727         wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
1728         const size_t pane_count 
= all_panes
.GetCount(); 
1729         for (size_t i 
= 0; i 
< pane_count
; ++i
) 
1731             wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
1732             if (pane
.name 
== wxT("dummy")) 
1734             wxTabFrame
* tab_frame 
= (wxTabFrame
*)pane
.window
; 
1735             wxAuiTabCtrl
* tabctrl 
= tab_frame
->m_tabs
; 
1736             tabctrl
->SetArtProvider(art
->Clone()); 
1741 // SetTabCtrlHeight() is the highest-level override of the 
1742 // tab height.  A call to this function effectively enforces a 
1743 // specified tab ctrl height, overriding all other considerations, 
1744 // such as text or bitmap height.  It overrides any call to 
1745 // SetUniformBitmapSize().  Specifying a height of -1 reverts 
1746 // any previous call and returns to the default behaviour 
1748 void wxAuiNotebook::SetTabCtrlHeight(int height
) 
1750     m_requestedTabCtrlHeight 
= height
; 
1752     // if window is already initialized, recalculate the tab height 
1755         UpdateTabCtrlHeight(); 
1760 // SetUniformBitmapSize() ensures that all tabs will have 
1761 // the same height, even if some tabs don't have bitmaps 
1762 // Passing wxDefaultSize to this function will instruct 
1763 // the control to use dynamic tab height-- so when a tab 
1764 // with a large bitmap is added, the tab ctrl's height will 
1765 // automatically increase to accommodate the bitmap 
1767 void wxAuiNotebook::SetUniformBitmapSize(const wxSize
& size
) 
1769     m_requestedBmpSize 
= size
; 
1771     // if window is already initialized, recalculate the tab height 
1774         UpdateTabCtrlHeight(); 
1778 // UpdateTabCtrlHeight() does the actual tab resizing. It's meant 
1779 // to be used internally 
1780 bool wxAuiNotebook::UpdateTabCtrlHeight() 
1782     // get the tab ctrl height we will use 
1783     int height 
= CalculateTabCtrlHeight(); 
1785     // if the tab control height needs to change, update 
1786     // all of our tab controls with the new height 
1787     if (m_tabCtrlHeight 
== height
) 
1790     wxAuiTabArt
* art 
= m_tabs
.GetArtProvider(); 
1792     m_tabCtrlHeight 
= height
; 
1794     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
1795     size_t i
, pane_count 
= all_panes
.GetCount(); 
1796     for (i 
= 0; i 
< pane_count
; ++i
) 
1798         wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
1799         if (pane
.name 
== wxT("dummy")) 
1801         wxTabFrame
* tab_frame 
= (wxTabFrame
*)pane
.window
; 
1802         wxAuiTabCtrl
* tabctrl 
= tab_frame
->m_tabs
; 
1803         tab_frame
->SetTabCtrlHeight(m_tabCtrlHeight
); 
1804         tabctrl
->SetArtProvider(art
->Clone()); 
1805         tab_frame
->DoSizing(); 
1811 void wxAuiNotebook::UpdateHintWindowSize() 
1813     wxSize size 
= CalculateNewSplitSize(); 
1815     // the placeholder hint window should be set to this size 
1816     wxAuiPaneInfo
& info 
= m_mgr
.GetPane(wxT("dummy")); 
1820         info
.BestSize(size
); 
1821         m_dummyWnd
->SetSize(size
); 
1826 // calculates the size of the new split 
1827 wxSize 
wxAuiNotebook::CalculateNewSplitSize() 
1829     // count number of tab controls 
1830     int tab_ctrl_count 
= 0; 
1831     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
1832     size_t i
, pane_count 
= all_panes
.GetCount(); 
1833     for (i 
= 0; i 
< pane_count
; ++i
) 
1835         wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
1836         if (pane
.name 
== wxT("dummy")) 
1841     wxSize new_split_size
; 
1843     // if there is only one tab control, the first split 
1844     // should happen around the middle 
1845     if (tab_ctrl_count 
< 2) 
1847         new_split_size 
= GetClientSize(); 
1848         new_split_size
.x 
/= 2; 
1849         new_split_size
.y 
/= 2; 
1853         // this is in place of a more complicated calculation 
1854         // that needs to be implemented 
1855         new_split_size 
= wxSize(180,180); 
1858     return new_split_size
; 
1861 int wxAuiNotebook::CalculateTabCtrlHeight() 
1863     // if a fixed tab ctrl height is specified, 
1864     // just return that instead of calculating a 
1866     if (m_requestedTabCtrlHeight 
!= -1) 
1867         return m_requestedTabCtrlHeight
; 
1869     // find out new best tab height 
1870     wxAuiTabArt
* art 
= m_tabs
.GetArtProvider(); 
1872     return art
->GetBestTabCtrlSize(this, 
1874                                    m_requestedBmpSize
); 
1878 wxAuiTabArt
* wxAuiNotebook::GetArtProvider() const 
1880     return m_tabs
.GetArtProvider(); 
1883 void wxAuiNotebook::SetWindowStyleFlag(long style
) 
1885     wxControl::SetWindowStyleFlag(style
); 
1887     m_flags 
= (unsigned int)style
; 
1889     // if the control is already initialized 
1890     if (m_mgr
.GetManagedWindow() == (wxWindow
*)this) 
1892         // let all of the tab children know about the new style 
1894         wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
1895         size_t i
, pane_count 
= all_panes
.GetCount(); 
1896         for (i 
= 0; i 
< pane_count
; ++i
) 
1898             wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
1899             if (pane
.name 
== wxT("dummy")) 
1901             wxTabFrame
* tabframe 
= (wxTabFrame
*)pane
.window
; 
1902             wxAuiTabCtrl
* tabctrl 
= tabframe
->m_tabs
; 
1903             tabctrl
->SetFlags(m_flags
); 
1904             tabframe
->DoSizing(); 
1912 bool wxAuiNotebook::AddPage(wxWindow
* page
, 
1913                             const wxString
& caption
, 
1915                             const wxBitmap
& bitmap
) 
1917     return InsertPage(GetPageCount(), page
, caption
, select
, bitmap
); 
1920 bool wxAuiNotebook::InsertPage(size_t page_idx
, 
1922                                const wxString
& caption
, 
1924                                const wxBitmap
& bitmap
) 
1926     wxASSERT_MSG(page
, wxT("page pointer must be non-NULL")); 
1930     page
->Reparent(this); 
1932     wxAuiNotebookPage info
; 
1934     info
.caption 
= caption
; 
1935     info
.bitmap 
= bitmap
; 
1936     info
.active 
= false; 
1938     // if there are currently no tabs, the first added 
1939     // tab must be active 
1940     if (m_tabs
.GetPageCount() == 0) 
1943     m_tabs
.InsertPage(page
, info
, page_idx
); 
1945     // if that was the first page added, even if 
1946     // select is false, it must become the "current page" 
1947     // (though no select events will be fired) 
1948     if (!select 
&& m_tabs
.GetPageCount() == 1) 
1950         //m_curPage = GetPageIndex(page); 
1952     wxAuiTabCtrl
* active_tabctrl 
= GetActiveTabCtrl(); 
1953     if (page_idx 
>= active_tabctrl
->GetPageCount()) 
1954         active_tabctrl
->AddPage(page
, info
); 
1956         active_tabctrl
->InsertPage(page
, info
, page_idx
); 
1958     UpdateTabCtrlHeight(); 
1960     active_tabctrl
->DoShowHide(); 
1962     // adjust selected index 
1963     if(m_curPage 
>= (int) page_idx
) 
1968         SetSelectionToWindow(page
); 
1975 // DeletePage() removes a tab from the multi-notebook, 
1976 // and destroys the window as well 
1977 bool wxAuiNotebook::DeletePage(size_t page_idx
) 
1979     if (page_idx 
>= m_tabs
.GetPageCount()) 
1982     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(page_idx
); 
1984     // hide the window in advance, as this will 
1986     ShowWnd(wnd
, false); 
1988     if (!RemovePage(page_idx
)) 
1992     // actually destroy the window now 
1993     if (wxDynamicCast(wnd
, wxAuiMDIChildFrame
)) 
1995         // delete the child frame with pending delete, as is 
1996         // customary with frame windows 
1997         if (!wxPendingDelete
.Member(wnd
)) 
1998             wxPendingDelete
.Append(wnd
); 
2011 // RemovePage() removes a tab from the multi-notebook, 
2012 // but does not destroy the window 
2013 bool wxAuiNotebook::RemovePage(size_t page_idx
) 
2015     // save active window pointer 
2016     wxWindow
* active_wnd 
= NULL
; 
2018         active_wnd 
= m_tabs
.GetWindowFromIdx(m_curPage
); 
2020     // save pointer of window being deleted 
2021     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(page_idx
); 
2022     wxWindow
* new_active 
= NULL
; 
2024     // make sure we found the page 
2028     // find out which onscreen tab ctrl owns this tab 
2031     if (!FindTab(wnd
, &ctrl
, &ctrl_idx
)) 
2034     bool is_curpage 
= (m_curPage 
== (int)page_idx
); 
2035     bool is_active_in_split 
= ctrl
->GetPage(ctrl_idx
).active
; 
2038     // remove the tab from main catalog 
2039     if (!m_tabs
.RemovePage(wnd
)) 
2042     // remove the tab from the onscreen tab ctrl 
2043     ctrl
->RemovePage(wnd
); 
2045     if (is_active_in_split
) 
2047         int ctrl_new_page_count 
= (int)ctrl
->GetPageCount(); 
2049         if (ctrl_idx 
>= ctrl_new_page_count
) 
2050             ctrl_idx 
= ctrl_new_page_count
-1; 
2052         if (ctrl_idx 
>= 0 && ctrl_idx 
< (int)ctrl
->GetPageCount()) 
2054             // set new page as active in the tab split 
2055             ctrl
->SetActivePage(ctrl_idx
); 
2057             // if the page deleted was the current page for the 
2058             // entire tab control, then record the window 
2059             // pointer of the new active page for activation 
2062                 new_active 
= ctrl
->GetWindowFromIdx(ctrl_idx
); 
2068         // we are not deleting the active page, so keep it the same 
2069         new_active 
= active_wnd
; 
2075         // we haven't yet found a new page to active, 
2076         // so select the next page from the main tab 
2079         if (page_idx 
< m_tabs
.GetPageCount()) 
2081             new_active 
= m_tabs
.GetPage(page_idx
).window
; 
2084         if (!new_active 
&& m_tabs
.GetPageCount() > 0) 
2086             new_active 
= m_tabs
.GetPage(0).window
; 
2091     RemoveEmptyTabFrames(); 
2093     m_curPage 
= wxNOT_FOUND
; 
2095     // set new active pane unless we're being destroyed anyhow 
2096     if (new_active 
&& !m_isBeingDeleted
) 
2097         SetSelectionToWindow(new_active
); 
2102 // GetPageIndex() returns the index of the page, or -1 if the 
2103 // page could not be located in the notebook 
2104 int wxAuiNotebook::GetPageIndex(wxWindow
* page_wnd
) const 
2106     return m_tabs
.GetIdxFromWindow(page_wnd
); 
2111 // SetPageText() changes the tab caption of the specified page 
2112 bool wxAuiNotebook::SetPageText(size_t page_idx
, const wxString
& text
) 
2114     if (page_idx 
>= m_tabs
.GetPageCount()) 
2117     // update our own tab catalog 
2118     wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2119     page_info
.caption 
= text
; 
2121     // update what's on screen 
2124     if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
)) 
2126         wxAuiNotebookPage
& info 
= ctrl
->GetPage(ctrl_idx
); 
2127         info
.caption 
= text
; 
2135 // returns the page caption 
2136 wxString 
wxAuiNotebook::GetPageText(size_t page_idx
) const 
2138     if (page_idx 
>= m_tabs
.GetPageCount()) 
2139         return wxEmptyString
; 
2141     // update our own tab catalog 
2142     const wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2143     return page_info
.caption
; 
2146 bool wxAuiNotebook::SetPageToolTip(size_t page_idx
, const wxString
& text
) 
2148     if (page_idx 
>= m_tabs
.GetPageCount()) 
2151     // update our own tab catalog 
2152     wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2153     page_info
.tooltip 
= text
; 
2157     if (!FindTab(page_info
.window
, &ctrl
, &ctrl_idx
)) 
2160     wxAuiNotebookPage
& info 
= ctrl
->GetPage(ctrl_idx
); 
2161     info
.tooltip 
= text
; 
2163     // NB: we don't update the tooltip if it is already being displayed, it 
2164     //     typically never happens, no need to code that 
2168 wxString 
wxAuiNotebook::GetPageToolTip(size_t page_idx
) const 
2170     if (page_idx 
>= m_tabs
.GetPageCount()) 
2173     const wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2174     return page_info
.tooltip
; 
2177 bool wxAuiNotebook::SetPageBitmap(size_t page_idx
, const wxBitmap
& bitmap
) 
2179     if (page_idx 
>= m_tabs
.GetPageCount()) 
2182     // update our own tab catalog 
2183     wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2184     page_info
.bitmap 
= bitmap
; 
2186     // tab height might have changed 
2187     UpdateTabCtrlHeight(); 
2189     // update what's on screen 
2192     if (FindTab(page_info
.window
, &ctrl
, &ctrl_idx
)) 
2194         wxAuiNotebookPage
& info 
= ctrl
->GetPage(ctrl_idx
); 
2195         info
.bitmap 
= bitmap
; 
2203 // returns the page bitmap 
2204 wxBitmap 
wxAuiNotebook::GetPageBitmap(size_t page_idx
) const 
2206     if (page_idx 
>= m_tabs
.GetPageCount()) 
2209     // update our own tab catalog 
2210     const wxAuiNotebookPage
& page_info 
= m_tabs
.GetPage(page_idx
); 
2211     return page_info
.bitmap
; 
2214 // GetSelection() returns the index of the currently active page 
2215 int wxAuiNotebook::GetSelection() const 
2220 // SetSelection() sets the currently active page 
2221 int wxAuiNotebook::SetSelection(size_t new_page
) 
2223     return DoModifySelection(new_page
, true); 
2226 void wxAuiNotebook::SetSelectionToWindow(wxWindow 
*win
) 
2228     const int idx 
= m_tabs
.GetIdxFromWindow(win
); 
2229     wxCHECK_RET( idx 
!= wxNOT_FOUND
, wxT("invalid notebook page") ); 
2232     // since a tab was clicked, let the parent know that we received 
2233     // the focus, even if we will assign that focus immediately 
2234     // to the child tab in the SetSelection call below 
2235     // (the child focus event will also let wxAuiManager, if any, 
2236     // know that the notebook control has been activated) 
2238     wxWindow
* parent 
= GetParent(); 
2241         wxChildFocusEvent 
eventFocus(this); 
2242         parent
->GetEventHandler()->ProcessEvent(eventFocus
); 
2249 // GetPageCount() returns the total number of 
2250 // pages managed by the multi-notebook 
2251 size_t wxAuiNotebook::GetPageCount() const 
2253     return m_tabs
.GetPageCount(); 
2256 // GetPage() returns the wxWindow pointer of the 
2258 wxWindow
* wxAuiNotebook::GetPage(size_t page_idx
) const 
2260     wxASSERT(page_idx 
< m_tabs
.GetPageCount()); 
2262     return m_tabs
.GetWindowFromIdx(page_idx
); 
2265 // DoSizing() performs all sizing operations in each tab control 
2266 void wxAuiNotebook::DoSizing() 
2268     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2269     size_t i
, pane_count 
= all_panes
.GetCount(); 
2270     for (i 
= 0; i 
< pane_count
; ++i
) 
2272         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2275         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2276         tabframe
->DoSizing(); 
2280 // GetActiveTabCtrl() returns the active tab control.  It is 
2281 // called to determine which control gets new windows being added 
2282 wxAuiTabCtrl
* wxAuiNotebook::GetActiveTabCtrl() 
2284     if (m_curPage 
>= 0 && m_curPage 
< (int)m_tabs
.GetPageCount()) 
2289         // find the tab ctrl with the current page 
2290         if (FindTab(m_tabs
.GetPage(m_curPage
).window
, 
2297     // no current page, just find the first tab ctrl 
2298     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2299     size_t i
, pane_count 
= all_panes
.GetCount(); 
2300     for (i 
= 0; i 
< pane_count
; ++i
) 
2302         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2305         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2306         return tabframe
->m_tabs
; 
2309     // If there is no tabframe at all, create one 
2310     wxTabFrame
* tabframe 
= new wxTabFrame
; 
2311     tabframe
->SetTabCtrlHeight(m_tabCtrlHeight
); 
2312     tabframe
->m_tabs 
= new wxAuiTabCtrl(this, 
2316                                         wxNO_BORDER
|wxWANTS_CHARS
); 
2317     tabframe
->m_tabs
->SetFlags(m_flags
); 
2318     tabframe
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
2319     m_mgr
.AddPane(tabframe
, 
2320                   wxAuiPaneInfo().Center().CaptionVisible(false)); 
2324     return tabframe
->m_tabs
; 
2327 // FindTab() finds the tab control that currently contains the window as well 
2328 // as the index of the window in the tab control.  It returns true if the 
2329 // window was found, otherwise false. 
2330 bool wxAuiNotebook::FindTab(wxWindow
* page
, wxAuiTabCtrl
** ctrl
, int* idx
) 
2332     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2333     size_t i
, pane_count 
= all_panes
.GetCount(); 
2334     for (i 
= 0; i 
< pane_count
; ++i
) 
2336         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2339         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2341         int page_idx 
= tabframe
->m_tabs
->GetIdxFromWindow(page
); 
2344             *ctrl 
= tabframe
->m_tabs
; 
2353 void wxAuiNotebook::Split(size_t page
, int direction
) 
2355     wxSize cli_size 
= GetClientSize(); 
2357     // get the page's window pointer 
2358     wxWindow
* wnd 
= GetPage(page
); 
2362     // notebooks with 1 or less pages can't be split 
2363     if (GetPageCount() < 2) 
2366     // find out which tab control the page currently belongs to 
2367     wxAuiTabCtrl 
*src_tabs
, *dest_tabs
; 
2370     if (!FindTab(wnd
, &src_tabs
, &src_idx
)) 
2372     if (!src_tabs 
|| src_idx 
== -1) 
2375     // choose a split size 
2377     if (GetPageCount() > 2) 
2379         split_size 
= CalculateNewSplitSize(); 
2383         // because there are two panes, always split them 
2385         split_size 
= GetClientSize(); 
2391     // create a new tab frame 
2392     wxTabFrame
* new_tabs 
= new wxTabFrame
; 
2393     new_tabs
->m_rect 
= wxRect(wxPoint(0,0), split_size
); 
2394     new_tabs
->SetTabCtrlHeight(m_tabCtrlHeight
); 
2395     new_tabs
->m_tabs 
= new wxAuiTabCtrl(this, 
2399                                         wxNO_BORDER
|wxWANTS_CHARS
); 
2400     new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
2401     new_tabs
->m_tabs
->SetFlags(m_flags
); 
2402     dest_tabs 
= new_tabs
->m_tabs
; 
2404     // create a pane info structure with the information 
2405     // about where the pane should be added 
2406     wxAuiPaneInfo paneInfo 
= wxAuiPaneInfo().Bottom().CaptionVisible(false); 
2409     if (direction 
== wxLEFT
) 
2412         mouse_pt 
= wxPoint(0, cli_size
.y
/2); 
2414     else if (direction 
== wxRIGHT
) 
2417         mouse_pt 
= wxPoint(cli_size
.x
, cli_size
.y
/2); 
2419     else if (direction 
== wxTOP
) 
2422         mouse_pt 
= wxPoint(cli_size
.x
/2, 0); 
2424     else if (direction 
== wxBOTTOM
) 
2427         mouse_pt 
= wxPoint(cli_size
.x
/2, cli_size
.y
); 
2430     m_mgr
.AddPane(new_tabs
, paneInfo
, mouse_pt
); 
2433     // remove the page from the source tabs 
2434     wxAuiNotebookPage page_info 
= src_tabs
->GetPage(src_idx
); 
2435     page_info
.active 
= false; 
2436     src_tabs
->RemovePage(page_info
.window
); 
2437     if (src_tabs
->GetPageCount() > 0) 
2439         src_tabs
->SetActivePage((size_t)0); 
2440         src_tabs
->DoShowHide(); 
2441         src_tabs
->Refresh(); 
2445     // add the page to the destination tabs 
2446     dest_tabs
->InsertPage(page_info
.window
, page_info
, 0); 
2448     if (src_tabs
->GetPageCount() == 0) 
2450         RemoveEmptyTabFrames(); 
2454     dest_tabs
->DoShowHide(); 
2455     dest_tabs
->Refresh(); 
2457     // force the set selection function reset the selection 
2460     // set the active page to the one we just split off 
2461     SetSelectionToPage(page_info
); 
2463     UpdateHintWindowSize(); 
2467 void wxAuiNotebook::OnSize(wxSizeEvent
& evt
) 
2469     UpdateHintWindowSize(); 
2474 void wxAuiNotebook::OnTabClicked(wxAuiNotebookEvent
& evt
) 
2476     wxAuiTabCtrl
* ctrl 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
2477     wxASSERT(ctrl 
!= NULL
); 
2479     wxWindow
* wnd 
= ctrl
->GetWindowFromIdx(evt
.GetSelection()); 
2480     wxASSERT(wnd 
!= NULL
); 
2482     SetSelectionToWindow(wnd
); 
2485 void wxAuiNotebook::OnTabBgDClick(wxAuiNotebookEvent
& evt
) 
2487     // select the tab ctrl which received the db click 
2490     wxAuiTabCtrl
* ctrl 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
2492         && ((selection 
= ctrl
->GetActivePage()) != wxNOT_FOUND
) 
2493         && ((wnd 
= ctrl
->GetWindowFromIdx(selection
)) != NULL
)) 
2495         SetSelectionToWindow(wnd
); 
2498     // notify owner that the tabbar background has been double-clicked 
2499     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_BG_DCLICK
, m_windowId
); 
2500     e
.SetEventObject(this); 
2501     GetEventHandler()->ProcessEvent(e
); 
2504 void wxAuiNotebook::OnTabBeginDrag(wxAuiNotebookEvent
&) 
2509 void wxAuiNotebook::OnTabDragMotion(wxAuiNotebookEvent
& evt
) 
2511     wxPoint screen_pt 
= ::wxGetMousePosition(); 
2512     wxPoint client_pt 
= ScreenToClient(screen_pt
); 
2515     wxAuiTabCtrl
* src_tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
2516     wxAuiTabCtrl
* dest_tabs 
= GetTabCtrlFromPoint(client_pt
); 
2518     if (dest_tabs 
== src_tabs
) 
2522             src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
)); 
2525         // always hide the hint for inner-tabctrl drag 
2528         // if tab moving is not allowed, leave 
2529         if (!(m_flags 
& wxAUI_NB_TAB_MOVE
)) 
2534         wxPoint pt 
= dest_tabs
->ScreenToClient(screen_pt
); 
2535         wxWindow
* dest_location_tab
; 
2537         // this is an inner-tab drag/reposition 
2538         if (dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &dest_location_tab
)) 
2540             int src_idx 
= evt
.GetSelection(); 
2541             int dest_idx 
= dest_tabs
->GetIdxFromWindow(dest_location_tab
); 
2543             // prevent jumpy drag 
2544             if ((src_idx 
== dest_idx
) || dest_idx 
== -1 || 
2545                 (src_idx 
> dest_idx 
&& m_lastDragX 
<= pt
.x
) || 
2546                 (src_idx 
< dest_idx 
&& m_lastDragX 
>= pt
.x
)) 
2553             wxWindow
* src_tab 
= dest_tabs
->GetWindowFromIdx(src_idx
); 
2554             dest_tabs
->MovePage(src_tab
, dest_idx
); 
2555             m_tabs
.MovePage(m_tabs
.GetPage(src_idx
).window
, dest_idx
); 
2556             dest_tabs
->SetActivePage((size_t)dest_idx
); 
2557             dest_tabs
->DoShowHide(); 
2558             dest_tabs
->Refresh(); 
2567     // if external drag is allowed, check if the tab is being dragged 
2568     // over a different wxAuiNotebook control 
2569     if (m_flags 
& wxAUI_NB_TAB_EXTERNAL_MOVE
) 
2571         wxWindow
* tab_ctrl 
= ::wxFindWindowAtPoint(screen_pt
); 
2573         // if we aren't over any window, stop here 
2577         // make sure we are not over the hint window 
2578         if (!wxDynamicCast(tab_ctrl
, wxFrame
)) 
2582                 if (wxDynamicCast(tab_ctrl
, wxAuiTabCtrl
)) 
2584                 tab_ctrl 
= tab_ctrl
->GetParent(); 
2589                 wxAuiNotebook
* nb 
= (wxAuiNotebook
*)tab_ctrl
->GetParent(); 
2593                     wxRect hint_rect 
= tab_ctrl
->GetClientRect(); 
2594                     tab_ctrl
->ClientToScreen(&hint_rect
.x
, &hint_rect
.y
); 
2595                     m_mgr
.ShowHint(hint_rect
); 
2604                 // we are either over a hint window, or not over a tab 
2605                 // window, and there is no where to drag to, so exit 
2612     // if there are less than two panes, split can't happen, so leave 
2613     if (m_tabs
.GetPageCount() < 2) 
2616     // if tab moving is not allowed, leave 
2617     if (!(m_flags 
& wxAUI_NB_TAB_SPLIT
)) 
2623         src_tabs
->SetCursor(wxCursor(wxCURSOR_SIZING
)); 
2629         wxRect hint_rect 
= dest_tabs
->GetRect(); 
2630         ClientToScreen(&hint_rect
.x
, &hint_rect
.y
); 
2631         m_mgr
.ShowHint(hint_rect
); 
2635         m_mgr
.DrawHintRect(m_dummyWnd
, client_pt
, zero
); 
2641 void wxAuiNotebook::OnTabEndDrag(wxAuiNotebookEvent
& evt
) 
2646     wxAuiTabCtrl
* src_tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
2647     wxCHECK_RET( src_tabs
, wxT("no source object?") ); 
2649     src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
)); 
2651     // get the mouse position, which will be used to determine the drop point 
2652     wxPoint mouse_screen_pt 
= ::wxGetMousePosition(); 
2653     wxPoint mouse_client_pt 
= ScreenToClient(mouse_screen_pt
); 
2657     // check for an external move 
2658     if (m_flags 
& wxAUI_NB_TAB_EXTERNAL_MOVE
) 
2660         wxWindow
* tab_ctrl 
= ::wxFindWindowAtPoint(mouse_screen_pt
); 
2664             if (wxDynamicCast(tab_ctrl
, wxAuiTabCtrl
)) 
2666             tab_ctrl 
= tab_ctrl
->GetParent(); 
2671             wxAuiNotebook
* nb 
= (wxAuiNotebook
*)tab_ctrl
->GetParent(); 
2675                 // find out from the destination control 
2676                 // if it's ok to drop this tab here 
2677                 wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_ALLOW_DND
, m_windowId
); 
2678                 e
.SetSelection(evt
.GetSelection()); 
2679                 e
.SetOldSelection(evt
.GetSelection()); 
2680                 e
.SetEventObject(this); 
2681                 e
.SetDragSource(this); 
2682                 e
.Veto(); // dropping must be explicitly approved by control owner 
2684                 nb
->GetEventHandler()->ProcessEvent(e
); 
2688                     // no answer or negative answer 
2694                 int src_idx 
= evt
.GetSelection(); 
2695                 wxWindow
* src_page 
= src_tabs
->GetWindowFromIdx(src_idx
); 
2697                 // Check that it's not an impossible parent relationship 
2699                 while (p 
&& !p
->IsTopLevel()) 
2708                 // get main index of the page 
2709                 int main_idx 
= m_tabs
.GetIdxFromWindow(src_page
); 
2710                 wxCHECK_RET( main_idx 
!= wxNOT_FOUND
, wxT("no source page?") ); 
2713                 // make a copy of the page info 
2714                 wxAuiNotebookPage page_info 
= m_tabs
.GetPage(main_idx
); 
2716                 // remove the page from the source notebook 
2717                 RemovePage(main_idx
); 
2719                 // reparent the page 
2720                 src_page
->Reparent(nb
); 
2723                 // found out the insert idx 
2724                 wxAuiTabCtrl
* dest_tabs 
= (wxAuiTabCtrl
*)tab_ctrl
; 
2725                 wxPoint pt 
= dest_tabs
->ScreenToClient(mouse_screen_pt
); 
2727                 wxWindow
* target 
= NULL
; 
2728                 int insert_idx 
= -1; 
2729                 dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
); 
2732                     insert_idx 
= dest_tabs
->GetIdxFromWindow(target
); 
2736                 // add the page to the new notebook 
2737                 if (insert_idx 
== -1) 
2738                     insert_idx 
= dest_tabs
->GetPageCount(); 
2739                 dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
); 
2740                 nb
->m_tabs
.InsertPage(page_info
.window
, page_info
, insert_idx
); 
2743                 dest_tabs
->DoShowHide(); 
2744                 dest_tabs
->Refresh(); 
2746                 // set the selection in the destination tab control 
2747                 nb
->SetSelectionToPage(page_info
); 
2749                 // notify owner that the tab has been dragged 
2750                 wxAuiNotebookEvent 
e2(wxEVT_AUINOTEBOOK_DRAG_DONE
, m_windowId
); 
2751                 e2
.SetSelection(evt
.GetSelection()); 
2752                 e2
.SetOldSelection(evt
.GetSelection()); 
2753                 e2
.SetEventObject(this); 
2754                 GetEventHandler()->ProcessEvent(e2
); 
2764     // only perform a tab split if it's allowed 
2765     wxAuiTabCtrl
* dest_tabs 
= NULL
; 
2767     if ((m_flags 
& wxAUI_NB_TAB_SPLIT
) && m_tabs
.GetPageCount() >= 2) 
2769         // If the pointer is in an existing tab frame, do a tab insert 
2770         wxWindow
* hit_wnd 
= ::wxFindWindowAtPoint(mouse_screen_pt
); 
2771         wxTabFrame
* tab_frame 
= (wxTabFrame
*)GetTabFrameFromTabCtrl(hit_wnd
); 
2772         int insert_idx 
= -1; 
2775             dest_tabs 
= tab_frame
->m_tabs
; 
2777             if (dest_tabs 
== src_tabs
) 
2781             wxPoint pt 
= dest_tabs
->ScreenToClient(mouse_screen_pt
); 
2782             wxWindow
* target 
= NULL
; 
2783             dest_tabs
->TabHitTest(pt
.x
, pt
.y
, &target
); 
2786                 insert_idx 
= dest_tabs
->GetIdxFromWindow(target
); 
2792             wxRect rect 
= m_mgr
.CalculateHintRect(m_dummyWnd
, 
2797                 // there is no suitable drop location here, exit out 
2801             // If there is no tabframe at all, create one 
2802             wxTabFrame
* new_tabs 
= new wxTabFrame
; 
2803             new_tabs
->m_rect 
= wxRect(wxPoint(0,0), CalculateNewSplitSize()); 
2804             new_tabs
->SetTabCtrlHeight(m_tabCtrlHeight
); 
2805             new_tabs
->m_tabs 
= new wxAuiTabCtrl(this, 
2809                                                 wxNO_BORDER
|wxWANTS_CHARS
); 
2810             new_tabs
->m_tabs
->SetArtProvider(m_tabs
.GetArtProvider()->Clone()); 
2811             new_tabs
->m_tabs
->SetFlags(m_flags
); 
2813             m_mgr
.AddPane(new_tabs
, 
2814                           wxAuiPaneInfo().Bottom().CaptionVisible(false), 
2817             dest_tabs 
= new_tabs
->m_tabs
; 
2822         // remove the page from the source tabs 
2823         wxAuiNotebookPage page_info 
= src_tabs
->GetPage(evt
.GetSelection()); 
2824         page_info
.active 
= false; 
2825         src_tabs
->RemovePage(page_info
.window
); 
2826         if (src_tabs
->GetPageCount() > 0) 
2828             src_tabs
->SetActivePage((size_t)0); 
2829             src_tabs
->DoShowHide(); 
2830             src_tabs
->Refresh(); 
2835         // add the page to the destination tabs 
2836         if (insert_idx 
== -1) 
2837             insert_idx 
= dest_tabs
->GetPageCount(); 
2838         dest_tabs
->InsertPage(page_info
.window
, page_info
, insert_idx
); 
2840         if (src_tabs
->GetPageCount() == 0) 
2842             RemoveEmptyTabFrames(); 
2846         dest_tabs
->DoShowHide(); 
2847         dest_tabs
->Refresh(); 
2849         // force the set selection function reset the selection 
2852         // set the active page to the one we just split off 
2853         SetSelectionToPage(page_info
); 
2855         UpdateHintWindowSize(); 
2858     // notify owner that the tab has been dragged 
2859     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_DRAG_DONE
, m_windowId
); 
2860     e
.SetSelection(evt
.GetSelection()); 
2861     e
.SetOldSelection(evt
.GetSelection()); 
2862     e
.SetEventObject(this); 
2863     GetEventHandler()->ProcessEvent(e
); 
2868 void wxAuiNotebook::OnTabCancelDrag(wxAuiNotebookEvent
& command_evt
) 
2870     wxAuiNotebookEvent
& evt 
= (wxAuiNotebookEvent
&)command_evt
; 
2874     wxAuiTabCtrl
* src_tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
2875     wxCHECK_RET( src_tabs
, wxT("no source object?") ); 
2877     src_tabs
->SetCursor(wxCursor(wxCURSOR_ARROW
)); 
2880 wxAuiTabCtrl
* wxAuiNotebook::GetTabCtrlFromPoint(const wxPoint
& pt
) 
2882     // if we've just removed the last tab from the source 
2883     // tab set, the remove the tab control completely 
2884     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2885     size_t i
, pane_count 
= all_panes
.GetCount(); 
2886     for (i 
= 0; i 
< pane_count
; ++i
) 
2888         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2891         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2892         if (tabframe
->m_tab_rect
.Contains(pt
)) 
2893             return tabframe
->m_tabs
; 
2899 wxWindow
* wxAuiNotebook::GetTabFrameFromTabCtrl(wxWindow
* tab_ctrl
) 
2901     // if we've just removed the last tab from the source 
2902     // tab set, the remove the tab control completely 
2903     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2904     size_t i
, pane_count 
= all_panes
.GetCount(); 
2905     for (i 
= 0; i 
< pane_count
; ++i
) 
2907         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2910         wxTabFrame
* tabframe 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2911         if (tabframe
->m_tabs 
== tab_ctrl
) 
2920 void wxAuiNotebook::RemoveEmptyTabFrames() 
2922     // if we've just removed the last tab from the source 
2923     // tab set, the remove the tab control completely 
2924     wxAuiPaneInfoArray all_panes 
= m_mgr
.GetAllPanes(); 
2925     size_t i
, pane_count 
= all_panes
.GetCount(); 
2926     for (i 
= 0; i 
< pane_count
; ++i
) 
2928         if (all_panes
.Item(i
).name 
== wxT("dummy")) 
2931         wxTabFrame
* tab_frame 
= (wxTabFrame
*)all_panes
.Item(i
).window
; 
2932         if (tab_frame
->m_tabs
->GetPageCount() == 0) 
2934             m_mgr
.DetachPane(tab_frame
); 
2936             // use pending delete because sometimes during 
2937             // window closing, refreshs are pending 
2938             if (!wxPendingDelete
.Member(tab_frame
->m_tabs
)) 
2939                 wxPendingDelete
.Append(tab_frame
->m_tabs
); 
2941             tab_frame
->m_tabs 
= NULL
; 
2948     // check to see if there is still a center pane; 
2949     // if there isn't, make a frame the center pane 
2950     wxAuiPaneInfoArray panes 
= m_mgr
.GetAllPanes(); 
2951     pane_count 
= panes
.GetCount(); 
2952     wxWindow
* first_good 
= NULL
; 
2953     bool center_found 
= false; 
2954     for (i 
= 0; i 
< pane_count
; ++i
) 
2956         if (panes
.Item(i
).name 
== wxT("dummy")) 
2958         if (panes
.Item(i
).dock_direction 
== wxAUI_DOCK_CENTRE
) 
2959             center_found 
= true; 
2961             first_good 
= panes
.Item(i
).window
; 
2964     if (!center_found 
&& first_good
) 
2966         m_mgr
.GetPane(first_good
).Centre(); 
2969     if (!m_isBeingDeleted
) 
2973 void wxAuiNotebook::OnChildFocusNotebook(wxChildFocusEvent
& evt
) 
2977     // if we're dragging a tab, don't change the current selection. 
2978     // This code prevents a bug that used to happen when the hint window 
2979     // was hidden.  In the bug, the focus would return to the notebook 
2980     // child, which would then enter this handler and call 
2981     // SetSelection, which is not desired turn tab dragging. 
2983     wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
2984     size_t i
, pane_count 
= all_panes
.GetCount(); 
2985     for (i 
= 0; i 
< pane_count
; ++i
) 
2987         wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
2988         if (pane
.name 
== wxT("dummy")) 
2990         wxTabFrame
* tabframe 
= (wxTabFrame
*)pane
.window
; 
2991         if (tabframe
->m_tabs
->IsDragging()) 
2996     // change the tab selection to the child 
2997     // which was focused 
2998     int idx 
= m_tabs
.GetIdxFromWindow(evt
.GetWindow()); 
2999     if (idx 
!= -1 && idx 
!= m_curPage
) 
3005 void wxAuiNotebook::OnNavigationKeyNotebook(wxNavigationKeyEvent
& event
) 
3007     if ( event
.IsWindowChange() ) { 
3009         // FIXME: the problem with this is that if we have a split notebook, 
3010         // we selection may go all over the place. 
3011         AdvanceSelection(event
.GetDirection()); 
3014         // we get this event in 3 cases 
3016         // a) one of our pages might have generated it because the user TABbed 
3017         // out from it in which case we should propagate the event upwards and 
3018         // our parent will take care of setting the focus to prev/next sibling 
3022         // b) the parent panel wants to give the focus to us so that we 
3023         // forward it to our selected page. We can't deal with this in 
3024         // OnSetFocus() because we don't know which direction the focus came 
3025         // from in this case and so can't choose between setting the focus to 
3026         // first or last panel child 
3030         // c) we ourselves (see MSWTranslateMessage) generated the event 
3032         wxWindow 
* const parent 
= GetParent(); 
3034         // the wxObject* casts are required to avoid MinGW GCC 2.95.3 ICE 
3035         const bool isFromParent 
= event
.GetEventObject() == (wxObject
*) parent
; 
3036         const bool isFromSelf 
= event
.GetEventObject() == (wxObject
*) this; 
3038         if ( isFromParent 
|| isFromSelf 
) 
3040             // no, it doesn't come from child, case (b) or (c): forward to a 
3041             // page but only if direction is backwards (TAB) or from ourselves, 
3042             if ( GetSelection() != wxNOT_FOUND 
&& 
3043                     (!event
.GetDirection() || isFromSelf
) ) 
3045                 // so that the page knows that the event comes from it's parent 
3046                 // and is being propagated downwards 
3047                 event
.SetEventObject(this); 
3049                 wxWindow 
*page 
= GetPage(GetSelection()); 
3050                 if ( !page
->GetEventHandler()->ProcessEvent(event
) ) 
3054                 //else: page manages focus inside it itself 
3056             else // otherwise set the focus to the notebook itself 
3063             // it comes from our child, case (a), pass to the parent, but only 
3064             // if the direction is forwards. Otherwise set the focus to the 
3065             // notebook itself. The notebook is always the 'first' control of a 
3067             if ( !event
.GetDirection() ) 
3073                 event
.SetCurrentFocus(this); 
3074                 parent
->GetEventHandler()->ProcessEvent(event
); 
3080 void wxAuiNotebook::OnTabButton(wxAuiNotebookEvent
& evt
) 
3082     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3084     int button_id 
= evt
.GetInt(); 
3086     if (button_id 
== wxAUI_BUTTON_CLOSE
) 
3088         int selection 
= evt
.GetSelection(); 
3090         if (selection 
== -1) 
3092             // if the close button is to the right, use the active 
3093             // page selection to determine which page to close 
3094             selection 
= tabs
->GetActivePage(); 
3097         if (selection 
!= -1) 
3099             wxWindow
* close_wnd 
= tabs
->GetWindowFromIdx(selection
); 
3101             // ask owner if it's ok to close the tab 
3102             wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_PAGE_CLOSE
, m_windowId
); 
3103             e
.SetSelection(m_tabs
.GetIdxFromWindow(close_wnd
)); 
3104             const int idx 
= m_tabs
.GetIdxFromWindow(close_wnd
); 
3105             e
.SetSelection(idx
); 
3106             e
.SetOldSelection(evt
.GetSelection()); 
3107             e
.SetEventObject(this); 
3108             GetEventHandler()->ProcessEvent(e
); 
3114             if (wxDynamicCast(close_wnd
, wxAuiMDIChildFrame
)) 
3121                 int main_idx 
= m_tabs
.GetIdxFromWindow(close_wnd
); 
3122                 wxCHECK_RET( main_idx 
!= wxNOT_FOUND
, wxT("no page to delete?") ); 
3124                 DeletePage(main_idx
); 
3127             // notify owner that the tab has been closed 
3128             wxAuiNotebookEvent 
e2(wxEVT_AUINOTEBOOK_PAGE_CLOSED
, m_windowId
); 
3129             e2
.SetSelection(idx
); 
3130             e2
.SetEventObject(this); 
3131             GetEventHandler()->ProcessEvent(e2
); 
3137 void wxAuiNotebook::OnTabMiddleDown(wxAuiNotebookEvent
& evt
) 
3139     // patch event through to owner 
3140     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3141     wxWindow
* wnd 
= tabs
->GetWindowFromIdx(evt
.GetSelection()); 
3143     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
, m_windowId
); 
3144     e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
)); 
3145     e
.SetEventObject(this); 
3146     GetEventHandler()->ProcessEvent(e
); 
3149 void wxAuiNotebook::OnTabMiddleUp(wxAuiNotebookEvent
& evt
) 
3151     // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle 
3152     // click should act like a tab close action.  However, first 
3153     // give the owner an opportunity to handle the middle up event 
3154     // for custom action 
3156     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3157     wxWindow
* wnd 
= tabs
->GetWindowFromIdx(evt
.GetSelection()); 
3159     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_MIDDLE_UP
, m_windowId
); 
3160     e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
)); 
3161     e
.SetEventObject(this); 
3162     if (GetEventHandler()->ProcessEvent(e
)) 
3167     // check if we are supposed to close on middle-up 
3168     if ((m_flags 
& wxAUI_NB_MIDDLE_CLICK_CLOSE
) == 0) 
3171     // simulate the user pressing the close button on the tab 
3172     evt
.SetInt(wxAUI_BUTTON_CLOSE
); 
3176 void wxAuiNotebook::OnTabRightDown(wxAuiNotebookEvent
& evt
) 
3178     // patch event through to owner 
3179     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3180     wxWindow
* wnd 
= tabs
->GetWindowFromIdx(evt
.GetSelection()); 
3182     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN
, m_windowId
); 
3183     e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
)); 
3184     e
.SetEventObject(this); 
3185     GetEventHandler()->ProcessEvent(e
); 
3188 void wxAuiNotebook::OnTabRightUp(wxAuiNotebookEvent
& evt
) 
3190     // patch event through to owner 
3191     wxAuiTabCtrl
* tabs 
= (wxAuiTabCtrl
*)evt
.GetEventObject(); 
3192     wxWindow
* wnd 
= tabs
->GetWindowFromIdx(evt
.GetSelection()); 
3194     wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP
, m_windowId
); 
3195     e
.SetSelection(m_tabs
.GetIdxFromWindow(wnd
)); 
3196     e
.SetEventObject(this); 
3197     GetEventHandler()->ProcessEvent(e
); 
3200 // Sets the normal font 
3201 void wxAuiNotebook::SetNormalFont(const wxFont
& font
) 
3203     m_normalFont 
= font
; 
3204     GetArtProvider()->SetNormalFont(font
); 
3207 // Sets the selected tab font 
3208 void wxAuiNotebook::SetSelectedFont(const wxFont
& font
) 
3210     m_selectedFont 
= font
; 
3211     GetArtProvider()->SetSelectedFont(font
); 
3214 // Sets the measuring font 
3215 void wxAuiNotebook::SetMeasuringFont(const wxFont
& font
) 
3217     GetArtProvider()->SetMeasuringFont(font
); 
3220 // Sets the tab font 
3221 bool wxAuiNotebook::SetFont(const wxFont
& font
) 
3223     wxControl::SetFont(font
); 
3225     wxFont 
normalFont(font
); 
3226     wxFont 
selectedFont(normalFont
); 
3227     selectedFont
.SetWeight(wxBOLD
); 
3229     SetNormalFont(normalFont
); 
3230     SetSelectedFont(selectedFont
); 
3231     SetMeasuringFont(selectedFont
); 
3236 // Gets the tab control height 
3237 int wxAuiNotebook::GetTabCtrlHeight() const 
3239     return m_tabCtrlHeight
; 
3242 // Gets the height of the notebook for a given page height 
3243 int wxAuiNotebook::GetHeightForPageHeight(int pageHeight
) 
3245     UpdateTabCtrlHeight(); 
3247     int tabCtrlHeight 
= GetTabCtrlHeight(); 
3248     int decorHeight 
= 2; 
3249     return tabCtrlHeight 
+ pageHeight 
+ decorHeight
; 
3252 // Shows the window menu 
3253 bool wxAuiNotebook::ShowWindowMenu() 
3255     wxAuiTabCtrl
* tabCtrl 
= GetActiveTabCtrl(); 
3257     int idx 
= tabCtrl
->GetArtProvider()->ShowDropDown(tabCtrl
, tabCtrl
->GetPages(), tabCtrl
->GetActivePage()); 
3261         wxAuiNotebookEvent 
e(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, tabCtrl
->GetId()); 
3262         e
.SetSelection(idx
); 
3263         e
.SetOldSelection(tabCtrl
->GetActivePage()); 
3264         e
.SetEventObject(tabCtrl
); 
3265         GetEventHandler()->ProcessEvent(e
); 
3273 void wxAuiNotebook::DoThaw() 
3277     wxBookCtrlBase::DoThaw(); 
3280 void wxAuiNotebook::SetPageSize (const wxSize
& WXUNUSED(size
)) 
3282     wxFAIL_MSG("Not implemented for wxAuiNotebook"); 
3285 int wxAuiNotebook::HitTest (const wxPoint
& WXUNUSED(pt
), long* WXUNUSED(flags
)) const 
3287     wxFAIL_MSG("Not implemented for wxAuiNotebook"); 
3291 int wxAuiNotebook::GetPageImage(size_t WXUNUSED(n
)) const 
3293     wxFAIL_MSG("Not implemented for wxAuiNotebook"); 
3297 bool wxAuiNotebook::SetPageImage(size_t n
, int imageId
) 
3299     return SetPageBitmap(n
, GetImageList()->GetBitmap(imageId
)); 
3302 int wxAuiNotebook::ChangeSelection(size_t n
) 
3304     return DoModifySelection(n
, false); 
3307 bool wxAuiNotebook::AddPage(wxWindow 
*page
, const wxString 
&text
, bool select
,  
3312         return AddPage(page
, text
, select
, GetImageList()->GetBitmap(imageId
)); 
3316         return AddPage(page
, text
, select
, wxNullBitmap
); 
3320 bool wxAuiNotebook::DeleteAllPages() 
3322     size_t count 
= GetPageCount(); 
3323     for(size_t i 
= 0; i 
< count
; i
++) 
3330 bool wxAuiNotebook::InsertPage(size_t index
, wxWindow 
*page
,  
3331                                const wxString 
&text
, bool select
,  
3336         return InsertPage(index
, page
, text
, select
,  
3337                           GetImageList()->GetBitmap(imageId
)); 
3341         return InsertPage(index
, page
, text
, select
, wxNullBitmap
); 
3345 int wxAuiNotebook::DoModifySelection(size_t n
, bool events
) 
3347     wxWindow
* wnd 
= m_tabs
.GetWindowFromIdx(n
); 
3351     // don't change the page unless necessary; 
3352     // however, clicking again on a tab should give it the focus. 
3353     if ((int)n 
== m_curPage
) 
3357         if (FindTab(wnd
, &ctrl
, &ctrl_idx
)) 
3359             if (FindFocus() != ctrl
) 
3365     bool vetoed 
= false; 
3367     wxAuiNotebookEvent 
evt(wxEVT_AUINOTEBOOK_PAGE_CHANGING
, m_windowId
); 
3371         evt
.SetSelection(n
); 
3372         evt
.SetOldSelection(m_curPage
); 
3373         evt
.SetEventObject(this); 
3374         GetEventHandler()->ProcessEvent(evt
); 
3375         vetoed 
= !evt
.IsAllowed(); 
3380         int old_curpage 
= m_curPage
; 
3383         // program allows the page change 
3386             evt
.SetEventType(wxEVT_AUINOTEBOOK_PAGE_CHANGED
); 
3387             (void)GetEventHandler()->ProcessEvent(evt
); 
3393         if (FindTab(wnd
, &ctrl
, &ctrl_idx
)) 
3395             m_tabs
.SetActivePage(wnd
); 
3397             ctrl
->SetActivePage(ctrl_idx
); 
3401             ctrl
->MakeTabVisible(ctrl_idx
, ctrl
); 
3404             wxAuiPaneInfoArray
& all_panes 
= m_mgr
.GetAllPanes(); 
3405             size_t i
, pane_count 
= all_panes
.GetCount(); 
3406             for (i 
= 0; i 
< pane_count
; ++i
) 
3408                 wxAuiPaneInfo
& pane 
= all_panes
.Item(i
); 
3409                 if (pane
.name 
== wxT("dummy")) 
3411                 wxAuiTabCtrl
* tabctrl 
= ((wxTabFrame
*)pane
.window
)->m_tabs
; 
3412                 if (tabctrl 
!= ctrl
) 
3413                     tabctrl
->SetSelectedFont(m_normalFont
); 
3415                     tabctrl
->SetSelectedFont(m_selectedFont
); 
3419             // Set the focus to the page if we're not currently focused on the tab. 
3420             // This is Firefox-like behaviour. 
3421             if (wnd
->IsShownOnScreen() && FindFocus() != ctrl
)