X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/de5d5cc0fac7d4618d179132e06e579b6cc416a8..0534259ab803b0edd8692e966947b202cd9e10c0:/src/aui/framemanager.cpp diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index ff8ead25d8..940ecfdad4 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -40,6 +40,7 @@ #include "wx/dcscreen.h" #include "wx/toolbar.h" #include "wx/image.h" + #include "wx/statusbr.h" #endif WX_CHECK_BUILD_OPTIONS("wxAUI") @@ -54,12 +55,12 @@ WX_DEFINE_OBJARRAY(wxAuiPaneInfoArray) wxAuiPaneInfo wxAuiNullPaneInfo; wxAuiDockInfo wxAuiNullDockInfo; -wxDEFINE_EVENT( wxEVT_AUI_PANE_BUTTON, wxAuiManagerEvent ) -wxDEFINE_EVENT( wxEVT_AUI_PANE_CLOSE, wxAuiManagerEvent ) -wxDEFINE_EVENT( wxEVT_AUI_PANE_MAXIMIZE, wxAuiManagerEvent ) -wxDEFINE_EVENT( wxEVT_AUI_PANE_RESTORE, wxAuiManagerEvent ) -wxDEFINE_EVENT( wxEVT_AUI_RENDER, wxAuiManagerEvent ) -wxDEFINE_EVENT( wxEVT_AUI_FIND_MANAGER, wxAuiManagerEvent ) +wxDEFINE_EVENT( wxEVT_AUI_PANE_BUTTON, wxAuiManagerEvent ); +wxDEFINE_EVENT( wxEVT_AUI_PANE_CLOSE, wxAuiManagerEvent ); +wxDEFINE_EVENT( wxEVT_AUI_PANE_MAXIMIZE, wxAuiManagerEvent ); +wxDEFINE_EVENT( wxEVT_AUI_PANE_RESTORE, wxAuiManagerEvent ); +wxDEFINE_EVENT( wxEVT_AUI_RENDER, wxAuiManagerEvent ); +wxDEFINE_EVENT( wxEVT_AUI_FIND_MANAGER, wxAuiManagerEvent ); #ifdef __WXMAC__ // a few defines to avoid nameclashes @@ -558,6 +559,136 @@ static int PaneSortFunc(wxAuiPaneInfo** p1, wxAuiPaneInfo** p2) } + + +// this utility class implements a proportional sizer +// as it existed in wxWidgets 2.8 and before. + +class wxAuiProportionalBoxSizer : public wxBoxSizer +{ +public: + wxAuiProportionalBoxSizer(int orientation) : wxBoxSizer(orientation) { } + + void RecalcSizes() + { + if (m_children.GetCount() == 0) + return; + + int fixed_height = 0; + int fixed_width = 0; + int stretchable = 0; + wxSizerItemList::compatibility_iterator node; + + // find fixed width and height, as well + // as the total stretchable proportions + node = m_children.GetFirst(); + while (node) + { + wxSizerItem *item = node->GetData(); + + if (item->IsShown()) + { + stretchable += item->GetProportion(); + + wxSize size(item->GetMinSizeWithBorder()); + if (item->GetProportion() == 0) + { + if (m_orient == wxVERTICAL) + { + fixed_height += size.y; + fixed_width = wxMax(fixed_width, size.x); + } + else + { + fixed_width += size.x; + fixed_height = wxMax(fixed_height, size.y); + } + } + } + + node = node->GetNext(); + } + + + // delta specifies the total amount to be allocated to stretch spaces + int delta = 0; + if (stretchable) + { + if (m_orient == wxHORIZONTAL) + delta = m_size.x - fixed_width; + else + delta = m_size.y - fixed_height; + } + + // go through each item and assign sizes + wxPoint pt(m_position); + node = m_children.GetFirst(); + while (node) + { + wxSizerItem* item = node->GetData(); + + if (item->IsShown()) + { + wxSize size(item->GetMinSizeWithBorder()); + + if (m_orient == wxVERTICAL) + { + wxCoord height = size.y; + if (item->GetProportion()) + { + height = (delta * item->GetProportion()) / stretchable; + delta -= height; + stretchable -= item->GetProportion(); + } + + wxPoint child_pos(pt); + wxSize child_size(size.x, height); + + if (item->GetFlag() & (wxEXPAND | wxSHAPED)) + child_size.x = m_size.x; + else if (item->GetFlag() & wxALIGN_RIGHT) + child_pos.x += m_size.x - size.x; + else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL)) + child_pos.x += (m_size.x - size.x) / 2; + + item->SetDimension(child_pos, child_size); + + pt.y += height; + } + else + { + wxCoord width = size.x; + if (item->GetProportion()) + { + width = (delta * item->GetProportion()) / stretchable; + delta -= width; + stretchable -= item->GetProportion(); + } + + wxPoint child_pos(pt); + wxSize child_size(width, size.y); + + if (item->GetFlag() & (wxEXPAND | wxSHAPED)) + child_size.y = m_size.y; + else if (item->GetFlag() & wxALIGN_BOTTOM) + child_pos.y += m_size.y - size.y; + else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL)) + child_pos.y += (m_size.y - size.y) / 2; + + item->SetDimension(child_pos, child_size); + + pt.x += width; + } + } + + node = node->GetNext(); + } + } +}; + + + + // -- wxAuiManager class implementation -- @@ -743,6 +874,7 @@ bool wxAuiManager_HasLiveResize(wxAuiManager& manager) // With Core Graphics on Mac, it's not possible to show sash feedback, // so we'll always use live update instead. #if defined(__WXMAC__) + wxUnusedVar(manager); return true; #else return (manager.GetFlags() & wxAUI_MGR_LIVE_RESIZE) == wxAUI_MGR_LIVE_RESIZE; @@ -1048,21 +1180,15 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) { pinfo.best_size = pinfo.window->GetClientSize(); +#if wxUSE_TOOLBAR if (pinfo.window->IsKindOf(CLASSINFO(wxToolBar))) { // GetClientSize() doesn't get the best size for // a toolbar under some newer versions of wxWidgets, // so use GetBestSize() pinfo.best_size = pinfo.window->GetBestSize(); - - // for some reason, wxToolBar::GetBestSize() is returning - // a size that is a pixel shy of the correct amount. - // I believe this to be the correct action, until - // wxToolBar::GetBestSize() is fixed. Is this assumption - // correct? - // commented out by JACS 2007-9-08 after having added a pixel in wxMSW's wxToolBar::DoGetBestSize() - // pinfo.best_size.y++; } +#endif // wxUSE_TOOLBAR if (pinfo.min_size != wxDefaultSize) { @@ -1281,7 +1407,7 @@ 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.IsFloating()) { p.Restore(); @@ -1712,8 +1838,8 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont, // value that the pane will receive int pane_proportion = pane.dock_proportion; - wxBoxSizer* horz_pane_sizer = new wxBoxSizer(wxHORIZONTAL); - wxBoxSizer* vert_pane_sizer = new wxBoxSizer(wxVERTICAL); + wxAuiProportionalBoxSizer* horz_pane_sizer = new wxAuiProportionalBoxSizer(wxHORIZONTAL); + wxAuiProportionalBoxSizer* vert_pane_sizer = new wxAuiProportionalBoxSizer(wxVERTICAL); if (pane.HasGripper()) { @@ -1735,7 +1861,7 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont, if (pane.HasCaption()) { // create the caption sizer - wxBoxSizer* caption_sizer = new wxBoxSizer(wxHORIZONTAL); + wxAuiProportionalBoxSizer* caption_sizer = new wxAuiProportionalBoxSizer(wxHORIZONTAL); sizer_item = caption_sizer->Add(1, caption_size, 1, wxEXPAND); @@ -1884,7 +2010,7 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont, } // create the sizer for the dock - wxSizer* dock_sizer = new wxBoxSizer(orientation); + wxSizer* dock_sizer = new wxAuiProportionalBoxSizer(orientation); // add each pane to the dock bool has_maximized_pane = false; @@ -2017,7 +2143,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, wxAuiDockUIPartArray& uiparts, bool spacer_only) { - wxBoxSizer* container = new wxBoxSizer(wxVERTICAL); + wxAuiProportionalBoxSizer* container = new wxAuiProportionalBoxSizer(wxVERTICAL); int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE); int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE); @@ -2300,7 +2426,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // create a container which will hold this layer's // docks (top, bottom, left, right) - cont = new wxBoxSizer(wxVERTICAL); + cont = new wxAuiProportionalBoxSizer(wxVERTICAL); // find any top docks in this layer @@ -2315,7 +2441,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, // fill out the middle layer (which consists // of left docks, content area and right docks) - middle = new wxBoxSizer(wxHORIZONTAL); + middle = new wxAuiProportionalBoxSizer(wxHORIZONTAL); // find any left docks in this layer FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr); @@ -2384,7 +2510,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes, { // no sizer available, because there are no docks, // therefore we will create a simple background area - cont = new wxBoxSizer(wxVERTICAL); + cont = new wxAuiProportionalBoxSizer(wxVERTICAL); wxSizerItem* sizer_item = cont->Add(1,1, 1, wxEXPAND); wxAuiDockUIPart part; part.type = wxAuiDockUIPart::typeBackground; @@ -2895,7 +3021,8 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, // toolbars may only be moved in and to fixed-pane docks, // otherwise we will try to float the pane. Also, the pane // should float if being dragged over center pane windows - if (!part->dock->fixed || part->dock->dock_direction == wxAUI_DOCK_CENTER) + if (!part->dock->fixed || part->dock->dock_direction == wxAUI_DOCK_CENTER || + pt.x >= cli_size.x || pt.x <= 0 || pt.y >= cli_size.y || pt.y <= 0) { if (m_last_rect.IsEmpty() || m_last_rect.Contains(pt.x, pt.y )) { @@ -2903,13 +3030,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks, } else { - if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) && - (drop.IsFloatable() || - (part->dock->dock_direction != wxAUI_DOCK_CENTER && - part->dock->dock_direction != wxAUI_DOCK_NONE))) + if ((m_flags & wxAUI_MGR_ALLOW_FLOATING) && drop.IsFloatable()) { - if (drop.IsFloatable()) - drop.Float(); + drop.Float(); } m_skipping = false; @@ -3476,6 +3599,9 @@ void wxAuiManager::OnFloatingPaneMoving(wxWindow* wnd, wxDirection dir) wxAuiPaneInfo& pane = GetPane(wnd); wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); + if(!pane.frame) + return; + wxPoint pt = ::wxGetMousePosition(); #if 0 @@ -3576,6 +3702,9 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir) wxAuiPaneInfo& pane = GetPane(wnd); wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found")); + if(!pane.frame) + return; + wxPoint pt = ::wxGetMousePosition(); #if 0 @@ -4046,26 +4175,84 @@ bool wxAuiManager::DoEndResizeAction(wxMouseEvent& event) // resize the dock or the pane if (m_action_part && m_action_part->type==wxAuiDockUIPart::typeDockSizer) { + // first, we must calculate the maximum size the dock may be + int sash_size = m_art->GetMetric(wxAUI_DOCKART_SASH_SIZE); + + int used_width = 0, used_height = 0; + + wxSize client_size = m_frame->GetClientSize(); + + size_t dock_i, dock_count = m_docks.GetCount(); + for (dock_i = 0; dock_i < dock_count; ++dock_i) + { + wxAuiDockInfo& dock = m_docks.Item(dock_i); + if (dock.dock_direction == wxAUI_DOCK_TOP || + dock.dock_direction == wxAUI_DOCK_BOTTOM) + { + used_height += dock.size; + } + if (dock.dock_direction == wxAUI_DOCK_LEFT || + dock.dock_direction == wxAUI_DOCK_RIGHT) + { + used_width += dock.size; + } + if (dock.resizable) + used_width += sash_size; + } + + + int available_width = client_size.GetWidth() - used_width; + int available_height = client_size.GetHeight() - used_height; + + +#if wxUSE_STATUSBAR + // if there's a status control, the available + // height decreases accordingly + if (m_frame && m_frame->IsKindOf(CLASSINFO(wxFrame))) + { + wxFrame* frame = static_cast(m_frame); + wxStatusBar* status = frame->GetStatusBar(); + if (status) + { + wxSize status_client_size = status->GetClientSize(); + available_height -= status_client_size.GetHeight(); + } + } +#endif + wxRect& rect = m_action_part->dock->rect; wxPoint new_pos(event.m_x - m_action_offset.x, event.m_y - m_action_offset.y); + int new_size, old_size = m_action_part->dock->size; switch (m_action_part->dock->dock_direction) { case wxAUI_DOCK_LEFT: - m_action_part->dock->size = new_pos.x - rect.x; + new_size = new_pos.x - rect.x; + if (new_size-old_size > available_width) + new_size = old_size+available_width; + m_action_part->dock->size = new_size; break; case wxAUI_DOCK_TOP: - m_action_part->dock->size = new_pos.y - rect.y; + new_size = new_pos.y - rect.y; + if (new_size-old_size > available_height) + new_size = old_size+available_height; + m_action_part->dock->size = new_size; break; case wxAUI_DOCK_RIGHT: - m_action_part->dock->size = rect.x + rect.width - - new_pos.x - m_action_part->rect.GetWidth(); + new_size = rect.x + rect.width - new_pos.x - + m_action_part->rect.GetWidth(); + if (new_size-old_size > available_width) + new_size = old_size+available_width; + m_action_part->dock->size = new_size; break; case wxAUI_DOCK_BOTTOM: - m_action_part->dock->size = rect.y + rect.height - + new_size = rect.y + rect.height - new_pos.y - m_action_part->rect.GetHeight(); + if (new_size-old_size > available_height) + new_size = old_size+available_height; + m_action_part->dock->size = new_size; break; } @@ -4140,6 +4327,11 @@ bool wxAuiManager::DoEndResizeAction(wxMouseEvent& event) } } + // new size can never be more than the number of dock pixels + if (new_pixsize > dock_pixels) + new_pixsize = dock_pixels; + + // find a pane in our dock to 'steal' space from or to 'give' // space to -- this is essentially what is done when a pane is // resized; the pane should usually be the first non-fixed pane @@ -4214,10 +4406,26 @@ bool wxAuiManager::DoEndResizeAction(wxMouseEvent& event) int prop_diff = new_proportion - pane.dock_proportion; // borrow the space from our neighbor pane to the - // right or bottom (depending on orientation) - dock.panes.Item(borrow_pane)->dock_proportion -= prop_diff; + // right or bottom (depending on orientation); + // also make sure we don't make the neighbor too small + int prop_borrow = dock.panes.Item(borrow_pane)->dock_proportion; + + if (prop_borrow - prop_diff < 0) + { + // borrowing from other pane would make it too small, + // so cancel the resize operation + prop_borrow = min_proportion; + } + else + { + prop_borrow -= prop_diff; + } + + + dock.panes.Item(borrow_pane)->dock_proportion = prop_borrow; pane.dock_proportion = new_proportion; + // repaint Update(); Repaint(NULL); @@ -4355,9 +4563,19 @@ void wxAuiManager::OnMotion(wxMouseEvent& event) wxScreenDC dc; if (!m_action_hintrect.IsEmpty()) + { + // remove old resize hint DrawResizeHint(dc, m_action_hintrect); - DrawResizeHint(dc, rect); - m_action_hintrect = rect; + m_action_hintrect = wxRect(); + } + + // draw new resize hint, if it's inside the managed frame + wxRect frame_screen_rect = m_frame->GetScreenRect(); + if (frame_screen_rect.Contains(rect)) + { + DrawResizeHint(dc, rect); + m_action_hintrect = rect; + } } } }