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;
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
};
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;
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;
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
/**
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.
*/
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.
/**
@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
@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
@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().
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}
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)();
}
}
{
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)
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 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();
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;
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)
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
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;
{
area = GetSizeInOrientation(m_sizes[i], major_axis);
row_count = m_nrows_min + i;
+ bestSize = m_sizes[i];
}
}
}
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();