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" 
  36     #include "wx/settings.h" 
  38     #include "wx/dcclient.h" 
  39     #include "wx/dcscreen.h" 
  40     #include "wx/toolbar.h" 
  45 WX_CHECK_BUILD_OPTIONS("wxAUI") 
  47 #include "wx/arrimpl.cpp" 
  48 WX_DECLARE_OBJARRAY(wxRect
, wxAuiRectArray
); 
  49 WX_DEFINE_OBJARRAY(wxAuiRectArray
) 
  50 WX_DEFINE_OBJARRAY(wxAuiDockUIPartArray
) 
  51 WX_DEFINE_OBJARRAY(wxAuiDockInfoArray
) 
  52 WX_DEFINE_OBJARRAY(wxAuiPaneButtonArray
) 
  53 WX_DEFINE_OBJARRAY(wxAuiPaneInfoArray
) 
  55 wxAuiPaneInfo wxAuiNullPaneInfo
; 
  56 wxAuiDockInfo wxAuiNullDockInfo
; 
  57 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_BUTTON
) 
  58 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_CLOSE
) 
  59 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_MAXIMIZE
) 
  60 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_RESTORE
) 
  61 DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER
) 
  62 DEFINE_EVENT_TYPE(wxEVT_AUI_FIND_MANAGER
) 
  65     // a few defines to avoid nameclashes 
  66     #define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1 
  68     #include "wx/osx/private.h" 
  72     #include "wx/msw/wrapwin.h" 
  73     #include "wx/msw/private.h" 
  74     #include "wx/msw/dc.h" 
  77 IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent
, wxEvent
) 
  78 IMPLEMENT_CLASS(wxAuiManager
, wxEvtHandler
) 
  82 const int auiToolBarLayer 
= 10; 
  87 class wxPseudoTransparentFrame 
: public wxFrame
 
  90     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
  91                 wxWindowID id 
= wxID_ANY
, 
  92                 const wxString
& title 
= wxEmptyString
, 
  93                 const wxPoint
& pos 
= wxDefaultPosition
, 
  94                 const wxSize
& size 
= wxDefaultSize
, 
  95                 long style 
= wxDEFAULT_FRAME_STYLE
, 
  96                 const wxString 
&name 
= wxT("frame")) 
  97                     : wxFrame(parent
, id
, title
, pos
, size
, style 
| wxFRAME_SHAPED
, name
) 
  99         SetBackgroundStyle(wxBG_STYLE_CUSTOM
); 
 106         m_CanSetShape 
= false; // have to wait for window create event on GTK 
 108         m_CanSetShape 
= true; 
 110         m_Region 
= wxRegion(0, 0, 0, 0); 
 114     virtual bool SetTransparent(wxByte alpha
) 
 118             int w
=100; // some defaults 
 120             GetClientSize(&w
, &h
); 
 126 //            m_Region.Union(0, 0, 1, m_MaxWidth); 
 129                 for (int y
=0; y
<m_MaxHeight
; y
++) 
 131                     // Reverse the order of the bottom 4 bits 
 132                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 133                     if ((j
*16+8)<m_Amount
) 
 134                         m_Region
.Union(0, y
, m_MaxWidth
, 1); 
 143     void OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 147         if (m_Region
.IsEmpty()) 
 151         dc
.SetBrush(wxColour(128, 192, 255)); 
 153         dc
.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 155         dc
.SetPen(*wxTRANSPARENT_PEN
); 
 157         wxRegionIterator 
upd(GetUpdateRegion()); // get the update rect list 
 161             wxRect 
rect(upd
.GetRect()); 
 162             dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 169     void OnWindowCreate(wxWindowCreateEvent
& WXUNUSED(event
)) 
 176     void OnSize(wxSizeEvent
& event
) 
 178         // We sometimes get surplus size events 
 179         if ((event
.GetSize().GetWidth() == m_lastWidth
) && 
 180             (event
.GetSize().GetHeight() == m_lastHeight
)) 
 185         m_lastWidth 
= event
.GetSize().GetWidth(); 
 186         m_lastHeight 
= event
.GetSize().GetHeight(); 
 188         SetTransparent(m_Amount
); 
 189         m_Region
.Intersect(0, 0, event
.GetSize().GetWidth(), 
 190                            event
.GetSize().GetHeight()); 
 201     int m_lastWidth
,m_lastHeight
; 
 205     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 206     DECLARE_EVENT_TABLE() 
 210 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 212 BEGIN_EVENT_TABLE(wxPseudoTransparentFrame
, wxFrame
) 
 213     EVT_PAINT(wxPseudoTransparentFrame::OnPaint
) 
 214     EVT_SIZE(wxPseudoTransparentFrame::OnSize
) 
 216     EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate
) 
 227 gtk_pseudo_window_realized_callback( GtkWidget 
*m_widget
, void *WXUNUSED(win
) ) 
 229         wxSize disp 
= wxGetDisplaySize(); 
 232         for (int y
=0; y
<disp
.y
; y
++) 
 234                     // Reverse the order of the bottom 4 bits 
 235                     int j
=((y
&8)?1:0)|((y
&4)?2:0)|((y
&2)?4:0)|((y
&1)?8:0); 
 237                         region
.Union(0, y
, disp
.x
, 1); 
 239         gdk_window_shape_combine_region(m_widget
->window
, region
.GetRegion(), 0, 0); 
 243 class wxPseudoTransparentFrame
: public wxFrame
 
 246     wxPseudoTransparentFrame(wxWindow
* parent 
= NULL
, 
 247                 wxWindowID id 
= wxID_ANY
, 
 248                 const wxString
& title 
= wxEmptyString
, 
 249                 const wxPoint
& pos 
= wxDefaultPosition
, 
 250                 const wxSize
& size 
= wxDefaultSize
, 
 251                 long style 
= wxDEFAULT_FRAME_STYLE
, 
 252                 const wxString 
&name 
= wxT("frame")) 
 254          if (!CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 259         m_widget 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 260         g_object_ref(m_widget
); 
 262         if (parent
) parent
->AddChild(this); 
 264         g_signal_connect( m_widget
, "realize", 
 265                       G_CALLBACK (gtk_pseudo_window_realized_callback
), this ); 
 269         col
.green 
= 192 * 256; 
 270         col
.blue 
= 255 * 256; 
 271         gtk_widget_modify_bg( m_widget
, GTK_STATE_NORMAL
, &col 
); 
 274     bool SetTransparent(wxByte 
WXUNUSED(alpha
)) 
 280     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame
) 
 283 IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame
, wxFrame
) 
 290 // -- static utility functions -- 
 292 static wxBitmap 
wxPaneCreateStippleBitmap() 
 294     unsigned char data
[] = { 0,0,0,192,192,192, 192,192,192,0,0,0 }; 
 295     wxImage 
img(2,2,data
,true); 
 296     return wxBitmap(img
); 
 299 static void DrawResizeHint(wxDC
& dc
, const wxRect
& rect
) 
 301     wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
 302     wxBrush 
brush(stipple
); 
 305     wxMSWDCImpl 
*impl 
= (wxMSWDCImpl
*) dc
.GetImpl(); 
 306     PatBlt(GetHdcOf(*impl
), rect
.GetX(), rect
.GetY(), rect
.GetWidth(), rect
.GetHeight(), PATINVERT
); 
 308     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 310     dc
.SetLogicalFunction(wxXOR
); 
 311     dc
.DrawRectangle(rect
); 
 317 // CopyDocksAndPanes() - this utility function creates copies of 
 318 // the dock and pane info.  wxAuiDockInfo's usually contain pointers 
 319 // to wxAuiPaneInfo classes, thus this function is necessary to reliably 
 320 // reconstruct that relationship in the new dock info and pane info arrays 
 322 static void CopyDocksAndPanes(wxAuiDockInfoArray
& dest_docks
, 
 323                               wxAuiPaneInfoArray
& dest_panes
, 
 324                               const wxAuiDockInfoArray
& src_docks
, 
 325                               const wxAuiPaneInfoArray
& src_panes
) 
 327     dest_docks 
= src_docks
; 
 328     dest_panes 
= src_panes
; 
 329     int i
, j
, k
, dock_count
, pc1
, pc2
; 
 330     for (i 
= 0, dock_count 
= dest_docks
.GetCount(); i 
< dock_count
; ++i
) 
 332         wxAuiDockInfo
& dock 
= dest_docks
.Item(i
); 
 333         for (j 
= 0, pc1 
= dock
.panes
.GetCount(); j 
< pc1
; ++j
) 
 334             for (k 
= 0, pc2 
= src_panes
.GetCount(); k 
< pc2
; ++k
) 
 335                 if (dock
.panes
.Item(j
) == &src_panes
.Item(k
)) 
 336                     dock
.panes
.Item(j
) = &dest_panes
.Item(k
); 
 340 // GetMaxLayer() is an internal function which returns 
 341 // the highest layer inside the specified dock 
 342 static int GetMaxLayer(const wxAuiDockInfoArray
& docks
, 
 345     int i
, dock_count
, max_layer 
= 0; 
 346     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 348         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
 349         if (dock
.dock_direction 
== dock_direction 
&& 
 350             dock
.dock_layer 
> max_layer 
&& !dock
.fixed
) 
 351                 max_layer 
= dock
.dock_layer
; 
 357 // GetMaxRow() is an internal function which returns 
 358 // the highest layer inside the specified dock 
 359 static int GetMaxRow(const wxAuiPaneInfoArray
& panes
, int direction
, int layer
) 
 361     int i
, pane_count
, max_row 
= 0; 
 362     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 364         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 365         if (pane
.dock_direction 
== direction 
&& 
 366             pane
.dock_layer 
== layer 
&& 
 367             pane
.dock_row 
> max_row
) 
 368                 max_row 
= pane
.dock_row
; 
 375 // DoInsertDockLayer() is an internal function that inserts a new dock 
 376 // layer by incrementing all existing dock layer values by one 
 377 static void DoInsertDockLayer(wxAuiPaneInfoArray
& panes
, 
 382     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 384         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 385         if (!pane
.IsFloating() && 
 386             pane
.dock_direction 
== dock_direction 
&& 
 387             pane
.dock_layer 
>= dock_layer
) 
 392 // DoInsertDockLayer() is an internal function that inserts a new dock 
 393 // row by incrementing all existing dock row values by one 
 394 static void DoInsertDockRow(wxAuiPaneInfoArray
& panes
, 
 400     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 402         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 403         if (!pane
.IsFloating() && 
 404             pane
.dock_direction 
== dock_direction 
&& 
 405             pane
.dock_layer 
== dock_layer 
&& 
 406             pane
.dock_row 
>= dock_row
) 
 411 // DoInsertDockLayer() is an internal function that inserts a space for 
 412 // another dock pane by incrementing all existing dock row values by one 
 413 static void DoInsertPane(wxAuiPaneInfoArray
& panes
, 
 420     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 422         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 423         if (!pane
.IsFloating() && 
 424             pane
.dock_direction 
== dock_direction 
&& 
 425             pane
.dock_layer 
== dock_layer 
&& 
 426             pane
.dock_row 
== dock_row 
&& 
 427             pane
.dock_pos 
>= dock_pos
) 
 432 // FindDocks() is an internal function that returns a list of docks which meet 
 433 // the specified conditions in the parameters and returns a sorted array 
 434 // (sorted by layer and then row) 
 435 static void FindDocks(wxAuiDockInfoArray
& docks
, 
 439                       wxAuiDockInfoPtrArray
& arr
) 
 441     int begin_layer 
= dock_layer
; 
 442     int end_layer 
= dock_layer
; 
 443     int begin_row 
= dock_row
; 
 444     int end_row 
= dock_row
; 
 445     int dock_count 
= docks
.GetCount(); 
 446     int layer
, row
, i
, max_row 
= 0, max_layer 
= 0; 
 448     // discover the maximum dock layer and the max row 
 449     for (i 
= 0; i 
< dock_count
; ++i
) 
 451         max_row 
= wxMax(max_row
, docks
.Item(i
).dock_row
); 
 452         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
 455     // if no dock layer was specified, search all dock layers 
 456     if (dock_layer 
== -1) 
 459         end_layer 
= max_layer
; 
 462     // if no dock row was specified, search all dock row 
 471     for (layer 
= begin_layer
; layer 
<= end_layer
; ++layer
) 
 472         for (row 
= begin_row
; row 
<= end_row
; ++row
) 
 473             for (i 
= 0; i 
< dock_count
; ++i
) 
 475                 wxAuiDockInfo
& d 
= docks
.Item(i
); 
 476                 if (dock_direction 
== -1 || dock_direction 
== d
.dock_direction
) 
 478                     if (d
.dock_layer 
== layer 
&& d
.dock_row 
== row
) 
 484 // FindPaneInDock() looks up a specified window pointer inside a dock. 
 485 // If found, the corresponding wxAuiPaneInfo pointer is returned, otherwise NULL. 
 486 static wxAuiPaneInfo
* FindPaneInDock(const wxAuiDockInfo
& dock
, wxWindow
* window
) 
 488     int i
, count 
= dock
.panes
.GetCount(); 
 489     for (i 
= 0; i 
< count
; ++i
) 
 491         wxAuiPaneInfo
* p 
= dock
.panes
.Item(i
); 
 492         if (p
->window 
== window
) 
 498 // RemovePaneFromDocks() removes a pane window from all docks 
 499 // with a possible exception specified by parameter "ex_cept" 
 500 static void RemovePaneFromDocks(wxAuiDockInfoArray
& docks
, 
 502                                 wxAuiDockInfo
* ex_cept  
= NULL  
) 
 505     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
 507         wxAuiDockInfo
& d 
= docks
.Item(i
); 
 510         wxAuiPaneInfo
* pi 
= FindPaneInDock(d
, pane
.window
); 
 517 // This function works fine, and may be used in the future 
 519 // RenumberDockRows() takes a dock and assigns sequential numbers 
 520 // to existing rows.  Basically it takes out the gaps; so if a 
 521 // dock has rows with numbers 0,2,5, they will become 0,1,2 
 522 static void RenumberDockRows(wxAuiDockInfoPtrArray& docks) 
 525     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) 
 527         wxAuiDockInfo& dock = *docks.Item(i); 
 531         for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j) 
 532             dock.panes.Item(j)->dock_row = i; 
 538 // SetActivePane() sets the active pane, as well as cycles through 
 539 // every other pane and makes sure that all others' active flags 
 541 static void SetActivePane(wxAuiPaneInfoArray
& panes
, wxWindow
* active_pane
) 
 544     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
 546         wxAuiPaneInfo
& pane 
= panes
.Item(i
); 
 547         pane
.state 
&= ~wxAuiPaneInfo::optionActive
; 
 548         if (pane
.window 
== active_pane
) 
 549             pane
.state 
|= wxAuiPaneInfo::optionActive
; 
 554 // this function is used to sort panes by dock position 
 555 static int PaneSortFunc(wxAuiPaneInfo
** p1
, wxAuiPaneInfo
** p2
) 
 557     return ((*p1
)->dock_pos 
< (*p2
)->dock_pos
) ? -1 : 1; 
 561 // -- wxAuiManager class implementation -- 
 564 BEGIN_EVENT_TABLE(wxAuiManager
, wxEvtHandler
) 
 565     EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton
) 
 566     EVT_AUI_RENDER(wxAuiManager::OnRender
) 
 567     EVT_PAINT(wxAuiManager::OnPaint
) 
 568     EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground
) 
 569     EVT_SIZE(wxAuiManager::OnSize
) 
 570     EVT_SET_CURSOR(wxAuiManager::OnSetCursor
) 
 571     EVT_LEFT_DOWN(wxAuiManager::OnLeftDown
) 
 572     EVT_LEFT_UP(wxAuiManager::OnLeftUp
) 
 573     EVT_MOTION(wxAuiManager::OnMotion
) 
 574     EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow
) 
 575     EVT_MOUSE_CAPTURE_LOST(wxAuiManager::OnCaptureLost
) 
 576     EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus
) 
 577     EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager
) 
 578     EVT_TIMER(101, wxAuiManager::OnHintFadeTimer
) 
 582 wxAuiManager::wxAuiManager(wxWindow
* managed_wnd
, unsigned int flags
) 
 584     m_action 
= actionNone
; 
 585     m_last_mouse_move 
= wxPoint(); 
 586     m_hover_button 
= NULL
; 
 587     m_art 
= new wxAuiDefaultDockArt
; 
 591     m_has_maximized 
= false; 
 593     m_dock_constraint_x 
= 0.3; 
 594     m_dock_constraint_y 
= 0.3; 
 596     m_currentDragItem 
= -1; 
 600         SetManagedWindow(managed_wnd
); 
 604 wxAuiManager::~wxAuiManager() 
 606     // NOTE: It's possible that the windows have already been destroyed by the 
 607     // time this dtor is called, so this loop can result in memory access via 
 608     // invalid pointers, resulting in a crash.  So it will be disabled while 
 609     // waiting for a better solution. 
 611     for ( size_t i 
= 0; i 
< m_panes
.size(); i
++ ) 
 613         wxAuiPaneInfo
& pinfo 
= m_panes
[i
]; 
 614         if (pinfo
.window 
&& !pinfo
.window
->GetParent()) 
 622 // creates a floating frame for the windows 
 623 wxAuiFloatingFrame
* wxAuiManager::CreateFloatingFrame(wxWindow
* parent
, 
 624                                                       const wxAuiPaneInfo
& pane_info
) 
 626     return new wxAuiFloatingFrame(parent
, this, pane_info
); 
 629 bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo 
