X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/528a5e8f92e938407ee2c33b29e519af064e6608..908eeca88dee75d5ac3ba10d539fb7e0f5387d2c:/src/aui/framemanager.cpp diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index 98e77ae3e9..9e91f09a2a 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -28,6 +28,7 @@ #include "wx/aui/framemanager.h" #include "wx/aui/dockart.h" #include "wx/aui/floatpane.h" +#include "wx/aui/tabmdi.h" #ifndef WX_PRECOMP #include "wx/panel.h" @@ -52,11 +53,12 @@ WX_DEFINE_OBJARRAY(wxAuiPaneInfoArray) wxAuiPaneInfo wxAuiNullPaneInfo; wxAuiDockInfo wxAuiNullDockInfo; -DEFINE_EVENT_TYPE(wxEVT_AUI_PANEBUTTON) -DEFINE_EVENT_TYPE(wxEVT_AUI_PANECLOSE) -DEFINE_EVENT_TYPE(wxEVT_AUI_PANEMAXIMIZE) -DEFINE_EVENT_TYPE(wxEVT_AUI_PANERESTORE) +DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_BUTTON) +DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_CLOSE) +DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_MAXIMIZE) +DEFINE_EVENT_TYPE(wxEVT_AUI_PANE_RESTORE) DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER) +DEFINE_EVENT_TYPE(wxEVT_AUI_FIND_MANAGER) #ifdef __WXMAC__ // a few defines to avoid nameclashes @@ -65,7 +67,20 @@ DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER) #include "wx/mac/private.h" #endif +#ifdef __WXMSW__ + #include "wx/msw/wrapwin.h" + #include "wx/msw/private.h" +#endif + IMPLEMENT_DYNAMIC_CLASS(wxAuiManagerEvent, wxEvent) +IMPLEMENT_CLASS(wxAuiManager, wxEvtHandler) + + + +const int auiToolBarLayer = 10; + +#ifndef __WXGTK20__ + class wxPseudoTransparentFrame : public wxFrame { @@ -144,7 +159,7 @@ public: wxRect rect(upd.GetRect()); dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); - upd++; + ++upd; } } @@ -201,6 +216,72 @@ BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame) END_EVENT_TABLE() +#else + // __WXGTK20__ + +#include + +static void +gtk_pseudo_window_realized_callback( GtkWidget *m_widget, void *WXUNUSED(win) ) +{ + wxSize disp = wxGetDisplaySize(); + int amount = 128; + wxRegion region; + for (int y=0; ywindow, region.GetRegion(), 0, 0); +} + + +class wxPseudoTransparentFrame: public wxFrame +{ +public: + wxPseudoTransparentFrame(wxWindow* parent = NULL, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE, + const wxString &name = wxT("frame")) + { + if (!CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) + return; + + m_title = title; + + m_widget = gtk_window_new( GTK_WINDOW_POPUP ); + + g_signal_connect( m_widget, "realize", + G_CALLBACK (gtk_pseudo_window_realized_callback), this ); + + GdkColor col; + col.red = 128 * 256; + col.green = 192 * 256; + col.blue = 255 * 256; + gtk_widget_modify_bg( m_widget, GTK_STATE_NORMAL, &col ); + } + + bool SetTransparent(wxByte WXUNUSED(alpha)) + { + return true; + } + +private: + DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame) +}; + +IMPLEMENT_DYNAMIC_CLASS(wxPseudoTransparentFrame, wxFrame) + +#endif + // __WXGTK20__ + + + // -- static utility functions -- static wxBitmap wxPaneCreateStippleBitmap() @@ -215,10 +296,14 @@ static void DrawResizeHint(wxDC& dc, const wxRect& rect) wxBitmap stipple = wxPaneCreateStippleBitmap(); wxBrush brush(stipple); dc.SetBrush(brush); +#ifdef __WXMSW__ + PatBlt(GetHdcOf(dc), rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight(), PATINVERT); +#else dc.SetPen(*wxTRANSPARENT_PEN); dc.SetLogicalFunction(wxXOR); dc.DrawRectangle(rect); +#endif } @@ -248,7 +333,8 @@ static void CopyDocksAndPanes(wxAuiDockInfoArray& dest_docks, // GetMaxLayer() is an internal function which returns // the highest layer inside the specified dock -static int GetMaxLayer(const wxAuiDockInfoArray& docks, int dock_direction) +static int GetMaxLayer(const wxAuiDockInfoArray& docks, + int dock_direction) { int i, dock_count, max_layer = 0; for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) @@ -421,20 +507,26 @@ static void RemovePaneFromDocks(wxAuiDockInfoArray& docks, } } +/* +// This function works fine, and may be used in the future + // RenumberDockRows() takes a dock and assigns sequential numbers // to existing rows. Basically it takes out the gaps; so if a // dock has rows with numbers 0,2,5, they will become 0,1,2 static void RenumberDockRows(wxAuiDockInfoPtrArray& docks) { - int i, dock_count, j, pane_count; + int i, dock_count; for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) { wxAuiDockInfo& dock = *docks.Item(i); dock.dock_row = i; + + int j, pane_count; for (j = 0, pane_count = dock.panes.GetCount(); j < pane_count; ++j) dock.panes.Item(j)->dock_row = i; } } +*/ // SetActivePane() sets the active pane, as well as cycles through @@ -464,7 +556,7 @@ static int PaneSortFunc(wxAuiPaneInfo** p1, wxAuiPaneInfo** p2) BEGIN_EVENT_TABLE(wxAuiManager, wxEvtHandler) - EVT_AUI_PANEBUTTON(wxAuiManager::OnPaneButton) + EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton) EVT_AUI_RENDER(wxAuiManager::OnRender) EVT_PAINT(wxAuiManager::OnPaint) EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground) @@ -475,6 +567,7 @@ BEGIN_EVENT_TABLE(wxAuiManager, wxEvtHandler) EVT_MOTION(wxAuiManager::OnMotion) EVT_LEAVE_WINDOW(wxAuiManager::OnLeaveWindow) EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus) + EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager) EVT_TIMER(101, wxAuiManager::OnHintFadeTimer) END_EVENT_TABLE() @@ -490,7 +583,10 @@ wxAuiManager::wxAuiManager(wxWindow* managed_wnd, unsigned int flags) m_skipping = false; m_has_maximized = false; m_frame = NULL; - + m_dock_constraint_x = 0.3; + m_dock_constraint_y = 0.3; + m_reserved = NULL; + if (managed_wnd) { SetManagedWindow(managed_wnd); @@ -499,13 +595,34 @@ wxAuiManager::wxAuiManager(wxWindow* managed_wnd, unsigned int flags) wxAuiManager::~wxAuiManager() { + // NOTE: It's possible that the windows have already been destroyed by the + // time this dtor is called, so this loop can result in memory access via + // invalid pointers, resulting in a crash. So it will be disabled while + // waiting for a better solution. +#if 0 + for ( size_t i = 0; i < m_panes.size(); i++ ) + { + wxAuiPaneInfo& pinfo = m_panes[i]; + if (pinfo.window && !pinfo.window->GetParent()) + delete pinfo.window; + } +#endif + delete m_art; } -// Creates a floating frame for the windows -wxAuiFloatingFrame * wxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p) +// creates a floating frame for the windows +wxAuiFloatingFrame* wxAuiManager::CreateFloatingFrame(wxWindow* parent, + const wxAuiPaneInfo& pane_info) { - return new wxAuiFloatingFrame(parent, this, p); + return new wxAuiFloatingFrame(parent, this, pane_info); +} + +bool wxAuiManager::CanDockPanel(const wxAuiPaneInfo & WXUNUSED(p)) +{ + // if a key modifier is pressed while dragging the frame, + // don't dock the window + return !(wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT)); } // GetPane() looks up a wxAuiPaneInfo structure based @@ -599,7 +716,7 @@ void wxAuiManager::SetFlags(unsigned int flags) // set the new flags m_flags = flags; - + if (update_hint_wnd) { UpdateHintWindowConfig(); @@ -625,26 +742,41 @@ wxFrame* wxAuiManager::GetFrame() const } +// this function will return the aui manager for a given +// window. The |window| parameter should be any child window +// or grand-child window (and so on) of the frame/window +// managed by wxAuiManager. The |window| parameter does not +// need to be managed by the manager itself. +wxAuiManager* wxAuiManager::GetManager(wxWindow* window) +{ + wxAuiManagerEvent evt(wxEVT_AUI_FIND_MANAGER); + evt.SetManager(NULL); + evt.ResumePropagation(wxEVENT_PROPAGATE_MAX); + if (!window->ProcessEvent(evt)) + return NULL; + + return evt.GetManager(); +} + + void wxAuiManager::UpdateHintWindowConfig() { // find out if the the system can do transparent frames bool can_do_transparent = false; - + wxWindow* w = m_frame; while (w) { if (w->IsKindOf(CLASSINFO(wxFrame))) { wxFrame* f = static_cast(w); - #if wxCHECK_VERSION(2,7,0) can_do_transparent = f->CanSetTransparent(); - #endif break; } - + w = w->GetParent(); } - + // if there is an existing hint window, delete it if (m_hint_wnd) { @@ -654,9 +786,9 @@ void wxAuiManager::UpdateHintWindowConfig() m_hint_fademax = 50; m_hint_wnd = NULL; - + if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) && can_do_transparent) - { + { // Make a window to use for a transparent hint #if defined(__WXMSW__) || defined(__WXGTK__) m_hint_wnd = new wxFrame(m_frame, wxID_ANY, wxEmptyString, @@ -684,9 +816,9 @@ void wxAuiManager::UpdateHintWindowConfig() // blue. p->SetBackgroundColour(*wxBLUE); #endif - + } - else + else { if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 || (m_flags & wxAUI_MGR_VENETIAN_BLINDS_HINT) != 0) @@ -734,6 +866,17 @@ void wxAuiManager::SetManagedWindow(wxWindow* wnd) wxAuiPaneInfo().Name(wxT("mdiclient")). CenterPane().PaneBorder(false)); } + else if (m_frame->IsKindOf(CLASSINFO(wxAuiMDIParentFrame))) + { + wxAuiMDIParentFrame* mdi_frame = (wxAuiMDIParentFrame*)m_frame; + wxAuiMDIClientWindow* client_window = mdi_frame->GetClientWindow(); + wxASSERT_MSG(client_window, wxT("Client window is NULL!")); + + AddPane(client_window, + wxAuiPaneInfo().Name(wxT("mdiclient")). + CenterPane().PaneBorder(false)); + } + #endif UpdateHintWindowConfig(); @@ -795,10 +938,23 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) if (!window) return false; - // check if the pane already exists + // check if the window is already managed by us if (GetPane(pane_info.window).IsOk()) return false; + // check if the pane name already exists, this could reveal a + // bug in the library user's application + bool already_exists = false; + if (!pane_info.name.empty() && GetPane(pane_info.name).IsOk()) + { + wxFAIL_MSG(wxT("A pane with that name already exists in the manager!")); + already_exists = true; + } + + // if the new pane is docked then we should undo maximize + if (pane_info.IsDocked()) + RestoreMaximizedPane(); + m_panes.Add(pane_info); wxAuiPaneInfo& pinfo = m_panes.Last(); @@ -806,8 +962,9 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) // set the pane window pinfo.window = window; + // if the pane's name identifier is blank, create a random string - if (pinfo.name.empty()) + if (pinfo.name.empty() || already_exists) { pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"), ((unsigned long)pinfo.window) & 0xffffffff, @@ -831,6 +988,13 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) pinfo.buttons.Add(button); } + if (pinfo.HasPinButton()) + { + wxAuiPaneButton button; + button.button_id = wxAUI_BUTTON_PIN; + pinfo.buttons.Add(button); + } + if (pinfo.HasCloseButton()) { wxAuiPaneButton button; @@ -855,7 +1019,8 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) // I believe this to be the correct action, until // wxToolBar::GetBestSize() is fixed. Is this assumption // correct? - pinfo.best_size.y++; + // commented out by JACS 2007-9-08 after having added a pixel in wxMSW's wxToolBar::DoGetBestSize() + // pinfo.best_size.y++; } if (pinfo.min_size != wxDefaultSize) @@ -871,8 +1036,8 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) } bool wxAuiManager::AddPane(wxWindow* window, - int direction, - const wxString& caption) + int direction, + const wxString& caption) { wxAuiPaneInfo pinfo; pinfo.Caption(caption); @@ -888,8 +1053,8 @@ bool wxAuiManager::AddPane(wxWindow* window, } bool wxAuiManager::AddPane(wxWindow* window, - const wxAuiPaneInfo& pane_info, - const wxPoint& drop_pos) + const wxAuiPaneInfo& pane_info, + const wxPoint& drop_pos) { if (!AddPane(window, pane_info)) return false; @@ -934,7 +1099,7 @@ bool wxAuiManager::InsertPane(wxWindow* window, const wxAuiPaneInfo& pane_info, { return AddPane(window, pane_info); } - else + else { if (pane_info.IsFloating()) { @@ -944,8 +1109,11 @@ bool wxAuiManager::InsertPane(wxWindow* window, const wxAuiPaneInfo& pane_info, if (pane_info.floating_size != wxDefaultSize) existing_pane.FloatingSize(pane_info.floating_size); } - else + else { + // if the new pane is docked then we should undo maximize + RestoreMaximizedPane(); + existing_pane.Direction(pane_info.dock_direction); existing_pane.Layer(pane_info.dock_layer); existing_pane.Row(pane_info.dock_row); @@ -979,9 +1147,11 @@ bool wxAuiManager::DetachPane(wxWindow* window) p.frame->Show(false); // reparent to m_frame and destroy the pane - if(m_action_window == p.frame) { + if (m_action_window == p.frame) + { m_action_window = NULL; } + p.window->Reparent(m_frame); p.frame->SetSizer(NULL); p.frame->Destroy(); @@ -1012,41 +1182,45 @@ bool wxAuiManager::DetachPane(wxWindow* window) return false; } -// ClosePane() destroys or hides the pane depending on its -// flags +// ClosePane() destroys or hides the pane depending on its flags void wxAuiManager::ClosePane(wxAuiPaneInfo& pane_info) { // if we were maximized, restore - if(pane_info.IsMaximized()) { + if (pane_info.IsMaximized()) + { RestorePane(pane_info); } // first, hide the window - if (pane_info.window && pane_info.window->IsShown()) { + if (pane_info.window && pane_info.window->IsShown()) + { pane_info.window->Show(false); } // make sure that we are the parent of this window - if(pane_info.window && pane_info.window->GetParent() != m_frame) { + if (pane_info.window && pane_info.window->GetParent() != m_frame) + { pane_info.window->Reparent(m_frame); } // if we have a frame, destroy it - if(pane_info.frame) { + if (pane_info.frame) + { pane_info.frame->Destroy(); pane_info.frame = NULL; } // now we need to either destroy or hide the pane - if(pane_info.IsDestroyOnClose()) + if (pane_info.IsDestroyOnClose()) { wxWindow * window = pane_info.window; DetachPane(window); - if(window) { + if (window) + { window->Destroy(); } - } - else + } + else { pane_info.Hide(); } @@ -1060,9 +1234,16 @@ void wxAuiManager::MaximizePane(wxAuiPaneInfo& pane_info) for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) { wxAuiPaneInfo& p = m_panes.Item(i); - if(!p.IsToolbar()) { + if (!p.IsToolbar()) + { p.Restore(); - p.SaveHidden(); + + // save hidden state + p.SetFlag(wxAuiPaneInfo::savedHiddenState, + p.HasFlag(wxAuiPaneInfo::optionHidden)); + + // hide the pane, because only the newly + // maximized pane should show p.Hide(); } } @@ -1073,7 +1254,8 @@ void wxAuiManager::MaximizePane(wxAuiPaneInfo& pane_info) m_has_maximized = true; // last, show the window - if (pane_info.window && !pane_info.window->IsShown()) { + if (pane_info.window && !pane_info.window->IsShown()) + { pane_info.window->Show(true); } } @@ -1086,8 +1268,10 @@ void wxAuiManager::RestorePane(wxAuiPaneInfo& pane_info) for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) { wxAuiPaneInfo& p = m_panes.Item(i); - if(!p.IsToolbar()) { - p.RestoreHidden(); + if (!p.IsToolbar()) + { + p.SetFlag(wxAuiPaneInfo::optionHidden, + p.HasFlag(wxAuiPaneInfo::savedHiddenState)); } } @@ -1096,7 +1280,8 @@ void wxAuiManager::RestorePane(wxAuiPaneInfo& pane_info) m_has_maximized = false; // last, show the window - if (pane_info.window && !pane_info.window->IsShown()) { + if (pane_info.window && !pane_info.window->IsShown()) + { pane_info.window->Show(true); } } @@ -1109,7 +1294,8 @@ void wxAuiManager::RestoreMaximizedPane() for (i = 0, pane_count = m_panes.GetCount(); i < pane_count; ++i) { wxAuiPaneInfo& p = m_panes.Item(i); - if(p.IsMaximized()) { + if (p.IsMaximized()) + { RestorePane(p); break; } @@ -1250,7 +1436,7 @@ wxString wxAuiManager::SavePerspective() { wxString result; result.Alloc(500); - result = wxT("layout1|"); + result = wxT("layout2|"); int pane_i, pane_count = m_panes.GetCount(); for (pane_i = 0; pane_i < pane_count; ++pane_i) @@ -1281,11 +1467,13 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update) wxString part; // check layout string version + // 'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 + // 'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) part = input.BeforeFirst(wxT('|')); input = input.AfterFirst(wxT('|')); part.Trim(true); part.Trim(false); - if (part != wxT("layout1")) + if (part != wxT("layout2")) return false; // mark all panes currently managed as docked and hidden @@ -1347,12 +1535,11 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update) if (!p.IsOk()) { // the pane window couldn't be found - // in the existing layout - return false; + // in the existing layout -- skip it + continue; } p.SafeSet(pane); - } if (update) @@ -1362,12 +1549,12 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update) } void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock, - wxArrayInt& positions, - wxArrayInt& sizes) + wxArrayInt& positions, + wxArrayInt& sizes) { - int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE); - int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE); - int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE); + int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE); + int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); + int gripper_size = m_art->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE); positions.Empty(); sizes.Empty(); @@ -1405,7 +1592,7 @@ void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock, size += gripper_size; size += pane.best_size.x; } - else + else { if (pane.HasGripper() && pane.HasGripperTop()) size += gripper_size; @@ -1430,7 +1617,7 @@ void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock, if (amount >= 0) offset += amount; - else + else positions[pane_i] -= -amount; offset += sizes[pane_i]; @@ -1444,7 +1631,7 @@ void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock, int amount = positions[pane_i] - offset; if (amount >= 0) offset += amount; - else + else positions[pane_i] += -amount; offset += sizes[pane_i]; @@ -1453,25 +1640,25 @@ void wxAuiManager::GetPanePositionsAndSizes(wxAuiDockInfo& dock, void wxAuiManager::LayoutAddPane(wxSizer* cont, - wxAuiDockInfo& dock, - wxAuiPaneInfo& pane, - wxAuiDockUIPartArray& uiparts, - bool spacer_only) + wxAuiDockInfo& dock, + wxAuiPaneInfo& pane, + wxAuiDockUIPartArray& uiparts, + bool spacer_only) { wxAuiDockUIPart part; wxSizerItem* sizer_item; - int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE); - int gripper_size = m_art->GetMetric(wxAUI_ART_GRIPPER_SIZE); - int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE); - int pane_button_size = m_art->GetMetric(wxAUI_ART_PANE_BUTTON_SIZE); + int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE); + int gripper_size = m_art->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE); + int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); + int pane_button_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BUTTON_SIZE); // find out the orientation of the item (orientation for panes // is the same as the dock's orientation) int orientation; if (dock.IsHorizontal()) orientation = wxHORIZONTAL; - else + else orientation = wxVERTICAL; // this variable will store the proportion @@ -1536,6 +1723,13 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont, uiparts.Add(part); } + // if we have buttons, add a little space to the right + // of them to ease visual crowding + if (button_count >= 1) + { + caption_sizer->Add(3,1); + } + // add the caption sizer sizer_item = vert_pane_sizer->Add(caption_sizer, 0, wxEXPAND); @@ -1567,7 +1761,7 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont, // determine if the pane should have a minimum size; if the pane is - // non-resizable (fixed) then we must set a minimum size. Alternitavely, + // non-resizable (fixed) then we must set a minimum size. Alternatively, // if the pane.min_size is set, we must use that value as well wxSize min_size = pane.min_size; @@ -1616,14 +1810,14 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont, } void wxAuiManager::LayoutAddDock(wxSizer* cont, - wxAuiDockInfo& dock, - wxAuiDockUIPartArray& uiparts, - bool spacer_only) + wxAuiDockInfo& dock, + wxAuiDockUIPartArray& uiparts, + bool spacer_only) { wxSizerItem* sizer_item; wxAuiDockUIPart part; - int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE); + int sash_size = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE); int orientation = dock.IsHorizontal() ? wxHORIZONTAL : wxVERTICAL; // resizable bottom and right docks have a sash before them @@ -1662,16 +1856,17 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, { wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i)); int pane_pos = pane_positions.Item(pane_i); - if(pane.IsMaximized()) { + + if (pane.IsMaximized()) has_maximized_pane = true; - } + int amount = pane_pos - offset; if (amount > 0) { if (dock.IsVertical()) sizer_item = dock_sizer->Add(1, amount, 0, wxEXPAND); - else + else sizer_item = dock_sizer->Add(amount, 1, 0, wxEXPAND); part.type = wxAuiDockUIPart::typeBackground; @@ -1692,7 +1887,7 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, } // at the end add a very small stretchable background area - sizer_item = dock_sizer->Add(1,1, 1, wxEXPAND); + sizer_item = dock_sizer->Add(0,0, 1, wxEXPAND); part.type = wxAuiDockUIPart::typeBackground; part.dock = &dock; @@ -1708,9 +1903,9 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, for (pane_i = 0; pane_i < pane_count; ++pane_i) { wxAuiPaneInfo& pane = *(dock.panes.Item(pane_i)); - if(pane.IsMaximized()) { + + if (pane.IsMaximized()) has_maximized_pane = true; - } // if this is not the first pane being added, // we need to add a pane sizer @@ -1734,7 +1929,7 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, if (dock.dock_direction == wxAUI_DOCK_CENTER || has_maximized_pane) sizer_item = cont->Add(dock_sizer, 1, wxEXPAND); - else + else sizer_item = cont->Add(dock_sizer, 0, wxEXPAND); part.type = wxAuiDockUIPart::typeDock; @@ -1748,12 +1943,14 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, if (dock.IsHorizontal()) cont->SetItemMinSize(dock_sizer, 0, dock.size); - else + else cont->SetItemMinSize(dock_sizer, dock.size, 0); // top and left docks have a sash after them - if (!m_has_maximized && !dock.fixed && (dock.dock_direction == wxAUI_DOCK_TOP || - dock.dock_direction == wxAUI_DOCK_LEFT)) + if (!m_has_maximized && + !dock.fixed && + (dock.dock_direction == wxAUI_DOCK_TOP || + dock.dock_direction == wxAUI_DOCK_LEFT)) { sizer_item = cont->Add(sash_size, sash_size, 0, wxEXPAND); @@ -1769,21 +1966,33 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, } wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, - wxAuiDockInfoArray& docks, - wxAuiDockUIPartArray& uiparts, - bool spacer_only) + wxAuiDockInfoArray& docks, + wxAuiDockUIPartArray& uiparts, + bool spacer_only) { wxBoxSizer* container = new wxBoxSizer(wxVERTICAL); - int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE); - int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE); + int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); + int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE); wxSize cli_size = m_frame->GetClientSize(); int i, dock_count, pane_count; // empty all docks out for (i = 0, dock_count = docks.GetCount(); i < dock_count; ++i) - docks.Item(i).panes.Empty(); + { + wxAuiDockInfo& dock = docks.Item(i); + + // empty out all panes, as they will be readded below + dock.panes.Empty(); + + if (dock.fixed) + { + // always reset fixed docks' sizes, because + // the contained windows may have been resized + dock.size = 0; + } + } // iterate through all known panes, filing each @@ -1793,16 +2002,18 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, { wxAuiPaneInfo& p = panes.Item(i); - // find any docks in this layer + // find any docks with the same dock direction, dock layer, and + // dock row as the pane we are working on wxAuiDockInfo* dock; wxAuiDockInfoPtrArray arr; FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row, arr); if (arr.GetCount() > 0) { + // found the right dock dock = arr.Item(0); } - else + else { // dock was not found, so we need to create a new one wxAuiDockInfo d; @@ -1824,7 +2035,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, if (!FindPaneInDock(*dock, p.window)) dock->panes.Add(&p); } - else + else { // remove the pane from any existing docks RemovePaneFromDocks(docks, p); @@ -1865,7 +2076,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, if (dock.IsHorizontal()) size = wxMax(pane_size.y, size); - else + else size = wxMax(pane_size.x, size); } @@ -1894,14 +2105,22 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, } } - // new dock's size may not be more than 1/3 of the frame size + + // new dock's size may not be more than the dock constraint + // parameter specifies. See SetDockSizeConstraint() + + int max_dock_x_size = (int)(m_dock_constraint_x * ((double)cli_size.x)); + int max_dock_y_size = (int)(m_dock_constraint_y * ((double)cli_size.y)); + if (dock.IsHorizontal()) - size = wxMin(size, cli_size.y/3); - else - size = wxMin(size, cli_size.x/3); + size = wxMin(size, max_dock_y_size); + else + size = wxMin(size, max_dock_x_size); + // absolute minimum size for a dock is 10 pixels if (size < 10) size = 10; + dock.size = size; } @@ -1924,7 +2143,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, if (pane.min_size.y > dock_min_size) dock_min_size = pane.min_size.y; } - else + else { if (pane.min_size.x > dock_min_size) dock_min_size = pane.min_size.x; @@ -1958,6 +2177,8 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, dock.fixed = false; if (!pane.IsToolbar()) dock.toolbar = false; + if (pane.HasFlag(wxAuiPaneInfo::optionDockFixed)) + dock.fixed = true; if (pane.state & wxAuiPaneInfo::actionPane) action_pane_marked = true; } @@ -1978,7 +2199,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // if the dock mode is fixed, and none of the panes // are being moved right now, make sure the panes // do not overlap each other. If they do, we will - // adjust the panes' positions + // adjust the positions of the panes if (dock.fixed && !action_pane_marked) { wxArrayInt pane_positions, pane_sizes; @@ -1993,7 +2214,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, int amount = pane.dock_pos - offset; if (amount >= 0) offset += amount; - else + else pane.dock_pos += -amount; offset += pane_sizes[j]; @@ -2037,7 +2258,6 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // find any top docks in this layer FindDocks(docks, wxAUI_DOCK_TOP, layer, -1, arr); - RenumberDockRows(arr); if (!arr.IsEmpty()) { for (row = 0, row_count = arr.GetCount(); row < row_count; ++row) @@ -2052,7 +2272,6 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // find any left docks in this layer FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr); - RenumberDockRows(arr); if (!arr.IsEmpty()) { for (row = 0, row_count = arr.GetCount(); row < row_count; ++row) @@ -2070,7 +2289,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, for (row = 0,row_count = arr.GetCount(); rowAdd(1,1, 1, wxEXPAND); @@ -2084,14 +2303,13 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, uiparts.Add(part); } } - else + else { middle->Add(old_cont, 1, wxEXPAND); } // find any right docks in this layer FindDocks(docks, wxAUI_DOCK_RIGHT, layer, -1, arr); - RenumberDockRows(arr); if (!arr.IsEmpty()) { for (row = arr.GetCount()-1; row >= 0; --row) @@ -2104,7 +2322,6 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // find any bottom docks in this layer FindDocks(docks, wxAUI_DOCK_BOTTOM, layer, -1, arr); - RenumberDockRows(arr); if (!arr.IsEmpty()) { for (row = arr.GetCount()-1; row >= 0; --row) @@ -2134,17 +2351,38 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, } +// SetDockSizeConstraint() allows the dock constraints to be set. For example, +// specifying values of 0.5, 0.5 will mean that upon dock creation, a dock may +// not be larger than half of the window's size + +void wxAuiManager::SetDockSizeConstraint(double width_pct, double height_pct) +{ + m_dock_constraint_x = wxMax(0.0, wxMin(1.0, width_pct)); + m_dock_constraint_y = wxMax(0.0, wxMin(1.0, height_pct)); +} + +void wxAuiManager::GetDockSizeConstraint(double* width_pct, double* height_pct) const +{ + if (width_pct) + *width_pct = m_dock_constraint_x; + + if (height_pct) + *height_pct = m_dock_constraint_y; +} + + + // Update() updates the layout. Whenever changes are made to // one or more panes, this function should be called. It is the // external entry point for running the layout engine. void wxAuiManager::Update() { + m_hover_button = NULL; + wxSizer* sizer; int i, pane_count = m_panes.GetCount(); - // delete old sizer first - m_frame->SetSizer(NULL); // destroy floating panes which have been // redocked or are becoming non-floating @@ -2161,30 +2399,30 @@ void wxAuiManager::Update() p.window->SetSize(1,1); - // the following block is a workaround for bug #1531361 - // (see wxWidgets sourceforge page). On wxGTK (only), when - // a frame is shown/hidden, a move event unfortunately - // also gets fired. Because we may be dragging around - // a pane, we need to cancel that action here to prevent - // a spurious crash. - if (m_action_window == p.frame) - { - if (wxWindow::GetCapture() == m_frame) + // the following block is a workaround for bug #1531361 + // (see wxWidgets sourceforge page). On wxGTK (only), when + // a frame is shown/hidden, a move event unfortunately + // also gets fired. Because we may be dragging around + // a pane, we need to cancel that action here to prevent + // a spurious crash. + if (m_action_window == p.frame) + { + if (wxWindow::GetCapture() == m_frame) m_frame->ReleaseMouse(); m_action = actionNone; - m_action_window = NULL; - } + m_action_window = NULL; + } - // hide the frame + // hide the frame if (p.frame->IsShown()) p.frame->Show(false); // reparent to m_frame and destroy the pane - if(m_action_window == p.frame) + if (m_action_window == p.frame) { m_action_window = NULL; } - + p.window->Reparent(m_frame); p.frame->SetSizer(NULL); p.frame->Destroy(); @@ -2193,6 +2431,9 @@ void wxAuiManager::Update() } + // delete old sizer first + m_frame->SetSizer(NULL); + // create a layout for all of the panes sizer = LayoutAll(m_panes, m_docks, m_uiparts, false); @@ -2210,14 +2451,12 @@ void wxAuiManager::Update() // pane, which has recently been floated wxAuiFloatingFrame* frame = CreateFloatingFrame(m_frame, p); -#if wxCHECK_VERSION(2,7,0) // on MSW and Mac, if the owner desires transparent dragging, and // the dragging is happening right now, then the floating // window should have this style by default if (m_action == actionDragFloatingPane && (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)) frame->SetTransparent(150); -#endif frame->SetPaneWindow(p); p.frame = frame; @@ -2225,23 +2464,28 @@ void wxAuiManager::Update() if (p.IsShown() && !frame->IsShown()) frame->Show(); } - else + else { // frame already exists, make sure it's position // and size reflect the information in wxAuiPaneInfo - if (p.frame->GetPosition() != p.floating_pos) + if ((p.frame->GetPosition() != p.floating_pos) || (p.frame->GetSize() != p.floating_size)) { + p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, + p.floating_size.x, p.floating_size.y, + wxSIZE_USE_EXISTING); + /* p.frame->SetSize(p.floating_pos.x, p.floating_pos.y, wxDefaultCoord, wxDefaultCoord, wxSIZE_USE_EXISTING); //p.frame->Move(p.floating_pos.x, p.floating_pos.y); + */ } if (p.frame->IsShown() != p.IsShown()) p.frame->Show(p.IsShown()); } } - else + else { if (p.window->IsShown() != p.IsShown()) p.window->Show(p.IsShown()); @@ -2444,7 +2688,7 @@ int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo& test) { if (dock.IsVertical()) return dock.rect.y; - else + else return dock.rect.x; } } @@ -2459,7 +2703,7 @@ int wxAuiManager::GetDockPixelOffset(wxAuiPaneInfo& test) // the target info. If the operation was allowed, the function returns true. bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo& target, - const wxAuiPaneInfo& new_pos) + const wxAuiPaneInfo& new_pos) { bool allowed = false; switch (new_pos.dock_direction) @@ -2491,10 +2735,10 @@ const int auiLayerInsertPixels = 40; const int auiLayerInsertOffset = 5; bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, - wxAuiPaneInfoArray& panes, - wxAuiPaneInfo& target, - const wxPoint& pt, - const wxPoint& offset) + wxAuiPaneInfoArray& panes, + wxAuiPaneInfo& target, + const wxPoint& pt, + const wxPoint& offset) { wxSize cli_size = m_frame->GetClientSize(); @@ -2510,13 +2754,22 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, int layer_insert_offset = auiLayerInsertOffset; - if (target.IsToolbar()) + if (drop.IsToolbar()) layer_insert_offset = 0; + if (pt.x < layer_insert_offset && pt.x > layer_insert_offset-auiLayerInsertPixels) { + int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT), + GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)), + GetMaxLayer(docks, wxAUI_DOCK_TOP)) + 1; + + if (drop.IsToolbar()) + new_layer = auiToolBarLayer; + drop.Dock().Left(). + Layer(new_layer). Row(0). Position(pt.y - GetDockPixelOffset(drop) - offset.y); return ProcessDockResult(target, drop); @@ -2524,7 +2777,15 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, else if (pt.y < layer_insert_offset && pt.y > layer_insert_offset-auiLayerInsertPixels) { + int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP), + GetMaxLayer(docks, wxAUI_DOCK_LEFT)), + GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1; + + if (drop.IsToolbar()) + new_layer = auiToolBarLayer; + drop.Dock().Top(). + Layer(new_layer). Row(0). Position(pt.x - GetDockPixelOffset(drop) - offset.x); return ProcessDockResult(target, drop); @@ -2532,7 +2793,15 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, else if (pt.x >= cli_size.x - layer_insert_offset && pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels) { + int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT), + GetMaxLayer(docks, wxAUI_DOCK_TOP)), + GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)) + 1; + + if (drop.IsToolbar()) + new_layer = auiToolBarLayer; + drop.Dock().Right(). + Layer(new_layer). Row(0). Position(pt.y - GetDockPixelOffset(drop) - offset.y); return ProcessDockResult(target, drop); @@ -2544,6 +2813,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, GetMaxLayer(docks, wxAUI_DOCK_LEFT)), GetMaxLayer(docks, wxAUI_DOCK_RIGHT)) + 1; + if (drop.IsToolbar()) + new_layer = auiToolBarLayer; + drop.Dock().Bottom(). Layer(new_layer). Row(0). @@ -2551,6 +2823,7 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, return ProcessDockResult(target, drop); } + wxAuiDockUIPart* part = HitTest(pt.x, pt.y); @@ -2564,7 +2837,7 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, int dock_drop_offset = 0; if (part->dock->IsHorizontal()) dock_drop_offset = pt.x - part->dock->rect.x - offset.x; - else + else dock_drop_offset = pt.y - part->dock->rect.y - offset.y; @@ -2596,16 +2869,11 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, return ProcessDockResult(target, drop); } - else - { - m_skipping = false; - } - if (!m_skipping) - { - m_last_rect = part->dock->rect; - m_last_rect.Inflate( 15, 15 ); - } + m_skipping = false; + + m_last_rect = part->dock->rect; + m_last_rect.Inflate( 15, 15 ); drop.Dock(). Direction(part->dock->dock_direction). @@ -2783,23 +3051,19 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, insert_layer = 0; insert_dock_row = true; - if (pt.x >= part->rect.x && - pt.x < part->rect.x+new_row_pixels_x) - insert_dir = wxAUI_DOCK_LEFT; - else - if (pt.y >= part->rect.y && - pt.y < part->rect.y+new_row_pixels_y) - insert_dir = wxAUI_DOCK_TOP; - else - if (pt.x >= part->rect.x + part->rect.width-new_row_pixels_x && - pt.x < part->rect.x + part->rect.width) - insert_dir = wxAUI_DOCK_RIGHT; - else - if (pt.y >= part->rect.y+ part->rect.height-new_row_pixels_y && - pt.y < part->rect.y + part->rect.height) - insert_dir = wxAUI_DOCK_BOTTOM; - else - return false; + const wxRect& pr = part->rect; + if (pt.x >= pr.x && pt.x < pr.x + new_row_pixels_x) + insert_dir = wxAUI_DOCK_LEFT; + else if (pt.y >= pr.y && pt.y < pr.y + new_row_pixels_y) + insert_dir = wxAUI_DOCK_TOP; + else if (pt.x >= pr.x + pr.width - new_row_pixels_x && + pt.x < pr.x + pr.width) + insert_dir = wxAUI_DOCK_RIGHT; + else if (pt.y >= pr.y+ pr.height - new_row_pixels_y && + pt.y < pr.y + pr.height) + insert_dir = wxAUI_DOCK_BOTTOM; + else + return false; insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1; } @@ -2825,7 +3089,7 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, offset = pt.y - part->rect.y; size = part->rect.GetHeight(); } - else + else { offset = pt.x - part->rect.x; size = part->rect.GetWidth(); @@ -2878,12 +3142,7 @@ void wxAuiManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event)) } m_hint_fadeamt += 4; -#if wxCHECK_VERSION(2,7,0) m_hint_wnd->SetTransparent(m_hint_fadeamt); -#else - if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) - ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(m_hint_fadeamt); -#endif } void wxAuiManager::ShowHint(const wxRect& rect) @@ -2896,7 +3155,7 @@ void wxAuiManager::ShowHint(const wxRect& rect) m_last_hint = rect; m_hint_fadeamt = m_hint_fademax; - + if ((m_flags & wxAUI_MGR_HINT_FADE) && !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) && (m_flags & wxAUI_MGR_NO_VENETIAN_BLINDS_FADE)) @@ -2904,6 +3163,7 @@ void wxAuiManager::ShowHint(const wxRect& rect) m_hint_fadeamt = 0; m_hint_wnd->SetSize(rect); + m_hint_wnd->SetTransparent(m_hint_fadeamt); if (!m_hint_wnd->IsShown()) m_hint_wnd->Show(); @@ -2913,12 +3173,6 @@ void wxAuiManager::ShowHint(const wxRect& rect) if (m_action == actionDragFloatingPane && m_action_window) m_action_window->SetFocus(); -#if wxCHECK_VERSION(2,7,0) - m_hint_wnd->SetTransparent(m_hint_fadeamt); -#else - if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) - ((wxPseudoTransparentFrame*)m_hint_wnd)->SetTransparent(m_hint_fadeamt); -#endif m_hint_wnd->Raise(); @@ -2929,11 +3183,11 @@ void wxAuiManager::ShowHint(const wxRect& rect) m_hint_fadetimer.Start(5); } } - else // Not using a transparent hint window... + else // Not using a transparent hint window... { if (!(m_flags & wxAUI_MGR_RECTANGLE_HINT)) return; - + if (m_last_hint != rect) { // remove the last hint rectangle @@ -2992,12 +3246,7 @@ void wxAuiManager::HideHint() { if (m_hint_wnd->IsShown()) m_hint_wnd->Show(false); -#if wxCHECK_VERSION(2,7,0) m_hint_wnd->SetTransparent(0); -#else - if (m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) - ((wxPseudoTransparentFrame *)m_hint_wnd)->SetTransparent(0); -#endif m_hint_fadetimer.Stop(); m_last_hint = wxRect(); return; @@ -3014,15 +3263,40 @@ void wxAuiManager::HideHint() -// DrawHintRect() draws a drop hint rectangle. First calls DoDrop() to -// determine the exact position the pane would be at were if dropped. If -// the pame would indeed become docked at the specified drop point, -// DrawHintRect() then calls ShowHint() to indicate this drop rectangle. -// "pane_window" is the window pointer of the pane being dragged, pt is -// the mouse position, in client coordinates -void wxAuiManager::DrawHintRect(wxWindow* pane_window, - const wxPoint& pt, - const wxPoint& offset) +void wxAuiManager::StartPaneDrag(wxWindow* pane_window, + const wxPoint& offset) +{ + wxAuiPaneInfo& pane = GetPane(pane_window); + if (!pane.IsOk()) + return; + + if (pane.IsToolbar()) + { + m_action = actionDragToolbarPane; + } + else + { + m_action = actionDragFloatingPane; + } + + m_action_window = pane_window; + m_action_offset = offset; + m_frame->CaptureMouse(); +} + + +// CalculateHintRect() calculates the drop hint rectangle. The method +// first calls DoDrop() to determine the exact position the pane would +// be at were if dropped. If the pane would indeed become docked at the +// specified drop point, the the rectangle hint will be returned in +// screen coordinates. Otherwise, an empty rectangle is returned. +// |pane_window| is the window pointer of the pane being dragged, |pt| is +// the mouse position, in client coordinates. |offset| describes the offset +// that the mouse is from the upper-left corner of the item being dragged + +wxRect wxAuiManager::CalculateHintRect(wxWindow* pane_window, + const wxPoint& pt, + const wxPoint& offset) { wxRect rect; @@ -3037,10 +3311,11 @@ void wxAuiManager::DrawHintRect(wxWindow* pane_window, wxAuiDockUIPartArray uiparts; wxAuiPaneInfo hint = GetPane(pane_window); hint.name = wxT("__HINT__"); + hint.PaneBorder(true); hint.Show(); if (!hint.IsOk()) - return; + return rect; CopyDocksAndPanes(docks, panes, m_docks, m_panes); @@ -3059,8 +3334,7 @@ void wxAuiManager::DrawHintRect(wxWindow* pane_window, // find out where the new pane would be if (!DoDrop(docks, panes, hint, pt, offset)) { - HideHint(); - return; + return rect; } panes.Add(hint); @@ -3088,13 +3362,39 @@ void wxAuiManager::DrawHintRect(wxWindow* pane_window, if (rect.IsEmpty()) { - HideHint(); - return; + return rect; } // actually show the hint rectangle on the screen m_frame->ClientToScreen(&rect.x, &rect.y); - ShowHint(rect); + + if ( m_frame->GetLayoutDirection() == wxLayout_RightToLeft ) + { + // Mirror rectangle in RTL mode + rect.x -= rect.GetWidth(); + } + + return rect; +} + +// DrawHintRect() calculates the hint rectangle by calling +// CalculateHintRect(). If there is a rectangle, it shows it +// by calling ShowHint(), otherwise it hides any hint +// rectangle currently shown +void wxAuiManager::DrawHintRect(wxWindow* pane_window, + const wxPoint& pt, + const wxPoint& offset) +{ + wxRect rect = CalculateHintRect(pane_window, pt, offset); + + if (rect.IsEmpty()) + { + HideHint(); + } + else + { + ShowHint(rect); + } } void wxAuiManager::OnFloatingPaneMoveStart(wxWindow* wnd) @@ -3103,10 +3403,8 @@ void wxAuiManager::OnFloatingPaneMoveStart(wxWindow* wnd) wxAuiPaneInfo& pane = GetPane(wnd); wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); -#if wxCHECK_VERSION(2,7,0) if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) pane.frame->SetTransparent(150); -#endif } void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir) @@ -3127,22 +3425,22 @@ void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir) pt.y = pos.y; // and some more pixels for the title bar pt.y -= 5; - } else - if (dir == wxWEST) + } + else if (dir == wxWEST) { // move to pane's left border wxPoint pos( 0,0 ); pos = wnd->ClientToScreen( pos ); pt.x = pos.x; - } else - if (dir == wxEAST) + } + else if (dir == wxEAST) { // move to pane's right border wxPoint pos( wnd->GetSize().x, 0 ); pos = wnd->ClientToScreen( pos ); pt.x = pos.x; - } else - if (dir == wxSOUTH) + } + else if (dir == wxSOUTH) { // move to pane's bottom border wxPoint pos( 0, wnd->GetSize().y ); @@ -3163,27 +3461,24 @@ void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir) // no hint for toolbar floating windows if (pane.IsToolbar() && m_action == actionDragFloatingPane) { - if (m_action == actionDragFloatingPane) - { - wxAuiDockInfoArray docks; - wxAuiPaneInfoArray panes; - wxAuiDockUIPartArray uiparts; - wxAuiPaneInfo hint = pane; + wxAuiDockInfoArray docks; + wxAuiPaneInfoArray panes; + wxAuiDockUIPartArray uiparts; + wxAuiPaneInfo hint = pane; - CopyDocksAndPanes(docks, panes, m_docks, m_panes); + CopyDocksAndPanes(docks, panes, m_docks, m_panes); - // find out where the new pane would be - if (!DoDrop(docks, panes, hint, client_pt)) - return; - if (hint.IsFloating()) - return; + // find out where the new pane would be + if (!DoDrop(docks, panes, hint, client_pt)) + return; + if (hint.IsFloating()) + return; - pane = hint; - m_action = actionDragToolbarPane; - m_action_window = pane.window; + pane = hint; + m_action = actionDragToolbarPane; + m_action_window = pane.window; - Update(); - } + Update(); return; } @@ -3191,7 +3486,7 @@ void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir) // if a key modifier is pressed while dragging the frame, // don't dock the window - if (wxGetKeyState(WXK_CONTROL) || wxGetKeyState(WXK_ALT)) + if (!CanDockPanel(pane)) { HideHint(); return; @@ -3230,22 +3525,22 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir) pt.y = pos.y; // and some more pixels for the title bar pt.y -= 10; - } else - if (dir == wxWEST) + } + else if (dir == wxWEST) { // move to pane's left border wxPoint pos( 0,0 ); pos = wnd->ClientToScreen( pos ); pt.x = pos.x; - } else - if (dir == wxEAST) + } + else if (dir == wxEAST) { // move to pane's right border wxPoint pos( wnd->GetSize().x, 0 ); pos = wnd->ClientToScreen( pos ); pt.x = pos.x; - } else - if (dir == wxSOUTH) + } + else if (dir == wxSOUTH) { // move to pane's bottom border wxPoint pos( 0, wnd->GetSize().y ); @@ -3266,7 +3561,7 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir) // if a key modifier is pressed while dragging the frame, // don't dock the window - if (!wxGetKeyState(WXK_CONTROL) && !wxGetKeyState(WXK_ALT)) + if (CanDockPanel(pane)) { // do the drop calculation DoDrop(m_docks, m_panes, pane, client_pt, action_offset); @@ -3278,11 +3573,11 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir) { pane.floating_pos = pane.frame->GetPosition(); -#if wxCHECK_VERSION(2,7,0) if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG) pane.frame->SetTransparent(255); -#endif - } else if(m_has_maximized) { + } + else if (m_has_maximized) + { RestoreMaximizedPane(); } @@ -3309,7 +3604,7 @@ void wxAuiManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt) // fire pane close event - wxAuiManagerEvent e(wxEVT_AUI_PANECLOSE); + wxAuiManagerEvent e(wxEVT_AUI_PANE_CLOSE); e.SetPane(&pane); e.SetCanVeto(evt.CanVeto()); ProcessMgrEvent(e); @@ -3319,9 +3614,17 @@ void wxAuiManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt) evt.Veto(); return; } - else + else { - ClosePane(pane); + // close the pane, but check that it + // still exists in our pane array first + // (the event handler above might have removed it) + + wxAuiPaneInfo& check = GetPane(wnd); + if (check.IsOk()) + { + ClosePane(pane); + } } } @@ -3329,11 +3632,8 @@ void wxAuiManager::OnFloatingPaneClosed(wxWindow* wnd, wxCloseEvent& evt) void wxAuiManager::OnFloatingPaneActivated(wxWindow* wnd) { - if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) + if ((GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) && GetPane(wnd).IsOk()) { - // try to find the pane - wxASSERT_MSG(GetPane(wnd).IsOk(), wxT("Pane window not found")); - SetActivePane(m_panes, wnd); Repaint(); } @@ -3345,6 +3645,10 @@ void wxAuiManager::OnFloatingPaneActivated(wxWindow* wnd) void wxAuiManager::OnRender(wxAuiManagerEvent& evt) { + // if the frame is about to be deleted, don't bother + if (!m_frame || wxPendingDelete.Member(m_frame)) + return; + wxDC* dc = evt.GetDC(); #ifdef __WXMAC__ @@ -3356,8 +3660,8 @@ void wxAuiManager::OnRender(wxAuiManagerEvent& evt) { wxAuiDockUIPart& part = m_uiparts.Item(i); - // don't draw hidden pane items - if (part.sizer_item && !part.sizer_item->IsShown()) + // don't draw hidden pane items or items that aren't windows + if (part.sizer_item && ((!part.sizer_item->IsWindow() && !part.sizer_item->IsSpacer() && !part.sizer_item->IsSizer()) || !part.sizer_item->IsShown())) continue; switch (part.type) @@ -3396,6 +3700,7 @@ void wxAuiManager::OnRender(wxAuiManagerEvent& evt) void wxAuiManager::Render(wxDC* dc) { wxAuiManagerEvent e(wxEVT_AUI_RENDER); + e.SetManager(this); e.SetDC(dc); ProcessMgrEvent(e); } @@ -3458,10 +3763,42 @@ void wxAuiManager::OnSize(wxSizeEvent& event) { DoFrameLayout(); Repaint(); + +#if wxUSE_MDI + if (m_frame->IsKindOf(CLASSINFO(wxMDIParentFrame))) + { + // for MDI parent frames, this event must not + // be "skipped". In other words, the parent frame + // must not be allowed to resize the client window + // after we are finished processing sizing changes + return; + } +#endif } event.Skip(); } +void wxAuiManager::OnFindManager(wxAuiManagerEvent& evt) +{ + // get the window we are managing, if none, return NULL + wxWindow* window = GetManagedWindow(); + if (!window) + { + evt.SetManager(NULL); + return; + } + + // if we are managing a child frame, get the 'real' manager + if (window->IsKindOf(CLASSINFO(wxAuiFloatingFrame))) + { + wxAuiFloatingFrame* float_frame = static_cast(window); + evt.SetManager(float_frame->GetOwnerManager()); + return; + } + + // return pointer to ourself + evt.SetManager(this); +} void wxAuiManager::OnSetCursor(wxSetCursorEvent& event) { @@ -3487,10 +3824,10 @@ void wxAuiManager::OnSetCursor(wxSetCursorEvent& event) if (part->orientation == wxVERTICAL) cursor = wxCursor(wxCURSOR_SIZEWE); - else + else cursor = wxCursor(wxCURSOR_SIZENS); } - else if (part->type == wxAuiDockUIPart::typeGripper) + else if (part->type == wxAuiDockUIPart::typeGripper) { cursor = wxCursor(wxCURSOR_SIZING); } @@ -3502,9 +3839,11 @@ void wxAuiManager::OnSetCursor(wxSetCursorEvent& event) void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart* button_ui_part, - const wxMouseEvent& event) + const wxMouseEvent& event) { wxAuiDockUIPart* hit_test = HitTest(event.GetX(), event.GetY()); + if (!hit_test || !button_ui_part) + return; int state = wxAUI_BUTTON_STATE_NORMAL; @@ -3512,10 +3851,10 @@ void wxAuiManager::UpdateButtonOnScreen(wxAuiDockUIPart* button_ui_part, { if (event.LeftDown()) state = wxAUI_BUTTON_STATE_PRESSED; - else + else state = wxAUI_BUTTON_STATE_HOVER; } - else + else { if (event.LeftDown()) state = wxAUI_BUTTON_STATE_HOVER; @@ -3545,12 +3884,13 @@ void wxAuiManager::OnLeftDown(wxMouseEvent& event) wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY()); if (part) { - if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) - return; - if (part->type == wxAuiDockUIPart::typeDockSizer || part->type == wxAuiDockUIPart::typePaneSizer) { + // Removing this restriction so that a centre pane can be resized + //if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) + // return; + // a dock may not be resized if it has a single // pane which is not resizable if (part->type == wxAuiDockUIPart::typeDockSizer && part->dock && @@ -3570,7 +3910,7 @@ void wxAuiManager::OnLeftDown(wxMouseEvent& event) event.m_y - part->rect.y); m_frame->CaptureMouse(); } - else if (part->type == wxAuiDockUIPart::typePaneButton) + else if (part->type == wxAuiDockUIPart::typePaneButton) { m_action = actionClickButton; m_action_part = part; @@ -3579,9 +3919,29 @@ void wxAuiManager::OnLeftDown(wxMouseEvent& event) UpdateButtonOnScreen(part, event); } - else if (part->type == wxAuiDockUIPart::typeCaption || + else if (part->type == wxAuiDockUIPart::typeCaption || part->type == wxAuiDockUIPart::typeGripper) { + // if we are managing a wxAuiFloatingFrame window, then + // we are an embedded wxAuiManager inside the wxAuiFloatingFrame. + // We want to initiate a toolbar drag in our owner manager + wxWindow* managed_wnd = GetManagedWindow(); + + if (part->pane && + part->pane->window && + managed_wnd && + managed_wnd->IsKindOf(CLASSINFO(wxAuiFloatingFrame))) + { + wxAuiFloatingFrame* floating_frame = (wxAuiFloatingFrame*)managed_wnd; + wxAuiManager* owner_mgr = floating_frame->GetOwnerManager(); + owner_mgr->StartPaneDrag(part->pane->window, + wxPoint(event.m_x - part->rect.x, + event.m_y - part->rect.y)); + return; + } + + + if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) { // set the caption as active @@ -3589,6 +3949,9 @@ void wxAuiManager::OnLeftDown(wxMouseEvent& event) Repaint(); } + if (part->dock && part->dock->dock_direction == wxAUI_DOCK_CENTER) + return; + m_action = actionClickCaption; m_action_part = part; m_action_start = wxPoint(event.m_x, event.m_y); @@ -3653,8 +4016,8 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) Update(); Repaint(NULL); } - else if (m_action_part && - m_action_part->type == wxAuiDockUIPart::typePaneSizer) + else if (m_action_part && + m_action_part->type == wxAuiDockUIPart::typePaneSizer) { wxAuiDockInfo& dock = *m_action_part->dock; wxAuiPaneInfo& pane = *m_action_part->pane; @@ -3663,9 +4026,9 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) int dock_pixels = 0; int new_pixsize = 0; - int caption_size = m_art->GetMetric(wxAUI_ART_CAPTION_SIZE); - int pane_border_size = m_art->GetMetric(wxAUI_ART_PANE_BORDER_SIZE); - int sash_size = m_art->GetMetric(wxAUI_ART_SASH_SIZE); + int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE); + int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); + int sash_size = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE); wxPoint new_pos(event.m_x - m_action_offset.x, event.m_y - m_action_offset.y); @@ -3679,13 +4042,13 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) // this will help us recalculate the pane's proportion if (dock.IsHorizontal()) new_pixsize = new_pos.x - pane_part->rect.x; - else + else new_pixsize = new_pos.y - pane_part->rect.y; // determine the size of the dock, based on orientation if (dock.IsHorizontal()) dock_pixels = dock.rect.GetWidth(); - else + else dock_pixels = dock.rect.GetHeight(); // determine the total proportion of all resizable panes, @@ -3712,10 +4075,10 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) { if (dock.IsHorizontal()) dock_pixels -= p.best_size.x; - else + else dock_pixels -= p.best_size.y; } - else + else { total_proportion += p.dock_proportion; } @@ -3772,7 +4135,7 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) if (pane.HasCaption()) min_size += caption_size; } - else + else { min_size += pane.min_size.x; } @@ -3814,7 +4177,8 @@ void wxAuiManager::OnLeftUp(wxMouseEvent& event) if (m_action_part == HitTest(event.GetX(), event.GetY())) { // fire button-click event - wxAuiManagerEvent e(wxEVT_AUI_PANEBUTTON); + wxAuiManagerEvent e(wxEVT_AUI_PANE_BUTTON); + e.SetManager(this); e.SetPane(m_action_part->pane); e.SetButton(m_action_part->button->button_id); ProcessMgrEvent(e); @@ -3883,7 +4247,7 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) wxPoint pos = m_action_part->rect.GetPosition(); if (m_action_part->orientation == wxHORIZONTAL) pos.y = wxMax(0, event.m_y - m_action_offset.y); - else + else pos.x = wxMax(0, event.m_x - m_action_offset.x); wxRect rect(m_frame->ClientToScreen(pos), @@ -3921,9 +4285,8 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) pt.y - m_action_offset.y); // float the window - if(pane_info->IsMaximized()) { + if (pane_info->IsMaximized()) RestorePane(*pane_info); - } pane_info->Float(); Update(); @@ -3939,7 +4302,7 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) m_action_offset.x = 30; } } - else + else { m_action = actionDragToolbarPane; m_action_window = pane_info->window; @@ -3948,7 +4311,8 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) } else if (m_action == actionDragFloatingPane) { - if(m_action_window) { + if (m_action_window) + { wxPoint pt = m_frame->ClientToScreen(event.GetPosition()); m_action_window->Move(pt.x - m_action_offset.x, pt.y - m_action_offset.y); @@ -4002,22 +4366,22 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) UpdateButtonOnScreen(m_hover_button, event); Repaint(); } - + // mouse is over a button, so repaint the // button in hover mode UpdateButtonOnScreen(part, event); m_hover_button = part; - + } } - else + else { if (m_hover_button) { m_hover_button = NULL; Repaint(); } - else + else { event.Skip(); } @@ -4041,7 +4405,8 @@ void wxAuiManager::OnChildFocus(wxChildFocusEvent& event) // active panes are allowed by the owner) if (GetFlags() & wxAUI_MGR_ALLOW_ACTIVE_PANE) { - if (GetPane(event.GetWindow()).IsOk()) + wxAuiPaneInfo& pane = GetPane(event.GetWindow()); + if (pane.IsOk() && (pane.state & wxAuiPaneInfo::optionActive) == 0) { SetActivePane(m_panes, event.GetWindow()); m_frame->Refresh(); @@ -4063,20 +4428,31 @@ void wxAuiManager::OnPaneButton(wxAuiManagerEvent& evt) if (evt.button == wxAUI_BUTTON_CLOSE) { // fire pane close event - wxAuiManagerEvent e(wxEVT_AUI_PANECLOSE); + wxAuiManagerEvent e(wxEVT_AUI_PANE_CLOSE); + e.SetManager(this); e.SetPane(evt.pane); ProcessMgrEvent(e); if (!e.GetVeto()) { - ClosePane(pane); + // close the pane, but check that it + // still exists in our pane array first + // (the event handler above might have removed it) + + wxAuiPaneInfo& check = GetPane(pane.window); + if (check.IsOk()) + { + ClosePane(pane); + } + Update(); } } else if (evt.button == wxAUI_BUTTON_MAXIMIZE_RESTORE && !pane.IsMaximized()) { // fire pane close event - wxAuiManagerEvent e(wxEVT_AUI_PANEMAXIMIZE); + wxAuiManagerEvent e(wxEVT_AUI_PANE_MAXIMIZE); + e.SetManager(this); e.SetPane(evt.pane); ProcessMgrEvent(e); @@ -4089,7 +4465,8 @@ void wxAuiManager::OnPaneButton(wxAuiManagerEvent& evt) else if (evt.button == wxAUI_BUTTON_MAXIMIZE_RESTORE && pane.IsMaximized()) { // fire pane close event - wxAuiManagerEvent e(wxEVT_AUI_PANERESTORE); + wxAuiManagerEvent e(wxEVT_AUI_PANE_RESTORE); + e.SetManager(this); e.SetPane(evt.pane); ProcessMgrEvent(e); @@ -4099,7 +4476,7 @@ void wxAuiManager::OnPaneButton(wxAuiManagerEvent& evt) Update(); } } - else if (evt.button == wxAUI_BUTTON_PIN) + else if (evt.button == wxAUI_BUTTON_PIN) { if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) && pane.IsFloatable())