]> git.saurik.com Git - wxWidgets.git/commitdiff
Added wxRIBBON_PANEL_FLEXIBLE flag to allow toolbars to wrap, taking up the optimum...
authorJulian Smart <julian@anthemion.co.uk>
Mon, 12 Mar 2012 19:30:10 +0000 (19:30 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Mon, 12 Mar 2012 19:30:10 +0000 (19:30 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70885 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/ribbon/control.h
include/wx/ribbon/panel.h
include/wx/ribbon/toolbar.h
interface/wx/ribbon/control.h
interface/wx/ribbon/panel.h
src/ribbon/page.cpp
src/ribbon/panel.cpp
src/ribbon/toolbar.cpp

index 35cfd5777c8268af684bf0d93a508b852eb99255..f0f3d1208972f639002700bd7f34ef47afa242a4 100644 (file)
@@ -55,6 +55,9 @@ public:
     virtual bool Realize();
     bool Realise() {return Realize();}
 
+    // Finds the best width and height given the parent's width and height
+    virtual wxSize GetBestSizeForParentSize(const wxSize& WXUNUSED(parentSize)) const { return GetBestSize(); }
+
 protected:
     wxRibbonArtProvider* m_art;
 
index 8a48c836fb54c93cfb9ed12c6abc027e9c1695e5..51d49c7964e1e3241dd3b3f7320f94e2a48efbf1 100644 (file)
@@ -24,6 +24,7 @@ enum wxRibbonPanelOption
     wxRIBBON_PANEL_EXT_BUTTON       = 1 << 3,
     wxRIBBON_PANEL_MINIMISE_BUTTON  = 1 << 4,
     wxRIBBON_PANEL_STRETCH          = 1 << 5,
+    wxRIBBON_PANEL_FLEXIBLE         = 1 << 6,
 
     wxRIBBON_PANEL_DEFAULT_STYLE    = 0
 };
@@ -75,6 +76,11 @@ public:
     wxRibbonPanel* GetExpandedDummy();
     wxRibbonPanel* GetExpandedPanel();
 
+    // Finds the best width and height given the parent's width and height
+    virtual wxSize GetBestSizeForParentSize(const wxSize& parentSize) const;
+
+    long GetFlags() { return m_flags; }
+
 protected:
     virtual wxSize DoGetBestSize() const;
     virtual wxSize GetPanelSizerBestSize() const;
index a31f5aef4839c264e6a40e307376e28d39c8440e..da6c2624b7eb985d20db71f0509dca857f82f2b9 100644 (file)
@@ -155,6 +155,9 @@ public:
     virtual void EnableTool(int tool_id, bool enable = true);
     virtual void ToggleTool(int tool_id, bool checked);
 
+    // Finds the best width and height given the parent's width and height
+    virtual wxSize GetBestSizeForParentSize(const wxSize& parentSize) const;
+
 protected:
     friend class wxRibbonToolBarEvent;
     virtual wxSize DoGetBestSize() const;
index 8f497ef6145721a6079b15a418bf921c653c2a1c..4a79b47354d736354a38f73e3e6e52ea66ae2ae3 100644 (file)
@@ -13,7 +13,7 @@
     ribbon characteristics of having a ribbon art provider, and (optionally)
     non-continuous resizing. Despite what the name may imply, it is not the
     top-level control for creating a ribbon interface - that is wxRibbonBar.
-  
+
     Ribbon controls often have a region which is "transparent", and shows the
     contents of the ribbon page or panel behind it. If implementing a new
     ribbon control, then it may be useful to realise that this effect is done
@@ -36,7 +36,7 @@ public:
 
     /**
         Constructor.
-        
+
         If @a parent is a wxRibbonControl with a non-NULL art provider, then
         the art provider of new control is set to that of @a parent.
     */
@@ -50,12 +50,12 @@ public:
         Set the art provider to be used. In many cases, setting the art provider
         will also set the art provider on all child windows which extend
         wxRibbonControl.
-        
+
         In most cases, controls will not take ownership of the given pointer,
         with the notable exception being wxRibbonBar::SetArtProvider().
     */
     virtual void SetArtProvider(wxRibbonArtProvider* art);
-    
+
     /**
         Get the art provider to be used. Note that until an art provider has
         been set in some way, this function may return NULL.
@@ -65,31 +65,31 @@ public:
     /**
         @return @true if this window can take any size (greater than its minimum
         size), @false if it can only take certain sizes.
-        
+
         @see GetNextSmallerSize()
         @see GetNextLargerSize()
     */
     virtual bool IsSizingContinuous() const;
-    
+
     /**
         If sizing is not continuous, then return a suitable size for the control
         which is smaller than the current size.
-    
+
         @param direction
             The direction(s) in which the size should reduce.
         @return
             The current size if there is no smaller size, otherwise a suitable
             size which is smaller in the given direction(s), and the same as the
             current size in the other direction (if any).
-      
+
         @see IsSizingContinuous()
     */
     wxSize GetNextSmallerSize(wxOrientation direction) const;
-    
+
     /**
         If sizing is not continuous, then return a suitable size for the control
         which is smaller than the given size.
-    
+
         @param direction
             The direction(s) in which the size should reduce.
         @param relative_to
@@ -98,31 +98,31 @@ public:
             @a relative_to if there is no smaller size, otherwise a suitable
             size which is smaller in the given direction(s), and the same as
             @a relative_to in the other direction (if any).
-      
+
         @see IsSizingContinuous()
         @see DoGetNextSmallerSize()
     */
     wxSize GetNextSmallerSize(wxOrientation direction, wxSize relative_to) const;
-    
+
     /**
         If sizing is not continuous, then return a suitable size for the control
         which is larger than the current size.
-    
+
         @param direction
             The direction(s) in which the size should increase.
         @return
             The current size if there is no larger size, otherwise a suitable
             size which is larger in the given direction(s), and the same as the
             current size in the other direction (if any).
-    
+
         @see IsSizingContinuous()
     */
     wxSize GetNextLargerSize(wxOrientation direction) const;
-    
+
     /**
         If sizing is not continuous, then return a suitable size for the control
         which is larger than the given size.
-    
+
         @param direction
             The direction(s) in which the size should increase.
         @param relative_to
@@ -131,23 +131,28 @@ public:
             @a relative_to if there is no larger size, otherwise a suitable
             size which is larger in the given direction(s), and the same as
             @a relative_to in the other direction (if any).
-    
+
         @see IsSizingContinuous()
         @see DoGetNextLargerSize()
     */
     wxSize GetNextLargerSize(wxOrientation direction, wxSize relative_to) const;
-    
+
     /**
         Perform initial size and layout calculations after children have been
         added, and/or realize children.
     */
     virtual bool Realize();
-    
+
     /**
         Alias for Realize().
     */
     bool Realise();
-    
+
+    /**
+        Finds the best width and height given the parent's width and height.
+        Used to implement the wxRIBBON_PANEL_FLEXIBLE panel style.
+    */
+    virtual wxSize GetBestSizeForParentSize(const wxSize& parentSize) const;
 protected:
     /**
         Implementation of GetNextSmallerSize().
index fd455fe32ac49cf37ebd5c60a1c340c253b8537f..0f91684637f6c2f8d14fe03bd79953da4071bc5b 100644 (file)
         minimises.
     @style{wxRIBBON_PANEL_STRETCH}
         Stretches a single panel to fit the parent page.
+    @style{wxRIBBON_PANEL_FLEXIBLE}
+        Allows the panel to size in both directions; currently only useful
+        when a single wxRibbonToolBar is the child of the panel, particularly
+        in vertical orientation where the number of rows is dependent on the
+        amount of horizontal space available. Set the minimum and maximum
+        toolbar rows to take full advantage of this wrapping behaviour.
     @endStyleTable
 
     @library{wxribbon}
index 3448462420b4bfe709af4b5a3c81e97e2f127818..17d8c316dc3f359946dd5ad4901a044dd9cb3756 100644 (file)
@@ -495,19 +495,30 @@ bool wxRibbonPage::Realize()
 
 void wxRibbonPage::PopulateSizeCalcArray(wxSize (wxWindow::*get_size)(void) const)
 {
+    wxSize parentSize = GetSize();
+    parentSize.x -= m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE);
+    parentSize.x -= m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE);
+    parentSize.y -= m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE);
+    parentSize.y -= m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE);
+
     if(m_size_calc_array_size != GetChildren().GetCount())
     {
         delete[] m_size_calc_array;
         m_size_calc_array_size = GetChildren().GetCount();
         m_size_calc_array = new wxSize[m_size_calc_array_size];
     }
+
     wxSize* node_size = m_size_calc_array;
     for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
           node;
           node = node->GetNext(), ++node_size )
     {
         wxWindow* child = node->GetData();
-        *node_size = (child->*get_size)();
+        wxRibbonPanel* panel = wxDynamicCast(child, wxRibbonPanel);
+        if (panel && panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE)
+            *node_size = panel->GetBestSizeForParentSize(parentSize);
+        else
+            *node_size = (child->*get_size)();
     }
 }
 
@@ -776,7 +787,12 @@ bool wxRibbonPage::ExpandPanels(wxOrientation direction, int maximum_amount)
             {
                 continue;
             }
-            if(panel->IsSizingContinuous())
+            if (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE)
+            {
+                // Don't change if it's flexible since we already calculated the
+                // correct size for the panel.
+            }
+            else if(panel->IsSizingContinuous())
             {
                 int size = GetSizeInOrientation(*panel_size, direction);
                 if(size < smallest_size)
index a14bb7336ba000c1395183b1f1aebe1c0a01314d..f8f26f1e890258d0632f99a0fc8899f76ef77d1d 100644 (file)
@@ -311,6 +311,24 @@ bool wxRibbonPanel::IsSizingContinuous() const
     return (m_flags & wxRIBBON_PANEL_STRETCH) != 0;
 }
 
+// Finds the best width and height given the parent's width and height
+wxSize wxRibbonPanel::GetBestSizeForParentSize(const wxSize& parentSize) const
+{
+    if (GetChildren().GetCount() == 1)
+    {
+        wxWindow* win = GetChildren().GetFirst()->GetData();
+        wxRibbonControl* control = wxDynamicCast(win, wxRibbonControl);
+        if (control)
+        {
+            wxClientDC temp_dc((wxRibbonPanel*) this);
+            wxSize childSize = control->GetBestSizeForParentSize(parentSize);
+            wxSize overallSize = m_art->GetPanelSize(temp_dc, this, childSize, NULL);
+            return overallSize;
+        }
+    }
+    return GetSize();
+}
+
 wxSize wxRibbonPanel::DoGetNextSmallerSize(wxOrientation direction,
                                          wxSize relative_to) const
 {
@@ -742,6 +760,13 @@ bool wxRibbonPanel::ShowExpanded()
     }
 
     wxSize size = GetBestSize();
+
+    // Special case for flexible panel layout, where GetBestSize doesn't work
+    if (GetFlags() & wxRIBBON_PANEL_FLEXIBLE)
+    {
+        size = GetBestSizeForParentSize(wxSize(400, 1000));
+    }
+
     wxPoint pos = GetExpandedPosition(wxRect(GetScreenPosition(), GetSize()),
         size, m_preferred_expand_direction).GetTopLeft();
 
@@ -750,7 +775,7 @@ bool wxRibbonPanel::ShowExpanded()
         pos, size, wxFRAME_NO_TASKBAR | wxBORDER_NONE);
 
     m_expanded_panel = new wxRibbonPanel(container, wxID_ANY,
-        GetLabel(), m_minimised_icon, wxPoint(0, 0), size, m_flags);
+        GetLabel(), m_minimised_icon, wxPoint(0, 0), size, (m_flags /* & ~wxRIBBON_PANEL_FLEXIBLE */));
 
     m_expanded_panel->SetArtProvider(m_art);
     m_expanded_panel->m_expanded_dummy = this;