& WXUNUSED(p
)) 
 631     // if a key modifier is pressed while dragging the frame, 
 632     // don't dock the window 
 633     return !(wxGetKeyState(WXK_CONTROL
) || wxGetKeyState(WXK_ALT
)); 
 636 // GetPane() looks up a wxAuiPaneInfo structure based 
 637 // on the supplied window pointer.  Upon failure, GetPane() 
 638 // returns an empty wxAuiPaneInfo, a condition which can be checked 
 639 // by calling wxAuiPaneInfo::IsOk(). 
 641 // The pane info's structure may then be modified.  Once a pane's 
 642 // info is modified, wxAuiManager::Update() must be called to 
 643 // realize the changes in the UI. 
 645 wxAuiPaneInfo
& wxAuiManager::GetPane(wxWindow
* window
) 
 648     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 650         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 651         if (p
.window 
== window
) 
 654     return wxAuiNullPaneInfo
; 
 657 // this version of GetPane() looks up a pane based on a 
 658 // 'pane name', see above comment for more info 
 659 wxAuiPaneInfo
& wxAuiManager::GetPane(const wxString
& name
) 
 662     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
 664         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
 668     return wxAuiNullPaneInfo
; 
 671 // GetAllPanes() returns a reference to all the pane info structures 
 672 wxAuiPaneInfoArray
& wxAuiManager::GetAllPanes() 
 677 // HitTest() is an internal function which determines 
 678 // which UI item the specified coordinates are over 
 679 // (x,y) specify a position in client coordinates 
 680 wxAuiDockUIPart
* wxAuiManager::HitTest(int x
, int y
) 
 682     wxAuiDockUIPart
* result 
= NULL
; 
 685     for (i 
= 0, part_count 
= m_uiparts
.GetCount(); i 
< part_count
; ++i
) 
 687         wxAuiDockUIPart
* item 
= &m_uiparts
.Item(i
); 
 689         // we are not interested in typeDock, because this space 
 690         // isn't used to draw anything, just for measurements; 
 691         // besides, the entire dock area is covered with other 
 692         // rectangles, which we are interested in. 
 693         if (item
->type 
== wxAuiDockUIPart::typeDock
) 
 696         // if we already have a hit on a more specific item, we are not 
 697         // interested in a pane hit.  If, however, we don't already have 
 698         // a hit, returning a pane hit is necessary for some operations 
 699         if ((item
->type 
== wxAuiDockUIPart::typePane 
|| 
 700             item
->type 
== wxAuiDockUIPart::typePaneBorder
) && result
) 
 703         // if the point is inside the rectangle, we have a hit 
 704         if (item
->rect
.Contains(x
,y
)) 
 712 // SetFlags() and GetFlags() allow the owner to set various 
 713 // options which are global to wxAuiManager 
 714 void wxAuiManager::SetFlags(unsigned int flags
) 
 716     // find out if we have to call UpdateHintWindowConfig() 
 717     bool update_hint_wnd 
= false; 
 718     unsigned int hint_mask 
= wxAUI_MGR_TRANSPARENT_HINT 
| 
 719                              wxAUI_MGR_VENETIAN_BLINDS_HINT 
| 
 720                              wxAUI_MGR_RECTANGLE_HINT
; 
 721     if ((flags 
& hint_mask
) != (m_flags 
& hint_mask
)) 
 722         update_hint_wnd 
= true; 
 730         UpdateHintWindowConfig(); 
 734 unsigned int wxAuiManager::GetFlags() const 
 739 // Convenience function 
 740 bool wxAuiManager_HasLiveResize(wxAuiManager
& manager
) 
 742     // With Core Graphics on Mac, it's not possible to show sash feedback, 
 743     // so we'll always use live update instead. 
 744 #if defined(__WXMAC__) 
 747     return (manager
.GetFlags() & wxAUI_MGR_LIVE_RESIZE
) == wxAUI_MGR_LIVE_RESIZE
; 
 751 // don't use these anymore as they are deprecated 
 752 // use Set/GetManagedFrame() instead 
 753 void wxAuiManager::SetFrame(wxFrame
* frame
) 
 755     SetManagedWindow((wxWindow
*)frame
); 
 758 wxFrame
* wxAuiManager::GetFrame() const 
 760     return (wxFrame
*)m_frame
; 
 764 // this function will return the aui manager for a given 
 765 // window.  The |window| parameter should be any child window 
 766 // or grand-child window (and so on) of the frame/window 
 767 // managed by wxAuiManager.  The |window| parameter does not 
 768 // need to be managed by the manager itself. 
 769 wxAuiManager
* wxAuiManager::GetManager(wxWindow
* window
) 
 771     wxAuiManagerEvent 
evt(wxEVT_AUI_FIND_MANAGER
); 
 772     evt
.SetManager(NULL
); 
 773     evt
.ResumePropagation(wxEVENT_PROPAGATE_MAX
); 
 774     if (!window
->ProcessEvent(evt
)) 
 777     return evt
.GetManager(); 
 781 void wxAuiManager::UpdateHintWindowConfig() 
 783     // find out if the the system can do transparent frames 
 784     bool can_do_transparent 
= false; 
 786     wxWindow
* w 
= m_frame
; 
 789         if (w
->IsKindOf(CLASSINFO(wxFrame
))) 
 791             wxFrame
* f 
= static_cast<wxFrame
*>(w
); 
 792             can_do_transparent 
= f
->CanSetTransparent(); 
 800     // if there is an existing hint window, delete it 
 803         m_hint_wnd
->Destroy(); 
 810     if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) && can_do_transparent
) 
 812         // Make a window to use for a transparent hint 
 813         #if defined(__WXMSW__) || defined(__WXGTK__) 
 814             m_hint_wnd 
= new wxFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 815                                      wxDefaultPosition
, wxSize(1,1), 
 816                                          wxFRAME_TOOL_WINDOW 
| 
 817                                          wxFRAME_FLOAT_ON_PARENT 
| 
 821             m_hint_wnd
->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION
)); 
 822         #elif defined(__WXMAC__) 
 823             // Using a miniframe with float and tool styles keeps the parent 
 824             // frame activated and highlighted as such... 
 825             m_hint_wnd 
= new wxMiniFrame(m_frame
, wxID_ANY
, wxEmptyString
, 
 826                                          wxDefaultPosition
, wxSize(1,1), 
 827                                          wxFRAME_FLOAT_ON_PARENT
 
 828                                          | wxFRAME_TOOL_WINDOW 
); 
 829             m_hint_wnd
->Connect(wxEVT_ACTIVATE
, 
 830                 wxActivateEventHandler(wxAuiManager::OnHintActivate
), NULL
, this); 
 832             // Can't set the bg colour of a Frame in wxMac 
 833             wxPanel
* p 
= new wxPanel(m_hint_wnd
); 
 835             // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver 
 836             // color that is really hard to see, especially transparent. 
 837             // Until a better system color is decided upon we'll just use 
 839             p
->SetBackgroundColour(*wxBLUE
); 
 845         if ((m_flags 
& wxAUI_MGR_TRANSPARENT_HINT
) != 0 || 
 846             (m_flags 
& wxAUI_MGR_VENETIAN_BLINDS_HINT
) != 0) 
 848             // system can't support transparent fade, or the venetian 
 849             // blinds effect was explicitly requested 
 850             m_hint_wnd 
