1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/aui/framemanager.cpp 
   3 // Purpose:     wxaui: wx advanced user interface - docking window manager 
   4 // Author:      Benjamin I. Williams 
   8 // Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved 
   9 // Licence:     wxWindows Library Licence, Version 3.1 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #include "wx/wxprec.h" 
  28 #include "wx/aui/framemanager.h" 
  29 #include "wx/aui/dockart.h" 
  30 #include "wx/aui/floatpane.h" 
  31 #include "wx/aui/tabmdi.h" 
  32 #include "wx/aui/auibar.h" 
  37     #include "wx/settings.h" 
  39     #include "wx/dcclient.h" 
  40     #include "wx/dcscreen.h" 
  41     #include "wx/toolbar.h" 
  43     #include "wx/statusbr.h" 
  46 WX_CHECK_BUILD_OPTIONS("wxAUI") 
  48 #include "wx/arrimpl.cpp" 
  49 WX_DECLARE_OBJARRAY(wxRect
, wxAuiRectArray
); 
  50 WX_DEFINE_OBJARRAY(wxAuiRectArray
) 
  51 WX_DEFINE_OBJARRAY(wxAuiDockUIPartArray
) 
  52 WX_DEFINE_OBJARRAY(wxAuiDockInfoArray
) 
  53 WX_DEFINE_OBJARRAY(wxAuiPaneButtonArray
) 
  54 WX_DEFINE_OBJARRAY(wxAuiPaneInfoArray
) 
  56 wxAuiPaneInfo wxAuiNullPaneInfo
; 
  57 wxAuiDockInfo wxAuiNullDockInfo
; 
  58 wxDEFINE_EVENT( wxEVT_AUI_PANE_BUTTON
, wxAuiManagerEvent 
); 
  59 wxDEFINE_EVENT( wxEVT_AUI_PANE_CLOSE
, wxAuiManagerEvent 
); 
  60 wxDEFINE_EVENT( wxEVT_AUI_PANE_MAXIMIZE
, wxAuiManagerEvent 
); 
  61 wxDEFINE_EVENT( wxEVT_AUI_PANE_RESTORE
, wxAuiManagerEvent 
); 
  62 wxDEFINE_EVENT( wxEVT_AUI_RENDER
, wxAuiManagerEvent 
); 
  63 wxDEFINE_EVENT( wxEVT_AUI_FIND_MANAGER
, wxAuiManagerEvent 
); 
  66     // a few defines to avoid nameclashes 
  67     #define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1 
  69     #include "wx/osx/private.h" 
  73     #include "wx/msw/wrapwin.h" 
  74     #include "wx/msw/private.h" 
  75     #include "wx/msw/dc.h" 
  78 IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent
, wxEvent
) 
  79 IMPLEMENT_CLASS(wxAuiManager
, wxEvtHandler
) 
  83 const int auiToolBarLayer 
= 10; 
  88 class wxPseudoTransparentFrame 
: public wxFrame
 
  91     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
  92                 wxWindowID id 
= wxID_ANY
, 
  93                 const wxString
& title 
= wxEmptyString
, 
  94                 const wxPoint
& pos 
= wxDefaultPosition
, 
  95                 const wxSize
& size 
= wxDefaultSize
, 
  96                 long style 
= wxDEFAULT_FRAME_STYLE
, 
  97                 const wxString 
&name 
= wxT("frame")) 
  98                     : wxFrame(parent
, id
, title
, pos
, size
, style 
| wxFRAME_SHAPED
, name
) 
 100         SetBackgroundStyle(wxBG_STYLE_CUSTOM
); 
 107         m_canSetShape 
= false; // have to wait for window create event on GTK 
 109         m_canSetShape 
= true; 
 111         m_region 
= wxRegion(0, 0, 0, 0); 
 115     virtual bool SetTransparent(wxByte alpha
) 
 119             int w
=100; // some defaults 
 121             GetClientSize(&w
, &h
); 
 127 //            m_region.Union(0, 0, 1, m_maxWidth); 
 130                 for (int y
=0; y
<m_maxHeight
; y
++) 
 132                     // Reverse the order of the bottom 4 bits 
 133                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 134                     if ((j
*16+8)<m_amount
) 
 135                         m_region
.Union(0, y
, m_maxWidth
, 1); 
 144     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 148         if (m_region
.IsEmpty()) 
 152         dc
.SetBrush(wxColour(128, 192, 255)); 
 154         dc
.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 156         dc
.SetPen(*wxTRANSPARENT_PEN
); 
 158         wxRegionIterator 
upd(GetUpdateRegion()); // get the update rect list 
 162             wxRect 
rect(upd
.GetRect()); 
 163             dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 170     void OnWindowCreate(wxWindowCreateEvent
& WXUNUSED(event
)) 
 177     void OnSize(wxSizeEvent
& event
) 
 179         // We sometimes get surplus size events 
 180         if ((event
.GetSize().GetWidth() == m_lastWidth
) && 
 181             (event
.GetSize().GetHeight() == m_lastHeight
)) 
 186         m_lastWidth 
= event
.GetSize().GetWidth(); 
 187         m_lastHeight 
= event
.GetSize().GetHeight(); 
 189         SetTransparent(m_amount
); 
 190         m_region
.Intersect(0, 0, event
.GetSize().GetWidth(), 
 191                            event
.GetSize().GetHeight()); 
 202     int m_lastWidth
,m_lastHeight
; 
 206     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 207     DECLARE_EVENT_TABLE() 
 211 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 213 BEGIN_EVENT_TABLE(wxPseudoTransparentFrame
, wxFrame
) 
 214     EVT_PAINT(wxPseudoTransparentFrame::OnPaint
) 
 215     EVT_SIZE(wxPseudoTransparentFrame::OnSize
) 
 217     EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate
) 
 226 #include "wx/gtk/private/gtk2-compat.h" 
 229 gtk_pseudo_window_realized_callback( GtkWidget 
*m_widget
, void *WXUNUSED(win
) ) 
 231         wxSize disp 
= wxGetDisplaySize(); 
 234         for (int y
=0; y
<disp
.y
; y
++) 
 236                     // Reverse the order of the bottom 4 bits 
 237                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 239                         region
.Union(0, y
, disp
.x
, 1); 
 241         gdk_window_shape_combine_region(gtk_widget_get_window(m_widget
), region
.GetRegion(), 0, 0); 
 245 class wxPseudoTransparentFrame
: public wxFrame
 
 248     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
 249                 wxWindowID id 
= wxID_ANY
, 
 250                 const wxString
& title 
= wxEmptyString
, 
 251                 const wxPoint
& pos 
= wxDefaultPosition
, 
 252                 const wxSize
& size 
= wxDefaultSize
, 
 253                 long style 
= wxDEFAULT_FRAME_STYLE
, 
 254                 const wxString 
&name 
= wxT("frame")) 
 256          if (!CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 261         m_widget 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 262         g_object_ref(m_widget
); 
 264         if (parent
) parent
->AddChild(this); 
 266         g_signal_connect( m_widget
, "realize", 
 267                       G_CALLBACK (gtk_pseudo_window_realized_callback
), this ); 
 271         col
.green 
= 192 * 256; 
 272         col
.blue 
= 255 * 256; 
 273         gtk_widget_modify_bg( m_widget
, GTK_STATE_NORMAL
, &col 
); 
 276     bool SetTransparent(wxByte 
WXUNUSED(alpha
)) 
 282     virtual void DoSetSizeHints( int minW
, int minH
, 
 286         // the real wxFrame method doesn't work for us because we're not really 
 287         // a top level window so skip it 
 288         wxWindow::DoSetSizeHints(minW
, minH
, maxW
, maxH
, incW
, incH
); 
 292     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 295 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 302 // -- static utility functions -- 
 304 static wxBitmap 
wxPaneCreateStippleBitmap() 
 306     unsigned char data
[] = { 0,0,0,192,192,192, 192,192,192,0,0,0 }; 
 307     wxImage 
img(2,2,data
,true); 
 308     return wxBitmap(img
); 
 311 static void DrawResizeHint(wxDC
& dc
, const wxRect
& rect
) 
 313     wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
 314     wxBrush 
brush(stipple
); 
 317     wxMSWDCImpl 
*impl 
= (wxMSWDCImpl
*) dc
.GetImpl(); 
 318     PatBlt(GetHdcOf(*impl
), rect
.GetX(), rect
.GetY(), rect
.GetWidth(), rect
.GetHeight(), PATINVERT
); 
 320     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 322     dc
.SetLogicalFunction(wxXOR
); 
 323     dc
.DrawRectangle(rect
); 
 329 // CopyDocksAndPanes() - this utility function creates copies of 
 330 // the dock and pane info.  wxAuiDockInfo's usually contain pointers 
 331 // to wxAuiPaneInfo classes, thus this function is necessary to reliably 
 332 // reconstruct that relationship in the new dock info and pane info arrays 
 334 static void CopyDocksAndPanes(wxAuiDockInfoArray
& dest_docks
, 
 335                               wxAuiPaneInfoArray
& dest_panes
, 
 336                               const wxAuiDockInfoArray
& src_docks
, 
 337                               const wxAuiPaneInfoArray
& src_panes
) 
 339     dest_docks 
= src_docks
; 
 340     dest_panes 
= src_panes
; 
 341     int i
, j
, k
, dock_count
, pc1
, pc2
; 
 342     for (i 
= 0, dock_count 
= dest_docks
.GetCount(); i 
< dock_count
; ++i
) 
 344         wxAuiDockInfo
& dock 
= dest_docks
.Item(i
); 
 345         for (j 
= 0, pc1 
= dock
.panes
.GetCount(); j 
< pc1
; ++j
) 
 346             for (k 
= 0, pc2 
= src_panes
.GetCount(); k 
< pc2
; ++k
) 
 347                 if (dock
.panes
.Item(j
) == &src_panes
.Item(k
)) 
 348                     dock
.panes
.Item(j
) = &dest_panes
.Item(k
); 
 352 // GetMaxLayer() is an internal function which returns 
 353 // the highest layer inside the specified dock 
 354 static int GetMaxLayer(const wxAuiDockInfoArray
& docks
, 
 357     int i
, dock_count
, max_layer 
= 0; 
 358     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 360         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
 361         if (dock
.dock_direction 
== dock_direction 
&& 
 362             dock
.dock_layer 
> max_layer 
&& !dock
.fixed
) 
 363                 max_layer 
= dock
.dock_layer
; 
 369 // GetMaxRow() is an internal function which returns 
 370 // the highest layer inside the specified dock 
 371 static int GetMaxRow(const wxAuiPaneInfoArray
& panes
, int direction
, int layer
) 
 373     int i
, pane_count
, max_row 
= 0; 
 374     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 376         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 377         if (pane
.dock_direction 
== direction 
&& 
 378             pane
.dock_layer 
== layer 
&& 
 379             pane
.dock_row 
> max_row
) 
 380                 max_row 
= pane
.dock_row
; 
 387 // DoInsertDockLayer() is an internal function that inserts a new dock 
 388 // layer by incrementing all existing dock layer values by one 
 389 static void DoInsertDockLayer(wxAuiPaneInfoArray
& panes
, 
 394     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 396         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 397         if (!pane
.IsFloating() && 
 398             pane
.dock_direction 
== dock_direction 
&& 
 399             pane
.dock_layer 
>= dock_layer
) 
 404 // DoInsertDockLayer() is an internal function that inserts a new dock 
 405 // row by incrementing all existing dock row values by one 
 406 static void DoInsertDockRow(wxAuiPaneInfoArray
& panes
, 
 412     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 414         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 415         if (!pane
.IsFloating() && 
 416             pane
.dock_direction 
== dock_direction 
&& 
 417             pane
.dock_layer 
== dock_layer 
&& 
 418             pane
.dock_row 
>= dock_row
) 
 423 // DoInsertDockLayer() is an internal function that inserts a space for 
 424 // another dock pane by incrementing all existing dock row values by one 
 425 static void DoInsertPane(wxAuiPaneInfoArray
& panes
, 
 432     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 434         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 435         if (!pane
.IsFloating() && 
 436             pane
.dock_direction 
== dock_direction 
&& 
 437             pane
.dock_layer 
== dock_layer 
&& 
 438             pane
.dock_row 
== dock_row 
&& 
 439             pane
.dock_pos 
>= dock_pos
) 
 444 // FindDocks() is an internal function that returns a list of docks which meet 
 445 // the specified conditions in the parameters and returns a sorted array 
 446 // (sorted by layer and then row) 
 447 static void FindDocks(wxAuiDockInfoArray
& docks
, 
 451                       wxAuiDockInfoPtrArray
& arr
) 
 453     int begin_layer 
= dock_layer
; 
 454     int end_layer 
= dock_layer
; 
 455     int begin_row 
= dock_row
; 
 456     int end_row 
= dock_row
; 
 457     int dock_count 
= docks
.GetCount(); 
 458     int layer
, row
, i
, max_row 
= 0, max_layer 
= 0; 
 460     // discover the maximum dock layer and the max row 
 461     for (i 
= 0; i 
< dock_count
; ++i
) 
 463         max_row 
= wxMax(max_row
, docks
.Item(i
).dock_row
); 
 464         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
 467     // if no dock layer was specified, search all dock layers 
 468     if (dock_layer 
== -1) 
 471         end_layer 
= max_layer
; 
 474     // if no dock row was specified, search all dock row 
 483     for (layer 
= begin_layer
; layer 
<= end_layer
; ++layer
) 
 484         for (row 
= begin_row
; row 
<= end_row
; ++row
) 
 485             for (i 
= 0; i 
< dock_count
; ++i
) 
 487                 wxAuiDockInfo
& d 
= docks
.Item(i
); 
 488                 if (dock_direction 
== -1 || dock_direction 
== d
.dock_direction
) 
 490                     if (d
.dock_layer 
== layer 
&& d
.dock_row 
== row
) 
 496 // FindPaneInDock() looks up a specified window pointer inside a dock. 
 497 // If found, the corresponding wxAuiPaneInfo pointer is returned, otherwise NULL. 
 498 static wxAuiPaneInfo
* FindPaneInDock(const wxAuiDockInfo
& dock
, wxWindow
* window
) 
 500     int i
, count 
= dock
.panes
.GetCount(); 
 501     for (i 
= 0; i 
< count
; ++i
) 
 503         wxAuiPaneInfo
* p 
= dock
.panes
.Item(i
); 
 504         if (p
->window 
== window
) 
 510 // RemovePaneFromDocks() removes a pane window from all docks 
 511 // with a possible exception specified by parameter "ex_cept" 
 512 static void RemovePaneFromDocks(wxAuiDockInfoArray
& docks
, 
 514                                 wxAuiDockInfo
* ex_cept  
= NULL  
) 
 517     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 519         wxAuiDockInfo
& d 
= docks
.Item(i
); 
 522         wxAuiPaneInfo
* pi 
= FindPaneInDock(d
, pane
.window
); 
 529 // This function works fine, and may be used in the future 
 531 // RenumberDockRows() takes a dock and assigns sequential numbers 
 532 // to existing rows.  Basically it takes out the gaps; so if a 
 533 // dock has rows with numbers 0,2,5, they will become 0,1,2 
 534 static void RenumberDockRows(wxAuiDockInfoPtrArray& docks) 
 537     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) 
 539         wxAuiDockInfo& dock = *docks.Item(i); 
 543         for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j) 
 544             dock.panes.Item(j)->dock_row = i; 
 550 // SetActivePane() sets the active pane, as well as cycles through 
 551 // every other pane and makes sure that all others' active flags 
 553 static void SetActivePane(wxAuiPaneInfoArray
& panes
, wxWindow
* active_pane
) 
 556     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 558         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 559         pane
.state 
&= ~wxAuiPaneInfo::optionActive
; 
 560         if (pane
.window 
== active_pane
) 
 561             pane
.state 
|= wxAuiPaneInfo::optionActive
; 
 566 // this function is used to sort panes by dock position 
 567 static int PaneSortFunc(wxAuiPaneInfo
** p1
, wxAuiPaneInfo
** p2
) 
 569     return ((*p1
)->dock_pos 
< (*p2
)->dock_pos
) ? -1 : 1; 
 573 bool wxAuiPaneInfo::IsValid() const 
 575     // Should this RTTI and function call be rewritten as 
 576     // sending a new event type to allow other window types 
 577     // to check the pane settings? 
 578     wxAuiToolBar
* toolbar 
= wxDynamicCast(window
, wxAuiToolBar
); 
 579     return !toolbar 
|| toolbar
->IsPaneValid(*this); 
 582 // -- wxAuiManager class implementation -- 
 585 BEGIN_EVENT_TABLE(wxAuiManager
, wxEvtHandler
) 
 586     EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton
) 
 587     EVT_AUI_RENDER(wxAuiManager::OnRender
) 
 588     EVT_PAINT(wxAuiManager::OnPaint
) 
 589     EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground
) 
 590     EVT_SIZE(wxAuiManager::OnSize
) 
 591     EVT_SET_CURSOR(wxAuiManager::OnSetCursor
) 
 592     EVT_LEFT_DOWN(wxAuiManager::OnLeftDown
) 
 593     EVT_LEFT_UP(wxAuiManager::OnLeftUp
) 
 594     EVT_MOTION(wxAuiManager::OnMotion
) 
 595     EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow
) 
 596     EVT_MOUSE_CAPTURE_LOST(wxAuiManager::OnCaptureLost
) 
 597     EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus
) 
 598     EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager
) 
 602 wxAuiManager::wxAuiManager(wxWindow
* managed_wnd
, unsigned int flags
) 
 604     m_action 
