Optionally support using wxImageList in wxRibbonBar

This allows to avoid consuming too many bitmap resources.

Closes #18657.
This commit is contained in:
wxBen
2020-02-07 17:25:34 +01:00
committed by Vadim Zeitlin
parent 249e5add7e
commit 23ebbb139d
5 changed files with 146 additions and 11 deletions

View File

@@ -15,6 +15,8 @@
#if wxUSE_RIBBON
class wxImageList;
#include "wx/ribbon/control.h"
#include "wx/ribbon/page.h"
@@ -152,6 +154,13 @@ public:
void HideIfExpanded();
void UseImageList(bool useImageList = true) { m_useImageList = useImageList; }
bool UsesImageList() const { return m_useImageList; }
// Implementation only.
wxImageList* GetButtonImageList(wxSize* isize = NULL);
// Implementation only.
wxImageList* GetButtonSmallImageList(wxSize* isize = NULL);
protected:
friend class wxRibbonPage;
@@ -208,6 +217,10 @@ protected:
wxRibbonDisplayMode m_ribbon_state;
bool m_useImageList;
wxImageList* m_buttonImageList;
wxImageList* m_buttonSmallImageList;
#ifndef SWIG
wxDECLARE_CLASS(wxRibbonBar);
wxDECLARE_EVENT_TABLE();

View File

@@ -213,6 +213,7 @@ protected:
bool m_layouts_valid;
bool m_lock_active_state;
bool m_show_tooltips_for_disabled;
wxRibbonBar* m_ownerRibbonBar;
#ifndef SWIG
wxDECLARE_CLASS(wxRibbonButtonBar);

View File

@@ -453,4 +453,26 @@ public:
Also calls wxRibbonPage::Realize() on each child page.
*/
virtual bool Realize();
/**
If the ribbon bar has many buttons, wxImageList can be used to reduce
bitmap resources. Call SetUseImageList after creating the ribbon bar,
and any subsequent AddButton or InsertButton calls will have their
images stored in an image list instead. Note that the conversion might
cause some images created from icons with alpha layers to have a black
background. Such images need to be edited before use.
@since 3.1.4
*/
void UseImageList(bool useImageList = true);
/**
Returns whether a wxImageList is being used for buttons.
@see SetUseImageList()
@since 3.1.4
*/
bool UsesImageList() const;
};

View File