= new wxPseudoTransparentFrame(m_frame
, 
 855                                                             wxFRAME_TOOL_WINDOW 
| 
 856                                                             wxFRAME_FLOAT_ON_PARENT 
| 
 859             m_hint_fademax 
= 128; 
 865 // SetManagedWindow() is usually called once when the frame 
 866 // manager class is being initialized.  "frame" specifies 
 867 // the frame which should be managed by the frame mananger 
 868 void wxAuiManager::SetManagedWindow(wxWindow
* wnd
) 
 870     wxASSERT_MSG(wnd
, wxT("specified window must be non-NULL")); 
 873     m_frame
->PushEventHandler(this); 
 876     // if the owner is going to manage an MDI parent frame, 
 877     // we need to add the MDI client window as the default 
 880     if (m_frame
->IsKindOf(CLASSINFO(wxMDIParentFrame
))) 
 882         wxMDIParentFrame
* mdi_frame 
= (wxMDIParentFrame
*)m_frame
; 
 883         wxWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 885         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 887         AddPane(client_window
, 
 888                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 889                 CenterPane().PaneBorder(false)); 
 891     else if (m_frame
->IsKindOf(CLASSINFO(wxAuiMDIParentFrame
))) 
 893         wxAuiMDIParentFrame
* mdi_frame 
= (wxAuiMDIParentFrame
*)m_frame
; 
 894         wxAuiMDIClientWindow
* client_window 
= mdi_frame
->GetClientWindow(); 
 895         wxASSERT_MSG(client_window
, wxT("Client window is NULL!")); 
 897         AddPane(client_window
, 
 898                 wxAuiPaneInfo().Name(wxT("mdiclient")). 
 899                 CenterPane().PaneBorder(false)); 
 904     UpdateHintWindowConfig(); 
 908 // UnInit() must be called, usually in the destructor 
 909 // of the frame class.   If it is not called, usually this 
 910 // will result in a crash upon program exit 
 911 void wxAuiManager::UnInit() 
 915         m_frame
->RemoveEventHandler(this); 
 919 // GetManagedWindow() returns the window pointer being managed 
 920 wxWindow
* wxAuiManager::GetManagedWindow() const 
 925 wxAuiDockArt
* wxAuiManager::GetArtProvider() const 
 930 void wxAuiManager::ProcessMgrEvent(wxAuiManagerEvent
& event
) 
 932     // first, give the owner frame a chance to override 
 935         if (m_frame
->ProcessEvent(event
)) 
 942 // SetArtProvider() instructs wxAuiManager to use the 
 943 // specified art provider for all drawing calls.  This allows 
 944 // plugable look-and-feel features.  The pointer that is 
 945 // passed to this method subsequently belongs to wxAuiManager, 
 946 // and is deleted in the frame manager destructor 
 947 void wxAuiManager::SetArtProvider(wxAuiDockArt
* art_provider
) 
 949     // delete the last art provider, if any 
 952     // assign the new art provider 
 953     m_art 
= art_provider
; 
 957 bool wxAuiManager::AddPane(wxWindow
* window
, const wxAuiPaneInfo
& pane_info
) 
 959     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
 961     // check if the pane has a valid window 
 965     // check if the window is already managed by us 
 966     if (GetPane(pane_info
.window
).IsOk()) 
 969     // check if the pane name already exists, this could reveal a 
 970     // bug in the library user's application 
 971     bool already_exists 
= false; 
 972     if (!pane_info
.name
.empty() && GetPane(pane_info
.name
).IsOk()) 
 974         wxFAIL_MSG(wxT("A pane with that name already exists in the manager!")); 
 975         already_exists 
= true; 
 978     // if the new pane is docked then we should undo maximize 
 979     if (pane_info
.IsDocked()) 
 980         RestoreMaximizedPane(); 
 982     m_panes
.Add(pane_info
); 
 984     wxAuiPaneInfo
& pinfo 
= m_panes
.Last(); 
 986     // set the pane window 
 987     pinfo
.window 
= window
; 
 990     // if the pane's name identifier is blank, create a random string 
 991     if (pinfo
.name
.empty() || already_exists
) 
 993         pinfo
.name
.Printf(wxT("%08lx%08x%08x%08lx"), 
 994              wxPtrToUInt(pinfo
.window
) & 0xffffffff, 
 995              (unsigned int)time(NULL
), 
 997              (unsigned int)GetTickCount(), 
 999              (unsigned int)clock(), 
1001              (unsigned long)m_panes
.GetCount()); 
1004     // set initial proportion (if not already set) 
1005     if (pinfo
.dock_proportion 
== 0) 
1006         pinfo
.dock_proportion 
= 100000; 
1008     if (pinfo
.HasMaximizeButton()) 
1010         wxAuiPaneButton button
; 
1011         button
.button_id 
= wxAUI_BUTTON_MAXIMIZE_RESTORE
; 
1012         pinfo
.buttons
.Add(button
); 
1015     if (pinfo
.HasPinButton()) 
1017         wxAuiPaneButton button
; 
1018         button
.button_id 
= wxAUI_BUTTON_PIN
; 
1019         pinfo
.buttons
.Add(button
); 
1022     if (pinfo
.HasCloseButton()) 
1024         wxAuiPaneButton button
; 
1025         button
.button_id 
= wxAUI_BUTTON_CLOSE
; 
1026         pinfo
.buttons
.Add(button
); 
1029     if (pinfo
.HasGripper()) 
1031         if (pinfo
.window
->IsKindOf(CLASSINFO(wxAuiToolBar
))) 
1033             // prevent duplicate gripper -- both wxAuiManager and wxAuiToolBar 
1034             // have a gripper control.  The toolbar's built-in gripper 
1035             // meshes better with the look and feel of the control than ours, 
1036             // so turn wxAuiManager's gripper off, and the toolbar's on. 
1038             wxAuiToolBar
* tb 
= static_cast<wxAuiToolBar
*>(pinfo
.window
); 
1039             pinfo
.SetFlag(wxAuiPaneInfo::optionGripper
, false); 
1040             tb
->SetGripperVisible(true); 
1045     if (pinfo
.best_size 
== wxDefaultSize 
&& 
1048         pinfo
.best_size 
= pinfo
.window
->GetClientSize(); 
1050         if (pinfo
.window
->IsKindOf(CLASSINFO(wxToolBar
))) 
1052             // GetClientSize() doesn't get the best size for 
1053             // a toolbar under some newer versions of wxWidgets, 
1054             // so use GetBestSize() 
1055             pinfo
.best_size 
= pinfo
.window
->GetBestSize(); 
1057             // for some reason, wxToolBar::GetBestSize() is returning 
1058             // a size that is a pixel shy of the correct amount. 
1059             // I believe this to be the correct action, until 
1060             // wxToolBar::GetBestSize() is fixed.  Is this assumption 
1062             // commented out by JACS 2007-9-08 after having added a pixel in wxMSW's wxToolBar::DoGetBestSize() 
1063             // pinfo.best_size.y++; 
1066         if (pinfo
.min_size 
!= wxDefaultSize
) 
1068             if (pinfo
.best_size
.x 
< pinfo
.min_size
.x
) 
1069                 pinfo
.best_size
.x 
= pinfo
.min_size
.x
; 
1070             if (pinfo
.best_size
.y 
< pinfo
.min_size
.y
) 
1071                 pinfo
.best_size
.y 
= pinfo
.min_size
.y
; 
1080 bool wxAuiManager::AddPane(wxWindow
* window
, 
1082                            const wxString
& caption
) 
1084     wxAuiPaneInfo pinfo
; 
1085     pinfo
.Caption(caption
); 
1088         case wxTOP
:    pinfo
.Top(); break; 
1089         case wxBOTTOM
: pinfo
.Bottom(); break; 
1090         case wxLEFT
:   pinfo
.Left(); break; 
1091         case wxRIGHT
:  pinfo
.Right(); break; 
1092         case wxCENTER
: pinfo
.CenterPane(); break; 
1094     return AddPane(window
, pinfo
); 
1097 bool wxAuiManager::AddPane(wxWindow
* window
, 
1098                            const wxAuiPaneInfo
& pane_info
, 
1099                            const wxPoint
& drop_pos
) 
1101     if (!AddPane(window
, pane_info
)) 
1104     wxAuiPaneInfo
& pane 
= GetPane(window
); 
1106     DoDrop(m_docks
, m_panes
, pane
, drop_pos
, wxPoint(0,0)); 
1111 bool wxAuiManager::InsertPane(wxWindow
* window
, const wxAuiPaneInfo
& pane_info
, 
1114     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1116     // shift the panes around, depending on the insert level 
1117     switch (insert_level
) 
1119         case wxAUI_INSERT_PANE
: 
1120             DoInsertPane(m_panes
, 
1121                  pane_info
.dock_direction
, 
1122                  pane_info
.dock_layer
, 
1124                  pane_info
.dock_pos
); 
1126         case wxAUI_INSERT_ROW
: 
1127             DoInsertDockRow(m_panes
, 
1128                  pane_info
.dock_direction
, 
1129                  pane_info
.dock_layer
, 
1130                  pane_info
.dock_row
); 
1132         case wxAUI_INSERT_DOCK
: 
1133             DoInsertDockLayer(m_panes
, 
1134                  pane_info
.dock_direction
, 
1135                  pane_info
.dock_layer
); 
1139     // if the window already exists, we are basically just moving/inserting the 
1140     // existing window.  If it doesn't exist, we need to add it and insert it 
1141     wxAuiPaneInfo
& existing_pane 
= GetPane(window
); 
1142     if (!existing_pane
.IsOk()) 
1144         return AddPane(window
, pane_info
); 
1148         if (pane_info
.IsFloating()) 
1150             existing_pane
.Float(); 
1151             if (pane_info
.floating_pos 
!= wxDefaultPosition
) 
1152                 existing_pane
.FloatingPosition(pane_info
.floating_pos
); 
1153             if (pane_info
.floating_size 
!= wxDefaultSize
) 
1154                 existing_pane
.FloatingSize(pane_info
.floating_size
); 
1158             // if the new pane is docked then we should undo maximize 
1159             RestoreMaximizedPane(); 
1161             existing_pane
.Direction(pane_info
.dock_direction
); 
1162             existing_pane
.Layer(pane_info
.dock_layer
); 
1163             existing_pane
.Row(pane_info
.dock_row
); 
1164             existing_pane
.Position(pane_info
.dock_pos
); 
1172 // DetachPane() removes a pane from the frame manager.  This 
1173 // method will not destroy the window that is removed. 
1174 bool wxAuiManager::DetachPane(wxWindow
* window
) 
1176     wxASSERT_MSG(window
, wxT("NULL window ptrs are not allowed")); 
1179     for (i 
= 0, count 
= m_panes
.GetCount(); i 
< count
; ++i
) 
1181         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1182         if (p
.window 
== window
) 
1186                 // we have a floating frame which is being detached. We need to 
1187                 // reparent it to m_frame and destroy the floating frame 
1190                 p
.window
->SetSize(1,1); 
1192                 if (p
.frame
->IsShown()) 
1193                     p
.frame
->Show(false); 
1195                 // reparent to m_frame and destroy the pane 
1196                 if (m_action_window 
== p
.frame
) 
1198                     m_action_window 
= NULL
; 
1201                 p
.window
->Reparent(m_frame
); 
1202                 p
.frame
->SetSizer(NULL
); 
1207             // make sure there are no references to this pane in our uiparts, 
1208             // just in case the caller doesn't call Update() immediately after 
1209             // the DetachPane() call.  This prevets obscure crashes which would 
1210             // happen at window repaint if the caller forgets to call Update() 
1212             for (pi 
= 0, part_count 
= (int)m_uiparts
.GetCount(); pi 
< part_count
; ++pi
) 
1214                 wxAuiDockUIPart
& part 
= m_uiparts
.Item(pi
); 
1215                 if (part
.pane 
== &p
) 
1217                     m_uiparts
.RemoveAt(pi
); 
1224             m_panes
.RemoveAt(i
); 
1231 // ClosePane() destroys or hides the pane depending on its flags 
1232 void wxAuiManager::ClosePane(wxAuiPaneInfo
& pane_info
) 
1234     // if we were maximized, restore 
1235     if (pane_info
.IsMaximized()) 
1237         RestorePane(pane_info
); 
1240     // first, hide the window 
1241     if (pane_info
.window 
&& pane_info
.window
->IsShown()) 
1243         pane_info
.window
->Show(false); 
1246     // make sure that we are the parent of this window 
1247     if (pane_info
.window 
&& pane_info
.window
->GetParent() != m_frame
) 
1249         pane_info
.window
->Reparent(m_frame
); 
1252     // if we have a frame, destroy it 
1253     if (pane_info
.frame
) 
1255         pane_info
.frame
->Destroy(); 
1256         pane_info
.frame 
= NULL
; 
1259     // now we need to either destroy or hide the pane 
1260     if (pane_info
.IsDestroyOnClose()) 
1262         wxWindow 
* window 
= pane_info
.window
; 
1275 void wxAuiManager::MaximizePane(wxAuiPaneInfo
& pane_info
) 
1279     // un-maximize and hide all other panes 
1280     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1282         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1287             // save hidden state 
1288             p
.SetFlag(wxAuiPaneInfo::savedHiddenState
, 
1289                       p
.HasFlag(wxAuiPaneInfo::optionHidden
)); 
1291             // hide the pane, because only the newly 
1292             // maximized pane should show 
1297     // mark ourselves maximized 
1298     pane_info
.Maximize(); 
1300     m_has_maximized 
= true; 
1302     // last, show the window 
1303     if (pane_info
.window 
&& !pane_info
.window
->IsShown()) 
1305         pane_info
.window
->Show(true); 
1309 void wxAuiManager::RestorePane(wxAuiPaneInfo
& pane_info
) 
1313     // restore all the panes 
1314     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1316         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1319             p
.SetFlag(wxAuiPaneInfo::optionHidden
, 
1320                       p
.HasFlag(wxAuiPaneInfo::savedHiddenState
)); 
1324     // mark ourselves non-maximized 
1325     pane_info
.Restore(); 
1326     m_has_maximized 
= false; 
1328     // last, show the window 
1329     if (pane_info
.window 
&& !pane_info
.window
->IsShown()) 
1331         pane_info
.window
->Show(true); 
1335 void wxAuiManager::RestoreMaximizedPane() 
1339     // restore all the panes 
1340     for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
1342         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
1343         if (p
.IsMaximized()) 
1351 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|" 
1352 // in the input string.  This is an internal functions which is 
1353 // used for saving perspectives 
1354 static wxString 
EscapeDelimiters(const wxString
& s
) 
1357     result
.Alloc(s
.length()); 
1358     const wxChar
* ch 
= s
.c_str(); 
1361         if (*ch 
== wxT(';') || *ch 
== wxT('|')) 
1362             result 
+= wxT('\\'); 
1369 wxString 
wxAuiManager::SavePaneInfo(wxAuiPaneInfo
& pane
) 
1371     wxString result 
= wxT("name="); 
1372     result 
+= EscapeDelimiters(pane
.name
); 
1375     result 
+= wxT("caption="); 
1376     result 
+= EscapeDelimiters(pane
.caption
); 
1379     result 
+= wxString::Format(wxT("state=%u;"), pane
.state
); 
1380     result 
+= wxString::Format(wxT("dir=%d;"), pane
.dock_direction
); 
1381     result 
+= wxString::Format(wxT("layer=%d;"), pane
.dock_layer
); 
1382     result 
+= wxString::Format(wxT("row=%d;"), pane
.dock_row
); 
1383     result 
+= wxString::Format(wxT("pos=%d;"), pane
.dock_pos
); 
1384     result 
+= wxString::Format(wxT("prop=%d;"), pane
.dock_proportion
); 
1385     result 
+= wxString::Format(wxT("bestw=%d;"), pane
.best_size
.x
); 
1386     result 
+= wxString::Format(wxT("besth=%d;"), pane
.best_size
.y
); 
1387     result 
+= wxString::Format(wxT("minw=%d;"), pane
.min_size
.x
); 
1388     result 
+= wxString::Format(wxT("minh=%d;"), pane
.min_size
.y
); 
1389     result 
+= wxString::Format(wxT("maxw=%d;"), pane
.max_size
.x
); 
1390     result 
+= wxString::Format(wxT("maxh=%d;"), pane
.max_size
.y
); 
1391     result 
+= wxString::Format(wxT("floatx=%d;"), pane
.floating_pos
.x
); 
1392     result 
+= wxString::Format(wxT("floaty=%d;"), pane
.floating_pos
.y
); 
1393     result 
+= wxString::Format(wxT("floatw=%d;"), pane
.floating_size
.x
); 
1394     result 
+= wxString::Format(wxT("floath=%d"), pane
.floating_size
.y
); 
1399 // Load a "pane" with the pane infor settings in pane_part 
1400 void wxAuiManager::LoadPaneInfo(wxString pane_part
, wxAuiPaneInfo 
&pane
) 
1402     // replace escaped characters so we can 
1403     // split up the string easily 
1404     pane_part
.Replace(wxT("\\|"), wxT("\a")); 
1405     pane_part
.Replace(wxT("\\;"), wxT("\b")); 
1409         wxString val_part 
= pane_part
.BeforeFirst(wxT(';')); 
1410         pane_part 
= pane_part
.AfterFirst(wxT(';')); 
1411         wxString val_name 
= val_part
.BeforeFirst(wxT('=')); 
1412         wxString value 
= val_part
.AfterFirst(wxT('=')); 
1413         val_name
.MakeLower(); 
1414         val_name
.Trim(true); 
1415         val_name
.Trim(false); 
1419         if (val_name
.empty()) 
1422         if (val_name 
== wxT("name")) 
1424         else if (val_name 
== wxT("caption")) 
1425             pane
.caption 
= value
; 
1426         else if (val_name 
== wxT("state")) 
1427             pane
.state 
= (unsigned int)wxAtoi(value
.c_str()); 
1428         else if (val_name 
== wxT("dir")) 
1429             pane
.dock_direction 
= wxAtoi(value
.c_str()); 
1430         else if (val_name 
== wxT("layer")) 
1431             pane
.dock_layer 
= wxAtoi(value
.c_str()); 
1432         else if (val_name 
== wxT("row")) 
1433             pane
.dock_row 
= wxAtoi(value
.c_str()); 
1434         else if (val_name 
== wxT("pos")) 
1435             pane
.dock_pos 
= wxAtoi(value
.c_str()); 
1436         else if (val_name 
== wxT("prop")) 
1437             pane
.dock_proportion 
= wxAtoi(value
.c_str()); 
1438         else if (val_name 
== wxT("bestw")) 
1439             pane
.best_size
.x 
= wxAtoi(value
.c_str()); 
1440         else if (val_name 
== wxT("besth")) 
1441             pane
.best_size
.y 
= wxAtoi(value
.c_str()); 
1442         else if (val_name 
== wxT("minw")) 
1443             pane
.min_size
.x 
= wxAtoi(value
.c_str()); 
1444         else if (val_name 
== wxT("minh")) 
1445             pane
.min_size
.y 
= wxAtoi(value
.c_str()); 
1446         else if (val_name 
== wxT("maxw")) 
1447             pane
.max_size
.x 
= wxAtoi(value
.c_str()); 
1448         else if (val_name 
== wxT("maxh")) 
1449             pane
.max_size
.y 
= wxAtoi(value
.c_str()); 
1450         else if (val_name 
== wxT("floatx")) 
1451             pane
.floating_pos
.x 
= wxAtoi(value
.c_str()); 
1452         else if (val_name 
== wxT("floaty")) 
1453             pane
.floating_pos
.y 
= wxAtoi(value
.c_str()); 
1454         else if (val_name 
== wxT("floatw")) 
1455             pane
.floating_size
.x 
= wxAtoi(value
.c_str()); 
1456         else if (val_name 
== wxT("floath")) 
1457             pane
.floating_size
.y 
= wxAtoi(value
.c_str()); 
1459             wxFAIL_MSG(wxT("Bad Perspective String")); 
1463     // replace escaped characters so we can 
1464     // split up the string easily 
1465     pane
.name
.Replace(wxT("\a"), wxT("|")); 
1466     pane
.name
.Replace(wxT("\b"), wxT(";")); 
1467     pane
.caption
.Replace(wxT("\a"), wxT("|")); 
1468     pane
.caption
.Replace(wxT("\b"), wxT(";")); 
1469     pane_part
.Replace(wxT("\a"), wxT("|")); 
1470     pane_part
.Replace(wxT("\b"), wxT(";")); 
1476 // SavePerspective() saves all pane information as a single string. 
1477 // This string may later be fed into LoadPerspective() to restore 
1478 // all pane settings.  This save and load mechanism allows an 
1479 // exact pane configuration to be saved and restored at a later time 
1481 wxString 
wxAuiManager::SavePerspective() 
1485     result 
= wxT("layout2|"); 
1487     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1488     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1490         wxAuiPaneInfo
& pane 
= m_panes
.Item(pane_i
); 
1491         result 
+= SavePaneInfo(pane
)+wxT("|"); 
1494     int dock_i
, dock_count 
= m_docks
.GetCount(); 
1495     for (dock_i 
= 0; dock_i 
< dock_count
; ++dock_i
) 
1497         wxAuiDockInfo
& dock 
= m_docks
.Item(dock_i
); 
1499         result 
+= wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"), 
1500                                    dock
.dock_direction
, dock
.dock_layer
, 
1501                                    dock
.dock_row
, dock
.size
); 
1507 // LoadPerspective() loads a layout which was saved with SavePerspective() 
1508 // If the "update" flag parameter is true, the GUI will immediately be updated 
1510 bool wxAuiManager::LoadPerspective(const wxString
& layout
, bool update
) 
1512     wxString input 
= layout
; 
1515     // check layout string version 
1516     //    'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 
1517     //    'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) 
1518     part 
= input
.BeforeFirst(wxT('|')); 
1519     input 
= input
.AfterFirst(wxT('|')); 
1522     if (part 
!= wxT("layout2")) 
1525     // mark all panes currently managed as docked and hidden 
1526     int pane_i
, pane_count 
= m_panes
.GetCount(); 
1527     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1528         m_panes
.Item(pane_i
).Dock().Hide(); 
1530     // clear out the dock array; this will be reconstructed 
1533     // replace escaped characters so we can 
1534     // split up the string easily 
1535     input
.Replace(wxT("\\|"), wxT("\a")); 
1536     input
.Replace(wxT("\\;"), wxT("\b")); 
1542         wxString pane_part 
= input
.BeforeFirst(wxT('|')); 
1543         input 
= input
.AfterFirst(wxT('|')); 
1544         pane_part
.Trim(true); 
1546         // if the string is empty, we're done parsing 
1547         if (pane_part
.empty()) 
1550         if (pane_part
.Left(9) == wxT("dock_size")) 
1552             wxString val_name 
= pane_part
.BeforeFirst(wxT('=')); 
1553             wxString value 
= pane_part
.AfterFirst(wxT('=')); 
1555             long dir
, layer
, row
, size
; 
1556             wxString piece 
= val_name
.AfterFirst(wxT('(')); 
1557             piece 
= piece
.BeforeLast(wxT(')')); 
1558             piece
.BeforeFirst(wxT(',')).ToLong(&dir
); 
1559             piece 
= piece
.AfterFirst(wxT(',')); 
1560             piece
.BeforeFirst(wxT(',')).ToLong(&layer
); 
1561             piece
.AfterFirst(wxT(',')).ToLong(&row
); 
1562             value
.ToLong(&size
); 
1565             dock
.dock_direction 
= dir
; 
1566             dock
.dock_layer 
= layer
; 
1567             dock
.dock_row 
= row
; 
1573         // Undo our escaping as LoadPaneInfo needs to take an unescaped 
1574         // name so it can be called by external callers 
1575         pane_part
.Replace(wxT("\a"), wxT("|")); 
1576         pane_part
.Replace(wxT("\b"), wxT(";")); 
1578         LoadPaneInfo(pane_part
, pane
); 
1580         wxAuiPaneInfo
& p 
= GetPane(pane
.name
); 
1583             // the pane window couldn't be found 
1584             // in the existing layout -- skip it 
1597 void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo
& dock
, 
1598                                             wxArrayInt
& positions
, 
1601     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1602     int pane_border_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1603     int gripper_size 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1608     int offset
, action_pane 
= -1; 
1609     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1611     // find the pane marked as our action pane 
1612     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1614         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1616         if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
1618             wxASSERT_MSG(action_pane
==-1, wxT("Too many fixed action panes")); 
1619             action_pane 
= pane_i
; 
1623     // set up each panes default position, and 
1624     // determine the size (width or height, depending 
1625     // on the dock's orientation) of each pane 
1626     for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1628         wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1629         positions
.Add(pane
.dock_pos
); 
1632         if (pane
.HasBorder()) 
1633             size 
+= (pane_border_size
*2); 
1635         if (dock
.IsHorizontal()) 
1637             if (pane
.HasGripper() && !pane
.HasGripperTop()) 
1638                 size 
+= gripper_size
; 
1639             size 
+= pane
.best_size
.x
; 
1643             if (pane
.HasGripper() && pane
.HasGripperTop()) 
1644                 size 
+= gripper_size
; 
1646             if (pane
.HasCaption()) 
1647                 size 
+= caption_size
; 
1648             size 
+= pane
.best_size
.y
; 
1654     // if there is no action pane, just return the default 
1655     // positions (as specified in pane.pane_pos) 
1656     if (action_pane 
== -1) 
1660     for (pane_i 
= action_pane
-1; pane_i 
>= 0; --pane_i
) 
1662         int amount 
= positions
[pane_i
+1] - (positions
[pane_i
] + sizes
[pane_i
]); 
1667             positions
[pane_i
] -= -amount
; 
1669         offset 
+= sizes
[pane_i
]; 
1672     // if the dock mode is fixed, make sure none of the panes 
1673     // overlap; we will bump panes that overlap 
1675     for (pane_i 
= action_pane
; pane_i 
< pane_count
; ++pane_i
) 
1677         int amount 
= positions
[pane_i
] - offset
; 
1681             positions
[pane_i
] += -amount
; 
1683         offset 
+= sizes
[pane_i
]; 
1688 void wxAuiManager::LayoutAddPane(wxSizer
* cont
, 
1689                                  wxAuiDockInfo
& dock
, 
1690                                  wxAuiPaneInfo
& pane
, 
1691                                  wxAuiDockUIPartArray
& uiparts
, 
1694     wxAuiDockUIPart part
; 
1695     wxSizerItem
* sizer_item
; 
1697     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
1698     int gripper_size 
= m_art
->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE
); 
1699     int pane_border_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
1700     int pane_button_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BUTTON_SIZE
); 
1702     // find out the orientation of the item (orientation for panes 
1703     // is the same as the dock's orientation) 
1705     if (dock
.IsHorizontal()) 
1706         orientation 
= wxHORIZONTAL
; 
1708         orientation 
= wxVERTICAL
; 
1710     // this variable will store the proportion 
1711     // value that the pane will receive 
1712     int pane_proportion 
= pane
.dock_proportion
; 
1714     wxBoxSizer
* horz_pane_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1715     wxBoxSizer
* vert_pane_sizer 
= new wxBoxSizer(wxVERTICAL
); 
1717     if (pane
.HasGripper()) 
1719         if (pane
.HasGripperTop()) 
1720             sizer_item 
= vert_pane_sizer 
->Add(1, gripper_size
, 0, wxEXPAND
); 
1722             sizer_item 
= horz_pane_sizer 
->Add(gripper_size
, 1, 0, wxEXPAND
); 
1724         part
.type 
= wxAuiDockUIPart::typeGripper
; 
1728         part
.orientation 
= orientation
; 
1729         part
.cont_sizer 
= horz_pane_sizer
; 
1730         part
.sizer_item 
= sizer_item
; 
1734     if (pane
.HasCaption()) 
1736         // create the caption sizer 
1737         wxBoxSizer
* caption_sizer 
= new wxBoxSizer(wxHORIZONTAL
); 
1739         sizer_item 
= caption_sizer
->Add(1, caption_size
, 1, wxEXPAND
); 
1741         part
.type 
= wxAuiDockUIPart::typeCaption
; 
1745         part
.orientation 
= orientation
; 
1746         part
.cont_sizer 
= vert_pane_sizer
; 
1747         part
.sizer_item 
= sizer_item
; 
1748         int caption_part_idx 
= uiparts
.GetCount(); 
1751         // add pane buttons to the caption 
1752         int i
, button_count
; 
1753         for (i 
= 0, button_count 
= pane
.buttons
.GetCount(); 
1754              i 
< button_count
; ++i
) 
1756             wxAuiPaneButton
& button 
= pane
.buttons
.Item(i
); 
1758             sizer_item 
= caption_sizer
->Add(pane_button_size
, 
1762             part
.type 
= wxAuiDockUIPart::typePaneButton
; 
1765             part
.button 
= &button
; 
1766             part
.orientation 
= orientation
; 
1767             part
.cont_sizer 
= caption_sizer
; 
1768             part
.sizer_item 
= sizer_item
; 
1772         // if we have buttons, add a little space to the right 
1773         // of them to ease visual crowding 
1774         if (button_count 
>= 1) 
1776             caption_sizer
->Add(3,1); 
1779         // add the caption sizer 
1780         sizer_item 
= vert_pane_sizer
->Add(caption_sizer
, 0, wxEXPAND
); 
1782         uiparts
.Item(caption_part_idx
).sizer_item 
= sizer_item
; 
1785     // add the pane window itself 
1788         sizer_item 
= vert_pane_sizer
->Add(1, 1, 1, wxEXPAND
); 
1792         sizer_item 
= vert_pane_sizer
->Add(pane
.window
, 1, wxEXPAND
); 
1793         // Don't do this because it breaks the pane size in floating windows 
1794         // BIW: Right now commenting this out is causing problems with 
1795         // an mdi client window as the center pane. 
1796         vert_pane_sizer
->SetItemMinSize(pane
.window
, 1, 1); 
1799     part
.type 
= wxAuiDockUIPart::typePane
; 
1803     part
.orientation 
= orientation
; 
1804     part
.cont_sizer 
= vert_pane_sizer
; 
1805     part
.sizer_item 
= sizer_item
; 
1809     // determine if the pane should have a minimum size; if the pane is 
1810     // non-resizable (fixed) then we must set a minimum size. Alternatively, 
1811     // if the pane.min_size is set, we must use that value as well 
1813     wxSize min_size 
= pane
.min_size
; 
1816         if (min_size 
== wxDefaultSize
) 
1818             min_size 
= pane
.best_size
; 
1819             pane_proportion 
= 0; 
1823     if (min_size 
!= wxDefaultSize
) 
1825         vert_pane_sizer
->SetItemMinSize( 
1826                         vert_pane_sizer
->GetChildren().GetCount()-1, 
1827                         min_size
.x
, min_size
.y
); 
1831     // add the verticle sizer (caption, pane window) to the 
1832     // horizontal sizer (gripper, verticle sizer) 
1833     horz_pane_sizer
->Add(vert_pane_sizer
, 1, wxEXPAND
); 
1835     // finally, add the pane sizer to the dock sizer 
1837     if (pane
.HasBorder()) 
1839         // allowing space for the pane's border 
1840         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, 
1841                                wxEXPAND 
| wxALL
, pane_border_size
); 
1843         part
.type 
= wxAuiDockUIPart::typePaneBorder
; 
1847         part
.orientation 
= orientation
; 
1848         part
.cont_sizer 
= cont
; 
1849         part
.sizer_item 
= sizer_item
; 
1854         sizer_item 
= cont
->Add(horz_pane_sizer
, pane_proportion
, wxEXPAND
); 
1858 void wxAuiManager::LayoutAddDock(wxSizer
* cont
, 
1859                                  wxAuiDockInfo
& dock
, 
1860                                  wxAuiDockUIPartArray
& uiparts
, 
1863     wxSizerItem
* sizer_item
; 
1864     wxAuiDockUIPart part
; 
1866     int sash_size 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
1867     int orientation 
= dock
.IsHorizontal() ? wxHORIZONTAL 
: wxVERTICAL
; 
1869     // resizable bottom and right docks have a sash before them 
1870     if (!m_has_maximized 
&& !dock
.fixed 
&& (dock
.dock_direction 
== wxAUI_DOCK_BOTTOM 
|| 
1871                         dock
.dock_direction 
== wxAUI_DOCK_RIGHT
)) 
1873         sizer_item 
= cont
->Add(sash_size
, sash_size
, 0, wxEXPAND
); 
1875         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
1876         part
.orientation 
= orientation
; 
1880         part
.cont_sizer 
= cont
; 
1881         part
.sizer_item 
= sizer_item
; 
1885     // create the sizer for the dock 
1886     wxSizer
* dock_sizer 
= new wxBoxSizer(orientation
); 
1888     // add each pane to the dock 
1889     bool has_maximized_pane 
= false; 
1890     int pane_i
, pane_count 
= dock
.panes
.GetCount(); 
1894         wxArrayInt pane_positions
, pane_sizes
; 
1896         // figure out the real pane positions we will 
1897         // use, without modifying the each pane's pane_pos member 
1898         GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
1901         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1903             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1904             int pane_pos 
= pane_positions
.Item(pane_i
); 
1906             if (pane
.IsMaximized()) 
1907                 has_maximized_pane 
= true; 
1910             int amount 
= pane_pos 
- offset
; 
1913                 if (dock
.IsVertical()) 
1914                     sizer_item 
= dock_sizer
->Add(1, amount
, 0, wxEXPAND
); 
1916                     sizer_item 
= dock_sizer
->Add(amount
, 1, 0, wxEXPAND
); 
1918                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
1922                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
1923                 part
.cont_sizer 
= dock_sizer
; 
1924                 part
.sizer_item 
= sizer_item
; 
1930             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
1932             offset 
+= pane_sizes
.Item(pane_i
); 
1935         // at the end add a very small stretchable background area 
1936         sizer_item 
= dock_sizer
->Add(0,0, 1, wxEXPAND
); 
1938         part
.type 
= wxAuiDockUIPart::typeBackground
; 
1942         part
.orientation 
= orientation
; 
1943         part
.cont_sizer 
= dock_sizer
; 
1944         part
.sizer_item 
= sizer_item
; 
1949         for (pane_i 
= 0; pane_i 
< pane_count
; ++pane_i
) 
1951             wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(pane_i
)); 
1953             if (pane
.IsMaximized()) 
1954                 has_maximized_pane 
= true; 
1956             // if this is not the first pane being added, 
1957             // we need to add a pane sizer 
1958             if (!m_has_maximized 
&& pane_i 
> 0) 
1960                 sizer_item 
= dock_sizer
->Add(sash_size
, sash_size
, 0, wxEXPAND
); 
1962                 part
.type 
= wxAuiDockUIPart::typePaneSizer
; 
1964                 part
.pane 
= dock
.panes
.Item(pane_i
-1); 
1966                 part
.orientation 
= (orientation
==wxHORIZONTAL
) ? wxVERTICAL
:wxHORIZONTAL
; 
1967                 part
.cont_sizer 
= dock_sizer
; 
1968                 part
.sizer_item 
= sizer_item
; 
1972             LayoutAddPane(dock_sizer
, dock
, pane
, uiparts
, spacer_only
); 
1976     if (dock
.dock_direction 
== wxAUI_DOCK_CENTER 
|| has_maximized_pane
) 
1977         sizer_item 
= cont
->Add(dock_sizer
, 1, wxEXPAND
); 
1979         sizer_item 
= cont
->Add(dock_sizer
, 0, wxEXPAND
); 
1981     part
.type 
= wxAuiDockUIPart::typeDock
; 
1985     part
.orientation 
= orientation
; 
1986     part
.cont_sizer 
= cont
; 
1987     part
.sizer_item 
= sizer_item
; 
1990     if (dock
.IsHorizontal()) 
1991         cont
->SetItemMinSize(dock_sizer
, 0, dock
.size
); 
1993         cont
->SetItemMinSize(dock_sizer
, dock
.size
, 0); 
1995     //  top and left docks have a sash after them 
1996     if (!m_has_maximized 
&& 
1998           (dock
.dock_direction 
== wxAUI_DOCK_TOP 
|| 
1999            dock
.dock_direction 
== wxAUI_DOCK_LEFT
)) 
2001         sizer_item 
= cont
->Add(sash_size
, sash_size
, 0, wxEXPAND
); 
2003         part
.type 
= wxAuiDockUIPart::typeDockSizer
; 
2007         part
.orientation 
= orientation
; 
2008         part
.cont_sizer 
= cont
; 
2009         part
.sizer_item 
= sizer_item
; 
2014 wxSizer
* wxAuiManager::LayoutAll(wxAuiPaneInfoArray
& panes
, 
2015                                  wxAuiDockInfoArray
& docks
, 
2016                                  wxAuiDockUIPartArray
& uiparts
, 
2019     wxBoxSizer
* container 
= new wxBoxSizer(wxVERTICAL
); 
2021     int pane_border_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
2022     int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
2023     wxSize cli_size 
= m_frame
->GetClientSize(); 
2024     int i
, dock_count
, pane_count
; 
2027     // empty all docks out 
2028     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2030         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2032         // empty out all panes, as they will be readded below 
2037             // always reset fixed docks' sizes, because 
2038             // the contained windows may have been resized 
2044     // iterate through all known panes, filing each 
2045     // of them into the appropriate dock. If the 
2046     // pane does not exist in the dock, add it 
2047     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
2049         wxAuiPaneInfo
& p 
= panes
.Item(i
); 
2051         // find any docks with the same dock direction, dock layer, and 
2052         // dock row as the pane we are working on 
2053         wxAuiDockInfo
* dock
; 
2054         wxAuiDockInfoPtrArray arr
; 
2055         FindDocks(docks
, p
.dock_direction
, p
.dock_layer
, p
.dock_row
, arr
); 
2057         if (arr
.GetCount() > 0) 
2059             // found the right dock 
2064             // dock was not found, so we need to create a new one 
2066             d
.dock_direction 
= p
.dock_direction
; 
2067             d
.dock_layer 
= p
.dock_layer
; 
2068             d
.dock_row 
= p
.dock_row
; 
2070             dock 
= &docks
.Last(); 
2074         if (p
.IsDocked() && p
.IsShown()) 
2076             // remove the pane from any existing docks except this one 
2077             RemovePaneFromDocks(docks
, p
, dock
); 
2079             // pane needs to be added to the dock, 
2080             // if it doesn't already exist 
2081             if (!FindPaneInDock(*dock
, p
.window
)) 
2082                 dock
->panes
.Add(&p
); 
2086             // remove the pane from any existing docks 
2087             RemovePaneFromDocks(docks
, p
); 
2092     // remove any empty docks 
2093     for (i 
= docks
.GetCount()-1; i 
>= 0; --i
) 
2095         if (docks
.Item(i
).panes
.GetCount() == 0) 
2099     // configure the docks further 
2100     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2102         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2103         int j
, dock_pane_count 
= dock
.panes
.GetCount(); 
2105         // sort the dock pane array by the pane's 
2106         // dock position (dock_pos), in ascending order 
2107         dock
.panes
.Sort(PaneSortFunc
); 
2109         // for newly created docks, set up their initial size 
2114             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2116                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2117                 wxSize pane_size 
= pane
.best_size
; 
2118                 if (pane_size 
== wxDefaultSize
) 
2119                     pane_size 
= pane
.min_size
; 
2120                 if (pane_size 
== wxDefaultSize
) 
2121                     pane_size 
= pane
.window
->GetSize(); 
2123                 if (dock
.IsHorizontal()) 
2124                     size 
= wxMax(pane_size
.y
, size
); 
2126                     size 
= wxMax(pane_size
.x
, size
); 
2129             // add space for the border (two times), but only 
2130             // if at least one pane inside the dock has a pane border 
2131             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2133                 if (dock
.panes
.Item(j
)->HasBorder()) 
2135                     size 
+= (pane_border_size
*2); 
2140             // if pane is on the top or bottom, add the caption height, 
2141             // but only if at least one pane inside the dock has a caption 
2142             if (dock
.IsHorizontal()) 
2144                 for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2146                     if (dock
.panes
.Item(j
)->HasCaption()) 
2148                         size 
+= caption_size
; 
2155             // new dock's size may not be more than the dock constraint 
2156             // parameter specifies.  See SetDockSizeConstraint() 
2158             int max_dock_x_size 
= (int)(m_dock_constraint_x 
* ((double)cli_size
.x
)); 
2159             int max_dock_y_size 
= (int)(m_dock_constraint_y 
* ((double)cli_size
.y
)); 
2161             if (dock
.IsHorizontal()) 
2162                 size 
= wxMin(size
, max_dock_y_size
); 
2164                 size 
= wxMin(size
, max_dock_x_size
); 
2166             // absolute minimum size for a dock is 10 pixels 
2174         // determine the dock's minimum size 
2175         bool plus_border 
= false; 
2176         bool plus_caption 
= false; 
2177         int dock_min_size 
= 0; 
2178         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2180             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2181             if (pane
.min_size 
!= wxDefaultSize
) 
2183                 if (pane
.HasBorder()) 
2185                 if (pane
.HasCaption()) 
2186                     plus_caption 
= true; 
2187                 if (dock
.IsHorizontal()) 
2189                     if (pane
.min_size
.y 
> dock_min_size
) 
2190                         dock_min_size 
= pane
.min_size
.y
; 
2194                     if (pane
.min_size
.x 
> dock_min_size
) 
2195                         dock_min_size 
= pane
.min_size
.x
; 
2201             dock_min_size 
+= (pane_border_size
*2); 
2202         if (plus_caption 
&& dock
.IsHorizontal()) 
2203             dock_min_size 
+= (caption_size
); 
2205         dock
.min_size 
= dock_min_size
; 
2208         // if the pane's current size is less than it's 
2209         // minimum, increase the dock's size to it's minimum 
2210         if (dock
.size 
< dock
.min_size
) 
2211             dock
.size 
= dock
.min_size
; 
2214         // determine the dock's mode (fixed or proportional); 
2215         // determine whether the dock has only toolbars 
2216         bool action_pane_marked 
= false; 
2218         dock
.toolbar 
= true; 
2219         for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2221             wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2222             if (!pane
.IsFixed()) 
2224             if (!pane
.IsToolbar()) 
2225                 dock
.toolbar 
= false; 
2226             if (pane
.HasFlag(wxAuiPaneInfo::optionDockFixed
)) 
2228             if (pane
.HasFlag(wxAuiPaneInfo::actionPane
)) 
2229                 action_pane_marked 
= true; 
2233         // if the dock mode is proportional and not fixed-pixel, 
2234         // reassign the dock_pos to the sequential 0, 1, 2, 3; 
2235         // e.g. remove gaps like 1, 2, 30, 500 
2238             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2240                 wxAuiPaneInfo
& pane 
= *dock
.panes
.Item(j
); 
2245         // if the dock mode is fixed, and none of the panes 
2246         // are being moved right now, make sure the panes 
2247         // do not overlap each other.  If they do, we will 
2248         // adjust the positions of the panes 
2249         if (dock
.fixed 
&& !action_pane_marked
) 
2251             wxArrayInt pane_positions
, pane_sizes
; 
2252             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
2255             for (j 
= 0; j 
< dock_pane_count
; ++j
) 
2257                 wxAuiPaneInfo
& pane 
= *(dock
.panes
.Item(j
)); 
2258                 pane
.dock_pos 
= pane_positions
[j
]; 
2260                 int amount 
= pane
.dock_pos 
- offset
; 
2264                     pane
.dock_pos 
+= -amount
; 
2266                 offset 
+= pane_sizes
[j
]; 
2271     // discover the maximum dock layer 
2273     for (i 
= 0; i 
< dock_count
; ++i
) 
2274         max_layer 
= wxMax(max_layer
, docks
.Item(i
).dock_layer
); 
2277     // clear out uiparts 
2280     // create a bunch of box sizers, 
2281     // from the innermost level outwards. 
2282     wxSizer
* cont 
= NULL
; 
2283     wxSizer
* middle 
= NULL
; 
2287     for (layer 
= 0; layer 
<= max_layer
; ++layer
) 
2289         wxAuiDockInfoPtrArray arr
; 
2291         // find any docks in this layer 
2292         FindDocks(docks
, -1, layer
, -1, arr
); 
2294         // if there aren't any, skip to the next layer 
2298         wxSizer
* old_cont 
= cont
; 
2300         // create a container which will hold this layer's 
2301         // docks (top, bottom, left, right) 
2302         cont 
= new wxBoxSizer(wxVERTICAL
); 
2305         // find any top docks in this layer 
2306         FindDocks(docks
, wxAUI_DOCK_TOP
, layer
, -1, arr
); 
2309             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2310                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2314         // fill out the middle layer (which consists 
2315         // of left docks, content area and right docks) 
2317         middle 
= new wxBoxSizer(wxHORIZONTAL
); 
2319         // find any left docks in this layer 
2320         FindDocks(docks
, wxAUI_DOCK_LEFT
, layer
, -1, arr
); 
2323             for (row 
= 0, row_count 
= arr
.GetCount(); row 
< row_count
; ++row
) 
2324                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2327         // add content dock (or previous layer's sizer 
2331             // find any center docks 
2332             FindDocks(docks
, wxAUI_DOCK_CENTER
, -1, -1, arr
); 
2335                 for (row 
= 0,row_count 
= arr
.GetCount(); row
<row_count
; ++row
) 
2336                    LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2338             else if (!m_has_maximized
) 
2340                 // there are no center docks, add a background area 
2341                 wxSizerItem
* sizer_item 
= middle
->Add(1,1, 1, wxEXPAND
); 
2342                 wxAuiDockUIPart part
; 
2343                 part
.type 
= wxAuiDockUIPart::typeBackground
; 
2347                 part
.cont_sizer 
= middle
; 
2348                 part
.sizer_item 
= sizer_item
; 
2354             middle
->Add(old_cont
, 1, wxEXPAND
); 
2357         // find any right docks in this layer 
2358         FindDocks(docks
, wxAUI_DOCK_RIGHT
, layer
, -1, arr
); 
2361             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2362                 LayoutAddDock(middle
, *arr
.Item(row
), uiparts
, spacer_only
); 
2365         if (middle
->GetChildren().GetCount() > 0) 
2366             cont
->Add(middle
, 1, wxEXPAND
); 
2372         // find any bottom docks in this layer 
2373         FindDocks(docks
, wxAUI_DOCK_BOTTOM
, layer
, -1, arr
); 
2376             for (row 
= arr
.GetCount()-1; row 
>= 0; --row
) 
2377                 LayoutAddDock(cont
, *arr
.Item(row
), uiparts
, spacer_only
); 
2384         // no sizer available, because there are no docks, 
2385         // therefore we will create a simple background area 
2386         cont 
= new wxBoxSizer(wxVERTICAL
); 
2387         wxSizerItem
* sizer_item 
= cont
->Add(1,1, 1, wxEXPAND
); 
2388         wxAuiDockUIPart part
; 
2389         part
.type 
= wxAuiDockUIPart::typeBackground
; 
2393         part
.cont_sizer 
= middle
; 
2394         part
.sizer_item 
= sizer_item
; 
2398     container
->Add(cont
, 1, wxEXPAND
); 
2403 // SetDockSizeConstraint() allows the dock constraints to be set.  For example, 
2404 // specifying values of 0.5, 0.5 will mean that upon dock creation, a dock may 
2405 // not be larger than half of the window's size 
2407 void wxAuiManager::SetDockSizeConstraint(double width_pct
, double height_pct
) 
2409     m_dock_constraint_x 
= wxMax(0.0, wxMin(1.0, width_pct
)); 
2410     m_dock_constraint_y 
= wxMax(0.0, wxMin(1.0, height_pct
)); 
2413 void wxAuiManager::GetDockSizeConstraint(double* width_pct
, double* height_pct
) const 
2416         *width_pct 
= m_dock_constraint_x
; 
2419         *height_pct 
= m_dock_constraint_y
; 
2424 // Update() updates the layout.  Whenever changes are made to 
2425 // one or more panes, this function should be called.  It is the 
2426 // external entry point for running the layout engine. 
2428 void wxAuiManager::Update() 
2430     m_hover_button 
= NULL
; 
2431     m_action_part 
= NULL
; 
2434     int i
, pane_count 
= m_panes
.GetCount(); 
2437     // destroy floating panes which have been 
2438     // redocked or are becoming non-floating 
2439     for (i 
= 0; i 
< pane_count
; ++i
) 
2441         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2443         if (!p
.IsFloating() && p
.frame
) 
2445             // because the pane is no longer in a floating, we need to 
2446             // reparent it to m_frame and destroy the floating frame 
2449             p
.window
->SetSize(1,1); 
2452             // the following block is a workaround for bug #1531361 
2453             // (see wxWidgets sourceforge page).  On wxGTK (only), when 
2454             // a frame is shown/hidden, a move event unfortunately 
2455             // also gets fired.  Because we may be dragging around 
2456             // a pane, we need to cancel that action here to prevent 
2457             // a spurious crash. 
2458             if (m_action_window 
== p
.frame
) 
2460                 if (wxWindow::GetCapture() == m_frame
) 
2461                     m_frame
->ReleaseMouse(); 
2462                 m_action 
= actionNone
; 
2463                 m_action_window 
= NULL
; 
2467             if (p
.frame
->IsShown()) 
2468                 p
.frame
->Show(false); 
2470             // reparent to m_frame and destroy the pane 
2471             if (m_action_window 
== p
.frame
) 
2473                 m_action_window 
= NULL
; 
2476             p
.window
->Reparent(m_frame
); 
2477             p
.frame
->SetSizer(NULL
); 
2484     // delete old sizer first 
2485     m_frame
->SetSizer(NULL
); 
2487     // create a layout for all of the panes 
2488     sizer 
= LayoutAll(m_panes
, m_docks
, m_uiparts
, false); 
2490     // hide or show panes as necessary, 
2491     // and float panes as necessary 
2492     for (i 
= 0; i 
< pane_count
; ++i
) 
2494         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2498             if (p
.frame 
== NULL
) 
2500                 // we need to create a frame for this 
2501                 // pane, which has recently been floated 
2502                 wxAuiFloatingFrame
* frame 
= CreateFloatingFrame(m_frame
, p
); 
2504                 // on MSW and Mac, if the owner desires transparent dragging, and 
2505                 // the dragging is happening right now, then the floating 
2506                 // window should have this style by default 
2507                 if (m_action 
== actionDragFloatingPane 
&& 
2508                     (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
)) 
2509                         frame
->SetTransparent(150); 
2511                 frame
->SetPaneWindow(p
); 
2514                 if (p
.IsShown() && !frame
->IsShown()) 
2519                 // frame already exists, make sure it's position 
2520                 // and size reflect the information in wxAuiPaneInfo 
2521                 if ((p
.frame
->GetPosition() != p
.floating_pos
) || (p
.frame
->GetSize() != p
.floating_size
)) 
2523                     p
.frame
->SetSize(p
.floating_pos
.x
, p
.floating_pos
.y
, 
2524                                      p
.floating_size
.x
, p
.floating_size
.y
, 
2525                                      wxSIZE_USE_EXISTING
); 
2527                     p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, 
2528                                      wxDefaultCoord, wxDefaultCoord, 
2529                                      wxSIZE_USE_EXISTING); 
2530                     //p.frame->Move(p.floating_pos.x, p.floating_pos.y); 
2534                 if (p
.frame
->IsShown() != p
.IsShown()) 
2535                     p
.frame
->Show(p
.IsShown()); 
2540             if (p
.window
->IsShown() != p
.IsShown()) 
2541                 p
.window
->Show(p
.IsShown()); 
2544         // if "active panes" are no longer allowed, clear 
2545         // any optionActive values from the pane states 
2546         if ((m_flags 
& wxAUI_MGR_ALLOW_ACTIVE_PANE
) == 0) 
2548             p
.state 
&= ~wxAuiPaneInfo::optionActive
; 
2553     // keep track of the old window rectangles so we can 
2554     // refresh those windows whose rect has changed 
2555     wxAuiRectArray old_pane_rects
; 
2556     for (i 
= 0; i 
< pane_count
; ++i
) 
2559         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2561         if (p
.window 
&& p
.IsShown() && p
.IsDocked()) 
2564         old_pane_rects
.Add(r
); 
2570     // apply the new sizer 
2571     m_frame
->SetSizer(sizer
); 
2572     m_frame
->SetAutoLayout(false); 
2577     // now that the frame layout is done, we need to check 
2578     // the new pane rectangles against the old rectangles that 
2579     // we saved a few lines above here.  If the rectangles have 
2580     // changed, the corresponding panes must also be updated 
2581     for (i 
= 0; i 
< pane_count
; ++i
) 
2583         wxAuiPaneInfo
& p 
= m_panes
.Item(i
); 
2584         if (p
.window 
&& p
.window
->IsShown() && p
.IsDocked()) 
2586             if (p
.rect 
!= old_pane_rects
[i
]) 
2588                 p
.window
->Refresh(); 
2597     // set frame's minimum size 
2600     // N.B. More work needs to be done on frame minimum sizes; 
2601     // this is some intresting code that imposes the minimum size, 
2602     // but we may want to include a more flexible mechanism or 
2603     // options for multiple minimum-size modes, e.g. strict or lax 
2604     wxSize min_size = sizer->GetMinSize(); 
2605     wxSize frame_size = m_frame->GetSize(); 
2606     wxSize client_size = m_frame->GetClientSize(); 
2608     wxSize minframe_size(min_size.x+frame_size.x-client_size.x, 
2609                          min_size.y+frame_size.y-client_size.y ); 
2611     m_frame->SetMinSize(minframe_size); 
2613     if (frame_size.x < minframe_size.x || 
2614         frame_size.y < minframe_size.y) 
2615             sizer->Fit(m_frame); 
2620 // DoFrameLayout() is an internal function which invokes wxSizer::Layout 
2621 // on the frame's main sizer, then measures all the various UI items 
2622 // and updates their internal rectangles.  This should always be called 
2623 // instead of calling m_frame->Layout() directly 
2625 void wxAuiManager::DoFrameLayout() 
2630     for (i 
= 0, part_count 
= m_uiparts
.GetCount(); i 
< part_count
; ++i
) 
2632         wxAuiDockUIPart
& part 
= m_uiparts
.Item(i
); 
2634         // get the rectangle of the UI part 
2635         // originally, this code looked like this: 
2636         //    part.rect = wxRect(part.sizer_item->GetPosition(), 
2637         //                       part.sizer_item->GetSize()); 
2638         // this worked quite well, with one exception: the mdi 
2639         // client window had a "deferred" size variable 
2640         // that returned the wrong size.  It looks like 
2641         // a bug in wx, because the former size of the window 
2642         // was being returned.  So, we will retrieve the part's 
2643         // rectangle via other means 
2646         part
.rect 
= part
.sizer_item
->GetRect(); 
2647         int flag 
= part
.sizer_item
->GetFlag(); 
2648         int border 
= part
.sizer_item
->GetBorder(); 
2651             part
.rect
.y 
-= border
; 
2652             part
.rect
.height 
+= border
; 
2656             part
.rect
.x 
-= border
; 
2657             part
.rect
.width 
+= border
; 
2659         if (flag 
& wxBOTTOM
) 
2660             part
.rect
.height 
+= border
; 
2662             part
.rect
.width 
+= border
; 
2665         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2666             part
.dock
->rect 
= part
.rect
; 
2667         if (part
.type 
== wxAuiDockUIPart::typePane
) 
2668             part
.pane
->rect 
= part
.rect
; 
2672 // GetPanePart() looks up the pane the pane border UI part (or the regular 
2673 // pane part if there is no border). This allows the caller to get the exact 
2674 // rectangle of the pane in question, including decorations like 
2675 // caption and border (if any). 
2677 wxAuiDockUIPart
* wxAuiManager::GetPanePart(wxWindow
* wnd
) 
2680     for (i 
= 0, part_count 
= m_uiparts
.GetCount(); i 
< part_count
; ++i
) 
2682         wxAuiDockUIPart
& part 
= m_uiparts
.Item(i
); 
2683         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
2684             part
.pane 
&& part
.pane
->window 
== wnd
) 
2687     for (i 
= 0, part_count 
= m_uiparts
.GetCount(); i 
< part_count
; ++i
) 
2689         wxAuiDockUIPart
& part 
= m_uiparts
.Item(i
); 
2690         if (part
.type 
== wxAuiDockUIPart::typePane 
&& 
2691             part
.pane 
&& part
.pane
->window 
== wnd
) 
2699 // GetDockPixelOffset() is an internal function which returns 
2700 // a dock's offset in pixels from the left side of the window 
2701 // (for horizontal docks) or from the top of the window (for 
2702 // vertical docks).  This value is necessary for calculating 
2703 // fixel-pane/toolbar offsets when they are dragged. 
2705 int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo
& test
) 
2707     // the only way to accurately calculate the dock's 
2708     // offset is to actually run a theoretical layout 
2710     int i
, part_count
, dock_count
; 
2711     wxAuiDockInfoArray docks
; 
2712     wxAuiPaneInfoArray panes
; 
2713     wxAuiDockUIPartArray uiparts
; 
2714     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
2717     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
2718     wxSize client_size 
= m_frame
->GetClientSize(); 
2719     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
2722     for (i 
= 0, part_count 
= uiparts
.GetCount(); i 
< part_count
; ++i
) 
2724         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
2725         part
.rect 
= wxRect(part
.sizer_item
->GetPosition(), 
2726                            part
.sizer_item
->GetSize()); 
2727         if (part
.type 
== wxAuiDockUIPart::typeDock
) 
2728             part
.dock
->rect 
= part
.rect
; 
2733     for (i 
= 0, dock_count 
= docks
.GetCount(); i 
< dock_count
; ++i
) 
2735         wxAuiDockInfo
& dock 
= docks
.Item(i
); 
2736         if (test
.dock_direction 
== dock
.dock_direction 
&& 
2737             test
.dock_layer
==dock
.dock_layer 
&& test
.dock_row
==dock
.dock_row
) 
2739             if (dock
.IsVertical()) 
2751 // ProcessDockResult() is a utility function used by DoDrop() - it checks 
2752 // if a dock operation is allowed, the new dock position is copied into 
2753 // the target info.  If the operation was allowed, the function returns true. 
2755 bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo
& target
, 
2756                                      const wxAuiPaneInfo
& new_pos
) 
2758     bool allowed 
= false; 
2759     switch (new_pos
.dock_direction
) 
2761         case wxAUI_DOCK_TOP
:    allowed 
= target
.IsTopDockable();    break; 
2762         case wxAUI_DOCK_BOTTOM
: allowed 
= target
.IsBottomDockable(); break; 
2763         case wxAUI_DOCK_LEFT
:   allowed 
= target
.IsLeftDockable();   break; 
2764         case wxAUI_DOCK_RIGHT
:  allowed 
= target
.IsRightDockable();  break; 
2774 // DoDrop() is an important function.  It basically takes a mouse position, 
2775 // and determines where the pane's new position would be.  If the pane is to be 
2776 // dropped, it performs the drop operation using the specified dock and pane 
2777 // arrays.  By specifying copied dock and pane arrays when calling, a "what-if" 
2778 // scenario can be performed, giving precise coordinates for drop hints. 
2779 // If, however, wxAuiManager:m_docks and wxAuiManager::m_panes are specified 
2780 // as parameters, the changes will be made to the main state arrays 
2782 const int auiInsertRowPixels 
= 10; 
2783 const int auiNewRowPixels 
= 40; 
2784 const int auiLayerInsertPixels 
= 40; 
2785 const int auiLayerInsertOffset 
= 5; 
2787 bool wxAuiManager::DoDrop(wxAuiDockInfoArray
& docks
, 
2788                           wxAuiPaneInfoArray
& panes
, 
2789                           wxAuiPaneInfo
& target
, 
2791                           const wxPoint
& offset
) 
2793     wxSize cli_size 
= m_frame
->GetClientSize(); 
2795     wxAuiPaneInfo drop 
= target
; 
2798     // The result should always be shown 
2802     // Check to see if the pane has been dragged outside of the window 
2803     // (or near to the outside of the window), if so, dock it along the edge 
2806     int layer_insert_offset 
= auiLayerInsertOffset
; 
2807     if (drop
.IsToolbar()) 
2808         layer_insert_offset 
= 0; 
2811     if (pt
.x 
< layer_insert_offset 
&& 
2812         pt
.x 
> layer_insert_offset
-auiLayerInsertPixels
) 
2814         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
2815                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
2816                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)) + 1; 
2818         if (drop
.IsToolbar()) 
2819             new_layer 
= auiToolBarLayer
; 
2824              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2825         return ProcessDockResult(target
, drop
); 
2827     else if (pt
.y 
< layer_insert_offset 
&& 
2828              pt
.y 
> layer_insert_offset
-auiLayerInsertPixels
) 
2830         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
2831                                 GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2832                                 GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2834         if (drop
.IsToolbar()) 
2835             new_layer 
= auiToolBarLayer
; 
2840              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2841         return ProcessDockResult(target
, drop
); 
2843     else if (pt
.x 
>= cli_size
.x 
- layer_insert_offset 
&& 
2844              pt
.x 
< cli_size
.x 
- layer_insert_offset 
+ auiLayerInsertPixels
) 
2846         int new_layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
2847                                 GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
2848                                 GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)) + 1; 
2850         if (drop
.IsToolbar()) 
2851             new_layer 
= auiToolBarLayer
; 
2853         drop
.Dock().Right(). 
2856              Position(pt
.y 
- GetDockPixelOffset(drop
) - offset
.y
); 
2857         return ProcessDockResult(target
, drop
); 
2859     else if (pt
.y 
>= cli_size
.y 
- layer_insert_offset 
&& 
2860              pt
.y 
< cli_size
.y 
- layer_insert_offset 
+ auiLayerInsertPixels
) 
2862         int new_layer 
= wxMax( wxMax( GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
2863                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
2864                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)) + 1; 
2866         if (drop
.IsToolbar()) 
2867             new_layer 
= auiToolBarLayer
; 
2869         drop
.Dock().Bottom(). 
2872              Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2873         return ProcessDockResult(target
, drop
); 
2877     wxAuiDockUIPart
* part 
= HitTest(pt
.x
, pt
.y
); 
2880     if (drop
.IsToolbar()) 
2882         if (!part 
|| !part
->dock
) 
2885         // calculate the offset from where the dock begins 
2886         // to the point where the user dropped the pane 
2887         int dock_drop_offset 
= 0; 
2888         if (part
->dock
->IsHorizontal()) 
2889             dock_drop_offset 
= pt
.x 
- part
->dock
->rect
.x 
- offset
.x
; 
2891             dock_drop_offset 
= pt
.y 
- part
->dock
->rect
.y 
- offset
.y
; 
2894         // toolbars may only be moved in and to fixed-pane docks, 
2895         // otherwise we will try to float the pane.  Also, the pane 
2896         // should float if being dragged over center pane windows 
2897         if (!part
->dock
->fixed 
|| part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER
) 
2899             if (m_last_rect
.IsEmpty() || m_last_rect
.Contains(pt
.x
, pt
.y 
)) 
2905                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && 
2906                    (drop
.IsFloatable() || 
2907                     (part
->dock
->dock_direction 
!= wxAUI_DOCK_CENTER 
&& 
2908                      part
->dock
->dock_direction 
!= wxAUI_DOCK_NONE
))) 
2910                     if (drop
.IsFloatable()) 
2916                 return ProcessDockResult(target
, drop
); 
2919             drop
.Position(pt
.x 
- GetDockPixelOffset(drop
) - offset
.x
); 
2921             return ProcessDockResult(target
, drop
); 
2926         m_last_rect 
= part
->dock
->rect
; 
2927         m_last_rect
.Inflate( 15, 15 ); 
2930              Direction(part
->dock
->dock_direction
). 
2931              Layer(part
->dock
->dock_layer
). 
2932              Row(part
->dock
->dock_row
). 
2933              Position(dock_drop_offset
); 
2936             ((pt
.y 
< part
->dock
->rect
.y 
+ 1) && part
->dock
->IsHorizontal()) || 
2937             ((pt
.x 
< part
->dock
->rect
.x 
+ 1) && part
->dock
->IsVertical()) 
2938             ) && part
->dock
->panes
.GetCount() > 1) 
2940             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
2941                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
2943                 int row 
= drop
.dock_row
; 
2944                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
2945                                 part
->dock
->dock_layer
, 
2946                                 part
->dock
->dock_row
); 
2947                 drop
.dock_row 
= row
; 
2951                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
2952                                 part
->dock
->dock_layer
, 
2953                                 part
->dock
->dock_row
+1); 
2954                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
2959             ((pt
.y 
> part
->dock
->rect
.y 
+ part
->dock
->rect
.height 
- 2 ) && part
->dock
->IsHorizontal()) || 
2960             ((pt
.x 
> part
->dock
->rect
.x 
+ part
->dock
->rect
.width 
- 2 ) && part
->dock
->IsVertical()) 
2961             ) && part
->dock
->panes
.GetCount() > 1) 
2963             if ((part
->dock
->dock_direction 
== wxAUI_DOCK_TOP
) || 
2964                 (part
->dock
->dock_direction 
== wxAUI_DOCK_LEFT
)) 
2966                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
2967                                 part
->dock
->dock_layer
, 
2968                                 part
->dock
->dock_row
+1); 
2969                 drop
.dock_row 
= part
->dock
->dock_row
+1; 
2973                 int row 
= drop
.dock_row
; 
2974                 DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
2975                                 part
->dock
->dock_layer
, 
2976                                 part
->dock
->dock_row
); 
2977                 drop
.dock_row 
= row
; 
2981         return ProcessDockResult(target
, drop
); 
2990     if (part
->type 
== wxAuiDockUIPart::typePaneBorder 
|| 
2991         part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
2992         part
->type 
== wxAuiDockUIPart::typeGripper 
|| 
2993         part
->type 
== wxAuiDockUIPart::typePaneButton 
|| 
2994         part
->type 
== wxAuiDockUIPart::typePane 
|| 
2995         part
->type 
== wxAuiDockUIPart::typePaneSizer 
|| 
2996         part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
2997         part
->type 
== wxAuiDockUIPart::typeBackground
) 
2999         if (part
->type 
== wxAuiDockUIPart::typeDockSizer
) 
3001             if (part
->dock
->panes
.GetCount() != 1) 
3003             part 
= GetPanePart(part
->dock
->panes
.Item(0)->window
); 
3010         // If a normal frame is being dragged over a toolbar, insert it 
3011         // along the edge under the toolbar, but over all other panes. 
3012         // (this could be done much better, but somehow factoring this 
3013         // calculation with the one at the beginning of this function) 
3014         if (part
->dock 
&& part
->dock
->toolbar
) 
3018             switch (part
->dock
->dock_direction
) 
3020                 case wxAUI_DOCK_LEFT
: 
3021                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_LEFT
), 
3022                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)), 
3023                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)); 
3025                 case wxAUI_DOCK_TOP
: 
3026                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_TOP
), 
3027                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3028                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3030                 case wxAUI_DOCK_RIGHT
: 
3031                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
), 
3032                                       GetMaxLayer(docks
, wxAUI_DOCK_TOP
)), 
3033                                       GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
)); 
3035                 case wxAUI_DOCK_BOTTOM
: 
3036                     layer 
= wxMax(wxMax(GetMaxLayer(docks
, wxAUI_DOCK_BOTTOM
), 
3037                                       GetMaxLayer(docks
, wxAUI_DOCK_LEFT
)), 
3038                                       GetMaxLayer(docks
, wxAUI_DOCK_RIGHT
)); 
3042             DoInsertDockRow(panes
, part
->dock
->dock_direction
, 
3045                  Direction(part
->dock
->dock_direction
). 
3046                  Layer(layer
).Row(0).Position(0); 
3047             return ProcessDockResult(target
, drop
); 
3054         part 
= GetPanePart(part
->pane
->window
); 
3058         bool insert_dock_row 
= false; 
3059         int insert_row 
= part
->pane
->dock_row
; 
3060         int insert_dir 
= part
->pane
->dock_direction
; 
3061         int insert_layer 
= part
->pane
->dock_layer
; 
3063         switch (part
->pane
->dock_direction
) 
3065             case wxAUI_DOCK_TOP
: 
3066                 if (pt
.y 
>= part
->rect
.y 
&& 
3067                     pt
.y 
< part
->rect
.y
+auiInsertRowPixels
) 
3068                         insert_dock_row 
= true; 
3070             case wxAUI_DOCK_BOTTOM
: 
3071                 if (pt
.y 
> part
->rect
.y
+part
->rect
.height
-auiInsertRowPixels 
&& 
3072                     pt
.y 
<= part
->rect
.y 
+ part
->rect
.height
) 
3073                         insert_dock_row 
= true; 
3075             case wxAUI_DOCK_LEFT
: 
3076                 if (pt
.x 
>= part
->rect
.x 
&& 
3077                     pt
.x 
< part
->rect
.x
+auiInsertRowPixels
) 
3078                         insert_dock_row 
= true; 
3080             case wxAUI_DOCK_RIGHT
: 
3081                 if (pt
.x 
> part
->rect
.x
+part
->rect
.width
-auiInsertRowPixels 
&& 
3082                     pt
.x 
<= part
->rect
.x
+part
->rect
.width
) 
3083                         insert_dock_row 
= true; 
3085             case wxAUI_DOCK_CENTER
: 
3087                 // "new row pixels" will be set to the default, but 
3088                 // must never exceed 20% of the window size 
3089                 int new_row_pixels_x 
= auiNewRowPixels
; 
3090                 int new_row_pixels_y 
= auiNewRowPixels
; 
3092                 if (new_row_pixels_x 
> (part
->rect
.width
*20)/100) 
3093                     new_row_pixels_x 
= (part
->rect
.width
*20)/100; 
3095                 if (new_row_pixels_y 
> (part
->rect
.height
*20)/100) 
3096                     new_row_pixels_y 
= (part
->rect
.height
*20)/100; 
3099                 // determine if the mouse pointer is in a location that 
3100                 // will cause a new row to be inserted.  The hot spot positions 
3101                 // are along the borders of the center pane 
3104                 insert_dock_row 
= true; 
3105                 const wxRect
& pr 
= part
->rect
; 
3106                 if (pt
.x 
>= pr
.x 
&& pt
.x 
< pr
.x 
+ new_row_pixels_x
) 
3107                     insert_dir 
= wxAUI_DOCK_LEFT
; 
3108                 else if (pt
.y 
>= pr
.y 
&& pt
.y 
< pr
.y 
+ new_row_pixels_y
) 
3109                     insert_dir 
= wxAUI_DOCK_TOP
; 
3110                 else if (pt
.x 
>= pr
.x 
+ pr
.width 
- new_row_pixels_x 
&& 
3111                          pt
.x 
< pr
.x 
+ pr
.width
) 
3112                     insert_dir 
= wxAUI_DOCK_RIGHT
; 
3113                 else if (pt
.y 
>= pr
.y
+ pr
.height 
- new_row_pixels_y 
&& 
3114                          pt
.y 
< pr
.y 
+ pr
.height
) 
3115                     insert_dir 
= wxAUI_DOCK_BOTTOM
; 
3119                 insert_row 
= GetMaxRow(panes
, insert_dir
, insert_layer
) + 1; 
3123         if (insert_dock_row
) 
3125             DoInsertDockRow(panes
, insert_dir
, insert_layer
, insert_row
); 
3126             drop
.Dock().Direction(insert_dir
). 
3127                         Layer(insert_layer
). 
3130             return ProcessDockResult(target
, drop
); 
3133         // determine the mouse offset and the pane size, both in the 
3134         // direction of the dock itself, and perpendicular to the dock 
3138         if (part
->orientation 
== wxVERTICAL
) 
3140             offset 
= pt
.y 
- part
->rect
.y
; 
3141             size 
= part
->rect
.GetHeight(); 
3145             offset 
= pt
.x 
- part
->rect
.x
; 
3146             size 
= part
->rect
.GetWidth(); 
3149         int drop_position 
= part
->pane
->dock_pos
; 
3151         // if we are in the top/left part of the pane, 
3152         // insert the pane before the pane being hovered over 
3153         if (offset 
<= size
/2) 
3155             drop_position 
= part
->pane
->dock_pos
; 
3157                          part
->pane
->dock_direction
, 
3158                          part
->pane
->dock_layer
, 
3159                          part
->pane
->dock_row
, 
3160                          part
->pane
->dock_pos
); 
3163         // if we are in the bottom/right part of the pane, 
3164         // insert the pane before the pane being hovered over 
3165         if (offset 
> size
/2) 
3167             drop_position 
= part
->pane
->dock_pos
+1; 
3169                          part
->pane
->dock_direction
, 
3170                          part
->pane
->dock_layer
, 
3171                          part
->pane
->dock_row
, 
3172                          part
->pane
->dock_pos
+1); 
3176              Direction(part
->dock
->dock_direction
). 
3177              Layer(part
->dock
->dock_layer
). 
3178              Row(part
->dock
->dock_row
). 
3179              Position(drop_position
); 
3180         return ProcessDockResult(target
, drop
); 
3187 void wxAuiManager::OnHintFadeTimer(wxTimerEvent
& WXUNUSED(event
)) 
3189     if (!m_hint_wnd 
|| m_hint_fadeamt 
>= m_hint_fademax
) 
3191         m_hint_fadetimer
.Stop(); 
3195     m_hint_fadeamt 
+= 4; 
3196     m_hint_wnd
->SetTransparent(m_hint_fadeamt
); 
3199 void wxAuiManager::ShowHint(const wxRect
& rect
) 
3203         // if the hint rect is the same as last time, don't do anything 
3204         if (m_last_hint 
== rect
) 
3208         m_hint_fadeamt 
= m_hint_fademax
; 
3210         if ((m_flags 
& wxAUI_MGR_HINT_FADE
) 
3211             && !((m_hint_wnd
->IsKindOf(CLASSINFO(wxPseudoTransparentFrame
))) && 
3212                  (m_flags 
& wxAUI_MGR_NO_VENETIAN_BLINDS_FADE
)) 
3216         m_hint_wnd
->SetSize(rect
); 
3217         m_hint_wnd
->SetTransparent(m_hint_fadeamt
); 
3219         if (!m_hint_wnd
->IsShown()) 
3222         // if we are dragging a floating pane, set the focus 
3223         // back to that floating pane (otherwise it becomes unfocused) 
3224         if (m_action 
== actionDragFloatingPane 
&& m_action_window
) 
3225             m_action_window
->SetFocus(); 
3227         m_hint_wnd
->Raise(); 
3230         if (m_hint_fadeamt 
!= m_hint_fademax
) //  Only fade if we need to 
3232             // start fade in timer 
3233             m_hint_fadetimer
.SetOwner(this, 101); 
3234             m_hint_fadetimer
.Start(5); 
3237     else  // Not using a transparent hint window... 
3239         if (!(m_flags 
& wxAUI_MGR_RECTANGLE_HINT
)) 
3242         if (m_last_hint 
!= rect
) 
3244             // remove the last hint rectangle 
3250         wxScreenDC screendc
; 
3251         wxRegion 
clip(1, 1, 10000, 10000); 
3253         // clip all floating windows, so we don't draw over them 
3255         for (i 
= 0, pane_count 
= m_panes
.GetCount(); i 
< pane_count
; ++i
) 
3257             wxAuiPaneInfo
& pane 
= m_panes
.Item(i
); 
3259             if (pane
.IsFloating() && 
3260                 pane
.frame
->IsShown()) 
3262                 wxRect rect 
= pane
.frame
->GetRect(); 
3264                 // wxGTK returns the client size, not the whole frame size 
3270                 clip
.Subtract(rect
); 
3274         // As we can only hide the hint by redrawing the managed window, we 
3275         // need to clip the region to the managed window too or we get 
3276         // nasty redrawn problems. 
3277         clip
.Intersect(m_frame
->GetRect()); 
3279         screendc
.SetDeviceClippingRegion(clip
); 
3281         wxBitmap stipple 
= wxPaneCreateStippleBitmap(); 
3282         wxBrush 
brush(stipple
); 
3283         screendc
.SetBrush(brush
); 
3284         screendc
.SetPen(*wxTRANSPARENT_PEN
); 
3286         screendc
.DrawRectangle(rect
.x
, rect
.y
, 5, rect
.height
); 
3287         screendc
.DrawRectangle(rect
.x
+5, rect
.y
, rect
.width
-10, 5); 
3288         screendc
.DrawRectangle(rect
.x
+rect
.width
-5, rect
.y
, 5, rect
.height
); 
3289         screendc
.DrawRectangle(rect
.x
+5, rect
.y
+rect
.height
-5, rect
.width
-10, 5); 
3293 void wxAuiManager::HideHint() 
3295     // hides a transparent window hint, if there is one 
3298         if (m_hint_wnd
->IsShown()) 
3299             m_hint_wnd
->Show(false); 
3300         m_hint_wnd
->SetTransparent(0); 
3301         m_hint_fadetimer
.Stop(); 
3302         m_last_hint 
= wxRect(); 
3306     // hides a painted hint by redrawing the frame window 
3307     if (!m_last_hint
.IsEmpty()) 
3311         m_last_hint 
= wxRect(); 
3315 void wxAuiManager::OnHintActivate(wxActivateEvent
& WXUNUSED(event
)) 
3317     // Do nothing so this event isn't handled in the base handlers. 
3319     // Letting the hint window activate without this handler can lead to 
3320     // weird behavior on Mac where the menu is switched out to the top 
3321     // window's menu in MDI applications when it shouldn't be. So since 
3322     // we don't want user interaction with the hint window anyway, we just 
3323     // prevent it from activating here. 
3328 void wxAuiManager::StartPaneDrag(wxWindow
* pane_window
, 
3329                                  const wxPoint
& offset
) 
3331     wxAuiPaneInfo
& pane 
= GetPane(pane_window
); 
3335     if (pane
.IsToolbar()) 
3337         m_action 
= actionDragToolbarPane
; 
3341         m_action 
= actionDragFloatingPane
; 
3344     m_action_window 
= pane_window
; 
3345     m_action_offset 
= offset
; 
3346     m_frame
->CaptureMouse(); 
3350 // CalculateHintRect() calculates the drop hint rectangle.  The method 
3351 // first calls DoDrop() to determine the exact position the pane would 
3352 // be at were if dropped.  If the pane would indeed become docked at the 
3353 // specified drop point, the the rectangle hint will be returned in 
3354 // screen coordinates.  Otherwise, an empty rectangle is returned. 
3355 // |pane_window| is the window pointer of the pane being dragged, |pt| is 
3356 // the mouse position, in client coordinates.  |offset| describes the offset 
3357 // that the mouse is from the upper-left corner of the item being dragged 
3359 wxRect 
wxAuiManager::CalculateHintRect(wxWindow
* pane_window
, 
3361                                        const wxPoint
& offset
) 
3365     // we need to paint a hint rectangle; to find out the exact hint rectangle, 
3366     // we will create a new temporary layout and then measure the resulting 
3367     // rectangle; we will create a copy of the docking structures (m_dock) 
3368     // so that we don't modify the real thing on screen 
3370     int i
, pane_count
, part_count
; 
3371     wxAuiDockInfoArray docks
; 
3372     wxAuiPaneInfoArray panes
; 
3373     wxAuiDockUIPartArray uiparts
; 
3374     wxAuiPaneInfo hint 
= GetPane(pane_window
); 
3375     hint
.name 
= wxT("__HINT__"); 
3376     hint
.PaneBorder(true); 
3382     CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3384     // remove any pane already there which bears the same window; 
3385     // this happens when you are moving a pane around in a dock 
3386     for (i 
= 0, pane_count 
= panes
.GetCount(); i 
< pane_count
; ++i
) 
3388         if (panes
.Item(i
).window 
== pane_window
) 
3390             RemovePaneFromDocks(docks
, panes
.Item(i
)); 
3396     // find out where the new pane would be 
3397     if (!DoDrop(docks
, panes
, hint
, pt
, offset
)) 
3404     wxSizer
* sizer 
= LayoutAll(panes
, docks
, uiparts
, true); 
3405     wxSize client_size 
= m_frame
->GetClientSize(); 
3406     sizer
->SetDimension(0, 0, client_size
.x
, client_size
.y
); 
3409     for (i 
= 0, part_count 
= uiparts
.GetCount(); 
3410          i 
< part_count
; ++i
) 
3412         wxAuiDockUIPart
& part 
= uiparts
.Item(i
); 
3414         if (part
.type 
== wxAuiDockUIPart::typePaneBorder 
&& 
3415             part
.pane 
&& part
.pane
->name 
== wxT("__HINT__")) 
3417             rect 
= wxRect(part
.sizer_item
->GetPosition(), 
3418                           part
.sizer_item
->GetSize()); 
3430     // actually show the hint rectangle on the screen 
3431     m_frame
->ClientToScreen(&rect
.x
, &rect
.y
); 
3433     if ( m_frame
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
3435         // Mirror rectangle in RTL mode 
3436         rect
.x 
-= rect
.GetWidth(); 
3442 // DrawHintRect() calculates the hint rectangle by calling 
3443 // CalculateHintRect().  If there is a rectangle, it shows it 
3444 // by calling ShowHint(), otherwise it hides any hint 
3445 // rectangle currently shown 
3446 void wxAuiManager::DrawHintRect(wxWindow
* pane_window
, 
3448                                 const wxPoint
& offset
) 
3450     wxRect rect 
= CalculateHintRect(pane_window
, pt
, offset
); 
3462 void wxAuiManager::OnFloatingPaneMoveStart(wxWindow
* wnd
) 
3464     // try to find the pane 
3465     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3466     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3468     if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3469         pane
.frame
->SetTransparent(150); 
3472 void wxAuiManager::OnFloatingPaneMoving(wxWindow
* wnd
, wxDirection dir
) 
3474     // try to find the pane 
3475     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3476     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3478     wxPoint pt 
= ::wxGetMousePosition(); 
3481     // Adapt pt to direction 
3484         // move to pane's upper border 
3486         pos 
= wnd
->ClientToScreen( pos 
); 
3488         // and some more pixels for the title bar 
3491     else if (dir 
== wxWEST
) 
3493         // move to pane's left border 
3495         pos 
= wnd
->ClientToScreen( pos 
); 
3498     else if (dir 
== wxEAST
) 
3500         // move to pane's right border 
3501         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3502         pos 
= wnd
->ClientToScreen( pos 
); 
3505     else if (dir 
== wxSOUTH
) 
3507         // move to pane's bottom border 
3508         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3509         pos 
= wnd
->ClientToScreen( pos 
); 
3516     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3518     // calculate the offset from the upper left-hand corner 
3519     // of the frame to the mouse pointer 
3520     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3521     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3523     // no hint for toolbar floating windows 
3524     if (pane
.IsToolbar() && m_action 
== actionDragFloatingPane
) 
3526         wxAuiDockInfoArray docks
; 
3527         wxAuiPaneInfoArray panes
; 
3528         wxAuiDockUIPartArray uiparts
; 
3529         wxAuiPaneInfo hint 
= pane
; 
3531         CopyDocksAndPanes(docks
, panes
, m_docks
, m_panes
); 
3533         // find out where the new pane would be 
3534         if (!DoDrop(docks
, panes
, hint
, client_pt
)) 
3536         if (hint
.IsFloating()) 
3540         m_action 
= actionDragToolbarPane
; 
3541         m_action_window 
= pane
.window
; 
3549     // if a key modifier is pressed while dragging the frame, 
3550     // don't dock the window 
3551     if (!CanDockPanel(pane
)) 
3558     DrawHintRect(wnd
, client_pt
, action_offset
); 
3561     // this cleans up some screen artifacts that are caused on GTK because 
3562     // we aren't getting the exact size of the window (see comment 
3572 void wxAuiManager::OnFloatingPaneMoved(wxWindow
* wnd
, wxDirection dir
) 
3574     // try to find the pane 
3575     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3576     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3578     wxPoint pt 
= ::wxGetMousePosition(); 
3581     // Adapt pt to direction 
3584         // move to pane's upper border 
3586         pos 
= wnd
->ClientToScreen( pos 
); 
3588         // and some more pixels for the title bar 
3591     else if (dir 
== wxWEST
) 
3593         // move to pane's left border 
3595         pos 
= wnd
->ClientToScreen( pos 
); 
3598     else if (dir 
== wxEAST
) 
3600         // move to pane's right border 
3601         wxPoint 
pos( wnd
->GetSize().x
, 0 ); 
3602         pos 
= wnd
->ClientToScreen( pos 
); 
3605     else if (dir 
== wxSOUTH
) 
3607         // move to pane's bottom border 
3608         wxPoint 
pos( 0, wnd
->GetSize().y 
); 
3609         pos 
= wnd
->ClientToScreen( pos 
); 
3616     wxPoint client_pt 
= m_frame
->ScreenToClient(pt
); 
3618     // calculate the offset from the upper left-hand corner 
3619     // of the frame to the mouse pointer 
3620     wxPoint frame_pos 
= pane
.frame
->GetPosition(); 
3621     wxPoint 
action_offset(pt
.x
-frame_pos
.x
, pt
.y
-frame_pos
.y
); 
3623     // if a key modifier is pressed while dragging the frame, 
3624     // don't dock the window 
3625     if (CanDockPanel(pane
)) 
3627         // do the drop calculation 
3628         DoDrop(m_docks
, m_panes
, pane
, client_pt
, action_offset
); 
3631     // if the pane is still floating, update it's floating 
3632     // position (that we store) 
3633     if (pane
.IsFloating()) 
3635         pane
.floating_pos 
= pane
.frame
->GetPosition(); 
3637         if (m_flags 
& wxAUI_MGR_TRANSPARENT_DRAG
) 
3638             pane
.frame
->SetTransparent(255); 
3640     else if (m_has_maximized
) 
3642         RestoreMaximizedPane(); 
3650 void wxAuiManager::OnFloatingPaneResized(wxWindow
* wnd
, const wxSize
& size
) 
3652     // try to find the pane 
3653     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3654     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3656     pane
.floating_size 
= size
; 
3660 void wxAuiManager::OnFloatingPaneClosed(wxWindow
* wnd
, wxCloseEvent
& evt
) 
3662     // try to find the pane 
3663     wxAuiPaneInfo
& pane 
= GetPane(wnd
); 
3664     wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
3667     // fire pane close event 
3668     wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
3670     e
.SetCanVeto(evt
.CanVeto()); 
3680         // close the pane, but check that it 
3681         // still exists in our pane array first 
3682         // (the event handler above might have removed it) 
3684         wxAuiPaneInfo
& check 
= GetPane(wnd
); 
3694 void wxAuiManager::OnFloatingPaneActivated(wxWindow
* wnd
) 
3696     if ((GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) && GetPane(wnd
).IsOk()) 
3698         SetActivePane(m_panes
, wnd
); 
3703 // OnRender() draws all of the pane captions, sashes, 
3704 // backgrounds, captions, grippers, pane borders and buttons. 
3705 // It renders the entire user interface. 
3707 void wxAuiManager::OnRender(wxAuiManagerEvent
& evt
) 
3709     // if the frame is about to be deleted, don't bother 
3710     if (!m_frame 
|| wxPendingDelete
.Member(m_frame
)) 
3713     wxDC
* dc 
= evt
.GetDC(); 
3719     for (i 
= 0, part_count 
= m_uiparts
.GetCount(); 
3720          i 
< part_count
; ++i
) 
3722         wxAuiDockUIPart
& part 
= m_uiparts
.Item(i
); 
3724         // don't draw hidden pane items or items that aren't windows 
3725         if (part
.sizer_item 
&& ((!part
.sizer_item
->IsWindow() && !part
.sizer_item
->IsSpacer() && !part
.sizer_item
->IsSizer()) || !part
.sizer_item
->IsShown())) 
3730             case wxAuiDockUIPart::typeDockSizer
: 
3731             case wxAuiDockUIPart::typePaneSizer
: 
3732                 m_art
->DrawSash(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3734             case wxAuiDockUIPart::typeBackground
: 
3735                 m_art
->DrawBackground(*dc
, m_frame
, part
.orientation
, part
.rect
); 
3737             case wxAuiDockUIPart::typeCaption
: 
3738                 m_art
->DrawCaption(*dc
, m_frame
, part
.pane
->caption
, part
.rect
, *part
.pane
); 
3740             case wxAuiDockUIPart::typeGripper
: 
3741                 m_art
->DrawGripper(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3743             case wxAuiDockUIPart::typePaneBorder
: 
3744                 m_art
->DrawBorder(*dc
, m_frame
, part
.rect
, *part
.pane
); 
3746             case wxAuiDockUIPart::typePaneButton
: 
3747                 m_art
->DrawPaneButton(*dc
, m_frame
, part
.button
->button_id
, 
3748                         wxAUI_BUTTON_STATE_NORMAL
, part
.rect
, *part
.pane
); 
3755 // Render() fire a render event, which is normally handled by 
3756 // wxAuiManager::OnRender().  This allows the render function to 
3757 // be overridden via the render event.  This can be useful for paintin 
3758 // custom graphics in the main window. Default behavior can be 
3759 // invoked in the overridden function by calling OnRender() 
3761 void wxAuiManager::Render(wxDC
* dc
) 
3763     wxAuiManagerEvent 
e(wxEVT_AUI_RENDER
); 
3769 void wxAuiManager::Repaint(wxDC
* dc
) 
3774         m_frame
->Refresh() ; 
3780     m_frame
->GetClientSize(&w
, &h
); 
3782     // figure out which dc to use; if one 
3783     // has been specified, use it, otherwise 
3785     wxClientDC
* client_dc 
= NULL
; 
3788         client_dc 
= new wxClientDC(m_frame
); 
3792     // if the frame has a toolbar, the client area 
3793     // origin will not be (0,0). 
3794     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
3795     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
3796         dc
->SetDeviceOrigin(pt
.x
, pt
.y
); 
3798     // render all the items 
3801     // if we created a client_dc, delete it 
3806 void wxAuiManager::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
3808     wxPaintDC 
dc(m_frame
); 
3812 void wxAuiManager::OnEraseBackground(wxEraseEvent
& event
) 
3821 void wxAuiManager::OnSize(wxSizeEvent
& event
) 
3829         if (m_frame
->IsKindOf(CLASSINFO(wxMDIParentFrame
))) 
3831             // for MDI parent frames, this event must not 
3832             // be "skipped".  In other words, the parent frame 
3833             // must not be allowed to resize the client window 
3834             // after we are finished processing sizing changes 
3842 void wxAuiManager::OnFindManager(wxAuiManagerEvent
& evt
) 
3844     // get the window we are managing, if none, return NULL 
3845     wxWindow
* window 
= GetManagedWindow(); 
3848         evt
.SetManager(NULL
); 
3852     // if we are managing a child frame, get the 'real' manager 
3853     if (window
->IsKindOf(CLASSINFO(wxAuiFloatingFrame
))) 
3855         wxAuiFloatingFrame
* float_frame 
= static_cast<wxAuiFloatingFrame
*>(window
); 
3856         evt
.SetManager(float_frame
->GetOwnerManager()); 
3860     // return pointer to ourself 
3861     evt
.SetManager(this); 
3864 void wxAuiManager::OnSetCursor(wxSetCursorEvent
& event
) 
3867     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
3868     wxCursor cursor 
= wxNullCursor
; 
3872         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
3873             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
3875             // a dock may not be resized if it has a single 
3876             // pane which is not resizable 
3877             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
3878                 part
->dock
->panes
.GetCount() == 1 && 
3879                 part
->dock
->panes
.Item(0)->IsFixed()) 
3882             // panes that may not be resized do not get a sizing cursor 
3883             if (part
->pane 
&& part
->pane
->IsFixed()) 
3886             if (part
->orientation 
== wxVERTICAL
) 
3887                 cursor 
= wxCursor(wxCURSOR_SIZEWE
); 
3889                 cursor 
= wxCursor(wxCURSOR_SIZENS
); 
3891         else if (part
->type 
== wxAuiDockUIPart::typeGripper
) 
3893             cursor 
= wxCursor(wxCURSOR_SIZING
); 
3897     event
.SetCursor(cursor
); 
3902 void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart
* button_ui_part
, 
3903                                         const wxMouseEvent
& event
) 
3905     wxAuiDockUIPart
* hit_test 
= HitTest(event
.GetX(), event
.GetY()); 
3906     if (!hit_test 
|| !button_ui_part
) 
3909     int state 
= wxAUI_BUTTON_STATE_NORMAL
; 
3911     if (hit_test 
== button_ui_part
) 
3913         if (event
.LeftDown()) 
3914             state 
= wxAUI_BUTTON_STATE_PRESSED
; 
3916             state 
= wxAUI_BUTTON_STATE_HOVER
; 
3920         if (event
.LeftDown()) 
3921             state 
= wxAUI_BUTTON_STATE_HOVER
; 
3924     // now repaint the button with hover state 
3925     wxClientDC 
cdc(m_frame
); 
3927     // if the frame has a toolbar, the client area 
3928     // origin will not be (0,0). 
3929     wxPoint pt 
= m_frame
->GetClientAreaOrigin(); 
3930     if (pt
.x 
!= 0 || pt
.y 
!= 0) 
3931         cdc
.SetDeviceOrigin(pt
.x
, pt
.y
); 
3935         m_art
->DrawPaneButton(cdc
, m_frame
, 
3936                   button_ui_part
->button
->button_id
, 
3938                   button_ui_part
->rect
, 
3943 void wxAuiManager::OnLeftDown(wxMouseEvent
& event
) 
3945     m_currentDragItem 
= -1; 
3947     wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
3950         if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
|| 
3951             part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
3953             // Removing this restriction so that a centre pane can be resized 
3954             //if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) 
3957             // a dock may not be resized if it has a single 
3958             // pane which is not resizable 
3959             if (part
->type 
== wxAuiDockUIPart::typeDockSizer 
&& part
->dock 
&& 
3960                 part
->dock
->panes
.GetCount() == 1 && 
3961                 part
->dock
->panes
.Item(0)->IsFixed()) 
3964             // panes that may not be resized should be ignored here 
3965             if (part
->pane 
&& part
->pane
->IsFixed()) 
3968             m_action 
= actionResize
; 
3969             m_action_part 
= part
; 
3970             m_action_hintrect 
= wxRect(); 
3971             m_action_start 
= wxPoint(event
.m_x
, event
.m_y
); 
3972             m_action_offset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
3973                                       event
.m_y 
- part
->rect
.y
); 
3974             m_frame
->CaptureMouse(); 
3976         else if (part
->type 
== wxAuiDockUIPart::typePaneButton
) 
3978             m_action 
= actionClickButton
; 
3979             m_action_part 
= part
; 
3980             m_action_start 
= wxPoint(event
.m_x
, event
.m_y
); 
3981             m_frame
->CaptureMouse(); 
3983             UpdateButtonOnScreen(part
, event
); 
3985         else if (part
->type 
== wxAuiDockUIPart::typeCaption 
|| 
3986                   part
->type 
== wxAuiDockUIPart::typeGripper
) 
3988             // if we are managing a wxAuiFloatingFrame window, then 
3989             // we are an embedded wxAuiManager inside the wxAuiFloatingFrame. 
3990             // We want to initiate a toolbar drag in our owner manager 
3991             wxWindow
* managed_wnd 
= GetManagedWindow(); 
3994                 part
->pane
->window 
&& 
3996                 managed_wnd
->IsKindOf(CLASSINFO(wxAuiFloatingFrame
))) 
3998                 wxAuiFloatingFrame
* floating_frame 
= (wxAuiFloatingFrame
*)managed_wnd
; 
3999                 wxAuiManager
* owner_mgr 
= floating_frame
->GetOwnerManager(); 
4000                 owner_mgr
->StartPaneDrag(part
->pane
->window
, 
4001                                              wxPoint(event
.m_x 
- part
->rect
.x
, 
4002                                                      event
.m_y 
- part
->rect
.y
)); 
4008             if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4010                 // set the caption as active 
4011                 SetActivePane(m_panes
, part
->pane
->window
); 
4015             if (part
->dock 
&& part
->dock
->dock_direction 
== wxAUI_DOCK_CENTER
) 
4018             m_action 
= actionClickCaption
; 
4019             m_action_part 
= part
; 
4020             m_action_start 
= wxPoint(event
.m_x
, event
.m_y
); 
4021             m_action_offset 
= wxPoint(event
.m_x 
- part
->rect
.x
, 
4022                                       event
.m_y 
- part
->rect
.y
); 
4023             m_frame
->CaptureMouse(); 
4042 /// Ends a resize action, or for live update, resizes the sash 
4043 bool wxAuiManager::DoEndResizeAction(wxMouseEvent
& event
) 
4045     // resize the dock or the pane 
4046     if (m_action_part 
&& m_action_part
->type
==wxAuiDockUIPart::typeDockSizer
) 
4048         wxRect
& rect 
= m_action_part
->dock
->rect
; 
4050         wxPoint 
new_pos(event
.m_x 
- m_action_offset
.x
, 
4051             event
.m_y 
- m_action_offset
.y
); 
4053         switch (m_action_part
->dock
->dock_direction
) 
4055         case wxAUI_DOCK_LEFT
: 
4056             m_action_part
->dock
->size 
= new_pos
.x 
- rect
.x
; 
4058         case wxAUI_DOCK_TOP
: 
4059             m_action_part
->dock
->size 
= new_pos
.y 
- rect
.y
; 
4061         case wxAUI_DOCK_RIGHT
: 
4062             m_action_part
->dock
->size 
= rect
.x 
+ rect
.width 
- 
4063                 new_pos
.x 
- m_action_part
->rect
.GetWidth(); 
4065         case wxAUI_DOCK_BOTTOM
: 
4066             m_action_part
->dock
->size 
= rect
.y 
+ rect
.height 
- 
4067                 new_pos
.y 
- m_action_part
->rect
.GetHeight(); 
4074     else if (m_action_part 
&& 
4075         m_action_part
->type 
== wxAuiDockUIPart::typePaneSizer
) 
4077         wxAuiDockInfo
& dock 
= *m_action_part
->dock
; 
4078         wxAuiPaneInfo
& pane 
= *m_action_part
->pane
; 
4080         int total_proportion 
= 0; 
4081         int dock_pixels 
= 0; 
4082         int new_pixsize 
= 0; 
4084         int caption_size 
= m_art
->GetMetric(wxAUI_DOCKART_CAPTION_SIZE
); 
4085         int pane_border_size 
= m_art
->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE
); 
4086         int sash_size 
= m_art
->GetMetric(wxAUI_DOCKART_SASH_SIZE
); 
4088         wxPoint 
new_pos(event
.m_x 
- m_action_offset
.x
, 
4089             event
.m_y 
- m_action_offset
.y
); 
4091         // determine the pane rectangle by getting the pane part 
4092         wxAuiDockUIPart
* pane_part 
= GetPanePart(pane
.window
); 
4093         wxASSERT_MSG(pane_part
, 
4094             wxT("Pane border part not found -- shouldn't happen")); 
4096         // determine the new pixel size that the user wants; 
4097         // this will help us recalculate the pane's proportion 
4098         if (dock
.IsHorizontal()) 
4099             new_pixsize 
= new_pos
.x 
- pane_part
->rect
.x
; 
4101             new_pixsize 
= new_pos
.y 
- pane_part
->rect
.y
; 
4103         // determine the size of the dock, based on orientation 
4104         if (dock
.IsHorizontal()) 
4105             dock_pixels 
= dock
.rect
.GetWidth(); 
4107             dock_pixels 
= dock
.rect
.GetHeight(); 
4109         // determine the total proportion of all resizable panes, 
4110         // and the total size of the dock minus the size of all 
4112         int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4113         int pane_position 
= -1; 
4114         for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4116             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4117             if (p
.window 
== pane
.window
) 
4120             // while we're at it, subtract the pane sash 
4121             // width from the dock width, because this would 
4122             // skew our proportion calculations 
4124                 dock_pixels 
-= sash_size
; 
4126             // also, the whole size (including decorations) of 
4127             // all fixed panes must also be subtracted, because they 
4128             // are not part of the proportion calculation 
4131                 if (dock
.IsHorizontal()) 
4132                     dock_pixels 
-= p
.best_size
.x
; 
4134                     dock_pixels 
-= p
.best_size
.y
; 
4138                 total_proportion 
+= p
.dock_proportion
; 
4142         // find a pane in our dock to 'steal' space from or to 'give' 
4143         // space to -- this is essentially what is done when a pane is 
4144         // resized; the pane should usually be the first non-fixed pane 
4145         // to the right of the action pane 
4146         int borrow_pane 
= -1; 
4147         for (i 
= pane_position
+1; i 
< dock_pane_count
; ++i
) 
4149             wxAuiPaneInfo
& p 
= *dock
.panes
.Item(i
); 
4158         // demand that the pane being resized is found in this dock 
4159         // (this assert really never should be raised) 
4160         wxASSERT_MSG(pane_position 
!= -1, wxT("Pane not found in dock")); 
4162         // prevent division by zero 
4163         if (dock_pixels 
== 0 || total_proportion 
== 0 || borrow_pane 
== -1) 
4165             m_action 
= actionNone
; 
4169         // calculate the new proportion of the pane 
4170         int new_proportion 
= (new_pixsize
*total_proportion
)/dock_pixels
; 
4172         // default minimum size 
4175         // check against the pane's minimum size, if specified. please note 
4176         // that this is not enough to ensure that the minimum size will 
4177         // not be violated, because the whole frame might later be shrunk, 
4178         // causing the size of the pane to violate it's minimum size 
4179         if (pane
.min_size
.IsFullySpecified()) 
4183             if (pane
.HasBorder()) 
4184                 min_size 
+= (pane_border_size
*2); 
4186             // calculate minimum size with decorations (border,caption) 
4187             if (pane_part
->orientation 
== wxVERTICAL
) 
4189                 min_size 
+= pane
.min_size
.y
; 
4190                 if (pane
.HasCaption()) 
4191                     min_size 
+= caption_size
; 
4195                 min_size 
+= pane
.min_size
.x
; 
4200         // for some reason, an arithmatic error somewhere is causing 
4201         // the proportion calculations to always be off by 1 pixel; 
4202         // for now we will add the 1 pixel on, but we really should 
4203         // determine what's causing this. 
4206         int min_proportion 
= (min_size
*total_proportion
)/dock_pixels
; 
4208         if (new_proportion 
< min_proportion
) 
4209             new_proportion 
= min_proportion
; 
4213         int prop_diff 
= new_proportion 
- pane
.dock_proportion
; 
4215         // borrow the space from our neighbor pane to the 
4216         // right or bottom (depending on orientation) 
4217         dock
.panes
.Item(borrow_pane
)->dock_proportion 
-= prop_diff
; 
4218         pane
.dock_proportion 
= new_proportion
; 
4228 void wxAuiManager::OnLeftUp(wxMouseEvent
& event
) 
4230     if (m_action 
== actionResize
) 
4232         m_frame
->ReleaseMouse(); 
4234         if (!wxAuiManager_HasLiveResize(*this)) 
4236             // get rid of the hint rectangle 
4238             DrawResizeHint(dc
, m_action_hintrect
); 
4240         if (m_currentDragItem 
!= -1 && wxAuiManager_HasLiveResize(*this)) 
4241             m_action_part 
= & (m_uiparts
.Item(m_currentDragItem
)); 
4243         DoEndResizeAction(event
); 
4245         m_currentDragItem 
= -1; 
4248     else if (m_action 
== actionClickButton
) 
4250         m_hover_button 
= NULL
; 
4251         m_frame
->ReleaseMouse(); 
4255             UpdateButtonOnScreen(m_action_part
, event
); 
4257             // make sure we're still over the item that was originally clicked 
4258             if (m_action_part 
== HitTest(event
.GetX(), event
.GetY())) 
4260                 // fire button-click event 
4261                 wxAuiManagerEvent 
e(wxEVT_AUI_PANE_BUTTON
); 
4263                 e
.SetPane(m_action_part
->pane
); 
4264                 e
.SetButton(m_action_part
->button
->button_id
); 
4269     else if (m_action 
== actionClickCaption
) 
4271         m_frame
->ReleaseMouse(); 
4273     else if (m_action 
== actionDragFloatingPane
) 
4275         m_frame
->ReleaseMouse(); 
4277     else if (m_action 
== actionDragToolbarPane
) 
4279         m_frame
->ReleaseMouse(); 
4281         wxAuiPaneInfo
& pane 
= GetPane(m_action_window
); 
4282         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4284         // save the new positions 
4285         wxAuiDockInfoPtrArray docks
; 
4286         FindDocks(m_docks
, pane
.dock_direction
, 
4287                   pane
.dock_layer
, pane
.dock_row
, docks
); 
4288         if (docks
.GetCount() == 1) 
4290             wxAuiDockInfo
& dock 
= *docks
.Item(0); 
4292             wxArrayInt pane_positions
, pane_sizes
; 
4293             GetPanePositionsAndSizes(dock
, pane_positions
, pane_sizes
); 
4295             int i
, dock_pane_count 
= dock
.panes
.GetCount(); 
4296             for (i 
= 0; i 
< dock_pane_count
; ++i
) 
4297                 dock
.panes
.Item(i
)->dock_pos 
= pane_positions
[i
]; 
4300         pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4308     m_action 
= actionNone
; 
4309     m_last_mouse_move 
= wxPoint(); // see comment in OnMotion() 
4313 void wxAuiManager::OnMotion(wxMouseEvent
& event
) 
4315     // sometimes when Update() is called from inside this method, 
4316     // a spurious mouse move event is generated; this check will make 
4317     // sure that only real mouse moves will get anywhere in this method; 
4318     // this appears to be a bug somewhere, and I don't know where the 
4319     // mouse move event is being generated.  only verified on MSW 
4321     wxPoint mouse_pos 
= event
.GetPosition(); 
4322     if (m_last_mouse_move 
== mouse_pos
) 
4324     m_last_mouse_move 
= mouse_pos
; 
4327     if (m_action 
== actionResize
) 
4329         // It's necessary to reset m_action_part since it destroyed 
4330         // by the Update within DoEndResizeAction. 
4331         if (m_currentDragItem 
!= -1) 
4332             m_action_part 
= & (m_uiparts
.Item(m_currentDragItem
)); 
4334             m_currentDragItem 
= m_uiparts
.Index(* m_action_part
); 
4338             wxPoint pos 
= m_action_part
->rect
.GetPosition(); 
4339             if (m_action_part
->orientation 
== wxHORIZONTAL
) 
4340                 pos
.y 
= wxMax(0, event
.m_y 
- m_action_offset
.y
); 
4342                 pos
.x 
= wxMax(0, event
.m_x 
- m_action_offset
.x
); 
4344             if (wxAuiManager_HasLiveResize(*this)) 
4346                 m_frame
->ReleaseMouse(); 
4347                 DoEndResizeAction(event
); 
4348                 m_frame
->CaptureMouse(); 
4352                 wxRect 
rect(m_frame
->ClientToScreen(pos
), 
4353                     m_action_part
->rect
.GetSize()); 
4356                 if (!m_action_hintrect
.IsEmpty()) 
4357                     DrawResizeHint(dc
, m_action_hintrect
); 
4358                 DrawResizeHint(dc
, rect
); 
4359                 m_action_hintrect 
= rect
; 
4363     else if (m_action 
== actionClickCaption
) 
4365         int drag_x_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_X
); 
4366         int drag_y_threshold 
= wxSystemSettings::GetMetric(wxSYS_DRAG_Y
); 
4368         // caption has been clicked.  we need to check if the mouse 
4369         // is now being dragged. if it is, we need to change the 
4370         // mouse action to 'drag' 
4371         if (m_action_part 
&& 
4372             (abs(event
.m_x 
- m_action_start
.x
) > drag_x_threshold 
|| 
4373              abs(event
.m_y 
- m_action_start
.y
) > drag_y_threshold
)) 
4375             wxAuiPaneInfo
* pane_info 
= m_action_part
->pane
; 
4377             if (!pane_info
->IsToolbar()) 
4379                 if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) && 
4380                     pane_info
->IsFloatable()) 
4382                     m_action 
= actionDragFloatingPane
; 
4384                     // set initial float position 
4385                     wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4386                     pane_info
->floating_pos 
= wxPoint(pt
.x 
- m_action_offset
.x
, 
4387                                                       pt
.y 
- m_action_offset
.y
); 
4390                     if (pane_info
->IsMaximized()) 
4391                         RestorePane(*pane_info
); 
4395                     m_action_window 
= pane_info
->frame
; 
4397                     // action offset is used here to make it feel "natural" to the user 
4398                     // to drag a docked pane and suddenly have it become a floating frame. 
4399                     // Sometimes, however, the offset where the user clicked on the docked 
4400                     // caption is bigger than the width of the floating frame itself, so 
4401                     // in that case we need to set the action offset to a sensible value 
4402                     wxSize frame_size 
= m_action_window
->GetSize(); 
4403                     if (frame_size
.x 
<= m_action_offset
.x
) 
4404                         m_action_offset
.x 
= 30; 
4409                 m_action 
= actionDragToolbarPane
; 
4410                 m_action_window 
= pane_info
->window
; 
4414     else if (m_action 
== actionDragFloatingPane
) 
4416         if (m_action_window
) 
4418             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4419             m_action_window
->Move(pt
.x 
- m_action_offset
.x
, 
4420                                 pt
.y 
- m_action_offset
.y
); 
4423     else if (m_action 
== actionDragToolbarPane
) 
4425         wxAuiPaneInfo
& pane 
= GetPane(m_action_window
); 
4426         wxASSERT_MSG(pane
.IsOk(), wxT("Pane window not found")); 
4428         pane
.SetFlag(wxAuiPaneInfo::actionPane
, true); 
4430         wxPoint pt 
= event
.GetPosition(); 
4431         DoDrop(m_docks
, m_panes
, pane
, pt
, m_action_offset
); 
4433         // if DoDrop() decided to float the pane, set up 
4434         // the floating pane's initial position 
4435         if (pane
.IsFloating()) 
4437             wxPoint pt 
= m_frame
->ClientToScreen(event
.GetPosition()); 
4438             pane
.floating_pos 
= wxPoint(pt
.x 
- m_action_offset
.x
, 
4439                                         pt
.y 
- m_action_offset
.y
); 
4442         // this will do the actiual move operation; 
4443         // in the case that the pane has been floated, 
4444         // this call will create the floating pane 
4445         // and do the reparenting 
4448         // if the pane has been floated, change the mouse 
4449         // action actionDragFloatingPane so that subsequent 
4450         // EVT_MOTION() events will move the floating pane 
4451         if (pane
.IsFloating()) 
4453             pane
.state 
&= ~wxAuiPaneInfo::actionPane
; 
4454             m_action 
= actionDragFloatingPane
; 
4455             m_action_window 
= pane
.frame
; 
4460         wxAuiDockUIPart
* part 
= HitTest(event
.GetX(), event
.GetY()); 
4461         if (part 
&& part
->type 
== wxAuiDockUIPart::typePaneButton
) 
4463             if (part 
!= m_hover_button
) 
4465                 // make the old button normal 
4468                     UpdateButtonOnScreen(m_hover_button
, event
); 
4472                 // mouse is over a button, so repaint the 
4473                 // button in hover mode 
4474                 UpdateButtonOnScreen(part
, event
); 
4475                 m_hover_button 
= part
; 
4483                 m_hover_button 
= NULL
; 
4494 void wxAuiManager::OnLeaveWindow(wxMouseEvent
& WXUNUSED(event
)) 
4498         m_hover_button 
= NULL
; 
4503 void wxAuiManager::OnCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
)) 
4505     // cancel the operation in progress, if any 
4506     if ( m_action 
!= actionNone 
) 
4508         m_action 
= actionNone
; 
4513 void wxAuiManager::OnChildFocus(wxChildFocusEvent
& event
) 
4515     // when a child pane has it's focus set, we should change the 
4516     // pane's active state to reflect this. (this is only true if 
4517     // active panes are allowed by the owner) 
4518     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE
) 
4520         wxAuiPaneInfo
& pane 
= GetPane(event
.GetWindow()); 
4521         if (pane
.IsOk() && (pane
.state 
& wxAuiPaneInfo::optionActive
) == 0) 
4523             SetActivePane(m_panes
, event
.GetWindow()); 
4532 // OnPaneButton() is an event handler that is called 
4533 // when a pane button has been pressed. 
4534 void wxAuiManager::OnPaneButton(wxAuiManagerEvent
& evt
) 
4536     wxASSERT_MSG(evt
.pane
, wxT("Pane Info passed to wxAuiManager::OnPaneButton must be non-null")); 
4538     wxAuiPaneInfo
& pane 
= *(evt
.pane
); 
4540     if (evt
.button 
== wxAUI_BUTTON_CLOSE
) 
4542         // fire pane close event 
4543         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_CLOSE
); 
4545         e
.SetPane(evt
.pane
); 
4550             // close the pane, but check that it 
4551             // still exists in our pane array first 
4552             // (the event handler above might have removed it) 
4554             wxAuiPaneInfo
& check 
= GetPane(pane
.window
); 
4563     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& !pane
.IsMaximized()) 
4565         // fire pane close event 
4566         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_MAXIMIZE
); 
4568         e
.SetPane(evt
.pane
); 
4577     else if (evt
.button 
== wxAUI_BUTTON_MAXIMIZE_RESTORE 
&& pane
.IsMaximized()) 
4579         // fire pane close event 
4580         wxAuiManagerEvent 
e(wxEVT_AUI_PANE_RESTORE
); 
4582         e
.SetPane(evt
.pane
); 
4591     else if (evt
.button 
== wxAUI_BUTTON_PIN
) 
4593         if ((m_flags 
& wxAUI_MGR_ALLOW_FLOATING
) &&