diff --git a/include/wx/ribbon/bar.h b/include/wx/ribbon/bar.h index 78c272a488..142e1bab3b 100644 --- a/include/wx/ribbon/bar.h +++ b/include/wx/ribbon/bar.h @@ -15,9 +15,13 @@ #if wxUSE_RIBBON +class WXDLLIMPEXP_FWD_CORE wxImageList; + #include "wx/ribbon/control.h" #include "wx/ribbon/page.h" +#include "wx/vector.h" + enum wxRibbonBarOption { wxRIBBON_BAR_SHOW_PAGE_LABELS = 1 << 0, @@ -152,6 +156,10 @@ public: void HideIfExpanded(); + // Return the image list containing images of the given size, creating it + // if necessary. + wxImageList* GetButtonImageList(wxSize size); + protected: friend class wxRibbonPage; @@ -208,6 +216,8 @@ protected: wxRibbonDisplayMode m_ribbon_state; + wxVector m_image_lists; + #ifndef SWIG wxDECLARE_CLASS(wxRibbonBar); wxDECLARE_EVENT_TABLE(); diff --git a/include/wx/ribbon/buttonbar.h b/include/wx/ribbon/buttonbar.h index bc54379261..a38d1fac07 100644 --- a/include/wx/ribbon/buttonbar.h +++ b/include/wx/ribbon/buttonbar.h @@ -190,13 +190,6 @@ protected: void TryCollapseLayout(wxRibbonButtonBarLayout* original, size_t first_btn, size_t* last_button, wxRibbonButtonBarButtonState target_size); - void MakeBitmaps(wxRibbonButtonBarButtonBase* base, - const wxBitmap& bitmap_large, - const wxBitmap& bitmap_large_disabled, - const wxBitmap& bitmap_small, - const wxBitmap& bitmap_small_disabled); - static wxBitmap MakeResizedBitmap(const wxBitmap& original, wxSize size); - static wxBitmap MakeDisabledBitmap(const wxBitmap& original); void FetchButtonSizeInfo(wxRibbonButtonBarButtonBase* button, wxRibbonButtonBarButtonState size, wxDC& dc); virtual void UpdateWindowUI(long flags) wxOVERRIDE; diff --git a/src/ribbon/bar.cpp b/src/ribbon/bar.cpp index bb53511cf5..df2d57e1e8 100644 --- a/src/ribbon/bar.cpp +++ b/src/ribbon/bar.cpp @@ -30,6 +30,7 @@ #endif #include "wx/arrimpl.cpp" +#include "wx/imaglist.h" WX_DEFINE_USER_EXPORTED_OBJARRAY(wxRibbonPageTabInfoArray) @@ -735,6 +736,7 @@ wxRibbonBar::wxRibbonBar() m_tab_scroll_buttons_shown = false; m_arePanelsShown = true; m_help_button_hovered = false; + } wxRibbonBar::wxRibbonBar(wxWindow* parent, @@ -750,6 +752,11 @@ wxRibbonBar::wxRibbonBar(wxWindow* parent, wxRibbonBar::~wxRibbonBar() { SetArtProvider(NULL); + + for ( size_t n = 0; n < m_image_lists.size(); ++n ) + { + delete m_image_lists[n]; + } } bool wxRibbonBar::Create(wxWindow* parent, @@ -800,6 +807,21 @@ void wxRibbonBar::CommonInit(long style) m_ribbon_state = wxRIBBON_BAR_PINNED; } +wxImageList* wxRibbonBar::GetButtonImageList(wxSize size) +{ + for ( size_t n = 0; n < m_image_lists.size(); ++n ) + { + if ( m_image_lists[n]->GetSize() == size ) + return m_image_lists[n]; + } + + wxImageList* const + il = new wxImageList(size.GetWidth(), size.GetHeight(), /*mask*/false); + m_image_lists.push_back(il); + + return il; +} + void wxRibbonBar::SetArtProvider(wxRibbonArtProvider* art) { wxRibbonArtProvider *old = m_art; diff --git a/src/ribbon/buttonbar.cpp b/src/ribbon/buttonbar.cpp index 17cbd00827..f4648c6a87 100644 --- a/src/ribbon/buttonbar.cpp +++ b/src/ribbon/buttonbar.cpp @@ -20,6 +20,7 @@ #include "wx/ribbon/buttonbar.h" #include "wx/ribbon/art.h" #include "wx/dcbuffer.h" +#include "wx/imaglist.h" #ifndef WX_PRECOMP #endif @@ -63,9 +64,112 @@ public: wxRibbonButtonBarButtonState size; }; +namespace +{ + +wxBitmap MakeResizedBitmap(const wxBitmap& original, wxSize size) +{ + double scale = original.GetScaleFactor(); + if (scale > 1.0) + scale = 2.0; + + wxImage img(original.ConvertToImage()); + img.Rescale(scale * size.GetWidth(), scale * size.GetHeight(), wxIMAGE_QUALITY_HIGH); + return wxBitmap(img, -1, scale); +} + +wxBitmap MakeDisabledBitmap(const wxBitmap& original) +{ + wxImage img(original.ConvertToImage()); + return wxBitmap(img.ConvertToGreyscale(), -1, original.GetScaleFactor()); +} + +} // anonymous namespace + class wxRibbonButtonBarButtonBase { public: + wxRibbonButtonBarButtonBase() + { + barButtonImageListPos = + barButtonSmallImageListPos = -1; + } + + void SetBitmaps(wxRibbonBar* ribbon, + wxSize bitmap_size_large, + wxSize bitmap_size_small, + wxBitmap bitmap_large, + wxBitmap bitmap_large_disabled, + wxBitmap bitmap_small, + wxBitmap bitmap_small_disabled) + { + if(!bitmap_large.IsOk()) + { + bitmap_large = MakeResizedBitmap(bitmap_small, bitmap_size_large); + } + else if(bitmap_large.GetScaledSize() != bitmap_size_large) + { + bitmap_large = MakeResizedBitmap(bitmap_large, bitmap_size_large); + } + + if(!bitmap_small.IsOk()) + { + bitmap_small = MakeResizedBitmap(bitmap_large, bitmap_size_small); + } + else if(bitmap_small.GetScaledSize() != bitmap_size_small) + { + bitmap_small = MakeResizedBitmap(bitmap_small, bitmap_size_small); + } + + if(!bitmap_large_disabled.IsOk()) + { + bitmap_large_disabled = MakeDisabledBitmap(bitmap_large); + } + + if(!bitmap_small_disabled.IsOk()) + { + bitmap_small_disabled = MakeDisabledBitmap(bitmap_small); + } + + if ( bitmap_large.IsOk() ) + { + wxImageList* const + buttonImageList = ribbon->GetButtonImageList(bitmap_size_large); + + barButtonImageListPos = buttonImageList->Add(bitmap_large); + buttonImageList->Add(bitmap_large_disabled); + } + + wxImageList* const + buttonSmallImageList = ribbon->GetButtonImageList(bitmap_size_small); + + barButtonSmallImageListPos = buttonSmallImageList->Add(bitmap_small); + buttonSmallImageList->Add(bitmap_small_disabled); + } + + void GetBitmaps(wxRibbonBar* ribbon, + wxSize bitmap_size_large, + wxSize bitmap_size_small, + wxBitmap& bitmap, + wxBitmap& bitmap_small) const + { + wxImageList* buttonImageList = ribbon->GetButtonImageList(bitmap_size_large); + wxImageList* buttonSmallImageList = ribbon->GetButtonImageList(bitmap_size_small); + + int pos = barButtonImageListPos; + int pos_small = barButtonSmallImageListPos; + + if (state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED) + { + // Disabled buttons are stored after the normal ones. + pos++; + pos_small++; + } + + bitmap = buttonImageList->GetBitmap(pos); + bitmap_small = buttonSmallImageList->GetBitmap(pos_small); + } + wxRibbonButtonBarButtonInstance NewInstance() { wxRibbonButtonBarButtonInstance i; @@ -122,11 +226,15 @@ public: wxString label; wxString help_string; - wxBitmap bitmap_large; - wxBitmap bitmap_large_disabled; - wxBitmap bitmap_small; - wxBitmap bitmap_small_disabled; wxCoord text_min_width[3]; + + // Index of the bitmap in the wxRibbonBar normal image list. Notice that + // the disabled bitmap is in the next position, so this one is always even. + int barButtonImageListPos; + + // Same thing for the small bitmap index in the small image list. + int barButtonSmallImageListPos; + wxRibbonButtonBarButtonSizeInfo sizes[3]; wxRibbonButtonBarButtonState min_size_class; wxRibbonButtonBarButtonState max_size_class; @@ -334,8 +442,8 @@ wxRibbonButtonBarButtonBase* wxRibbonButtonBar::InsertButton( wxRibbonButtonBarButtonBase* base = new wxRibbonButtonBarButtonBase; base->id = button_id; base->label = label; - MakeBitmaps(base, bitmap, bitmap_disabled, - bitmap_small, bitmap_small_disabled); + base->SetBitmaps(GetAncestorRibbonBar(), m_bitmap_size_large, m_bitmap_size_small, + bitmap, bitmap_disabled, bitmap_small, bitmap_small_disabled); base->kind = kind; base->help_string = help_string; base->state = 0; @@ -451,23 +559,6 @@ void wxRibbonButtonBar::FetchButtonSizeInfo(wxRibbonButtonBarButtonBase* button, info.is_supported = false; } -wxBitmap wxRibbonButtonBar::MakeResizedBitmap(const wxBitmap& original, wxSize size) -{ - double scale = original.GetScaleFactor(); - if (scale > 1.0) - scale = 2.0; - - wxImage img(original.ConvertToImage()); - img.Rescale(scale * size.GetWidth(), scale * size.GetHeight(), wxIMAGE_QUALITY_HIGH); - return wxBitmap(img, -1, scale); -} - -wxBitmap wxRibbonButtonBar::MakeDisabledBitmap(const wxBitmap& original) -{ - wxImage img(original.ConvertToImage()); - return wxBitmap(img.ConvertToGreyscale(), -1, original.GetScaleFactor()); -} - size_t wxRibbonButtonBar::GetButtonCount() const { return m_buttons.GetCount(); @@ -591,8 +682,8 @@ void wxRibbonButtonBar::SetButtonIcon( wxRibbonButtonBarButtonBase* base = GetItemById(button_id); if(base == NULL) return; - MakeBitmaps(base, bitmap, bitmap_small, - bitmap_disabled, bitmap_small_disabled); + base->SetBitmaps(GetAncestorRibbonBar(), m_bitmap_size_large, m_bitmap_size_small, + bitmap, bitmap_disabled, bitmap_small, bitmap_small_disabled); Refresh(); } @@ -845,25 +936,23 @@ void wxRibbonButtonBar::OnPaint(wxPaintEvent& WXUNUSED(evt)) wxRibbonButtonBarLayout* layout = m_layouts.Item(m_current_layout); + wxRibbonBar* const ribbon = GetAncestorRibbonBar(); + size_t btn_count = layout->buttons.Count(); size_t btn_i; for(btn_i = 0; btn_i < btn_count; ++btn_i) { wxRibbonButtonBarButtonInstance& button = layout->buttons.Item(btn_i); wxRibbonButtonBarButtonBase* base = button.base; - - wxBitmap* bitmap = &base->bitmap_large; - wxBitmap* bitmap_small = &base->bitmap_small; - if(base->state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED) - { - bitmap = &base->bitmap_large_disabled; - bitmap_small = &base->bitmap_small_disabled; - } wxRect rect(button.position + m_layout_offset, base->sizes[button.size].size); + wxBitmap bitmap, bitmap_small; + base->GetBitmaps(ribbon, + m_bitmap_size_large, m_bitmap_size_small, bitmap, + bitmap_small); m_art->DrawButtonBarButton(dc, this, rect, base->kind, - base->state | button.size, base->label, *bitmap, *bitmap_small); - } + base->state | button.size, base->label, bitmap, bitmap_small); + } } void wxRibbonButtonBar::OnSize(wxSizeEvent& evt) @@ -1161,46 +1250,6 @@ void wxRibbonButtonBar::TryCollapseLayout(wxRibbonButtonBarLayout* original, m_layouts.Add(layout); } -void wxRibbonButtonBar::MakeBitmaps(wxRibbonButtonBarButtonBase* base, - const wxBitmap& bitmap_large, - const wxBitmap& bitmap_large_disabled, - const wxBitmap& bitmap_small, - const wxBitmap& bitmap_small_disabled) -{ - base->bitmap_large = bitmap_large; - if(!base->bitmap_large.IsOk()) - { - base->bitmap_large = MakeResizedBitmap(base->bitmap_small, - m_bitmap_size_large); - } - else if(base->bitmap_large.GetScaledSize() != m_bitmap_size_large) - { - base->bitmap_large = MakeResizedBitmap(base->bitmap_large, - m_bitmap_size_large); - } - base->bitmap_small = bitmap_small; - if(!base->bitmap_small.IsOk()) - { - base->bitmap_small = MakeResizedBitmap(base->bitmap_large, - m_bitmap_size_small); - } - else if(base->bitmap_small.GetScaledSize() != m_bitmap_size_small) - { - base->bitmap_small = MakeResizedBitmap(base->bitmap_small, - m_bitmap_size_small); - } - base->bitmap_large_disabled = bitmap_large_disabled; - if(!base->bitmap_large_disabled.IsOk()) - { - base->bitmap_large_disabled = MakeDisabledBitmap(base->bitmap_large); - } - base->bitmap_small_disabled = bitmap_small_disabled; - if(!base->bitmap_small_disabled.IsOk()) - { - base->bitmap_small_disabled = MakeDisabledBitmap(base->bitmap_small); - } -} - void wxRibbonButtonBar::OnMouseMove(wxMouseEvent& evt) { wxPoint cursor(evt.GetPosition());