@@ -30,6 +30,7 @@
#endif
#include "wx/arrimpl.cpp"
#include "wx/imaglist.h"
WX_DEFINE_USER_EXPORTED_OBJARRAY(wxRibbonPageTabInfoArray)
@@ -735,6 +736,10 @@ wxRibbonBar::wxRibbonBar()
m_tab_scroll_buttons_shown = false;
m_arePanelsShown = true;
m_help_button_hovered = false;
m_useImageList = false;
m_buttonImageList = NULL;
m_buttonSmallImageList = NULL;
}
wxRibbonBar::wxRibbonBar(wxWindow* parent,
@@ -750,6 +755,14 @@ wxRibbonBar::wxRibbonBar(wxWindow* parent,
wxRibbonBar::~wxRibbonBar()
{
SetArtProvider(NULL);
if (m_buttonImageList)
{
delete m_buttonImageList; m_buttonImageList = NULL;
}
if (m_buttonSmallImageList)
{
delete m_buttonSmallImageList; m_buttonSmallImageList = NULL;
}
}
bool wxRibbonBar::Create(wxWindow* parent,
@@ -798,6 +811,28 @@ void wxRibbonBar::CommonInit(long style)
m_bar_hovered = false;
m_ribbon_state = wxRIBBON_BAR_PINNED;
m_useImageList = false;
m_buttonImageList = NULL;
m_buttonSmallImageList = NULL;
}
wxImageList* wxRibbonBar::GetButtonImageList(wxSize* isize)
{
if (m_useImageList && m_buttonImageList == NULL)
{
m_buttonImageList = new wxImageList(isize->GetWidth(), isize->GetHeight(), /*mask*/false);
}
return m_buttonImageList;
}
wxImageList* wxRibbonBar::GetButtonSmallImageList(wxSize* isize)
{
if (m_useImageList && m_buttonSmallImageList == NULL)
{
m_buttonSmallImageList = new wxImageList(isize->GetWidth(), isize->GetHeight(), /*mask*/false);
}
return m_buttonSmallImageList;
}
void wxRibbonBar::SetArtProvider(wxRibbonArtProvider* art)

View File

@@ -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
@@ -127,6 +128,8 @@ public:
wxBitmap bitmap_small;
wxBitmap bitmap_small_disabled;
wxCoord text_min_width[3];
wxCoord barButtonImageListPos;
int barButtonSmallImageListPos;
wxRibbonButtonBarButtonSizeInfo sizes[3];
wxRibbonButtonBarButtonState min_size_class;
wxRibbonButtonBarButtonState max_size_class;
@@ -345,6 +348,31 @@ wxRibbonButtonBarButtonBase* wxRibbonButtonBar::InsertButton(
base->min_size_class = wxRIBBON_BUTTONBAR_BUTTON_SMALL;
base->max_size_class = wxRIBBON_BUTTONBAR_BUTTON_LARGE;
wxImageList* buttonImageList = NULL;
wxImageList* buttonSmallImageList = NULL;
if (m_ownerRibbonBar)
{
buttonImageList = m_ownerRibbonBar->GetButtonImageList(&m_bitmap_size_large);
buttonSmallImageList = m_ownerRibbonBar->GetButtonSmallImageList(&m_bitmap_size_small);
}
if (base->bitmap_large.IsOk() && buttonImageList)
{
base->barButtonImageListPos = buttonImageList->Add(base->bitmap_large);
base->bitmap_large = wxNullBitmap;
buttonImageList->Add(base->bitmap_large_disabled);
base->bitmap_large_disabled = wxNullBitmap;
base->barButtonSmallImageListPos = buttonSmallImageList->Add(base->bitmap_small);
base->bitmap_small = wxNullBitmap;
buttonSmallImageList->Add(base->bitmap_small_disabled);
base->bitmap_small_disabled = wxNullBitmap;
}
else
{
base->barButtonImageListPos = -1;
base->barButtonSmallImageListPos = -1;
}
wxClientDC temp_dc(this);
FetchButtonSizeInfo(base, wxRIBBON_BUTTONBAR_BUTTON_SMALL, temp_dc);
FetchButtonSizeInfo(base, wxRIBBON_BUTTONBAR_BUTTON_MEDIUM, temp_dc);
@@ -851,7 +879,29 @@ void wxRibbonButtonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
wxRibbonButtonBarButtonInstance& button = layout->buttons.Item(btn_i);
wxRibbonButtonBarButtonBase* base = button.base;
wxRect rect(button.position + m_layout_offset, base->sizes[button.size].size);
if (base->barButtonImageListPos != -1 && m_ownerRibbonBar)
{
wxImageList* buttonImageList = m_ownerRibbonBar->GetButtonImageList();
wxImageList* buttonSmallImageList = m_ownerRibbonBar->GetButtonSmallImageList();
wxBitmap bitmap;
wxBitmap bitmap_small;
if (base->state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED)
{
bitmap = buttonImageList->GetBitmap(base->barButtonImageListPos+1);
bitmap_small = buttonSmallImageList->GetBitmap(base->barButtonSmallImageListPos+1);
}
else
{
bitmap = buttonImageList->GetBitmap(base->barButtonImageListPos);
bitmap_small = buttonSmallImageList->GetBitmap(base->barButtonSmallImageListPos);
}
m_art->DrawButtonBarButton(dc, this, rect, base->kind,
base->state | button.size, base->label, bitmap, bitmap_small);
}
else
{
wxBitmap* bitmap = &base->bitmap_large;
wxBitmap* bitmap_small = &base->bitmap_small;
if(base->state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED)
@@ -859,11 +909,11 @@ void wxRibbonButtonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
bitmap = &base->bitmap_large_disabled;
bitmap_small = &base->bitmap_small_disabled;
}
wxRect rect(button.position + m_layout_offset, base->sizes[button.size].size);
m_art->DrawButtonBarButton(dc, this, rect, base->kind,
base->state | button.size, base->label, *bitmap, *bitmap_small);
}
}
}
void wxRibbonButtonBar::OnSize(wxSizeEvent& evt)
@@ -889,6 +939,20 @@ void wxRibbonButtonBar::OnSize(wxSizeEvent& evt)
void wxRibbonButtonBar::CommonInit(long WXUNUSED(style))
{
//Our ultimate parent MAY be a ribbon bar, in which case
//we can use its image list.
m_ownerRibbonBar = NULL;
wxWindow* pWin = GetParent();
while (pWin)
{
m_ownerRibbonBar = dynamic_cast<wxRibbonBar*>(pWin);
if (m_ownerRibbonBar)
{
break;
}
pWin = pWin->GetParent();
}
m_bitmap_size_large = wxSize(32, 32);
m_bitmap_size_small = wxSize(16, 16);