]> git.saurik.com Git - wxWidgets.git/blobdiff - src/aui/framemanager.cpp
Implement SetShape() for wxPopupWindow in wxGTK.
[wxWidgets.git] / src / aui / framemanager.cpp
index 940ecfdad41ec2dab8806687ab1783e586c493ee..bdb37e182c35d1fadec69391a3daf478d1d5a7af 100644 (file)
@@ -223,6 +223,7 @@ END_EVENT_TABLE()
   // __WXGTK20__
 
 #include <gtk/gtk.h>
+#include "wx/gtk/private/gtk2-compat.h"
 
 static void
 gtk_pseudo_window_realized_callback( GtkWidget *m_widget, void *WXUNUSED(win) )
@@ -237,7 +238,7 @@ gtk_pseudo_window_realized_callback( GtkWidget *m_widget, void *WXUNUSED(win) )
                     if ((j*16+8)<amount)
                         region.Union(0, y, disp.x, 1);
                 }
-        gdk_window_shape_combine_region(m_widget->window, region.GetRegion(), 0, 0);
+        gdk_window_shape_combine_region(gtk_widget_get_window(m_widget), region.GetRegion(), 0, 0);
 }
 
 
@@ -277,6 +278,16 @@ public:
         return true;
     }
 
+protected:
+    virtual void DoSetSizeHints( int minW, int minH,
+                                 int maxW, int maxH,
+                                 int incW, int incH)
+    {
+        // the real wxFrame method doesn't work for us because we're not really
+        // a top level window so skip it
+        wxWindow::DoSetSizeHints(minW, minH, maxW, maxH, incW, incH);
+    }
+
 private:
     DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame)
 };
@@ -559,135 +570,14 @@ 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
+bool wxAuiPaneInfo::IsValid() const
 {
-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();
-        }
-    }
-};
-
-
-
+    // Should this RTTI and function call be rewritten as
+    // sending a new event type to allow other window types
+    // to check the pane settings?
+    wxAuiToolBar* toolbar = wxDynamicCast(window, wxAuiToolBar);
+    return !toolbar || toolbar->IsPaneValid(*this);
+}
 
 // -- wxAuiManager class implementation --
 
@@ -706,7 +596,6 @@ BEGIN_EVENT_TABLE(wxAuiManager, wxEvtHandler)
     EVT_MOUSE_CAPTURE_LOST(wxAuiManager::OnCaptureLost)
     EVT_CHILD_FOCUS(wxAuiManager::OnChildFocus)
     EVT_AUI_FIND_MANAGER(wxAuiManager::OnFindManager)
-    EVT_TIMER(101, wxAuiManager::OnHintFadeTimer)
 END_EVENT_TABLE()
 
 
@@ -913,7 +802,7 @@ wxAuiManager* wxAuiManager::GetManager(wxWindow* window)
 
 void wxAuiManager::UpdateHintWindowConfig()
 {
-    // find out if the the system can do transparent frames
+    // find out if the system can do transparent frames
     bool can_do_transparent = false;
 
     wxWindow* w = m_frame;
@@ -1112,7 +1001,40 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info)
     if (pane_info.IsDocked())
         RestoreMaximizedPane();
 
-    m_panes.Add(pane_info);
+    // special case:  wxAuiToolBar style interacts with docking flags
+    wxAuiPaneInfo test(pane_info);
+    wxAuiToolBar* toolbar = wxDynamicCast(window, wxAuiToolBar);
+    if (toolbar)
+    {
+        // if pane has default docking flags
+        const unsigned int dockMask = wxAuiPaneInfo::optionLeftDockable |
+                                        wxAuiPaneInfo::optionRightDockable |
+                                        wxAuiPaneInfo::optionTopDockable |
+                                        wxAuiPaneInfo::optionBottomDockable;
+        const unsigned int defaultDock = wxAuiPaneInfo().
+                                            DefaultPane().state & dockMask;
+        if ((test.state & dockMask) == defaultDock)
+        {
+            // set docking flags based on toolbar style
+            if (toolbar->GetWindowStyleFlag() & wxAUI_TB_VERTICAL)
+            {
+                test.TopDockable(false).BottomDockable(false);
+            }
+            else if (toolbar->GetWindowStyleFlag() & wxAUI_TB_HORIZONTAL)
+            {
+                test.LeftDockable(false).RightDockable(false);
+            }
+        }
+        else
+        {
+            // see whether non-default docking flags are valid
+            test.window = window;
+            wxCHECK_MSG(test.IsValid(), false,
+                        "toolbar style and pane docking flags are incompatible");
+        }
+    }
+
+    m_panes.Add(test);
 
     wxAuiPaneInfo& pinfo = m_panes.Last();
 
