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_PANE_ACTIVATED
, wxAuiManagerEvent 
); 
  63 wxDEFINE_EVENT( wxEVT_AUI_RENDER
, wxAuiManagerEvent 
); 
  64 wxDEFINE_EVENT( wxEVT_AUI_FIND_MANAGER
, wxAuiManagerEvent 
); 
  67     // a few defines to avoid nameclashes 
  68     #define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1 
  70     #include "wx/osx/private.h" 
  74     #include "wx/msw/wrapwin.h" 
  75     #include "wx/msw/private.h" 
  76     #include "wx/msw/dc.h" 
  79 IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent
, wxEvent
) 
  80 IMPLEMENT_CLASS(wxAuiManager
, wxEvtHandler
) 
  84 const int auiToolBarLayer 
= 10; 
  89 class wxPseudoTransparentFrame 
: public wxFrame
 
  92     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
  93                 wxWindowID id 
= wxID_ANY
, 
  94                 const wxString
& title 
= wxEmptyString
, 
  95                 const wxPoint
& pos 
= wxDefaultPosition
, 
  96                 const wxSize
& size 
= wxDefaultSize
, 
  97                 long style 
= wxDEFAULT_FRAME_STYLE
, 
  98                 const wxString 
&name 
= wxT("frame")) 
  99                     : wxFrame(parent
, id
, title
, pos
, size
, style 
| wxFRAME_SHAPED
, name
) 
 101         SetBackgroundStyle(wxBG_STYLE_CUSTOM
); 
 108         m_canSetShape 
= false; // have to wait for window create event on GTK 
 110         m_canSetShape 
= true; 
 112         m_region 
= wxRegion(0, 0, 0, 0); 
 116     virtual bool SetTransparent(wxByte alpha
) 
 120             int w
=100; // some defaults 
 122             GetClientSize(&w
, &h
); 
 128 //            m_region.Union(0, 0, 1, m_maxWidth); 
 131                 for (int y
=0; y
<m_maxHeight
; y
++) 
 133                     // Reverse the order of the bottom 4 bits 
 134                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 135                     if ((j
*16+8)<m_amount
) 
 136                         m_region
.Union(0, y
, m_maxWidth
, 1); 
 145     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 149         if (m_region
.IsEmpty()) 
 153         dc
.SetBrush(wxColour(128, 192, 255)); 
 155         dc
.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 157         dc
.SetPen(*wxTRANSPARENT_PEN
); 
 159         wxRegionIterator 
upd(GetUpdateRegion()); // get the update rect list 
 163             wxRect 
rect(upd
.GetRect()); 
 164             dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 171     void OnWindowCreate(wxWindowCreateEvent
& WXUNUSED(event
)) 
 178     void OnSize(wxSizeEvent
& event
) 
 180         // We sometimes get surplus size events 
 181         if ((event
.GetSize().GetWidth() == m_lastWidth
) && 
 182             (event
.GetSize().GetHeight() == m_lastHeight
)) 
 187         m_lastWidth 
= event
.GetSize().GetWidth(); 
 188         m_lastHeight 
= event
.GetSize().GetHeight(); 
 190         SetTransparent(m_amount
); 
 191         m_region
.Intersect(0, 0, event
.GetSize().GetWidth(), 
 192                            event
.GetSize().GetHeight()); 
 203     int m_lastWidth
,m_lastHeight
; 
 207     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 208     DECLARE_EVENT_TABLE() 
 212 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 214 BEGIN_EVENT_TABLE(wxPseudoTransparentFrame
, wxFrame
) 
 215     EVT_PAINT(wxPseudoTransparentFrame::OnPaint
) 
 216     EVT_SIZE(wxPseudoTransparentFrame::OnSize
) 
 218     EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate
) 
 227 #include "wx/gtk/private/gtk2-compat.h" 
 230 gtk_pseudo_window_realized_callback( GtkWidget 
*m_widget
, void *WXUNUSED(win
) ) 
 232         wxSize disp 
= wxGetDisplaySize(); 
 235         for (int y
=0; y
<disp
.y
; y
++) 
 237                     // Reverse the order of the bottom 4 bits 
 238                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 240                         region
.Union(0, y
, disp
.x
, 1); 
 242         gdk_window_shape_combine_region(gtk_widget_get_window(m_widget
), region
.GetRegion(), 0, 0); 
 246 class wxPseudoTransparentFrame
: public wxFrame
 
 249     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
 250                 wxWindowID id 
= wxID_ANY
, 
 251                 const wxString
& title 
= wxEmptyString
, 
 252                 const wxPoint
& pos 
= wxDefaultPosition
, 
 253                 const wxSize
& size 
= wxDefaultSize
, 
 254                 long style 
= wxDEFAULT_FRAME_STYLE
, 
 255                 const wxString 
&name 
= wxT("frame")) 
 257          if (!CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 262         m_widget 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 263         g_object_ref(m_widget
); 
 265         if (parent
) parent
->AddChild(this); 
 267         g_signal_connect( m_widget
, "realize", 
 268                       G_CALLBACK (gtk_pseudo_window_realized_callback
), this ); 
 272         col
.green 
= 192 * 256; 
 273         col
.blue 
= 255 * 256; 
 274         gtk_widget_modify_bg( m_widget
, GTK_STATE_NORMAL
, &col 
); 
 277     bool SetTransparent(wxByte 
WXUNUSED(alpha
)) 
 283     virtual void DoSetSizeHints( int minW
, int minH
, 
 287         // the real wxFrame method doesn't work for us because we're not really 
 288         // a top level window so skip it 
 289         wxWindow::DoSetSizeHints(minW
, minH
, maxW
, maxH
, incW
, incH
); 
 293     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 296 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 303 // -- static utility functions -- 
 305 static wxBitmap 
wxPaneCreateStippleBitmap() 
 307     unsigned char data
[] = { 0,0,0,192,192,192, 192,192,192,0,0,0 }; 
 308     wxImage 
img(2,2,data
,true); 
 309     return wxBitmap(img
); 
 312 static void DrawResizeHint(wxDC
& dc
, const wxRect
& rect
) 
 314     wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
 315     wxBrush 
brush(stipple
); 
 318     wxMSWDCImpl 
*impl 
= (wxMSWDCImpl
*) dc
.GetImpl(); 
 319     PatBlt(GetHdcOf(*impl
), rect
.GetX(), rect
.GetY(), rect
.GetWidth(), rect
.GetHeight(), PATINVERT
); 
 321     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 323     dc
.SetLogicalFunction(wxXOR
); 
 324     dc
.DrawRectangle(rect
); 
 330 // CopyDocksAndPanes() - this utility function creates copies of 
 331 // the dock and pane info.  wxAuiDockInfo's usually contain pointers 
 332 // to wxAuiPaneInfo classes, thus this function is necessary to reliably 
 333 // reconstruct that relationship in the new dock info and pane info arrays 
 335 static void CopyDocksAndPanes(wxAuiDockInfoArray
& dest_docks
, 
 336                               wxAuiPaneInfoArray
& dest_panes
, 
 337                               const wxAuiDockInfoArray
& src_docks
, 
 338                               const wxAuiPaneInfoArray
& src_panes
) 
 340     dest_docks 
= src_docks
; 
 341     dest_panes 
= src_panes
; 
 342     int i
, j
, k
, dock_count
, pc1
, pc2
; 
 343     for (i 
= 0, dock_count 
= dest_docks
.GetCount(); i 
< dock_count
; ++i
) 
 345         wxAuiDockInfo
& dock 
= dest_docks
.Item(i
); 
 346         for (j 
= 0, pc1 
= dock
.panes
.GetCount(); j 
< pc1
; ++j
) 
 347             for (k 
= 0, pc2 
= src_panes
.GetCount(); k 
< pc2
; ++k
) 
 348                 if (dock
.panes
.Item(j
) == &src_panes
.Item(k
)) 
 349                     dock
.panes
.Item(j
) = &dest_panes
.Item(k
); 
 353 // GetMaxLayer() is an internal function which returns 
 354 // the highest layer inside the specified dock 
 355 static int GetMaxLayer(const wxAuiDockInfoArray
& docks
, 
 358     int i
, dock_count
, max_layer 
= 0; 
 359     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 361         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
 362         if (dock
.dock_direction 
== dock_direction 
&& 
 363             dock
.dock_layer 
> max_layer 
&& !dock
.fixed
) 
 364                 max_layer 
= dock
.dock_layer
; 
 370 // GetMaxRow() is an internal function which returns 
 371 // the highest layer inside the specified dock 
 372 static int GetMaxRow(const wxAuiPaneInfoArray
& panes
, int direction
, int layer
) 
 374     int i
, pane_count
, max_row 
= 0; 
 375     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 377         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 378         if (pane
.dock_direction 
== direction 
&& 
 379             pane
.dock_layer 
== layer 
&& 
 380             pane
.dock_row 
> max_row
) 
 381                 max_row 
= pane
.dock_row
; 
 388 // DoInsertDockLayer() is an internal function that inserts a new dock 
 389 // layer by incrementing all existing dock layer values by one 
 390 static void DoInsertDockLayer(wxAuiPaneInfoArray
& panes
, 
 395     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 397         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 398         if (!pane
.IsFloating() && 
 399             pane
.dock_direction 
== dock_direction 
&& 
 400             pane
.dock_layer 
>= dock_layer
) 
 405 // DoInsertDockLayer() is an internal function that inserts a new dock 
 406 // row by incrementing all existing dock row values by one 
 407 static void DoInsertDockRow(wxAuiPaneInfoArray
& panes
, 
 413     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 415         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 416         if (!pane
.IsFloating() && 
 417             pane
.dock_direction 
== dock_direction 
&& 
 418             pane
.dock_layer 
== dock_layer 
&& 
 419             pane
.dock_row 
>= dock_row
) 
 424 // DoInsertDockLayer() is an internal function that inserts a space for 
 425 // another dock pane by incrementing all existing dock row values by one 
 426 static void DoInsertPane(wxAuiPaneInfoArray
& panes
, 
 433     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 435         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 436         if (!pane
.IsFloating() && 
 437             pane
.dock_direction 
== dock_direction 
&& 
 438             pane
.dock_layer 
== dock_layer 
&& 
 439             pane
.dock_row 
== dock_row 
&& 
 440             pane
.dock_pos 
>= dock_pos
) 
 445 // FindDocks() is an internal function that returns a list of docks which meet 
 446 // the specified conditions in the parameters and returns a sorted array 
 447 // (sorted by layer and then row) 
 448 static void FindDocks(wxAuiDockInfoArray
& docks
, 
 452                       wxAuiDockInfoPtrArray
& arr
) 
 454     int begin_layer 
= dock_layer
; 
 455     int end_layer 
= dock_layer
; 
 456     int begin_row 
= dock_row
; 
 457     int end_row 
= dock_row
; 
 458     int dock_count 
= docks
.GetCount(); 
 459     int layer
, row
, i
, max_row 
= 0, max_layer 
= 0; 
 461     // discover the maximum dock layer and the max row 
 462     for (i 
= 0; i 
< dock_count
; ++i
) 
 464         max_row 
= wxMax(max_row
, docks
.Item(i
).dock_row
); 
 465         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
 468     // if no dock layer was specified, search all dock layers 
 469     if (dock_layer 
== -1) 
 472         end_layer 
= max_layer
; 
 475     // if no dock row was specified, search all dock row 
 484     for (layer 
= begin_layer
; layer 
<= end_layer
; ++layer
) 
 485         for (row 
= begin_row
; row 
<= end_row
; ++row
) 
 486             for (i 
= 0; i 
< dock_count
; ++i
) 
 488                 wxAuiDockInfo
& d 
= docks
.Item(i
); 
 489                 if (dock_direction 
== -1 || dock_direction 
== d
.dock_direction
) 
 491                     if (d
.dock_layer 
== layer 
&& d
.dock_row 
== row
) 
 497 // FindPaneInDock() looks up a specified window pointer inside a dock. 
 498 // If found, the corresponding wxAuiPaneInfo pointer is returned, otherwise NULL. 
 499 static wxAuiPaneInfo
* FindPaneInDock(const wxAuiDockInfo
& dock
, wxWindow
* window
) 
 501     int i
, count 
= dock
.panes
.GetCount(); 
 502     for (i 
= 0; i 
< count
; ++i
) 
 504         wxAuiPaneInfo
* p 
= dock
.panes
.Item(i
); 
 505         if (p
->window 
== window
) 
 511 // RemovePaneFromDocks() removes a pane window from all docks 
 512 // with a possible exception specified by parameter "ex_cept" 
 513 static void RemovePaneFromDocks(wxAuiDockInfoArray
& docks
, 
 515                                 wxAuiDockInfo
* ex_cept  
= NULL  
) 
 518     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 520         wxAuiDockInfo
& d 
= docks
.Item(i
); 
 523         wxAuiPaneInfo
* pi 
= FindPaneInDock(d
, pane
.window
); 
 530 // This function works fine, and may be used in the future 
 532 // RenumberDockRows() takes a dock and assigns sequential numbers 
 533 // to existing rows.  Basically it takes out the gaps; so if a 
 534 // dock has rows with numbers 0,2,5, they will become 0,1,2 
 535 static void RenumberDockRows(wxAuiDockInfoPtrArray& docks) 
 538     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) 
 540         wxAuiDockInfo& dock = *docks.Item(i); 
 544         for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j) 
 545             dock.panes.Item(j)->dock_row = i; 
 551 // SetActivePane() sets the active pane, as well as cycles through 
 552 // every other pane and makes sure that all others' active flags 
 554 void wxAuiManager::SetActivePane(wxWindow
* active_pane
) 
 557     wxAuiPaneInfo
* active_paneinfo 
= NULL
; 
 558     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 560         wxAuiPaneInfo
& pane 
= m_panes
.Item(i
); 
 561         pane
.state 
&= ~wxAuiPaneInfo::optionActive
; 
 562         if (pane
.window 
== active_pane
) 
 564             pane
.state 
|= wxAuiPaneInfo::optionActive
; 
 565             active_paneinfo 
= &pane
; 
 569     // send the 'activated' event after all panes have been updated 
 570     if ( active_paneinfo 
) 
 572         wxAuiManagerEvent 
evt(wxEVT_AUI_PANE_ACTIVATED
); 
 573         evt
.SetManager(this); 
 574         evt
.SetPane(active_paneinfo
); 
 575         ProcessMgrEvent(evt
); 
 580 // this function is used to sort panes by dock position 
 581 static int PaneSortFunc(wxAuiPaneInfo
** p1
, wxAuiPaneInfo
** p2
) 
 583     return ((*p1
)->dock_pos 
< (*p2
)->dock_pos
) ? -1 : 1; 
 587 bool wxAuiPaneInfo::IsValid() const 
 589     // Should this RTTI and function call be rewritten as 
 590     // sending a new event type to allow other window types 
 591     // to check the pane settings? 
 592     wxAuiToolBar
* toolbar 
= wxDynamicCast(window
, wxAuiToolBar
); 
 593     return !toolbar 
|| toolbar
->IsPaneValid(*this); 
 596 // -- wxAuiManager class implementation -- 
 599 BEGIN_EVENT_TABLE(wxAuiManager
, wxEvtHandler
) 
 600     EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton
) 
 601     EVT_AUI_RENDER(wxAuiManager::OnRender
) 
 602     EVT_PAINT(wxAuiManager::OnPaint
) 
 603     EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground
) 
 604     EVT_SIZE(wxAuiManager::OnSize
) 
 605     EVT_SET_CURSOR(wxAuiManager::OnSetCursor
) 
 606     EVT_LEFT_DOWN(wxAuiManager::OnLeftDown
) 
 607     EVT_LEFT_UP(wxAuiManager::OnLeftUp
) 
 608     EVT_MOTION(wxAuiManager::OnMotion
) 
 609     EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow
) 
 610     EVT_MOUSE_CAPTURE_LOST(wxAuiManager::OnCaptureLost
) 
 611     EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus
) 
 612     EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager
) 
 616 wxAuiManager::wxAuiManager(wxWindow
* managed_wnd
, unsigned int flags
) 
 618     m_action 
= actionNone
; 
 619     m_actionWindow 
= NULL
; 
 620     m_lastMouseMove 
= wxPoint(); 
 621     m_hoverButton 
= NULL
; 
 622     m_art 
= new wxAuiDefaultDockArt
; 
 626     m_hasMaximized 
= false; 
 628     m_dockConstraintX 
= 0.3; 
 629     m_dockConstraintY 
= 0.3; 
 631     m_currentDragItem 
= -1; 
 635         SetManagedWindow(managed_wnd
); 
 639 wxAuiManager::~wxAuiManager() 
 641     // NOTE: It's possible that the windows have already been destroyed by the 
 642     // time this dtor is called, so this loop can result in memory access via 
 643     // invalid pointers, resulting in a crash.  So it will be disabled while 
 644     // waiting for a better solution. 
 646     for ( size_t i 
= 0; i 
< m_panes
.size(); i
++ ) 
 648         wxAuiPaneInfo
& pinfo 
= m_panes
[i
]; 
 649         if (pinfo
.window 
&& !pinfo
.window
->GetParent()) 
 657 // creates a floating frame for the windows 
 658 wxAuiFloatingFrame
* wxAuiManager::CreateFloatingFrame(wxWindow
* parent
, 
 659                                                       const wxAuiPaneInfo
& paneInfo
) 
 661     return new wxAuiFloatingFrame(parent
, this, paneInfo
); 
 664 bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo 
