Firstly, there is a problem maintain size across dock/undock. This is because (on GTK anyway, haven't checked MSW / Mac), no wxEVT_SIZE is sent on a resize of a floating pane unless m_hasScroll is set (see src/gtk/window.cpp and look for the gtk callback that handles window sizing). This means that wxFloatingPane::OnSize is NEVER called, because it doesn't have the possibilty of having scrollbars. In turn, this means pane.size is never updated, which means when a floating pane is resized, docked, then undocked, its size information is lost. This is pretty easily verifiable in the sample application. Therefore, I simulate an OnSize event when the window at the start and end of a move (so the docking code gets the right size), and at one other point which I now forget.
The next issue is that a window which has no defined minsize (i.e. for which no minsize has specificly been set by the user in paneinfo) does not respect the minimum size of that window when floated. So if you take a panel with a sizer in, with a minimum size (due to the sizer), then add it to wxAUI with float() set to true, the floating pane has the minimum size set wrong. I can't EXPLICITLY set minsize, because I want the minimum size to continue to depend on what's in the sizer. have added a line to fix this.
There is some curious code a little further down which tests IsFullySpecified() on the paneinfo minsize. I can't work out for the life of me what this is meant to do. It's almost as if the check is back to front (i.e. it should be checking for !IsFullySpecified() ), but changing it around doesn't help, because by the time it gets to that bit of code, Update/Layout has already trampled on the sizer's minimum size (see below for one reason why).
The above alone is not, however, sufficient to get minimum sizes to work without further changes. This is because SetPaneWindow (having fixed the frame minimum size) calls Update() (this is all before pane.frame is set (things break badly if p.frame is set before). Update() in turn calls LayoutAddPane(), which does a SetItemMinSize on the sizer. This changes the minsize of the window (not the frame) to (1,1). If the frame is then docked and undocked, when the new frame is created, it looks back at the windows minimum size, which has now been lost. I do not think there is a good reason why LayoutAddPane() should be setting the minimum size of a window. Surely if it's set (and not wxDefaultSize), it's set for a reason? (IE because we don't want it smaller than that). I have thus commented out this line, and left the call in below which does SetItemMinSize() if the user specified a minsize in the paneinfo, which seems fair enough.
Whilst I'm pretty positive the code to maintain size across dock/undock is right, I am not so sure about the code to maintain minsize (both to respect it, and to maintain it across dock/undock). As far as I can tell it has no ill effects, but I don't quite understand how the original code was meant to work (especially the IsFullySpecified() bit in SetPaneWindow).
Patch follows:
- Code: Select all
Index: src/manager.cpp
===================================================================
--- src/manager.cpp (revision 849)
+++ src/manager.cpp (working copy)
@@ -613,6 +613,9 @@
PaneBorder(false).
Layer(0).Row(0).Position(0);
+ // Carry over the minimum size
+ SetMinSize(pane.window->GetMinSize());
+
m_mgr.AddPane(m_pane_window, contained_pane);
m_mgr.Update();
@@ -651,10 +654,17 @@
}
}
+ void EnsureSizeRecorded()
+ {
+ // This is a work around for a wxGTK problem - see OnSize
+ m_owner_mgr->OnFloatingPaneResized(m_pane_window, GetSize());
+ }
+
private:
void OnSize(wxSizeEvent& event)
{
+ // This never gets called on wxGTK (2.6.3 and below) because m_hasScrolling is false
m_owner_mgr->OnFloatingPaneResized(m_pane_window, event.GetSize());
}
@@ -662,6 +672,8 @@
{
static wxList s_closing;
+ EnsureSizeRecorded();
+
if (!s_closing.Member(this))
{
s_closing.Append(this);
@@ -727,6 +739,8 @@
void OnMoveStart()
{
+ // Check we have a record of our own size for dock hints
+ EnsureSizeRecorded();
// notify the owner manager that the pane has started to move
m_owner_mgr->OnFloatingPaneMoveStart(m_pane_window);
}
@@ -739,6 +753,8 @@
void OnMoveFinished()
{
+ // Check we have a record of our own size for docking
+ EnsureSizeRecorded();
// notify the owner manager that the pane has finished moving
m_owner_mgr->OnFloatingPaneMoved(m_pane_window);
}
@@ -788,8 +804,11 @@
wxFrameManager m_mgr;
DECLARE_EVENT_TABLE()
+ DECLARE_CLASS(wxFloatingPaneBaseClass)
};
+IMPLEMENT_CLASS( wxFloatingPane, wxFloatingPaneBaseClass )
+
BEGIN_EVENT_TABLE(wxFloatingPane, wxFloatingPaneBaseClass)
EVT_SIZE(wxFloatingPane::OnSize)
EVT_MOVE(wxFloatingPane::OnMoveEvent)
@@ -1992,7 +2011,8 @@
else
{
sizer_item = vert_pane_sizer->Add(pane.window, 1, wxEXPAND);
- vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
+ // Don't do this because it breaks the pane size in floating windows
+ // vert_pane_sizer->SetItemMinSize(pane.window, 1, 1);
}
part.type = wxDockUIPart::typePane;
@@ -2587,7 +2607,12 @@
{
// because the pane is no longer in a floating, we need to
// reparent it to m_frame and destroy the floating frame
-
+
+ // First ensure the size is recorded in case the last thing was
+ // a resize before a dock was done via a method other than a drag
+ if (p.frame->IsKindOf(CLASSINFO(wxFloatingPane)))
+ ((wxFloatingPane *)(p.frame))->EnsureSizeRecorded();
+
// reduce flicker
p.window->SetSize(1,1);
p.frame->Show(false);