1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/ribbon/page.cpp
3 // Purpose: Container for ribbon-bar-style interface panels
4 // Author: Peter Cawley
8 // Copyright: (C) Peter Cawley
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
17 #include "wx/ribbon/page.h"
21 #include "wx/ribbon/art.h"
22 #include "wx/ribbon/bar.h"
23 #include "wx/dcbuffer.h"
29 #include "wx/msw/private.h"
32 static int GetSizeInOrientation(wxSize size
, wxOrientation orientation
);
34 // As scroll buttons need to be rendered on top of a page's child windows, the
35 // buttons themselves have to be proper child windows (rather than just painted
36 // onto the page). In order to get proper clipping of a page's children (with
37 // regard to the scroll button), the scroll buttons are created as children of
38 // the ribbon bar rather than children of the page. This could not have been
39 // achieved by creating buttons as children of the page and then doing some Z-order
40 // manipulation, as this causes problems on win32 due to ribbon panels having the
41 // transparent flag set.
42 class wxRibbonPageScrollButton
: public wxRibbonControl
45 wxRibbonPageScrollButton(wxRibbonPage
* sibling
,
46 wxWindowID id
= wxID_ANY
,
47 const wxPoint
& pos
= wxDefaultPosition
,
48 const wxSize
& size
= wxDefaultSize
,
51 virtual ~wxRibbonPageScrollButton();
54 virtual wxBorder
GetDefaultBorder() const { return wxBORDER_NONE
; }
56 void OnEraseBackground(wxEraseEvent
& evt
);
57 void OnPaint(wxPaintEvent
& evt
);
58 void OnMouseEnter(wxMouseEvent
& evt
);
59 void OnMouseLeave(wxMouseEvent
& evt
);
60 void OnMouseDown(wxMouseEvent
& evt
);
61 void OnMouseUp(wxMouseEvent
& evt
);
63 wxRibbonPage
* m_sibling
;
66 DECLARE_CLASS(wxRibbonPageScrollButton
)
70 IMPLEMENT_CLASS(wxRibbonPageScrollButton
, wxRibbonControl
)
72 BEGIN_EVENT_TABLE(wxRibbonPageScrollButton
, wxRibbonControl
)
73 EVT_ENTER_WINDOW(wxRibbonPageScrollButton::OnMouseEnter
)
74 EVT_ERASE_BACKGROUND(wxRibbonPageScrollButton::OnEraseBackground
)
75 EVT_LEAVE_WINDOW(wxRibbonPageScrollButton::OnMouseLeave
)
76 EVT_LEFT_DOWN(wxRibbonPageScrollButton::OnMouseDown
)
77 EVT_LEFT_UP(wxRibbonPageScrollButton::OnMouseUp
)
78 EVT_PAINT(wxRibbonPageScrollButton::OnPaint
)
81 wxRibbonPageScrollButton::wxRibbonPageScrollButton(wxRibbonPage
* sibling
,
85 long style
) : wxRibbonControl(sibling
->GetParent(), id
, pos
, size
, wxBORDER_NONE
)
87 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
89 m_flags
= (style
& wxRIBBON_SCROLL_BTN_DIRECTION_MASK
) | wxRIBBON_SCROLL_BTN_FOR_PAGE
;
92 wxRibbonPageScrollButton::~wxRibbonPageScrollButton()
96 void wxRibbonPageScrollButton::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
98 // Do nothing - all painting done in main paint handler
101 void wxRibbonPageScrollButton::OnPaint(wxPaintEvent
& WXUNUSED(evt
))
103 wxAutoBufferedPaintDC
dc(this);
106 m_art
->DrawScrollButton(dc
, this, GetSize(), m_flags
);
110 void wxRibbonPageScrollButton::OnMouseEnter(wxMouseEvent
& WXUNUSED(evt
))
112 m_flags
|= wxRIBBON_SCROLL_BTN_HOVERED
;
116 void wxRibbonPageScrollButton::OnMouseLeave(wxMouseEvent
& WXUNUSED(evt
))
118 m_flags
&= ~wxRIBBON_SCROLL_BTN_HOVERED
;
119 m_flags
&= ~wxRIBBON_SCROLL_BTN_ACTIVE
;
123 void wxRibbonPageScrollButton::OnMouseDown(wxMouseEvent
& WXUNUSED(evt
))
125 m_flags
|= wxRIBBON_SCROLL_BTN_ACTIVE
;
129 void wxRibbonPageScrollButton::OnMouseUp(wxMouseEvent
& WXUNUSED(evt
))
131 if(m_flags
& wxRIBBON_SCROLL_BTN_ACTIVE
)
133 m_flags
&= ~wxRIBBON_SCROLL_BTN_ACTIVE
;
135 switch(m_flags
& wxRIBBON_SCROLL_BTN_DIRECTION_MASK
)
137 case wxRIBBON_SCROLL_BTN_DOWN
:
138 case wxRIBBON_SCROLL_BTN_RIGHT
:
139 m_sibling
->ScrollLines(1);
141 case wxRIBBON_SCROLL_BTN_UP
:
142 case wxRIBBON_SCROLL_BTN_LEFT
:
143 m_sibling
->ScrollLines(-1);
151 IMPLEMENT_CLASS(wxRibbonPage
, wxRibbonControl
)
153 BEGIN_EVENT_TABLE(wxRibbonPage
, wxRibbonControl
)
154 EVT_ERASE_BACKGROUND(wxRibbonPage::OnEraseBackground
)
155 EVT_PAINT(wxRibbonPage::OnPaint
)
156 EVT_SIZE(wxRibbonPage::OnSize
)
159 wxRibbonPage::wxRibbonPage()
161 m_scroll_left_btn
= NULL
;
162 m_scroll_right_btn
= NULL
;
164 m_scroll_buttons_visible
= false;
167 wxRibbonPage::wxRibbonPage(wxRibbonBar
* parent
,
169 const wxString
& label
,
170 const wxBitmap
& icon
,
171 long WXUNUSED(style
))
172 : wxRibbonControl(parent
, id
, wxDefaultPosition
, wxDefaultSize
, wxBORDER_NONE
)
174 CommonInit(label
, icon
);
177 wxRibbonPage::~wxRibbonPage()
179 delete[] m_size_calc_array
;
182 bool wxRibbonPage::Create(wxRibbonBar
* parent
,
184 const wxString
& label
,
185 const wxBitmap
& icon
,
186 long WXUNUSED(style
))
188 if(!wxRibbonControl::Create(parent
, id
, wxDefaultPosition
, wxDefaultSize
, wxBORDER_NONE
))
191 CommonInit(label
, icon
);
196 void wxRibbonPage::CommonInit(const wxString
& label
, const wxBitmap
& icon
)
201 m_old_size
= wxSize(0, 0);
203 m_scroll_left_btn
= NULL
;
204 m_scroll_right_btn
= NULL
;
205 m_size_calc_array
= NULL
;
206 m_size_calc_array_size
= 0;
208 m_scroll_buttons_visible
= false;
210 SetBackgroundStyle(wxBG_STYLE_CUSTOM
);
212 wxDynamicCast(GetParent(), wxRibbonBar
)->AddPage(this);
215 void wxRibbonPage::SetArtProvider(wxRibbonArtProvider
* art
)
218 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
220 node
= node
->GetNext() )
222 wxWindow
* child
= node
->GetData();
223 wxRibbonControl
* ribbon_child
= wxDynamicCast(child
, wxRibbonControl
);
226 ribbon_child
->SetArtProvider(art
);
231 void wxRibbonPage::AdjustRectToIncludeScrollButtons(wxRect
* rect
) const
233 if(m_scroll_buttons_visible
)
235 if(GetMajorAxis() == wxVERTICAL
)
237 if(m_scroll_left_btn
)
239 rect
->SetY(rect
->GetY() -
240 m_scroll_left_btn
->GetSize().GetHeight());
241 rect
->SetHeight(rect
->GetHeight() +
242 m_scroll_left_btn
->GetSize().GetHeight());
244 if(m_scroll_right_btn
)
246 rect
->SetHeight(rect
->GetHeight() +
247 m_scroll_right_btn
->GetSize().GetHeight());
252 if(m_scroll_left_btn
)
254 rect
->SetX(rect
->GetX() -
255 m_scroll_left_btn
->GetSize().GetWidth());
256 rect
->SetWidth(rect
->GetWidth() +
257 m_scroll_left_btn
->GetSize().GetWidth());
259 if(m_scroll_right_btn
)
261 rect
->SetWidth(rect
->GetWidth() +
262 m_scroll_right_btn
->GetSize().GetWidth());
268 void wxRibbonPage::OnEraseBackground(wxEraseEvent
& WXUNUSED(evt
))
270 // All painting done in main paint handler to minimise flicker
273 void wxRibbonPage::OnPaint(wxPaintEvent
& WXUNUSED(evt
))
275 // No foreground painting done by the page itself, but a paint DC
276 // must be created anyway.
277 wxAutoBufferedPaintDC
dc(this);
278 wxRect
rect(GetSize());
279 AdjustRectToIncludeScrollButtons(&rect
);
280 m_art
->DrawPageBackground(dc
, this, rect
);
283 wxOrientation
wxRibbonPage::GetMajorAxis() const
285 if(m_art
&& (m_art
->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL
))
295 bool wxRibbonPage::ScrollLines(int lines
)
297 return ScrollPixels(lines
* 8);
300 bool wxRibbonPage::ScrollPixels(int pixels
)
304 if(m_scroll_amount
== 0)
306 if(m_scroll_amount
< -pixels
)
307 pixels
= -m_scroll_amount
;
311 if(m_scroll_amount
== m_scroll_amount_limit
)
313 if(m_scroll_amount
+ pixels
> m_scroll_amount_limit
)
314 pixels
= m_scroll_amount_limit
- m_scroll_amount
;
319 m_scroll_amount
+= pixels
;
321 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
323 node
= node
->GetNext() )
325 wxWindow
* child
= node
->GetData();
327 child
->GetPosition(&x
, &y
);
328 if(GetMajorAxis() == wxHORIZONTAL
)
332 child
->SetPosition(wxPoint(x
, y
));
340 void wxRibbonPage::SetSizeWithScrollButtonAdjustment(int x
, int y
, int width
, int height
)
342 if(m_scroll_buttons_visible
)
344 if(GetMajorAxis() == wxHORIZONTAL
)
346 if(m_scroll_left_btn
)
348 int w
= m_scroll_left_btn
->GetSize().GetWidth();
349 m_scroll_left_btn
->SetPosition(wxPoint(x
, y
));
353 if(m_scroll_right_btn
)
355 int w
= m_scroll_right_btn
->GetSize().GetWidth();
357 m_scroll_right_btn
->SetPosition(wxPoint(x
+ width
, y
));
362 if(m_scroll_left_btn
)
364 int h
= m_scroll_left_btn
->GetSize().GetHeight();
365 m_scroll_left_btn
->SetPosition(wxPoint(x
, y
));
369 if(m_scroll_right_btn
)
371 int h
= m_scroll_right_btn
->GetSize().GetHeight();
373 m_scroll_right_btn
->SetPosition(wxPoint(x
, y
+ height
));
377 SetSize(x
, y
, width
, height
);
380 void wxRibbonPage::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
382 // When a resize triggers the scroll buttons to become visible, the page is resized.
383 // This resize from within a resize event can cause (MSW) wxWidgets some confusion,
384 // and report the 1st size to the 2nd size event. Hence the most recent size is
385 // remembered internally and used in Layout() where appropiate.
387 if(GetMajorAxis() == wxHORIZONTAL
)
389 m_size_in_major_axis_for_children
= width
;
390 if(m_scroll_buttons_visible
)
392 if(m_scroll_left_btn
)
393 m_size_in_major_axis_for_children
+= m_scroll_left_btn
->GetSize().GetWidth();
394 if(m_scroll_right_btn
)
395 m_size_in_major_axis_for_children
+= m_scroll_right_btn
->GetSize().GetWidth();
400 m_size_in_major_axis_for_children
= height
;
401 if(m_scroll_buttons_visible
)
403 if(m_scroll_left_btn
)
404 m_size_in_major_axis_for_children
+= m_scroll_left_btn
->GetSize().GetHeight();
405 if(m_scroll_right_btn
)
406 m_size_in_major_axis_for_children
+= m_scroll_right_btn
->GetSize().GetHeight();
410 wxRibbonControl::DoSetSize(x
, y
, width
, height
, sizeFlags
);
413 void wxRibbonPage::OnSize(wxSizeEvent
& evt
)
415 wxSize new_size
= evt
.GetSize();
418 wxRect invalid_rect
= m_art
->GetPageBackgroundRedrawArea(temp_dc
, this, m_old_size
, new_size
);
419 Refresh(true, &invalid_rect
);
421 m_old_size
= new_size
;
423 if(new_size
.GetX() > 0 && new_size
.GetY() > 0)
429 // Simplify other calculations by pretending new size is zero in both
432 // When size == 0, no point in doing any layout
438 void wxRibbonPage::RemoveChild(wxWindowBase
*child
)
440 // Remove all references to the child from the collapse stack
441 size_t count
= m_collapse_stack
.GetCount();
443 for(src
= 0, dst
= 0; src
< count
; ++src
, ++dst
)
445 wxRibbonControl
*item
= m_collapse_stack
.Item(src
);
456 m_collapse_stack
.Item(dst
) = item
;
461 m_collapse_stack
.RemoveAt(dst
, src
- dst
);
464 // ... and then proceed as normal
465 wxRibbonControl::RemoveChild(child
);
468 bool wxRibbonPage::Realize()
472 m_collapse_stack
.Clear();
473 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
475 node
= node
->GetNext())
477 wxRibbonControl
* child
= wxDynamicCast(node
->GetData(), wxRibbonControl
);
482 if(!child
->Realize())
487 PopulateSizeCalcArray(&wxWindow::GetMinSize
);
489 return DoActualLayout() && status
;
492 void wxRibbonPage::PopulateSizeCalcArray(wxSize (wxWindow::*get_size
)(void) const)
494 if(m_size_calc_array_size
!= GetChildren().GetCount())
496 delete[] m_size_calc_array
;
497 m_size_calc_array_size
= GetChildren().GetCount();
498 m_size_calc_array
= new wxSize
[m_size_calc_array_size
];
500 wxSize
* node_size
= m_size_calc_array
;
501 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
503 node
= node
->GetNext(), ++node_size
)
505 wxWindow
* child
= node
->GetData();
506 *node_size
= (child
->*get_size
)();
510 bool wxRibbonPage::Layout()
512 if(GetChildren().GetCount() == 0)
518 PopulateSizeCalcArray(&wxWindow::GetSize
);
519 return DoActualLayout();
523 bool wxRibbonPage::DoActualLayout()
525 wxPoint
origin(m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE
), m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE
));
526 wxOrientation major_axis
= GetMajorAxis();
530 if(major_axis
== wxHORIZONTAL
)
532 gap
= m_art
->GetMetric(wxRIBBON_ART_PANEL_X_SEPARATION_SIZE
);
533 minor_axis_size
= GetSize().GetHeight() - origin
.y
- m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE
);
534 available_space
= m_size_in_major_axis_for_children
- m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE
) - origin
.x
;
538 gap
= m_art
->GetMetric(wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE
);
539 minor_axis_size
= GetSize().GetWidth() - origin
.x
- m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE
);
540 available_space
= m_size_in_major_axis_for_children
- m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE
) - origin
.y
;
542 if (minor_axis_size
< 0) minor_axis_size
= 0;
544 for(size_index
= 0; size_index
< m_size_calc_array_size
; ++size_index
)
546 if(major_axis
== wxHORIZONTAL
)
548 available_space
-= m_size_calc_array
[size_index
].GetWidth();
549 m_size_calc_array
[size_index
].SetHeight(minor_axis_size
);
553 available_space
-= m_size_calc_array
[size_index
].GetHeight();
554 m_size_calc_array
[size_index
].SetWidth(minor_axis_size
);
557 available_space
-= gap
;
559 bool todo_hide_scroll_buttons
= false;
560 bool todo_show_scroll_buttons
= false;
561 if(available_space
>= 0)
563 if(m_scroll_buttons_visible
)
564 todo_hide_scroll_buttons
= true;
565 if(available_space
> 0)
566 ExpandPanels(major_axis
, available_space
);
570 if(m_scroll_buttons_visible
)
572 // Scroll buttons already visible - not going to be able to downsize any more
573 m_scroll_amount_limit
= -available_space
;
574 if(m_scroll_amount
> m_scroll_amount_limit
)
576 m_scroll_amount
= m_scroll_amount_limit
;
577 todo_show_scroll_buttons
= true;
582 if(!CollapsePanels(major_axis
, -available_space
))
585 m_scroll_amount_limit
= -available_space
;
586 todo_show_scroll_buttons
= true;
590 if(m_scroll_buttons_visible
)
592 if(major_axis
== wxHORIZONTAL
)
594 origin
.x
-= m_scroll_amount
;
595 if(m_scroll_left_btn
)
596 origin
.x
-= m_scroll_left_btn
->GetSize().GetWidth();
600 origin
.y
-= m_scroll_amount
;
601 if(m_scroll_left_btn
)
602 origin
.y
-= m_scroll_left_btn
->GetSize().GetHeight();
606 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
608 node
= node
->GetNext(), ++size_index
)
610 wxWindow
* child
= node
->GetData();
611 int w
= m_size_calc_array
[size_index
].GetWidth();
612 int h
= m_size_calc_array
[size_index
].GetHeight();
613 child
->SetSize(origin
.x
, origin
.y
, w
, h
);
614 if(major_axis
== wxHORIZONTAL
)
624 if(todo_show_scroll_buttons
)
626 else if(todo_hide_scroll_buttons
)
633 bool wxRibbonPage::Show(bool show
)
635 if(m_scroll_left_btn
)
636 m_scroll_left_btn
->Show(show
);
637 if(m_scroll_right_btn
)
638 m_scroll_right_btn
->Show(show
);
639 return wxRibbonControl::Show(show
);
642 void wxRibbonPage::HideScrollButtons()
645 m_scroll_amount_limit
= 0;
649 void wxRibbonPage::ShowScrollButtons()
651 bool show_left
= true;
652 bool show_right
= true;
653 bool reposition
= false;
654 if(m_scroll_amount
== 0)
658 if(m_scroll_amount
>= m_scroll_amount_limit
)
661 m_scroll_amount
= m_scroll_amount_limit
;
663 m_scroll_buttons_visible
= show_left
|| show_right
;
667 if(m_scroll_left_btn
== NULL
)
672 if(GetMajorAxis() == wxHORIZONTAL
)
674 direction
= wxRIBBON_SCROLL_BTN_LEFT
;
675 size
= m_art
->GetScrollButtonMinimumSize(temp_dc
, GetParent(), direction
);
676 size
.SetHeight(GetSize().GetHeight());
680 direction
= wxRIBBON_SCROLL_BTN_UP
;
681 size
= m_art
->GetScrollButtonMinimumSize(temp_dc
, GetParent(), direction
);
682 size
.SetWidth(GetSize().GetWidth());
684 m_scroll_left_btn
= new wxRibbonPageScrollButton(this, wxID_ANY
, GetPosition(), size
, direction
);
687 m_scroll_left_btn
->Hide();
694 if(m_scroll_left_btn
!= NULL
)
696 m_scroll_left_btn
->Destroy();
697 m_scroll_left_btn
= NULL
;
704 if(m_scroll_right_btn
== NULL
)
709 if(GetMajorAxis() == wxHORIZONTAL
)
711 direction
= wxRIBBON_SCROLL_BTN_RIGHT
;
712 size
= m_art
->GetScrollButtonMinimumSize(temp_dc
, GetParent(), direction
);
713 size
.SetHeight(GetSize().GetHeight());
717 direction
= wxRIBBON_SCROLL_BTN_DOWN
;
718 size
= m_art
->GetScrollButtonMinimumSize(temp_dc
, GetParent(), direction
);
719 size
.SetWidth(GetSize().GetWidth());
721 wxPoint initial_pos
= GetPosition() + GetSize() - size
;
722 m_scroll_right_btn
= new wxRibbonPageScrollButton(this, wxID_ANY
, initial_pos
, size
, direction
);
725 m_scroll_right_btn
->Hide();
732 if(m_scroll_right_btn
!= NULL
)
734 m_scroll_right_btn
->Destroy();
735 m_scroll_right_btn
= NULL
;
742 wxDynamicCast(GetParent(), wxRibbonBar
)->RepositionPage(this);
746 static int GetSizeInOrientation(wxSize size
, wxOrientation orientation
)
750 case wxHORIZONTAL
: return size
.GetWidth();
751 case wxVERTICAL
: return size
.GetHeight();
752 case wxBOTH
: return size
.GetWidth() * size
.GetHeight();
757 bool wxRibbonPage::ExpandPanels(wxOrientation direction
, int maximum_amount
)
759 bool expanded_something
= false;
760 while(maximum_amount
> 0)
762 int smallest_size
= INT_MAX
;
763 wxRibbonPanel
* smallest_panel
= NULL
;
764 wxSize
* smallest_panel_size
= NULL
;
765 wxSize
* panel_size
= m_size_calc_array
;
766 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
768 node
= node
->GetNext(), ++panel_size
)
770 wxRibbonPanel
* panel
= wxDynamicCast(node
->GetData(), wxRibbonPanel
);
775 if(panel
->IsSizingContinuous())
777 int size
= GetSizeInOrientation(*panel_size
, direction
);
778 if(size
< smallest_size
)
780 smallest_size
= size
;
781 smallest_panel
= panel
;
782 smallest_panel_size
= panel_size
;
787 int size
= GetSizeInOrientation(*panel_size
, direction
);
788 if(size
< smallest_size
)
790 wxSize larger
= panel
->GetNextLargerSize(direction
, *panel_size
);
791 if(larger
!= (*panel_size
) && GetSizeInOrientation(larger
, direction
) > size
)
793 smallest_size
= size
;
794 smallest_panel
= panel
;
795 smallest_panel_size
= panel_size
;
800 if(smallest_panel
!= NULL
)
802 if(smallest_panel
->IsSizingContinuous())
804 int amount
= maximum_amount
;
807 // For "large" growth, grow this panel a bit, and then re-allocate
808 // the remainder (which may come to this panel again anyway)
811 if(direction
& wxHORIZONTAL
)
813 smallest_panel_size
->x
+= amount
;
815 if(direction
& wxVERTICAL
)
817 smallest_panel_size
->y
+= amount
;
819 maximum_amount
-= amount
;
820 m_collapse_stack
.Add(smallest_panel
);
821 expanded_something
= true;
825 wxSize larger
= smallest_panel
->GetNextLargerSize(direction
, *smallest_panel_size
);
826 wxSize delta
= larger
- (*smallest_panel_size
);
827 if(GetSizeInOrientation(delta
, direction
) <= maximum_amount
)
829 *smallest_panel_size
= larger
;
830 maximum_amount
-= GetSizeInOrientation(delta
, direction
);
831 m_collapse_stack
.Add(smallest_panel
);
832 expanded_something
= true;
845 return expanded_something
;
848 bool wxRibbonPage::CollapsePanels(wxOrientation direction
, int minimum_amount
)
850 bool collapsed_something
= false;
851 while(minimum_amount
> 0)
853 int largest_size
= 0;
854 wxRibbonPanel
* largest_panel
= NULL
;
855 wxSize
* largest_panel_size
= NULL
;
856 wxSize
* panel_size
= m_size_calc_array
;
857 if(!m_collapse_stack
.IsEmpty())
859 // For a more consistent panel layout, try to collapse panels which
860 // were recently expanded.
861 largest_panel
= wxDynamicCast(m_collapse_stack
.Last(), wxRibbonPanel
);
862 m_collapse_stack
.RemoveAt(m_collapse_stack
.GetCount() - 1);
863 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
865 node
= node
->GetNext(), ++panel_size
)
867 wxRibbonPanel
* panel
= wxDynamicCast(node
->GetData(), wxRibbonPanel
);
868 if(panel
== largest_panel
)
870 largest_panel_size
= panel_size
;
877 for(wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
879 node
= node
->GetNext(), ++panel_size
)
881 wxRibbonPanel
* panel
= wxDynamicCast(node
->GetData(), wxRibbonPanel
);
886 if(panel
->IsSizingContinuous())
888 int size
= GetSizeInOrientation(*panel_size
, direction
);
889 if(size
> largest_size
)
892 largest_panel
= panel
;
893 largest_panel_size
= panel_size
;
898 int size
= GetSizeInOrientation(*panel_size
, direction
);
899 if(size
> largest_size
)
901 wxSize smaller
= panel
->GetNextSmallerSize(direction
, *panel_size
);
902 if(smaller
!= (*panel_size
) &&
903 GetSizeInOrientation(smaller
, direction
) < size
)
906 largest_panel
= panel
;
907 largest_panel_size
= panel_size
;
913 if(largest_panel
!= NULL
)
915 if(largest_panel
->IsSizingContinuous())
917 int amount
= minimum_amount
;
920 // For "large" contraction, reduce this panel a bit, and
921 // then re-allocate the remainder of the quota (which may
922 // come to this panel again anyway)
925 if(direction
& wxHORIZONTAL
)
927 largest_panel_size
->x
-= amount
;
929 if(direction
& wxVERTICAL
)
931 largest_panel_size
->y
-= amount
;
933 minimum_amount
-= amount
;
934 collapsed_something
= true;
938 wxSize smaller
= largest_panel
->GetNextSmallerSize(direction
, *largest_panel_size
);
939 wxSize delta
= (*largest_panel_size
) - smaller
;
940 *largest_panel_size
= smaller
;
941 minimum_amount
-= GetSizeInOrientation(delta
, direction
);
942 collapsed_something
= true;
950 return collapsed_something
;
953 bool wxRibbonPage::DismissExpandedPanel()
955 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
957 node
= node
->GetNext() )
959 wxRibbonPanel
* panel
= wxDynamicCast(node
->GetData(), wxRibbonPanel
);
964 if(panel
->GetExpandedPanel() != NULL
)
966 return panel
->HideExpanded();
972 wxSize
wxRibbonPage::GetMinSize() const
974 wxSize
min(wxDefaultCoord
, wxDefaultCoord
);
976 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
978 node
= node
->GetNext() )
980 wxWindow
* child
= node
->GetData();
981 wxSize
child_min(child
->GetMinSize());
983 min
.x
= wxMax(min
.x
, child_min
.x
);
984 min
.y
= wxMax(min
.y
, child_min
.y
);
987 if(GetMajorAxis() == wxHORIZONTAL
)
989 min
.x
= wxDefaultCoord
;
990 if(min
.y
!= wxDefaultCoord
)
992 min
.y
+= m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE
) + m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE
);
997 if(min
.x
!= wxDefaultCoord
)
999 min
.x
+= m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE
) + m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE
);
1001 min
.y
= wxDefaultCoord
;
1007 wxSize
wxRibbonPage::DoGetBestSize() const
1012 if(GetMajorAxis() == wxHORIZONTAL
)
1014 best
.y
= wxDefaultCoord
;
1016 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1018 node
= node
->GetNext() )
1020 wxWindow
* child
= node
->GetData();
1021 wxSize
child_best(child
->GetBestSize());
1023 if(child_best
.x
!= wxDefaultCoord
)
1025 best
.IncBy(child_best
.x
, 0);
1027 best
.y
= wxMax(best
.y
, child_best
.y
);
1034 best
.IncBy((count
- 1) * m_art
->GetMetric(wxRIBBON_ART_PANEL_X_SEPARATION_SIZE
), 0);
1039 best
.x
= wxDefaultCoord
;
1041 for ( wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
1043 node
= node
->GetNext() )
1045 wxWindow
* child
= node
->GetData();
1046 wxSize
child_best(child
->GetBestSize());
1048 best
.x
= wxMax(best
.x
, child_best
.x
);
1049 if(child_best
.y
!= wxDefaultCoord
)
1051 best
.IncBy(0, child_best
.y
);
1059 best
.IncBy(0, (count
- 1) * m_art
->GetMetric(wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE
));
1063 if(best
.x
!= wxDefaultCoord
)
1065 best
.x
+= m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE
) + m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE
);
1067 if(best
.y
!= wxDefaultCoord
)
1069 best
.y
+= m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE
) + m_art
->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE
);
1074 #endif // wxUSE_RIBBON