]> 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();}
 
     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;
 
 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_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
 };
 
     wxRIBBON_PANEL_DEFAULT_STYLE    = 0
 };
@@ -75,6 +76,11 @@ public:
     wxRibbonPanel* GetExpandedDummy();
     wxRibbonPanel* GetExpandedPanel();
 
     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;
 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);
 
     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;
 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 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
     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.
 
     /**
         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.
     */
         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.
         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);
         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.
     /**
         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.
     /**
         @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;
         @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.
     /**
         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).
         @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;
         @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.
     /**
         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
         @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).
             @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;
         @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.
     /**
         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).
         @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;
         @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.
     /**
         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
         @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).
             @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;
         @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();
     /**
         Perform initial size and layout calculations after children have been
         added, and/or realize children.
     */
     virtual bool Realize();
-    
+
     /**
         Alias for Realize().
     */
     bool Realise();
     /**
         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().
 protected:
     /**
         Implementation of GetNextSmallerSize().
index fd455fe32ac49cf37ebd5c60a1c340c253b8537f..0f91684637f6c2f8d14fe03bd79953da4071bc5b 100644 (file)
         minimises.
     @style{wxRIBBON_PANEL_STRETCH}
         Stretches a single panel to fit the parent page.
         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}
     @endStyleTable
 
     @library{wxribbon}
index 3448462420b4bfe709af4b5a3c81e97e2f127818..17d8c316dc3f359946dd5ad4901a044dd9cb3756 100644 (file)
@@ -495,19 +495,30 @@ bool wxRibbonPage::Realize()
 
 void wxRibbonPage::PopulateSizeCalcArray(wxSize (wxWindow::*get_size)(void) const)
 {
 
 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];
     }
     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();
     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;
             }
             {
                 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)
             {
                 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;
 }
 
     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
 {
 wxSize wxRibbonPanel::DoGetNextSmallerSize(wxOrientation direction,
                                          wxSize relative_to) const
 {
@@ -742,6 +760,13 @@ bool wxRibbonPanel::ShowExpanded()
     }
 
     wxSize size = GetBestSize();
     }
 
     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();
 
     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,
         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;
 
     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;
     wxSize* row_sizes = new wxSize[m_nrows_max];
     wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
         wxVERTICAL : wxHORIZONTAL;
+
     SetMinSize(wxSize(0, 0));
     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)
     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;
             size.IncBy(0, row_sizes[r].y);
         }
         m_sizes[nrows - m_nrows_min] = size;
+
         if(GetSizeInOrientation(size, major_axis) < smallest_area)
         {
         if(GetSizeInOrientation(size, major_axis) < smallest_area)
         {
-            SetMinSize(size);
             smallest_area = GetSizeInOrientation(size, major_axis);
             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
     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;
     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;
     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;
             {
                 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;
 }
 
     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();
 wxSize wxRibbonToolBar::DoGetBestSize() const
 {
     return GetMinSize();