X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3c3ead1d1513a5eb79091a604f4e42b45d1bdf5d..07aaf32633ecf18ec3edfbb41793a112914792d0:/src/ribbon/page.cpp diff --git a/src/ribbon/page.cpp b/src/ribbon/page.cpp index 812d0da69c..0fecb1c0a2 100644 --- a/src/ribbon/page.cpp +++ b/src/ribbon/page.cpp @@ -14,10 +14,9 @@ #pragma hdrstop #endif -#include "wx/ribbon/page.h" - #if wxUSE_RIBBON +#include "wx/ribbon/page.h" #include "wx/ribbon/art.h" #include "wx/ribbon/bar.h" #include "wx/dcbuffer.h" @@ -176,6 +175,7 @@ wxRibbonPage::wxRibbonPage(wxRibbonBar* parent, wxRibbonPage::~wxRibbonPage() { + delete[] m_size_calc_array; } bool wxRibbonPage::Create(wxRibbonBar* parent, @@ -201,6 +201,8 @@ void wxRibbonPage::CommonInit(const wxString& label, const wxBitmap& icon) m_icon = icon; m_scroll_left_btn = NULL; m_scroll_right_btn = NULL; + m_size_calc_array = NULL; + m_size_calc_array_size = 0; m_scroll_amount = 0; m_scroll_buttons_visible = false; @@ -371,6 +373,8 @@ void wxRibbonPage::SetSizeWithScrollButtonAdjustment(int x, int y, int width, in } } } + if (width < 0) width = 0; + if (height < 0) height = 0; SetSize(x, y, width, height); } @@ -379,12 +383,30 @@ void wxRibbonPage::DoSetSize(int x, int y, int width, int height, int sizeFlags) // When a resize triggers the scroll buttons to become visible, the page is resized. // This resize from within a resize event can cause (MSW) wxWidgets some confusion, // and report the 1st size to the 2nd size event. Hence the most recent size is - // remembered internally and used in Layout() where appropiate. + // remembered internally and used in Layout() where appropriate. if(GetMajorAxis() == wxHORIZONTAL) + { m_size_in_major_axis_for_children = width; + if(m_scroll_buttons_visible) + { + if(m_scroll_left_btn) + m_size_in_major_axis_for_children += m_scroll_left_btn->GetSize().GetWidth(); + if(m_scroll_right_btn) + m_size_in_major_axis_for_children += m_scroll_right_btn->GetSize().GetWidth(); + } + } else + { m_size_in_major_axis_for_children = height; + if(m_scroll_buttons_visible) + { + if(m_scroll_left_btn) + m_size_in_major_axis_for_children += m_scroll_left_btn->GetSize().GetHeight(); + if(m_scroll_right_btn) + m_size_in_major_axis_for_children += m_scroll_right_btn->GetSize().GetHeight(); + } + } wxRibbonControl::DoSetSize(x, y, width, height, sizeFlags); } @@ -393,9 +415,12 @@ void wxRibbonPage::OnSize(wxSizeEvent& evt) { wxSize new_size = evt.GetSize(); - wxMemoryDC temp_dc; - wxRect invalid_rect = m_art->GetPageBackgroundRedrawArea(temp_dc, this, m_old_size, new_size); - Refresh(true, &invalid_rect); + if (m_art) + { + wxMemoryDC temp_dc; + wxRect invalid_rect = m_art->GetPageBackgroundRedrawArea(temp_dc, this, m_old_size, new_size); + Refresh(true, &invalid_rect); + } m_old_size = new_size; @@ -462,15 +487,39 @@ bool wxRibbonPage::Realize() { status = false; } - child->SetSize(child->GetMinSize()); } + PopulateSizeCalcArray(&wxWindow::GetMinSize); - if(GetSize().GetX() > 0 && GetSize().GetY() > 0) + return DoActualLayout() && status; +} + +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()) { - status = Layout() && status; + delete[] m_size_calc_array; + m_size_calc_array_size = GetChildren().GetCount(); + m_size_calc_array = new wxSize[m_size_calc_array_size]; } - return status; + 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)(); + } } bool wxRibbonPage::Layout() @@ -479,112 +528,122 @@ bool wxRibbonPage::Layout() { return true; } - - wxPoint origin_(m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE), m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE)); - wxOrientation major_axis = GetMajorAxis(); - if(m_scroll_buttons_visible) + else { - if(major_axis == wxHORIZONTAL) - { - origin_.x -= m_scroll_amount; - if(m_scroll_left_btn) - origin_.x -= m_scroll_left_btn->GetSize().GetWidth(); - } - else - { - origin_.y -= m_scroll_amount; - if(m_scroll_left_btn) - origin_.y -= m_scroll_left_btn->GetSize().GetHeight(); - } + PopulateSizeCalcArray(&wxWindow::GetSize); + return DoActualLayout(); } - wxPoint origin(origin_); +} + +bool wxRibbonPage::DoActualLayout() +{ + wxPoint origin(m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_LEFT_SIZE), m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_TOP_SIZE)); + wxOrientation major_axis = GetMajorAxis(); int gap; int minor_axis_size; + int available_space; if(major_axis == wxHORIZONTAL) { gap = m_art->GetMetric(wxRIBBON_ART_PANEL_X_SEPARATION_SIZE); minor_axis_size = GetSize().GetHeight() - origin.y - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE); + available_space = m_size_in_major_axis_for_children - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE) - origin.x; } else { gap = m_art->GetMetric(wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE); minor_axis_size = GetSize().GetWidth() - origin.x - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE); + available_space = m_size_in_major_axis_for_children - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE) - origin.y; } - - for(int iteration = 1; iteration <= 2; ++iteration) + if (minor_axis_size < 0) minor_axis_size = 0; + size_t size_index; + for(size_index = 0; size_index < m_size_calc_array_size; ++size_index) { - for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - node; - node = node->GetNext() ) + if(major_axis == wxHORIZONTAL) { - wxWindow* child = node->GetData(); - int w, h; - child->GetSize(&w, &h); - if(major_axis == wxHORIZONTAL) - { - child->SetSize(origin.x, origin.y, w, minor_axis_size); - origin.x += w + gap; - } - else - { - child->SetSize(origin.x, origin.y, minor_axis_size, h); - origin.y += h + gap; - } + available_space -= m_size_calc_array[size_index].GetWidth(); + m_size_calc_array[size_index].SetHeight(minor_axis_size); } - if(iteration == 1) + else { - int available_space; - if(major_axis == wxHORIZONTAL) - available_space = m_size_in_major_axis_for_children - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_RIGHT_SIZE) - origin.x + gap; - else - available_space = m_size_in_major_axis_for_children - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE) - origin.y + gap; - if(m_scroll_buttons_visible) - { - available_space -= m_scroll_amount; - if(m_scroll_right_btn != NULL) - available_space += GetSizeInOrientation(m_scroll_right_btn->GetSize(), major_axis); - } - if(available_space > 0) - { - if(m_scroll_buttons_visible) - { - HideScrollButtons(); - break; - } - - if(!ExpandPanels(major_axis, available_space)) - break; - } - else if(available_space < 0) + available_space -= m_size_calc_array[size_index].GetHeight(); + m_size_calc_array[size_index].SetWidth(minor_axis_size); + } + if(size_index != 0) + available_space -= gap; + } + bool todo_hide_scroll_buttons = false; + bool todo_show_scroll_buttons = false; + if(available_space >= 0) + { + if(m_scroll_buttons_visible) + todo_hide_scroll_buttons = true; + if(available_space > 0) + ExpandPanels(major_axis, available_space); + } + else + { + if(m_scroll_buttons_visible) + { + // Scroll buttons already visible - not going to be able to downsize any more + m_scroll_amount_limit = -available_space; + if(m_scroll_amount > m_scroll_amount_limit) { - if(m_scroll_buttons_visible) - { - // Scroll buttons already visible - not going to be able to downsize any more - m_scroll_amount_limit = -available_space; - if(m_scroll_amount > m_scroll_amount_limit) - { - ScrollPixels(m_scroll_amount_limit - m_scroll_amount); - } - } - else - { - if(!CollapsePanels(major_axis, -available_space)) - { - m_scroll_amount = 0; - m_scroll_amount_limit = -available_space; - ShowScrollButtons(); - break; - } - } + m_scroll_amount = m_scroll_amount_limit; + todo_show_scroll_buttons = true; } - else + } + else + { + if(!CollapsePanels(major_axis, -available_space)) { - break; + m_scroll_amount = 0; + m_scroll_amount_limit = -available_space; + todo_show_scroll_buttons = true; } - origin = origin_; // Reset the origin } } + if(m_scroll_buttons_visible) + { + if(major_axis == wxHORIZONTAL) + { + origin.x -= m_scroll_amount; + if(m_scroll_left_btn) + origin.x -= m_scroll_left_btn->GetSize().GetWidth(); + } + else + { + origin.y -= m_scroll_amount; + if(m_scroll_left_btn) + origin.y -= m_scroll_left_btn->GetSize().GetHeight(); + } + } + size_index = 0; + for(wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext(), ++size_index ) + { + wxWindow* child = node->GetData(); + int w = m_size_calc_array[size_index].GetWidth(); + int h = m_size_calc_array[size_index].GetHeight(); + child->SetSize(origin.x, origin.y, w, h); + if(major_axis == wxHORIZONTAL) + { + origin.x += w + gap; + } + else + { + origin.y += h + gap; + } + } + + if(todo_show_scroll_buttons) + ShowScrollButtons(); + else if(todo_hide_scroll_buttons) + HideScrollButtons(); + else if(m_scroll_buttons_visible) + ShowScrollButtons(); + Refresh(); return true; } @@ -622,29 +681,33 @@ void wxRibbonPage::ShowScrollButtons() if(show_left) { - if(m_scroll_left_btn == NULL) + wxMemoryDC temp_dc; + wxSize size; + long direction; + if(GetMajorAxis() == wxHORIZONTAL) { - wxMemoryDC temp_dc; - wxSize size; - long direction; - if(GetMajorAxis() == wxHORIZONTAL) - { - direction = wxRIBBON_SCROLL_BTN_LEFT; - size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); - size.SetHeight(GetSize().GetHeight()); - } - else - { - direction = wxRIBBON_SCROLL_BTN_UP; - size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); - size.SetWidth(GetSize().GetWidth()); - } - m_scroll_left_btn = new wxRibbonPageScrollButton(this, wxID_ANY, GetPosition(), size, direction); - if(!IsShown()) - { - m_scroll_left_btn->Hide(); - } - reposition = true; + direction = wxRIBBON_SCROLL_BTN_LEFT; + size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); + size.SetHeight(GetSize().GetHeight()); + } + else + { + direction = wxRIBBON_SCROLL_BTN_UP; + size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); + size.SetWidth(GetSize().GetWidth()); + } + if (m_scroll_left_btn) + { + m_scroll_left_btn->SetSize(size); + } + else + { + m_scroll_left_btn = new wxRibbonPageScrollButton(this, wxID_ANY, GetPosition(), size, direction); + reposition = true; + } + if(!IsShown()) + { + m_scroll_left_btn->Hide(); } } else @@ -659,30 +722,34 @@ void wxRibbonPage::ShowScrollButtons() if(show_right) { - if(m_scroll_right_btn == NULL) + wxMemoryDC temp_dc; + wxSize size; + long direction; + if(GetMajorAxis() == wxHORIZONTAL) { - wxMemoryDC temp_dc; - wxSize size; - long direction; - if(GetMajorAxis() == wxHORIZONTAL) - { - direction = wxRIBBON_SCROLL_BTN_RIGHT; - size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); - size.SetHeight(GetSize().GetHeight()); - } - else - { - direction = wxRIBBON_SCROLL_BTN_DOWN; - size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); - size.SetWidth(GetSize().GetWidth()); - } - wxPoint initial_pos = GetPosition() + GetSize() - size; - m_scroll_right_btn = new wxRibbonPageScrollButton(this, wxID_ANY, initial_pos, size, direction); - if(!IsShown()) - { - m_scroll_right_btn->Hide(); - } - reposition = true; + direction = wxRIBBON_SCROLL_BTN_RIGHT; + size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); + size.SetHeight(GetSize().GetHeight()); + } + else + { + direction = wxRIBBON_SCROLL_BTN_DOWN; + size = m_art->GetScrollButtonMinimumSize(temp_dc, GetParent(), direction); + size.SetWidth(GetSize().GetWidth()); + } + wxPoint initial_pos = GetPosition() + GetSize() - size; + if (m_scroll_right_btn) + { + m_scroll_right_btn->SetSize(size); + } + else + { + m_scroll_right_btn = new wxRibbonPageScrollButton(this, wxID_ANY, initial_pos, size, direction); + reposition = true; + } + if(!IsShown()) + { + m_scroll_right_btn->Hide(); } } else @@ -719,35 +786,43 @@ bool wxRibbonPage::ExpandPanels(wxOrientation direction, int maximum_amount) { int smallest_size = INT_MAX; wxRibbonPanel* smallest_panel = NULL; + wxSize* smallest_panel_size = NULL; + wxSize* panel_size = m_size_calc_array; for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; - node = node->GetNext() ) + node = node->GetNext(), ++panel_size ) { wxRibbonPanel* panel = wxDynamicCast(node->GetData(), wxRibbonPanel); if(panel == NULL) { continue; } - if(panel->IsSizingContinuous()) + if (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE) { - int size = GetSizeInOrientation(panel->GetSize(), direction); + // 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) { smallest_size = size; smallest_panel = panel; + smallest_panel_size = panel_size; } } else { - wxSize current = panel->GetSize(); - int size = GetSizeInOrientation(current, direction); + int size = GetSizeInOrientation(*panel_size, direction); if(size < smallest_size) { - wxSize larger = panel->GetNextLargerSize(direction); - if(larger != current && GetSizeInOrientation(larger, direction) > size) + wxSize larger = panel->GetNextLargerSize(direction, *panel_size); + if(larger != (*panel_size) && GetSizeInOrientation(larger, direction) > size) { smallest_size = size; smallest_panel = panel; + smallest_panel_size = panel_size; } } } @@ -756,7 +831,6 @@ bool wxRibbonPage::ExpandPanels(wxOrientation direction, int maximum_amount) { if(smallest_panel->IsSizingContinuous()) { - wxSize size = smallest_panel->GetSize(); int amount = maximum_amount; if(amount > 32) { @@ -766,25 +840,23 @@ bool wxRibbonPage::ExpandPanels(wxOrientation direction, int maximum_amount) } if(direction & wxHORIZONTAL) { - size.x += amount; + smallest_panel_size->x += amount; } if(direction & wxVERTICAL) { - size.y += amount; + smallest_panel_size->y += amount; } - smallest_panel->SetSize(size); maximum_amount -= amount; m_collapse_stack.Add(smallest_panel); expanded_something = true; } else { - wxSize current = smallest_panel->GetSize(); - wxSize larger = smallest_panel->GetNextLargerSize(direction); - wxSize delta = larger - current; + wxSize larger = smallest_panel->GetNextLargerSize(direction, *smallest_panel_size); + wxSize delta = larger - (*smallest_panel_size); if(GetSizeInOrientation(delta, direction) <= maximum_amount) { - smallest_panel->SetSize(larger); + *smallest_panel_size = larger; maximum_amount -= GetSizeInOrientation(delta, direction); m_collapse_stack.Add(smallest_panel); expanded_something = true; @@ -800,15 +872,7 @@ bool wxRibbonPage::ExpandPanels(wxOrientation direction, int maximum_amount) break; } } - if(expanded_something) - { - Refresh(); - return true; - } - else - { - return false; - } + return expanded_something; } bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) @@ -818,18 +882,31 @@ bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) { int largest_size = 0; wxRibbonPanel* largest_panel = NULL; + wxSize* largest_panel_size = NULL; + wxSize* panel_size = m_size_calc_array; if(!m_collapse_stack.IsEmpty()) { // For a more consistent panel layout, try to collapse panels which // were recently expanded. largest_panel = wxDynamicCast(m_collapse_stack.Last(), wxRibbonPanel); m_collapse_stack.RemoveAt(m_collapse_stack.GetCount() - 1); + for(wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext(), ++panel_size ) + { + wxRibbonPanel* panel = wxDynamicCast(node->GetData(), wxRibbonPanel); + if(panel == largest_panel) + { + largest_panel_size = panel_size; + break; + } + } } else { for(wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; - node = node->GetNext() ) + node = node->GetNext(), ++panel_size ) { wxRibbonPanel* panel = wxDynamicCast(node->GetData(), wxRibbonPanel); if(panel == NULL) @@ -838,25 +915,26 @@ bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) } if(panel->IsSizingContinuous()) { - int size = GetSizeInOrientation(panel->GetSize(), direction); + int size = GetSizeInOrientation(*panel_size, direction); if(size > largest_size) { largest_size = size; largest_panel = panel; + largest_panel_size = panel_size; } } else { - wxSize current = panel->GetSize(); - int size = GetSizeInOrientation(current, direction); + int size = GetSizeInOrientation(*panel_size, direction); if(size > largest_size) { - wxSize smaller = panel->GetNextSmallerSize(direction); - if(smaller != current && + wxSize smaller = panel->GetNextSmallerSize(direction, *panel_size); + if(smaller != (*panel_size) && GetSizeInOrientation(smaller, direction) < size) { largest_size = size; largest_panel = panel; + largest_panel_size = panel_size; } } } @@ -866,7 +944,6 @@ bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) { if(largest_panel->IsSizingContinuous()) { - wxSize size = largest_panel->GetSize(); int amount = minimum_amount; if(amount > 32) { @@ -877,22 +954,20 @@ bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) } if(direction & wxHORIZONTAL) { - size.x -= amount; + largest_panel_size->x -= amount; } if(direction & wxVERTICAL) { - size.y -= amount; + largest_panel_size->y -= amount; } - largest_panel->SetSize(size); minimum_amount -= amount; collapsed_something = true; } else { - wxSize current = largest_panel->GetSize(); - wxSize smaller = largest_panel->GetNextSmallerSize(direction); - wxSize delta = current - smaller; - largest_panel->SetSize(smaller); + wxSize smaller = largest_panel->GetNextSmallerSize(direction, *largest_panel_size); + wxSize delta = (*largest_panel_size) - smaller; + *largest_panel_size = smaller; minimum_amount -= GetSizeInOrientation(delta, direction); collapsed_something = true; } @@ -902,15 +977,7 @@ bool wxRibbonPage::CollapsePanels(wxOrientation direction, int minimum_amount) break; } } - if(collapsed_something) - { - Refresh(); - return true; - } - else - { - return false; - } + return collapsed_something; } bool wxRibbonPage::DismissExpandedPanel() @@ -1034,4 +1101,9 @@ wxSize wxRibbonPage::DoGetBestSize() const return best; } +void wxRibbonPage::HideIfExpanded() +{ + wxStaticCast(m_parent, wxRibbonBar)->HideIfExpanded(); +} + #endif // wxUSE_RIBBON