index 4c4b14cdac41beb278ddb10fa1da9161013bfb38..6c6c8b7f5a527af6ad55919c7073111da08ad7ca 100644 (file)
@@ -781,7 +781,21 @@ bool wxRibbonToolBar::Realize()
     wxSize* row_sizes = new wxSize[m_nrows_max];
     wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
         wxVERTICAL : wxHORIZONTAL;
+
     SetMinSize(wxSize(0, 0));
+    wxSize minSize(INT_MAX, INT_MAX);
+
+    // See if we're sizing flexibly (i.e. wrapping), and set min size differently
+    bool sizingFlexibly = false;
+    wxRibbonPanel* panel = wxDynamicCast(GetParent(), wxRibbonPanel);
+    if (panel && (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE))
+        sizingFlexibly = true;
+
+    // Without this, there will be redundant horizontal space because SetMinSize will
+    // use the smallest possible height (and therefore largest width).
+    if (sizingFlexibly)
+        major_axis = wxHORIZONTAL;
+
     for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
     {
         for(r = 0; r < nrows; ++r)
@@ -809,12 +823,29 @@ bool wxRibbonToolBar::Realize()
             size.IncBy(0, row_sizes[r].y);
         }
         m_sizes[nrows - m_nrows_min] = size;
+
         if(GetSizeInOrientation(size, major_axis) < smallest_area)
         {
-            SetMinSize(size);
             smallest_area = GetSizeInOrientation(size, major_axis);
+            SetMinSize(size);
+        }
+
+        if (sizingFlexibly)
+        {
+            if (size.x < minSize.x)
+                minSize.x = size.x;
+            if (size.y < minSize.y)
+                minSize.y = size.y;
         }
     }