& WXUNUSED(p
)) 
 666     // if a key modifier is pressed while dragging the frame, 
 667     // don't dock the window 
 668     return !(wxGetKeyState(WXK_CONTROL
) || wxGetKeyState(WXK_ALT
)); 
 671 // GetPane() looks up a wxAuiPaneInfo structure based 
 672 // on the supplied window pointer.  Upon failure, GetPane() 
 673 // returns an empty wxAuiPaneInfo, a condition which can be checked 
 674 // by calling wxAuiPaneInfo::IsOk(). 
 676 // The pane info's structure may then be modified.  Once a pane's 
 677 // info is modified, wxAuiManager::Update() must be called to 
 678 // realize the changes in the UI. 
 680 wxAuiPaneInfo
& wxAuiManager::GetPane(wxWindow
* window
) 
 683     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 685         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 686         if (p
.window 
== window
) 
 689     return wxAuiNullPaneInfo
; 
 692 // this version of GetPane() looks up a pane based on a 
 693 // 'pane name', see above comment for more info 
 694 wxAuiPaneInfo
& wxAuiManager::GetPane(const wxString
& name
) 
 697     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 699         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 703     return wxAuiNullPaneInfo
; 
 706 // GetAllPanes() returns a reference to all the pane info structures 
 707 wxAuiPaneInfoArray
& wxAuiManager::GetAllPanes() 
 712 // HitTest() is an internal function which determines 
 713 // which UI item the specified coordinates are over 
 714 // (x,y) specify a position in client coordinates 
 715 wxAuiDockUIPart
* wxAuiManager::HitTest(int x
, int y
) 
 717     wxAuiDockUIPart
* result 
= NULL
; 
 720     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
 722         wxAuiDockUIPart
* item 
= &m_uiParts
.Item(i
); 
 724         // we are not interested in typeDock, because this space 
 725         // isn't used to draw anything, just for measurements; 
 726         // besides, the entire dock area is covered with other 
 727         // rectangles, which we are interested in. 
 728         if (item
->type 
== wxAuiDockUIPart::typeDock
) 
 731         // if we already have a hit on a more specific item, we are not 
 732         // interested in a pane hit.  If, however, we don't already have 
 733         // a hit, returning a pane hit is necessary for some operations 
 734         if ((item
->type 
== wxAuiDockUIPart::typePane 
|| 
 735             item
->type 
== wxAuiDockUIPart::typePaneBorder
) && result
) 
 738         // if the point is inside the rectangle, we have a hit 
 739         if (item
->rect
.Contains(x
,y
)) 
 747 // SetFlags() and GetFlags() allow the owner to set various 
 748 // options which are global to wxAuiManager 
 749 void wxAuiManager::SetFlags(unsigned int flags
) 
 751     // find out if we have to call UpdateHintWindowConfig() 
 752     bool update_hint_wnd 
= false; 
 753     unsigned int hint_mask 
= wxAUI_MGR_TRANSPARENT_HINT 
| 
 754                              wxAUI_MGR_VENETIAN_BLINDS_HINT 
| 
 755                              wxAUI_MGR_RECTANGLE_HINT
; 
 756     if ((flags 
& hint_mask
) != (m_flags 
& hint_mask
)) 
 757         update_hint_wnd 
= true; 
 765         UpdateHintWindowConfig(); 
 769 unsigned int wxAuiManager::GetFlags() const 
 774 // Convenience function 
 775 bool wxAuiManager_HasLiveResize(wxAuiManager
& manager
) 
 777     // With Core Graphics on Mac, it's not possible to show sash feedback, 
 778     // so we'll always use live update instead. 
 779 #if defined(__WXMAC__) 
 780     wxUnusedVar(manager
); 
 783     return (manager
.GetFlags() & wxAUI_MGR_LIVE_RESIZE
) == wxAUI_MGR_LIVE_RESIZE
; 
 787 // don't use these anymore as they are deprecated 
 788 // use Set/GetManagedFrame() instead 
 789 void wxAuiManager::SetFrame(wxFrame
* frame
) 
 791     SetManagedWindow((wxWindow
*)frame
); 
 794 wxFrame
* wxAuiManager::GetFrame() const 
 796     return (wxFrame
*)m_frame
; 
 800 // this function will return the aui manager for a given 
 801 // window.  The |window| parameter should be any child window 
 802 // or grand-child window (and so on) of the frame/window 
 803 // managed by wxAuiManager.  The |window| parameter does not 
 804 // need to be managed by the manager itself. 
 805 wxAuiManager
* wxAuiManager::GetManager(wxWindow
* window
) 
 807     wxAuiManagerEvent 
evt(wxEVT_AUI_FIND_MANAGER
); 
 808     evt
.SetManager(NULL
); 
 809     evt
.ResumePropagation(wxEVENT_PROPAGATE_MAX
); 
 810     if (!window
->GetEventHandler()->ProcessEvent(evt
)) 
 813     return evt
.GetManager(); 
 817 void wxAuiManager::UpdateHintWindowConfig() 
 819     // find out if the system can do transparent frames 
 820     bool can_do_transparent 
= false; 
 822     wxWindow
* w 
= m_frame
; 
 825         if (wxDynamicCast(w
, wxFrame
)) 
 827             wxFrame
* f 
= static_cast<wxFrame
*>(w
); 
 828             can_do_transparent 
= f
->CanSetTransparent(); 
 836     // if there is an existing hint window, delete it 
 839         m_hintWnd
->Destroy(); 
 846     if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) && can_do_transparent
) 
 848         // Make a window to use for a transparent hint 
 849         #if defined(__WXMSW__) || defined(__WXGTK__) 
 850             m_hintWnd 
= new wxFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 851                                      wxDefaultPosition
, wxSize(1,1), 
 852                                          wxFRAME_TOOL_WINDOW 
| 
 853                                          wxFRAME_FLOAT_ON_PARENT 
| 
 857             m_hintWnd
->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 858         #elif defined(__WXMAC__) 
 859             // Using a miniframe with float and tool styles keeps the parent 
 860             // frame activated and highlighted as such... 
 861             m_hintWnd 
= new wxMiniFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 862                                          wxDefaultPosition
, wxSize(1,1), 
 863                                          wxFRAME_FLOAT_ON_PARENT
 
 864                                          | wxFRAME_TOOL_WINDOW 
); 
 865             m_hintWnd
->Connect(wxEVT_ACTIVATE
, 
 866                 wxActivateEventHandler(wxAuiManager::OnHintActivate
), NULL
, this); 
 868             // Can't set the bg colour of a Frame in wxMac 
 869             wxPanel
* p 
= new wxPanel(m_hintWnd
); 
 871             // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver 
 872             // color that is really hard to see, especially transparent. 
 873             // Until a better system color is decided upon we'll just use 
 875             p
->SetBackgroundColour(*wxBLUE
); 
 881         if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) != 0 || 
 882             (m_flags 
& wxAUI_MGR_VENETIAN_BLINDS_HINT
) != 0) 
 884             // system can't support transparent fade, or the venetian 
 885             // blinds effect was explicitly requested 
 886             m_hintWnd 
