Added wxRIBBON_PANEL_FLEXIBLE flag to allow toolbars to wrap, taking up the optimum amount of space when used in a vertical palette.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70885 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2012-03-12 19:30:10 +00:00
parent 4f134f0cf8
commit 98742322cd
8 changed files with 169 additions and 24 deletions

View 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;

View 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;

View 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;

View File

@@ -148,6 +148,11 @@ public:
*/
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().

View File

@@ -45,6 +45,12 @@
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}

View File

@@ -495,18 +495,29 @@ 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();
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)

View 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;

View 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,11 +823,28 @@ 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;
@@ -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();