framemanager.cpp

Go to the documentation of this file.
00001 
00002 // Name:        src/aui/framemanager.cpp
00003 // Purpose:     wxaui: wx advanced user interface - docking window manager
00004 // Author:      Benjamin I. Williams
00005 // Modified by:
00006 // Created:     2005-05-17
00007 // RCS-ID:      $Id: framemanager.cpp,v 1.17 2006/07/05 16:39:04 BIW Exp $
00008 // Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
00009 // Licence:     wxWindows Library Licence, Version 3.1
00011 
00012 // ============================================================================
00013 // declarations
00014 // ============================================================================
00015 
00016 // ----------------------------------------------------------------------------
00017 // headers
00018 // ----------------------------------------------------------------------------
00019 
00020 #include "framemanager.h"
00021 #include "dockart.h"
00022 #include "floatpane.h"
00023 
00024 #if wxXTRA_AUI
00025 
00026 #include <wx/settings.h>
00027 #include <wx/app.h>
00028 #include <wx/dcclient.h>
00029 #include <wx/dcscreen.h>
00030 #include <wx/toolbar.h>
00031 #include <wx/mdi.h>
00032 #include <wx/image.h>
00033 
00034 #include <wx/arrimpl.cpp>
00035 WX_DECLARE_OBJARRAY(wxRect, wxAuiRectArray);
00036 WX_DEFINE_OBJARRAY(wxAuiRectArray)
00037 WX_DEFINE_OBJARRAY(wxAuiDockUIPartArray)
00038 WX_DEFINE_OBJARRAY(wxAuiDockInfoArray)
00039 WX_DEFINE_OBJARRAY(wxAuiPaneButtonArray)
00040 WX_DEFINE_OBJARRAY(wxAuiPaneInfoArray)
00041 
00042 wxAuiPaneInfo wxAuiNullPaneInfo;
00043 wxAuiDockInfo wxAuiNullDockInfo;
00044 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_BUTTON)
00045 DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_CLOSE)
00046 DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER)
00047 
00048 #ifdef __WXMAC__
00049     // a few defines to avoid nameclashes
00050     #define __MAC_OS_X_MEMORY_MANAGER_CLEAN__ 1
00051     #define __AIFF__
00052     #include "wx/mac/private.h"
00053 #endif
00054 
00055 IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent, wxEvent)
00056 
00057 class wxPseudoTransparentFrame : public wxFrame
00058 {
00059 public:
00060     wxPseudoTransparentFrame(wxWindow* parent = NULL,
00061                 wxWindowID id = wxID_ANY,
00062                 const wxString& title = wxEmptyString,
00063                 const wxPoint& pos = wxDefaultPosition,
00064                 const wxSize& size = wxDefaultSize,
00065                 long style = wxDEFAULT_FRAME_STYLE,
00066                 const wxString &name = wxT("frame"))
00067                     : wxFrame(parent, id, title, pos, size, style | wxFRAME_SHAPED, name)
00068     {
00069         SetBackgroundStyle(wxBG_STYLE_CUSTOM);
00070         m_Amount=0;
00071         m_MaxWidth=0;
00072         m_MaxHeight=0;
00073 #ifdef __WXGTK__
00074         m_CanSetShape = false; // have to wait for window create event on GTK
00075 #else
00076         m_CanSetShape = true;
00077 #endif
00078         SetTransparent(0);
00079     }
00080 
00081     virtual bool SetTransparent(wxByte alpha)
00082     {
00083         if (m_CanSetShape)
00084         {
00085             int w=100; // some defaults
00086             int h=100;
00087             GetClientSize(&w, &h);
00088             if ((alpha != m_Amount) || (m_MaxWidth<w) | (m_MaxHeight<h))
00089             {
00090                 // Make the region at least double the height and width so we don't have
00091                 // to rebuild if the size changes.
00092                 m_MaxWidth=w*2;
00093                 m_MaxHeight=h*2;
00094                 m_Amount = alpha;
00095                 m_Region.Clear();
00096 //                m_Region.Union(0, 0, 1, m_MaxWidth);
00097                 if (m_Amount)
00098                 {
00099                     for (int y=0; y<m_MaxHeight; y++)
00100                     {
00101                         // Reverse the order of the bottom 4 bits
00102                         int j=((y&8)?1:0)|((y&4)?2:0)|((y&2)?4:0)|((y&1)?8:0);
00103                         if ((j*16+8)<m_Amount)
00104                             m_Region.Union(0, y, m_MaxWidth, 1);
00105                     }
00106                 }
00107                 SetShape(m_Region);
00108                 Refresh();
00109             }
00110         }
00111         return true;
00112     }
00113 
00114     void OnPaint(wxPaintEvent& WXUNUSED(event))
00115     {
00116         wxPaintDC dc(this);
00117 
00118         dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
00119         dc.SetPen(*wxTRANSPARENT_PEN);
00120 
00121         wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
00122 
00123         while (upd)
00124         {
00125             wxRect rect(upd.GetRect());
00126             dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
00127 
00128             upd++;
00129         }
00130     }
00131 
00132 #ifdef __WXGTK__
00133     void OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event)) {m_CanSetShape=true; SetTransparent(0);}
00134 #endif
00135 
00136 private:
00137     int m_Amount;
00138     int m_MaxWidth;
00139     int m_MaxHeight;
00140     bool m_CanSetShape;
00141 
00142     wxRegion m_Region;
00143 
00144     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame)
00145     DECLARE_EVENT_TABLE()
00146 };
00147 
00148 
00149 IMPLEMENT_DYNAMIC_CLASS( wxPseudoTransparentFrame, wxFrame )
00150 
00151 BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame)
00152     EVT_PAINT(wxPseudoTransparentFrame::OnPaint)
00153 #ifdef __WXGTK__
00154     EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate)
00155 #endif
00156 END_EVENT_TABLE()
00157 
00158 
00159 // -- static utility functions --
00160 
00161 static wxBitmap wxPaneCreateStippleBitmap()
00162 {
00163     unsigned char data[] = { 0,0,0,192,192,192, 192,192,192,0,0,0 };
00164     wxImage img(2,2,data,true);
00165     return wxBitmap(img);
00166 }
00167 
00168 static void DrawResizeHint(wxDC& dc, const wxRect& rect)
00169 {
00170     wxBitmap stipple = wxPaneCreateStippleBitmap();
00171     wxBrush brush(stipple);
00172     dc.SetBrush(brush);
00173     dc.SetPen(*wxTRANSPARENT_PEN);
00174 
00175     dc.SetLogicalFunction(wxXOR);
00176     dc.DrawRectangle(rect);
00177 }
00178 
00179 
00180 
00181 // CopyDocksAndPanes() - this utility function creates copies of
00182 // the dock and pane info.  wxAuiDockInfo's usually contain pointers
00183 // to wxAuiPaneInfo classes, thus this function is necessary to reliably
00184 // reconstruct that relationship in the new dock info and pane info arrays
00185 
00186 static void CopyDocksAndPanes(wxAuiDockInfoArray& dest_docks,
00187                               wxAuiPaneInfoArray& dest_panes,
00188                               const wxAuiDockInfoArray& src_docks,
00189                               const wxAuiPaneInfoArray& src_panes)
00190 {
00191     dest_docks = src_docks;
00192     dest_panes = src_panes;
00193     int i, j, k, dock_count, pc1, pc2;
00194     for (i = 0, dock_count = dest_docks.GetCount(); i < dock_count; ++i)
00195     {
00196         wxAuiDockInfo& dock = dest_docks.Item(i);
00197         for (j = 0, pc1 = dock.panes.GetCount(); j < pc1; ++j)
00198             for (k = 0, pc2 = src_panes.GetCount(); k < pc2; ++k)
00199                 if (dock.panes.Item(j) == &src_panes.Item(k))
00200                     dock.panes.Item(j) = &dest_panes.Item(k);
00201     }
00202 }
00203 
00204 // GetMaxLayer() is an internal function which returns
00205 // the highest layer inside the specified dock
00206 static int GetMaxLayer(const wxAuiDockInfoArray& docks, int dock_direction)
00207 {
00208     int i, dock_count, max_layer = 0;
00209     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
00210     {
00211         wxAuiDockInfo& dock = docks.Item(i);
00212         if (dock.dock_direction == dock_direction &&
00213             dock.dock_layer > max_layer && !dock.fixed)
00214                 max_layer = dock.dock_layer;
00215     }
00216     return max_layer;
00217 }
00218 
00219 
00220 // GetMaxRow() is an internal function which returns
00221 // the highest layer inside the specified dock
00222 static int GetMaxRow(const wxAuiPaneInfoArray& panes, int direction, int layer)
00223 {
00224     int i, pane_count, max_row = 0;
00225     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
00226     {
00227         wxAuiPaneInfo& pane = panes.Item(i);
00228         if (pane.dock_direction == direction &&
00229             pane.dock_layer == layer &&
00230             pane.dock_row > max_row)
00231                 max_row = pane.dock_row;
00232     }
00233     return max_row;
00234 }
00235 
00236 
00237 
00238 // DoInsertDockLayer() is an internal function that inserts a new dock
00239 // layer by incrementing all existing dock layer values by one
00240 static void DoInsertDockLayer(wxAuiPaneInfoArray& panes,
00241                               int dock_direction,
00242                               int dock_layer)
00243 {
00244     int i, pane_count;
00245     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
00246     {
00247         wxAuiPaneInfo& pane = panes.Item(i);
00248         if (!pane.IsFloating() &&
00249             pane.dock_direction == dock_direction &&
00250             pane.dock_layer >= dock_layer)
00251                 pane.dock_layer++;
00252     }
00253 }
00254 
00255 // DoInsertDockLayer() is an internal function that inserts a new dock
00256 // row by incrementing all existing dock row values by one
00257 static void DoInsertDockRow(wxAuiPaneInfoArray& panes,
00258                             int dock_direction,
00259                             int dock_layer,
00260                             int dock_row)
00261 {
00262     int i, pane_count;
00263     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
00264     {
00265         wxAuiPaneInfo& pane = panes.Item(i);
00266         if (!pane.IsFloating() &&
00267             pane.dock_direction == dock_direction &&
00268             pane.dock_layer == dock_layer &&
00269             pane.dock_row >= dock_row)
00270                 pane.dock_row++;
00271     }
00272 }
00273 
00274 // DoInsertDockLayer() is an internal function that inserts a space for
00275 // another dock pane by incrementing all existing dock row values by one
00276 static void DoInsertPane(wxAuiPaneInfoArray& panes,
00277                          int dock_direction,
00278                          int dock_layer,
00279                          int dock_row,
00280                          int dock_pos)
00281 {
00282     int i, pane_count;
00283     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
00284     {
00285         wxAuiPaneInfo& pane = panes.Item(i);
00286         if (!pane.IsFloating() &&
00287             pane.dock_direction == dock_direction &&
00288             pane.dock_layer == dock_layer &&
00289             pane.dock_row == dock_row &&
00290             pane.dock_pos >= dock_pos)
00291                 pane.dock_pos++;
00292     }
00293 }
00294 
00295 // FindDocks() is an internal function that returns a list of docks which meet
00296 // the specified conditions in the parameters and returns a sorted array
00297 // (sorted by layer and then row)
00298 static void FindDocks(wxAuiDockInfoArray& docks,
00299                       int dock_direction,
00300                       int dock_layer,
00301                       int dock_row,
00302                       wxAuiDockInfoPtrArray& arr)
00303 {
00304     int begin_layer = dock_layer;
00305     int end_layer = dock_layer;
00306     int begin_row = dock_row;
00307     int end_row = dock_row;
00308     int dock_count = docks.GetCount();
00309     int layer, row, i, max_row = 0, max_layer = 0;
00310 
00311     // discover the maximum dock layer and the max row
00312     for (i = 0; i < dock_count; ++i)
00313     {
00314         max_row = wxMax(max_row, docks.Item(i).dock_row);
00315         max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
00316     }
00317 
00318     // if no dock layer was specified, search all dock layers
00319     if (dock_layer == -1)
00320     {
00321         begin_layer = 0;
00322         end_layer = max_layer;
00323     }
00324 
00325     // if no dock row was specified, search all dock row
00326     if (dock_row == -1)
00327     {
00328         begin_row = 0;
00329         end_row = max_row;
00330     }
00331 
00332     arr.Clear();
00333 
00334     for (layer = begin_layer; layer <= end_layer; ++layer)
00335         for (row = begin_row; row <= end_row; ++row)
00336             for (i = 0; i < dock_count; ++i)
00337             {
00338                 wxAuiDockInfo& d = docks.Item(i);
00339                 if (dock_direction == -1 || dock_direction == d.dock_direction)
00340                 {
00341                     if (d.dock_layer == layer && d.dock_row == row)
00342                         arr.Add(&d);
00343                 }
00344             }
00345 }
00346 
00347 // FindPaneInDock() looks up a specified window pointer inside a dock.
00348 // If found, the corresponding wxAuiPaneInfo pointer is returned, otherwise NULL.
00349 static wxAuiPaneInfo* FindPaneInDock(const wxAuiDockInfo& dock, wxWindow* window)
00350 {
00351     int i, count = dock.panes.GetCount();
00352     for (i = 0; i < count; ++i)
00353     {
00354         wxAuiPaneInfo* p = dock.panes.Item(i);
00355         if (p->window == window)
00356             return p;
00357     }
00358     return NULL;
00359 }
00360 
00361 // RemovePaneFromDocks() removes a pane window from all docks
00362 // with a possible exception specified by parameter "except"
00363 static void RemovePaneFromDocks(wxAuiDockInfoArray& docks,
00364                                 wxAuiPaneInfo& pane,
00365                                 wxAuiDockInfo* except = NULL)
00366 {
00367     int i, dock_count;
00368     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
00369     {
00370         wxAuiDockInfo& d = docks.Item(i);
00371         if (&d == except)
00372             continue;
00373         wxAuiPaneInfo* pi = FindPaneInDock(d, pane.window);
00374         if (pi)
00375             d.panes.Remove(pi);
00376     }
00377 }
00378 
00379 // RenumberDockRows() takes a dock and assigns sequential numbers
00380 // to existing rows.  Basically it takes out the gaps; so if a
00381 // dock has rows with numbers 0,2,5, they will become 0,1,2
00382 static void RenumberDockRows(wxAuiDockInfoPtrArray& docks)
00383 {
00384     int i, dock_count, j, pane_count;
00385     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
00386     {
00387         wxAuiDockInfo& dock = *docks.Item(i);
00388         dock.dock_row = i;
00389         for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j)
00390             dock.panes.Item(j)->dock_row = i;
00391     }
00392 }
00393 
00394 
00395 // SetActivePane() sets the active pane, as well as cycles through
00396 // every other pane and makes sure that all others' active flags
00397 // are turned off
00398 static void SetActivePane(wxAuiPaneInfoArray& panes, wxWindow* active_pane)
00399 {
00400     int i, pane_count;
00401     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
00402     {
00403         wxAuiPaneInfo& pane = panes.Item(i);
00404         pane.state &= ~wxAuiPaneInfo::optionActive;
00405         if (pane.window == active_pane)
00406             pane.state |= wxAuiPaneInfo::optionActive;
00407     }
00408 }
00409 
00410 
00411 // this function is used to sort panes by dock position
00412 static int PaneSortFunc(wxAuiPaneInfo** p1, wxAuiPaneInfo** p2)
00413 {
00414     return ((*p1)->dock_pos < (*p2)->dock_pos) ? -1 : 1;
00415 }
00416 
00417 
00418 // -- wxAuiManager class implementation --
00419 
00420 
00421 BEGIN_EVENT_TABLE(wxAuiManager, wxEvtHandler)
00422     EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton)
00423     EVT_AUI_RENDER(wxAuiManager::OnRender)
00424     EVT_PAINT(wxAuiManager::OnPaint)
00425     EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground)
00426     EVT_SIZE(wxAuiManager::OnSize)
00427     EVT_SET_CURSOR(wxAuiManager::OnSetCursor)
00428     EVT_LEFT_DOWN(wxAuiManager::OnLeftDown)
00429     EVT_LEFT_UP(wxAuiManager::OnLeftUp)
00430     EVT_MOTION(wxAuiManager::OnMotion)
00431     EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow)
00432     EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus)
00433     EVT_TIMER(101, wxAuiManager::OnHintFadeTimer)
00434 END_EVENT_TABLE()
00435 
00436 
00437 wxAuiManager::wxAuiManager(wxWindow* managed_wnd, unsigned int flags)
00438 {
00439     m_action = actionNone;
00440     m_last_mouse_move = wxPoint();
00441     m_hover_button = NULL;
00442     m_art = new wxAuiDefaultDockArt;
00443     m_hint_wnd = NULL;
00444     m_flags = flags;
00445 
00446     if (managed_wnd)
00447     {
00448         SetManagedWindow(managed_wnd);
00449     }
00450 }
00451 
00452 wxAuiManager::~wxAuiManager()
00453 {
00454     delete m_art;
00455 }
00456 
00457 // GetPane() looks up a wxAuiPaneInfo structure based
00458 // on the supplied window pointer.  Upon failure, GetPane()
00459 // returns an empty wxAuiPaneInfo, a condition which can be checked
00460 // by calling wxAuiPaneInfo::IsOk().
00461 //
00462 // The pane info's structure may then be modified.  Once a pane's
00463 // info is modified, wxAuiManager::Update() must be called to
00464 // realize the changes in the UI.
00465 
00466 wxAuiPaneInfo& wxAuiManager::GetPane(wxWindow* window)
00467 {
00468     int i, pane_count;
00469     for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
00470     {
00471         wxAuiPaneInfo& p = m_panes.Item(i);
00472         if (p.window == window)
00473             return p;
00474     }
00475     return wxAuiNullPaneInfo;
00476 }
00477 
00478 // this version of GetPane() looks up a pane based on a
00479 // 'pane name', see above comment for more info
00480 wxAuiPaneInfo& wxAuiManager::GetPane(const wxString& name)
00481 {
00482     int i, pane_count;
00483     for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
00484     {
00485         wxAuiPaneInfo& p = m_panes.Item(i);
00486         if (p.name == name)
00487             return p;
00488     }
00489     return wxAuiNullPaneInfo;
00490 }
00491 
00492 // GetAllPanes() returns a reference to all the pane info structures
00493 wxAuiPaneInfoArray& wxAuiManager::GetAllPanes()
00494 {
00495     return m_panes;
00496 }
00497 
00498 // HitTest() is an internal function which determines
00499 // which UI item the specified coordinates are over
00500 // (x,y) specify a position in client coordinates
00501 wxAuiDockUIPart* wxAuiManager::HitTest(int x, int y)
00502 {
00503     wxAuiDockUIPart* result = NULL;
00504 
00505     int i, part_count;
00506     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
00507     {
00508         wxAuiDockUIPart* item = &m_uiparts.Item(i);
00509 
00510         // we are not interested in typeDock, because this space
00511         // isn't used to draw anything, just for measurements;
00512         // besides, the entire dock area is covered with other
00513         // rectangles, which we are interested in.
00514         if (item->type == wxAuiDockUIPart::typeDock)
00515             continue;
00516 
00517         // if we already have a hit on a more specific item, we are not
00518         // interested in a pane hit.  If, however, we don't already have
00519         // a hit, returning a pane hit is necessary for some operations
00520         if ((item->type == wxAuiDockUIPart::typePane ||
00521             item->type == wxAuiDockUIPart::typePaneBorder) && result)
00522             continue;
00523 
00524         // if the point is inside the rectangle, we have a hit
00525         if (item->rect.Inside(x,y))
00526             result = item;
00527     }
00528 
00529     return result;
00530 }
00531 
00532 
00533 // SetFlags() and GetFlags() allow the owner to set various
00534 // options which are global to wxAuiManager
00535 void wxAuiManager::SetFlags(unsigned int flags)
00536 {
00537     m_flags = flags;
00538 }
00539 
00540 unsigned int wxAuiManager::GetFlags() const
00541 {
00542     return m_flags;
00543 }
00544 
00545 
00546 // don't use these anymore as they are deprecated
00547 // use Set/GetManagedFrame() instead
00548 void wxAuiManager::SetFrame(wxFrame* frame)
00549 {
00550     SetManagedWindow((wxWindow*)frame);
00551 }
00552 
00553 wxFrame* wxAuiManager::GetFrame() const
00554 {
00555     return (wxFrame*)m_frame;
00556 }
00557 
00558 
00559 
00560 
00561 // SetManagedWindow() is usually called once when the frame
00562 // manager class is being initialized.  "frame" specifies
00563 // the frame which should be managed by the frame mananger
00564 void wxAuiManager::SetManagedWindow(wxWindow* frame)
00565 {
00566     wxASSERT_MSG(frame, wxT("specified frame must be non-NULL"));
00567 
00568     m_frame = frame;
00569     m_frame->PushEventHandler(this);
00570 
00571 #if wxUSE_MDI
00572     // if the owner is going to manage an MDI parent frame,
00573     // we need to add the MDI client window as the default
00574     // center pane
00575 
00576     if (frame->IsKindOf(CLASSINFO(wxMDIParentFrame)))
00577     {
00578         wxMDIParentFrame* mdi_frame = (wxMDIParentFrame*)frame;
00579         wxWindow* client_window = mdi_frame->GetClientWindow();
00580 
00581         wxASSERT_MSG(client_window, wxT("Client window is NULL!"));
00582 
00583         AddPane(client_window,
00584                 wxAuiPaneInfo().Name(wxT("mdiclient")).
00585                 CenterPane().PaneBorder(false));
00586     }
00587 #endif
00588 
00589     // Make a window to use for a transparent hint
00590 #if defined(__WXMSW__) || defined(__WXGTK__)
00591     m_hint_wnd = new wxFrame(m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
00592                              wxFRAME_TOOL_WINDOW |
00593                              wxFRAME_FLOAT_ON_PARENT |
00594                              wxFRAME_NO_TASKBAR |
00595                              wxNO_BORDER);
00596 
00597     m_hint_wnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
00598 
00599 #elif defined(__WXMAC__)
00600     // Using a miniframe with float and tool styles keeps the parent
00601     // frame activated and highlighted as such...
00602     m_hint_wnd = new wxMiniFrame(m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
00603                                  wxFRAME_FLOAT_ON_PARENT
00604                                  | wxFRAME_TOOL_WINDOW
00605                                  | wxCAPTION );
00606 
00607     // Can't set the bg colour of a Frame in wxMac
00608     wxPanel* p = new wxPanel(m_hint_wnd);
00609 
00610     // The default wxSYS_COLOUR_ACTIVECAPTION colour is a light silver
00611     // color that is really hard to see, especially transparent.
00612     // Until a better system color is decided upon we'll just use
00613     // blue.
00614     p->SetBackgroundColour(*wxBLUE);
00615 #endif
00616 
00617     m_hint_fademax=50;
00618 
00619     if (m_hint_wnd
00620         // CanSetTransparent is only present in the 2.7.0 ABI. To allow this file to be easily used
00621         // in a backported environment, conditionally compile this in.
00622 #if wxCHECK_VERSION(2,7,0)
00623        && !m_hint_wnd->CanSetTransparent()
00624 #endif
00625         )
00626     {
00627 
00628         m_hint_wnd->Close();
00629         m_hint_wnd->Destroy();
00630         m_hint_wnd = NULL;
00631 
00632         // If we can convert it to a PseudoTransparent window, do so
00633         m_hint_wnd = new wxPseudoTransparentFrame (m_frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(1,1),
00634                                                 wxFRAME_TOOL_WINDOW |
00635                                                 wxFRAME_FLOAT_ON_PARENT |
00636                                                 wxFRAME_NO_TASKBAR |
00637                                                 wxNO_BORDER);
00638 
00639         m_hint_fademax = 128;
00640     }
00641 }
00642 
00643 
00644 // UnInit() must be called, usually in the destructor
00645 // of the frame class.   If it is not called, usually this
00646 // will result in a crash upon program exit
00647 void wxAuiManager::UnInit()
00648 {
00649     m_frame->RemoveEventHandler(this);
00650 }
00651 
00652 // GetManagedWindow() returns the window pointer being managed
00653 wxWindow* wxAuiManager::GetManagedWindow() const
00654 {
00655     return m_frame;
00656 }
00657 
00658 wxAuiDockArt* wxAuiManager::GetArtProvider() const
00659 {
00660     return m_art;
00661 }
00662 
00663 void wxAuiManager::ProcessMgrEvent(wxAuiManagerEvent& event)
00664 {
00665     // first, give the owner frame a chance to override
00666     if (m_frame)
00667     {
00668         if (m_frame->ProcessEvent(event))
00669             return;
00670     }
00671 
00672     ProcessEvent(event);
00673 }
00674 
00675 // SetArtProvider() instructs wxAuiManager to use the
00676 // specified art provider for all drawing calls.  This allows
00677 // plugable look-and-feel features.  The pointer that is
00678 // passed to this method subsequently belongs to wxAuiManager,
00679 // and is deleted in the frame manager destructor
00680 void wxAuiManager::SetArtProvider(wxAuiDockArt* art_provider)
00681 {
00682     // delete the last art provider, if any
00683     delete m_art;
00684 
00685     // assign the new art provider
00686     m_art = art_provider;
00687 }
00688 
00689 
00690 bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info)
00691 {
00692     // check if the pane has a valid window
00693     if (!window)
00694         return false;
00695 
00696     // check if the pane already exists
00697     if (GetPane(pane_info.window).IsOk())
00698         return false;
00699 
00700     m_panes.Add(pane_info);
00701 
00702     wxAuiPaneInfo& pinfo = m_panes.Last();
00703 
00704     // set the pane window
00705     pinfo.window = window;
00706 
00707     // if the pane's name identifier is blank, create a random string
00708     if (pinfo.name.empty())
00709     {
00710         pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"),
00711              ((unsigned long)pinfo.window) & 0xffffffff,
00712              (unsigned int)time(NULL),
00713 #ifdef __WXWINCE__
00714              (unsigned int)GetTickCount(),
00715 #else
00716              (unsigned int)clock(),
00717 #endif
00718              (unsigned long)m_panes.GetCount());
00719     }
00720 
00721     // set initial proportion (if not already set)
00722     if (pinfo.dock_proportion == 0)
00723         pinfo.dock_proportion = 100000;
00724 
00725     if (pinfo.HasCloseButton() &&
00726         pinfo.buttons.size() == 0)
00727     {
00728         wxAuiPaneButton button;
00729         button.button_id = wxAuiPaneInfo::buttonClose;
00730         pinfo.buttons.Add(button);
00731     }
00732 
00733     if (pinfo.best_size == wxDefaultSize &&
00734         pinfo.window)
00735     {
00736         pinfo.best_size = pinfo.window->GetClientSize();
00737 
00738         if (pinfo.window->IsKindOf(CLASSINFO(wxToolBar)))
00739         {
00740             // GetClientSize() doesn't get the best size for
00741             // a toolbar under some newer versions of wxWidgets,
00742             // so use GetBestSize()
00743             pinfo.best_size = pinfo.window->GetBestSize();
00744 
00745             // for some reason, wxToolBar::GetBestSize() is returning
00746             // a size that is a pixel shy of the correct amount.
00747             // I believe this to be the correct action, until
00748             // wxToolBar::GetBestSize() is fixed.  Is this assumption
00749             // correct?
00750             pinfo.best_size.y++;
00751         }
00752 
00753         if (pinfo.min_size != wxDefaultSize)
00754         {
00755             if (pinfo.best_size.x < pinfo.min_size.x)
00756                 pinfo.best_size.x = pinfo.min_size.x;
00757             if (pinfo.best_size.y < pinfo.min_size.y)
00758                 pinfo.best_size.y = pinfo.min_size.y;
00759         }
00760     }
00761 
00762     return true;
00763 }
00764 
00765 bool wxAuiManager::AddPane(wxWindow* window,
00766                              int direction,
00767                              const wxString& caption)
00768 {
00769     wxAuiPaneInfo pinfo;
00770     pinfo.Caption(caption);
00771     switch (direction)
00772     {
00773         case wxTOP:    pinfo.Top(); break;
00774         case wxBOTTOM: pinfo.Bottom(); break;
00775         case wxLEFT:   pinfo.Left(); break;
00776         case wxRIGHT:  pinfo.Right(); break;
00777         case wxCENTER: pinfo.CenterPane(); break;
00778     }
00779     return AddPane(window, pinfo);
00780 }
00781 
00782 bool wxAuiManager::AddPane(wxWindow* window,
00783                              const wxAuiPaneInfo& pane_info,
00784                              const wxPoint& drop_pos)
00785 {
00786     if (!AddPane(window, pane_info))
00787         return false;
00788 
00789     wxAuiPaneInfo& pane = GetPane(window);
00790 
00791     DoDrop(m_docks, m_panes, pane, drop_pos, wxPoint(0,0));
00792 
00793     return true;
00794 }
00795 
00796 bool wxAuiManager::InsertPane(wxWindow* window, const wxAuiPaneInfo& pane_info,
00797                                 int insert_level)
00798 {
00799     // shift the panes around, depending on the insert level
00800     switch (insert_level)
00801     {
00802         case wxAUI_INSERT_PANE:
00803             DoInsertPane(m_panes,
00804                  pane_info.dock_direction,
00805                  pane_info.dock_layer,
00806                  pane_info.dock_row,
00807                  pane_info.dock_pos);
00808             break;
00809         case wxAUI_INSERT_ROW:
00810             DoInsertDockRow(m_panes,
00811                  pane_info.dock_direction,
00812                  pane_info.dock_layer,
00813                  pane_info.dock_row);
00814             break;
00815         case wxAUI_INSERT_DOCK:
00816             DoInsertDockLayer(m_panes,
00817                  pane_info.dock_direction,
00818                  pane_info.dock_layer);
00819             break;
00820     }
00821 
00822     // if the window already exists, we are basically just moving/inserting the
00823     // existing window.  If it doesn't exist, we need to add it and insert it
00824     wxAuiPaneInfo& existing_pane = GetPane(window);
00825     if (!existing_pane.IsOk())
00826     {
00827         return AddPane(window, pane_info);
00828     }
00829     else
00830     {
00831         if (pane_info.IsFloating())
00832         {
00833             existing_pane.Float();
00834             if (pane_info.floating_pos != wxDefaultPosition)
00835                 existing_pane.FloatingPosition(pane_info.floating_pos);
00836             if (pane_info.floating_size != wxDefaultSize)
00837                 existing_pane.FloatingSize(pane_info.floating_size);
00838         }
00839          else
00840         {
00841             existing_pane.Direction(pane_info.dock_direction);
00842             existing_pane.Layer(pane_info.dock_layer);
00843             existing_pane.Row(pane_info.dock_row);
00844             existing_pane.Position(pane_info.dock_pos);
00845         }
00846     }
00847 
00848     return true;
00849 }
00850 
00851 
00852 // DetachPane() removes a pane from the frame manager.  This
00853 // method will not destroy the window that is removed.
00854 bool wxAuiManager::DetachPane(wxWindow* window)
00855 {
00856     int i, count;
00857     for (i = 0, count = m_panes.GetCount(); i < count; ++i)
00858     {
00859         wxAuiPaneInfo& p = m_panes.Item(i);
00860         if (p.window == window)
00861         {
00862             if (p.frame)
00863             {
00864                 // we have a floating frame which is being detached. We need to
00865                 // reparent it to m_frame and destroy the floating frame
00866 
00867                 // reduce flicker
00868                 p.window->SetSize(1,1);
00869                 p.frame->Show(false);
00870 
00871                 // reparent to m_frame and destroy the pane
00872                 p.window->Reparent(m_frame);
00873                 p.frame->SetSizer(NULL);
00874                 p.frame->Destroy();
00875                 p.frame = NULL;
00876             }
00877 
00878             // make sure there are no references to this pane in our uiparts,
00879             // just in case the caller doesn't call Update() immediately after
00880             // the DetachPane() call.  This prevets obscure crashes which would
00881             // happen at window repaint if the caller forgets to call Update()
00882             int pi, part_count;
00883             for (pi = 0, part_count = (int)m_uiparts.GetCount(); pi < part_count; ++pi)
00884             {
00885                 wxAuiDockUIPart& part = m_uiparts.Item(pi);
00886                 if (part.pane == &p)
00887                 {
00888                     m_uiparts.RemoveAt(pi);
00889                     part_count--;
00890                     pi--;
00891                     continue;
00892                 }
00893             }
00894 
00895             m_panes.RemoveAt(i);
00896             return true;
00897         }
00898     }
00899     return false;
00900 }
00901 
00902 
00903 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
00904 // in the input string.  This is an internal functions which is
00905 // used for saving perspectives
00906 static wxString EscapeDelimiters(const wxString& s)
00907 {
00908     wxString result;
00909     result.Alloc(s.length());
00910     const wxChar* ch = s.c_str();
00911     while (*ch)
00912     {
00913         if (*ch == wxT(';') || *ch == wxT('|'))
00914             result += wxT('\\');
00915         result += *ch;
00916         ++ch;
00917     }
00918     return result;
00919 }
00920 
00921 wxString wxAuiManager::SavePaneInfo(wxAuiPaneInfo& pane)
00922 {
00923     wxString result = wxT("name=");
00924     result += EscapeDelimiters(pane.name);
00925     result += wxT(";");
00926 
00927     result += wxT("caption=");
00928     result += EscapeDelimiters(pane.caption);
00929     result += wxT(";");
00930 
00931     result += wxString::Format(wxT("state=%u;"), pane.state);
00932     result += wxString::Format(wxT("dir=%d;"), pane.dock_direction);
00933     result += wxString::Format(wxT("layer=%d;"), pane.dock_layer);
00934     result += wxString::Format(wxT("row=%d;"), pane.dock_row);
00935     result += wxString::Format(wxT("pos=%d;"), pane.dock_pos);
00936     result += wxString::Format(wxT("prop=%d;"), pane.dock_proportion);
00937     result += wxString::Format(wxT("bestw=%d;"), pane.best_size.x);
00938     result += wxString::Format(wxT("besth=%d;"), pane.best_size.y);
00939     result += wxString::Format(wxT("minw=%d;"), pane.min_size.x);
00940     result += wxString::Format(wxT("minh=%d;"), pane.min_size.y);
00941     result += wxString::Format(wxT("maxw=%d;"), pane.max_size.x);
00942     result += wxString::Format(wxT("maxh=%d;"), pane.max_size.y);
00943     result += wxString::Format(wxT("floatx=%d;"), pane.floating_pos.x);
00944     result += wxString::Format(wxT("floaty=%d;"), pane.floating_pos.y);
00945     result += wxString::Format(wxT("floatw=%d;"), pane.floating_size.x);
00946     result += wxString::Format(wxT("floath=%d"), pane.floating_size.y);
00947 
00948     return result;
00949 }
00950 
00951 // Load a "pane" with the pane infor settings in pane_part
00952 void wxAuiManager::LoadPaneInfo(wxString pane_part, wxAuiPaneInfo &pane)
00953 {
00954     // replace escaped characters so we can
00955     // split up the string easily
00956     pane_part.Replace(wxT("\\|"), wxT("\a"));
00957     pane_part.Replace(wxT("\\;"), wxT("\b"));
00958 
00959     while(1)
00960     {
00961         wxString val_part = pane_part.BeforeFirst(wxT(';'));
00962         pane_part = pane_part.AfterFirst(wxT(';'));
00963         wxString val_name = val_part.BeforeFirst(wxT('='));
00964         wxString value = val_part.AfterFirst(wxT('='));
00965         val_name.MakeLower();
00966         val_name.Trim(true);
00967         val_name.Trim(false);
00968         value.Trim(true);
00969         value.Trim(false);
00970     
00971         if (val_name.empty())
00972             break;
00973     
00974         if (val_name == wxT("name"))
00975             pane.name = value;
00976         else if (val_name == wxT("caption"))
00977             pane.caption = value;
00978         else if (val_name == wxT("state"))
00979             pane.state = (unsigned int)wxAtoi(value.c_str());
00980         else if (val_name == wxT("dir"))
00981             pane.dock_direction = wxAtoi(value.c_str());
00982         else if (val_name == wxT("layer"))
00983             pane.dock_layer = wxAtoi(value.c_str());
00984         else if (val_name == wxT("row"))
00985             pane.dock_row = wxAtoi(value.c_str());
00986         else if (val_name == wxT("pos"))
00987             pane.dock_pos = wxAtoi(value.c_str());
00988         else if (val_name == wxT("prop"))
00989             pane.dock_proportion = wxAtoi(value.c_str());
00990         else if (val_name == wxT("bestw"))
00991             pane.best_size.x = wxAtoi(value.c_str());
00992         else if (val_name == wxT("besth"))
00993             pane.best_size.y = wxAtoi(value.c_str());
00994         else if (val_name == wxT("minw"))
00995             pane.min_size.x = wxAtoi(value.c_str());
00996         else if (val_name == wxT("minh"))
00997             pane.min_size.y = wxAtoi(value.c_str());
00998         else if (val_name == wxT("maxw"))
00999             pane.max_size.x = wxAtoi(value.c_str());
01000         else if (val_name == wxT("maxh"))
01001             pane.max_size.y = wxAtoi(value.c_str());
01002         else if (val_name == wxT("floatx"))
01003             pane.floating_pos.x = wxAtoi(value.c_str());
01004         else if (val_name == wxT("floaty"))
01005             pane.floating_pos.y = wxAtoi(value.c_str());
01006         else if (val_name == wxT("floatw"))
01007             pane.floating_size.x = wxAtoi(value.c_str());
01008         else if (val_name == wxT("floath"))
01009             pane.floating_size.y = wxAtoi(value.c_str());
01010         else {
01011             wxFAIL_MSG(wxT("Bad Perspective String"));
01012         }
01013     }
01014 
01015     // replace escaped characters so we can
01016     // split up the string easily
01017     pane.name.Replace(wxT("\a"), wxT("|"));
01018     pane.name.Replace(wxT("\b"), wxT(";"));
01019     pane.caption.Replace(wxT("\a"), wxT("|"));
01020     pane.caption.Replace(wxT("\b"), wxT(";"));
01021     pane_part.Replace(wxT("\a"), wxT("|"));
01022     pane_part.Replace(wxT("\b"), wxT(";"));
01023 
01024     return;
01025 }
01026 
01027 
01028 // SavePerspective() saves all pane information as a single string.
01029 // This string may later be fed into LoadPerspective() to restore
01030 // all pane settings.  This save and load mechanism allows an
01031 // exact pane configuration to be saved and restored at a later time
01032 
01033 wxString wxAuiManager::SavePerspective()
01034 {
01035     wxString result;
01036     result.Alloc(500);
01037     result = wxT("layout1|");
01038 
01039     int pane_i, pane_count = m_panes.GetCount();
01040     for (pane_i = 0; pane_i < pane_count; ++pane_i)
01041     {
01042         wxAuiPaneInfo& pane = m_panes.Item(pane_i);
01043         result += SavePaneInfo(pane)+wxT("|");
01044     }
01045 
01046     int dock_i, dock_count = m_docks.GetCount();
01047     for (dock_i = 0; dock_i < dock_count; ++dock_i)
01048     {
01049         wxAuiDockInfo& dock = m_docks.Item(dock_i);
01050 
01051         result += wxString::Format(wxT("dock_size(%d,%d,%d)=%d|"),
01052                                    dock.dock_direction, dock.dock_layer,
01053                                    dock.dock_row, dock.size);
01054     }
01055 
01056     return result;
01057 }
01058 
01059 // LoadPerspective() loads a layout which was saved with SavePerspective()
01060 // If the "update" flag parameter is true, the GUI will immediately be updated
01061 
01062 bool wxAuiManager::LoadPerspective(const wxString& layout, bool update)
01063 {
01064     wxString input = layout;
01065     wxString part;
01066 
01067     // check layout string version
01068     part = input.BeforeFirst(wxT('|'));
01069     input = input.AfterFirst(wxT('|'));
01070     part.Trim(true);
01071     part.Trim(false);
01072     if (part != wxT("layout1"))
01073         return false;
01074 
01075     // mark all panes currently managed as docked and hidden
01076     int pane_i, pane_count = m_panes.GetCount();
01077     for (pane_i = 0; pane_i < pane_count; ++pane_i)
01078         m_panes.Item(pane_i).Dock().Hide();
01079 
01080     // clear out the dock array; this will be reconstructed
01081     m_docks.Clear();
01082 
01083     // replace escaped characters so we can
01084     // split up the string easily
01085     input.Replace(wxT("\\|"), wxT("\a"));
01086     input.Replace(wxT("\\;"), wxT("\b"));
01087 
01088     while (1)
01089     {
01090         wxAuiPaneInfo pane;
01091 
01092         wxString pane_part = input.BeforeFirst(wxT('|'));
01093         input = input.AfterFirst(wxT('|'));
01094         pane_part.Trim(true);
01095 
01096         // if the string is empty, we're done parsing
01097         if (pane_part.empty())
01098             break;
01099 
01100         if (pane_part.Left(9) == wxT("dock_size"))
01101         {
01102             wxString val_name = pane_part.BeforeFirst(wxT('='));
01103             wxString value = pane_part.AfterFirst(wxT('='));
01104 
01105             long dir, layer, row, size;
01106             wxString piece = val_name.AfterFirst(wxT('('));
01107             piece = piece.BeforeLast(wxT(')'));
01108             piece.BeforeFirst(wxT(',')).ToLong(&dir);
01109             piece = piece.AfterFirst(wxT(','));
01110             piece.BeforeFirst(wxT(',')).ToLong(&layer);
01111             piece.AfterFirst(wxT(',')).ToLong(&row);
01112             value.ToLong(&size);
01113 
01114             wxAuiDockInfo dock;
01115             dock.dock_direction = dir;
01116             dock.dock_layer = layer;
01117             dock.dock_row = row;
01118             dock.size = size;
01119             m_docks.Add(dock);
01120             continue;
01121         }
01122 
01123         // Undo our escaping as LoadPaneInfo needs to take an unescaped
01124         // name so it can be called by external callers
01125         pane_part.Replace(wxT("\a"), wxT("|"));
01126         pane_part.Replace(wxT("\b"), wxT(";"));
01127 
01128         LoadPaneInfo(pane_part, pane);
01129 
01130         wxAuiPaneInfo& p = GetPane(pane.name);
01131         if (!p.IsOk())
01132         {
01133             // the pane window couldn't be found
01134             // in the existing layout
01135             return false;
01136         }
01137 
01138         p.SafeSet(pane);
01139 
01140     }
01141 
01142     if (update)
01143         Update();
01144 
01145     return true;
01146 }
01147 
01148 void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock,
01149                                               wxArrayInt& positions,
01150                                               wxArrayInt& sizes)
01151 {
01152     int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
01153     int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
01154     int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
01155 
01156     positions.Empty();
01157     sizes.Empty();
01158 
01159     int offset, action_pane = -1;
01160     int pane_i, pane_count = dock.panes.GetCount();
01161 
01162     // find the pane marked as our action pane
01163     for (pane_i = 0; pane_i < pane_count; ++pane_i)
01164     {
01165         wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i));
01166 
01167         if (pane.state & wxAuiPaneInfo::actionPane)
01168         {
01169             wxASSERT_MSG(action_pane==-1, wxT("Too many fixed action panes"));
01170             action_pane = pane_i;
01171         }
01172     }
01173 
01174     // set up each panes default position, and
01175     // determine the size (width or height, depending
01176     // on the dock's orientation) of each pane
01177     for (pane_i = 0; pane_i < pane_count; ++pane_i)
01178     {
01179         wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i));
01180         positions.Add(pane.dock_pos);
01181         int size = 0;
01182 
01183         if (pane.HasBorder())
01184             size += (pane_border_size*2);
01185 
01186         if (dock.IsHorizontal())
01187         {
01188             if (pane.HasGripper() && !pane.HasGripperTop())
01189                 size += gripper_size;
01190             size += pane.best_size.x;
01191         }
01192          else
01193         {
01194             if (pane.HasGripper() && pane.HasGripperTop())
01195                 size += gripper_size;
01196 
01197             if (pane.HasCaption())
01198                 size += caption_size;
01199             size += pane.best_size.y;
01200         }
01201 
01202         sizes.Add(size);
01203     }
01204 
01205     // if there is no action pane, just return the default
01206     // positions (as specified in pane.pane_pos)
01207     if (action_pane == -1)
01208         return;
01209 
01210     offset = 0;
01211     for (pane_i = action_pane-1; pane_i >= 0; --pane_i)
01212     {
01213         int amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]);
01214 
01215         if (amount >= 0)
01216             offset += amount;
01217              else
01218             positions[pane_i] -= -amount;
01219 
01220         offset += sizes[pane_i];
01221     }
01222 
01223     // if the dock mode is fixed, make sure none of the panes
01224     // overlap; we will bump panes that overlap
01225     offset = 0;
01226     for (pane_i = action_pane; pane_i < pane_count; ++pane_i)
01227     {
01228         int amount = positions[pane_i] - offset;
01229         if (amount >= 0)
01230             offset += amount;
01231              else
01232             positions[pane_i] += -amount;
01233 
01234         offset += sizes[pane_i];
01235     }
01236 }
01237 
01238 
01239 void wxAuiManager::LayoutAddPane(wxSizer* cont,
01240                                    wxAuiDockInfo& dock,
01241                                    wxAuiPaneInfo& pane,
01242                                    wxAuiDockUIPartArray& uiparts,
01243                                    bool spacer_only)
01244 {
01245     wxAuiDockUIPart part;
01246     wxSizerItem* sizer_item;
01247 
01248     int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
01249     int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE);
01250     int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
01251     int pane_button_size = m_art->GetMetric(wxAUI_ART_PANE_BUTTON_SIZE);
01252 
01253     // find out the orientation of the item (orientation for panes
01254     // is the same as the dock's orientation)
01255     int orientation;
01256     if (dock.IsHorizontal())
01257         orientation = wxHORIZONTAL;
01258          else
01259         orientation = wxVERTICAL;
01260 
01261     // this variable will store the proportion
01262     // value that the pane will receive
01263     int pane_proportion = pane.dock_proportion;
01264 
01265     wxBoxSizer* horz_pane_sizer = new wxBoxSizer(wxHORIZONTAL);
01266     wxBoxSizer* vert_pane_sizer = new wxBoxSizer(wxVERTICAL);
01267 
01268     if (pane.HasGripper())
01269     {
01270         if (pane.HasGripperTop())
01271             sizer_item = vert_pane_sizer ->Add(1, gripper_size, 0, wxEXPAND);
01272         else
01273             sizer_item = horz_pane_sizer ->Add(gripper_size, 1, 0, wxEXPAND);
01274 
01275         part.type = wxAuiDockUIPart::typeGripper;
01276         part.dock = &dock;
01277         part.pane = &pane;
01278         part.button = NULL;
01279         part.orientation = orientation;
01280         part.cont_sizer = horz_pane_sizer;
01281         part.sizer_item = sizer_item;
01282         uiparts.Add(part);
01283     }
01284 
01285     if (pane.HasCaption())
01286     {
01287         // create the caption sizer
01288         wxBoxSizer* caption_sizer = new wxBoxSizer(wxHORIZONTAL);
01289 
01290         sizer_item = caption_sizer->Add(1, caption_size, 1, wxEXPAND);
01291 
01292         part.type = wxAuiDockUIPart::typeCaption;
01293         part.dock = &dock;
01294         part.pane = &pane;
01295         part.button = NULL;
01296         part.orientation = orientation;
01297         part.cont_sizer = vert_pane_sizer;
01298         part.sizer_item = sizer_item;
01299         int caption_part_idx = uiparts.GetCount();
01300         uiparts.Add(part);
01301 
01302         // add pane buttons to the caption
01303         int i, button_count;
01304         for (i = 0, button_count = pane.buttons.GetCount();
01305              i < button_count; ++i)
01306         {
01307             wxAuiPaneButton& button = pane.buttons.Item(i);
01308 
01309             sizer_item = caption_sizer->Add(pane_button_size,
01310                                             caption_size,
01311                                             0, wxEXPAND);
01312 
01313             part.type = wxAuiDockUIPart::typePaneButton;
01314             part.dock = &dock;
01315             part.pane = &pane;
01316             part.button = &button;
01317             part.orientation = orientation;
01318             part.cont_sizer = caption_sizer;
01319             part.sizer_item = sizer_item;
01320             uiparts.Add(part);
01321         }
01322 
01323         // add the caption sizer
01324         sizer_item = vert_pane_sizer->Add(caption_sizer, 0, wxEXPAND);
01325 
01326         uiparts.Item(caption_part_idx).sizer_item = sizer_item;
01327     }
01328 
01329     // add the pane window itself
01330     if (spacer_only)
01331     {
01332         sizer_item = vert_pane_sizer->Add(1, 1, 1, wxEXPAND);
01333     }
01334     else
01335     {
01336         sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND);
01337         // Don't do this because it breaks the pane size in floating windows
01338         // BIW: Right now commenting this out is causing problems with
01339         // an mdi client window as the center pane.
01340         vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
01341     }
01342 
01343     part.type = wxAuiDockUIPart::typePane;
01344     part.dock = &dock;
01345     part.pane = &pane;
01346     part.button = NULL;
01347     part.orientation = orientation;
01348     part.cont_sizer = vert_pane_sizer;
01349     part.sizer_item = sizer_item;
01350     uiparts.Add(part);
01351 
01352 
01353     // determine if the pane should have a minimum size; if the pane is
01354     // non-resizable (fixed) then we must set a minimum size. Alternitavely,
01355     // if the pane.min_size is set, we must use that value as well
01356 
01357     wxSize min_size = pane.min_size;
01358     if (pane.IsFixed())
01359     {
01360         if (min_size == wxDefaultSize)
01361         {
01362             min_size = pane.best_size;
01363             pane_proportion = 0;
01364         }
01365     }
01366 
01367     if (min_size != wxDefaultSize)
01368     {
01369         vert_pane_sizer->SetItemMinSize(
01370                         vert_pane_sizer->GetChildren().GetCount()-1,
01371                         min_size.x, min_size.y);
01372     }
01373 
01374 
01375     // add the verticle sizer (caption, pane window) to the
01376     // horizontal sizer (gripper, verticle sizer)
01377     horz_pane_sizer->Add(vert_pane_sizer, 1, wxEXPAND);
01378 
01379     // finally, add the pane sizer to the dock sizer
01380 
01381     if (pane.HasBorder())
01382     {
01383         // allowing space for the pane's border
01384         sizer_item = cont->Add(horz_pane_sizer, pane_proportion,
01385                                wxEXPAND | wxALL, pane_border_size);
01386 
01387         part.type = wxAuiDockUIPart::typePaneBorder;
01388         part.dock = &dock;
01389         part.pane = &pane;
01390         part.button = NULL;
01391         part.orientation = orientation;
01392         part.cont_sizer = cont;
01393         part.sizer_item = sizer_item;
01394         uiparts.Add(part);
01395     }
01396     else
01397     {
01398         sizer_item = cont->Add(horz_pane_sizer, pane_proportion, wxEXPAND);
01399     }
01400 }
01401 
01402 void wxAuiManager::LayoutAddDock(wxSizer* cont,
01403                                    wxAuiDockInfo& dock,
01404                                    wxAuiDockUIPartArray& uiparts,
01405                                    bool spacer_only)
01406 {
01407     wxSizerItem* sizer_item;
01408     wxAuiDockUIPart part;
01409 
01410     int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE);
01411     int orientation = dock.IsHorizontal() ? wxHORIZONTAL : wxVERTICAL;
01412 
01413     // resizable bottom and right docks have a sash before them
01414     if (!dock.fixed && (dock.dock_direction == wxAUI_DOCK_BOTTOM ||
01415                         dock.dock_direction == wxAUI_DOCK_RIGHT))
01416     {
01417         sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
01418 
01419         part.type = wxAuiDockUIPart::typeDockSizer;
01420         part.orientation = orientation;
01421         part.dock = &dock;
01422         part.pane = NULL;
01423         part.button = NULL;
01424         part.cont_sizer = cont;
01425         part.sizer_item = sizer_item;
01426         uiparts.Add(part);
01427     }
01428 
01429     // create the sizer for the dock
01430     wxSizer* dock_sizer = new wxBoxSizer(orientation);
01431 
01432     // add each pane to the dock
01433     int pane_i, pane_count = dock.panes.GetCount();
01434 
01435     if (dock.fixed)
01436     {
01437         wxArrayInt pane_positions, pane_sizes;
01438 
01439         // figure out the real pane positions we will
01440         // use, without modifying the each pane's pane_pos member
01441         GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
01442 
01443         int offset = 0;
01444         for (pane_i = 0; pane_i < pane_count; ++pane_i)
01445         {
01446             wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i));
01447             int pane_pos = pane_positions.Item(pane_i);
01448 
01449             int amount = pane_pos - offset;
01450             if (amount > 0)
01451             {
01452                 if (dock.IsVertical())
01453                     sizer_item = dock_sizer->Add(1, amount, 0, wxEXPAND);
01454                      else
01455                     sizer_item = dock_sizer->Add(amount, 1, 0, wxEXPAND);
01456 
01457                 part.type = wxAuiDockUIPart::typeBackground;
01458                 part.dock = &dock;
01459                 part.pane = NULL;
01460                 part.button = NULL;
01461                 part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
01462                 part.cont_sizer = dock_sizer;
01463                 part.sizer_item = sizer_item;
01464                 uiparts.Add(part);
01465 
01466                 offset += amount;
01467             }
01468 
01469             LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
01470 
01471             offset += pane_sizes.Item(pane_i);
01472         }
01473 
01474         // at the end add a very small stretchable background area
01475         sizer_item = dock_sizer->Add(1,1, 1, wxEXPAND);
01476 
01477         part.type = wxAuiDockUIPart::typeBackground;
01478         part.dock = &dock;
01479         part.pane = NULL;
01480         part.button = NULL;
01481         part.orientation = orientation;
01482         part.cont_sizer = dock_sizer;
01483         part.sizer_item = sizer_item;
01484         uiparts.Add(part);
01485     }
01486     else
01487     {
01488         for (pane_i = 0; pane_i < pane_count; ++pane_i)
01489         {
01490             wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i));
01491 
01492             // if this is not the first pane being added,
01493             // we need to add a pane sizer
01494             if (pane_i > 0)
01495             {
01496                 sizer_item = dock_sizer->Add(sash_size, sash_size, 0, wxEXPAND);
01497 
01498                 part.type = wxAuiDockUIPart::typePaneSizer;
01499                 part.dock = &dock;
01500                 part.pane = dock.panes.Item(pane_i-1);
01501                 part.button = NULL;
01502                 part.orientation = (orientation==wxHORIZONTAL) ? wxVERTICAL:wxHORIZONTAL;
01503                 part.cont_sizer = dock_sizer;
01504                 part.sizer_item = sizer_item;
01505                 uiparts.Add(part);
01506             }
01507 
01508             LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only);
01509         }
01510     }
01511 
01512     if (dock.dock_direction == wxAUI_DOCK_CENTER)
01513         sizer_item = cont->Add(dock_sizer, 1, wxEXPAND);
01514          else
01515         sizer_item = cont->Add(dock_sizer, 0, wxEXPAND);
01516 
01517     part.type = wxAuiDockUIPart::typeDock;
01518     part.dock = &dock;
01519     part.pane = NULL;
01520     part.button = NULL;
01521     part.orientation = orientation;
01522     part.cont_sizer = cont;
01523     part.sizer_item = sizer_item;
01524     uiparts.Add(part);
01525 
01526     if (dock.IsHorizontal())
01527         cont->SetItemMinSize(dock_sizer, 0, dock.size);
01528          else
01529         cont->SetItemMinSize(dock_sizer, dock.size, 0);
01530 
01531     //  top and left docks have a sash after them
01532     if (!dock.fixed && (dock.dock_direction == wxAUI_DOCK_TOP ||
01533                         dock.dock_direction == wxAUI_DOCK_LEFT))
01534     {
01535         sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND);
01536 
01537         part.type = wxAuiDockUIPart::typeDockSizer;
01538         part.dock = &dock;
01539         part.pane = NULL;
01540         part.button = NULL;
01541         part.orientation = orientation;
01542         part.cont_sizer = cont;
01543         part.sizer_item = sizer_item;
01544         uiparts.Add(part);
01545     }
01546 }
01547 
01548 wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
01549                                    wxAuiDockInfoArray& docks,
01550                                    wxAuiDockUIPartArray& uiparts,
01551                                    bool spacer_only)
01552 {
01553     wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
01554 
01555     int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
01556     int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
01557     wxSize cli_size = m_frame->GetClientSize();
01558     int i, dock_count, pane_count;
01559 
01560 
01561     // empty all docks out
01562     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
01563         docks.Item(i).panes.Empty();
01564 
01565     // iterate through all known panes, filing each
01566     // of them into the appropriate dock. If the
01567     // pane does not exist in the dock, add it
01568     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
01569     {
01570         wxAuiPaneInfo& p = panes.Item(i);
01571 
01572         // find any docks in this layer
01573         wxAuiDockInfo* dock;
01574         wxAuiDockInfoPtrArray arr;
01575         FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row, arr);
01576 
01577         if (arr.GetCount() > 0)
01578         {
01579             dock = arr.Item(0);
01580         }
01581          else
01582         {
01583             // dock was not found, so we need to create a new one
01584             wxAuiDockInfo d;
01585             d.dock_direction = p.dock_direction;
01586             d.dock_layer = p.dock_layer;
01587             d.dock_row = p.dock_row;
01588             docks.Add(d);
01589             dock = &docks.Last();
01590         }
01591 
01592 
01593         if (p.IsDocked() && p.IsShown())
01594         {
01595             // remove the pane from any existing docks except this one
01596             RemovePaneFromDocks(docks, p, dock);
01597 
01598             // pane needs to be added to the dock,
01599             // if it doesn't already exist
01600             if (!FindPaneInDock(*dock, p.window))
01601                 dock->panes.Add(&p);
01602         }
01603          else
01604         {
01605             // remove the pane from any existing docks
01606             RemovePaneFromDocks(docks, p);
01607         }
01608 
01609     }
01610 
01611     // remove any empty docks
01612     for (i = docks.GetCount()-1; i >= 0; --i)
01613     {
01614         if (docks.Item(i).panes.GetCount() == 0)
01615             docks.RemoveAt(i);
01616     }
01617 
01618     // configure the docks further
01619     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
01620     {
01621         wxAuiDockInfo& dock = docks.Item(i);
01622         int j, dock_pane_count = dock.panes.GetCount();
01623 
01624         // sort the dock pane array by the pane's
01625         // dock position (dock_pos), in ascending order
01626         dock.panes.Sort(PaneSortFunc);
01627 
01628         // for newly created docks, set up their initial size
01629         if (dock.size == 0)
01630         {
01631             int size = 0;
01632 
01633             for (j = 0; j < dock_pane_count; ++j)
01634             {
01635                 wxAuiPaneInfo& pane = *dock.panes.Item(j);
01636                 wxSize pane_size = pane.best_size;
01637                 if (pane_size == wxDefaultSize)
01638                     pane_size = pane.min_size;
01639                 if (pane_size == wxDefaultSize)
01640                     pane_size = pane.window->GetSize();
01641 
01642                 if (dock.IsHorizontal())
01643                     size = wxMax(pane_size.y, size);
01644                      else
01645                     size = wxMax(pane_size.x, size);
01646             }
01647 
01648             // add space for the border (two times), but only
01649             // if at least one pane inside the dock has a pane border
01650             for (j = 0; j < dock_pane_count; ++j)
01651             {
01652                 if (dock.panes.Item(j)->HasBorder())
01653                 {
01654                     size += (pane_border_size*2);
01655                     break;
01656                 }
01657             }
01658 
01659             // if pane is on the top or bottom, add the caption height,
01660             // but only if at least one pane inside the dock has a caption
01661             if (dock.IsHorizontal())
01662             {
01663                 for (j = 0; j < dock_pane_count; ++j)
01664                 {
01665                     if (dock.panes.Item(j)->HasCaption())
01666                     {
01667                         size += caption_size;
01668                         break;
01669                     }
01670                 }
01671             }
01672 
01673             // new dock's size may not be more than 1/3 of the frame size
01674             if (dock.IsHorizontal())
01675                 size = wxMin(size, cli_size.y/3);
01676                  else
01677                 size = wxMin(size, cli_size.x/3);
01678 
01679             if (size < 10)
01680                 size = 10;
01681             dock.size = size;
01682         }
01683 
01684 
01685         // determine the dock's minimum size
01686         bool plus_border = false;
01687         bool plus_caption = false;
01688         int dock_min_size = 0;
01689         for (j = 0; j < dock_pane_count; ++j)
01690         {
01691             wxAuiPaneInfo& pane = *dock.panes.Item(j);
01692             if (pane.min_size != wxDefaultSize)
01693             {
01694                 if (pane.HasBorder())
01695                     plus_border = true;
01696                 if (pane.HasCaption())
01697                     plus_caption = true;
01698                 if (dock.IsHorizontal())
01699                 {
01700                     if (pane.min_size.y > dock_min_size)
01701                         dock_min_size = pane.min_size.y;
01702                 }
01703                  else
01704                 {
01705                     if (pane.min_size.x > dock_min_size)
01706                         dock_min_size = pane.min_size.x;
01707                 }
01708             }
01709         }
01710 
01711         if (plus_border)
01712             dock_min_size += (pane_border_size*2);
01713         if (plus_caption && dock.IsHorizontal())
01714             dock_min_size += (caption_size);
01715 
01716         dock.min_size = dock_min_size;
01717 
01718 
01719         // if the pane's current size is less than it's
01720         // minimum, increase the dock's size to it's minimum
01721         if (dock.size < dock.min_size)
01722             dock.size = dock.min_size;
01723 
01724 
01725         // determine the dock's mode (fixed or proportional);
01726         // determine whether the dock has only toolbars
01727         bool action_pane_marked = false;
01728         dock.fixed = true;
01729         dock.toolbar = true;
01730         for (j = 0; j < dock_pane_count; ++j)
01731         {
01732             wxAuiPaneInfo& pane = *dock.panes.Item(j);
01733             if (!pane.IsFixed())
01734                 dock.fixed = false;
01735             if (!pane.IsToolbar())
01736                 dock.toolbar = false;
01737             if (pane.state & wxAuiPaneInfo::actionPane)
01738                 action_pane_marked = true;
01739         }
01740 
01741 
01742         // if the dock mode is proportional and not fixed-pixel,
01743         // reassign the dock_pos to the sequential 0, 1, 2, 3;
01744         // e.g. remove gaps like 1, 2, 30, 500
01745         if (!dock.fixed)
01746         {
01747             for (j = 0; j < dock_pane_count; ++j)
01748             {
01749                 wxAuiPaneInfo& pane = *dock.panes.Item(j);
01750                 pane.dock_pos = j;
01751             }
01752         }
01753 
01754         // if the dock mode is fixed, and none of the panes
01755         // are being moved right now, make sure the panes
01756         // do not overlap each other.  If they do, we will
01757         // adjust the panes' positions
01758         if (dock.fixed && !action_pane_marked)
01759         {
01760             wxArrayInt pane_positions, pane_sizes;
01761             GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
01762 
01763             int offset = 0;
01764             for (j = 0; j < dock_pane_count; ++j)
01765             {
01766                 wxAuiPaneInfo& pane = *(dock.panes.Item(j));
01767                 pane.dock_pos = pane_positions[j];
01768 
01769                 int amount = pane.dock_pos - offset;
01770                 if (amount >= 0)
01771                     offset += amount;
01772                      else
01773                     pane.dock_pos += -amount;
01774 
01775                 offset += pane_sizes[j];
01776             }
01777         }
01778     }
01779 
01780     // discover the maximum dock layer
01781     int max_layer = 0;
01782     for (i = 0; i < dock_count; ++i)
01783         max_layer = wxMax(max_layer, docks.Item(i).dock_layer);
01784 
01785 
01786     // clear out uiparts
01787     uiparts.Empty();
01788 
01789     // create a bunch of box sizers,
01790     // from the innermost level outwards.
01791     wxSizer* cont = NULL;
01792     wxSizer* middle = NULL;
01793     int layer = 0;
01794     int row, row_count;
01795 
01796     for (layer = 0; layer <= max_layer; ++layer)
01797     {
01798         wxAuiDockInfoPtrArray arr;
01799 
01800         // find any docks in this layer
01801         FindDocks(docks, -1, layer, -1, arr);
01802 
01803         // if there aren't any, skip to the next layer
01804         if (arr.IsEmpty())
01805             continue;
01806 
01807         wxSizer* old_cont = cont;
01808 
01809         // create a container which will hold this layer's
01810         // docks (top, bottom, left, right)
01811         cont = new wxBoxSizer(wxVERTICAL);
01812 
01813 
01814         // find any top docks in this layer
01815         FindDocks(docks, wxAUI_DOCK_TOP, layer, -1, arr);
01816         RenumberDockRows(arr);
01817         if (!arr.IsEmpty())
01818         {
01819             for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
01820                 LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
01821         }
01822 
01823 
01824         // fill out the middle layer (which consists
01825         // of left docks, content area and right docks)
01826 
01827         middle = new wxBoxSizer(wxHORIZONTAL);
01828 
01829         // find any left docks in this layer
01830         FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr);
01831         RenumberDockRows(arr);
01832         if (!arr.IsEmpty())
01833         {
01834             for (row = 0, row_count = arr.GetCount(); row < row_count; ++row)
01835                 LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
01836         }
01837 
01838         // add content dock (or previous layer's sizer
01839         // to the middle
01840         if (!old_cont)
01841         {
01842             // find any center docks
01843             FindDocks(docks, wxAUI_DOCK_CENTER, -1, -1, arr);
01844             if (!arr.IsEmpty())
01845             {
01846                 for (row = 0,row_count = arr.GetCount(); row<row_count; ++row)
01847                    LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
01848             }
01849              else
01850             {
01851                 // there are no center docks, add a background area
01852                 wxSizerItem* sizer_item = middle->Add(1,1, 1, wxEXPAND);
01853                 wxAuiDockUIPart part;
01854                 part.type = wxAuiDockUIPart::typeBackground;
01855                 part.pane = NULL;
01856                 part.dock = NULL;
01857                 part.button = NULL;
01858                 part.cont_sizer = middle;
01859                 part.sizer_item = sizer_item;
01860                 uiparts.Add(part);
01861             }
01862         }
01863          else
01864         {
01865             middle->Add(old_cont, 1, wxEXPAND);
01866         }
01867 
01868         // find any right docks in this layer
01869         FindDocks(docks, wxAUI_DOCK_RIGHT, layer, -1, arr);
01870         RenumberDockRows(arr);
01871         if (!arr.IsEmpty())
01872         {
01873             for (row = arr.GetCount()-1; row >= 0; --row)
01874                 LayoutAddDock(middle, *arr.Item(row), uiparts, spacer_only);
01875         }
01876 
01877         cont->Add(middle, 1, wxEXPAND);
01878 
01879 
01880 
01881         // find any bottom docks in this layer
01882         FindDocks(docks, wxAUI_DOCK_BOTTOM, layer, -1, arr);
01883         RenumberDockRows(arr);
01884         if (!arr.IsEmpty())
01885         {
01886             for (row = arr.GetCount()-1; row >= 0; --row)
01887                 LayoutAddDock(cont, *arr.Item(row), uiparts, spacer_only);
01888         }
01889 
01890     }
01891 
01892     if (!cont)
01893     {
01894         // no sizer available, because there are no docks,
01895         // therefore we will create a simple background area
01896         cont = new wxBoxSizer(wxVERTICAL);
01897         wxSizerItem* sizer_item = cont->Add(1,1, 1, wxEXPAND);
01898         wxAuiDockUIPart part;
01899         part.type = wxAuiDockUIPart::typeBackground;
01900         part.pane = NULL;
01901         part.dock = NULL;
01902         part.button = NULL;
01903         part.cont_sizer = middle;
01904         part.sizer_item = sizer_item;
01905         uiparts.Add(part);
01906     }
01907 
01908     container->Add(cont, 1, wxEXPAND);
01909     return container;
01910 }
01911 
01912 
01913 // Update() updates the layout.  Whenever changes are made to
01914 // one or more panes, this function should be called.  It is the
01915 // external entry point for running the layout engine.
01916 
01917 void wxAuiManager::Update()
01918 {
01919     wxSizer* sizer;
01920     int i, pane_count = m_panes.GetCount();
01921 
01922     // delete old sizer first
01923     m_frame->SetSizer(NULL);
01924 
01925     // destroy floating panes which have been
01926     // redocked or are becoming non-floating
01927     for (i = 0; i < pane_count; ++i)
01928     {
01929         wxAuiPaneInfo& p = m_panes.Item(i);
01930 
01931         if (!p.IsFloating() && p.frame)
01932         {
01933             // because the pane is no longer in a floating, we need to
01934             // reparent it to m_frame and destroy the floating frame
01935 
01936             // reduce flicker
01937             p.window->SetSize(1,1);
01938             p.frame->Show(false);
01939 
01940             // reparent to m_frame and destroy the pane
01941             p.window->Reparent(m_frame);
01942             p.frame->SetSizer(NULL);
01943             p.frame->Destroy();
01944             p.frame = NULL;
01945         }
01946     }
01947 
01948 
01949     // create a layout for all of the panes
01950     sizer = LayoutAll(m_panes, m_docks, m_uiparts, false);
01951 
01952     // hide or show panes as necessary,
01953     // and float panes as necessary
01954     for (i = 0; i < pane_count; ++i)
01955     {
01956         wxAuiPaneInfo& p = m_panes.Item(i);
01957 
01958         if (p.IsFloating())
01959         {
01960             if (p.frame == NULL)
01961             {
01962                 // we need to create a frame for this
01963                 // pane, which has recently been floated
01964                 wxAuiFloatingFrame* frame = new wxAuiFloatingFrame(m_frame,
01965                                                   this,
01966                                                   p);
01967 
01968 #if wxCHECK_VERSION(2,7,0)
01969                 // on MSW and Mac, if the owner desires transparent dragging, and
01970                 // the dragging is happening right now, then the floating
01971                 // window should have this style by default
01972                 if (m_action == actionDragFloatingPane &&
01973                     (m_flags & wxAUI_MGR_TRANSPARENT_DRAG))
01974                         frame->SetTransparent(150);
01975 #endif
01976 
01977                 frame->SetPaneWindow(p);
01978                 p.frame = frame;
01979 
01980                 if (p.frame->IsShown() != p.IsShown())
01981                     p.frame->Show(p.IsShown());
01982 
01983             }
01984              else
01985             {
01986                 // frame already exists, make sure it's position
01987                 // and size reflect the information in wxAuiPaneInfo
01988                 if (p.frame->GetPosition() != p.floating_pos)
01989                 {
01990                     p.frame->SetSize(p.floating_pos.x, p.floating_pos.y,
01991                                      wxDefaultCoord, wxDefaultCoord,
01992                                      wxSIZE_USE_EXISTING);
01993                     //p.frame->Move(p.floating_pos.x, p.floating_pos.y);
01994                 }
01995 
01996                 if (p.frame->IsShown() != p.IsShown())
01997                     p.frame->Show(p.IsShown());
01998             }
01999         }
02000          else
02001         {
02002             if (p.window->IsShown() != p.IsShown())
02003                 p.window->Show(p.IsShown());
02004         }
02005 
02006         // if "active panes" are no longer allowed, clear
02007         // any optionActive values from the pane states
02008         if ((m_flags & wxAUI_MGR_ALLOW_ACTIVE_PANE) == 0)
02009         {
02010             p.state &= ~wxAuiPaneInfo::optionActive;
02011         }
02012     }
02013 
02014 
02015     // keep track of the old window rectangles so we can
02016     // refresh those windows whose rect has changed
02017     wxAuiRectArray old_pane_rects;
02018     for (i = 0; i < pane_count; ++i)
02019     {
02020         wxRect r;
02021         wxAuiPaneInfo& p = m_panes.Item(i);
02022 
02023         if (p.window && p.IsShown() && p.IsDocked())
02024             r = p.rect;
02025 
02026         old_pane_rects.Add(r);
02027     }
02028 
02029 
02030 
02031 
02032     // apply the new sizer
02033     m_frame->SetSizer(sizer);
02034     m_frame->SetAutoLayout(false);
02035     DoFrameLayout();
02036 
02037 
02038 
02039     // now that the frame layout is done, we need to check
02040     // the new pane rectangles against the old rectangles that
02041     // we saved a few lines above here.  If the rectangles have
02042     // changed, the corresponding panes must also be updated
02043     for (i = 0; i < pane_count; ++i)
02044     {
02045         wxAuiPaneInfo& p = m_panes.Item(i);
02046         if (p.window && p.window->IsShown() && p.IsDocked())
02047         {
02048             if (p.rect != old_pane_rects[i])
02049             {
02050                 p.window->Refresh();
02051                 p.window->Update();
02052             }
02053         }
02054     }
02055 
02056 
02057     Repaint();
02058 
02059     // set frame's minimum size
02060 
02061 /*
02062     // N.B. More work needs to be done on frame minimum sizes;
02063     // this is some intresting code that imposes the minimum size,
02064     // but we may want to include a more flexible mechanism or
02065     // options for multiple minimum-size modes, e.g. strict or lax
02066     wxSize min_size = sizer->GetMinSize();
02067     wxSize frame_size = m_frame->GetSize();
02068     wxSize client_size = m_frame->GetClientSize();
02069 
02070     wxSize minframe_size(min_size.x+frame_size.x-client_size.x,
02071                          min_size.y+frame_size.y-client_size.y );
02072 
02073     m_frame->SetMinSize(minframe_size);
02074 
02075     if (frame_size.x < minframe_size.x ||
02076         frame_size.y < minframe_size.y)
02077             sizer->Fit(m_frame);
02078 */
02079 }
02080 
02081 
02082 // DoFrameLayout() is an internal function which invokes wxSizer::Layout
02083 // on the frame's main sizer, then measures all the various UI items
02084 // and updates their internal rectangles.  This should always be called
02085 // instead of calling m_frame->Layout() directly
02086 
02087 void wxAuiManager::DoFrameLayout()
02088 {
02089     m_frame->Layout();
02090 
02091     int i, part_count;
02092     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
02093     {
02094         wxAuiDockUIPart& part = m_uiparts.Item(i);
02095 
02096         // get the rectangle of the UI part
02097         // originally, this code looked like this:
02098         //    part.rect = wxRect(part.sizer_item->GetPosition(),
02099         //                       part.sizer_item->GetSize());
02100         // this worked quite well, with one exception: the mdi
02101         // client window had a "deferred" size variable
02102         // that returned the wrong size.  It looks like
02103         // a bug in wx, because the former size of the window
02104         // was being returned.  So, we will retrieve the part's
02105         // rectangle via other means
02106 
02107 
02108         part.rect = part.sizer_item->GetRect();
02109         int flag = part.sizer_item->GetFlag();
02110         int border = part.sizer_item->GetBorder();
02111         if (flag & wxTOP)
02112         {
02113             part.rect.y -= border;
02114             part.rect.height += border;
02115         }
02116         if (flag & wxLEFT)
02117         {
02118             part.rect.x -= border;
02119             part.rect.width += border;
02120         }
02121         if (flag & wxBOTTOM)
02122             part.rect.height += border;
02123         if (flag & wxRIGHT)
02124             part.rect.width += border;
02125 
02126 
02127         if (part.type == wxAuiDockUIPart::typeDock)
02128             part.dock->rect = part.rect;
02129         if (part.type == wxAuiDockUIPart::typePane)
02130             part.pane->rect = part.rect;
02131     }
02132 }
02133 
02134 // GetPanePart() looks up the pane the pane border UI part (or the regular
02135 // pane part if there is no border). This allows the caller to get the exact
02136 // rectangle of the pane in question, including decorations like
02137 // caption and border (if any).
02138 
02139 wxAuiDockUIPart* wxAuiManager::GetPanePart(wxWindow* wnd)
02140 {
02141     int i, part_count;
02142     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
02143     {
02144         wxAuiDockUIPart& part = m_uiparts.Item(i);
02145         if (part.type == wxAuiDockUIPart::typePaneBorder &&
02146             part.pane && part.pane->window == wnd)
02147                 return &part;
02148     }
02149     for (i = 0, part_count = m_uiparts.GetCount(); i < part_count; ++i)
02150     {
02151         wxAuiDockUIPart& part = m_uiparts.Item(i);
02152         if (part.type == wxAuiDockUIPart::typePane &&
02153             part.pane && part.pane->window == wnd)
02154                 return &part;
02155     }
02156     return NULL;
02157 }
02158 
02159 
02160 
02161 // GetDockPixelOffset() is an internal function which returns
02162 // a dock's offset in pixels from the left side of the window
02163 // (for horizontal docks) or from the top of the window (for
02164 // vertical docks).  This value is necessary for calculating
02165 // fixel-pane/toolbar offsets when they are dragged.
02166 
02167 int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo& test)
02168 {
02169     // the only way to accurately calculate the dock's
02170     // offset is to actually run a theoretical layout
02171 
02172     int i, part_count, dock_count;
02173     wxAuiDockInfoArray docks;
02174     wxAuiPaneInfoArray panes;
02175     wxAuiDockUIPartArray uiparts;
02176     CopyDocksAndPanes(docks, panes, m_docks, m_panes);
02177     panes.Add(test);
02178 
02179     wxSizer* sizer = LayoutAll(panes, docks, uiparts, true);
02180     wxSize client_size = m_frame->GetClientSize();
02181     sizer->SetDimension(0, 0, client_size.x, client_size.y);
02182     sizer->Layout();
02183 
02184     for (i = 0, part_count = uiparts.GetCount(); i < part_count; ++i)
02185     {
02186         wxAuiDockUIPart& part = uiparts.Item(i);
02187         part.rect = wxRect(part.sizer_item->GetPosition(),
02188                            part.sizer_item->GetSize());
02189         if (part.type == wxAuiDockUIPart::typeDock)
02190             part.dock->rect = part.rect;
02191     }
02192 
02193     delete sizer;
02194 
02195     for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i)
02196     {
02197         wxAuiDockInfo& dock = docks.Item(i);
02198         if (test.dock_direction == dock.dock_direction &&
02199             test.dock_layer==dock.dock_layer && test.dock_row==dock.dock_row)
02200         {
02201             if (dock.IsVertical())
02202                 return dock.rect.y;
02203                  else
02204                 return dock.rect.x;
02205         }
02206     }
02207 
02208     return 0;
02209 }
02210 
02211 
02212 
02213 // ProcessDockResult() is a utility function used by DoDrop() - it checks
02214 // if a dock operation is allowed, the new dock position is copied into
02215 // the target info.  If the operation was allowed, the function returns true.
02216 
02217 bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo& target,
02218                               const wxAuiPaneInfo& new_pos)
02219 {
02220     bool allowed = false;
02221     switch (new_pos.dock_direction)
02222     {
02223         case wxAUI_DOCK_TOP:    allowed = target.IsTopDockable();    break;
02224         case wxAUI_DOCK_BOTTOM: allowed = target.IsBottomDockable(); break;
02225         case wxAUI_DOCK_LEFT:   allowed = target.IsLeftDockable();   break;
02226         case wxAUI_DOCK_RIGHT:  allowed = target.IsRightDockable();  break;
02227     }
02228 
02229     if (allowed)
02230         target = new_pos;
02231 
02232     return allowed;
02233 }
02234 
02235 
02236 // DoDrop() is an important function.  It basically takes a mouse position,
02237 // and determines where the pane's new position would be.  If the pane is to be
02238 // dropped, it performs the drop operation using the specified dock and pane
02239 // arrays.  By specifying copied dock and pane arrays when calling, a "what-if"
02240 // scenario can be performed, giving precise coordinates for drop hints.
02241 // If, however, wxAuiManager:m_docks and wxAuiManager::m_panes are specified
02242 // as parameters, the changes will be made to the main state arrays
02243 
02244 const int auiInsertRowPixels = 10;
02245 const int auiNewRowPixels = 40;
02246 const int auiLayerInsertPixels = 40;
02247 const int auiLayerInsertOffset = 5;
02248 
02249 bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks,
02250                             wxAuiPaneInfoArray& panes,
02251                             wxAuiPaneInfo& target,
02252                             const wxPoint& pt,
02253                             const wxPoint& offset)
02254 {
02255     wxSize cli_size = m_frame->GetClientSize();
02256 
02257     wxAuiPaneInfo drop = target;
02258 
02259 
02260     // The result should always be shown
02261     drop.Show();
02262 
02263 
02264     // Check to see if the pane has been dragged outside of the window
02265     // (or near to the outside of the window), if so, dock it along the edge
02266 
02267 
02268     int layer_insert_offset = auiLayerInsertOffset;
02269     if (target.IsToolbar())
02270         layer_insert_offset = 0;
02271 
02272     if (pt.x < layer_insert_offset &&
02273         pt.x > layer_insert_offset-auiLayerInsertPixels)
02274     {
02275         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
02276                                     GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
02277                                     GetMaxLayer(docks, wxAUI_DOCK_TOP)) + 1;
02278         drop.Dock().Left().
02279              Layer(new_layer).
02280              Row(0).
02281              Position(pt.y - GetDockPixelOffset(drop) - offset.y);
02282         return ProcessDockResult(target, drop);
02283     }
02284     else if (pt.y < layer_insert_offset &&
02285              pt.y > layer_insert_offset-auiLayerInsertPixels)
02286     {
02287         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
02288                                     GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
02289                                     GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
02290         drop.Dock().Top().
02291              Layer(new_layer).
02292              Row(0).
02293              Position(pt.x - GetDockPixelOffset(drop) - offset.x);
02294         return ProcessDockResult(target, drop);
02295     }
02296     else if (pt.x >= cli_size.x - layer_insert_offset &&
02297              pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
02298     {
02299         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
02300                                     GetMaxLayer(docks, wxAUI_DOCK_TOP)),
02301                                     GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)) + 1;
02302         drop.Dock().Right().
02303              Layer(new_layer).
02304              Row(0).
02305              Position(pt.y - GetDockPixelOffset(drop) - offset.y);
02306         return ProcessDockResult(target, drop);
02307     }
02308     else if (pt.y >= cli_size.y - layer_insert_offset &&
02309              pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
02310     {
02311         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
02312                                     GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
02313                                     GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1;
02314         drop.Dock().Bottom().
02315              Layer(new_layer).
02316              Row(0).
02317              Position(pt.x - GetDockPixelOffset(drop) - offset.x);
02318         return ProcessDockResult(target, drop);
02319     }
02320 
02321 
02322     wxAuiDockUIPart* part = HitTest(pt.x, pt.y);
02323 
02324 
02325     if (drop.IsToolbar())
02326     {
02327         if (!part || !part->dock)
02328             return false;
02329 
02330 
02331         // calculate the offset from where the dock begins
02332         // to the point where the user dropped the pane
02333         int dock_drop_offset = 0;
02334         if (part->dock->IsHorizontal())
02335             dock_drop_offset = pt.x - part->dock->rect.x - offset.x;
02336              else
02337             dock_drop_offset = pt.y - part->dock->rect.y - offset.y;
02338 
02339 
02340         // toolbars may only be moved in and to fixed-pane docks,
02341         // otherwise we will try to float the pane.  Also, the pane
02342         // should float if being dragged over center pane windows
02343         if (!part->dock->fixed || part->dock->dock_direction == wxAUI_DOCK_CENTER)
02344         {
02345             if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
02346                    (drop.IsFloatable() ||
02347                     (part->dock->dock_direction != wxAUI_DOCK_CENTER &&
02348                      part->dock->dock_direction != wxAUI_DOCK_NONE)))
02349             {
02350                 drop.Float();
02351             }
02352 
02353             return ProcessDockResult(target, drop);
02354         }
02355 
02356         drop.Dock().
02357              Direction(part->dock->dock_direction).
02358              Layer(part->dock->dock_layer).
02359              Row(part->dock->dock_row).
02360              Position(dock_drop_offset);
02361 
02362         if ((
02363             ((pt.y < part->dock->rect.y + 2) && part->dock->IsHorizontal()) ||
02364             ((pt.x < part->dock->rect.x + 2) && part->dock->IsVertical())
02365             ) && part->dock->panes.GetCount() > 1)
02366         {
02367             int row = drop.dock_row;
02368             DoInsertDockRow(panes, part->dock->dock_direction,
02369                             part->dock->dock_layer,
02370                             part->dock->dock_row);
02371             drop.dock_row = row;
02372         }
02373 
02374         if ((
02375             ((pt.y > part->dock->rect.y + part->dock->rect.height - 2 ) && part->dock->IsHorizontal()) ||
02376             ((pt.x > part->dock->rect.x + part->dock->rect.width - 2 ) && part->dock->IsVertical())
02377             ) && part->dock->panes.GetCount() > 1)
02378         {
02379             DoInsertDockRow(panes, part->dock->dock_direction,
02380                             part->dock->dock_layer,
02381                             part->dock->dock_row+1);
02382             drop.dock_row = part->dock->dock_row+1;
02383         }
02384 
02385         return ProcessDockResult(target, drop);
02386     }
02387 
02388 
02389 
02390 
02391     if (!part)
02392         return false;
02393 
02394     if (part->type == wxAuiDockUIPart::typePaneBorder ||
02395         part->type == wxAuiDockUIPart::typeCaption ||
02396         part->type == wxAuiDockUIPart::typeGripper ||
02397         part->type == wxAuiDockUIPart::typePaneButton ||
02398         part->type == wxAuiDockUIPart::typePane ||
02399         part->type == wxAuiDockUIPart::typePaneSizer ||
02400         part->type == wxAuiDockUIPart::typeDockSizer ||
02401         part->type == wxAuiDockUIPart::typeBackground)
02402     {
02403         if (part->type == wxAuiDockUIPart::typeDockSizer)
02404         {
02405             if (part->dock->panes.GetCount() != 1)
02406                 return false;
02407             part = GetPanePart(part->dock->panes.Item(0)->window);
02408             if (!part)
02409                 return false;
02410         }
02411 
02412 
02413 
02414         // If a normal frame is being dragged over a toolbar, insert it
02415         // along the edge under the toolbar, but over all other panes.
02416         // (this could be done much better, but somehow factoring this
02417         // calculation with the one at the beginning of this function)
02418         if (part->dock && part->dock->toolbar)
02419         {
02420             int layer = 0;
02421 
02422             switch (part->dock->dock_direction)
02423             {
02424                 case wxAUI_DOCK_LEFT:
02425                     layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
02426                                       GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
02427                                       GetMaxLayer(docks, wxAUI_DOCK_TOP));
02428                     break;
02429                 case wxAUI_DOCK_TOP:
02430                     layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
02431                                       GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
02432                                       GetMaxLayer(docks, wxAUI_DOCK_RIGHT));
02433                     break;
02434                 case wxAUI_DOCK_RIGHT:
02435                     layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
02436                                       GetMaxLayer(docks, wxAUI_DOCK_TOP)),
02437                                       GetMaxLayer(docks, wxAUI_DOCK_BOTTOM));
02438                     break;
02439                 case wxAUI_DOCK_BOTTOM:
02440                     layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
02441                                       GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
02442                                       GetMaxLayer(docks, wxAUI_DOCK_RIGHT));
02443                     break;
02444             }
02445 
02446             DoInsertDockRow(panes, part->dock->dock_direction,
02447                             layer, 0);
02448             drop.Dock().
02449                  Direction(part->dock->dock_direction).
02450                  Layer(layer).Row(0).Position(0);
02451             return ProcessDockResult(target, drop);
02452         }
02453 
02454 
02455         if (!part->pane)
02456             return false;
02457 
02458         part = GetPanePart(part->pane->window);
02459         if (!part)
02460             return false;
02461 
02462         bool insert_dock_row = false;
02463         int insert_row = part->pane->dock_row;
02464         int insert_dir = part->pane->dock_direction;
02465         int insert_layer = part->pane->dock_layer;
02466 
02467         switch (part->pane->dock_direction)
02468         {
02469             case wxAUI_DOCK_TOP:
02470                 if (pt.y >= part->rect.y &&
02471                     pt.y < part->rect.y+auiInsertRowPixels)
02472                         insert_dock_row = true;
02473                 break;
02474             case wxAUI_DOCK_BOTTOM:
02475                 if (pt.y > part->rect.y+part->rect.height-auiInsertRowPixels &&
02476                     pt.y <= part->rect.y + part->rect.height)
02477                         insert_dock_row = true;
02478                 break;
02479             case wxAUI_DOCK_LEFT:
02480                 if (pt.x >= part->rect.x &&
02481                     pt.x < part->rect.x+auiInsertRowPixels)
02482                         insert_dock_row = true;
02483                 break;
02484             case wxAUI_DOCK_RIGHT:
02485                 if (pt.x > part->rect.x+part->rect.width-auiInsertRowPixels &&
02486                     pt.x <= part->rect.x+part->rect.width)
02487                         insert_dock_row = true;
02488                 break;
02489             case wxAUI_DOCK_CENTER:
02490             {
02491                 // "new row pixels" will be set to the default, but
02492                 // must never exceed 20% of the window size
02493                 int new_row_pixels_x = auiNewRowPixels;
02494                 int new_row_pixels_y = auiNewRowPixels;
02495 
02496                 if (new_row_pixels_x > (part->rect.width*20)/100)
02497                     new_row_pixels_x = (part->rect.width*20)/100;
02498 
02499                 if (new_row_pixels_y > (part->rect.height*20)/100)
02500                     new_row_pixels_y = (part->rect.height*20)/100;
02501 
02502 
02503                 // determine if the mouse pointer is in a location that
02504                 // will cause a new row to be inserted.  The hot spot positions
02505                 // are along the borders of the center pane
02506 
02507                 insert_layer = 0;
02508                 insert_dock_row = true;
02509                 if (pt.x >= part->rect.x &&
02510                     pt.x < part->rect.x+new_row_pixels_x)
02511                         insert_dir = wxAUI_DOCK_LEFT;
02512                  else
02513                 if (pt.y >= part->rect.y &&
02514                     pt.y < part->rect.y+new_row_pixels_y)
02515                         insert_dir = wxAUI_DOCK_TOP;
02516                  else
02517                 if (pt.x >= part->rect.x + part->rect.width-new_row_pixels_x &&
02518                     pt.x < part->rect.x + part->rect.width)
02519                         insert_dir = wxAUI_DOCK_RIGHT;
02520                  else
02521                 if (pt.y >= part->rect.y+ part->rect.height-new_row_pixels_y &&
02522                     pt.y < part->rect.y + part->rect.height)
02523                         insert_dir = wxAUI_DOCK_BOTTOM;
02524                  else
02525                 return false;
02526 
02527                 insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1;
02528             }
02529         }
02530 
02531         if (insert_dock_row)
02532         {
02533             DoInsertDockRow(panes, insert_dir, insert_layer, insert_row);
02534             drop.Dock().Direction(insert_dir).
02535                         Layer(insert_layer).
02536                         Row(insert_row).
02537                         Position(0);
02538             return ProcessDockResult(target, drop);
02539         }
02540 
02541         // determine the mouse offset and the pane size, both in the
02542         // direction of the dock itself, and perpendicular to the dock
02543 
02544         int offset, size;
02545 
02546         if (part->orientation == wxVERTICAL)
02547         {
02548             offset = pt.y - part->rect.y;
02549             size = part->rect.GetHeight();
02550         }
02551          else
02552         {
02553             offset = pt.x - part->rect.x;
02554             size = part->rect.GetWidth();
02555         }
02556 
02557         int drop_position = part->pane->dock_pos;
02558 
02559         // if we are in the top/left part of the pane,
02560         // insert the pane before the pane being hovered over
02561         if (offset <= size/2)
02562         {
02563             drop_position = part->pane->dock_pos;
02564             DoInsertPane(panes,
02565                          part->pane->dock_direction,
02566                          part->pane->dock_layer,
02567                          part->pane->dock_row,
02568                          part->pane->dock_pos);
02569         }
02570 
02571         // if we are in the bottom/right part of the pane,
02572         // insert the pane before the pane being hovered over
02573         if (offset > size/2)
02574         {
02575             drop_position = part->pane->dock_pos+1;
02576             DoInsertPane(panes,
02577                          part->pane->dock_direction,
02578                          part->pane->dock_layer,
02579                          part->pane->dock_row,
02580                          part->pane->dock_pos+1);
02581         }
02582 
02583         drop.Dock().
02584              Direction(part->dock->dock_direction).
02585              Layer(part->dock->dock_layer).
02586              Row(part->dock->dock_row).
02587              Position(drop_position);
02588         return ProcessDockResult(target, drop);
02589     }
02590 
02591     return false;
02592 }
02593 
02594 
02595 void wxAuiManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event))
02596 {
02597     if (!m_hint_wnd || m_hint_fadeamt >= m_hint_fademax)
02598     {
02599         m_hint_fadetimer.Stop();
02600         return;
02601     }
02602 
02603     m_hint_fadeamt += 4;
02604 #if wxCHECK_VERSION(2,7,0)
02605     m_hint_wnd->SetTransparent(m_hint_fadeamt);
02606 #else
02607     if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
02608         ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(m_hint_fadeamt);
02609 #endif
02610 }
02611 
02612 void wxAuiManager::ShowHint(const wxRect& rect)
02613 {
02614     if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0
02615         && m_hint_wnd
02616         // Finally, don't use a venetian blind effect if it's been specifically disabled
02617         && !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) &&
02618              (m_flags & wxAUI_MGR_DISABLE_VENETIAN_BLINDS))
02619        )
02620     {
02621         if (m_last_hint == rect)
02622             return;
02623         m_last_hint = rect;
02624 
02625         m_hint_fadeamt = m_hint_fademax;
02626         if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
02627             && !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) &&
02628                  (m_flags & wxAUI_MGR_DISABLE_VENETIAN_BLINDS_FADE))
02629             )
02630             m_hint_fadeamt = 0;
02631 
02632         if (! m_hint_wnd->IsShown())
02633             m_hint_wnd->Show();
02634 
02635         // if we are dragging a floating pane, set the focus
02636         // back to that floating pane (otherwise it becomes unfocused)
02637         if (m_action == actionDragFloatingPane && m_action_window)
02638             m_action_window->SetFocus();
02639 
02640 #if wxCHECK_VERSION(2,7,0)
02641         m_hint_wnd->SetTransparent(m_hint_fadeamt);
02642 #else
02643         if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
02644             ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(m_hint_fadeamt);
02645 #endif
02646         m_hint_wnd->SetSize(rect);
02647         m_hint_wnd->Raise();
02648 
02649 
02650         if (m_hint_fadeamt != m_hint_fademax) //  Only fade if we need to
02651         {
02652             // start fade in timer
02653             m_hint_fadetimer.SetOwner(this, 101);
02654             m_hint_fadetimer.Start(5);
02655         }
02656     }
02657 
02658     else  // Not using a transparent hint window...
02659     {
02660 
02661         if (m_last_hint != rect)
02662         {
02663             // remove the last hint rectangle
02664             m_last_hint = rect;
02665             m_frame->Refresh();
02666             m_frame->Update();
02667         }
02668 
02669         wxScreenDC screendc;
02670         wxRegion clip(1, 1, 10000, 10000);
02671 
02672         // clip all floating windows, so we don't draw over them
02673         int i, pane_count;
02674         for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i)
02675         {
02676             wxAuiPaneInfo& pane = m_panes.Item(i);
02677 
02678             if (pane.IsFloating() &&
02679                 pane.frame->IsShown())
02680             {
02681                 wxRect rect = pane.frame->GetRect();
02682 #ifdef __WXGTK__
02683                 // wxGTK returns the client size, not the whole frame size
02684                 rect.width += 15;
02685                 rect.height += 35;
02686                 rect.Inflate(5);
02687 #endif
02688 
02689                 clip.Subtract(rect);
02690             }
02691         }
02692 
02693         // As we can only hide the hint by redrawing the managed window, we
02694         // need to clip the region to the managed window too or we get
02695         // nasty redrawn problems.
02696         clip.Intersect(m_frame->GetRect());
02697 
02698         screendc.SetClippingRegion(clip);
02699 
02700         wxBitmap stipple = wxPaneCreateStippleBitmap();
02701         wxBrush brush(stipple);
02702         screendc.SetBrush(brush);
02703         screendc.SetPen(*wxTRANSPARENT_PEN);
02704 
02705         screendc.DrawRectangle(rect.x, rect.y, 5, rect.height);
02706         screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5);
02707         screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height);
02708         screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5);
02709     }
02710 }
02711 
02712 void wxAuiManager::HideHint()
02713 {
02714     // hides a transparent window hint, if there is one
02715     if (m_hint_wnd)
02716     {
02717         m_hint_wnd->Show(false);
02718 #if wxCHECK_VERSION(2,7,0)
02719         m_hint_wnd->SetTransparent(0);
02720 #else
02721         if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame)))
02722         ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(0);
02723 #endif
02724         m_hint_fadetimer.Stop();
02725         m_last_hint = wxRect();
02726         return;
02727     }
02728 
02729     // hides a painted hint by redrawing the frame window
02730     if (!m_last_hint.IsEmpty())
02731     {
02732         m_frame->Refresh();
02733         m_frame->Update();
02734         m_last_hint = wxRect();
02735     }
02736 }
02737 
02738 
02739 
02740 // DrawHintRect() draws a drop hint rectangle. First calls DoDrop() to
02741 // determine the exact position the pane would be at were if dropped.  If
02742 // the pame would indeed become docked at the specified drop point,
02743 // DrawHintRect() then calls ShowHint() to indicate this drop rectangle.
02744 // "pane_window" is the window pointer of the pane being dragged, pt is
02745 // the mouse position, in client coordinates
02746 void wxAuiManager::DrawHintRect(wxWindow* pane_window,
02747                                   const wxPoint& pt,
02748                                   const wxPoint& offset)
02749 {
02750     wxRect rect;
02751 
02752     // we need to paint a hint rectangle; to find out the exact hint rectangle,
02753     // we will create a new temporary layout and then measure the resulting
02754     // rectangle; we will create a copy of the docking structures (m_dock)
02755     // so that we don't modify the real thing on screen
02756 
02757     int i, pane_count, part_count;
02758     wxAuiDockInfoArray docks;
02759     wxAuiPaneInfoArray panes;
02760     wxAuiDockUIPartArray uiparts;
02761     wxAuiPaneInfo hint = GetPane(pane_window);
02762     hint.name = wxT("__HINT__");
02763     hint.Show();
02764 
02765     if (!hint.IsOk())
02766         return;
02767 
02768     CopyDocksAndPanes(docks, panes, m_docks, m_panes);
02769 
02770     // remove any pane already there which bears the same window;
02771     // this happens when you are moving a pane around in a dock
02772     for (i = 0, pane_count = panes.GetCount(); i < pane_count; ++i)
02773     {
02774         if (panes.Item(i).window == pane_window)
02775         {
02776             RemovePaneFromDocks(docks, panes.Item(i));
02777             panes.RemoveAt(i);
02778             break;
02779         }
02780     }
02781 
02782     // find out where the new pane would be
02783     if (!DoDrop(docks, panes, hint, pt, offset))
02784     {
02785         HideHint();
02786         return;
02787     }
02788 
02789     panes.Add(hint);
02790 
02791     wxSizer* sizer = LayoutAll(panes, docks, uiparts, true);
02792     wxSize client_size = m_frame->GetClientSize();
02793     sizer->SetDimension(0, 0, client_size.x, client_size.y);
02794     sizer->Layout();
02795 
02796     for (i = 0, part_count = uiparts.GetCount();
02797          i < part_count; ++i)
02798     {
02799         wxAuiDockUIPart& part = uiparts.Item(i);
02800 
02801         if (part.type == wxAuiDockUIPart::typePaneBorder &&
02802             part.pane && part.pane->name == wxT("__HINT__"))
02803         {
02804             rect = wxRect(part.sizer_item->GetPosition(),
02805                           part.sizer_item->GetSize());
02806             break;
02807         }
02808     }
02809 
02810     delete sizer;
02811 
02812     if (rect.IsEmpty())
02813     {
02814         HideHint();
02815         return;
02816     }
02817 
02818     // actually show the hint rectangle on the screen
02819     m_frame->ClientToScreen(&rect.x, &rect.y);
02820     ShowHint(rect);
02821 }
02822 
02823 void wxAuiManager::OnFloatingPaneMoveStart(wxWindow* wnd)
02824 {
02825     // try to find the pane
02826     wxAuiPaneInfo& pane = GetPane(wnd);
02827     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
02828 
02829 #if wxCHECK_VERSION(2,7,0)
02830     if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
02831         pane.frame->SetTransparent(150);
02832 #endif
02833 }
02834 
02835 void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd)
02836 {
02837     // try to find the pane
02838     wxAuiPaneInfo& pane = GetPane(wnd);
02839     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
02840 
02841     wxPoint pt = ::wxGetMousePosition();
02842     wxPoint client_pt = m_frame->ScreenToClient(pt);
02843 
02844     // calculate the offset from the upper left-hand corner
02845     // of the frame to the mouse pointer
02846     wxPoint frame_pos = pane.frame->GetPosition();
02847     wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
02848 
02849     // no hint for toolbar floating windows
02850     if (pane.IsToolbar() && m_action == actionDragFloatingPane)
02851     {
02852         if (m_action == actionDragFloatingPane)
02853         {
02854             wxAuiDockInfoArray docks;
02855             wxAuiPaneInfoArray panes;
02856             wxAuiDockUIPartArray uiparts;
02857             wxAuiPaneInfo hint = pane;
02858 
02859             CopyDocksAndPanes(docks, panes, m_docks, m_panes);
02860 
02861             // find out where the new pane would be
02862             if (!DoDrop(docks, panes, hint, client_pt))
02863                 return;
02864             if (hint.IsFloating())
02865                 return;
02866 
02867             pane = hint;
02868             m_action = actionDragToolbarPane;
02869             m_action_window = pane.window;
02870 
02871             Update();
02872         }
02873 
02874         return;
02875     }
02876 
02877 
02878     // if a key modifier is pressed while dragging the frame,
02879     // don't dock the window
02880     if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT))
02881     {
02882         HideHint();
02883         return;
02884     }
02885 
02886 
02887     DrawHintRect(wnd, client_pt, action_offset);
02888 
02889 #ifdef __WXGTK__
02890     // this cleans up some screen artifacts that are caused on GTK because
02891     // we aren't getting the exact size of the window (see comment
02892     // in DrawHintRect)
02893     //Refresh();
02894 #endif
02895 
02896 
02897     // reduces flicker
02898     m_frame->Update();
02899 }
02900 
02901 void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd)
02902 {
02903     // try to find the pane
02904     wxAuiPaneInfo& pane = GetPane(wnd);
02905     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
02906 
02907     wxPoint pt = ::wxGetMousePosition();
02908     wxPoint client_pt = m_frame->ScreenToClient(pt);
02909 
02910     // calculate the offset from the upper left-hand corner
02911     // of the frame to the mouse pointer
02912     wxPoint frame_pos = pane.frame->GetPosition();
02913     wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y);
02914 
02915 
02916     // if a key modifier is pressed while dragging the frame,
02917     // don't dock the window
02918     if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT))
02919     {
02920         // do the drop calculation
02921         DoDrop(m_docks, m_panes, pane, client_pt, action_offset);
02922     }
02923 
02924     // if the pane is still floating, update it's floating
02925     // position (that we store)
02926     if (pane.IsFloating())
02927     {
02928         pane.floating_pos = pane.frame->GetPosition();
02929 
02930 #if wxCHECK_VERSION(2,7,0)
02931         if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
02932             pane.frame->SetTransparent(255);
02933 #endif
02934     }
02935 
02936     Update();
02937 
02938     HideHint();
02939 }
02940 
02941 void wxAuiManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size)
02942 {
02943     // try to find the pane
02944     wxAuiPaneInfo& pane = GetPane(wnd);
02945     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
02946 
02947     pane.floating_size = size;
02948 }
02949 
02950 
02951 void wxAuiManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt)
02952 {
02953     // try to find the pane
02954     wxAuiPaneInfo& pane = GetPane(wnd);
02955     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
02956 
02957 
02958     // fire pane close event
02959     wxAuiManagerEvent e(wxEVT_AUI_PANE_CLOSE);
02960     e.SetPane(&pane);
02961     e.SetCanVeto(evt.CanVeto());
02962     ProcessMgrEvent(e);
02963 
02964     if (e.GetVeto())
02965     {
02966         evt.Veto();
02967         return;
02968     }
02969      else
02970     {
02971         // reparent the pane window back to us and
02972         // prepare the frame window for destruction
02973         pane.window->Show(false);
02974         pane.window->Reparent(m_frame);
02975         pane.frame = NULL;
02976         pane.Hide();
02977     }
02978 }
02979 
02980 
02981 
02982 void wxAuiManager::OnFloatingPaneActivated(wxWindow* wnd)
02983 {
02984     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
02985     {
02986         // try to find the pane
02987         wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found"));
02988 
02989         SetActivePane(m_panes, wnd);
02990         Repaint();
02991     }
02992 }
02993 
02994 // OnRender() draws all of the pane captions, sashes,
02995 // backgrounds, captions, grippers, pane borders and buttons.
02996 // It renders the entire user interface.
02997 
02998 void wxAuiManager::OnRender(wxAuiManagerEvent& evt)
02999 {
03000     wxDC* dc = evt.GetDC();
03001 
03002 #ifdef __WXMAC__
03003     dc->Clear() ;
03004 #endif
03005     int i, part_count;
03006     for (i = 0, part_count = m_uiparts.GetCount();
03007          i < part_count; ++i)
03008     {
03009         wxAuiDockUIPart& part = m_uiparts.Item(i);
03010 
03011         // don't draw hidden pane items
03012         if (part.sizer_item && !part.sizer_item->IsShown())
03013             continue;
03014 
03015         switch (part.type)
03016         {
03017             case wxAuiDockUIPart::typeDockSizer:
03018             case wxAuiDockUIPart::typePaneSizer:
03019                 m_art->DrawSash(*dc, part.orientation, part.rect);
03020                 break;
03021             case wxAuiDockUIPart::typeBackground:
03022                 m_art->DrawBackground(*dc, part.orientation, part.rect);
03023                 break;
03024             case wxAuiDockUIPart::typeCaption:
03025                 m_art->DrawCaption(*dc, part.pane->caption, part.rect, *part.pane);
03026                 break;
03027             case wxAuiDockUIPart::typeGripper:
03028                 m_art->DrawGripper(*dc, part.rect, *part.pane);
03029                 break;
03030             case wxAuiDockUIPart::typePaneBorder:
03031                 m_art->DrawBorder(*dc, part.rect, *part.pane);
03032                 break;
03033             case wxAuiDockUIPart::typePaneButton:
03034                 m_art->DrawPaneButton(*dc, part.button->button_id,
03035                         wxAUI_BUTTON_STATE_NORMAL, part.rect, *part.pane);
03036                 break;
03037         }
03038     }
03039 }
03040 
03041 
03042 // Render() fire a render event, which is normally handled by
03043 // wxAuiManager::OnRender().  This allows the render function to
03044 // be overridden via the render event.  This can be useful for paintin
03045 // custom graphics in the main window. Default behavior can be
03046 // invoked in the overridden function by calling OnRender()
03047 
03048 void wxAuiManager::Render(wxDC* dc)
03049 {
03050     wxAuiManagerEvent e(wxEVT_AUI_RENDER);
03051     e.SetDC(dc);
03052     ProcessMgrEvent(e);
03053 }
03054 
03055 void wxAuiManager::Repaint(wxDC* dc)
03056 {
03057 #ifdef __WXMAC__
03058     if ( dc == NULL )
03059     {
03060         m_frame->Refresh() ;
03061         m_frame->Update() ;
03062         return ;
03063     }
03064 #endif
03065     int w, h;
03066     m_frame->GetClientSize(&w, &h);
03067 
03068     // figure out which dc to use; if one
03069     // has been specified, use it, otherwise
03070     // make a client dc
03071     wxClientDC* client_dc = NULL;
03072     if (!dc)
03073     {
03074         client_dc = new wxClientDC(m_frame);
03075         dc = client_dc;
03076     }
03077 
03078     // if the frame has a toolbar, the client area
03079     // origin will not be (0,0).
03080     wxPoint pt = m_frame->GetClientAreaOrigin();
03081     if (pt.x != 0 || pt.y != 0)
03082         dc->SetDeviceOrigin(pt.x, pt.y);
03083 
03084     // render all the items
03085     Render(dc);
03086 
03087     // if we created a client_dc, delete it
03088     if (client_dc)
03089         delete client_dc;
03090 }
03091 
03092 void wxAuiManager::OnPaint(wxPaintEvent& WXUNUSED(event))
03093 {
03094     wxPaintDC dc(m_frame);
03095     Repaint(&dc);
03096 }
03097 
03098 void wxAuiManager::OnEraseBackground(wxEraseEvent& event)
03099 {
03100 #ifdef __WXMAC__
03101     event.Skip() ;
03102 #else
03103     wxUnusedVar(event);
03104 #endif
03105 }
03106 
03107 void wxAuiManager::OnSize(wxSizeEvent& WXUNUSED(event))
03108 {
03109     if (m_frame)
03110     {
03111         DoFrameLayout();
03112         Repaint();
03113     }
03114 }
03115 
03116 
03117 void wxAuiManager::OnSetCursor(wxSetCursorEvent& event)
03118 {
03119     // determine cursor
03120     wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY());
03121     wxCursor cursor = wxNullCursor;
03122 
03123     if (part)
03124     {
03125         if (part->type == wxAuiDockUIPart::typeDockSizer ||
03126             part->type == wxAuiDockUIPart::typePaneSizer)
03127         {
03128             // a dock may not be resized if it has a single
03129             // pane which is not resizable
03130             if (part->type == wxAuiDockUIPart::typeDockSizer && part->dock &&
03131                 part->dock->panes.GetCount() == 1 &&
03132                 part->dock->panes.Item(0)->IsFixed())
03133                     return;
03134 
03135             // panes that may not be resized do not get a sizing cursor
03136             if (part->pane && part->pane->IsFixed())
03137                 return;
03138 
03139             if (part->orientation == wxVERTICAL)
03140                 cursor = wxCursor(wxCURSOR_SIZEWE);
03141                  else
03142                 cursor = wxCursor(wxCURSOR_SIZENS);
03143         }
03144          else if (part->type == wxAuiDockUIPart::typeGripper)
03145         {
03146             cursor = wxCursor(wxCURSOR_SIZING);
03147         }
03148     }
03149 
03150     event.SetCursor(cursor);
03151 }
03152 
03153 
03154 
03155 void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart* button_ui_part,
03156                                           const wxMouseEvent& event)
03157 {
03158     wxAuiDockUIPart* hit_test = HitTest(event.GetX(), event.GetY());
03159 
03160     int state = wxAUI_BUTTON_STATE_NORMAL;
03161 
03162     if (hit_test == button_ui_part)
03163     {
03164         if (event.LeftDown())
03165             state = wxAUI_BUTTON_STATE_PRESSED;
03166              else
03167             state = wxAUI_BUTTON_STATE_HOVER;
03168     }
03169     else
03170     {
03171         if (event.LeftDown())
03172             state = wxAUI_BUTTON_STATE_HOVER;
03173     }
03174 
03175     // now repaint the button with hover state
03176     wxClientDC cdc(m_frame);
03177 
03178     // if the frame has a toolbar, the client area
03179     // origin will not be (0,0).
03180     wxPoint pt = m_frame->GetClientAreaOrigin();
03181     if (pt.x != 0 || pt.y != 0)
03182         cdc.SetDeviceOrigin(pt.x, pt.y);
03183 
03184     m_art->DrawPaneButton(cdc,
03185               button_ui_part->button->button_id,
03186               state,
03187               button_ui_part->rect,
03188               *hit_test->pane);
03189 }
03190 
03191 void wxAuiManager::OnLeftDown(wxMouseEvent& event)
03192 {
03193     wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY());
03194     if (part)
03195     {
03196         if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER)
03197             return;
03198 
03199         if (part->type == wxAuiDockUIPart::typeDockSizer ||
03200             part->type == wxAuiDockUIPart::typePaneSizer)
03201         {
03202             // a dock may not be resized if it has a single
03203             // pane which is not resizable
03204             if (part->type == wxAuiDockUIPart::typeDockSizer && part->dock &&
03205                 part->dock->panes.GetCount() == 1 &&
03206                 part->dock->panes.Item(0)->IsFixed())
03207                     return;
03208 
03209             // panes that may not be resized should be ignored here
03210             if (part->pane && part->pane->IsFixed())
03211                 return;
03212 
03213             m_action = actionResize;
03214             m_action_part = part;
03215             m_action_hintrect = wxRect();
03216             m_action_start = wxPoint(event.m_x, event.m_y);
03217             m_action_offset = wxPoint(event.m_x - part->rect.x,
03218                                       event.m_y - part->rect.y);
03219             m_frame->CaptureMouse();
03220         }
03221          else if (part->type == wxAuiDockUIPart::typePaneButton)
03222         {
03223             m_action = actionClickButton;
03224             m_action_part = part;
03225             m_action_start = wxPoint(event.m_x, event.m_y);
03226             m_frame->CaptureMouse();
03227 
03228             UpdateButtonOnScreen(part, event);
03229         }
03230          else if (part->type == wxAuiDockUIPart::typeCaption ||
03231                   part->type == wxAuiDockUIPart::typeGripper)
03232         {
03233             if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
03234             {
03235                 // set the caption as active
03236                 SetActivePane(m_panes, part->pane->window);
03237                 Repaint();
03238             }
03239 
03240             m_action = actionClickCaption;
03241             m_action_part = part;
03242             m_action_start = wxPoint(event.m_x, event.m_y);
03243             m_action_offset = wxPoint(event.m_x - part->rect.x,
03244                                       event.m_y - part->rect.y);
03245             m_frame->CaptureMouse();
03246         }
03247 #ifdef __WXMAC__
03248         else
03249         {
03250             event.Skip();
03251         }
03252 #endif
03253     }
03254 #ifdef __WXMAC__
03255     else
03256     {
03257         event.Skip();
03258     }
03259 #else
03260     event.Skip();
03261 #endif
03262 }
03263 
03264 
03265 void wxAuiManager::OnLeftUp(wxMouseEvent& event)
03266 {
03267     if (m_action == actionResize)
03268     {
03269         m_frame->ReleaseMouse();
03270 
03271         // get rid of the hint rectangle
03272         wxScreenDC dc;
03273         DrawResizeHint(dc, m_action_hintrect);
03274 
03275         // resize the dock or the pane
03276         if (m_action_part && m_action_part->type==wxAuiDockUIPart::typeDockSizer)
03277         {
03278             wxRect& rect = m_action_part->dock->rect;
03279 
03280             wxPoint new_pos(event.m_x - m_action_offset.x,
03281                             event.m_y - m_action_offset.y);
03282 
03283             switch (m_action_part->dock->dock_direction)
03284             {
03285                 case wxAUI_DOCK_LEFT:
03286                     m_action_part->dock->size = new_pos.x - rect.x;
03287                     break;
03288                 case wxAUI_DOCK_TOP:
03289                     m_action_part->dock->size = new_pos.y - rect.y;
03290                     break;
03291                 case wxAUI_DOCK_RIGHT:
03292                     m_action_part->dock->size = rect.x + rect.width -
03293                                   new_pos.x - m_action_part->rect.GetWidth();
03294                     break;
03295                 case wxAUI_DOCK_BOTTOM:
03296                     m_action_part->dock->size = rect.y + rect.height -
03297                                   new_pos.y - m_action_part->rect.GetHeight();
03298                     break;
03299             }
03300 
03301             Update();
03302             Repaint(NULL);
03303         }
03304          else if (m_action_part &&
03305                   m_action_part->type == wxAuiDockUIPart::typePaneSizer)
03306         {
03307             wxAuiDockInfo& dock = *m_action_part->dock;
03308             wxAuiPaneInfo& pane = *m_action_part->pane;
03309 
03310             int total_proportion = 0;
03311             int dock_pixels = 0;
03312             int new_pixsize = 0;
03313 
03314             int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE);
03315             int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
03316             int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE);
03317 
03318             wxPoint new_pos(event.m_x - m_action_offset.x,
03319                             event.m_y - m_action_offset.y);
03320 
03321             // determine the pane rectangle by getting the pane part
03322             wxAuiDockUIPart* pane_part = GetPanePart(pane.window);
03323             wxASSERT_MSG(pane_part,
03324                        wxT("Pane border part not found -- shouldn't happen"));
03325 
03326             // determine the new pixel size that the user wants;
03327             // this will help us recalculate the pane's proportion
03328             if (dock.IsHorizontal())
03329                 new_pixsize = new_pos.x - pane_part->rect.x;
03330                  else
03331                 new_pixsize = new_pos.y - pane_part->rect.y;
03332 
03333             // determine the size of the dock, based on orientation
03334             if (dock.IsHorizontal())
03335                 dock_pixels = dock.rect.GetWidth();
03336                  else
03337                 dock_pixels = dock.rect.GetHeight();
03338 
03339             // determine the total proportion of all resizable panes,
03340             // and the total size of the dock minus the size of all
03341             // the fixed panes
03342             int i, dock_pane_count = dock.panes.GetCount();
03343             int pane_position = -1;
03344             for (i = 0; i < dock_pane_count; ++i)
03345             {
03346                 wxAuiPaneInfo& p = *dock.panes.Item(i);
03347                 if (p.window == pane.window)
03348                     pane_position = i;
03349 
03350                 // while we're at it, subtract the pane sash
03351                 // width from the dock width, because this would
03352                 // skew our proportion calculations
03353                 if (i > 0)
03354                     dock_pixels -= sash_size;
03355 
03356                 // also, the whole size (including decorations) of
03357                 // all fixed panes must also be subtracted, because they
03358                 // are not part of the proportion calculation
03359                 if (p.IsFixed())
03360                 {
03361                     if (dock.IsHorizontal())
03362                         dock_pixels -= p.best_size.x;
03363                          else
03364                         dock_pixels -= p.best_size.y;
03365                 }
03366                  else
03367                 {
03368                     total_proportion += p.dock_proportion;
03369                 }
03370             }
03371 
03372             // find a pane in our dock to 'steal' space from or to 'give'
03373             // space to -- this is essentially what is done when a pane is
03374             // resized; the pane should usually be the first non-fixed pane
03375             // to the right of the action pane
03376             int borrow_pane = -1;
03377             for (i = pane_position+1; i < dock_pane_count; ++i)
03378             {
03379                 wxAuiPaneInfo& p = *dock.panes.Item(i);
03380                 if (!p.IsFixed())
03381                 {
03382                     borrow_pane = i;
03383                     break;
03384                 }
03385             }
03386 
03387 
03388             // demand that the pane being resized is found in this dock
03389             // (this assert really never should be raised)
03390             wxASSERT_MSG(pane_position != -1, wxT("Pane not found in dock"));
03391 
03392             // prevent division by zero
03393             if (dock_pixels == 0 || total_proportion == 0 || borrow_pane == -1)
03394             {
03395                 m_action = actionNone;
03396                 return;
03397             }
03398 
03399             // calculate the new proportion of the pane
03400             int new_proportion = (new_pixsize*total_proportion)/dock_pixels;
03401 
03402             // default minimum size
03403             int min_size = 0;
03404 
03405             // check against the pane's minimum size, if specified. please note
03406             // that this is not enough to ensure that the minimum size will
03407             // not be violated, because the whole frame might later be shrunk,
03408             // causing the size of the pane to violate it's minimum size
03409             if (pane.min_size.IsFullySpecified())
03410             {
03411                 min_size = 0;
03412 
03413                 if (pane.HasBorder())
03414                     min_size += (pane_border_size*2);
03415 
03416                 // calculate minimum size with decorations (border,caption)
03417                 if (pane_part->orientation == wxVERTICAL)
03418                 {
03419                     min_size += pane.min_size.y;
03420                     if (pane.HasCaption())
03421                         min_size += caption_size;
03422                 }
03423                  else
03424                 {
03425                     min_size += pane.min_size.x;
03426                 }
03427             }
03428 
03429 
03430             // for some reason, an arithmatic error somewhere is causing
03431             // the proportion calculations to always be off by 1 pixel;
03432             // for now we will add the 1 pixel on, but we really should
03433             // determine what's causing this.
03434             min_size++;
03435 
03436             int min_proportion = (min_size*total_proportion)/dock_pixels;
03437 
03438             if (new_proportion < min_proportion)
03439                 new_proportion = min_proportion;
03440 
03441 
03442 
03443             int prop_diff = new_proportion - pane.dock_proportion;
03444 
03445             // borrow the space from our neighbor pane to the
03446             // right or bottom (depending on orientation)
03447             dock.panes.Item(borrow_pane)->dock_proportion -= prop_diff;
03448             pane.dock_proportion = new_proportion;
03449 
03450             // repaint
03451             Update();
03452             Repaint(NULL);
03453         }
03454     }
03455     else if (m_action == actionClickButton)
03456     {
03457         m_hover_button = NULL;
03458         m_frame->ReleaseMouse();
03459         UpdateButtonOnScreen(m_action_part, event);
03460 
03461         // make sure we're still over the item that was originally clicked
03462         if (m_action_part == HitTest(event.GetX(), event.GetY()))
03463         {
03464             // fire button-click event
03465             wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON);
03466             e.SetPane(m_action_part->pane);
03467             e.SetButton(m_action_part->button->button_id);
03468             ProcessMgrEvent(e);
03469         }
03470     }
03471     else if (m_action == actionClickCaption)
03472     {
03473         m_frame->ReleaseMouse();
03474     }
03475     else if (m_action == actionDragFloatingPane)
03476     {
03477         m_frame->ReleaseMouse();
03478     }
03479     else if (m_action == actionDragToolbarPane)
03480     {
03481         m_frame->ReleaseMouse();
03482 
03483         wxAuiPaneInfo& pane = GetPane(m_action_window);
03484         wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
03485 
03486         // save the new positions
03487         wxAuiDockInfoPtrArray docks;
03488         FindDocks(m_docks, pane.dock_direction,
03489                   pane.dock_layer, pane.dock_row, docks);
03490         if (docks.GetCount() == 1)
03491         {
03492             wxAuiDockInfo& dock = *docks.Item(0);
03493 
03494             wxArrayInt pane_positions, pane_sizes;
03495             GetPanePositionsAndSizes(dock, pane_positions, pane_sizes);
03496 
03497             int i, dock_pane_count = dock.panes.GetCount();
03498             for (i = 0; i < dock_pane_count; ++i)
03499                 dock.panes.Item(i)->dock_pos = pane_positions[i];
03500         }
03501 
03502         pane.state &= ~wxAuiPaneInfo::actionPane;
03503         Update();
03504     }
03505     else
03506     {
03507         event.Skip();
03508     }
03509 
03510     m_action = actionNone;
03511     m_last_mouse_move = wxPoint(); // see comment in OnMotion()
03512 }
03513 
03514 
03515 void wxAuiManager::OnMotion(wxMouseEvent& event)
03516 {
03517     // sometimes when Update() is called from inside this method,
03518     // a spurious mouse move event is generated; this check will make
03519     // sure that only real mouse moves will get anywhere in this method;
03520     // this appears to be a bug somewhere, and I don't know where the
03521     // mouse move event is being generated.  only verified on MSW
03522 
03523     wxPoint mouse_pos = event.GetPosition();
03524     if (m_last_mouse_move == mouse_pos)
03525         return;
03526     m_last_mouse_move = mouse_pos;
03527 
03528 
03529     if (m_action == actionResize)
03530     {
03531         wxPoint pos = m_action_part->rect.GetPosition();
03532         if (m_action_part->orientation == wxHORIZONTAL)
03533             pos.y = wxMax(0, event.m_y - m_action_offset.y);
03534              else
03535             pos.x = wxMax(0, event.m_x - m_action_offset.x);
03536 
03537         wxRect rect(m_frame->ClientToScreen(pos),
03538                     m_action_part->rect.GetSize());
03539 
03540         wxScreenDC dc;
03541         if (!m_action_hintrect.IsEmpty())
03542             DrawResizeHint(dc, m_action_hintrect);
03543         DrawResizeHint(dc, rect);
03544         m_action_hintrect = rect;
03545     }
03546     else if (m_action == actionClickCaption)
03547     {
03548         int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
03549         int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
03550 
03551         // caption has been clicked.  we need to check if the mouse
03552         // is now being dragged. if it is, we need to change the
03553         // mouse action to 'drag'
03554         if (abs(event.m_x - m_action_start.x) > drag_x_threshold ||
03555             abs(event.m_y - m_action_start.y) > drag_y_threshold)
03556         {
03557             wxAuiPaneInfo* pane_info = m_action_part->pane;
03558 
03559             if (!pane_info->IsToolbar())
03560             {
03561                 if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
03562                     pane_info->IsFloatable())
03563                 {
03564                     m_action = actionDragFloatingPane;
03565 
03566                     // set initial float position
03567                     wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
03568                     pane_info->floating_pos = wxPoint(pt.x - m_action_offset.x,
03569                                                       pt.y - m_action_offset.y);
03570                     // float the window
03571                     pane_info->Float();
03572                     Update();
03573 
03574                     m_action_window = pane_info->frame;
03575 
03576                     // action offset is used here to make it feel "natural" to the user
03577                     // to drag a docked pane and suddenly have it become a floating frame.
03578                     // Sometimes, however, the offset where the user clicked on the docked
03579                     // caption is bigger than the width of the floating frame itself, so
03580                     // in that case we need to set the action offset to a sensible value
03581                     wxSize frame_size = m_action_window->GetSize();
03582                     if (frame_size.x <= m_action_offset.x)
03583                         m_action_offset.x = 30;
03584                 }
03585             }
03586              else
03587             {
03588                 m_action = actionDragToolbarPane;
03589                 m_action_window = pane_info->window;
03590             }
03591         }
03592     }
03593     else if (m_action == actionDragFloatingPane)
03594     {
03595         wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
03596         m_action_window->Move(pt.x - m_action_offset.x,
03597                              pt.y - m_action_offset.y);
03598     }
03599     else if (m_action == actionDragToolbarPane)
03600     {
03601         wxAuiPaneInfo& pane = GetPane(m_action_window);
03602         wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
03603 
03604         pane.state |= wxAuiPaneInfo::actionPane;
03605 
03606         wxPoint pt = event.GetPosition();
03607         DoDrop(m_docks, m_panes, pane, pt, m_action_offset);
03608 
03609         // if DoDrop() decided to float the pane, set up
03610         // the floating pane's initial position
03611         if (pane.IsFloating())
03612         {
03613             wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
03614             pane.floating_pos = wxPoint(pt.x - m_action_offset.x,
03615                                         pt.y - m_action_offset.y);
03616         }
03617 
03618         // this will do the actiual move operation;
03619         // in the case that the pane has been floated,
03620         // this call will create the floating pane
03621         // and do the reparenting
03622         Update();
03623 
03624         // if the pane has been floated, change the mouse
03625         // action actionDragFloatingPane so that subsequent
03626         // EVT_MOTION() events will move the floating pane
03627         if (pane.IsFloating())
03628         {
03629             pane.state &= ~wxAuiPaneInfo::actionPane;
03630             m_action = actionDragFloatingPane;
03631             m_action_window = pane.frame;
03632         }
03633     }
03634     else
03635     {
03636         wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY());
03637         if (part && part->type == wxAuiDockUIPart::typePaneButton)
03638         {
03639             if (part != m_hover_button)
03640             {
03641                 // make the old button normal
03642                 if (m_hover_button)
03643                     UpdateButtonOnScreen(m_hover_button, event);
03644 
03645                 // mouse is over a button, so repaint the
03646                 // button in hover mode
03647                 UpdateButtonOnScreen(part, event);
03648                 m_hover_button = part;
03649             }
03650         }
03651          else
03652         {
03653             if (m_hover_button)
03654             {
03655                 m_hover_button = NULL;
03656                 Repaint();
03657             }
03658              else
03659             {
03660                 event.Skip();
03661             }
03662         }
03663     }
03664 }
03665 
03666 void wxAuiManager::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
03667 {
03668     if (m_hover_button)
03669     {
03670         m_hover_button = NULL;
03671         Repaint();
03672     }
03673 }
03674 
03675 void wxAuiManager::OnChildFocus(wxChildFocusEvent& event)
03676 {
03677     // when a child pane has it's focus set, we should change the
03678     // pane's active state to reflect this. (this is only true if
03679     // active panes are allowed by the owner)
03680     if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE)
03681     {
03682         if (GetPane(event.GetWindow()).IsOk())
03683         {
03684             SetActivePane(m_panes, event.GetWindow());
03685             m_frame->Refresh();
03686         }
03687     }
03688 
03689     event.Skip();
03690 }
03691 
03692 
03693 // OnPaneButton() is an event handler that is called
03694 // when a pane button has been pressed.
03695 void wxAuiManager::OnPaneButton(wxAuiManagerEvent& evt)
03696 {
03697     wxASSERT_MSG(evt.pane, wxT("Pane Info passed to wxAuiManager::OnPaneButton must be non-null"));
03698 
03699     wxAuiPaneInfo& pane = *(evt.pane);
03700 
03701     if (evt.button == wxAuiPaneInfo::buttonClose)
03702     {
03703         // fire pane close event
03704         wxAuiManagerEvent e(wxEVT_AUI_PANE_CLOSE);
03705         e.SetPane(evt.pane);
03706         ProcessMgrEvent(e);
03707 
03708         if (!e.GetVeto())
03709         {
03710             pane.Hide();
03711             Update();
03712         }
03713     }
03714      else if (evt.button == wxAuiPaneInfo::buttonPin)
03715     {
03716         if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) &&
03717             pane.IsFloatable())
03718                 pane.Float();
03719         Update();
03720     }
03721 }
03722 
03723 #endif // wxUSE_AUI

Generated on Sat Nov 10 03:49:01 2007 for Camelot by  doxygen 1.4.4