@@ -1124,7 +1046,7 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info)
     if (pinfo.name.empty() || already_exists)
     {
         pinfo.name.Printf(wxT("%08lx%08x%08x%08lx"),
-             wxPtrToUInt(pinfo.window) & 0xffffffff,
+             (unsigned long)(wxPtrToUInt(pinfo.window) & 0xffffffff),
              (unsigned int)time(NULL),
 #ifdef __WXWINCE__
              (unsigned int)GetTickCount(),
@@ -1441,7 +1363,7 @@ 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())
+        if (!p.IsToolbar() && !p.IsFloating())
         {
             p.SetFlag(wxAuiPaneInfo::optionHidden,
                       p.HasFlag(wxAuiPaneInfo::savedHiddenState));
@@ -1649,10 +1571,15 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update)
     if (part != wxT("layout2"))
         return false;
 
-    // mark all panes currently managed as docked and hidden
+    // Mark all panes currently managed as hidden. Also, dock all panes that are dockable.
     int pane_i, pane_count = m_panes.GetCount();
     for (pane_i = 0; pane_i < pane_count; ++pane_i)
-        m_panes.Item(pane_i).Dock().Hide();
+    {
+        wxAuiPaneInfo& p = m_panes.Item(pane_i);
+        if(p.IsDockable())
+            p.Dock();
+        p.Hide();
+    }
 
     // clear out the dock array; this will be reconstructed
     m_docks.Clear();
@@ -1662,6 +1589,7 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update)
     input.Replace(wxT("\\|"), wxT("\a"));
     input.Replace(wxT("\\;"), wxT("\b"));
 
+    m_has_maximized = false;
     while (1)
     {
         wxAuiPaneInfo pane;
@@ -1704,6 +1632,9 @@ bool wxAuiManager::LoadPerspective(const wxString& layout, bool update)
 
         LoadPaneInfo(pane_part, pane);
 
+        if ( pane.IsMaximized() )
+            m_has_maximized = true;
+
         wxAuiPaneInfo& p = GetPane(pane.name);
         if (!p.IsOk())
         {
@@ -1838,8 +1769,8 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont,
     // value that the pane will receive
     int pane_proportion = pane.dock_proportion;
 
-    wxAuiProportionalBoxSizer* horz_pane_sizer = new wxAuiProportionalBoxSizer(wxHORIZONTAL);
-    wxAuiProportionalBoxSizer* vert_pane_sizer = new wxAuiProportionalBoxSizer(wxVERTICAL);
+    wxBoxSizer* horz_pane_sizer = new wxBoxSizer(wxHORIZONTAL);
+    wxBoxSizer* vert_pane_sizer = new wxBoxSizer(wxVERTICAL);
 
     if (pane.HasGripper())
     {
@@ -1861,7 +1792,7 @@ void wxAuiManager::LayoutAddPane(wxSizer* cont,
     if (pane.HasCaption())
     {
         // create the caption sizer
-        wxAuiProportionalBoxSizer* caption_sizer = new wxAuiProportionalBoxSizer(wxHORIZONTAL);
+        wxBoxSizer* caption_sizer = new wxBoxSizer(wxHORIZONTAL);
 
         sizer_item = caption_sizer->Add(1, caption_size, 1, wxEXPAND);
 
@@ -2010,7 +1941,7 @@ void wxAuiManager::LayoutAddDock(wxSizer* cont,
     }
 
     // create the sizer for the dock
-    wxSizer* dock_sizer = new wxAuiProportionalBoxSizer(orientation);
+    wxSizer* dock_sizer = new wxBoxSizer(orientation);
 
     // add each pane to the dock
     bool has_maximized_pane = false;
@@ -2143,7 +2074,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
                                  wxAuiDockUIPartArray& uiparts,
                                  bool spacer_only)
 {
-    wxAuiProportionalBoxSizer* container = new wxAuiProportionalBoxSizer(wxVERTICAL);
+    wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
 
     int pane_border_size = m_art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
     int caption_size = m_art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE);
@@ -2426,7 +2357,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
 
         // create a container which will hold this layer's
         // docks (top, bottom, left, right)
-        cont = new wxAuiProportionalBoxSizer(wxVERTICAL);
+        cont = new wxBoxSizer(wxVERTICAL);
 
 
         // find any top docks in this layer
@@ -2441,7 +2372,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
         // fill out the middle layer (which consists
         // of left docks, content area and right docks)
 
-        middle = new wxAuiProportionalBoxSizer(wxHORIZONTAL);
+        middle = new wxBoxSizer(wxHORIZONTAL);
 
         // find any left docks in this layer
         FindDocks(docks, wxAUI_DOCK_LEFT, layer, -1, arr);
@@ -2510,7 +2441,7 @@ wxSizer* wxAuiManager::LayoutAll(wxAuiPaneInfoArray& panes,
     {
         // no sizer available, because there are no docks,
         // therefore we will create a simple background area
-        cont = new wxAuiProportionalBoxSizer(wxVERTICAL);
+        cont = new wxBoxSizer(wxVERTICAL);
         wxSizerItem* sizer_item = cont->Add(1,1, 1, wxEXPAND);
         wxAuiDockUIPart part;
         part.type = wxAuiDockUIPart::typeBackground;
@@ -2658,6 +2589,17 @@ void wxAuiManager::Update()
                 */
                 }
 
+                // update whether the pane is resizable or not
+                long style = p.frame->GetWindowStyleFlag();
+                if (p.IsFixed())
+                    style &= ~wxRESIZE_BORDER;
+                else
+                    style |= wxRESIZE_BORDER;
+                p.frame->SetWindowStyleFlag(style);
+
+                if (p.frame->GetLabel() != p.caption)
+                    p.frame->SetLabel(p.caption);
+
                 if (p.frame->IsShown() != p.IsShown())
                     p.frame->Show(p.IsShown());
             }
@@ -2892,7 +2834,22 @@ bool wxAuiManager::ProcessDockResult(wxAuiPaneInfo& target,
     }
 
     if (allowed)
+    {
         target = new_pos;
+        // Should this RTTI and function call be rewritten as
+        // sending a new event type to allow other window types
+        // to vary size based on dock location?
+        wxAuiToolBar* toolbar = wxDynamicCast(target.window, wxAuiToolBar);
+        if (toolbar)
+        {
+            wxSize hintSize = toolbar->GetHintSize(target.dock_direction);
+            if (target.best_size != hintSize)
+            {
+                target.best_size = hintSize;
+                target.floating_size = wxDefaultSize;
+            }
+        }
+    }
 
     return allowed;
 }
@@ -2936,7 +2893,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks,
 
 
     if (pt.x < layer_insert_offset &&
-        pt.x > layer_insert_offset-auiLayerInsertPixels)
+        pt.x > layer_insert_offset-auiLayerInsertPixels &&
+        pt.y > 0 &&
+        pt.y < cli_size.y)
     {
         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_LEFT),
                                 GetMaxLayer(docks, wxAUI_DOCK_BOTTOM)),
@@ -2952,7 +2911,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks,
         return ProcessDockResult(target, drop);
     }
     else if (pt.y < layer_insert_offset &&
-             pt.y > layer_insert_offset-auiLayerInsertPixels)
+             pt.y > layer_insert_offset-auiLayerInsertPixels &&
+             pt.x > 0 &&
+             pt.x < cli_size.x)
     {
         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_TOP),
                                 GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