= new wxPseudoTransparentFrame(m_frame
, 
 891                                                             wxFRAME_TOOL_WINDOW 
| 
 892                                                             wxFRAME_FLOAT_ON_PARENT 
| 
 901 // SetManagedWindow() is usually called once when the frame 
 902 // manager class is being initialized.  "frame" specifies 
 903 // the frame which should be managed by the frame mananger 
 904 void wxAuiManager::SetManagedWindow(wxWindow
* wnd
) 
 906     wxASSERT_MSG(wnd
, wxT("specified window must be non-NULL")); 
 909     m_frame
->PushEventHandler(this); 
 912     // if the owner is going to manage an MDI parent frame, 
 913     // we need to add the MDI client window as the default 
 916     if (wxDynamicCast(m_frame
, wxMDIParentFrame
)) 
 918         wxMDIParentFrame
* mdi_frame 
= (wxMDIParentFrame
*)m_frame
; 
 919         wxWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 921         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 923         AddPane(client_window
, 
 924                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 925                 CenterPane().PaneBorder(false)); 
 927     else if (wxDynamicCast(m_frame
, wxAuiMDIParentFrame
)) 
 929         wxAuiMDIParentFrame
* mdi_frame 
= (wxAuiMDIParentFrame
*)m_frame
; 
 930         wxAuiMDIClientWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 931         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 933         AddPane(client_window
, 
 934                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 935                 CenterPane().PaneBorder(false)); 
 940     UpdateHintWindowConfig(); 
 944 // UnInit() must be called, usually in the destructor 
 945 // of the frame class.   If it is not called, usually this 
 946 // will result in a crash upon program exit 
 947 void wxAuiManager::UnInit() 
 951         m_frame
->RemoveEventHandler(this); 
 955 // GetManagedWindow() returns the window pointer being managed 
 956 wxWindow
* wxAuiManager::GetManagedWindow() const 
 961 wxAuiDockArt
* wxAuiManager::GetArtProvider() const 
 966 void wxAuiManager::ProcessMgrEvent(wxAuiManagerEvent
& event
) 
 968     // first, give the owner frame a chance to override 
 971         if (m_frame
->GetEventHandler()->ProcessEvent(event
)) 
 978 // SetArtProvider() instructs wxAuiManager to use the 
 979 // specified art provider for all drawing calls.  This allows 
 980 // plugable look-and-feel features.  The pointer that is 
 981 // passed to this method subsequently belongs to wxAuiManager, 
 982 // and is deleted in the frame manager destructor 
 983 void wxAuiManager::SetArtProvider(wxAuiDockArt
* art_provider
) 
 985     // delete the last art provider, if any 
 988     // assign the new art provider 
 989     m_art 
= art_provider
; 
 993 bool wxAuiManager::AddPane(wxWindow
* window
, const wxAuiPaneInfo
& paneInfo
) 
 995     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
 997     // check if the pane has a valid window 
1001     // check if the window is already managed by us 
1002     if (GetPane(paneInfo
.window
).IsOk()) 
1005     // check if the pane name already exists, this could reveal a 
1006     // bug in the library user's application 
1007     bool already_exists 
= false; 
1008     if (!paneInfo
.name
.empty() && GetPane(paneInfo
.name
).IsOk()) 
1010         wxFAIL_MSG(wxT("A pane with that name already exists in the manager!")); 
1011         already_exists 
= true; 
1014     // if the new pane is docked then we should undo maximize 
1015     if (paneInfo
.IsDocked()) 
1016         RestoreMaximizedPane(); 
1018     // special case:  wxAuiToolBar style interacts with docking flags 
1019     wxAuiPaneInfo 
test(paneInfo
); 
1020     wxAuiToolBar
* toolbar 
= wxDynamicCast(window
, wxAuiToolBar
); 
1023         // if pane has default docking flags 
1024         const unsigned int dockMask 
= wxAuiPaneInfo::optionLeftDockable 
| 
1025                                         wxAuiPaneInfo::optionRightDockable 
| 
1026                                         wxAuiPaneInfo::optionTopDockable 
| 
1027                                         wxAuiPaneInfo::optionBottomDockable
; 
1028         const unsigned int defaultDock 
= wxAuiPaneInfo(). 
1029                                             DefaultPane().state 
& dockMask
; 
1030         if ((test
.state 
& dockMask
) == defaultDock
) 
1032             // set docking flags based on toolbar style 
1033             if (toolbar
->GetWindowStyleFlag() & wxAUI_TB_VERTICAL
) 
1035                 test
.TopDockable(false).BottomDockable(false); 
1037             else if (toolbar
->GetWindowStyleFlag() & wxAUI_TB_HORIZONTAL
) 
1039                 test
.LeftDockable(false).RightDockable(false); 
1044             // see whether non-default docking flags are valid 
1045             test
.window 
= window
; 
1046             wxCHECK_MSG(test
.IsValid(), false, 
1047                         "toolbar style and pane docking flags are incompatible"); 
1053     wxAuiPaneInfo
& pinfo 
= m_panes
.Last(); 
1055     // set the pane window 
1056     pinfo
.window 
= window
; 
1059     // if the pane's name identifier is blank, create a random string 
1060     if (pinfo
.name
.empty() || already_exists
) 
1062         pinfo
.name
.Printf(wxT("%08lx%08x%08x%08lx"), 
1063              (unsigned long)(wxPtrToUInt(pinfo
.window
) & 0xffffffff), 
1064              (unsigned int)time(NULL
), 
1066              (unsigned int)GetTickCount(), 
1068              (unsigned int)clock(), 
1070              (unsigned long)m_panes
.GetCount()); 
1073     // set initial proportion (if not already set) 
1074     if (pinfo
.dock_proportion 
== 0) 
1075         pinfo
.dock_proportion 
= 100000; 
1077     if (pinfo
.HasMaximizeButton()) 
1079         wxAuiPaneButton button
; 
1080         button
.button_id 
= wxAUI_BUTTON_MAXIMIZE_RESTORE
; 
1081         pinfo
.buttons
.Add(button
); 
1084     if (pinfo
.HasPinButton()) 
1086         wxAuiPaneButton button
; 
1087         button
.button_id 
= wxAUI_BUTTON_PIN
; 
1088         pinfo
.buttons
.Add(button
); 
1091     if (pinfo
.HasCloseButton()) 
1093         wxAuiPaneButton button
; 
1094         button
.button_id 
= wxAUI_BUTTON_CLOSE
; 
1095         pinfo
.buttons
.Add(button
); 
1098     if (pinfo
.HasGripper()) 
1100         if (wxDynamicCast(pinfo
.window
, wxAuiToolBar
)) 
1102             // prevent duplicate gripper -- both wxAuiManager and wxAuiToolBar 
1103             // have a gripper control.  The toolbar's built-in gripper 
1104             // meshes better with the look and feel of the control than ours, 
1105             // so turn wxAuiManager's gripper off, and the toolbar's on. 
1107             wxAuiToolBar
* tb 
= static_cast<wxAuiToolBar
*>(pinfo
.window
); 
1108             pinfo
.SetFlag(wxAuiPaneInfo::optionGripper
, false); 
1109             tb
->SetGripperVisible(true); 
1114     if (pinfo
.best_size 
== wxDefaultSize 
&& 
1117         pinfo
.best_size 
= pinfo
.window
->GetClientSize(); 
1120         if (wxDynamicCast(pinfo
.window
, wxToolBar
)) 
1122             // GetClientSize() doesn't get the best size for 
1123             // a toolbar under some newer versions of wxWidgets, 
1124             // so use GetBestSize() 
1125             pinfo
.best_size 
= pinfo
.window
->GetBestSize(); 
1127 #endif // wxUSE_TOOLBAR 
1129         if (pinfo
.min_size 
!= wxDefaultSize
) 
1131             if (pinfo
.best_size
.x 
< pinfo
.min_size
.x
) 
1132                 pinfo
.best_size
.x 
= pinfo
.min_size
.x
; 
1133             if (pinfo
.best_size
.y 
< pinfo
.min_size
.y
) 
1134                 pinfo
.best_size
.y 
= pinfo
.min_size
.y
; 
1143 bool wxAuiManager::AddPane(wxWindow
* window
, 
1145                            const wxString
& caption
) 
1147     wxAuiPaneInfo pinfo
; 
1148     pinfo
.Caption(caption
); 
1151         case wxTOP
:    pinfo
.Top(); break; 
1152         case wxBOTTOM
: pinfo
.Bottom(); break; 
1153         case wxLEFT
:   pinfo
.Left(); break; 
1154         case wxRIGHT
:  pinfo
.Right(); break; 
1155         case wxCENTER
: pinfo
.CenterPane(); break; 
1157     return AddPane(window
, pinfo
); 
1160 bool wxAuiManager::AddPane(wxWindow
* window
, 
1161                            const wxAuiPaneInfo
& paneInfo
, 
1162                            const wxPoint
& drop_pos
) 
1164     if (!AddPane(window
, paneInfo
)) 
1167     wxAuiPaneInfo
& pane 
= GetPane(window
); 
1169     DoDrop(m_docks
, m_panes
, pane
, drop_pos
, wxPoint(0,0)); 
1174 bool wxAuiManager::InsertPane(wxWindow
* window
, const wxAuiPaneInfo
& paneInfo
, 
1177     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1179     // shift the panes around, depending on the insert level 
1180     switch (insert_level
) 
1182         case wxAUI_INSERT_PANE
: 
1183             DoInsertPane(m_panes
, 
1184                  paneInfo
.dock_direction
, 
1185                  paneInfo
.dock_layer
, 
1189         case wxAUI_INSERT_ROW
: 
1190             DoInsertDockRow(m_panes
, 
1191                  paneInfo
.dock_direction
, 
1192                  paneInfo
.dock_layer
, 
1195         case wxAUI_INSERT_DOCK
: 
1196             DoInsertDockLayer(m_panes
, 
1197                  paneInfo
.dock_direction
, 
1198                  paneInfo
.dock_layer
); 
1202     // if the window already exists, we are basically just moving/inserting the 
1203     // existing window.  If it doesn't exist, we need to add it and insert it 
1204     wxAuiPaneInfo
& existing_pane 
= GetPane(window
); 
1205     if (!existing_pane
.IsOk()) 
1207         return AddPane(window
, paneInfo
); 
1211         if (paneInfo
.IsFloating()) 
1213             existing_pane
.Float(); 
1214             if (paneInfo
.floating_pos 
!= wxDefaultPosition
) 
1215                 existing_pane
.FloatingPosition(paneInfo
.floating_pos
); 
1216             if (paneInfo
.floating_size 
!= wxDefaultSize
) 
1217                 existing_pane
.FloatingSize(paneInfo
.floating_size
); 
1221             // if the new pane is docked then we should undo maximize 
1222             RestoreMaximizedPane(); 
1224             existing_pane
.Direction(paneInfo
.dock_direction
); 
1225             existing_pane
.Layer(paneInfo
.dock_layer
); 
1226             existing_pane
.Row(paneInfo
.dock_row
); 
1227             existing_pane
.Position(paneInfo
.dock_pos
); 
1235 // DetachPane() removes a pane from the frame manager.  This 
1236 // method will not destroy the window that is removed. 
1237 bool wxAuiManager::DetachPane(wxWindow
* window
) 
1239     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1242     for (i 
= 0, count 
= m_panes
.GetCount(); i 
< count
; ++i
) 
1244         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1245         if (p
.window 
== window
) 
1249                 // we have a floating frame which is being detached. We need to 
1250                 // reparent it to m_frame and destroy the floating frame 
1253                 p
.window
->SetSize(1,1); 
1255                 if (p
.frame
->IsShown()) 
1256                     p
.frame
->Show(false); 
1258                 // reparent to m_frame and destroy the pane 
1259                 if (m_actionWindow 
== p
.frame
) 
1261                     m_actionWindow 
= NULL
; 
1264                 p
.window
->Reparent(m_frame
); 
1265                 p
.frame
->SetSizer(NULL
); 
1270             // make sure there are no references to this pane in our uiparts, 
1271             // just in case the caller doesn't call Update() immediately after 
1272             // the DetachPane() call.  This prevets obscure crashes which would 
1273             // happen at window repaint if the caller forgets to call Update() 
1275             for (pi 
= 0, part_count 
= (int)m_uiParts
.GetCount(); pi 
< part_count
; ++pi
) 
1277                 wxAuiDockUIPart
& part 
= m_uiParts
.Item(pi
); 
1278                 if (part
.pane 
== &p
) 
1280                     m_uiParts
.RemoveAt(pi
); 
1287             m_panes
.RemoveAt(i
); 
1294 // ClosePane() destroys or hides the pane depending on its flags 
1295 void wxAuiManager::ClosePane(wxAuiPaneInfo
& paneInfo
) 
1297     // if we were maximized, restore 
1298     if (paneInfo
.IsMaximized()) 
1300         RestorePane(paneInfo
); 
1303     // first, hide the window 
1304     if (paneInfo
.window 
&& paneInfo
.window
->IsShown()) 
1306         paneInfo
.window
->Show(false); 
1309     // make sure that we are the parent of this window 
1310     if (paneInfo
.window 
&& paneInfo
.window
->GetParent() != m_frame
) 
1312         paneInfo
.window
->Reparent(m_frame
); 
1315     // if we have a frame, destroy it 
1318         paneInfo
.frame
->Destroy(); 
1319         paneInfo
.frame 
= NULL
; 
1322     // now we need to either destroy or hide the pane 
1323     if (paneInfo
.IsDestroyOnClose()) 
1325         wxWindow 
* window 
= paneInfo
.window
; 
1338 void wxAuiManager::MaximizePane(wxAuiPaneInfo
& paneInfo
) 
1342     // un-maximize and hide all other panes 
1343     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1345         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1346         if (!p
.IsToolbar() && !p
.IsFloating()) 
1350             // save hidden state 
1351             p
.SetFlag(wxAuiPaneInfo::savedHiddenState
, 
1352                       p
.HasFlag(wxAuiPaneInfo::optionHidden
)); 
1354             // hide the pane, because only the newly 
1355             // maximized pane should show 
1360     // mark ourselves maximized 
1361     paneInfo
.Maximize(); 
1363     m_hasMaximized 
= true; 
1365     // last, show the window 
1366     if (paneInfo
.window 
&& !paneInfo
.window
->IsShown()) 
1368         paneInfo
.window
->Show(true); 
1372 void wxAuiManager::RestorePane(wxAuiPaneInfo
& paneInfo
) 
1376     // restore all the panes 
1377     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1379         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1380         if (!p
.IsToolbar() && !p
.IsFloating()) 
1382             p
.SetFlag(wxAuiPaneInfo::optionHidden
, 
1383                       p
.HasFlag(wxAuiPaneInfo::savedHiddenState
)); 
1387     // mark ourselves non-maximized 
1389     m_hasMaximized 
= false; 
1391     // last, show the window 
1392     if (paneInfo
.window 
&& !paneInfo
.window
->IsShown()) 
1394         paneInfo
.window
->Show(true); 
1398 void wxAuiManager::RestoreMaximizedPane() 
1402     // restore all the panes 
1403     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1405         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1406         if (p
.IsMaximized()) 
1414 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|" 
1415 // in the input string.  This is an internal functions which is 
1416 // used for saving perspectives 
1417 static wxString 
EscapeDelimiters(const wxString
& s
) 
1420     result
.Alloc(s
.length()); 
1421     const wxChar
* ch 
= s
.c_str(); 
1424         if (*ch 
== wxT(';') || *ch 
== wxT('|')) 
1425             result 
+= wxT('\\'); 
1432 wxString 
wxAuiManager::SavePaneInfo(wxAuiPaneInfo
& pane
) 
1434     wxString result 
= wxT("name="); 
1435     result 
+= EscapeDelimiters(pane
.name
); 
1438     result 
+= wxT("caption="); 
1439     result 
+= EscapeDelimiters(pane
.caption
); 
1442     result 
+= wxString::Format(wxT("state=%u;"), pane
.state
); 
1443     result 
+= wxString::Format(wxT("dir=%d;"), pane
.dock_direction
); 
1444     result 
+= wxString::Format(wxT("layer=%d;"), pane
.dock_layer
); 
1445     result 
+= wxString::Format(wxT("row=%d;"), pane
.dock_row
); 
1446     result 
+= wxString::Format(wxT("pos=%d;"), pane
.dock_pos
); 
1447     result 
+= wxString::Format(wxT("prop=%d;"), pane
.dock_proportion
); 
1448     result 
+= wxString::Format(wxT("bestw=%d;"), pane
.best_size
.x
); 
1449     result 
+= wxString::Format(wxT("besth=%d;"), pane
.best_size
.y
); 
1450     result 
+= wxString::Format(wxT("minw=%d;"), pane
.min_size
.x
); 
1451     result 
+= wxString::Format(wxT("minh=%d;"), pane
.min_size
.y
); 
1452     result 
+= wxString::Format(wxT("maxw=%d;"), pane
.max_size
.x
); 
1453     result 
+= wxString::Format(wxT("maxh=%d;"), pane
.max_size
.y
); 
1454     result 
+= wxString::Format(wxT("floatx=%d;"), pane
.floating_pos
.x
); 
1455     result 
+= wxString::Format(wxT("floaty=%d;"), pane
.floating_pos
.y
); 
1456     result 
+= wxString::Format(wxT("floatw=%d;"), pane
.floating_size
.x
); 
1457     result 
+= wxString::Format(wxT("floath=%d"), pane
.floating_size
.y
); 
1462 // Load a "pane" with the pane infor settings in pane_part 
1463 void wxAuiManager::LoadPaneInfo(wxString pane_part
, wxAuiPaneInfo 
&pane
) 
1465     // replace escaped characters so we can 
1466     // split up the string easily 
1467     pane_part
.Replace(wxT("\\|"), wxT("\a")); 
1468     pane_part
.Replace(wxT("\\;"), wxT("\b")); 
1472         wxString val_part 
= pane_part
.BeforeFirst(wxT(';')); 
1473         pane_part 
= pane_part
.AfterFirst(wxT(';')); 
1474         wxString val_name 
= val_part
.BeforeFirst(wxT('=')); 
1475         wxString value 
= val_part
.AfterFirst(wxT('=')); 
1476         val_name
.MakeLower(); 
1477         val_name
.Trim(true); 
1478         val_name
.Trim(false); 
1482         if (val_name
.empty()) 
1485         if (val_name 
== wxT("name")) 
1487         else if (val_name 
== wxT("caption")) 
1488             pane
.caption 
= value
; 
1489         else if (val_name 
== wxT("state")) 
1490             pane
.state 
= (unsigned int)wxAtoi(value
.c_str()); 
1491         else if (val_name 
== wxT("dir")) 
1492             pane
.dock_direction 
= wxAtoi(value
.c_str()); 
1493         else if (val_name 
== wxT("layer")) 
1494             pane
.dock_layer 
= wxAtoi(value
.c_str()); 
1495         else if (val_name 
== wxT("row")) 
1496             pane
.dock_row 
= wxAtoi(value
.c_str()); 
1497         else if (val_name 
== wxT("pos")) 
1498             pane
.dock_pos 
= wxAtoi(value
.c_str()); 
1499         else if (val_name 
== wxT("prop")) 
1500             pane
.dock_proportion 
= wxAtoi(value
.c_str()); 
1501         else if (val_name 
== wxT("bestw")) 
1502             pane
.best_size
.x 
= wxAtoi(value
.c_str()); 
1503         else if (val_name 
== wxT("besth")) 
1504             pane
.best_size
.y 
= wxAtoi(value
.c_str()); 
1505         else if (val_name 
== wxT("minw")) 
1506             pane
.min_size
.x 
= wxAtoi(value
.c_str()); 
1507         else if (val_name 
== wxT("minh")) 
1508             pane
.min_size
.y 
= wxAtoi(value
.c_str()); 
1509         else if (val_name 
== wxT("maxw")) 
1510             pane
.max_size
.x 
= wxAtoi(value
.c_str()); 
1511         else if (val_name 
== wxT("maxh")) 
1512             pane
.max_size
.y 
= wxAtoi(value
.c_str()); 
1513         else if (val_name 
== wxT("floatx")) 
1514             pane
.floating_pos
.x 
= wxAtoi(value
.c_str()); 
1515         else if (val_name 
== wxT("floaty")) 
1516             pane
.floating_pos
.y 
= wxAtoi(value
.c_str()); 
1517         else if (val_name 
== wxT("floatw")) 
1518             pane
.floating_size
.x 
= wxAtoi(value
.c_str()); 
1519         else if (val_name 
== wxT("floath")) 
1520             pane
.floating_size
.y 
= wxAtoi(value
.c_str()); 
1522             wxFAIL_MSG(wxT("Bad Perspective String")); 
1526     // replace escaped characters so we can 
1527     // split up the string easily 
1528     pane
.name
.Replace(wxT("\a"), wxT("|")); 
1529     pane
.name
.Replace(wxT("\b"), wxT(";")); 
1530     pane
.caption
.Replace(wxT("\a"), wxT("|")); 
1531     pane
.caption
.Replace(wxT("\b"), wxT(";")); 
1532     pane_part
.Replace(wxT("\a"), wxT("|")); 
1533     pane_part
.Replace(wxT("\b"), wxT(";")); 
1539 // SavePerspective() saves all pane information as a single string. 
1540 // This string may later be fed into LoadPerspective() to restore 
1541 // all pane settings.  This save and load mechanism allows an 
1542 // exact pane configuration to be saved and restored at a later time 
1544 wxString 
wxAuiManager::SavePerspective() 
1548     result 
= wxT("layout2|"); 
1550     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1551     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1553         wxAuiPaneInfo
& pane 
= m_panes
.Item(pane_i
); 
1554         result 
+= SavePaneInfo(pane
)+wxT("|"); 
1557     int dock_i
, dock_count 
= m_docks
.GetCount(); 
1558     for (dock_i 
= 0; dock_i 
< dock_count
; ++dock_i
) 
1560         wxAuiDockInfo
& dock 
= m_docks
.Item(dock_i
); 
1562         result 
+= wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"), 
1563                                    dock
.dock_direction
, dock
.dock_layer
, 
1564                                    dock
.dock_row
, dock
.size
); 
1570 // LoadPerspective() loads a layout which was saved with SavePerspective() 
1571 // If the "update" flag parameter is true, the GUI will immediately be updated 
1573 bool wxAuiManager::LoadPerspective(const wxString
& layout
, bool update
) 
1575     wxString input 
= layout
; 
1578     // check layout string version 
1579     //    'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 
1580     //    'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) 
1581     part 
= input
.BeforeFirst(wxT('|')); 
1582     input 
= input
.AfterFirst(wxT('|')); 
1585     if (part 
!= wxT("layout2")) 
1588     // Mark all panes currently managed as hidden. Also, dock all panes that are dockable. 
1589     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1590     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1592         wxAuiPaneInfo
& p 
= m_panes
.Item(pane_i
); 
1598     // clear out the dock array; this will be reconstructed 
1601     // replace escaped characters so we can 
1602     // split up the string easily 
1603     input
.Replace(wxT("\\|"), wxT("\a")); 
1604     input
.Replace(wxT("\\;"), wxT("\b")); 
1606     m_hasMaximized 
= false; 
1611         wxString pane_part 
= input
.BeforeFirst(wxT('|')); 
1612         input 
= input
.AfterFirst(wxT('|')); 
1613         pane_part
.Trim(true); 
1615         // if the string is empty, we're done parsing 
1616         if (pane_part
.empty()) 
1619         if (pane_part
.Left(9) == wxT("dock_size")) 
1621             wxString val_name 
= pane_part
.BeforeFirst(wxT('=')); 
1622             wxString value 
= pane_part
.AfterFirst(wxT('=')); 
1624             long dir
, layer
, row
, size
; 
1625             wxString piece 
= val_name
.AfterFirst(wxT('(')); 
1626             piece 
= piece
.BeforeLast(wxT(')')); 
1627             piece
.BeforeFirst(wxT(',')).ToLong(&dir
); 
1628             piece 
= piece
.AfterFirst(wxT(',')); 
1629             piece
.BeforeFirst(wxT(',')).ToLong(&layer
); 
1630             piece
.AfterFirst(wxT(',')).ToLong(&row
); 
1631             value
.ToLong(&size
); 
1634             dock
.dock_direction 
= dir
; 
1635             dock
.dock_layer 
= layer
; 
1636             dock
.dock_row 
= row
; 
1642         // Undo our escaping as LoadPaneInfo needs to take an unescaped 
1643         // name so it can be called by external callers 
1644         pane_part
.Replace(wxT("\a"), wxT("|")); 
1645         pane_part
.Replace(wxT("\b"), wxT(";")); 
1647         LoadPaneInfo(pane_part
, pane
); 
1649         if ( pane
.IsMaximized() ) 
1650             m_hasMaximized 
= true; 
1652         wxAuiPaneInfo
& p 
= GetPane(pane
.name
); 
1655             // the pane window couldn't be found 
1656             // in the existing layout -- skip it 
1669 void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo
& dock
, 
1670                                             wxArrayInt
& positions
, 
1673     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1674     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1675     int gripperSize 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1680     int offset
, action_pane 
= -1; 
1681     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1683     // find the pane marked as our action pane 
1684     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1686         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1688         if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
1690             wxASSERT_MSG(action_pane
==-1, wxT("Too many fixed action panes")); 
1691             action_pane 
= pane_i
; 
1695     // set up each panes default position, and 
1696     // determine the size (width or height, depending 
1697     // on the dock's orientation) of each pane 
1698     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1700         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1701         positions
.Add(pane
.dock_pos
); 
1704         if (pane
.HasBorder()) 
1705             size 
+= (pane_borderSize
*2); 
1707         if (dock
.IsHorizontal()) 
1709             if (pane
.HasGripper() && !pane
.HasGripperTop()) 
1710                 size 
+= gripperSize
; 
1711             size 
+= pane
.best_size
.x
; 
1715             if (pane
.HasGripper() && pane
.HasGripperTop()) 
1716                 size 
+= gripperSize
; 
1718             if (pane
.HasCaption()) 
1719                 size 
+= caption_size
; 
1720             size 
+= pane
.best_size
.y
; 
1726     // if there is no action pane, just return the default 
1727     // positions (as specified in pane.pane_pos) 
1728     if (action_pane 
== -1) 
1732     for (pane_i 
= action_pane
-1; pane_i 
>= 0; --pane_i
) 
1734         int amount 
= positions
[pane_i
+1] - (positions
[pane_i
] + sizes
[pane_i
]); 
1739             positions
[pane_i
] -= -amount
; 
1741         offset 
+= sizes
[pane_i
]; 
1744     // if the dock mode is fixed, make sure none of the panes 
1745     // overlap; we will bump panes that overlap 
1747     for (pane_i 
= action_pane
; pane_i 
< pane_count
; ++pane_i
) 
1749         int amount 
= positions
[pane_i
] - offset
; 
1753             positions
[pane_i
] += -amount
; 
1755         offset 
+= sizes
[pane_i
]; 
1760 void wxAuiManager::LayoutAddPane(wxSizer
* cont
, 
1761                                  wxAuiDockInfo
& dock
, 
1762                                  wxAuiPaneInfo
& pane
, 
1763                                  wxAuiDockUIPartArray
& uiparts
, 
1766     wxAuiDockUIPart part
; 
1767     wxSizerItem
* sizer_item
; 
1769     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1770     int gripperSize 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1771     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1772     int pane_button_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BUTTON_SIZE
); 
1774     // find out the orientation of the item (orientation for panes 
1775     // is the same as the dock's orientation) 
1777     if (dock
.IsHorizontal()) 
1778         orientation 
= wxHORIZONTAL
; 
1780         orientation 
= wxVERTICAL
; 
1782     // this variable will store the proportion 
1783     // value that the pane will receive 
1784     int pane_proportion 
= pane
.dock_proportion
; 
1786     wxBoxSizer
* horz_pane_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1787     wxBoxSizer
* vert_pane_sizer 
= new wxBoxSizer(wxVERTICAL
); 
1789     if (pane
.HasGripper()) 
1791         if (pane
.HasGripperTop()) 
1792             sizer_item 
= vert_pane_sizer 
->Add(1, gripperSize
, 0, wxEXPAND
); 
1794             sizer_item 
= horz_pane_sizer 
->Add(gripperSize
, 1, 0, wxEXPAND
); 
1796         part
.type 
= wxAuiDockUIPart::typeGripper
; 
1800         part
.orientation 
= orientation
; 
1801         part
.cont_sizer 
= horz_pane_sizer
; 
1802         part
.sizer_item 
= sizer_item
; 
1806     if (pane
.HasCaption()) 
1808         // create the caption sizer 
1809         wxBoxSizer
* caption_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1811         sizer_item 
= caption_sizer
->Add(1, caption_size
, 1, wxEXPAND
); 
1813         part
.type 
= wxAuiDockUIPart::typeCaption
; 
1817         part
.orientation 
= orientation
; 
1818         part
.cont_sizer 
= vert_pane_sizer
; 
1819         part
.sizer_item 
= sizer_item
; 
1820         int caption_part_idx 
= uiparts
.GetCount(); 
1823         // add pane buttons to the caption 
1824         int i
, button_count
; 
1825         for (i 
= 0, button_count 
= pane
.buttons
.GetCount(); 
1826              i 
< button_count
; ++i
) 
1828             wxAuiPaneButton
& button 
= pane
.buttons
.Item(i
); 
1830             sizer_item 
= caption_sizer
->Add(pane_button_size
, 
1834             part
.type 
= wxAuiDockUIPart::typePaneButton
; 
1837             part
.button 
= &button
; 
1838             part
.orientation 
= orientation
; 
1839             part
.cont_sizer 
= caption_sizer
; 
1840             part
.sizer_item 
= sizer_item
; 
1844         // if we have buttons, add a little space to the right 
1845         // of them to ease visual crowding 
1846         if (button_count 
>= 1) 
1848             caption_sizer
->Add(3,1); 
1851         // add the caption sizer 
1852         sizer_item 
= vert_pane_sizer
->Add(caption_sizer
, 0, wxEXPAND
); 
1854         uiparts
.Item(caption_part_idx
).sizer_item 
= sizer_item
; 
1857     // add the pane window itself 
1860         sizer_item 
= vert_pane_sizer
->Add(1, 1, 1, wxEXPAND
); 
1864         sizer_item 
= vert_pane_sizer
->Add(pane
.window
, 1, wxEXPAND
); 
1865         // Don't do this because it breaks the pane size in floating windows 
1866         // BIW: Right now commenting this out is causing problems with 
1867         // an mdi client window as the center pane. 
1868         vert_pane_sizer
->SetItemMinSize(pane
.window
, 1, 1); 
1871     part
.type 
= wxAuiDockUIPart::typePane
; 
1875     part
.orientation 
= orientation
; 
1876     part
.cont_sizer 
= vert_pane_sizer
; 
1877     part
.sizer_item 
= sizer_item
; 
1881     // determine if the pane should have a minimum size; if the pane is 
1882     // non-resizable (fixed) then we must set a minimum size. Alternatively, 
1883     // if the pane.min_size is set, we must use that value as well 
1885     wxSize min_size 
= pane
.min_size
; 
1888         if (min_size 
== wxDefaultSize
) 
1890             min_size 
= pane
.best_size
; 
1891             pane_proportion 
= 0; 
1895     if (min_size 
!= wxDefaultSize
) 
1897         vert_pane_sizer
->SetItemMinSize( 
1898                         vert_pane_sizer
->GetChildren().GetCount()-1, 
1899                         min_size
.x
, min_size
.y
); 
1903     // add the verticle sizer (caption, pane window) to the 
1904     // horizontal sizer (gripper, verticle sizer) 
1905     horz_pane_sizer
->Add(vert_pane_sizer
, 1, wxEXPAND
); 
1907     // finally, add the pane sizer to the dock sizer 
1909     if (pane
.HasBorder()) 
1911         // allowing space for the pane's border 
1912         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, 
1913                                wxEXPAND 
| wxALL
, pane_borderSize
); 
1915         part
.type 
= wxAuiDockUIPart::typePaneBorder
; 
1919         part
.orientation 
= orientation
; 
1920         part
.cont_sizer 
= cont
; 
1921         part
.sizer_item 
= sizer_item
; 
1926         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, wxEXPAND
); 
1930 void wxAuiManager::LayoutAddDock(wxSizer
* cont
, 
1931                                  wxAuiDockInfo
& dock
, 
1932                                  wxAuiDockUIPartArray
& uiparts
, 
1935     wxSizerItem
* sizer_item
; 
1936     wxAuiDockUIPart part
; 
1938     int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
1939     int orientation 
= dock
.IsHorizontal() ? wxHORIZONTAL 
: wxVERTICAL
; 
1941     // resizable bottom and right docks have a sash before them 
1942     if (!m_hasMaximized 
&& !dock
.fixed 
&& (dock
.dock_direction 
== wxAUI_DOCK_BOTTOM 
|| 
1943                         dock
.dock_direction 
== wxAUI_DOCK_RIGHT
)) 
1945         sizer_item 
= cont
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
1947         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
1948         part
.orientation 
= orientation
; 
1952         part
.cont_sizer 
= cont
; 
1953         part
.sizer_item 
= sizer_item
; 
1957     // create the sizer for the dock 
1958     wxSizer
* dock_sizer 
= new wxBoxSizer(orientation
); 
1960     // add each pane to the dock 
1961     bool has_maximized_pane 
= false; 
1962     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1966         wxArrayInt pane_positions
, pane_sizes
; 
1968         // figure out the real pane positions we will 
1969         // use, without modifying the each pane's pane_pos member 
1970         GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
1973         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1975             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1976             int pane_pos 
= pane_positions
.Item(pane_i
); 
1978             if (pane
.IsMaximized()) 
1979                 has_maximized_pane 
= true; 
1982             int amount 
= pane_pos 
- offset
; 
1985                 if (dock
.IsVertical()) 
1986                     sizer_item 
= dock_sizer
->Add(1, amount
, 0, wxEXPAND
); 
1988                     sizer_item 
= dock_sizer
->Add(amount
, 1, 0, wxEXPAND
); 
1990                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
1994                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
1995                 part
.cont_sizer 
= dock_sizer
; 
1996                 part
.sizer_item 
= sizer_item
; 
2002             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
2004             offset 
+= pane_sizes
.Item(pane_i
); 
2007         // at the end add a very small stretchable background area 
2008         sizer_item 
= dock_sizer
->Add(0,0, 1, wxEXPAND
); 
2010         part
.type 
= wxAuiDockUIPart::typeBackground
; 
2014         part
.orientation 
= orientation
; 
2015         part
.cont_sizer 
= dock_sizer
; 
2016         part
.sizer_item 
= sizer_item
; 
2021         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
2023             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
2025             if (pane
.IsMaximized()) 
2026                 has_maximized_pane 
= true; 
2028             // if this is not the first pane being added, 
2029             // we need to add a pane sizer 
2030             if (!m_hasMaximized 
&& pane_i 
> 0) 
2032                 sizer_item 
= dock_sizer
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
2034                 part
.type 
= wxAuiDockUIPart::typePaneSizer
; 
2036                 part
.pane 
= dock
.panes
.Item(pane_i
-1); 
2038                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
2039                 part
.cont_sizer 
= dock_sizer
; 
2040                 part
.sizer_item 
= sizer_item
; 
2044             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
2048     if (dock
.dock_direction 
== wxAUI_DOCK_CENTER 
|| has_maximized_pane
) 
2049         sizer_item 
= cont
->Add(dock_sizer
, 1, wxEXPAND
); 
2051         sizer_item 
= cont
->Add(dock_sizer
, 0, wxEXPAND
); 
2053     part
.type 
= wxAuiDockUIPart::typeDock
; 
2057     part
.orientation 
= orientation
; 
2058     part
.cont_sizer 
= cont
; 
2059     part
.sizer_item 
= sizer_item
; 
2062     if (dock
.IsHorizontal()) 
2063         cont
->SetItemMinSize(dock_sizer
, 0, dock
.size
); 
2065         cont
->SetItemMinSize(dock_sizer
, dock
.size
, 0); 
2067     //  top and left docks have a sash after them 
2068     if (!m_hasMaximized 
&& 
2070           (dock
.dock_direction 
== wxAUI_DOCK_TOP 
|| 
2071            dock
.dock_direction 
== wxAUI_DOCK_LEFT
)) 
2073         sizer_item 
= cont
->Add(sashSize
, sashSize
, 0, wxEXPAND
); 
2075         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
2079         part
.orientation 
= orientation
; 
2080         part
.cont_sizer 
= cont
; 
2081         part
.sizer_item 
= sizer_item
; 
2086 wxSizer
* wxAuiManager::LayoutAll(wxAuiPaneInfoArray
& panes
, 
2087                                  wxAuiDockInfoArray
& docks
, 
2088                                  wxAuiDockUIPartArray
& uiparts
, 
2091     wxBoxSizer
* container 
= new wxBoxSizer(wxVERTICAL
); 
2093     int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
2094     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
2095     wxSize cli_size 
= m_frame
->GetClientSize(); 
2096     int i
, dock_count
, pane_count
; 
2099     // empty all docks out 
2100     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2102         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2104         // empty out all panes, as they will be readded below 
2109             // always reset fixed docks' sizes, because 
2110             // the contained windows may have been resized 
2116     // iterate through all known panes, filing each 
2117     // of them into the appropriate dock. If the 
2118     // pane does not exist in the dock, add it 
2119     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
2121         wxAuiPaneInfo
& p 
= panes
.Item(i
); 
2123         // find any docks with the same dock direction, dock layer, and 
2124         // dock row as the pane we are working on 
2125         wxAuiDockInfo
* dock
; 
2126         wxAuiDockInfoPtrArray arr
; 
2127         FindDocks(docks
, p
.dock_direction
, p
.dock_layer
, p
.dock_row
, arr
); 
2129         if (arr
.GetCount() > 0) 
2131             // found the right dock 
2136             // dock was not found, so we need to create a new one 
2138             d
.dock_direction 
= p
.dock_direction
; 
2139             d
.dock_layer 
= p
.dock_layer
; 
2140             d
.dock_row 
= p
.dock_row
; 
2142             dock 
= &docks
.Last(); 
2146         if (p
.IsDocked() && p
.IsShown()) 
2148             // remove the pane from any existing docks except this one 
2149             RemovePaneFromDocks(docks
, p
, dock
); 
2151             // pane needs to be added to the dock, 
2152             // if it doesn't already exist 
2153             if (!FindPaneInDock(*dock
, p
.window
)) 
2154                 dock
->panes
.Add(&p
); 
2158             // remove the pane from any existing docks 
2159             RemovePaneFromDocks(docks
, p
); 
2164     // remove any empty docks 
2165     for (i 
= docks
.GetCount()-1; i 
>= 0; --i
) 
2167         if (docks
.Item(i
).panes
.GetCount() == 0) 
2171     // configure the docks further 
2172     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2174         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2175         int j
, dock_pane_count 
= dock
.panes
.GetCount(); 
2177         // sort the dock pane array by the pane's 
2178         // dock position (dock_pos), in ascending order 
2179         dock
.panes
.Sort(PaneSortFunc
); 
2181         // for newly created docks, set up their initial size 
2186             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2188                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2189                 wxSize pane_size 
= pane
.best_size
; 
2190                 if (pane_size 
== wxDefaultSize
) 
2191                     pane_size 
= pane
.min_size
; 
2192                 if (pane_size 
== wxDefaultSize
) 
2193                     pane_size 
= pane
.window
->GetSize(); 
2195                 if (dock
.IsHorizontal()) 
2196                     size 
= wxMax(pane_size
.y
, size
); 
2198                     size 
= wxMax(pane_size
.x
, size
); 
2201             // add space for the border (two times), but only 
2202             // if at least one pane inside the dock has a pane border 
2203             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2205                 if (dock
.panes
.Item(j
)->HasBorder()) 
2207                     size 
+= (pane_borderSize
*2); 
2212             // if pane is on the top or bottom, add the caption height, 
2213             // but only if at least one pane inside the dock has a caption 
2214             if (dock
.IsHorizontal()) 
2216                 for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2218                     if (dock
.panes
.Item(j
)->HasCaption()) 
2220                         size 
+= caption_size
; 
2227             // new dock's size may not be more than the dock constraint 
2228             // parameter specifies.  See SetDockSizeConstraint() 
2230             int max_dock_x_size 
= (int)(m_dockConstraintX 
* ((double)cli_size
.x
)); 
2231             int max_dock_y_size 
= (int)(m_dockConstraintY 
* ((double)cli_size
.y
)); 
2233             if (dock
.IsHorizontal()) 
2234                 size 
= wxMin(size
, max_dock_y_size
); 
2236                 size 
= wxMin(size
, max_dock_x_size
); 
2238             // absolute minimum size for a dock is 10 pixels 
2246         // determine the dock's minimum size 
2247         bool plus_border 
= false; 
2248         bool plus_caption 
= false; 
2249         int dock_min_size 
= 0; 
2250         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2252             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2253             if (pane
.min_size 
!= wxDefaultSize
) 
2255                 if (pane
.HasBorder()) 
2257                 if (pane
.HasCaption()) 
2258                     plus_caption 
= true; 
2259                 if (dock
.IsHorizontal()) 
2261                     if (pane
.min_size
.y 
> dock_min_size
) 
2262                         dock_min_size 
= pane
.min_size
.y
; 
2266                     if (pane
.min_size
.x 
> dock_min_size
) 
2267                         dock_min_size 
= pane
.min_size
.x
; 
2273             dock_min_size 
+= (pane_borderSize
*2); 
2274         if (plus_caption 
&& dock
.IsHorizontal()) 
2275             dock_min_size 
+= (caption_size
); 
2277         dock
.min_size 
= dock_min_size
; 
2280         // if the pane's current size is less than it's 
2281         // minimum, increase the dock's size to it's minimum 
2282         if (dock
.size 
< dock
.min_size
) 
2283             dock
.size 
= dock
.min_size
; 
2286         // determine the dock's mode (fixed or proportional); 
2287         // determine whether the dock has only toolbars 
2288         bool action_pane_marked 
= false; 
2290         dock
.toolbar 
= true; 
2291         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2293             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2294             if (!pane
.IsFixed()) 
2296             if (!pane
.IsToolbar()) 
2297                 dock
.toolbar 
= false; 
2298             if (pane
.HasFlag(wxAuiPaneInfo::optionDockFixed
)) 
2300             if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
2301                 action_pane_marked 
= true; 
2305         // if the dock mode is proportional and not fixed-pixel, 
2306         // reassign the dock_pos to the sequential 0, 1, 2, 3; 
2307         // e.g. remove gaps like 1, 2, 30, 500 
2310             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2312                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2317         // if the dock mode is fixed, and none of the panes 
2318         // are being moved right now, make sure the panes 
2319         // do not overlap each other.  If they do, we will 
2320         // adjust the positions of the panes 
2321         if (dock
.fixed 
&& !action_pane_marked
) 
2323             wxArrayInt pane_positions
, pane_sizes
; 
2324             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
2327             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2329                 wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(j
)); 
2330                 pane
.dock_pos 
= pane_positions
[j
]; 
2332                 int amount 
= pane
.dock_pos 
- offset
; 
2336                     pane
.dock_pos 
+= -amount
; 
2338                 offset 
+= pane_sizes
[j
]; 
2343     // discover the maximum dock layer 
2345     for (i 
= 0; i 
< dock_count
; ++i
) 
2346         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
2349     // clear out uiparts 
2352     // create a bunch of box sizers, 
2353     // from the innermost level outwards. 
2354     wxSizer
* cont 
= NULL
; 
2355     wxSizer
* middle 
= NULL
; 
2359     for (layer 
= 0; layer 
<= max_layer
; ++layer
) 
2361         wxAuiDockInfoPtrArray arr
; 
2363         // find any docks in this layer 
2364         FindDocks(docks
, -1, layer
, -1, arr
); 
2366         // if there aren't any, skip to the next layer 
2370         wxSizer
* old_cont 
= cont
; 
2372         // create a container which will hold this layer's 
2373         // docks (top, bottom, left, right) 
2374         cont 
= new wxBoxSizer(wxVERTICAL
); 
2377         // find any top docks in this layer 
2378         FindDocks(docks
, wxAUI_DOCK_TOP
, layer
, -1, arr
); 
2381             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2382                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2386         // fill out the middle layer (which consists 
2387         // of left docks, content area and right docks) 
2389         middle 
= new wxBoxSizer(wxHORIZONTAL
); 
2391         // find any left docks in this layer 
2392         FindDocks(docks
, wxAUI_DOCK_LEFT
, layer
, -1, arr
); 
2395             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2396                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2399         // add content dock (or previous layer's sizer 
2403             // find any center docks 
2404             FindDocks(docks
, wxAUI_DOCK_CENTER
, -1, -1, arr
); 
2407                 for (row 
= 0,row_count 
= arr
.GetCount(); row
<row_count
; ++row
) 
2408                    LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2410             else if (!m_hasMaximized
) 
2412                 // there are no center docks, add a background area 
2413                 wxSizerItem
* sizer_item 
= middle
->Add(1,1, 1, wxEXPAND
); 
2414                 wxAuiDockUIPart part
; 
2415                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
2419                 part
.cont_sizer 
= middle
; 
2420                 part
.sizer_item 
= sizer_item
; 
2426             middle
->Add(old_cont
, 1, wxEXPAND
); 
2429         // find any right docks in this layer 
2430         FindDocks(docks
, wxAUI_DOCK_RIGHT
, layer
, -1, arr
); 
2433             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2434                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2437         if (middle
->GetChildren().GetCount() > 0) 
2438             cont
->Add(middle
, 1, wxEXPAND
); 
2444         // find any bottom docks in this layer 
2445         FindDocks(docks
, wxAUI_DOCK_BOTTOM
, layer
, -1, arr
); 
2448             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2449                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2456         // no sizer available, because there are no docks, 
2457         // therefore we will create a simple background area 
2458         cont 
= new wxBoxSizer(wxVERTICAL
); 
2459         wxSizerItem
* sizer_item 
= cont
->Add(1,1, 1, wxEXPAND
); 
2460         wxAuiDockUIPart part
; 
2461         part
.type 
= wxAuiDockUIPart::typeBackground
; 
2465         part
.cont_sizer 
= middle
; 
2466         part
.sizer_item 
= sizer_item
; 
2470     container
->Add(cont
, 1, wxEXPAND
); 
2475 // SetDockSizeConstraint() allows the dock constraints to be set.  For example, 
2476 // specifying values of 0.5, 0.5 will mean that upon dock creation, a dock may 
2477 // not be larger than half of the window's size 
2479 void wxAuiManager::SetDockSizeConstraint(double width_pct
, double height_pct
) 
2481     m_dockConstraintX 
= wxMax(0.0, wxMin(1.0, width_pct
)); 
2482     m_dockConstraintY 
= wxMax(0.0, wxMin(1.0, height_pct
)); 
2485 void wxAuiManager::GetDockSizeConstraint(double* width_pct
, double* height_pct
) const 
2488         *width_pct 
= m_dockConstraintX
; 
2491         *height_pct 
= m_dockConstraintY
; 
2496 // Update() updates the layout.  Whenever changes are made to 
2497 // one or more panes, this function should be called.  It is the 
2498 // external entry point for running the layout engine. 
2500 void wxAuiManager::Update() 
2502     m_hoverButton 
= NULL
; 
2503     m_actionPart 
= NULL
; 
2506     int i
, pane_count 
= m_panes
.GetCount(); 
2509     // destroy floating panes which have been 
2510     // redocked or are becoming non-floating 
2511     for (i 
= 0; i 
< pane_count
; ++i
) 
2513         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2515         if (!p
.IsFloating() && p
.frame
) 
2517             // because the pane is no longer in a floating, we need to 
2518             // reparent it to m_frame and destroy the floating frame 
2521             p
.window
->SetSize(1,1); 
2524             // the following block is a workaround for bug #1531361 
2525             // (see wxWidgets sourceforge page).  On wxGTK (only), when 
2526             // a frame is shown/hidden, a move event unfortunately 
2527             // also gets fired.  Because we may be dragging around 
2528             // a pane, we need to cancel that action here to prevent 
2529             // a spurious crash. 
2530             if (m_actionWindow 
== p
.frame
) 
2532                 if (wxWindow::GetCapture() == m_frame
) 
2533                     m_frame
->ReleaseMouse(); 
2534                 m_action 
= actionNone
; 
2535                 m_actionWindow 
= NULL
; 
2539             if (p
.frame
->IsShown()) 
2540                 p
.frame
->Show(false); 
2542             // reparent to m_frame and destroy the pane 
2543             if (m_actionWindow 
== p
.frame
) 
2545                 m_actionWindow 
= NULL
; 
2548             p
.window
->Reparent(m_frame
); 
2549             p
.frame
->SetSizer(NULL
); 
2556     // delete old sizer first 
2557     m_frame
->SetSizer(NULL
); 
2559     // create a layout for all of the panes 
2560     sizer 
= LayoutAll(m_panes
, m_docks
, m_uiParts
, false); 
2562     // hide or show panes as necessary, 
2563     // and float panes as necessary 
2564     for (i 
= 0; i 
< pane_count
; ++i
) 
2566         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2570             if (p
.frame 
== NULL
) 
2572                 // we need to create a frame for this 
2573                 // pane, which has recently been floated 
2574                 wxAuiFloatingFrame
* frame 
= CreateFloatingFrame(m_frame
, p
); 
2576                 // on MSW and Mac, if the owner desires transparent dragging, and 
2577                 // the dragging is happening right now, then the floating 
2578                 // window should have this style by default 
2579                 if (m_action 
== actionDragFloatingPane 
&& 
2580                     (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
)) 
2581                         frame
->SetTransparent(150); 
2583                 frame
->SetPaneWindow(p
); 
2586                 if (p
.IsShown() && !frame
->IsShown()) 
2591                 // frame already exists, make sure it's position 
2592                 // and size reflect the information in wxAuiPaneInfo 
2593                 if ((p
.frame
->GetPosition() != p
.floating_pos
) || (p
.frame
->GetSize() != p
.floating_size
)) 
2595                     p
.frame
->SetSize(p
.floating_pos
.x
, p
.floating_pos
.y
, 
2596                                      p
.floating_size
.x
, p
.floating_size
.y
, 
2597                                      wxSIZE_USE_EXISTING
); 
2599                     p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, 
2600                                      wxDefaultCoord, wxDefaultCoord, 
2601                                      wxSIZE_USE_EXISTING); 
2602                     //p.frame->Move(p.floating_pos.x, p.floating_pos.y); 
2606                 // update whether the pane is resizable or not 
2607                 long style 
= p
.frame
->GetWindowStyleFlag(); 
2609                     style 
&= ~wxRESIZE_BORDER
; 
2611                     style 
|= wxRESIZE_BORDER
; 
2612                 p
.frame
->SetWindowStyleFlag(style
); 
2614                 if (p
.frame
->GetLabel() != p
.caption
) 
2615                     p
.frame
->SetLabel(p
.caption
); 
2617                 if (p
.frame
->IsShown() != p
.IsShown()) 
2618                     p
.frame
->Show(p
.IsShown()); 
2623             if (p
.window
->IsShown() != p
.IsShown()) 
2624                 p
.window
->Show(p
.IsShown()); 
2627         // if "active panes" are no longer allowed, clear 
2628         // any optionActive values from the pane states 
2629         if ((m_flags 
& wxAUI_MGR_ALLOW_ACTIVE_PANE
) == 0) 
2631             p
.state 
&= ~wxAuiPaneInfo::optionActive
; 
2636     // keep track of the old window rectangles so we can 
2637     // refresh those windows whose rect has changed 
2638     wxAuiRectArray old_pane_rects
; 
2639     for (i 
= 0; i 
< pane_count
; ++i
) 
2642         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2644         if (p
.window 
&& p
.IsShown() && p
.IsDocked()) 
2647         old_pane_rects
.Add(r
); 
2653     // apply the new sizer 
2654     m_frame
->SetSizer(sizer
); 
2655     m_frame
->SetAutoLayout(false); 
2660     // now that the frame layout is done, we need to check 
2661     // the new pane rectangles against the old rectangles that 
2662     // we saved a few lines above here.  If the rectangles have 
2663     // changed, the corresponding panes must also be updated 
2664     for (i 
= 0; i 
< pane_count
; ++i
) 
2666         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2667         if (p
.window 
&& p
.window
->IsShown() && p
.IsDocked()) 
2669             if (p
.rect 
!= old_pane_rects
[i
]) 
2671                 p
.window
->Refresh(); 
2680     // set frame's minimum size 
2683     // N.B. More work needs to be done on frame minimum sizes; 
2684     // this is some intresting code that imposes the minimum size, 
2685     // but we may want to include a more flexible mechanism or 
2686     // options for multiple minimum-size modes, e.g. strict or lax 
2687     wxSize min_size = sizer->GetMinSize(); 
2688     wxSize frame_size = m_frame->GetSize(); 
2689     wxSize client_size = m_frame->GetClientSize(); 
2691     wxSize minframe_size(min_size.x+frame_size.x-client_size.x, 
2692                          min_size.y+frame_size.y-client_size.y ); 
2694     m_frame->SetMinSize(minframe_size); 
2696     if (frame_size.x < minframe_size.x || 
2697         frame_size.y < minframe_size.y) 
2698             sizer->Fit(m_frame); 
2703 // DoFrameLayout() is an internal function which invokes wxSizer::Layout 
2704 // on the frame's main sizer, then measures all the various UI items 
2705 // and updates their internal rectangles.  This should always be called 
2706 // instead of calling m_frame->Layout() directly 
2708 void wxAuiManager::DoFrameLayout() 
2713     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2715         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2717         // get the rectangle of the UI part 
2718         // originally, this code looked like this: 
2719         //    part.rect = wxRect(part.sizer_item->GetPosition(), 
2720         //                       part.sizer_item->GetSize()); 
2721         // this worked quite well, with one exception: the mdi 
2722         // client window had a "deferred" size variable 
2723         // that returned the wrong size.  It looks like 
2724         // a bug in wx, because the former size of the window 
2725         // was being returned.  So, we will retrieve the part's 
2726         // rectangle via other means 
2729         part
.rect 
= part
.sizer_item
->GetRect(); 
2730         int flag 
= part
.sizer_item
->GetFlag(); 
2731         int border 
= part
.sizer_item
->GetBorder(); 
2734             part
.rect
.y 
-= border
; 
2735             part
.rect
.height 
+= border
; 
2739             part
.rect
.x 
-= border
; 
2740             part
.rect
.width 
+= border
; 
2742         if (flag 
& wxBOTTOM
) 
2743             part
.rect
.height 
+= border
; 
2745             part
.rect
.width 
+= border
; 
2748         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2749             part
.dock
->rect 
= part
.rect
; 
2750         if (part
.type 
== wxAuiDockUIPart::typePane
) 
2751             part
.pane
->rect 
= part
.rect
; 
2755 // GetPanePart() looks up the pane the pane border UI part (or the regular 
2756 // pane part if there is no border). This allows the caller to get the exact 
2757 // rectangle of the pane in question, including decorations like 
2758 // caption and border (if any). 
2760 wxAuiDockUIPart
* wxAuiManager::GetPanePart(wxWindow
* wnd
) 
2763     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2765         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2766         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
2767             part
.pane 
&& part
.pane
->window 
== wnd
) 
2770     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); i 
< part_count
; ++i
) 
2772         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
2773         if (part
.type 
== wxAuiDockUIPart::typePane 
&& 
2774             part
.pane 
&& part
.pane
->window 
== wnd
) 
2782 // GetDockPixelOffset() is an internal function which returns 
2783 // a dock's offset in pixels from the left side of the window 
2784 // (for horizontal docks) or from the top of the window (for 
2785 // vertical docks).  This value is necessary for calculating 
2786 // fixel-pane/toolbar offsets when they are dragged. 
2788 int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo
& test
) 
2790     // the only way to accurately calculate the dock's 
2791     // offset is to actually run a theoretical layout 
2793     int i
, part_count
, dock_count
; 
2794     wxAuiDockInfoArray docks
; 
2795     wxAuiPaneInfoArray panes
; 
2796     wxAuiDockUIPartArray uiparts
; 
2797     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
2800     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
2801     wxSize client_size 
= m_frame
->GetClientSize(); 
2802     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
2805     for (i 
= 0, part_count 
= uiparts
.GetCount(); i 
< part_count
; ++i
) 
2807         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
2808         part
.rect 
= wxRect(part
.sizer_item
->GetPosition(), 
2809                            part
.sizer_item
->GetSize()); 
2810         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2811             part
.dock
->rect 
= part
.rect
; 
2816     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2818         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2819         if (test
.dock_direction 
== dock
.dock_direction 
&& 
2820             test
.dock_layer
==dock
.dock_layer 
&& test
.dock_row
==dock
.dock_row
) 
2822             if (dock
.IsVertical()) 
2834 // ProcessDockResult() is a utility function used by DoDrop() - it checks 
2835 // if a dock operation is allowed, the new dock position is copied into 
2836 // the target info.  If the operation was allowed, the function returns true. 
2838 bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo
& target
, 
2839                                      const wxAuiPaneInfo
& new_pos
) 
2841     bool allowed 
= false; 
2842     switch (new_pos
.dock_direction
) 
2844         case wxAUI_DOCK_TOP
:    allowed 
= target
.IsTopDockable();    break; 
2845         case wxAUI_DOCK_BOTTOM
: allowed 
= target
.IsBottomDockable(); break; 
2846         case wxAUI_DOCK_LEFT
:   allowed 
= target
.IsLeftDockable();   break; 
2847         case wxAUI_DOCK_RIGHT
:  allowed 
= target
.IsRightDockable();  break; 
2853         // Should this RTTI and function call be rewritten as 
2854         // sending a new event type to allow other window types 
2855         // to vary size based on dock location? 
2856         wxAuiToolBar
* toolbar 
= wxDynamicCast(target
.window
, wxAuiToolBar
); 
2859             wxSize hintSize 
= toolbar
->GetHintSize(target
.dock_direction
); 
2860             if (target
.best_size 
!= hintSize
) 
2862                 target
.best_size 
= hintSize
; 
2863                 target
.floating_size 
= wxDefaultSize
; 
2872 // DoDrop() is an important function.  It basically takes a mouse position, 
2873 // and determines where the pane's new position would be.  If the pane is to be 
2874 // dropped, it performs the drop operation using the specified dock and pane 
2875 // arrays.  By specifying copied dock and pane arrays when calling, a "what-if" 
2876 // scenario can be performed, giving precise coordinates for drop hints. 
2877 // If, however, wxAuiManager:m_docks and wxAuiManager::m_panes are specified 
2878 // as parameters, the changes will be made to the main state arrays 
2880 const int auiInsertRowPixels 
= 10; 
2881 const int auiNewRowPixels 
= 40; 
2882 const int auiLayerInsertPixels 
= 40; 
2883 const int auiLayerInsertOffset 
= 5; 
2885 bool wxAuiManager::DoDrop(wxAuiDockInfoArray
& docks
, 
2886                           wxAuiPaneInfoArray
& panes
, 
2887                           wxAuiPaneInfo
& target
, 
2889                           const wxPoint
& offset
) 
2891     wxSize cli_size 
= m_frame
->GetClientSize(); 
2893     wxAuiPaneInfo drop 
= target
; 
2896     // The result should always be shown 
2900     // Check to see if the pane has been dragged outside of the window 
2901     // (or near to the outside of the window), if so, dock it along the edge 
2904     int layer_insert_offset 
= auiLayerInsertOffset
; 
2905     if (drop
.IsToolbar()) 
2906         layer_insert_offset 
= 0; 
2909     if (pt
.x 
< layer_insert_offset 
&& 
2910         pt
.x 
> layer_insert_offset
-auiLayerInsertPixels 
&& 
2914         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
2915                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
2916                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)) + 1; 
2918         if (drop
.IsToolbar()) 
2919             new_layer 
= auiToolBarLayer
; 
2924              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2925         return ProcessDockResult(target
, drop
); 
2927     else if (pt
.y 
< layer_insert_offset 
&& 
2928              pt
.y 
> layer_insert_offset
-auiLayerInsertPixels 
&& 
2932         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
2933                                 GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2934                                 GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2936         if (drop
.IsToolbar()) 
2937             new_layer 
= auiToolBarLayer
; 
2942              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2943         return ProcessDockResult(target
, drop
); 
2945     else if (pt
.x 
>= cli_size
.x 
- layer_insert_offset 
&& 
2946              pt
.x 
< cli_size
.x 
- layer_insert_offset 
+ auiLayerInsertPixels 
&& 
2950         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
2951                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
2952                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)) + 1; 
2954         if (drop
.IsToolbar()) 
2955             new_layer 
= auiToolBarLayer
; 
2957         drop
.Dock().Right(). 
2960              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2961         return ProcessDockResult(target
, drop
); 
2963     else if (pt
.y 
>= cli_size
.y 
- layer_insert_offset 
&& 
2964              pt
.y 
< cli_size
.y 
- layer_insert_offset 
+ auiLayerInsertPixels 
&& 
2968         int new_layer 
= wxMax( wxMax( GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
2969                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2970                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2972         if (drop
.IsToolbar()) 
2973             new_layer 
= auiToolBarLayer
; 
2975         drop
.Dock().Bottom(). 
2978              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2979         return ProcessDockResult(target
, drop
); 
2983     wxAuiDockUIPart
* part 
= HitTest(pt
.x
, pt
.y
); 
2986     if (drop
.IsToolbar()) 
2988         if (!part 
|| !part
->dock
) 
2991         // calculate the offset from where the dock begins 
2992         // to the point where the user dropped the pane 
2993         int dock_drop_offset 
= 0; 
2994         if (part
->dock
->IsHorizontal()) 
2995             dock_drop_offset 
= pt
.x 
- part
->dock
->rect
.x 
- offset
.x
; 
2997             dock_drop_offset 
= pt
.y 
- part
->dock
->rect
.y 
- offset
.y
; 
3000         // toolbars may only be moved in and to fixed-pane docks, 
3001         // otherwise we will try to float the pane.  Also, the pane 
3002         // should float if being dragged over center pane windows 
3003         if (!part
->dock
->fixed 
|| part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER 
|| 
3004             pt
.x 
>= cli_size
.x 
|| pt
.x 
<= 0 || pt
.y 
>= cli_size
.y 
|| pt
.y 
<= 0) 
3006             if (m_lastRect
.IsEmpty() || m_lastRect
.Contains(pt
.x
, pt
.y 
)) 
3012                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && drop
.IsFloatable()) 
3019                 return ProcessDockResult(target
, drop
); 
3022             drop
.Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
3024             return ProcessDockResult(target
, drop
); 
3029         m_lastRect 
= part
->dock
->rect
; 
3030         m_lastRect
.Inflate( 15, 15 ); 
3033              Direction(part
->dock
->dock_direction
). 
3034              Layer(part
->dock
->dock_layer
). 
3035              Row(part
->dock
->dock_row
). 
3036              Position(dock_drop_offset
); 
3039             ((pt
.y 
< part
->dock
->rect
.y 
+ 1) && part
->dock
->IsHorizontal()) || 
3040             ((pt
.x 
< part
->dock
->rect
.x 
+ 1) && part
->dock
->IsVertical()) 
3041             ) && part
->dock
->panes
.GetCount() > 1) 
3043             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
3044                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
3046                 int row 
= drop
.dock_row
; 
3047                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3048                                 part
->dock
->dock_layer
, 
3049                                 part
->dock
->dock_row
); 
3050                 drop
.dock_row 
= row
; 
3054                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3055                                 part
->dock
->dock_layer
, 
3056                                 part
->dock
->dock_row
+1); 
3057                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
3062             ((pt
.y 
> part
->dock
->rect
.y 
+ part
->dock
->rect
.height 
- 2 ) && part
->dock
->IsHorizontal()) || 
3063             ((pt
.x 
> part
->dock
->rect
.x 
+ part
->dock
->rect
.width 
- 2 ) && part
->dock
->IsVertical()) 
3064             ) && part
->dock
->panes
.GetCount() > 1) 
3066             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
3067                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
3069                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3070                                 part
->dock
->dock_layer
, 
3071                                 part
->dock
->dock_row
+1); 
3072                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
3076                 int row 
= drop
.dock_row
; 
3077                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3078                                 part
->dock
->dock_layer
, 
3079                                 part
->dock
->dock_row
); 
3080                 drop
.dock_row 
= row
; 
3084         return ProcessDockResult(target
, drop
); 
3093     if (part
->type 
== wxAuiDockUIPart::typePaneBorder 
|| 
3094         part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
3095         part
->type 
== wxAuiDockUIPart::typeGripper 
|| 
3096         part
->type 
== wxAuiDockUIPart::typePaneButton 
|| 
3097         part
->type 
== wxAuiDockUIPart::typePane 
|| 
3098         part
->type 
== wxAuiDockUIPart::typePaneSizer 
|| 
3099         part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
3100         part
->type 
== wxAuiDockUIPart::typeBackground
) 
3102         if (part
->type 
== wxAuiDockUIPart::typeDockSizer
) 
3104             if (part
->dock
->panes
.GetCount() != 1) 
3106             part 
= GetPanePart(part
->dock
->panes
.Item(0)->window
); 
3113         // If a normal frame is being dragged over a toolbar, insert it 
3114         // along the edge under the toolbar, but over all other panes. 
3115         // (this could be done much better, but somehow factoring this 
3116         // calculation with the one at the beginning of this function) 
3117         if (part
->dock 
&& part
->dock
->toolbar
) 
3121             switch (part
->dock
->dock_direction
) 
3123                 case wxAUI_DOCK_LEFT
: 
3124                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
3125                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
3126                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)); 
3128                 case wxAUI_DOCK_TOP
: 
3129                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
3130                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3131                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3133                 case wxAUI_DOCK_RIGHT
: 
3134                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
3135                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
3136                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)); 
3138                 case wxAUI_DOCK_BOTTOM
: 
3139                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
3140                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3141                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3145             DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3148                  Direction(part
->dock
->dock_direction
). 
3149                  Layer(layer
).Row(0).Position(0); 
3150             return ProcessDockResult(target
, drop
); 
3157         part 
= GetPanePart(part
->pane
->window
); 
3161         bool insert_dock_row 
= false; 
3162         int insert_row 
= part
->pane
->dock_row
; 
3163         int insert_dir 
= part
->pane
->dock_direction
; 
3164         int insert_layer 
= part
->pane
->dock_layer
; 
3166         switch (part
->pane
->dock_direction
) 
3168             case wxAUI_DOCK_TOP
: 
3169                 if (pt
.y 
>= part
->rect
.y 
&& 
3170                     pt
.y 
< part
->rect
.y
+auiInsertRowPixels
) 
3171                         insert_dock_row 
= true; 
3173             case wxAUI_DOCK_BOTTOM
: 
3174                 if (pt
.y 
> part
->rect
.y
+part
->rect
.height
-auiInsertRowPixels 
&& 
3175                     pt
.y 
<= part
->rect
.y 
+ part
->rect
.height
) 
3176                         insert_dock_row 
= true; 
3178             case wxAUI_DOCK_LEFT
: 
3179                 if (pt
.x 
>= part
->rect
.x 
&& 
3180                     pt
.x 
< part
->rect
.x
+auiInsertRowPixels
) 
3181                         insert_dock_row 
= true; 
3183             case wxAUI_DOCK_RIGHT
: 
3184                 if (pt
.x 
> part
->rect
.x
+part
->rect
.width
-auiInsertRowPixels 
&& 
3185                     pt
.x 
<= part
->rect
.x
+part
->rect
.width
) 
3186                         insert_dock_row 
= true; 
3188             case wxAUI_DOCK_CENTER
: 
3190                 // "new row pixels" will be set to the default, but 
3191                 // must never exceed 20% of the window size 
3192                 int new_row_pixels_x 
= auiNewRowPixels
; 
3193                 int new_row_pixels_y 
= auiNewRowPixels
; 
3195                 if (new_row_pixels_x 
> (part
->rect
.width
*20)/100) 
3196                     new_row_pixels_x 
= (part
->rect
.width
*20)/100; 
3198                 if (new_row_pixels_y 
> (part
->rect
.height
*20)/100) 
3199                     new_row_pixels_y 
= (part
->rect
.height
*20)/100; 
3202                 // determine if the mouse pointer is in a location that 
3203                 // will cause a new row to be inserted.  The hot spot positions 
3204                 // are along the borders of the center pane 
3207                 insert_dock_row 
= true; 
3208                 const wxRect
& pr 
= part
->rect
; 
3209                 if (pt
.x 
>= pr
.x 
&& pt
.x 
< pr
.x 
+ new_row_pixels_x
) 
3210                     insert_dir 
= wxAUI_DOCK_LEFT
; 
3211                 else if (pt
.y 
>= pr
.y 
&& pt
.y 
< pr
.y 
+ new_row_pixels_y
) 
3212                     insert_dir 
= wxAUI_DOCK_TOP
; 
3213                 else if (pt
.x 
>= pr
.x 
+ pr
.width 
- new_row_pixels_x 
&& 
3214                          pt
.x 
< pr
.x 
+ pr
.width
) 
3215                     insert_dir 
= wxAUI_DOCK_RIGHT
; 
3216                 else if (pt
.y 
>= pr
.y
+ pr
.height 
- new_row_pixels_y 
&& 
3217                          pt
.y 
< pr
.y 
+ pr
.height
) 
3218                     insert_dir 
= wxAUI_DOCK_BOTTOM
; 
3222                 insert_row 
= GetMaxRow(panes
, insert_dir
, insert_layer
) + 1; 
3226         if (insert_dock_row
) 
3228             DoInsertDockRow(panes
, insert_dir
, insert_layer
, insert_row
); 
3229             drop
.Dock().Direction(insert_dir
). 
3230                         Layer(insert_layer
). 
3233             return ProcessDockResult(target
, drop
); 
3236         // determine the mouse offset and the pane size, both in the 
3237         // direction of the dock itself, and perpendicular to the dock 
3239         int mouseOffset
, size
; 
3241         if (part
->orientation 
== wxVERTICAL
) 
3243             mouseOffset 
= pt
.y 
- part
->rect
.y
; 
3244             size 
= part
->rect
.GetHeight(); 
3248             mouseOffset 
= pt
.x 
- part
->rect
.x
; 
3249             size 
= part
->rect
.GetWidth(); 
3252         int drop_position 
= part
->pane
->dock_pos
; 
3254         // if we are in the top/left part of the pane, 
3255         // insert the pane before the pane being hovered over 
3256         if (mouseOffset 
<= size
/2) 
3258             drop_position 
= part
->pane
->dock_pos
; 
3260                          part
->pane
->dock_direction
, 
3261                          part
->pane
->dock_layer
, 
3262                          part
->pane
->dock_row
, 
3263                          part
->pane
->dock_pos
); 
3266         // if we are in the bottom/right part of the pane, 
3267         // insert the pane before the pane being hovered over 
3268         if (mouseOffset 
> size
/2) 
3270             drop_position 
= part
->pane
->dock_pos
+1; 
3272                          part
->pane
->dock_direction
, 
3273                          part
->pane
->dock_layer
, 
3274                          part
->pane
->dock_row
, 
3275                          part
->pane
->dock_pos
+1); 
3279              Direction(part
->dock
->dock_direction
). 
3280              Layer(part
->dock
->dock_layer
). 
3281              Row(part
->dock
->dock_row
). 
3282              Position(drop_position
); 
3283         return ProcessDockResult(target
, drop
); 
3290 void wxAuiManager::OnHintFadeTimer(wxTimerEvent
& WXUNUSED(event
)) 
3292     if (!m_hintWnd 
|| m_hintFadeAmt 
>= m_hintFadeMax
) 
3294         m_hintFadeTimer
.Stop(); 
3295         Disconnect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3296                    wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3301     m_hintWnd
->SetTransparent(m_hintFadeAmt
); 
3304 void wxAuiManager::ShowHint(const wxRect
& rect
) 
3308         // if the hint rect is the same as last time, don't do anything 
3309         if (m_lastHint 
== rect
) 
3313         m_hintFadeAmt 
= m_hintFadeMax
; 
3315         if ((m_flags 
& wxAUI_MGR_HINT_FADE
) 
3316             && !((wxDynamicCast(m_hintWnd
, wxPseudoTransparentFrame
)) && 
3317                  (m_flags 
& wxAUI_MGR_NO_VENETIAN_BLINDS_FADE
)) 
3321         m_hintWnd
->SetSize(rect
); 
3322         m_hintWnd
->SetTransparent(m_hintFadeAmt
); 
3324         if (!m_hintWnd
->IsShown()) 
3327         // if we are dragging a floating pane, set the focus 
3328         // back to that floating pane (otherwise it becomes unfocused) 
3329         if (m_action 
== actionDragFloatingPane 
&& m_actionWindow
) 
3330             m_actionWindow
->SetFocus(); 
3335         if (m_hintFadeAmt 
!= m_hintFadeMax
) //  Only fade if we need to 
3337             // start fade in timer 
3338             m_hintFadeTimer
.SetOwner(this); 
3339             m_hintFadeTimer
.Start(5); 
3340             Connect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3341                     wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3344     else  // Not using a transparent hint window... 
3346         if (!(m_flags 
& wxAUI_MGR_RECTANGLE_HINT
)) 
3349         if (m_lastHint 
!= rect
) 
3351             // remove the last hint rectangle 
3357         wxScreenDC screendc
; 
3358         wxRegion 
clip(1, 1, 10000, 10000); 
3360         // clip all floating windows, so we don't draw over them 
3362         for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
3364             wxAuiPaneInfo
& pane 
= m_panes
.Item(i
); 
3366             if (pane
.IsFloating() && 
3368                         pane
.frame
->IsShown()) 
3370                 wxRect r 
= pane
.frame
->GetRect(); 
3372                 // wxGTK returns the client size, not the whole frame size 
3382         // As we can only hide the hint by redrawing the managed window, we 
3383         // need to clip the region to the managed window too or we get 
3384         // nasty redrawn problems. 
3385         clip
.Intersect(m_frame
->GetRect()); 
3387         screendc
.SetDeviceClippingRegion(clip
); 
3389         wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
3390         wxBrush 
brush(stipple
); 
3391         screendc
.SetBrush(brush
); 
3392         screendc
.SetPen(*wxTRANSPARENT_PEN
); 
3394         screendc
.DrawRectangle(rect
.x
, rect
.y
, 5, rect
.height
); 
3395         screendc
.DrawRectangle(rect
.x
+5, rect
.y
, rect
.width
-10, 5); 
3396         screendc
.DrawRectangle(rect
.x
+rect
.width
-5, rect
.y
, 5, rect
.height
); 
3397         screendc
.DrawRectangle(rect
.x
+5, rect
.y
+rect
.height
-5, rect
.width
-10, 5); 
3401 void wxAuiManager::HideHint() 
3403     // hides a transparent window hint, if there is one 
3406         if (m_hintWnd
->IsShown()) 
3407             m_hintWnd
->Show(false); 
3408         m_hintWnd
->SetTransparent(0); 
3409         m_hintFadeTimer
.Stop(); 
3410         // In case this is called while a hint fade is going, we need to 
3411         // disconnect the event handler. 
3412         Disconnect(m_hintFadeTimer
.GetId(), wxEVT_TIMER
, 
3413                    wxTimerEventHandler(wxAuiManager::OnHintFadeTimer
)); 
3414         m_lastHint 
= wxRect(); 
3418     // hides a painted hint by redrawing the frame window 
3419     if (!m_lastHint
.IsEmpty()) 
3423         m_lastHint 
= wxRect(); 
3427 void wxAuiManager::OnHintActivate(wxActivateEvent
& WXUNUSED(event
)) 
3429     // Do nothing so this event isn't handled in the base handlers. 
3431     // Letting the hint window activate without this handler can lead to 
3432     // weird behaviour on Mac where the menu is switched out to the top 
3433     // window's menu in MDI applications when it shouldn't be. So since 
3434     // we don't want user interaction with the hint window anyway, we just 
3435     // prevent it from activating here. 
3440 void wxAuiManager::StartPaneDrag(wxWindow
* pane_window
, 
3441                                  const wxPoint
& offset
) 
3443     wxAuiPaneInfo
& pane 
= GetPane(pane_window
); 
3447     if (pane
.IsToolbar()) 
3449         m_action 
= actionDragToolbarPane
; 
3453         m_action 
= actionDragFloatingPane
; 
3456     m_actionWindow 
= pane_window
; 
3457     m_actionOffset 
= offset
; 
3458     m_frame
->CaptureMouse(); 
3462         wxRect window_rect 
= pane
.frame
->GetRect(); 
3463         wxRect client_rect 
= pane
.frame
->GetClientRect(); 
3464         wxPoint client_pt 
= pane
.frame
->ClientToScreen(client_rect
.GetTopLeft()); 
3465         wxPoint origin_pt 
= client_pt 
- window_rect
.GetTopLeft(); 
3466         m_actionOffset 
+= origin_pt
; 
3471 // CalculateHintRect() calculates the drop hint rectangle.  The method 
3472 // first calls DoDrop() to determine the exact position the pane would 
3473 // be at were if dropped.  If the pane would indeed become docked at the 
3474 // specified drop point, the rectangle hint will be returned in 
3475 // screen coordinates.  Otherwise, an empty rectangle is returned. 
3476 // |pane_window| is the window pointer of the pane being dragged, |pt| is 
3477 // the mouse position, in client coordinates.  |offset| describes the offset 
3478 // that the mouse is from the upper-left corner of the item being dragged 
3480 wxRect 
wxAuiManager::CalculateHintRect(wxWindow
* pane_window
, 
3482                                        const wxPoint
& offset
) 
3486     // we need to paint a hint rectangle; to find out the exact hint rectangle, 
3487     // we will create a new temporary layout and then measure the resulting 
3488     // rectangle; we will create a copy of the docking structures (m_dock) 
3489     // so that we don't modify the real thing on screen 
3491     int i
, pane_count
, part_count
; 
3492     wxAuiDockInfoArray docks
; 
3493     wxAuiPaneInfoArray panes
; 
3494     wxAuiDockUIPartArray uiparts
; 
3495     wxAuiPaneInfo hint 
= GetPane(pane_window
); 
3496     hint
.name 
= wxT("__HINT__"); 
3497     hint
.PaneBorder(true); 
3503     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3505     // remove any pane already there which bears the same window; 
3506     // this happens when you are moving a pane around in a dock 
3507     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
3509         if (panes
.Item(i
).window 
== pane_window
) 
3511             RemovePaneFromDocks(docks
, panes
.Item(i
)); 
3517     // find out where the new pane would be 
3518     if (!DoDrop(docks
, panes
, hint
, pt
, offset
)) 
3525     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
3526     wxSize client_size 
= m_frame
->GetClientSize(); 
3527     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
3530     for (i 
= 0, part_count 
= uiparts
.GetCount(); 
3531          i 
< part_count
; ++i
) 
3533         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
3535         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
3536             part
.pane 
&& part
.pane
->name 
== wxT("__HINT__")) 
3538             rect 
= wxRect(part
.sizer_item
->GetPosition(), 
3539                           part
.sizer_item
->GetSize()); 
3551     // actually show the hint rectangle on the screen 
3552     m_frame
->ClientToScreen(&rect
.x
, &rect
.y
); 
3554     if ( m_frame
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
3556         // Mirror rectangle in RTL mode 
3557         rect
.x 
-= rect
.GetWidth(); 
3563 // DrawHintRect() calculates the hint rectangle by calling 
3564 // CalculateHintRect().  If there is a rectangle, it shows it 
3565 // by calling ShowHint(), otherwise it hides any hint 
3566 // rectangle currently shown 
3567 void wxAuiManager::DrawHintRect(wxWindow
* pane_window
, 
3569                                 const wxPoint
& offset
) 
3571     wxRect rect 
= CalculateHintRect(pane_window
, pt
, offset
); 
3583 void wxAuiManager::OnFloatingPaneMoveStart(wxWindow
* wnd
) 
3585     // try to find the pane 
3586     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3587     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3592     if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3593         pane
.frame
->SetTransparent(150); 
3596 void wxAuiManager::OnFloatingPaneMoving(wxWindow
* wnd
, wxDirection dir
) 
3598     // try to find the pane 
3599     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3600     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3605     wxPoint pt 
= ::wxGetMousePosition(); 
3608     // Adapt pt to direction 
3611         // move to pane's upper border 
3613         pos 
= wnd
->ClientToScreen( pos 
); 
3615         // and some more pixels for the title bar 
3618     else if (dir 
== wxWEST
) 
3620         // move to pane's left border 
3622         pos 
= wnd
->ClientToScreen( pos 
); 
3625     else if (dir 
== wxEAST
) 
3627         // move to pane's right border 
3628         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3629         pos 
= wnd
->ClientToScreen( pos 
); 
3632     else if (dir 
== wxSOUTH
) 
3634         // move to pane's bottom border 
3635         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3636         pos 
= wnd
->ClientToScreen( pos 
); 
3643     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3645     // calculate the offset from the upper left-hand corner 
3646     // of the frame to the mouse pointer 
3647     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3648     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3650     // no hint for toolbar floating windows 
3651     if (pane
.IsToolbar() && m_action 
== actionDragFloatingPane
) 
3653         wxAuiDockInfoArray docks
; 
3654         wxAuiPaneInfoArray panes
; 
3655         wxAuiDockUIPartArray uiparts
; 
3656         wxAuiPaneInfo hint 
= pane
; 
3658         CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3660         // find out where the new pane would be 
3661         if (!DoDrop(docks
, panes
, hint
, client_pt
)) 
3663         if (hint
.IsFloating()) 
3667         m_action 
= actionDragToolbarPane
; 
3668         m_actionWindow 
= pane
.window
; 
3676     // if a key modifier is pressed while dragging the frame, 
3677     // don't dock the window 
3678     if (!CanDockPanel(pane
)) 
3685     DrawHintRect(wnd
, client_pt
, action_offset
); 
3688     // this cleans up some screen artifacts that are caused on GTK because 
3689     // we aren't getting the exact size of the window (see comment 
3699 void wxAuiManager::OnFloatingPaneMoved(wxWindow
* wnd
, wxDirection dir
) 
3701     // try to find the pane 
3702     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3703     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3708     wxPoint pt 
= ::wxGetMousePosition(); 
3711     // Adapt pt to direction 
3714         // move to pane's upper border 
3716         pos 
= wnd
->ClientToScreen( pos 
); 
3718         // and some more pixels for the title bar 
3721     else if (dir 
== wxWEST
) 
3723         // move to pane's left border 
3725         pos 
= wnd
->ClientToScreen( pos 
); 
3728     else if (dir 
== wxEAST
) 
3730         // move to pane's right border 
3731         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3732         pos 
= wnd
->ClientToScreen( pos 
); 
3735     else if (dir 
== wxSOUTH
) 
3737         // move to pane's bottom border 
3738         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3739         pos 
= wnd
->ClientToScreen( pos 
); 
3746     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3748     // calculate the offset from the upper left-hand corner 
3749     // of the frame to the mouse pointer 
3750     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3751     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3753     // if a key modifier is pressed while dragging the frame, 
3754     // don't dock the window 
3755     if (CanDockPanel(pane
)) 
3757         // do the drop calculation 
3758         DoDrop(m_docks
, m_panes
, pane
, client_pt
, action_offset
); 
3761     // if the pane is still floating, update it's floating 
3762     // position (that we store) 
3763     if (pane
.IsFloating()) 
3765         pane
.floating_pos 
= pane
.frame
->GetPosition(); 
3767         if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3768             pane
.frame
->SetTransparent(255); 
3770     else if (m_hasMaximized
) 
3772         RestoreMaximizedPane(); 
3780 void wxAuiManager::OnFloatingPaneResized(wxWindow
* wnd
, const wxRect
& rect
) 
3782     // try to find the pane 
3783     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3784     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3786     pane
.FloatingSize(rect
.GetWidth(), rect
.GetHeight()); 
3788     // the top-left position may change as well as the size 
3789     pane
.FloatingPosition(rect
.x
, rect
.y
); 
3793 void wxAuiManager::OnFloatingPaneClosed(wxWindow
* wnd
, wxCloseEvent
& evt
) 
3795     // try to find the pane 
3796     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3797     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3800     // fire pane close event 
3801     wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
3803     e
.SetCanVeto(evt
.CanVeto()); 
3813         // close the pane, but check that it 
3814         // still exists in our pane array first 
3815         // (the event handler above might have removed it) 
3817         wxAuiPaneInfo
& check 
= GetPane(wnd
); 
3827 void wxAuiManager::OnFloatingPaneActivated(wxWindow
* wnd
) 
3829     if ((GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) && GetPane(wnd
).IsOk()) 
3836 // OnRender() draws all of the pane captions, sashes, 
3837 // backgrounds, captions, grippers, pane borders and buttons. 
3838 // It renders the entire user interface. 
3840 void wxAuiManager::OnRender(wxAuiManagerEvent
& evt
) 
3842     // if the frame is about to be deleted, don't bother 
3843     if (!m_frame 
|| wxPendingDelete
.Member(m_frame
)) 
3846     wxDC
* dc 
= evt
.GetDC(); 
3852     for (i 
= 0, part_count 
= m_uiParts
.GetCount(); 
3853          i 
< part_count
; ++i
) 
3855         wxAuiDockUIPart
& part 
= m_uiParts
.Item(i
); 
3857         // don't draw hidden pane items or items that aren't windows 
3858         if (part
.sizer_item 
&& ((!part
.sizer_item
->IsWindow() && !part
.sizer_item
->IsSpacer() && !part
.sizer_item
->IsSizer()) || !part
.sizer_item
->IsShown())) 
3863             case wxAuiDockUIPart::typeDockSizer
: 
3864             case wxAuiDockUIPart::typePaneSizer
: 
3865                 m_art
->DrawSash(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3867             case wxAuiDockUIPart::typeBackground
: 
3868                 m_art
->DrawBackground(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3870             case wxAuiDockUIPart::typeCaption
: 
3871                 m_art
->DrawCaption(*dc
, m_frame
, part
.pane
->caption
, part
.rect
, *part
.pane
); 
3873             case wxAuiDockUIPart::typeGripper
: 
3874                 m_art
->DrawGripper(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3876             case wxAuiDockUIPart::typePaneBorder
: 
3877                 m_art
->DrawBorder(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3879             case wxAuiDockUIPart::typePaneButton
: 
3880                 m_art
->DrawPaneButton(*dc
, m_frame
, part
.button
->button_id
, 
3881                         wxAUI_BUTTON_STATE_NORMAL
, part
.rect
, *part
.pane
); 
3888 // Render() fire a render event, which is normally handled by 
3889 // wxAuiManager::OnRender().  This allows the render function to 
3890 // be overridden via the render event.  This can be useful for paintin 
3891 // custom graphics in the main window. Default behaviour can be 
3892 // invoked in the overridden function by calling OnRender() 
3894 void wxAuiManager::Render(wxDC
* dc
) 
3896     wxAuiManagerEvent 
e(wxEVT_AUI_RENDER
); 
3902 void wxAuiManager::Repaint(wxDC
* dc
) 
3907         m_frame
->Refresh() ; 
3913     m_frame
->GetClientSize(&w
, &h
); 
3915     // figure out which dc to use; if one 
3916     // has been specified, use it, otherwise 
3918     wxClientDC
* client_dc 
= NULL
; 
3921         client_dc 
= new wxClientDC(m_frame
); 
3925     // if the frame has a toolbar, the client area 
3926     // origin will not be (0,0). 
3927     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
3928     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
3929         dc
->SetDeviceOrigin(pt
.x
, pt
.y
); 
3931     // render all the items 
3934     // if we created a client_dc, delete it 
3939 void wxAuiManager::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
3941     wxPaintDC 
dc(m_frame
); 
3945 void wxAuiManager::OnEraseBackground(wxEraseEvent
& event
) 
3954 void wxAuiManager::OnSize(wxSizeEvent
& event
) 
3962         if (wxDynamicCast(m_frame
, wxMDIParentFrame
)) 
3964             // for MDI parent frames, this event must not 
3965             // be "skipped".  In other words, the parent frame 
3966             // must not be allowed to resize the client window 
3967             // after we are finished processing sizing changes 
3975 void wxAuiManager::OnFindManager(wxAuiManagerEvent
& evt
) 
3977     // get the window we are managing, if none, return NULL 
3978     wxWindow
* window 
= GetManagedWindow(); 
3981         evt
.SetManager(NULL
); 
3985     // if we are managing a child frame, get the 'real' manager 
3986     if (wxDynamicCast(window
, wxAuiFloatingFrame
)) 
3988         wxAuiFloatingFrame
* float_frame 
= static_cast<wxAuiFloatingFrame
*>(window
); 
3989         evt
.SetManager(float_frame
->GetOwnerManager()); 
3993     // return pointer to ourself 
3994     evt
.SetManager(this); 
3997 void wxAuiManager::OnSetCursor(wxSetCursorEvent
& event
) 
4000     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4001     wxCursor cursor 
= wxNullCursor
; 
4005         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
4006             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4008             // a dock may not be resized if it has a single 
4009             // pane which is not resizable 
4010             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
4011                 part
->dock
->panes
.GetCount() == 1 && 
4012                 part
->dock
->panes
.Item(0)->IsFixed()) 
4015             // panes that may not be resized do not get a sizing cursor 
4016             if (part
->pane 
&& part
->pane
->IsFixed()) 
4019             if (part
->orientation 
== wxVERTICAL
) 
4020                 cursor 
= wxCursor(wxCURSOR_SIZEWE
); 
4022                 cursor 
= wxCursor(wxCURSOR_SIZENS
); 
4024         else if (part
->type 
== wxAuiDockUIPart::typeGripper
) 
4026             cursor 
= wxCursor(wxCURSOR_SIZING
); 
4030     event
.SetCursor(cursor
); 
4035 void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart
* button_ui_part
, 
4036                                         const wxMouseEvent
& event
) 
4038     wxAuiDockUIPart
* hit_test 
= HitTest(event
.GetX(), event
.GetY()); 
4039     if (!hit_test 
|| !button_ui_part
) 
4042     int state 
= wxAUI_BUTTON_STATE_NORMAL
; 
4044     if (hit_test 
== button_ui_part
) 
4046         if (event
.LeftDown()) 
4047             state 
= wxAUI_BUTTON_STATE_PRESSED
; 
4049             state 
= wxAUI_BUTTON_STATE_HOVER
; 
4053         if (event
.LeftDown()) 
4054             state 
= wxAUI_BUTTON_STATE_HOVER
; 
4057     // now repaint the button with hover state 
4058     wxClientDC 
cdc(m_frame
); 
4060     // if the frame has a toolbar, the client area 
4061     // origin will not be (0,0). 
4062     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
4063     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
4064         cdc
.SetDeviceOrigin(pt
.x
, pt
.y
); 
4068         m_art
->DrawPaneButton(cdc
, m_frame
, 
4069                   button_ui_part
->button
->button_id
, 
4071                   button_ui_part
->rect
, 
4076 void wxAuiManager::OnLeftDown(wxMouseEvent
& event
) 
4078     m_currentDragItem 
= -1; 
4080     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4083         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
4084             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4086             // Removing this restriction so that a centre pane can be resized 
4087             //if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) 
4090             // a dock may not be resized if it has a single 
4091             // pane which is not resizable 
4092             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
4093                 part
->dock
->panes
.GetCount() == 1 && 
4094                 part
->dock
->panes
.Item(0)->IsFixed()) 
4097             // panes that may not be resized should be ignored here 
4098             if (part
->pane 
&& part
->pane
->IsFixed()) 
4101             m_action 
= actionResize
; 
4102             m_actionPart 
= part
; 
4103             m_actionHintRect 
= wxRect(); 
4104             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4105             m_actionOffset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
4106                                       event
.m_y 
- part
->rect
.y
); 
4107             m_frame
->CaptureMouse(); 
4109         else if (part
->type 
== wxAuiDockUIPart::typePaneButton
) 
4111             m_action 
= actionClickButton
; 
4112             m_actionPart 
= part
; 
4113             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4114             m_frame
->CaptureMouse(); 
4116             UpdateButtonOnScreen(part
, event
); 
4118         else if (part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
4119                   part
->type 
== wxAuiDockUIPart::typeGripper
) 
4121             // if we are managing a wxAuiFloatingFrame window, then 
4122             // we are an embedded wxAuiManager inside the wxAuiFloatingFrame. 
4123             // We want to initiate a toolbar drag in our owner manager 
4124             wxWindow
* managed_wnd 
= GetManagedWindow(); 
4127                 part
->pane
->window 
&& 
4129                 wxDynamicCast(managed_wnd
, wxAuiFloatingFrame
)) 
4131                 wxAuiFloatingFrame
* floating_frame 
= (wxAuiFloatingFrame
*)managed_wnd
; 
4132                 wxAuiManager
* owner_mgr 
= floating_frame
->GetOwnerManager(); 
4133                 owner_mgr
->StartPaneDrag(part
->pane
->window
, 
4134                                              wxPoint(event
.m_x 
- part
->rect
.x
, 
4135                                                      event
.m_y 
- part
->rect
.y
)); 
4141             if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4143                 // set the caption as active 
4144                 SetActivePane(part
->pane
->window
); 
4148             if (part
->dock 
&& part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER
) 
4151             m_action 
= actionClickCaption
; 
4152             m_actionPart 
= part
; 
4153             m_actionStart 
= wxPoint(event
.m_x
, event
.m_y
); 
4154             m_actionOffset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
4155                                       event
.m_y 
- part
->rect
.y
); 
4156             m_frame
->CaptureMouse(); 
4175 /// Ends a resize action, or for live update, resizes the sash 
4176 bool wxAuiManager::DoEndResizeAction(wxMouseEvent
& event
) 
4178     // resize the dock or the pane 
4179     if (m_actionPart 
&& m_actionPart
->type
==wxAuiDockUIPart::typeDockSizer
) 
4181         // first, we must calculate the maximum size the dock may be 
4182         int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
4184         int used_width 
= 0, used_height 
= 0; 
4186         wxSize client_size 
= m_frame
->GetClientSize(); 
4188         size_t dock_i
, dock_count 
= m_docks
.GetCount(); 
4189         for (dock_i 
= 0; dock_i 
< dock_count
; ++dock_i
) 
4191             wxAuiDockInfo
& dock 
= m_docks
.Item(dock_i
); 
4192             if (dock
.dock_direction 
== wxAUI_DOCK_TOP 
|| 
4193                 dock
.dock_direction 
== wxAUI_DOCK_BOTTOM
) 
4195                 used_height 
+= dock
.size
; 
4197             if (dock
.dock_direction 
== wxAUI_DOCK_LEFT 
|| 
4198                 dock
.dock_direction 
== wxAUI_DOCK_RIGHT
) 
4200                 used_width 
+= dock
.size
; 
4203                 used_width 
+= sashSize
; 
4207         int available_width 
= client_size
.GetWidth() - used_width
; 
4208         int available_height 
= client_size
.GetHeight() - used_height
; 
4212         // if there's a status control, the available 
4213         // height decreases accordingly 
4214         if (wxDynamicCast(m_frame
, wxFrame
)) 
4216             wxFrame
* frame 
= static_cast<wxFrame
*>(m_frame
); 
4217             wxStatusBar
* status 
= frame
->GetStatusBar(); 
4220                 wxSize status_client_size 
= status
->GetClientSize(); 
4221                 available_height 
-= status_client_size
.GetHeight(); 
4226         wxRect
& rect 
= m_actionPart
->dock
->rect
; 
4228         wxPoint 
new_pos(event
.m_x 
- m_actionOffset
.x
, 
4229             event
.m_y 
- m_actionOffset
.y
); 
4230         int new_size
, old_size 
= m_actionPart
->dock
->size
; 
4232         switch (m_actionPart
->dock
->dock_direction
) 
4234         case wxAUI_DOCK_LEFT
: 
4235             new_size 
= new_pos
.x 
- rect
.x
; 
4236             if (new_size
-old_size 
> available_width
) 
4237                 new_size 
= old_size
+available_width
; 
4238             m_actionPart
->dock
->size 
= new_size
; 
4240         case wxAUI_DOCK_TOP
: 
4241             new_size 
= new_pos
.y 
- rect
.y
; 
4242             if (new_size
-old_size 
> available_height
) 
4243                 new_size 
= old_size
+available_height
; 
4244             m_actionPart
->dock
->size 
= new_size
; 
4246         case wxAUI_DOCK_RIGHT
: 
4247             new_size 
= rect
.x 
+ rect
.width 
- new_pos
.x 
- 
4248                        m_actionPart
->rect
.GetWidth(); 
4249             if (new_size
-old_size 
> available_width
) 
4250                 new_size 
= old_size
+available_width
; 
4251             m_actionPart
->dock
->size 
= new_size
; 
4253         case wxAUI_DOCK_BOTTOM
: 
4254             new_size 
= rect
.y 
+ rect
.height 
- 
4255                 new_pos
.y 
- m_actionPart
->rect
.GetHeight(); 
4256             if (new_size
-old_size 
> available_height
) 
4257                 new_size 
= old_size
+available_height
; 
4258             m_actionPart
->dock
->size 
= new_size
; 
4265     else if (m_actionPart 
&& 
4266         m_actionPart
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4268         wxAuiDockInfo
& dock 
= *m_actionPart
->dock
; 
4269         wxAuiPaneInfo
& pane 
= *m_actionPart
->pane
; 
4271         int total_proportion 
= 0; 
4272         int dock_pixels 
= 0; 
4273         int new_pixsize 
= 0; 
4275         int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
4276         int pane_borderSize 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
4277         int sashSize 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
4279         wxPoint 
new_pos(event
.m_x 
- m_actionOffset
.x
, 
4280             event
.m_y 
- m_actionOffset
.y
); 
4282         // determine the pane rectangle by getting the pane part 
4283         wxAuiDockUIPart
* pane_part 
= GetPanePart(pane
.window
); 
4284         wxASSERT_MSG(pane_part
, 
4285             wxT("Pane border part not found -- shouldn't happen")); 
4287         // determine the new pixel size that the user wants; 
4288         // this will help us recalculate the pane's proportion 
4289         if (dock
.IsHorizontal()) 
4290             new_pixsize 
= new_pos
.x 
- pane_part
->rect
.x
; 
4292             new_pixsize 
= new_pos
.y 
- pane_part
->rect
.y
; 
4294         // determine the size of the dock, based on orientation 
4295         if (dock
.IsHorizontal()) 
4296             dock_pixels 
= dock
.rect
.GetWidth(); 
4298             dock_pixels 
= dock
.rect
.GetHeight(); 
4300         // determine the total proportion of all resizable panes, 
4301         // and the total size of the dock minus the size of all 
4303         int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4304         int pane_position 
= -1; 
4305         for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4307             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4308             if (p
.window 
== pane
.window
) 
4311             // while we're at it, subtract the pane sash 
4312             // width from the dock width, because this would 
4313             // skew our proportion calculations 
4315                 dock_pixels 
-= sashSize
; 
4317             // also, the whole size (including decorations) of 
4318             // all fixed panes must also be subtracted, because they 
4319             // are not part of the proportion calculation 
4322                 if (dock
.IsHorizontal()) 
4323                     dock_pixels 
-= p
.best_size
.x
; 
4325                     dock_pixels 
-= p
.best_size
.y
; 
4329                 total_proportion 
+= p
.dock_proportion
; 
4333         // new size can never be more than the number of dock pixels 
4334         if (new_pixsize 
> dock_pixels
) 
4335             new_pixsize 
= dock_pixels
; 
4338         // find a pane in our dock to 'steal' space from or to 'give' 
4339         // space to -- this is essentially what is done when a pane is 
4340         // resized; the pane should usually be the first non-fixed pane 
4341         // to the right of the action pane 
4342         int borrow_pane 
= -1; 
4343         for (i 
= pane_position
+1; i 
< dock_pane_count
; ++i
) 
4345             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4354         // demand that the pane being resized is found in this dock 
4355         // (this assert really never should be raised) 
4356         wxASSERT_MSG(pane_position 
!= -1, wxT("Pane not found in dock")); 
4358         // prevent division by zero 
4359         if (dock_pixels 
== 0 || total_proportion 
== 0 || borrow_pane 
== -1) 
4361             m_action 
= actionNone
; 
4365         // calculate the new proportion of the pane 
4366         int new_proportion 
= (new_pixsize
*total_proportion
)/dock_pixels
; 
4368         // default minimum size 
4371         // check against the pane's minimum size, if specified. please note 
4372         // that this is not enough to ensure that the minimum size will 
4373         // not be violated, because the whole frame might later be shrunk, 
4374         // causing the size of the pane to violate it's minimum size 
4375         if (pane
.min_size
.IsFullySpecified()) 
4379             if (pane
.HasBorder()) 
4380                 min_size 
+= (pane_borderSize
*2); 
4382             // calculate minimum size with decorations (border,caption) 
4383             if (pane_part
->orientation 
== wxVERTICAL
) 
4385                 min_size 
+= pane
.min_size
.y
; 
4386                 if (pane
.HasCaption()) 
4387                     min_size 
+= caption_size
; 
4391                 min_size 
+= pane
.min_size
.x
; 
4396         // for some reason, an arithmatic error somewhere is causing 
4397         // the proportion calculations to always be off by 1 pixel; 
4398         // for now we will add the 1 pixel on, but we really should 
4399         // determine what's causing this. 
4402         int min_proportion 
= (min_size
*total_proportion
)/dock_pixels
; 
4404         if (new_proportion 
< min_proportion
) 
4405             new_proportion 
= min_proportion
; 
4409         int prop_diff 
= new_proportion 
- pane
.dock_proportion
; 
4411         // borrow the space from our neighbor pane to the 
4412         // right or bottom (depending on orientation); 
4413         // also make sure we don't make the neighbor too small 
4414         int prop_borrow 
= dock
.panes
.Item(borrow_pane
)->dock_proportion
; 
4416         if (prop_borrow 
- prop_diff 
< 0) 
4418             // borrowing from other pane would make it too small, 
4419             // so cancel the resize operation 
4420             prop_borrow 
= min_proportion
; 
4424             prop_borrow 
-= prop_diff
; 
4428         dock
.panes
.Item(borrow_pane
)->dock_proportion 
= prop_borrow
; 
4429         pane
.dock_proportion 
= new_proportion
; 
4440 void wxAuiManager::OnLeftUp(wxMouseEvent
& event
) 
4442     if (m_action 
== actionResize
) 
4444         m_frame
->ReleaseMouse(); 
4446         if (!wxAuiManager_HasLiveResize(*this)) 
4448             // get rid of the hint rectangle 
4450             DrawResizeHint(dc
, m_actionHintRect
); 
4452         if (m_currentDragItem 
!= -1 && wxAuiManager_HasLiveResize(*this)) 
4453             m_actionPart 
= & (m_uiParts
.Item(m_currentDragItem
)); 
4455         DoEndResizeAction(event
); 
4457         m_currentDragItem 
= -1; 
4460     else if (m_action 
== actionClickButton
) 
4462         m_hoverButton 
= NULL
; 
4463         m_frame
->ReleaseMouse(); 
4467             UpdateButtonOnScreen(m_actionPart
, event
); 
4469             // make sure we're still over the item that was originally clicked 
4470             if (m_actionPart 
== HitTest(event
.GetX(), event
.GetY())) 
4472                 // fire button-click event 
4473                 wxAuiManagerEvent 
e(wxEVT_AUI_PANE_BUTTON
); 
4475                 e
.SetPane(m_actionPart
->pane
); 
4476                 e
.SetButton(m_actionPart
->button
->button_id
); 
4481     else if (m_action 
== actionClickCaption
) 
4483         m_frame
->ReleaseMouse(); 
4485     else if (m_action 
== actionDragFloatingPane
) 
4487         m_frame
->ReleaseMouse(); 
4489     else if (m_action 
== actionDragToolbarPane
) 
4491         m_frame
->ReleaseMouse(); 
4493         wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4494         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4496         // save the new positions 
4497         wxAuiDockInfoPtrArray docks
; 
4498         FindDocks(m_docks
, pane
.dock_direction
, 
4499                   pane
.dock_layer
, pane
.dock_row
, docks
); 
4500         if (docks
.GetCount() == 1) 
4502             wxAuiDockInfo
& dock 
= *docks
.Item(0); 
4504             wxArrayInt pane_positions
, pane_sizes
; 
4505             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
4507             int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4508             for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4509                 dock
.panes
.Item(i
)->dock_pos 
= pane_positions
[i
]; 
4512         pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4520     m_action 
= actionNone
; 
4521     m_lastMouseMove 
= wxPoint(); // see comment in OnMotion() 
4525 void wxAuiManager::OnMotion(wxMouseEvent
& event
) 
4527     // sometimes when Update() is called from inside this method, 
4528     // a spurious mouse move event is generated; this check will make 
4529     // sure that only real mouse moves will get anywhere in this method; 
4530     // this appears to be a bug somewhere, and I don't know where the 
4531     // mouse move event is being generated.  only verified on MSW 
4533     wxPoint mouse_pos 
= event
.GetPosition(); 
4534     if (m_lastMouseMove 
== mouse_pos
) 
4536     m_lastMouseMove 
= mouse_pos
; 
4539     if (m_action 
== actionResize
) 
4541         // It's necessary to reset m_actionPart since it destroyed 
4542         // by the Update within DoEndResizeAction. 
4543         if (m_currentDragItem 
!= -1) 
4544             m_actionPart 
= & (m_uiParts
.Item(m_currentDragItem
)); 
4546             m_currentDragItem 
= m_uiParts
.Index(* m_actionPart
); 
4550             wxPoint pos 
= m_actionPart
->rect
.GetPosition(); 
4551             if (m_actionPart
->orientation 
== wxHORIZONTAL
) 
4552                 pos
.y 
= wxMax(0, event
.m_y 
- m_actionOffset
.y
); 
4554                 pos
.x 
= wxMax(0, event
.m_x 
- m_actionOffset
.x
); 
4556             if (wxAuiManager_HasLiveResize(*this)) 
4558                 m_frame
->ReleaseMouse(); 
4559                 DoEndResizeAction(event
); 
4560                 m_frame
->CaptureMouse(); 
4564                 wxRect 
rect(m_frame
->ClientToScreen(pos
), 
4565                     m_actionPart
->rect
.GetSize()); 
4568                 if (!m_actionHintRect
.IsEmpty()) 
4570                     // remove old resize hint 
4571                     DrawResizeHint(dc
, m_actionHintRect
); 
4572                     m_actionHintRect 
= wxRect(); 
4575                 // draw new resize hint, if it's inside the managed frame 
4576                 wxRect frameScreenRect 
= m_frame
->GetScreenRect(); 
4577                 if (frameScreenRect
.Contains(rect
)) 
4579                     DrawResizeHint(dc
, rect
); 
4580                     m_actionHintRect 
= rect
; 
4585     else if (m_action 
== actionClickCaption
) 
4587         int drag_x_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
); 
4588         int drag_y_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
); 
4590         // caption has been clicked.  we need to check if the mouse 
4591         // is now being dragged. if it is, we need to change the 
4592         // mouse action to 'drag' 
4594             (abs(event
.m_x 
- m_actionStart
.x
) > drag_x_threshold 
|| 
4595              abs(event
.m_y 
- m_actionStart
.y
) > drag_y_threshold
)) 
4597             wxAuiPaneInfo
* paneInfo 
= m_actionPart
->pane
; 
4599             if (!paneInfo
->IsToolbar()) 
4601                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && 
4602                     paneInfo
->IsFloatable()) 
4604                     m_action 
= actionDragFloatingPane
; 
4606                     // set initial float position 
4607                     wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4608                     paneInfo
->floating_pos 
= wxPoint(pt
.x 
- m_actionOffset
.x
, 
4609                                                       pt
.y 
- m_actionOffset
.y
); 
4612                     if (paneInfo
->IsMaximized()) 
4613                         RestorePane(*paneInfo
); 
4617                     m_actionWindow 
= paneInfo
->frame
; 
4619                     // action offset is used here to make it feel "natural" to the user 
4620                     // to drag a docked pane and suddenly have it become a floating frame. 
4621                     // Sometimes, however, the offset where the user clicked on the docked 
4622                     // caption is bigger than the width of the floating frame itself, so 
4623                     // in that case we need to set the action offset to a sensible value 
4624                     wxSize frame_size 
= m_actionWindow
->GetSize(); 
4625                     if (frame_size
.x 
<= m_actionOffset
.x
) 
4626                         m_actionOffset
.x 
= 30; 
4631                 m_action 
= actionDragToolbarPane
; 
4632                 m_actionWindow 
= paneInfo
->window
; 
4636     else if (m_action 
== actionDragFloatingPane
) 
4640             // We can't move the child window so we need to get the frame that 
4641             // we want to be really moving. This is probably not the best place 
4642             // to do this but at least it fixes the bug (#13177) for now. 
4643             if (!wxDynamicCast(m_actionWindow
, wxAuiFloatingFrame
)) 
4645                 wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4646                 m_actionWindow 
= pane
.frame
; 
4649             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4650             m_actionWindow
->Move(pt
.x 
- m_actionOffset
.x
, 
4651                                 pt
.y 
- m_actionOffset
.y
); 
4654     else if (m_action 
== actionDragToolbarPane
) 
4656         wxAuiPaneInfo
& pane 
= GetPane(m_actionWindow
); 
4657         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4659         pane
.SetFlag(wxAuiPaneInfo::actionPane
, true); 
4661         wxPoint point 
= event
.GetPosition(); 
4662         DoDrop(m_docks
, m_panes
, pane
, point
, m_actionOffset
); 
4664         // if DoDrop() decided to float the pane, set up 
4665         // the floating pane's initial position 
4666         if (pane
.IsFloating()) 
4668             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4669             pane
.floating_pos 
= wxPoint(pt
.x 
- m_actionOffset
.x
, 
4670                                         pt
.y 
- m_actionOffset
.y
); 
4673         // this will do the actiual move operation; 
4674         // in the case that the pane has been floated, 
4675         // this call will create the floating pane 
4676         // and do the reparenting 
4679         // if the pane has been floated, change the mouse 
4680         // action actionDragFloatingPane so that subsequent 
4681         // EVT_MOTION() events will move the floating pane 
4682         if (pane
.IsFloating()) 
4684             pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4685             m_action 
= actionDragFloatingPane
; 
4686             m_actionWindow 
= pane
.frame
; 
4691         wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4692         if (part 
&& part
->type 
== wxAuiDockUIPart::typePaneButton
) 
4694             if (part 
!= m_hoverButton
) 
4696                 // make the old button normal 
4699                     UpdateButtonOnScreen(m_hoverButton
, event
); 
4703                 // mouse is over a button, so repaint the 
4704                 // button in hover mode 
4705                 UpdateButtonOnScreen(part
, event
); 
4706                 m_hoverButton 
= part
; 
4714                 m_hoverButton 
= NULL
; 
4725 void wxAuiManager::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
)) 
4729         m_hoverButton 
= NULL
; 
4734 void wxAuiManager::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
4736     // cancel the operation in progress, if any 
4737     if ( m_action 
!= actionNone 
) 
4739         m_action 
= actionNone
; 
4744 void wxAuiManager::OnChildFocus(wxChildFocusEvent
& event
) 
4746     // when a child pane has it's focus set, we should change the 
4747     // pane's active state to reflect this. (this is only true if 
4748     // active panes are allowed by the owner) 
4749     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4751         wxAuiPaneInfo
& pane 
= GetPane(event
.GetWindow()); 
4752         if (pane
.IsOk() && (pane
.state 
& wxAuiPaneInfo::optionActive
) == 0) 
4754             SetActivePane(event
.GetWindow()); 
4763 // OnPaneButton() is an event handler that is called 
4764 // when a pane button has been pressed. 
4765 void wxAuiManager::OnPaneButton(wxAuiManagerEvent
& evt
) 
4767     wxASSERT_MSG(evt
.pane
, wxT("Pane Info passed to wxAuiManager::OnPaneButton must be non-null")); 
4769     wxAuiPaneInfo
& pane 
= *(evt
.pane
); 
4771     if (evt
.button 
== wxAUI_BUTTON_CLOSE
) 
4773         // fire pane close event 
4774         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
4776         e
.SetPane(evt
.pane
); 
4781             // close the pane, but check that it 
4782             // still exists in our pane array first 
4783             // (the event handler above might have removed it) 
4785             wxAuiPaneInfo
& check 
= GetPane(pane
.window
); 
4794     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& !pane
.IsMaximized()) 
4796         // fire pane maximize event 
4797         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_MAXIMIZE
); 
4799         e
.SetPane(evt
.pane
); 
4808     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& pane
.IsMaximized()) 
4810         // fire pane restore event 
4811         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_RESTORE
); 
4813         e
.SetPane(evt
.pane
); 
4822     else if (evt
.button 
== wxAUI_BUTTON_PIN 
&& 
4823                 (m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && pane
.IsFloatable()) 
4825         if (pane
.IsMaximized()) 
4827             // If the pane is maximized, the original state must be restored 
4828             // before trying to float the pane, otherwise the other panels 
4829             // wouldn't appear correctly when it becomes floating. 
4830             wxAuiManagerEvent 
e(wxEVT_AUI_PANE_RESTORE
); 
4832             e
.SetPane(evt
.pane
); 
4837                 // If it can't be restored, it can't be floated neither.