+
+    if (sizingFlexibly)
+    {
+        // Give it the min size in either direction regardless of row,
+        // so that we're able to vary the size of the panel according to
+        // the space the toolbar takes up.
+        SetMinSize(minSize);
+    }
     delete[] row_sizes;
 
     // Position the groups
@@ -834,6 +865,20 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
     int row_count = m_nrows_max;
     wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
         wxVERTICAL : wxHORIZONTAL;
+
+    // See if we're sizing flexibly, and set min size differently
+    bool sizingFlexibly = false;
+    wxRibbonPanel* panel = wxDynamicCast(GetParent(), wxRibbonPanel);
+    if (panel && (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE))
+        sizingFlexibly = true;
+
+    // Without this, there will be redundant horizontal space because SetMinSize will
+    // use the smallest possible height (and therefore largest width).
+    if (sizingFlexibly)
+        major_axis = wxHORIZONTAL;
+
+    wxSize bestSize = m_sizes[0];
+
     if(m_nrows_max != m_nrows_min)
     {
         int area = 0;
@@ -844,6 +889,7 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
             {
                 area = GetSizeInOrientation(m_sizes[i], major_axis);
                 row_count = m_nrows_min + i;
+                bestSize = m_sizes[i];
             }
         }
     }
@@ -895,6 +941,41 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
     delete[] row_sizes;
 }
 