@@ -2968,7 +2929,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks,
         return ProcessDockResult(target, drop);
     }
     else if (pt.x >= cli_size.x - layer_insert_offset &&
-             pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels)
+             pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels &&
+             pt.y > 0 &&
+             pt.y < cli_size.y)
     {
         int new_layer = wxMax(wxMax(GetMaxLayer(docks, wxAUI_DOCK_RIGHT),
                                 GetMaxLayer(docks, wxAUI_DOCK_TOP)),
@@ -2984,7 +2947,9 @@ bool wxAuiManager::DoDrop(wxAuiDockInfoArray& docks,
         return ProcessDockResult(target, drop);
     }
     else if (pt.y >= cli_size.y - layer_insert_offset &&
-             pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels)
+             pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels &&
+             pt.x > 0 &&
+             pt.x < cli_size.x)
     {
         int new_layer = wxMax( wxMax( GetMaxLayer(docks, wxAUI_DOCK_BOTTOM),
                                       GetMaxLayer(docks, wxAUI_DOCK_LEFT)),
@@ -3313,6 +3278,8 @@ void wxAuiManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event))
     if (!m_hint_wnd || m_hint_fadeamt >= m_hint_fademax)
     {
         m_hint_fadetimer.Stop();
+        Disconnect(m_hint_fadetimer.GetId(), wxEVT_TIMER,
+                   wxTimerEventHandler(wxAuiManager::OnHintFadeTimer));
         return;
     }
 
@@ -3354,8 +3321,10 @@ void wxAuiManager::ShowHint(const wxRect& rect)
         if (m_hint_fadeamt != m_hint_fademax) //  Only fade if we need to
         {
             // start fade in timer
-            m_hint_fadetimer.SetOwner(this, 101);
+            m_hint_fadetimer.SetOwner(this);
             m_hint_fadetimer.Start(5);
+            Connect(m_hint_fadetimer.GetId(), wxEVT_TIMER,
+                    wxTimerEventHandler(wxAuiManager::OnHintFadeTimer));
         }
     }
     else  // Not using a transparent hint window...