= actionNone
; 
 605     m_actionWindow 
= NULL
; 
 606     m_lastMouseMove 
= wxPoint(); 
 607     m_hoverButton 
= NULL
; 
 608     m_art 
= new wxAuiDefaultDockArt
; 
 612     m_hasMaximized 
= false; 
 614     m_dockConstraintX 
= 0.3; 
 615     m_dockConstraintY 
= 0.3; 
 617     m_currentDragItem 
= -1; 
 621         SetManagedWindow(managed_wnd
); 
 625 wxAuiManager::~wxAuiManager() 
 627     // NOTE: It's possible that the windows have already been destroyed by the 
 628     // time this dtor is called, so this loop can result in memory access via 
 629     // invalid pointers, resulting in a crash.  So it will be disabled while 
 630     // waiting for a better solution. 
 632     for ( size_t i 
= 0; i 
< m_panes
.size(); i
++ ) 
 634         wxAuiPaneInfo
& pinfo 
= m_panes
[i
]; 
 635         if (pinfo
.window 
&& !pinfo
.window
->GetParent()) 
 643 // creates a floating frame for the windows 
 644 wxAuiFloatingFrame
* wxAuiManager::CreateFloatingFrame(wxWindow
* parent
, 
 645                                                       const wxAuiPaneInfo
& paneInfo
) 
 647     return new wxAuiFloatingFrame(parent
, this, paneInfo
); 
 650 bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo 
& WXUNUSED(p
)) 
 652     // if a key modifier is pressed while dragging the frame, 
 653     // don't dock the window 
 654     return !(wxGetKeyState(WXK_CONTROL
) || wxGetKeyState(WXK_ALT
)); 
 657 // GetPane() looks up a wxAuiPaneInfo structure based 
 658 // on the supplied window pointer.  Upon failure, GetPane() 
 659 // returns an empty wxAuiPaneInfo, a condition which can be checked 
 660 // by calling wxAuiPaneInfo::IsOk(). 
 662 // The pane info's structure may then be modified.  Once a pane's 
 663 // info is modified, wxAuiManager::Update() must be called to 
 664 // realize the changes in the UI. 
 666 wxAuiPaneInfo
& wxAuiManager::GetPane(wxWindow
* window
) 
 669     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 671         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 672         if (p
.window 
== window
) 
 675     return wxAuiNullPaneInfo
; 
 678 // this version of GetPane() looks up a pane based on a 
 679 // 'pane name', see above comment for more info 
 680 wxAuiPaneInfo
& wxAuiManager::GetPane(const wxString
& name
) 
 683     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 685         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 689     return wxAuiNullPaneInfo
; 
 692 // GetAllPanes() returns a reference to all the pane info structures 
 693 wxAuiPaneInfoArray
& wxAuiManager::GetAllPanes() 
 698 // HitTest() is an internal function which determines 
 699 // which UI item the specified coordinates are over 
 700 // (x,y) specify a position in client coordinates 
 701 wxAuiDockUIPart
* wxAuiManager::HitTest(int x
, int y
) 
 703     wxAuiDockUIPart
* result 
= NULL
; 
 706     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
 708         wxAuiDockUIPart
* item 
= &m_uiParts
.Item(i
); 
 710         // we are not interested in typeDock, because this space 
 711         // isn't used to draw anything, just for measurements; 
 712         // besides, the entire dock area is covered with other 
 713         // rectangles, which we are interested in. 
 714         if (item
->type 
== wxAuiDockUIPart::typeDock
) 
 717         // if we already have a hit on a more specific item, we are not 
 718         // interested in a pane hit.  If, however, we don't already have 
 719         // a hit, returning a pane hit is necessary for some operations 
 720         if ((item
->type 
== wxAuiDockUIPart::typePane 
|| 
 721             item
->type 
== wxAuiDockUIPart::typePaneBorder
) && result
) 
 724         // if the point is inside the rectangle, we have a hit 
 725         if (item
->rect
.Contains(x
,y
)) 
 733 // SetFlags() and GetFlags() allow the owner to set various 
 734 // options which are global to wxAuiManager 
 735 void wxAuiManager::SetFlags(unsigned int flags
) 
 737     // find out if we have to call UpdateHintWindowConfig() 
 738     bool update_hint_wnd 
= false; 
 739     unsigned int hint_mask 
= wxAUI_MGR_TRANSPARENT_HINT 
| 
 740                              wxAUI_MGR_VENETIAN_BLINDS_HINT 
| 
 741                              wxAUI_MGR_RECTANGLE_HINT
; 
 742     if ((flags 
& hint_mask
) != (m_flags 
& hint_mask
)) 
 743         update_hint_wnd 
= true; 
 751         UpdateHintWindowConfig(); 
 755 unsigned int wxAuiManager::GetFlags() const 
 760 // Convenience function 
 761 bool wxAuiManager_HasLiveResize(wxAuiManager
& manager
) 
 763     // With Core Graphics on Mac, it's not possible to show sash feedback, 
 764     // so we'll always use live update instead. 
 765 #if defined(__WXMAC__) 
 766     wxUnusedVar(manager
); 
 769     return (manager
.GetFlags() & wxAUI_MGR_LIVE_RESIZE
) == wxAUI_MGR_LIVE_RESIZE
; 
 773 // don't use these anymore as they are deprecated 
 774 // use Set/GetManagedFrame() instead 
 775 void wxAuiManager::SetFrame(wxFrame
* frame
) 
 777     SetManagedWindow((wxWindow
*)frame
); 
 780 wxFrame
* wxAuiManager::GetFrame() const 
 782     return (wxFrame
*)m_frame
; 
 786 // this function will return the aui manager for a given 
 787 // window.  The |window| parameter should be any child window 
 788 // or grand-child window (and so on) of the frame/window 
 789 // managed by wxAuiManager.  The |window| parameter does not 
 790 // need to be managed by the manager itself. 
 791 wxAuiManager
* wxAuiManager::GetManager(wxWindow
* window
) 
 793     wxAuiManagerEvent 
evt(wxEVT_AUI_FIND_MANAGER
); 
 794     evt
.SetManager(NULL
); 
 795     evt
.ResumePropagation(wxEVENT_PROPAGATE_MAX
); 
 796     if (!window
->GetEventHandler()->ProcessEvent(evt
)) 
 799     return evt
.GetManager(); 
 803 void wxAuiManager::UpdateHintWindowConfig() 
 805     // find out if the system can do transparent frames 
 806     bool can_do_transparent 
= false; 
 808     wxWindow
* w 
= m_frame
; 
 811         if (w
->IsKindOf(CLASSINFO(wxFrame
))) 
 813             wxFrame
* f 
= static_cast<wxFrame
*>(w
); 
 814             can_do_transparent 
= f
->CanSetTransparent(); 
 822     // if there is an existing hint window, delete it 
 825         m_hintWnd
->Destroy(); 
 832     if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) && can_do_transparent
) 
 834         // Make a window to use for a transparent hint 
 835         #if defined(__WXMSW__) || defined(__WXGTK__) 
 836             m_hintWnd 
= new wxFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 837                                      wxDefaultPosition
, wxSize(1,1), 
 838                                          wxFRAME_TOOL_WINDOW 
| 
 839                                          wxFRAME_FLOAT_ON_PARENT 
| 
 843             m_hintWnd
->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 844         #elif defined(__WXMAC__) 
 845             // Using a miniframe with float and tool styles keeps the parent 
 846             // frame activated and highlighted as such... 
 847             m_hintWnd 
= new wxMiniFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 848                                          wxDefaultPosition
, wxSize(1,1), 
 849                                          wxFRAME_FLOAT_ON_PARENT
 
 850                                          | wxFRAME_TOOL_WINDOW 
); 
 851             m_hintWnd
->Connect(wxEVT_ACTIVATE
, 
 852                 wxActivateEventHandler(wxAuiManager::OnHintActivate
), NULL
, this); 
 854             // Can't set the bg colour of a Frame in wxMac 
 855             wxPanel
* p 
= new wxPanel(m_hintWnd
); 
 857             // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver 
 858             // color that is really hard to see, especially transparent. 
 859             // Until a better system color is decided upon we'll just use 
 861             p
->SetBackgroundColour(*wxBLUE
); 
 867         if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) != 0 || 
 868             (m_flags 
& wxAUI_MGR_VENETIAN_BLINDS_HINT
) != 0) 
 870             // system can't support transparent fade, or the venetian 
 871             // blinds effect was explicitly requested 
 872             m_hintWnd 