+// Finds the best width and height given the parents' width and height
+wxSize wxRibbonToolBar::GetBestSizeForParentSize(const wxSize& parentSize) const
+{
+    if (!m_sizes)
+        return GetMinSize();
+
+    // Choose row count with largest possible area
+    wxSize size = parentSize;
+    int row_count = m_nrows_max;
+    wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
+        wxVERTICAL : wxHORIZONTAL;
+
+    // A toolbar should maximize its width whether vertical or horizontal, so
+    // force the major axis to be horizontal. Without this, there will be
+    // redundant horizontal space.
+    major_axis = wxHORIZONTAL;
+    wxSize bestSize = m_sizes[0];
+
+    if(m_nrows_max != m_nrows_min)
+    {
+        int area = 0;
+        for(int i = 0; i <= m_nrows_max - m_nrows_min; ++i)
+        {
+            if(m_sizes[i].x <= size.x && m_sizes[i].y <= size.y &&
+                GetSizeInOrientation(m_sizes[i], major_axis) > area)
+            {
+                area = GetSizeInOrientation(m_sizes[i], major_axis);
+                row_count = m_nrows_min + i;
+                bestSize = m_sizes[i];
+            }
+        }
+    }
+    return bestSize;
+}
+
 wxSize wxRibbonToolBar::DoGetBestSize() const
 {
     return GetMinSize();