@@ -3381,7 +3350,8 @@ void wxAuiManager::ShowHint(const wxRect& rect)
             wxAuiPaneInfo& pane = m_panes.Item(i);
 
             if (pane.IsFloating() &&
-                pane.frame->IsShown())
+                    pane.frame &&
+                        pane.frame->IsShown())
             {
                 wxRect rect = pane.frame->GetRect();
 #ifdef __WXGTK__
@@ -3423,6 +3393,10 @@ void wxAuiManager::HideHint()
             m_hint_wnd->Show(false);
         m_hint_wnd->SetTransparent(0);
         m_hint_fadetimer.Stop();
+        // In case this is called while a hint fade is going, we need to
+        // disconnect the event handler.
+        Disconnect(m_hint_fadetimer.GetId(), wxEVT_TIMER,
+                   wxTimerEventHandler(wxAuiManager::OnHintFadeTimer));
         m_last_hint = wxRect();
         return;
     }
@@ -3441,7 +3415,7 @@ void wxAuiManager::OnHintActivate(wxActivateEvent& WXUNUSED(event))
     // Do nothing so this event isn't handled in the base handlers.
 
     // Letting the hint window activate without this handler can lead to
-    // weird behavior on Mac where the menu is switched out to the top
+    // weird behaviour on Mac where the menu is switched out to the top
     // window's menu in MDI applications when it shouldn't be. So since
     // we don't want user interaction with the hint window anyway, we just
     // prevent it from activating here.
@@ -3468,13 +3442,22 @@ void wxAuiManager::StartPaneDrag(wxWindow* pane_window,
     m_action_window = pane_window;
     m_action_offset = offset;
     m_frame->CaptureMouse();
+
+    if (pane.frame)
+    {
+        wxRect window_rect = pane.frame->GetRect();
+        wxRect client_rect = pane.frame->GetClientRect();
+        wxPoint client_pt = pane.frame->ClientToScreen(client_rect.GetTopLeft());
+        wxPoint origin_pt = client_pt - window_rect.GetTopLeft();
+        m_action_offset += origin_pt;
+    }
 }
 
 
 // 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
+// specified drop point, 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
@@ -3589,6 +3572,9 @@ void wxAuiManager::OnFloatingPaneMoveStart(wxWindow* wnd)
     wxAuiPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
 
+    if(!pane.frame)
+        return;
+
     if (m_flags & wxAUI_MGR_TRANSPARENT_DRAG)
         pane.frame->SetTransparent(150);
 }
@@ -3777,13 +3763,16 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir)
     HideHint();
 }
 
-void wxAuiManager::OnFloatingPaneResized(wxWindow* wnd, const wxSize& size)
+void wxAuiManager::OnFloatingPaneResized(wxWindow* wnd, const wxRect& rect)
 {
     // try to find the pane
     wxAuiPaneInfo& pane = GetPane(wnd);
     wxASSERT_MSG(pane.IsOk(), wxT("Pane window not found"));
 
-    pane.floating_size = size;
+    pane.FloatingSize(rect.GetWidth(), rect.GetHeight());
+
+    // the top-left position may change as well as the size
+    pane.FloatingPosition(rect.x, rect.y);
 }
 
 
@@ -3885,7 +3874,7 @@ void wxAuiManager::OnRender(wxAuiManagerEvent& evt)
 // Render() fire a render event, which is normally handled by
 // wxAuiManager::OnRender().  This allows the render function to
 // be overridden via the render event.  This can be useful for paintin
-// custom graphics in the main window. Default behavior can be
+// custom graphics in the main window. Default behaviour can be
 // invoked in the overridden function by calling OnRender()
 
 void wxAuiManager::Render(wxDC* dc)
@@ -4634,6 +4623,15 @@ void wxAuiManager::OnMotion(wxMouseEvent& event)
     {
         if (m_action_window)
         {
+            // We can't move the child window so we need to get the frame that
+            // we want to be really moving. This is probably not the best place
+            // to do this but at least it fixes the bug (#13177) for now.
+            if (!m_action_window->IsKindOf(CLASSINFO(wxAuiFloatingFrame)))
+            {
+                wxAuiPaneInfo& pane = GetPane(m_action_window);
+                m_action_window = pane.frame;
+            }
+
             wxPoint pt = m_frame->ClientToScreen(event.GetPosition());
             m_action_window->Move(pt.x - m_action_offset.x,
                                 pt.y - m_action_offset.y);