= new wxPseudoTransparentFrame(m_frame
, 
 877                                                             wxFRAME_TOOL_WINDOW 
| 
 878                                                             wxFRAME_FLOAT_ON_PARENT 
| 
 887 // SetManagedWindow() is usually called once when the frame 
 888 // manager class is being initialized.  "frame" specifies 
 889 // the frame which should be managed by the frame mananger 
 890 void wxAuiManager::SetManagedWindow(wxWindow
* wnd
) 
 892     wxASSERT_MSG(wnd
, wxT("specified window must be non-NULL")); 
 895     m_frame
->PushEventHandler(this); 
 898     // if the owner is going to manage an MDI parent frame, 
 899     // we need to add the MDI client window as the default 
 902     if (m_frame
->IsKindOf(CLASSINFO(wxMDIParentFrame
))) 
 904         wxMDIParentFrame
* mdi_frame 
= (wxMDIParentFrame
*)m_frame
; 
 905         wxWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 907         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 909         AddPane(client_window
, 
 910                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 911                 CenterPane().PaneBorder(false)); 
 913     else if (m_frame
->IsKindOf(CLASSINFO(wxAuiMDIParentFrame
))) 
 915         wxAuiMDIParentFrame
* mdi_frame 
= (wxAuiMDIParentFrame
*)m_frame
; 
 916         wxAuiMDIClientWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 917         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 919         AddPane(client_window
, 
 920                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 921                 CenterPane().PaneBorder(false)); 
 926     UpdateHintWindowConfig(); 
 930 // UnInit() must be called, usually in the destructor 
 931 // of the frame class.   If it is not called, usually this 
 932 // will result in a crash upon program exit 
 933 void wxAuiManager::UnInit() 
 937         m_frame
->RemoveEventHandler(this); 
 941 // GetManagedWindow() returns the window pointer being managed 
 942 wxWindow
* wxAuiManager::GetManagedWindow() const 
 947 wxAuiDockArt
* wxAuiManager::GetArtProvider() const 
 952 void wxAuiManager::ProcessMgrEvent(wxAuiManagerEvent
& event
) 
 954     // first, give the owner frame a chance to override 
 957         if (m_frame
->GetEventHandler()->ProcessEvent(event
)) 
 964 // SetArtProvider() instructs wxAuiManager to use the 
 965 // specified art provider for all drawing calls.  This allows 
 966 // plugable look-and-feel features.  The pointer that is 
 967 // passed to this method subsequently belongs to wxAuiManager, 
 968 // and is deleted in the frame manager destructor 
 969 void wxAuiManager::SetArtProvider(wxAuiDockArt
* art_provider
) 
 971     // delete the last art provider, if any 
 974     // assign the new art provider 
 975     m_art 
= art_provider
; 
 979 bool wxAuiManager::AddPane(wxWindow
* window
, const wxAuiPaneInfo
& paneInfo
) 
 981     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
 983     // check if the pane has a valid window 
 987     // check if the window is already managed by us 
 988     if (GetPane(paneInfo
.window
).IsOk()) 
 991     // check if the pane name already exists, this could reveal a 
 992     // bug in the library user's application 
 993     bool already_exists 
= false; 
 994     if (!paneInfo
.name
.empty() && GetPane(paneInfo
.name
).IsOk()) 
 996         wxFAIL_MSG(wxT("A pane with that name already exists in the manager!")); 
 997         already_exists 
= true; 
1000     // if the new pane is docked then we should undo maximize 
1001     if (paneInfo
.IsDocked()) 
1002         RestoreMaximizedPane(); 
1004     // special case:  wxAuiToolBar style interacts with docking flags 
1005     wxAuiPaneInfo 
test(paneInfo
); 
1006     wxAuiToolBar
* toolbar 
= wxDynamicCast(window
, wxAuiToolBar
); 
1009         // if pane has default docking flags 
1010         const unsigned int dockMask 
= wxAuiPaneInfo::optionLeftDockable 
| 
1011                                         wxAuiPaneInfo::optionRightDockable 
| 
1012                                         wxAuiPaneInfo::optionTopDockable 
| 
1013                                         wxAuiPaneInfo::optionBottomDockable
; 
1014         const unsigned int defaultDock 
= wxAuiPaneInfo(). 
1015                                             DefaultPane().state 
& dockMask
; 
1016         if ((test
.state 
& dockMask
) == defaultDock
) 
1018             // set docking flags based on toolbar style 
1019             if (toolbar
->GetWindowStyleFlag() & wxAUI_TB_VERTICAL
) 
1021                 test
.TopDockable(false).BottomDockable(false); 
1023             else if (toolbar
->GetWindowStyleFlag() & wxAUI_TB_HORIZONTAL
) 
1025                 test
.LeftDockable(false).RightDockable(false); 
1030             // see whether non-default docking flags are valid 
1031             test
.window 
= window
; 
1032             wxCHECK_MSG(test
.IsValid(), false, 
1033                         "toolbar style and pane docking flags are incompatible"); 
1039     wxAuiPaneInfo
& pinfo 
= m_panes
.Last(); 
1041     // set the pane window 
1042     pinfo
.window 
= window
; 
1045     // if the pane's name identifier is blank, create a random string 
1046     if (pinfo
.name
.empty() || already_exists
) 
1048         pinfo
.name
.Printf(wxT("%08lx%08x%08x%08lx"), 
1049              (unsigned long)(wxPtrToUInt(pinfo
.window
) & 0xffffffff), 
1050              (unsigned int)time(NULL
), 
1052              (unsigned int)GetTickCount(), 
1054              (unsigned int)clock(), 
1056              (unsigned long)m_panes
.GetCount()); 
1059     // set initial proportion (if not already set) 
1060     if (pinfo
.dock_proportion 
== 0) 
1061         pinfo
.dock_proportion 
= 100000; 
1063     if (pinfo
.HasMaximizeButton()) 
1065         wxAuiPaneButton button
; 
1066         button
.button_id 
= wxAUI_BUTTON_MAXIMIZE_RESTORE
; 
1067         pinfo
.buttons
.Add(button
); 
1070     if (pinfo
.HasPinButton()) 
1072         wxAuiPaneButton button
; 
1073         button
.button_id 
= wxAUI_BUTTON_PIN
; 
1074         pinfo
.buttons
.Add(button
); 
1077     if (pinfo
.HasCloseButton()) 
1079         wxAuiPaneButton button
; 
1080         button
.button_id 
= wxAUI_BUTTON_CLOSE
; 
1081         pinfo
.buttons
.Add(button
); 
1084     if (pinfo
.HasGripper()) 
1086         if (pinfo
.window
->IsKindOf(CLASSINFO(wxAuiToolBar
))) 
1088             // prevent duplicate gripper -- both wxAuiManager and wxAuiToolBar 
1089             // have a gripper control.  The toolbar's built-in gripper 
1090             // meshes better with the look and feel of the control than ours, 
1091             // so turn wxAuiManager's gripper off, and the toolbar's on. 
1093             wxAuiToolBar
* tb 
= static_cast<wxAuiToolBar
*>(pinfo
.window
); 
1094             pinfo
.SetFlag(wxAuiPaneInfo::optionGripper
, false); 
1095             tb
->SetGripperVisible(true); 
1100     if (pinfo
.best_size 
== wxDefaultSize 
&& 
1103         pinfo
.best_size 
= pinfo
.window
->GetClientSize(); 
1106         if (pinfo
.window
->IsKindOf(CLASSINFO(wxToolBar
))) 
1108             // GetClientSize() doesn't get the best size for 
1109             // a toolbar under some newer versions of wxWidgets, 
1110             // so use GetBestSize() 
1111             pinfo
.best_size 
= pinfo
.window
->GetBestSize(); 
1113 #endif // wxUSE_TOOLBAR 
1115         if (pinfo
.min_size 
!= wxDefaultSize
) 
1117             if (pinfo
.best_size
.x 
< pinfo
.min_size
.x
) 
1118                 pinfo
.best_size
.x 
= pinfo
.min_size
.x
; 
1119             if (pinfo
.best_size
.y 
< pinfo
.min_size
.y
) 
1120                 pinfo
.best_size
.y 
= pinfo
.min_size
.y
; 
1129 bool wxAuiManager::AddPane(wxWindow
* window
, 
1131                            const wxString
& caption
) 
1133     wxAuiPaneInfo pinfo
; 
1134     pinfo
.Caption(caption
); 
1137         case wxTOP
:    pinfo
.Top(); break; 
1138         case wxBOTTOM
: pinfo
.Bottom(); break; 
1139         case wxLEFT
:   pinfo
.Left(); break; 
1140         case wxRIGHT
:  pinfo
.Right(); break; 
1141         case wxCENTER
: pinfo
.CenterPane(); break; 
1143     return AddPane(window
, pinfo
); 
1146 bool wxAuiManager::AddPane(wxWindow
* window
, 
1147                            const wxAuiPaneInfo
& paneInfo
, 
1148                            const wxPoint
& drop_pos
) 
1150     if (!AddPane(window
, paneInfo
)) 
1153     wxAuiPaneInfo
& pane 
= GetPane(window
); 
1155     DoDrop(m_docks
, m_panes
, pane
, drop_pos
, wxPoint(0,0)); 
1160 bool wxAuiManager::InsertPane(wxWindow
* window
, const wxAuiPaneInfo
& paneInfo
, 
1163     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1165     // shift the panes around, depending on the insert level 
1166     switch (insert_level
) 
1168         case wxAUI_INSERT_PANE
: 
1169             DoInsertPane(m_panes
, 
1170                  paneInfo
.dock_direction
, 
1171                  paneInfo
.dock_layer
, 
1175         case wxAUI_INSERT_ROW
: 
1176             DoInsertDockRow(m_panes
, 
1177                  paneInfo
.dock_direction
, 
1178                  paneInfo
.dock_layer
, 
1181         case wxAUI_INSERT_DOCK
: 
1182             DoInsertDockLayer(m_panes
, 
1183                  paneInfo
.dock_direction
, 
1184                  paneInfo
.dock_layer
); 
1188     // if the window already exists, we are basically just moving/inserting the 
1189     // existing window.  If it doesn't exist, we need to add it and insert it 
1190     wxAuiPaneInfo
& existing_pane 
= GetPane(window
); 
1191     if (!existing_pane
.IsOk()) 
1193         return AddPane(window
, paneInfo
); 
1197         if (paneInfo
.IsFloating()) 
1199             existing_pane
.Float(); 
1200             if (paneInfo
.floating_pos 
!= wxDefaultPosition
) 
1201                 existing_pane
.FloatingPosition(paneInfo
.floating_pos
); 
1202             if (paneInfo
.floating_size 
!= wxDefaultSize
) 
1203                 existing_pane
.FloatingSize(paneInfo
.floating_size
); 
1207             // if the new pane is docked then we should undo maximize 
1208             RestoreMaximizedPane(); 
1210             existing_pane
.Direction(paneInfo
.dock_direction
); 
1211             existing_pane
.Layer(paneInfo
.dock_layer
); 
1212             existing_pane
.Row(paneInfo
.dock_row
); 
1213             existing_pane
.Position(paneInfo
.dock_pos
); 
1221 // DetachPane() removes a pane from the frame manager.  This 
1222 // method will not destroy the window that is removed. 
1223 bool wxAuiManager::DetachPane(wxWindow
* window
) 
1225     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1228     for (i 
= 0, count 
= m_panes
.GetCount(); i 
< count
; ++i
) 
1230         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1231         if (p
.window 
== window
) 
1235                 // we have a floating frame which is being detached. We need to 
1236                 // reparent it to m_frame and destroy the floating frame 
1239                 p
.window
->SetSize(1,1); 
1241                 if (p
.frame
->IsShown()) 
1242                     p
.frame
->Show(false); 
1244                 // reparent to m_frame and destroy the pane 
1245                 if (m_actionWindow 
== p
.frame
) 
1247                     m_actionWindow 
= NULL
; 
1250                 p
.window
->Reparent(m_frame
); 
1251                 p
.frame
->SetSizer(NULL
); 
1256             // make sure there are no references to this pane in our uiparts, 
1257             // just in case the caller doesn't call Update() immediately after 
1258             // the DetachPane() call.  This prevets obscure crashes which would 
1259             // happen at window repaint if the caller forgets to call Update() 
1261             for (pi 
= 0, part_count 
= (int)m_uiParts
.GetCount(); pi 
< part_count
; ++pi
) 
1263                 wxAuiDockUIPart
& part 
= m_uiParts
.Item(pi
); 
1264                 if (part
.pane 
== &p
) 
1266                     m_uiParts
.RemoveAt(pi
); 
1273             m_panes
.RemoveAt(i
); 
1280 // ClosePane() destroys or hides the pane depending on its flags 
1281 void wxAuiManager::ClosePane(wxAuiPaneInfo
& paneInfo
) 
1283     // if we were maximized, restore 
1284     if (paneInfo
.IsMaximized()) 
1286         RestorePane(paneInfo
); 
1289     // first, hide the window 
1290     if (paneInfo
.window 
&& paneInfo
.window
->IsShown()) 
1292         paneInfo
.window
->Show(false); 
1295     // make sure that we are the parent of this window 
1296     if (paneInfo
.window 
&& paneInfo
.window
->GetParent() != m_frame
) 
1298         paneInfo
.window
->Reparent(m_frame
); 
1301     // if we have a frame, destroy it 
1304         paneInfo
.frame
->Destroy(); 
1305         paneInfo
.frame 
= NULL
; 
1308     // now we need to either destroy or hide the pane 
1309     if (paneInfo
.IsDestroyOnClose()) 
1311         wxWindow 
* window 
= paneInfo
.window
; 
1324 void wxAuiManager::MaximizePane(wxAuiPaneInfo
& paneInfo
) 
1328     // un-maximize and hide all other panes 
1329     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1331         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1332         if (!p
.IsToolbar() && !p
.IsFloating()) 
1336             // save hidden state 
1337             p
.SetFlag(wxAuiPaneInfo::savedHiddenState
, 
1338                       p
.HasFlag(wxAuiPaneInfo::optionHidden
)); 
1340             // hide the pane, because only the newly 
1341             // maximized pane should show 
1346     // mark ourselves maximized 
1347     paneInfo
.Maximize(); 
1349     m_hasMaximized 
= true; 
1351     // last, show the window 
1352     if (paneInfo
.window 
&& !paneInfo
.window
->IsShown()) 
1354         paneInfo
.window
->Show(true); 
1358 void wxAuiManager::RestorePane(wxAuiPaneInfo
& paneInfo
) 
1362     // restore all the panes 
1363     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1365         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1366         if (!p
.IsToolbar() && !p
.IsFloating()) 
1368             p
.SetFlag(wxAuiPaneInfo::optionHidden
, 
1369                       p
.HasFlag(wxAuiPaneInfo::savedHiddenState
)); 
1373     // mark ourselves non-maximized 
1375     m_hasMaximized 
= false; 
1377     // last, show the window 
1378     if (paneInfo
.window 
&& !paneInfo
.window
->IsShown()) 
1380         paneInfo
.window
->Show(true); 
1384 void wxAuiManager::RestoreMaximizedPane() 
1388     // restore all the panes 
1389     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1391         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1392         if (p
.IsMaximized()) 
1400 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|" 
1401 // in the input string.  This is an internal functions which is 
1402 // used for saving perspectives 
1403 static wxString 
EscapeDelimiters(const wxString
& s
) 
1406     result
.Alloc(s
.length()); 
1407     const wxChar
* ch 
= s
.c_str(); 
1410         if (*ch 
== wxT(';') || *ch 
== wxT('|')) 
1411             result 
+= wxT('\\'); 
1418 wxString 
wxAuiManager::SavePaneInfo(wxAuiPaneInfo
& pane
) 
1420     wxString result 
= wxT("name="); 
1421     result 
+= EscapeDelimiters(pane
.name
); 
1424     result 
+= wxT("caption="); 
1425     result 
+= EscapeDelimiters(pane
.caption
); 
1428     result 
+= wxString::Format(wxT("state=%u;"), pane
.state
); 
1429     result 
+= wxString::Format(wxT("dir=%d;"), pane
.dock_direction
); 
1430     result 
+= wxString::Format(wxT("layer=%d;"), pane
.dock_layer
); 
1431     result 
+= wxString::Format(wxT("row=%d;"), pane
.dock_row
); 
1432     result 
+= wxString::Format(wxT("pos=%d;"), pane
.dock_pos
); 
1433     result 
+= wxString::Format(wxT("prop=%d;"), pane
.dock_proportion
); 
1434     result 
+= wxString::Format(wxT("bestw=%d;"), pane
.best_size
.x
); 
1435     result 
+= wxString::Format(wxT("besth=%d;"), pane
.best_size
.y
); 
1436     result 
+= wxString::Format(wxT("minw=%d;"), pane
.min_size
.x
); 
1437     result 
+= wxString::Format(wxT("minh=%d;"), pane
.min_size
.y
); 
1438     result 
+= wxString::Format(wxT("maxw=%d;"), pane
.max_size
.x
); 
1439     result 
+= wxString::Format(wxT("maxh=%d;"), pane
.max_size
.y
); 
1440     result 
+= wxString::Format(wxT("floatx=%d;"), pane
.floating_pos
.x
); 
1441     result 
+= wxString::Format(wxT("floaty=%d;"), pane
.floating_pos
.y
); 
1442     result 
+= wxString::Format(wxT("floatw=%d;"), pane
.floating_size
.x
); 
1443     result 
+= wxString::Format(wxT("floath=%d"), pane
.floating_size
.y
); 
1448 // Load a "pane" with the pane infor settings in pane_part 
1449 void wxAuiManager::LoadPaneInfo(wxString pane_part
, wxAuiPaneInfo 
&pane
) 
1451     // replace escaped characters so we can 
1452     // split up the string easily 
1453     pane_part
.Replace(wxT("\\|"), wxT("\a")); 
1454     pane_part
.Replace(wxT("\\;"), wxT("\b")); 
1458         wxString val_part 
= pane_part
.BeforeFirst(wxT(';')); 
1459         pane_part 
= pane_part
.AfterFirst(wxT(';')); 
1460         wxString val_name 
= val_part
.BeforeFirst(wxT('=')); 
1461         wxString value 
= val_part
.AfterFirst(wxT('=')); 
1462         val_name
.MakeLower(); 
1463         val_name
.Trim(true); 
1464         val_name
.Trim(false); 
1468         if (val_name
.empty()) 
1471         if (val_name 
== wxT("name")) 
1473         else if (val_name 
== wxT("caption")) 
1474             pane
.caption 
= value
; 
1475         else if (val_name 
== wxT("state")) 
1476             pane
.state 
= (unsigned int)wxAtoi(value
.c_str()); 
1477         else if (val_name 
== wxT("dir")) 
1478             pane
.dock_direction 
= wxAtoi(value
.c_str()); 
1479         else if (val_name 
== wxT("layer")) 
1480             pane
.dock_layer 
= wxAtoi(value
.c_str()); 
1481         else if (val_name 
== wxT("row")) 
1482             pane
.dock_row 
= wxAtoi(value
.c_str()); 
1483         else if (val_name 
== wxT("pos")) 
1484             pane
.dock_pos 
= wxAtoi(value
.c_str()); 
1485         else if (val_name 
== wxT("prop")) 
1486             pane
.dock_proportion 
= wxAtoi(value
.c_str()); 
1487         else if (val_name 
== wxT("bestw")) 
1488             pane
.best_size
.x 
= wxAtoi(value
.c_str()); 
1489         else if (val_name 
== wxT("besth")) 
1490             pane
.best_size
.y 
= wxAtoi(value
.c_str()); 
1491         else if (val_name 
== wxT("minw")) 
1492             pane
.min_size
.x 
= wxAtoi(value
.c_str()); 
1493         else if (val_name 
== wxT("minh")) 
1494             pane
.min_size
.y 
= wxAtoi(value
.c_str()); 
1495         else if (val_name 
== wxT("maxw")) 
1496             pane
.max_size
.x 
= wxAtoi(value
.c_str()); 
1497         else if (val_name 
== wxT("maxh")) 
1498             pane
.max_size
.y 
= wxAtoi(value
.c_str()); 
1499         else if (val_name 
== wxT("floatx")) 
1500             pane
.floating_pos
.x 
= wxAtoi(value
.c_str()); 
1501         else if (val_name 
== wxT("floaty")) 
1502             pane
.floating_pos
.y 
= wxAtoi(value
.c_str()); 
1503         else if (val_name 
== wxT("floatw")) 
1504             pane
.floating_size
.x 
= wxAtoi(value
.c_str()); 
1505         else if (val_name 
== wxT("floath")) 
1506             pane
.floating_size
.y 
= wxAtoi(value
.c_str()); 
1508             wxFAIL_MSG(wxT("Bad Perspective String")); 
1512     // replace escaped characters so we can 
1513     // split up the string easily 
1514     pane
.name
.Replace(wxT("\a"), wxT("|")); 
1515     pane
.name
.Replace(wxT("\b"), wxT(";")); 
1516     pane
.caption
.Replace(wxT("\a"), wxT("|")); 
1517     pane
.caption
.Replace(wxT("\b"), wxT(";")); 
1518     pane_part
.Replace(wxT("\a"), wxT("|")); 
1519     pane_part
.Replace(wxT("\b"), wxT(";")); 
1525 // SavePerspective() saves all pane information as a single string. 
1526 // This string may later be fed into LoadPerspective() to restore 
1527 // all pane settings.  This save and load mechanism allows an 
1528 // exact pane configuration to be saved and restored at a later time 
1530 wxString 
wxAuiManager::SavePerspective() 
1534     result 
= wxT("layout2|"); 
1536     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1537     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1539         wxAuiPaneInfo
& pane 
= m_panes
.Item(pane_i
); 
1540         result 
+= SavePaneInfo(pane
)+wxT("|"); 
1543     int dock_i
, dock_count 
= m_docks
.GetCount(); 
1544     for (dock_i 
= 0; dock_i 
< dock_count
; ++dock_i
) 
1546         wxAuiDockInfo
& dock 
= m_docks
.Item(dock_i
); 
1548         result 
+= wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"), 
1549                                    dock
.dock_direction
, dock
.dock_layer
, 
1550                                    dock
.dock_row
, dock
.size
); 
1556 // LoadPerspective() loads a layout which was saved with SavePerspective() 
1557 // If the "update" flag parameter is true, the GUI will immediately be updated 
1559 bool wxAuiManager::LoadPerspective(const wxString
& layout
, bool update
) 
1561     wxString input 
= layout
; 
1564     // check layout string version 
1565     //    'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 
1566     //    'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) 
1567     part 
= input
.BeforeFirst(wxT('|')); 
1568     input 
= input
.AfterFirst(wxT('|')); 
1571     if (part 
!= wxT("layout2")) 
1574     // Mark all panes currently managed as hidden. Also, dock all panes that are dockable. 
1575     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1576     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1578         wxAuiPaneInfo
& p 
= m_panes
.Item(pane_i
); 
1584     // clear out the dock array; this will be reconstructed 
1587     // replace escaped characters so we can 
1588     // split up the string easily 
1589     input
.Replace(wxT("\\|"), wxT("\a")); 
1590     input
.Replace(wxT("\\;"), wxT("\b")); 
1592     m_hasMaximized 
= false; 
1597         wxString pane_part 
= input
.BeforeFirst(wxT('|')); 
1598         input 
= input
.AfterFirst(wxT('|')); 
1599         pane_part
.Trim(true); 
1601         // if the string is empty, we're done parsing 
1602         if (pane_part
.empty()) 
1605         if (pane_part
.Left(9) == wxT("dock_size")) 
1607             wxString val_name 
= pane_part
.BeforeFirst(wxT('=')); 
1608             wxString value 
= pane_part
.AfterFirst(wxT('=')); 
1610             long dir
, layer
, row
, size
; 
1611             wxString piece 
= val_name
.AfterFirst(wxT('(')); 
1612             piece 
= piece
.BeforeLast(wxT(')')); 
1613             piece
.BeforeFirst(wxT(',')).ToLong(&dir
); 
1614             piece 
= piece
.AfterFirst(wxT(',')); 
1615             piece
.BeforeFirst(wxT(',')).ToLong(&layer
); 
1616             piece
.AfterFirst(wxT(',')).ToLong(&row
); 
1617             value
.ToLong(&size
); 
1620             dock
.dock_direction 
= dir
; 
1621             dock
.dock_layer 
= layer
; 
1622             dock
.dock_row 
= row
; 
1628         // Undo our escaping as LoadPaneInfo needs to take an unescaped 
1629         // name so it can be called by external callers 
1630         pane_part
.Replace(wxT("\a"), wxT("|")); 
1631         pane_part
.Replace(wxT("\b"), wxT(";")); 
1633         LoadPaneInfo(pane_part
, pane
); 
1635         if ( pane
.IsMaximized() ) 
1636             m_hasMaximized 
= true; 
1638         wxAuiPaneInfo
& p 
= GetPane(pane
.name
); 
1641             // the pane window couldn't be found 
1642             // in the existing layout -- skip it 
1655 void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo
& dock
, 
1656                                             wxArrayInt
& positions
, 
1659     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1660     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1661     int gripperSize 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1666     int offset
, action_pane 
= -1; 
1667     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1669     // find the pane marked as our action pane 
1670     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1672         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1674         if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
1676             wxASSERT_MSG(action_pane
==-1, wxT("Too many fixed action panes")); 
1677             action_pane 
= pane_i
; 
1681     // set up each panes default position, and 
1682     // determine the size (width or height, depending 
1683     // on the dock's orientation) of each pane 
1684     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1686         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1687         positions
.Add(pane
.dock_pos
); 
1690         if (pane
.HasBorder()) 
1691             size 
+= (pane_borderSize
*2); 
1693         if (dock
.IsHorizontal()) 
1695             if (pane
.HasGripper() && !pane
.HasGripperTop()) 
1696                 size 
+= gripperSize
; 
1697             size 
+= pane
.best_size
.x
; 
1701             if (pane
.HasGripper() && pane
.HasGripperTop()) 
1702                 size 
+= gripperSize
; 
1704             if (pane
.HasCaption()) 
1705                 size 
+= caption_size
; 
1706             size 
+= pane
.best_size
.y
; 
1712     // if there is no action pane, just return the default 
1713     // positions (as specified in pane.pane_pos) 
1714     if (action_pane 
== -1) 
1718     for (pane_i 
= action_pane
-1; pane_i 
>= 0; --pane_i
) 
1720         int amount 
= positions
[pane_i
+1] - (positions
[pane_i
] + sizes
[pane_i
]); 
1725             positions
[pane_i
] -= -amount
; 
1727         offset 
+= sizes
[pane_i
]; 
1730     // if the dock mode is fixed, make sure none of the panes 
1731     // overlap; we will bump panes that overlap 
1733     for (pane_i 
= action_pane
; pane_i 
< pane_count
; ++pane_i
) 
1735         int amount 
= positions
[pane_i
] - offset
; 
1739             positions
[pane_i
] += -amount
; 
1741         offset 
+= sizes
[pane_i
]; 
1746 void wxAuiManager::LayoutAddPane(wxSizer
* cont
, 
1747                                  wxAuiDockInfo
& dock
, 
1748                                  wxAuiPaneInfo
& pane
, 
1749                                  wxAuiDockUIPartArray
& uiparts
, 
1752     wxAuiDockUIPart part
; 
1753     wxSizerItem
* sizer_item
; 
1755     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1756     int gripperSize 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1757     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1758     int pane_button_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BUTTON_SIZE
); 
1760     // find out the orientation of the item (orientation for panes 
1761     // is the same as the dock's orientation) 
1763     if (dock
.IsHorizontal()) 
1764         orientation 
= wxHORIZONTAL
; 
1766         orientation 
= wxVERTICAL
; 
1768     // this variable will store the proportion 
1769     // value that the pane will receive 
1770     int pane_proportion 
= pane
.dock_proportion
; 
1772     wxBoxSizer
* horz_pane_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1773     wxBoxSizer
* vert_pane_sizer 
= new wxBoxSizer(wxVERTICAL
); 
1775     if (pane
.HasGripper()) 
1777         if (pane
.HasGripperTop()) 
1778             sizer_item 
= vert_pane_sizer 
->Add(1, gripperSize
, 0, wxEXPAND
); 
1780             sizer_item 
= horz_pane_sizer 
->Add(gripperSize
, 1, 0, wxEXPAND
); 
1782         part
.type 
= wxAuiDockUIPart::typeGripper
; 
1786         part
.orientation 
= orientation
; 
1787         part
.cont_sizer 
= horz_pane_sizer
; 
1788         part
.sizer_item 
= sizer_item
; 
1792     if (pane
.HasCaption()) 
1794         // create the caption sizer 
1795         wxBoxSizer
* caption_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1797         sizer_item 
= caption_sizer
->Add(1, caption_size
, 1, wxEXPAND
); 
1799         part
.type 
= wxAuiDockUIPart::typeCaption
; 
1803         part
.orientation 
= orientation
; 
1804         part
.cont_sizer 
= vert_pane_sizer
; 
1805         part
.sizer_item 
= sizer_item
; 
1806         int caption_part_idx 
= uiparts
.GetCount(); 
1809         // add pane buttons to the caption 
1810         int i
, button_count
; 
1811         for (i 
= 0, button_count 
= pane
.buttons
.GetCount(); 
1812              i 
< button_count
; ++i
) 
1814             wxAuiPaneButton
& button 
= pane
.buttons
.Item(i
); 
1816             sizer_item 
= caption_sizer
->Add(pane_button_size
, 
1820             part
.type 
= wxAuiDockUIPart::typePaneButton
; 
1823             part
.button 
= &button
; 
1824             part
.orientation 
= orientation
; 
1825             part
.cont_sizer 
= caption_sizer
; 
1826             part
.sizer_item 
= sizer_item
; 
1830         // if we have buttons, add a little space to the right 
1831         // of them to ease visual crowding 
1832         if (button_count 
>= 1) 
1834             caption_sizer
->Add(3,1); 
1837         // add the caption sizer 
1838         sizer_item 
= vert_pane_sizer
->Add(caption_sizer
, 0, wxEXPAND
); 
1840         uiparts
.Item(caption_part_idx
).sizer_item 
= sizer_item
; 
1843     // add the pane window itself 
1846         sizer_item 
= vert_pane_sizer
->Add(1, 1, 1, wxEXPAND
); 
1850         sizer_item 
= vert_pane_sizer
->Add(pane
.window
, 1, wxEXPAND
); 
1851         // Don't do this because it breaks the pane size in floating windows 
1852         // BIW: Right now commenting this out is causing problems with 
1853         // an mdi client window as the center pane. 
1854         vert_pane_sizer
->SetItemMinSize(pane
.window
, 1, 1); 
1857     part
.type 
= wxAuiDockUIPart::typePane
; 
1861     part
.orientation 
= orientation
; 
1862     part
.cont_sizer 
= vert_pane_sizer
; 
1863     part
.sizer_item 
= sizer_item
; 
1867     // determine if the pane should have a minimum size; if the pane is 
1868     // non-resizable (fixed) then we must set a minimum size. Alternatively, 
1869     // if the pane.min_size is set, we must use that value as well 
1871     wxSize min_size 
= pane
.min_size
; 
1874         if (min_size 
== wxDefaultSize
) 
1876             min_size 
= pane
.best_size
; 
1877             pane_proportion 
= 0; 
1881     if (min_size 
!= wxDefaultSize
) 
1883         vert_pane_sizer
->SetItemMinSize( 
1884                         vert_pane_sizer
->GetChildren().GetCount()-1, 
1885                         min_size
.x
, min_size
.y
); 
1889     // add the verticle sizer (caption, pane window) to the 
1890     // horizontal sizer (gripper, verticle sizer) 
1891     horz_pane_sizer
->Add(vert_pane_sizer
, 1, wxEXPAND
); 
1893     // finally, add the pane sizer to the dock sizer 
1895     if (pane
.HasBorder()) 
1897         // allowing space for the pane's border 
1898         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, 
1899                                wxEXPAND 
| wxALL
, pane_borderSize
); 
1901         part
.type 
= wxAuiDockUIPart::typePaneBorder
; 
1905         part
.orientation 
= orientation
; 
1906         part
.cont_sizer 
= cont
; 
1907         part
.sizer_item 
= sizer_item
; 
1912         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, wxEXPAND
); 
1916 void wxAuiManager::LayoutAddDock(wxSizer
* cont
, 
1917                                  wxAuiDockInfo
& dock
, 
1918                                  wxAuiDockUIPartArray
& uiparts
, 
1921     wxSizerItem
* sizer_item
; 
1922     wxAuiDockUIPart part
; 
1924     int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
1925     int orientation 
= dock
.IsHorizontal() ? wxHORIZONTAL 
: wxVERTICAL
; 
1927     // resizable bottom and right docks have a sash before them 
1928     if (!m_hasMaximized 
&& !dock
.fixed 
&& (dock
.dock_direction 
== wxAUI_DOCK_BOTTOM 
|| 
1929                         dock
.dock_direction 
== wxAUI_DOCK_RIGHT
)) 
1931         sizer_item 
= cont
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
1933         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
1934         part
.orientation 
= orientation
; 
1938         part
.cont_sizer 
= cont
; 
1939         part
.sizer_item 
= sizer_item
; 
1943     // create the sizer for the dock 
1944     wxSizer
* dock_sizer 
= new wxBoxSizer(orientation
); 
1946     // add each pane to the dock 
1947     bool has_maximized_pane 
= false; 
1948     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1952         wxArrayInt pane_positions
, pane_sizes
; 
1954         // figure out the real pane positions we will 
1955         // use, without modifying the each pane's pane_pos member 
1956         GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
1959         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1961             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1962             int pane_pos 
= pane_positions
.Item(pane_i
); 
1964             if (pane
.IsMaximized()) 
1965                 has_maximized_pane 
= true; 
1968             int amount 
= pane_pos 
- offset
; 
1971                 if (dock
.IsVertical()) 
1972                     sizer_item 
= dock_sizer
->Add(1, amount
, 0, wxEXPAND
); 
1974                     sizer_item 
= dock_sizer
->Add(amount
, 1, 0, wxEXPAND
); 
1976                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
1980                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
1981                 part
.cont_sizer 
= dock_sizer
; 
1982                 part
.sizer_item 
= sizer_item
; 
1988             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
1990             offset 
+= pane_sizes
.Item(pane_i
); 
1993         // at the end add a very small stretchable background area 
1994         sizer_item 
= dock_sizer
->Add(0,0, 1, wxEXPAND
); 
1996         part
.type 
= wxAuiDockUIPart::typeBackground
; 
2000         part
.orientation 
= orientation
; 
2001         part
.cont_sizer 
= dock_sizer
; 
2002         part
.sizer_item 
= sizer_item
; 
2007         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
2009             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
2011             if (pane
.IsMaximized()) 
2012                 has_maximized_pane 
= true; 
2014             // if this is not the first pane being added, 
2015             // we need to add a pane sizer 
2016             if (!m_hasMaximized 
&& pane_i 
> 0) 
2018                 sizer_item 
= dock_sizer
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
2020                 part
.type 
= wxAuiDockUIPart::typePaneSizer
; 
2022                 part
.pane 
= dock
.panes
.Item(pane_i
-1); 
2024                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
2025                 part
.cont_sizer 
= dock_sizer
; 
2026                 part
.sizer_item 
= sizer_item
; 
2030             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
2034     if (dock
.dock_direction 
== wxAUI_DOCK_CENTER 
|| has_maximized_pane
) 
2035         sizer_item 
= cont
->Add(dock_sizer
, 1, wxEXPAND
); 
2037         sizer_item 
= cont
->Add(dock_sizer
, 0, wxEXPAND
); 
2039     part
.type 
= wxAuiDockUIPart::typeDock
; 
2043     part
.orientation 
= orientation
; 
2044     part
.cont_sizer 
= cont
; 
2045     part
.sizer_item 
= sizer_item
; 
2048     if (dock
.IsHorizontal()) 
2049         cont
->SetItemMinSize(dock_sizer
, 0, dock
.size
); 
2051         cont
->SetItemMinSize(dock_sizer
, dock
.size
, 0); 
2053     //  top and left docks have a sash after them 
2054     if (!m_hasMaximized 
&& 
2056           (dock
.dock_direction 
== wxAUI_DOCK_TOP 
|| 
2057            dock
.dock_direction 
== wxAUI_DOCK_LEFT
)) 
2059         sizer_item 
= cont
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
2061         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
2065         part
.orientation 
= orientation
; 
2066         part
.cont_sizer 
= cont
; 
2067         part
.sizer_item 
= sizer_item
; 
2072 wxSizer
* wxAuiManager::LayoutAll(wxAuiPaneInfoArray
& panes
, 
2073                                  wxAuiDockInfoArray
& docks
, 
2074                                  wxAuiDockUIPartArray
& uiparts
, 
2077     wxBoxSizer
* container 
= new wxBoxSizer(wxVERTICAL
); 
2079     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
2080     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
2081     wxSize cli_size 
= m_frame
->GetClientSize(); 
2082     int i
, dock_count
, pane_count
; 
2085     // empty all docks out 
2086     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2088         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2090         // empty out all panes, as they will be readded below 
2095             // always reset fixed docks' sizes, because 
2096             // the contained windows may have been resized 
2102     // iterate through all known panes, filing each 
2103     // of them into the appropriate dock. If the 
2104     // pane does not exist in the dock, add it 
2105     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
2107         wxAuiPaneInfo
& p 
= panes
.Item(i
); 
2109         // find any docks with the same dock direction, dock layer, and 
2110         // dock row as the pane we are working on 
2111         wxAuiDockInfo
* dock
; 
2112         wxAuiDockInfoPtrArray arr
; 
2113         FindDocks(docks
, p
.dock_direction
, p
.dock_layer
, p
.dock_row
, arr
); 
2115         if (arr
.GetCount() > 0) 
2117             // found the right dock 
2122             // dock was not found, so we need to create a new one 
2124             d
.dock_direction 
= p
.dock_direction
; 
2125             d
.dock_layer 
= p
.dock_layer
; 
2126             d
.dock_row 
= p
.dock_row
; 
2128             dock 
= &docks
.Last(); 
2132         if (p
.IsDocked() && p
.IsShown()) 
2134             // remove the pane from any existing docks except this one 
2135             RemovePaneFromDocks(docks
, p
, dock
); 
2137             // pane needs to be added to the dock, 
2138             // if it doesn't already exist 
2139             if (!FindPaneInDock(*dock
, p
.window
)) 
2140                 dock
->panes
.Add(&p
); 
2144             // remove the pane from any existing docks 
2145             RemovePaneFromDocks(docks
, p
); 
2150     // remove any empty docks 
2151     for (i 
= docks
.GetCount()-1; i 
>= 0; --i
) 
2153         if (docks
.Item(i
).panes
.GetCount() == 0) 
2157     // configure the docks further 
2158     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2160         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2161         int j
, dock_pane_count 
= dock
.panes
.GetCount(); 
2163         // sort the dock pane array by the pane's 
2164         // dock position (dock_pos), in ascending order 
2165         dock
.panes
.Sort(PaneSortFunc
); 
2167         // for newly created docks, set up their initial size 
2172             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2174                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2175                 wxSize pane_size 
= pane
.best_size
; 
2176                 if (pane_size 
== wxDefaultSize
) 
2177                     pane_size 
= pane
.min_size
; 
2178                 if (pane_size 
== wxDefaultSize
) 
2179                     pane_size 
= pane
.window
->GetSize(); 
2181                 if (dock
.IsHorizontal()) 
2182                     size 
= wxMax(pane_size
.y
, size
); 
2184                     size 
= wxMax(pane_size
.x
, size
); 
2187             // add space for the border (two times), but only 
2188             // if at least one pane inside the dock has a pane border 
2189             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2191                 if (dock
.panes
.Item(j
)->HasBorder()) 
2193                     size 
+= (pane_borderSize
*2); 
2198             // if pane is on the top or bottom, add the caption height, 
2199             // but only if at least one pane inside the dock has a caption 
2200             if (dock
.IsHorizontal()) 
2202                 for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2204                     if (dock
.panes
.Item(j
)->HasCaption()) 
2206                         size 
+= caption_size
; 
2213             // new dock's size may not be more than the dock constraint 
2214             // parameter specifies.  See SetDockSizeConstraint() 
2216             int max_dock_x_size 
= (int)(m_dockConstraintX 
* ((double)cli_size
.x
)); 
2217             int max_dock_y_size 
= (int)(m_dockConstraintY 
* ((double)cli_size
.y
)); 
2219             if (dock
.IsHorizontal()) 
2220                 size 
= wxMin(size
, max_dock_y_size
); 
2222                 size 
= wxMin(size
, max_dock_x_size
); 
2224             // absolute minimum size for a dock is 10 pixels 
2232         // determine the dock's minimum size 
2233         bool plus_border 
= false; 
2234         bool plus_caption 
= false; 
2235         int dock_min_size 
= 0; 
2236         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2238             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2239             if (pane
.min_size 
!= wxDefaultSize
) 
2241                 if (pane
.HasBorder()) 
2243                 if (pane
.HasCaption()) 
2244                     plus_caption 
= true; 
2245                 if (dock
.IsHorizontal()) 
2247                     if (pane
.min_size
.y 
> dock_min_size
) 
2248                         dock_min_size 
= pane
.min_size
.y
; 
2252                     if (pane
.min_size
.x 
> dock_min_size
) 
2253                         dock_min_size 
= pane
.min_size
.x
; 
2259             dock_min_size 
+= (pane_borderSize
*2); 
2260         if (plus_caption 
&& dock
.IsHorizontal()) 
2261             dock_min_size 
+= (caption_size
); 
2263         dock
.min_size 
= dock_min_size
; 
2266         // if the pane's current size is less than it's 
2267         // minimum, increase the dock's size to it's minimum 
2268         if (dock
.size 
< dock
.min_size
) 
2269             dock
.size 
= dock
.min_size
; 
2272         // determine the dock's mode (fixed or proportional); 
2273         // determine whether the dock has only toolbars 
2274         bool action_pane_marked 
= false; 
2276         dock
.toolbar 
= true; 
2277         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2279             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2280             if (!pane
.IsFixed()) 
2282             if (!pane
.IsToolbar()) 
2283                 dock
.toolbar 
= false; 
2284             if (pane
.HasFlag(wxAuiPaneInfo::optionDockFixed
)) 
2286             if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
2287                 action_pane_marked 
= true; 
2291         // if the dock mode is proportional and not fixed-pixel, 
2292         // reassign the dock_pos to the sequential 0, 1, 2, 3; 
2293         // e.g. remove gaps like 1, 2, 30, 500 
2296             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2298                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2303         // if the dock mode is fixed, and none of the panes 
2304         // are being moved right now, make sure the panes 
2305         // do not overlap each other.  If they do, we will 
2306         // adjust the positions of the panes 
2307         if (dock
.fixed 
&& !action_pane_marked
) 
2309             wxArrayInt pane_positions
, pane_sizes
; 
2310             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
2313             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2315                 wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(j
)); 
2316                 pane
.dock_pos 
= pane_positions
[j
]; 
2318                 int amount 
= pane
.dock_pos 
- offset
; 
2322                     pane
.dock_pos 
+= -amount
; 
2324                 offset 
+= pane_sizes
[j
]; 
2329     // discover the maximum dock layer 
2331     for (i 
= 0; i 
< dock_count
; ++i
) 
2332         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
2335     // clear out uiparts 
2338     // create a bunch of box sizers, 
2339     // from the innermost level outwards. 
2340     wxSizer
* cont 
= NULL
; 
2341     wxSizer
* middle 
= NULL
; 
2345     for (layer 
= 0; layer 
<= max_layer
; ++layer
) 
2347         wxAuiDockInfoPtrArray arr
; 
2349         // find any docks in this layer 
2350         FindDocks(docks
, -1, layer
, -1, arr
); 
2352         // if there aren't any, skip to the next layer 
2356         wxSizer
* old_cont 
= cont
; 
2358         // create a container which will hold this layer's 
2359         // docks (top, bottom, left, right) 
2360         cont 
= new wxBoxSizer(wxVERTICAL
); 
2363         // find any top docks in this layer 
2364         FindDocks(docks
, wxAUI_DOCK_TOP
, layer
, -1, arr
); 
2367             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2368                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2372         // fill out the middle layer (which consists 
2373         // of left docks, content area and right docks) 
2375         middle 
= new wxBoxSizer(wxHORIZONTAL
); 
2377         // find any left docks in this layer 
2378         FindDocks(docks
, wxAUI_DOCK_LEFT
, layer
, -1, arr
); 
2381             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2382                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2385         // add content dock (or previous layer's sizer 
2389             // find any center docks 
2390             FindDocks(docks
, wxAUI_DOCK_CENTER
, -1, -1, arr
); 
2393                 for (row 
= 0,row_count 
= arr
.GetCount(); row
<row_count
; ++row
) 
2394                    LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2396             else if (!m_hasMaximized
) 
2398                 // there are no center docks, add a background area 
2399                 wxSizerItem
* sizer_item 
= middle
->Add(1,1, 1, wxEXPAND
); 
2400                 wxAuiDockUIPart part
; 
2401                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
2405                 part
.cont_sizer 
= middle
; 
2406                 part
.sizer_item 
= sizer_item
; 
2412             middle
->Add(old_cont
, 1, wxEXPAND
); 
2415         // find any right docks in this layer 
2416         FindDocks(docks
, wxAUI_DOCK_RIGHT
, layer
, -1, arr
); 
2419             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2420                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2423         if (middle
->GetChildren().GetCount() > 0) 
2424             cont
->Add(middle
, 1, wxEXPAND
); 
2430         // find any bottom docks in this layer 
2431         FindDocks(docks
, wxAUI_DOCK_BOTTOM
, layer
, -1, arr
); 
2434             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2435                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2442         // no sizer available, because there are no docks, 
2443         // therefore we will create a simple background area 
2444         cont 
= new wxBoxSizer(wxVERTICAL
); 
2445         wxSizerItem
* sizer_item 
= cont
->Add(1,1, 1, wxEXPAND
); 
2446         wxAuiDockUIPart part
; 
2447         part
.type 
= wxAuiDockUIPart::typeBackground
; 
2451         part
.cont_sizer 
= middle
; 
2452         part
.sizer_item 
= sizer_item
; 
2456     container
->Add(cont
, 1, wxEXPAND
); 
2461 // SetDockSizeConstraint() allows the dock constraints to be set.  For example, 
2462 // specifying values of 0.5, 0.5 will mean that upon dock creation, a dock may 
2463 // not be larger than half of the window's size 
2465 void wxAuiManager::SetDockSizeConstraint(double width_pct
, double height_pct
) 
2467     m_dockConstraintX 
= wxMax(0.0, wxMin(1.0, width_pct
)); 
2468     m_dockConstraintY 
= wxMax(0.0, wxMin(1.0, height_pct
)); 
2471 void wxAuiManager::GetDockSizeConstraint(double* width_pct
, double* height_pct
) const 
2474         *width_pct 
= m_dockConstraintX
; 
2477         *height_pct 
= m_dockConstraintY
; 
2482 // Update() updates the layout.  Whenever changes are made to 
2483 // one or more panes, this function should be called.  It is the 
2484 // external entry point for running the layout engine. 
2486 void wxAuiManager::Update() 
2488     m_hoverButton 
= NULL
; 
2489     m_actionPart 
= NULL
; 
2492     int i
, pane_count 
= m_panes
.GetCount(); 
2495     // destroy floating panes which have been 
2496     // redocked or are becoming non-floating 
2497     for (i 
= 0; i 
< pane_count
; ++i
) 
2499         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2501         if (!p
.IsFloating() && p
.frame
) 
2503             // because the pane is no longer in a floating, we need to 
2504             // reparent it to m_frame and destroy the floating frame 
2507             p
.window
->SetSize(1,1); 
2510             // the following block is a workaround for bug #1531361 
2511             // (see wxWidgets sourceforge page).  On wxGTK (only), when 
2512             // a frame is shown/hidden, a move event unfortunately 
2513             // also gets fired.  Because we may be dragging around 
2514             // a pane, we need to cancel that action here to prevent 
2515             // a spurious crash. 
2516             if (m_actionWindow 
== p
.frame
) 
2518                 if (wxWindow::GetCapture() == m_frame
) 
2519                     m_frame
->ReleaseMouse(); 
2520                 m_action 
= actionNone
; 
2521                 m_actionWindow 
= NULL
; 
2525             if (p
.frame
->IsShown()) 
2526                 p
.frame
->Show(false); 
2528             // reparent to m_frame and destroy the pane 
2529             if (m_actionWindow 
== p
.frame
) 
2531                 m_actionWindow 
= NULL
; 
2534             p
.window
->Reparent(m_frame
); 
2535             p
.frame
->SetSizer(NULL
); 
2542     // delete old sizer first 
2543     m_frame
->SetSizer(NULL
); 
2545     // create a layout for all of the panes 
2546     sizer 
= LayoutAll(m_panes
, m_docks
, m_uiParts
, false); 
2548     // hide or show panes as necessary, 
2549     // and float panes as necessary 
2550     for (i 
= 0; i 
< pane_count
; ++i
) 
2552         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2556             if (p
.frame 
== NULL
) 
2558                 // we need to create a frame for this 
2559                 // pane, which has recently been floated 
2560                 wxAuiFloatingFrame
* frame 
= CreateFloatingFrame(m_frame
, p
); 
2562                 // on MSW and Mac, if the owner desires transparent dragging, and 
2563                 // the dragging is happening right now, then the floating 
2564                 // window should have this style by default 
2565                 if (m_action 
== actionDragFloatingPane 
&& 
2566                     (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
)) 
2567                         frame
->SetTransparent(150); 
2569                 frame
->SetPaneWindow(p
); 
2572                 if (p
.IsShown() && !frame
->IsShown()) 
2577                 // frame already exists, make sure it's position 
2578                 // and size reflect the information in wxAuiPaneInfo 
2579                 if ((p
.frame
->GetPosition() != p
.floating_pos
) || (p
.frame
->GetSize() != p
.floating_size
)) 
2581                     p
.frame
->SetSize(p
.floating_pos
.x
, p
.floating_pos
.y
, 
2582                                      p
.floating_size
.x
, p
.floating_size
.y
, 
2583                                      wxSIZE_USE_EXISTING
); 
2585                     p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, 
2586                                      wxDefaultCoord, wxDefaultCoord, 
2587                                      wxSIZE_USE_EXISTING); 
2588                     //p.frame->Move(p.floating_pos.x, p.floating_pos.y); 
2592                 // update whether the pane is resizable or not 
2593                 long style 
= p
.frame
->GetWindowStyleFlag(); 
2595                     style 
&= ~wxRESIZE_BORDER
; 
2597                     style 
|= wxRESIZE_BORDER
; 
2598                 p
.frame
->SetWindowStyleFlag(style
); 
2600                 if (p
.frame
->GetLabel() != p
.caption
) 
2601                     p
.frame
->SetLabel(p
.caption
); 
2603                 if (p
.frame
->IsShown() != p
.IsShown()) 
2604                     p
.frame
->Show(p
.IsShown()); 
2609             if (p
.window
->IsShown() != p
.IsShown()) 
2610                 p
.window
->Show(p
.IsShown()); 
2613         // if "active panes" are no longer allowed, clear 
2614         // any optionActive values from the pane states 
2615         if ((m_flags 
& wxAUI_MGR_ALLOW_ACTIVE_PANE
) == 0) 
2617             p
.state 
&= ~wxAuiPaneInfo::optionActive
; 
2622     // keep track of the old window rectangles so we can 
2623     // refresh those windows whose rect has changed 
2624     wxAuiRectArray old_pane_rects
; 
2625     for (i 
= 0; i 
< pane_count
; ++i
) 
2628         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2630         if (p
.window 
&& p
.IsShown() && p
.IsDocked()) 
2633         old_pane_rects
.Add(r
); 
2639     // apply the new sizer 
2640     m_frame
->SetSizer(sizer
); 
2641     m_frame
->SetAutoLayout(false); 
2646     // now that the frame layout is done, we need to check 
2647     // the new pane rectangles against the old rectangles that 
2648     // we saved a few lines above here.  If the rectangles have 
2649     // changed, the corresponding panes must also be updated 
2650     for (i 
= 0; i 
< pane_count
; ++i
) 
2652         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2653         if (p
.window 
&& p
.window
->IsShown() && p
.IsDocked()) 
2655             if (p
.rect 
!= old_pane_rects
[i
]) 
2657                 p
.window
->Refresh(); 
2666     // set frame's minimum size 
2669     // N.B. More work needs to be done on frame minimum sizes; 
2670     // this is some intresting code that imposes the minimum size, 
2671     // but we may want to include a more flexible mechanism or 
2672     // options for multiple minimum-size modes, e.g. strict or lax 
2673     wxSize min_size = sizer->GetMinSize(); 
2674     wxSize frame_size = m_frame->GetSize(); 
2675     wxSize client_size = m_frame->GetClientSize(); 
2677     wxSize minframe_size(min_size.x+frame_size.x-client_size.x, 
2678                          min_size.y+frame_size.y-client_size.y ); 
2680     m_frame->SetMinSize(minframe_size); 
2682     if (frame_size.x < minframe_size.x || 
2683         frame_size.y < minframe_size.y) 
2684             sizer->Fit(m_frame); 
2689 // DoFrameLayout() is an internal function which invokes wxSizer::Layout 
2690 // on the frame's main sizer, then measures all the various UI items 
2691 // and updates their internal rectangles.  This should always be called 
2692 // instead of calling m_frame->Layout() directly 
2694 void wxAuiManager::DoFrameLayout() 
2699     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2701         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2703         // get the rectangle of the UI part 
2704         // originally, this code looked like this: 
2705         //    part.rect = wxRect(part.sizer_item->GetPosition(), 
2706         //                       part.sizer_item->GetSize()); 
2707         // this worked quite well, with one exception: the mdi 
2708         // client window had a "deferred" size variable 
2709         // that returned the wrong size.  It looks like 
2710         // a bug in wx, because the former size of the window 
2711         // was being returned.  So, we will retrieve the part's 
2712         // rectangle via other means 
2715         part
.rect 
= part
.sizer_item
->GetRect(); 
2716         int flag 
= part
.sizer_item
->GetFlag(); 
2717         int border 
= part
.sizer_item
->GetBorder(); 
2720             part
.rect
.y 
-= border
; 
2721             part
.rect
.height 
+= border
; 
2725             part
.rect
.x 
-= border
; 
2726             part
.rect
.width 
+= border
; 
2728         if (flag 
& wxBOTTOM
) 
2729             part
.rect
.height 
+= border
; 
2731             part
.rect
.width 
+= border
; 
2734         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2735             part
.dock
->rect 
= part
.rect
; 
2736         if (part
.type 
== wxAuiDockUIPart::typePane
) 
2737             part
.pane
->rect 
= part
.rect
; 
2741 // GetPanePart() looks up the pane the pane border UI part (or the regular 
2742 // pane part if there is no border). This allows the caller to get the exact 
2743 // rectangle of the pane in question, including decorations like 
2744 // caption and border (if any). 
2746 wxAuiDockUIPart
* wxAuiManager::GetPanePart(wxWindow
* wnd
) 
2749     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2751         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2752         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
2753             part
.pane 
&& part
.pane
->window 
== wnd
) 
2756     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2758         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2759         if (part
.type 
== wxAuiDockUIPart::typePane 
&& 
2760             part
.pane 
&& part
.pane
->window 
== wnd
) 
2768 // GetDockPixelOffset() is an internal function which returns 
2769 // a dock's offset in pixels from the left side of the window 
2770 // (for horizontal docks) or from the top of the window (for 
2771 // vertical docks).  This value is necessary for calculating 
2772 // fixel-pane/toolbar offsets when they are dragged. 
2774 int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo
& test
) 
2776     // the only way to accurately calculate the dock's 
2777     // offset is to actually run a theoretical layout 
2779     int i
, part_count
, dock_count
; 
2780     wxAuiDockInfoArray docks
; 
2781     wxAuiPaneInfoArray panes
; 
2782     wxAuiDockUIPartArray uiparts
; 
2783     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
2786     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
2787     wxSize client_size 
= m_frame
->GetClientSize(); 
2788     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
2791     for (i 
= 0, part_count 
= uiparts
.GetCount(); i 
< part_count
; ++i
) 
2793         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
2794         part
.rect 
= wxRect(part
.sizer_item
->GetPosition(), 
2795                            part
.sizer_item
->GetSize()); 
2796         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2797             part
.dock
->rect 
= part
.rect
; 
2802     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2804         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2805         if (test
.dock_direction 
== dock
.dock_direction 
&& 
2806             test
.dock_layer
==dock
.dock_layer 
&& test
.dock_row
==dock
.dock_row
) 
2808             if (dock
.IsVertical()) 
2820 // ProcessDockResult() is a utility function used by DoDrop() - it checks 
2821 // if a dock operation is allowed, the new dock position is copied into 
2822 // the target info.  If the operation was allowed, the function returns true. 
2824 bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo
& target
, 
2825                                      const wxAuiPaneInfo
& new_pos
) 
2827     bool allowed 
= false; 
2828     switch (new_pos
.dock_direction
) 
2830         case wxAUI_DOCK_TOP
:    allowed 
= target
.IsTopDockable();    break; 
2831         case wxAUI_DOCK_BOTTOM
: allowed 
= target
.IsBottomDockable(); break; 
2832         case wxAUI_DOCK_LEFT
:   allowed 
= target
.IsLeftDockable();   break; 
2833         case wxAUI_DOCK_RIGHT
:  allowed 
= target
.IsRightDockable();  break; 
2839         // Should this RTTI and function call be rewritten as 
2840         // sending a new event type to allow other window types 
2841         // to vary size based on dock location? 
2842         wxAuiToolBar
* toolbar 
= wxDynamicCast(target
.window
, wxAuiToolBar
); 
2845             wxSize hintSize 
= toolbar
->GetHintSize(target
.dock_direction
); 
2846             if (target
.best_size 
!= hintSize
) 
2848                 target
.best_size 
= hintSize
; 
2849                 target
.floating_size 
= wxDefaultSize
; 
2858 // DoDrop() is an important function.  It basically takes a mouse position, 
2859 // and determines where the pane's new position would be.  If the pane is to be 
2860 // dropped, it performs the drop operation using the specified dock and pane 
2861 // arrays.  By specifying copied dock and pane arrays when calling, a "what-if" 
2862 // scenario can be performed, giving precise coordinates for drop hints. 
2863 // If, however, wxAuiManager:m_docks and wxAuiManager::m_panes are specified 
2864 // as parameters, the changes will be made to the main state arrays 
2866 const int auiInsertRowPixels 
= 10; 
2867 const int auiNewRowPixels 
= 40; 
2868 const int auiLayerInsertPixels 
= 40; 
2869 const int auiLayerInsertOffset 
= 5; 
2871 bool wxAuiManager::DoDrop(wxAuiDockInfoArray
& docks
, 
2872                           wxAuiPaneInfoArray
& panes
, 
2873                           wxAuiPaneInfo
& target
, 
2875                           const wxPoint
& offset
) 
2877     wxSize cli_size 
= m_frame
->GetClientSize(); 
2879     wxAuiPaneInfo drop 
= target
; 
2882     // The result should always be shown 
2886     // Check to see if the pane has been dragged outside of the window 
2887     // (or near to the outside of the window), if so, dock it along the edge 
2890     int layer_insert_offset 
= auiLayerInsertOffset
; 
2891     if (drop
.IsToolbar()) 
2892         layer_insert_offset 
= 0; 
2895     if (pt
.x 
< layer_insert_offset 
&& 
2896         pt
.x 
> layer_insert_offset
-auiLayerInsertPixels 
&& 
2900         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
2901                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
2902                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)) + 1; 
2904         if (drop
.IsToolbar()) 
2905             new_layer 
= auiToolBarLayer
; 
2910              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2911         return ProcessDockResult(target
, drop
); 
2913     else if (pt
.y 
< layer_insert_offset 
&& 
2914              pt
.y 
> layer_insert_offset
-auiLayerInsertPixels 
&& 
2918         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
2919                                 GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2920                                 GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2922         if (drop
.IsToolbar()) 
2923             new_layer 
= auiToolBarLayer
; 
2928              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2929         return ProcessDockResult(target
, drop
); 
2931     else if (pt
.x 
>= cli_size
.x 
- layer_insert_offset 
&& 
2932              pt
.x 
< cli_size
.x 
- layer_insert_offset 
+ auiLayerInsertPixels 
&& 
2936         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
2937                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
2938                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)) + 1; 
2940         if (drop
.IsToolbar()) 
2941             new_layer 
= auiToolBarLayer
; 
2943         drop
.Dock().Right(). 
2946              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2947         return ProcessDockResult(target
, drop
); 
2949     else if (pt
.y 
>= cli_size
.y 
- layer_insert_offset 
&& 
2950              pt
.y 
< cli_size
.y 
- layer_insert_offset 
+ auiLayerInsertPixels 
&& 
2954         int new_layer 
= wxMax( wxMax( GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
2955                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2956                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2958         if (drop
.IsToolbar()) 
2959             new_layer 
= auiToolBarLayer
; 
2961         drop
.Dock().Bottom(). 
2964              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2965         return ProcessDockResult(target
, drop
); 
2969     wxAuiDockUIPart
* part 
= HitTest(pt
.x
, pt
.y
); 
2972     if (drop
.IsToolbar()) 
2974         if (!part 
|| !part
->dock
) 
2977         // calculate the offset from where the dock begins 
2978         // to the point where the user dropped the pane 
2979         int dock_drop_offset 
= 0; 
2980         if (part
->dock
->IsHorizontal()) 
2981             dock_drop_offset 
= pt
.x 
- part
->dock
->rect
.x 
- offset
.x
; 
2983             dock_drop_offset 
= pt
.y 
- part
->dock
->rect
.y 
- offset
.y
; 
2986         // toolbars may only be moved in and to fixed-pane docks, 
2987         // otherwise we will try to float the pane.  Also, the pane 
2988         // should float if being dragged over center pane windows 
2989         if (!part
->dock
->fixed 
|| part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER 
|| 
2990             pt
.x 
>= cli_size
.x 
|| pt
.x 
<= 0 || pt
.y 
>= cli_size
.y 
|| pt
.y 
<= 0) 
2992             if (m_lastRect
.IsEmpty() || m_lastRect
.Contains(pt
.x
, pt
.y 
)) 
2998                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && drop
.IsFloatable()) 
3005                 return ProcessDockResult(target
, drop
); 
3008             drop
.Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
3010             return ProcessDockResult(target
, drop
); 
3015         m_lastRect 
= part
->dock
->rect
; 
3016         m_lastRect
.Inflate( 15, 15 ); 
3019              Direction(part
->dock
->dock_direction
). 
3020              Layer(part
->dock
->dock_layer
). 
3021              Row(part
->dock
->dock_row
). 
3022              Position(dock_drop_offset
); 
3025             ((pt
.y 
< part
->dock
->rect
.y 
+ 1) && part
->dock
->IsHorizontal()) || 
3026             ((pt
.x 
< part
->dock
->rect
.x 
+ 1) && part
->dock
->IsVertical()) 
3027             ) && part
->dock
->panes
.GetCount() > 1) 
3029             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
3030                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
3032                 int row 
= drop
.dock_row
; 
3033                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3034                                 part
->dock
->dock_layer
, 
3035                                 part
->dock
->dock_row
); 
3036                 drop
.dock_row 
= row
; 
3040                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3041                                 part
->dock
->dock_layer
, 
3042                                 part
->dock
->dock_row
+1); 
3043                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
3048             ((pt
.y 
> part
->dock
->rect
.y 
+ part
->dock
->rect
.height 
- 2 ) && part
->dock
->IsHorizontal()) || 
3049             ((pt
.x 
> part
->dock
->rect
.x 
+ part
->dock
->rect
.width 
- 2 ) && part
->dock
->IsVertical()) 
3050             ) && part
->dock
->panes
.GetCount() > 1) 
3052             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
3053                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
3055                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3056                                 part
->dock
->dock_layer
, 
3057                                 part
->dock
->dock_row
+1); 
3058                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
3062                 int row 
= drop
.dock_row
; 
3063                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3064                                 part
->dock
->dock_layer
, 
3065                                 part
->dock
->dock_row
); 
3066                 drop
.dock_row 
= row
; 
3070         return ProcessDockResult(target
, drop
); 
3079     if (part
->type 
== wxAuiDockUIPart::typePaneBorder 
|| 
3080         part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
3081         part
->type 
== wxAuiDockUIPart::typeGripper 
|| 
3082         part
->type 
== wxAuiDockUIPart::typePaneButton 
|| 
3083         part
->type 
== wxAuiDockUIPart::typePane 
|| 
3084         part
->type 
== wxAuiDockUIPart::typePaneSizer 
|| 
3085         part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
3086         part
->type 
== wxAuiDockUIPart::typeBackground
) 
3088         if (part
->type 
== wxAuiDockUIPart::typeDockSizer
) 
3090             if (part
->dock
->panes
.GetCount() != 1) 
3092             part 
= GetPanePart(part
->dock
->panes
.Item(0)->window
); 
3099         // If a normal frame is being dragged over a toolbar, insert it 
3100         // along the edge under the toolbar, but over all other panes. 
3101         // (this could be done much better, but somehow factoring this 
3102         // calculation with the one at the beginning of this function) 
3103         if (part
->dock 
&& part
->dock
->toolbar
) 
3107             switch (part
->dock
->dock_direction
) 
3109                 case wxAUI_DOCK_LEFT
: 
3110                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
3111                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
3112                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)); 
3114                 case wxAUI_DOCK_TOP
: 
3115                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
3116                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3117                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3119                 case wxAUI_DOCK_RIGHT
: 
3120                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
3121                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
3122                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)); 
3124                 case wxAUI_DOCK_BOTTOM
: 
3125                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
3126                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3127                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3131             DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3134                  Direction(part
->dock
->dock_direction
). 
3135                  Layer(layer
).Row(0).Position(0); 
3136             return ProcessDockResult(target
, drop
); 
3143         part 
= GetPanePart(part
->pane
->window
); 
3147         bool insert_dock_row 
= false; 
3148         int insert_row 
= part
->pane
->dock_row
; 
3149         int insert_dir 
= part
->pane
->dock_direction
; 
3150         int insert_layer 
= part
->pane
->dock_layer
; 
3152         switch (part
->pane
->dock_direction
) 
3154             case wxAUI_DOCK_TOP
: 
3155                 if (pt
.y 
>= part
->rect
.y 
&& 
3156                     pt
.y 
< part
->rect
.y
+auiInsertRowPixels
) 
3157                         insert_dock_row 
= true; 
3159             case wxAUI_DOCK_BOTTOM
: 
3160                 if (pt
.y 
> part
->rect
.y
+part
->rect
.height
-auiInsertRowPixels 
&& 
3161                     pt
.y 
<= part
->rect
.y 
+ part
->rect
.height
) 
3162                         insert_dock_row 
= true; 
3164             case wxAUI_DOCK_LEFT
: 
3165                 if (pt
.x 
>= part
->rect
.x 
&& 
3166                     pt
.x 
< part
->rect
.x
+auiInsertRowPixels
) 
3167                         insert_dock_row 
= true; 
3169             case wxAUI_DOCK_RIGHT
: 
3170                 if (pt
.x 
> part
->rect
.x
+part
->rect
.width
-auiInsertRowPixels 
&& 
3171                     pt
.x 
<= part
->rect
.x
+part
->rect
.width
) 
3172                         insert_dock_row 
= true; 
3174             case wxAUI_DOCK_CENTER
: 
3176                 // "new row pixels" will be set to the default, but 
3177                 // must never exceed 20% of the window size 
3178                 int new_row_pixels_x 
= auiNewRowPixels
; 
3179                 int new_row_pixels_y 
= auiNewRowPixels
; 
3181                 if (new_row_pixels_x 
> (part
->rect
.width
*20)/100) 
3182                     new_row_pixels_x 
= (part
->rect
.width
*20)/100; 
3184                 if (new_row_pixels_y 
> (part
->rect
.height
*20)/100) 
3185                     new_row_pixels_y 
= (part
->rect
.height
*20)/100; 
3188                 // determine if the mouse pointer is in a location that 
3189                 // will cause a new row to be inserted.  The hot spot positions 
3190                 // are along the borders of the center pane 
3193                 insert_dock_row 
= true; 
3194                 const wxRect
& pr 
= part
->rect
; 
3195                 if (pt
.x 
>= pr
.x 
&& pt
.x 
< pr
.x 
+ new_row_pixels_x
) 
3196                     insert_dir 
= wxAUI_DOCK_LEFT
; 
3197                 else if (pt
.y 
>= pr
.y 
&& pt
.y 
< pr
.y 
+ new_row_pixels_y
) 
3198                     insert_dir 
= wxAUI_DOCK_TOP
; 
3199                 else if (pt
.x 
>= pr
.x 
+ pr
.width 
- new_row_pixels_x 
&& 
3200                          pt
.x 
< pr
.x 
+ pr
.width
) 
3201                     insert_dir 
= wxAUI_DOCK_RIGHT
; 
3202                 else if (pt
.y 
>= pr
.y
+ pr
.height 
- new_row_pixels_y 
&& 
3203                          pt
.y 
< pr
.y 
+ pr
.height
) 
3204                     insert_dir 
= wxAUI_DOCK_BOTTOM
; 
3208                 insert_row 
= GetMaxRow(panes
, insert_dir
, insert_layer
) + 1; 
3212         if (insert_dock_row
) 
3214             DoInsertDockRow(panes
, insert_dir
, insert_layer
, insert_row
); 
3215             drop
.Dock().Direction(insert_dir
). 
3216                         Layer(insert_layer
). 
3219             return ProcessDockResult(target
, drop
); 
3222         // determine the mouse offset and the pane size, both in the 
3223         // direction of the dock itself, and perpendicular to the dock 
3227         if (part
->orientation 
== wxVERTICAL
) 
3229             offset 
= pt
.y 
- part
->rect
.y
; 
3230             size 
= part
->rect
.GetHeight(); 
3234             offset 
= pt
.x 
- part
->rect
.x
; 
3235             size 
= part
->rect
.GetWidth(); 
3238         int drop_position 
= part
->pane
->dock_pos
; 
3240         // if we are in the top/left part of the pane, 
3241         // insert the pane before the pane being hovered over 
3242         if (offset 
<= size
/2) 
3244             drop_position 
= part
->pane
->dock_pos
; 
3246                          part
->pane
->dock_direction
, 
3247                          part
->pane
->dock_layer
, 
3248                          part
->pane
->dock_row
, 
3249                          part
->pane
->dock_pos
); 
3252         // if we are in the bottom/right part of the pane, 
3253         // insert the pane before the pane being hovered over 
3254         if (offset 
> size
/2) 
3256             drop_position 
= part
->pane
->dock_pos
+1; 
3258                          part
->pane
->dock_direction
, 
3259                          part
->pane
->dock_layer
, 
3260                          part
->pane
->dock_row
, 
3261                          part
->pane
->dock_pos
+1); 
3265              Direction(part
->dock
->dock_direction
). 
3266              Layer(part
->dock
->dock_layer
). 
3267              Row(part
->dock
->dock_row
). 
3268              Position(drop_position
); 
3269         return ProcessDockResult(target
, drop
); 
3276 void wxAuiManager::OnHintFadeTimer(wxTimerEvent
& WXUNUSED(event
)) 
3278     if (!m_hintWnd 
|| m_hintFadeAmt 
>= m_hintFadeMax
) 
3280         m_hintFadeTimer
.Stop(); 
3281         Disconnect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3282                    wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3287     m_hintWnd
->SetTransparent(m_hintFadeAmt
); 
3290 void wxAuiManager::ShowHint(const wxRect
& rect
) 
3294         // if the hint rect is the same as last time, don't do anything 
3295         if (m_lastHint 
== rect
) 
3299         m_hintFadeAmt 
= m_hintFadeMax
; 
3301         if ((m_flags 
& wxAUI_MGR_HINT_FADE
) 
3302             && !((m_hintWnd
->IsKindOf(CLASSINFO(wxPseudoTransparentFrame
))) && 
3303                  (m_flags 
& wxAUI_MGR_NO_VENETIAN_BLINDS_FADE
)) 
3307         m_hintWnd
->SetSize(rect
); 
3308         m_hintWnd
->SetTransparent(m_hintFadeAmt
); 
3310         if (!m_hintWnd
->IsShown()) 
3313         // if we are dragging a floating pane, set the focus 
3314         // back to that floating pane (otherwise it becomes unfocused) 
3315         if (m_action 
== actionDragFloatingPane 
&& m_actionWindow
) 
3316             m_actionWindow
->SetFocus(); 
3321         if (m_hintFadeAmt 
!= m_hintFadeMax
) //  Only fade if we need to 
3323             // start fade in timer 
3324             m_hintFadeTimer
.SetOwner(this); 
3325             m_hintFadeTimer
.Start(5); 
3326             Connect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3327                     wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3330     else  // Not using a transparent hint window... 
3332         if (!(m_flags 
& wxAUI_MGR_RECTANGLE_HINT
)) 
3335         if (m_lastHint 
!= rect
) 
3337             // remove the last hint rectangle 
3343         wxScreenDC screendc
; 
3344         wxRegion 
clip(1, 1, 10000, 10000); 
3346         // clip all floating windows, so we don't draw over them 
3348         for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
3350             wxAuiPaneInfo
& pane 
= m_panes
.Item(i
); 
3352             if (pane
.IsFloating() && 
3354                         pane
.frame
->IsShown()) 
3356                 wxRect rect 
= pane
.frame
->GetRect(); 
3358                 // wxGTK returns the client size, not the whole frame size 
3364                 clip
.Subtract(rect
); 
3368         // As we can only hide the hint by redrawing the managed window, we 
3369         // need to clip the region to the managed window too or we get 
3370         // nasty redrawn problems. 
3371         clip
.Intersect(m_frame
->GetRect()); 
3373         screendc
.SetDeviceClippingRegion(clip
); 
3375         wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
3376         wxBrush 
brush(stipple
); 
3377         screendc
.SetBrush(brush
); 
3378         screendc
.SetPen(*wxTRANSPARENT_PEN
); 
3380         screendc
.DrawRectangle(rect
.x
, rect
.y
, 5, rect
.height
); 
3381         screendc
.DrawRectangle(rect
.x
+5, rect
.y
, rect
.width
-10, 5); 
3382         screendc
.DrawRectangle(rect
.x
+rect
.width
-5, rect
.y
, 5, rect
.height
); 
3383         screendc
.DrawRectangle(rect
.x
+5, rect
.y
+rect
.height
-5, rect
.width
-10, 5); 
3387 void wxAuiManager::HideHint() 
3389     // hides a transparent window hint, if there is one 
3392         if (m_hintWnd
->IsShown()) 
3393             m_hintWnd
->Show(false); 
3394         m_hintWnd
->SetTransparent(0); 
3395         m_hintFadeTimer
.Stop(); 
3396         // In case this is called while a hint fade is going, we need to 
3397         // disconnect the event handler. 
3398         Disconnect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3399                    wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3400         m_lastHint 
= wxRect(); 
3404     // hides a painted hint by redrawing the frame window 
3405     if (!m_lastHint
.IsEmpty()) 
3409         m_lastHint 
= wxRect(); 
3413 void wxAuiManager::OnHintActivate(wxActivateEvent
& WXUNUSED(event
)) 
3415     // Do nothing so this event isn't handled in the base handlers. 
3417     // Letting the hint window activate without this handler can lead to 
3418     // weird behaviour on Mac where the menu is switched out to the top 
3419     // window's menu in MDI applications when it shouldn't be. So since 
3420     // we don't want user interaction with the hint window anyway, we just 
3421     // prevent it from activating here. 
3426 void wxAuiManager::StartPaneDrag(wxWindow
* pane_window
, 
3427                                  const wxPoint
& offset
) 
3429     wxAuiPaneInfo
& pane 
= GetPane(pane_window
); 
3433     if (pane
.IsToolbar()) 
3435         m_action 
= actionDragToolbarPane
; 
3439         m_action 
= actionDragFloatingPane
; 
3442     m_actionWindow 
= pane_window
; 
3443     m_actionOffset 
= offset
; 
3444     m_frame
->CaptureMouse(); 
3448         wxRect window_rect 
= pane
.frame
->GetRect(); 
3449         wxRect client_rect 
= pane
.frame
->GetClientRect(); 
3450         wxPoint client_pt 
= pane
.frame
->ClientToScreen(client_rect
.GetTopLeft()); 
3451         wxPoint origin_pt 
= client_pt 
- window_rect
.GetTopLeft(); 
3452         m_actionOffset 
+= origin_pt
; 
3457 // CalculateHintRect() calculates the drop hint rectangle.  The method 
3458 // first calls DoDrop() to determine the exact position the pane would 
3459 // be at were if dropped.  If the pane would indeed become docked at the 
3460 // specified drop point, the rectangle hint will be returned in 
3461 // screen coordinates.  Otherwise, an empty rectangle is returned. 
3462 // |pane_window| is the window pointer of the pane being dragged, |pt| is 
3463 // the mouse position, in client coordinates.  |offset| describes the offset 
3464 // that the mouse is from the upper-left corner of the item being dragged 
3466 wxRect 
wxAuiManager::CalculateHintRect(wxWindow
* pane_window
, 
3468                                        const wxPoint
& offset
) 
3472     // we need to paint a hint rectangle; to find out the exact hint rectangle, 
3473     // we will create a new temporary layout and then measure the resulting 
3474     // rectangle; we will create a copy of the docking structures (m_dock) 
3475     // so that we don't modify the real thing on screen 
3477     int i
, pane_count
, part_count
; 
3478     wxAuiDockInfoArray docks
; 
3479     wxAuiPaneInfoArray panes
; 
3480     wxAuiDockUIPartArray uiparts
; 
3481     wxAuiPaneInfo hint 
= GetPane(pane_window
); 
3482     hint
.name 
= wxT("__HINT__"); 
3483     hint
.PaneBorder(true); 
3489     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3491     // remove any pane already there which bears the same window; 
3492     // this happens when you are moving a pane around in a dock 
3493     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
3495         if (panes
.Item(i
).window 
== pane_window
) 
3497             RemovePaneFromDocks(docks
, panes
.Item(i
)); 
3503     // find out where the new pane would be 
3504     if (!DoDrop(docks
, panes
, hint
, pt
, offset
)) 
3511     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
3512     wxSize client_size 
= m_frame
->GetClientSize(); 
3513     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
3516     for (i 
= 0, part_count 
= uiparts
.GetCount(); 
3517          i 
< part_count
; ++i
) 
3519         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
3521         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
3522             part
.pane 
&& part
.pane
->name 
== wxT("__HINT__")) 
3524             rect 
= wxRect(part
.sizer_item
->GetPosition(), 
3525                           part
.sizer_item
->GetSize()); 
3537     // actually show the hint rectangle on the screen 
3538     m_frame
->ClientToScreen(&rect
.x
, &rect
.y
); 
3540     if ( m_frame
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
3542         // Mirror rectangle in RTL mode 
3543         rect
.x 
-= rect
.GetWidth(); 
3549 // DrawHintRect() calculates the hint rectangle by calling 
3550 // CalculateHintRect().  If there is a rectangle, it shows it 
3551 // by calling ShowHint(), otherwise it hides any hint 
3552 // rectangle currently shown 
3553 void wxAuiManager::DrawHintRect(wxWindow
* pane_window
, 
3555                                 const wxPoint
& offset
) 
3557     wxRect rect 
= CalculateHintRect(pane_window
, pt
, offset
); 
3569 void wxAuiManager::OnFloatingPaneMoveStart(wxWindow
* wnd
) 
3571     // try to find the pane 
3572     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3573     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3578     if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3579         pane
.frame
->SetTransparent(150); 
3582 void wxAuiManager::OnFloatingPaneMoving(wxWindow
* wnd
, wxDirection dir
) 
3584     // try to find the pane 
3585     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3586     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3591     wxPoint pt 
= ::wxGetMousePosition(); 
3594     // Adapt pt to direction 
3597         // move to pane's upper border 
3599         pos 
= wnd
->ClientToScreen( pos 
); 
3601         // and some more pixels for the title bar 
3604     else if (dir 
== wxWEST
) 
3606         // move to pane's left border 
3608         pos 
= wnd
->ClientToScreen( pos 
); 
3611     else if (dir 
== wxEAST
) 
3613         // move to pane's right border 
3614         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3615         pos 
= wnd
->ClientToScreen( pos 
); 
3618     else if (dir 
== wxSOUTH
) 
3620         // move to pane's bottom border 
3621         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3622         pos 
= wnd
->ClientToScreen( pos 
); 
3629     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3631     // calculate the offset from the upper left-hand corner 
3632     // of the frame to the mouse pointer 
3633     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3634     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3636     // no hint for toolbar floating windows 
3637     if (pane
.IsToolbar() && m_action 
== actionDragFloatingPane
) 
3639         wxAuiDockInfoArray docks
; 
3640         wxAuiPaneInfoArray panes
; 
3641         wxAuiDockUIPartArray uiparts
; 
3642         wxAuiPaneInfo hint 
= pane
; 
3644         CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3646         // find out where the new pane would be 
3647         if (!DoDrop(docks
, panes
, hint
, client_pt
)) 
3649         if (hint
.IsFloating()) 
3653         m_action 
= actionDragToolbarPane
; 
3654         m_actionWindow 
= pane
.window
; 
3662     // if a key modifier is pressed while dragging the frame, 
3663     // don't dock the window 
3664     if (!CanDockPanel(pane
)) 
3671     DrawHintRect(wnd
, client_pt
, action_offset
); 
3674     // this cleans up some screen artifacts that are caused on GTK because 
3675     // we aren't getting the exact size of the window (see comment 
3685 void wxAuiManager::OnFloatingPaneMoved(wxWindow
* wnd
, wxDirection dir
) 
3687     // try to find the pane 
3688     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3689     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3694     wxPoint pt 
= ::wxGetMousePosition(); 
3697     // Adapt pt to direction 
3700         // move to pane's upper border 
3702         pos 
= wnd
->ClientToScreen( pos 
); 
3704         // and some more pixels for the title bar 
3707     else if (dir 
== wxWEST
) 
3709         // move to pane's left border 
3711         pos 
= wnd
->ClientToScreen( pos 
); 
3714     else if (dir 
== wxEAST
) 
3716         // move to pane's right border 
3717         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3718         pos 
= wnd
->ClientToScreen( pos 
); 
3721     else if (dir 
== wxSOUTH
) 
3723         // move to pane's bottom border 
3724         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3725         pos 
= wnd
->ClientToScreen( pos 
); 
3732     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3734     // calculate the offset from the upper left-hand corner 
3735     // of the frame to the mouse pointer 
3736     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3737     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3739     // if a key modifier is pressed while dragging the frame, 
3740     // don't dock the window 
3741     if (CanDockPanel(pane
)) 
3743         // do the drop calculation 
3744         DoDrop(m_docks
, m_panes
, pane
, client_pt
, action_offset
); 
3747     // if the pane is still floating, update it's floating 
3748     // position (that we store) 
3749     if (pane
.IsFloating()) 
3751         pane
.floating_pos 
= pane
.frame
->GetPosition(); 
3753         if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3754             pane
.frame
->SetTransparent(255); 
3756     else if (m_hasMaximized
) 
3758         RestoreMaximizedPane(); 
3766 void wxAuiManager::OnFloatingPaneResized(wxWindow
* wnd
, const wxRect
& rect
) 
3768     // try to find the pane 
3769     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3770     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3772     pane
.FloatingSize(rect
.GetWidth(), rect
.GetHeight()); 
3774     // the top-left position may change as well as the size 
3775     pane
.FloatingPosition(rect
.x
, rect
.y
); 
3779 void wxAuiManager::OnFloatingPaneClosed(wxWindow
* wnd
, wxCloseEvent
& evt
) 
3781     // try to find the pane 
3782     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3783     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3786     // fire pane close event 
3787     wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
3789     e
.SetCanVeto(evt
.CanVeto()); 
3799         // close the pane, but check that it 
3800         // still exists in our pane array first 
3801         // (the event handler above might have removed it) 
3803         wxAuiPaneInfo
& check 
= GetPane(wnd
); 
3813 void wxAuiManager::OnFloatingPaneActivated(wxWindow
* wnd
) 
3815     if ((GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) && GetPane(wnd
).IsOk()) 
3817         SetActivePane(m_panes
, wnd
); 
3822 // OnRender() draws all of the pane captions, sashes, 
3823 // backgrounds, captions, grippers, pane borders and buttons. 
3824 // It renders the entire user interface. 
3826 void wxAuiManager::OnRender(wxAuiManagerEvent
& evt
) 
3828     // if the frame is about to be deleted, don't bother 
3829     if (!m_frame 
|| wxPendingDelete
.Member(m_frame
)) 
3832     wxDC
* dc 
= evt
.GetDC(); 
3838     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); 
3839          i 
< part_count
; ++i
) 
3841         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
3843         // don't draw hidden pane items or items that aren't windows 
3844         if (part
.sizer_item 
&& ((!part
.sizer_item
->IsWindow() && !part
.sizer_item
->IsSpacer() && !part
.sizer_item
->IsSizer()) || !part
.sizer_item
->IsShown())) 
3849             case wxAuiDockUIPart::typeDockSizer
: 
3850             case wxAuiDockUIPart::typePaneSizer
: 
3851                 m_art
->DrawSash(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3853             case wxAuiDockUIPart::typeBackground
: 
3854                 m_art
->DrawBackground(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3856             case wxAuiDockUIPart::typeCaption
: 
3857                 m_art
->DrawCaption(*dc
, m_frame
, part
.pane
->caption
, part
.rect
, *part
.pane
); 
3859             case wxAuiDockUIPart::typeGripper
: 
3860                 m_art
->DrawGripper(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3862             case wxAuiDockUIPart::typePaneBorder
: 
3863                 m_art
->DrawBorder(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3865             case wxAuiDockUIPart::typePaneButton
: 
3866                 m_art
->DrawPaneButton(*dc
, m_frame
, part
.button
->button_id
, 
3867                         wxAUI_BUTTON_STATE_NORMAL
, part
.rect
, *part
.pane
); 
3874 // Render() fire a render event, which is normally handled by 
3875 // wxAuiManager::OnRender().  This allows the render function to 
3876 // be overridden via the render event.  This can be useful for paintin 
3877 // custom graphics in the main window. Default behaviour can be 
3878 // invoked in the overridden function by calling OnRender() 
3880 void wxAuiManager::Render(wxDC
* dc
) 
3882     wxAuiManagerEvent 
e(wxEVT_AUI_RENDER
); 
3888 void wxAuiManager::Repaint(wxDC
* dc
) 
3893         m_frame
->Refresh() ; 
3899     m_frame
->GetClientSize(&w
, &h
); 
3901     // figure out which dc to use; if one 
3902     // has been specified, use it, otherwise 
3904     wxClientDC
* client_dc 
= NULL
; 
3907         client_dc 
= new wxClientDC(m_frame
); 
3911     // if the frame has a toolbar, the client area 
3912     // origin will not be (0,0). 
3913     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
3914     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
3915         dc
->SetDeviceOrigin(pt
.x
, pt
.y
); 
3917     // render all the items 
3920     // if we created a client_dc, delete it 
3925 void wxAuiManager::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
3927     wxPaintDC 
dc(m_frame
); 
3931 void wxAuiManager::OnEraseBackground(wxEraseEvent
& event
) 
3940 void wxAuiManager::OnSize(wxSizeEvent
& event
) 
3948         if (m_frame
->IsKindOf(CLASSINFO(wxMDIParentFrame
))) 
3950             // for MDI parent frames, this event must not 
3951             // be "skipped".  In other words, the parent frame 
3952             // must not be allowed to resize the client window 
3953             // after we are finished processing sizing changes 
3961 void wxAuiManager::OnFindManager(wxAuiManagerEvent
& evt
) 
3963     // get the window we are managing, if none, return NULL 
3964     wxWindow
* window 
= GetManagedWindow(); 
3967         evt
.SetManager(NULL
); 
3971     // if we are managing a child frame, get the 'real' manager 
3972     if (window
->IsKindOf(CLASSINFO(wxAuiFloatingFrame
))) 
3974         wxAuiFloatingFrame
* float_frame 
= static_cast<wxAuiFloatingFrame
*>(window
); 
3975         evt
.SetManager(float_frame
->GetOwnerManager()); 
3979     // return pointer to ourself 
3980     evt
.SetManager(this); 
3983 void wxAuiManager::OnSetCursor(wxSetCursorEvent
& event
) 
3986     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
3987     wxCursor cursor 
= wxNullCursor
; 
3991         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
3992             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
3994             // a dock may not be resized if it has a single 
3995             // pane which is not resizable 
3996             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
3997                 part
->dock
->panes
.GetCount() == 1 && 
3998                 part
->dock
->panes
.Item(0)->IsFixed()) 
4001             // panes that may not be resized do not get a sizing cursor 
4002             if (part
->pane 
&& part
->pane
->IsFixed()) 
4005             if (part
->orientation 
== wxVERTICAL
) 
4006                 cursor 
= wxCursor(wxCURSOR_SIZEWE
); 
4008                 cursor 
= wxCursor(wxCURSOR_SIZENS
); 
4010         else if (part
->type 
== wxAuiDockUIPart::typeGripper
) 
4012             cursor 
= wxCursor(wxCURSOR_SIZING
); 
4016     event
.SetCursor(cursor
); 
4021 void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart
* button_ui_part
, 
4022                                         const wxMouseEvent
& event
) 
4024     wxAuiDockUIPart
* hit_test 
= HitTest(event
.GetX(), event
.GetY()); 
4025     if (!hit_test 
|| !button_ui_part
) 
4028     int state 
= wxAUI_BUTTON_STATE_NORMAL
; 
4030     if (hit_test 
== button_ui_part
) 
4032         if (event
.LeftDown()) 
4033             state 
= wxAUI_BUTTON_STATE_PRESSED
; 
4035             state 
= wxAUI_BUTTON_STATE_HOVER
; 
4039         if (event
.LeftDown()) 
4040             state 
= wxAUI_BUTTON_STATE_HOVER
; 
4043     // now repaint the button with hover state 
4044     wxClientDC 
cdc(m_frame
); 
4046     // if the frame has a toolbar, the client area 
4047     // origin will not be (0,0). 
4048     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
4049     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
4050         cdc
.SetDeviceOrigin(pt
.x
, pt
.y
); 
4054         m_art
->DrawPaneButton(cdc
, m_frame
, 
4055                   button_ui_part
->button
->button_id
, 
4057                   button_ui_part
->rect
, 
4062 void wxAuiManager::OnLeftDown(wxMouseEvent
& event
) 
4064     m_currentDragItem 
= -1; 
4066     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4069         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
4070             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4072             // Removing this restriction so that a centre pane can be resized 
4073             //if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) 
4076             // a dock may not be resized if it has a single 
4077             // pane which is not resizable 
4078             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
4079                 part
->dock
->panes
.GetCount() == 1 && 
4080                 part
->dock
->panes
.Item(0)->IsFixed()) 
4083             // panes that may not be resized should be ignored here 
4084             if (part
->pane 
&& part
->pane
->IsFixed()) 
4087             m_action 
= actionResize
; 
4088             m_actionPart 
= part
; 
4089             m_actionHintRect 
= wxRect(); 
4090             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4091             m_actionOffset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
4092                                       event
.m_y 
- part
->rect
.y
); 
4093             m_frame
->CaptureMouse(); 
4095         else if (part
->type 
== wxAuiDockUIPart::typePaneButton
) 
4097             m_action 
= actionClickButton
; 
4098             m_actionPart 
= part
; 
4099             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4100             m_frame
->CaptureMouse(); 
4102             UpdateButtonOnScreen(part
, event
); 
4104         else if (part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
4105                   part
->type 
== wxAuiDockUIPart::typeGripper
) 
4107             // if we are managing a wxAuiFloatingFrame window, then 
4108             // we are an embedded wxAuiManager inside the wxAuiFloatingFrame. 
4109             // We want to initiate a toolbar drag in our owner manager 
4110             wxWindow
* managed_wnd 
= GetManagedWindow(); 
4113                 part
->pane
->window 
&& 
4115                 managed_wnd
->IsKindOf(CLASSINFO(wxAuiFloatingFrame
))) 
4117                 wxAuiFloatingFrame
* floating_frame 
= (wxAuiFloatingFrame
*)managed_wnd
; 
4118                 wxAuiManager
* owner_mgr 
= floating_frame
->GetOwnerManager(); 
4119                 owner_mgr
->StartPaneDrag(part
->pane
->window
, 
4120                                              wxPoint(event
.m_x 
- part
->rect
.x
, 
4121                                                      event
.m_y 
- part
->rect
.y
)); 
4127             if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4129                 // set the caption as active 
4130                 SetActivePane(m_panes
, part
->pane
->window
); 
4134             if (part
->dock 
&& part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER
) 
4137             m_action 
= actionClickCaption
; 
4138             m_actionPart 
= part
; 
4139             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4140             m_actionOffset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
4141                                       event
.m_y 
- part
->rect
.y
); 
4142             m_frame
->CaptureMouse(); 
4161 /// Ends a resize action, or for live update, resizes the sash 
4162 bool wxAuiManager::DoEndResizeAction(wxMouseEvent
& event
) 
4164     // resize the dock or the pane 
4165     if (m_actionPart 
&& m_actionPart
->type
==wxAuiDockUIPart::typeDockSizer
) 
4167         // first, we must calculate the maximum size the dock may be 
4168         int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
4170         int used_width 
= 0, used_height 
= 0; 
4172         wxSize client_size 
= m_frame
->GetClientSize(); 
4174         size_t dock_i
, dock_count 
= m_docks
.GetCount(); 
4175         for (dock_i 
= 0; dock_i 
< dock_count
; ++dock_i
) 
4177             wxAuiDockInfo
& dock 
= m_docks
.Item(dock_i
); 
4178             if (dock
.dock_direction 
== wxAUI_DOCK_TOP 
|| 
4179                 dock
.dock_direction 
== wxAUI_DOCK_BOTTOM
) 
4181                 used_height 
+= dock
.size
; 
4183             if (dock
.dock_direction 
== wxAUI_DOCK_LEFT 
|| 
4184                 dock
.dock_direction 
== wxAUI_DOCK_RIGHT
) 
4186                 used_width 
+= dock
.size
; 
4189                 used_width 
+= sashSize
; 
4193         int available_width 
= client_size
.GetWidth() - used_width
; 
4194         int available_height 
= client_size
.GetHeight() - used_height
; 
4198         // if there's a status control, the available 
4199         // height decreases accordingly 
4200         if (m_frame 
&& m_frame
->IsKindOf(CLASSINFO(wxFrame
))) 
4202             wxFrame
* frame 
= static_cast<wxFrame
*>(m_frame
); 
4203             wxStatusBar
* status 
= frame
->GetStatusBar(); 
4206                 wxSize status_client_size 
= status
->GetClientSize(); 
4207                 available_height 
-= status_client_size
.GetHeight(); 
4212         wxRect
& rect 
= m_actionPart
->dock
->rect
; 
4214         wxPoint 
new_pos(event
.m_x 
- m_actionOffset
.x
, 
4215             event
.m_y 
- m_actionOffset
.y
); 
4216         int new_size
, old_size 
= m_actionPart
->dock
->size
; 
4218         switch (m_actionPart
->dock
->dock_direction
) 
4220         case wxAUI_DOCK_LEFT
: 
4221             new_size 
= new_pos
.x 
- rect
.x
; 
4222             if (new_size
-old_size 
> available_width
) 
4223                 new_size 
= old_size
+available_width
; 
4224             m_actionPart
->dock
->size 
= new_size
; 
4226         case wxAUI_DOCK_TOP
: 
4227             new_size 
= new_pos
.y 
- rect
.y
; 
4228             if (new_size
-old_size 
> available_height
) 
4229                 new_size 
= old_size
+available_height
; 
4230             m_actionPart
->dock
->size 
= new_size
; 
4232         case wxAUI_DOCK_RIGHT
: 
4233             new_size 
= rect
.x 
+ rect
.width 
- new_pos
.x 
- 
4234                        m_actionPart
->rect
.GetWidth(); 
4235             if (new_size
-old_size 
> available_width
) 
4236                 new_size 
= old_size
+available_width
; 
4237             m_actionPart
->dock
->size 
= new_size
; 
4239         case wxAUI_DOCK_BOTTOM
: 
4240             new_size 
= rect
.y 
+ rect
.height 
- 
4241                 new_pos
.y 
- m_actionPart
->rect
.GetHeight(); 
4242             if (new_size
-old_size 
> available_height
) 
4243                 new_size 
= old_size
+available_height
; 
4244             m_actionPart
->dock
->size 
= new_size
; 
4251     else if (m_actionPart 
&& 
4252         m_actionPart
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4254         wxAuiDockInfo
& dock 
= *m_actionPart
->dock
; 
4255         wxAuiPaneInfo
& pane 
= *m_actionPart
->pane
; 
4257         int total_proportion 
= 0; 
4258         int dock_pixels 
= 0; 
4259         int new_pixsize 
= 0; 
4261         int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
4262         int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
4263         int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
4265         wxPoint 
new_pos(event
.m_x 
- m_actionOffset
.x
, 
4266             event
.m_y 
- m_actionOffset
.y
); 
4268         // determine the pane rectangle by getting the pane part 
4269         wxAuiDockUIPart
* pane_part 
= GetPanePart(pane
.window
); 
4270         wxASSERT_MSG(pane_part
, 
4271             wxT("Pane border part not found -- shouldn't happen")); 
4273         // determine the new pixel size that the user wants; 
4274         // this will help us recalculate the pane's proportion 
4275         if (dock
.IsHorizontal()) 
4276             new_pixsize 
= new_pos
.x 
- pane_part
->rect
.x
; 
4278             new_pixsize 
= new_pos
.y 
- pane_part
->rect
.y
; 
4280         // determine the size of the dock, based on orientation 
4281         if (dock
.IsHorizontal()) 
4282             dock_pixels 
= dock
.rect
.GetWidth(); 
4284             dock_pixels 
= dock
.rect
.GetHeight(); 
4286         // determine the total proportion of all resizable panes, 
4287         // and the total size of the dock minus the size of all 
4289         int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4290         int pane_position 
= -1; 
4291         for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4293             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4294             if (p
.window 
== pane
.window
) 
4297             // while we're at it, subtract the pane sash 
4298             // width from the dock width, because this would 
4299             // skew our proportion calculations 
4301                 dock_pixels 
-= sashSize
; 
4303             // also, the whole size (including decorations) of 
4304             // all fixed panes must also be subtracted, because they 
4305             // are not part of the proportion calculation 
4308                 if (dock
.IsHorizontal()) 
4309                     dock_pixels 
-= p
.best_size
.x
; 
4311                     dock_pixels 
-= p
.best_size
.y
; 
4315                 total_proportion 
+= p
.dock_proportion
; 
4319         // new size can never be more than the number of dock pixels 
4320         if (new_pixsize 
> dock_pixels
) 
4321             new_pixsize 
= dock_pixels
; 
4324         // find a pane in our dock to 'steal' space from or to 'give' 
4325         // space to -- this is essentially what is done when a pane is 
4326         // resized; the pane should usually be the first non-fixed pane 
4327         // to the right of the action pane 
4328         int borrow_pane 
= -1; 
4329         for (i 
= pane_position
+1; i 
< dock_pane_count
; ++i
) 
4331             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4340         // demand that the pane being resized is found in this dock 
4341         // (this assert really never should be raised) 
4342         wxASSERT_MSG(pane_position 
!= -1, wxT("Pane not found in dock")); 
4344         // prevent division by zero 
4345         if (dock_pixels 
== 0 || total_proportion 
== 0 || borrow_pane 
== -1) 
4347             m_action 
= actionNone
; 
4351         // calculate the new proportion of the pane 
4352         int new_proportion 
= (new_pixsize
*total_proportion
)/dock_pixels
; 
4354         // default minimum size 
4357         // check against the pane's minimum size, if specified. please note 
4358         // that this is not enough to ensure that the minimum size will 
4359         // not be violated, because the whole frame might later be shrunk, 
4360         // causing the size of the pane to violate it's minimum size 
4361         if (pane
.min_size
.IsFullySpecified()) 
4365             if (pane
.HasBorder()) 
4366                 min_size 
+= (pane_borderSize
*2); 
4368             // calculate minimum size with decorations (border,caption) 
4369             if (pane_part
->orientation 
== wxVERTICAL
) 
4371                 min_size 
+= pane
.min_size
.y
; 
4372                 if (pane
.HasCaption()) 
4373                     min_size 
+= caption_size
; 
4377                 min_size 
+= pane
.min_size
.x
; 
4382         // for some reason, an arithmatic error somewhere is causing 
4383         // the proportion calculations to always be off by 1 pixel; 
4384         // for now we will add the 1 pixel on, but we really should 
4385         // determine what's causing this. 
4388         int min_proportion 
= (min_size
*total_proportion
)/dock_pixels
; 
4390         if (new_proportion 
< min_proportion
) 
4391             new_proportion 
= min_proportion
; 
4395         int prop_diff 
= new_proportion 
- pane
.dock_proportion
; 
4397         // borrow the space from our neighbor pane to the 
4398         // right or bottom (depending on orientation); 
4399         // also make sure we don't make the neighbor too small 
4400         int prop_borrow 
= dock
.panes
.Item(borrow_pane
)->dock_proportion
; 
4402         if (prop_borrow 
- prop_diff 
< 0) 
4404             // borrowing from other pane would make it too small, 
4405             // so cancel the resize operation 
4406             prop_borrow 
= min_proportion
; 
4410             prop_borrow 
-= prop_diff
; 
4414         dock
.panes
.Item(borrow_pane
)->dock_proportion 
= prop_borrow
; 
4415         pane
.dock_proportion 
= new_proportion
; 
4426 void wxAuiManager::OnLeftUp(wxMouseEvent
& event
) 
4428     if (m_action 
== actionResize
) 
4430         m_frame
->ReleaseMouse(); 
4432         if (!wxAuiManager_HasLiveResize(*this)) 
4434             // get rid of the hint rectangle 
4436             DrawResizeHint(dc
, m_actionHintRect
); 
4438         if (m_currentDragItem 
!= -1 && wxAuiManager_HasLiveResize(*this)) 
4439             m_actionPart 
= & (m_uiParts
.Item(m_currentDragItem
)); 
4441         DoEndResizeAction(event
); 
4443         m_currentDragItem 
= -1; 
4446     else if (m_action 
== actionClickButton
) 
4448         m_hoverButton 
= NULL
; 
4449         m_frame
->ReleaseMouse(); 
4453             UpdateButtonOnScreen(m_actionPart
, event
); 
4455             // make sure we're still over the item that was originally clicked 
4456             if (m_actionPart 
== HitTest(event
.GetX(), event
.GetY())) 
4458                 // fire button-click event 
4459                 wxAuiManagerEvent 
e(wxEVT_AUI_PANE_BUTTON
); 
4461                 e
.SetPane(m_actionPart
->pane
); 
4462                 e
.SetButton(m_actionPart
->button
->button_id
); 
4467     else if (m_action 
== actionClickCaption
) 
4469         m_frame
->ReleaseMouse(); 
4471     else if (m_action 
== actionDragFloatingPane
) 
4473         m_frame
->ReleaseMouse(); 
4475     else if (m_action 
== actionDragToolbarPane
) 
4477         m_frame
->ReleaseMouse(); 
4479         wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4480         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4482         // save the new positions 
4483         wxAuiDockInfoPtrArray docks
; 
4484         FindDocks(m_docks
, pane
.dock_direction
, 
4485                   pane
.dock_layer
, pane
.dock_row
, docks
); 
4486         if (docks
.GetCount() == 1) 
4488             wxAuiDockInfo
& dock 
= *docks
.Item(0); 
4490             wxArrayInt pane_positions
, pane_sizes
; 
4491             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
4493             int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4494             for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4495                 dock
.panes
.Item(i
)->dock_pos 
= pane_positions
[i
]; 
4498         pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4506     m_action 
= actionNone
; 
4507     m_lastMouseMove 
= wxPoint(); // see comment in OnMotion() 
4511 void wxAuiManager::OnMotion(wxMouseEvent
& event
) 
4513     // sometimes when Update() is called from inside this method, 
4514     // a spurious mouse move event is generated; this check will make 
4515     // sure that only real mouse moves will get anywhere in this method; 
4516     // this appears to be a bug somewhere, and I don't know where the 
4517     // mouse move event is being generated.  only verified on MSW 
4519     wxPoint mouse_pos 
= event
.GetPosition(); 
4520     if (m_lastMouseMove 
== mouse_pos
) 
4522     m_lastMouseMove 
= mouse_pos
; 
4525     if (m_action 
== actionResize
) 
4527         // It's necessary to reset m_actionPart since it destroyed 
4528         // by the Update within DoEndResizeAction. 
4529         if (m_currentDragItem 
!= -1) 
4530             m_actionPart 
= & (m_uiParts
.Item(m_currentDragItem
)); 
4532             m_currentDragItem 
= m_uiParts
.Index(* m_actionPart
); 
4536             wxPoint pos 
= m_actionPart
->rect
.GetPosition(); 
4537             if (m_actionPart
->orientation 
== wxHORIZONTAL
) 
4538                 pos
.y 
= wxMax(0, event
.m_y 
- m_actionOffset
.y
); 
4540                 pos
.x 
= wxMax(0, event
.m_x 
- m_actionOffset
.x
); 
4542             if (wxAuiManager_HasLiveResize(*this)) 
4544                 m_frame
->ReleaseMouse(); 
4545                 DoEndResizeAction(event
); 
4546                 m_frame
->CaptureMouse(); 
4550                 wxRect 
rect(m_frame
->ClientToScreen(pos
), 
4551                     m_actionPart
->rect
.GetSize()); 
4554                 if (!m_actionHintRect
.IsEmpty()) 
4556                     // remove old resize hint 
4557                     DrawResizeHint(dc
, m_actionHintRect
); 
4558                     m_actionHintRect 
= wxRect(); 
4561                 // draw new resize hint, if it's inside the managed frame 
4562                 wxRect frameScreenRect 
= m_frame
->GetScreenRect(); 
4563                 if (frameScreenRect
.Contains(rect
)) 
4565                     DrawResizeHint(dc
, rect
); 
4566                     m_actionHintRect 
= rect
; 
4571     else if (m_action 
== actionClickCaption
) 
4573         int drag_x_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
); 
4574         int drag_y_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
); 
4576         // caption has been clicked.  we need to check if the mouse 
4577         // is now being dragged. if it is, we need to change the 
4578         // mouse action to 'drag' 
4580             (abs(event
.m_x 
- m_actionStart
.x
) > drag_x_threshold 
|| 
4581              abs(event
.m_y 
- m_actionStart
.y
) > drag_y_threshold
)) 
4583             wxAuiPaneInfo
* paneInfo 
= m_actionPart
->pane
; 
4585             if (!paneInfo
->IsToolbar()) 
4587                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && 
4588                     paneInfo
->IsFloatable()) 
4590                     m_action 
= actionDragFloatingPane
; 
4592                     // set initial float position 
4593                     wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4594                     paneInfo
->floating_pos 
= wxPoint(pt
.x 
- m_actionOffset
.x
, 
4595                                                       pt
.y 
- m_actionOffset
.y
); 
4598                     if (paneInfo
->IsMaximized()) 
4599                         RestorePane(*paneInfo
); 
4603                     m_actionWindow 
= paneInfo
->frame
; 
4605                     // action offset is used here to make it feel "natural" to the user 
4606                     // to drag a docked pane and suddenly have it become a floating frame. 
4607                     // Sometimes, however, the offset where the user clicked on the docked 
4608                     // caption is bigger than the width of the floating frame itself, so 
4609                     // in that case we need to set the action offset to a sensible value 
4610                     wxSize frame_size 
= m_actionWindow
->GetSize(); 
4611                     if (frame_size
.x 
<= m_actionOffset
.x
) 
4612                         m_actionOffset
.x 
= 30; 
4617                 m_action 
= actionDragToolbarPane
; 
4618                 m_actionWindow 
= paneInfo
->window
; 
4622     else if (m_action 
== actionDragFloatingPane
) 
4626             // We can't move the child window so we need to get the frame that 
4627             // we want to be really moving. This is probably not the best place 
4628             // to do this but at least it fixes the bug (#13177) for now. 
4629             if (!m_actionWindow
->IsKindOf(CLASSINFO(wxAuiFloatingFrame
))) 
4631                 wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4632                 m_actionWindow 
= pane
.frame
; 
4635             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4636             m_actionWindow
->Move(pt
.x 
- m_actionOffset
.x
, 
4637                                 pt
.y 
- m_actionOffset
.y
); 
4640     else if (m_action 
== actionDragToolbarPane
) 
4642         wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4643         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4645         pane
.SetFlag(wxAuiPaneInfo::actionPane
, true); 
4647         wxPoint pt 
= event
.GetPosition(); 
4648         DoDrop(m_docks
, m_panes
, pane
, pt
, m_actionOffset
); 
4650         // if DoDrop() decided to float the pane, set up 
4651         // the floating pane's initial position 
4652         if (pane
.IsFloating()) 
4654             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4655             pane
.floating_pos 
= wxPoint(pt
.x 
- m_actionOffset
.x
, 
4656                                         pt
.y 
- m_actionOffset
.y
); 
4659         // this will do the actiual move operation; 
4660         // in the case that the pane has been floated, 
4661         // this call will create the floating pane 
4662         // and do the reparenting 
4665         // if the pane has been floated, change the mouse 
4666         // action actionDragFloatingPane so that subsequent 
4667         // EVT_MOTION() events will move the floating pane 
4668         if (pane
.IsFloating()) 
4670             pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4671             m_action 
= actionDragFloatingPane
; 
4672             m_actionWindow 
= pane
.frame
; 
4677         wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4678         if (part 
&& part
->type 
== wxAuiDockUIPart::typePaneButton
) 
4680             if (part 
!= m_hoverButton
) 
4682                 // make the old button normal 
4685                     UpdateButtonOnScreen(m_hoverButton
, event
); 
4689                 // mouse is over a button, so repaint the 
4690                 // button in hover mode 
4691                 UpdateButtonOnScreen(part
, event
); 
4692                 m_hoverButton 
= part
; 
4700                 m_hoverButton 
= NULL
; 
4711 void wxAuiManager::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
)) 
4715         m_hoverButton 
= NULL
; 
4720 void wxAuiManager::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
4722     // cancel the operation in progress, if any 
4723     if ( m_action 
!= actionNone 
) 
4725         m_action 
= actionNone
; 
4730 void wxAuiManager::OnChildFocus(wxChildFocusEvent
& event
) 
4732     // when a child pane has it's focus set, we should change the 
4733     // pane's active state to reflect this. (this is only true if 
4734     // active panes are allowed by the owner) 
4735     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4737         wxAuiPaneInfo
& pane 
= GetPane(event
.GetWindow()); 
4738         if (pane
.IsOk() && (pane
.state 
& wxAuiPaneInfo::optionActive
) == 0) 
4740             SetActivePane(m_panes
, event
.GetWindow()); 
4749 // OnPaneButton() is an event handler that is called 
4750 // when a pane button has been pressed. 
4751 void wxAuiManager::OnPaneButton(wxAuiManagerEvent
& evt
) 
4753     wxASSERT_MSG(evt
.pane
, wxT("Pane Info passed to wxAuiManager::OnPaneButton must be non-null")); 
4755     wxAuiPaneInfo
& pane 
= *(evt
.pane
); 
4757     if (evt
.button 
== wxAUI_BUTTON_CLOSE
) 
4759         // fire pane close event 
4760         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
4762         e
.SetPane(evt
.pane
); 
4767             // close the pane, but check that it 
4768             // still exists in our pane array first 
4769             // (the event handler above might have removed it) 
4771             wxAuiPaneInfo
& check 
= GetPane(pane
.window
); 
4780     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& !pane
.IsMaximized()) 
4782         // fire pane close event 
4783         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_MAXIMIZE
); 
4785         e
.SetPane(evt
.pane
); 
4794     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& pane
.IsMaximized()) 
4796         // fire pane close event 
4797         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_RESTORE
); 
4799         e
.SetPane(evt
.pane
); 
4808     else if (evt
.button 
== wxAUI_BUTTON_PIN
) 
4810         if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) &&