Allow using wxBitmapBundle for wxButton bitmaps
Take wxBitmapBundle in wxButton::SetBitmapLabel() and related functions in order to be able to associate several bitmaps to be used in different resolutions with the button, instead of just a single bitmap.
This commit is contained in:
@@ -97,18 +97,17 @@ extern wxWindowMSW *wxWindowBeingErased; // From src/msw/window.cpp
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// we use different data classes for owner drawn buttons and for themed XP ones
|
||||
//
|
||||
// Each class stores the bitmap bundles possibly containing images of multiple
|
||||
// sizes, but only stores bitmaps of the specific size used by the button right
|
||||
// now.
|
||||
|
||||
class wxButtonImageData: public wxObject
|
||||
{
|
||||
public:
|
||||
wxButtonImageData()
|
||||
explicit wxButtonImageData(const wxSize& bitmapSize)
|
||||
: m_bitmapSize(bitmapSize)
|
||||
{
|
||||
for ( int n = 0; n < wxAnyButton::State_Max; ++n )
|
||||
{
|
||||
// The normal bitmap is always set explicitly when the image data
|
||||
// is created, but the others ones are not (yet).
|
||||
m_bitmapSetExplicitly[n] = n == wxAnyButton::State_Normal;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~wxButtonImageData() { }
|
||||
@@ -117,30 +116,42 @@ public:
|
||||
// is specified by the application, or implicitly, when the bitmap for some
|
||||
// state is set as a side effect of setting another bitmap.
|
||||
//
|
||||
// These functions check the flags stored in the base class remembering
|
||||
// whether each bitmap is implicit or explicit and behave accordingly.
|
||||
wxBitmap GetExplicitBitmap(wxAnyButton::State which) const
|
||||
// When setting a bitmap explicitly, we update the entire bundle, while
|
||||
// setting it implicitly only updates the currently used bitmap.
|
||||
wxBitmapBundle GetBitmapBundle(wxAnyButton::State which) const
|
||||
{
|
||||
return m_bitmapSetExplicitly[which] ? GetBitmap(which) : wxBitmap();
|
||||
return m_bitmapBundles[which];
|
||||
}
|
||||
|
||||
void SetExplicitBitmap(const wxBitmap& bitmap, wxAnyButton::State which)
|
||||
void SetBitmapBundle(const wxBitmapBundle& bitmapBundle, wxAnyButton::State which)
|
||||
{
|
||||
SetBitmap(bitmap, which);
|
||||
m_bitmapSetExplicitly[which] = true;
|
||||
m_bitmapBundles[which] = bitmapBundle;
|
||||
|
||||
SetBitmapFromBundle(bitmapBundle, which);
|
||||
}
|
||||
|
||||
wxBitmap GetImplicitBitmap(wxAnyButton::State which) const
|
||||
// Actually get or update the bitmap being currently used (even if it is
|
||||
// used implicitly, i.e. as consequence of setting a bitmap for another
|
||||
// state).
|
||||
virtual wxBitmap GetBitmap(wxAnyButton::State which) const = 0;
|
||||
virtual void SetBitmap(const wxBitmap& bitmap, wxAnyButton::State which) = 0;
|
||||
|
||||
// Helper: get the bitmap of the currently used size from the bundle.
|
||||
wxBitmap GetBitmapFromBundle(const wxBitmapBundle& bitmapBundle) const
|
||||
{
|
||||
return GetBitmap(which);
|
||||
return bitmapBundle.GetBitmap(GetBitmapSize());
|
||||
}
|
||||
|
||||
void SetImplicitBitmap(const wxBitmap& bitmap, wxAnyButton::State which)
|
||||
// And another helper to call SetBitmap() with the result.
|
||||
void SetBitmapFromBundle(const wxBitmapBundle& bitmapBundle, wxAnyButton::State which)
|
||||
{
|
||||
SetBitmap(bitmap, which);
|
||||
m_bitmapSetExplicitly[which] = false;
|
||||
SetBitmap(GetBitmapFromBundle(bitmapBundle), which);
|
||||
}
|
||||
|
||||
|
||||
// Return the currently used bitmap size.
|
||||
wxSize GetBitmapSize() const { return m_bitmapSize; }
|
||||
|
||||
virtual wxSize GetBitmapMargins() const = 0;
|
||||
virtual void SetBitmapMargins(wxCoord x, wxCoord y) = 0;
|
||||
|
||||
@@ -148,12 +159,9 @@ public:
|
||||
virtual void SetBitmapPosition(wxDirection dir) = 0;
|
||||
|
||||
private:
|
||||
// These functions are private to force using explicit/implicit versions of
|
||||
// them in the code to make it clear which bitmap is needed.
|
||||
virtual wxBitmap GetBitmap(wxAnyButton::State which) const = 0;
|
||||
virtual void SetBitmap(const wxBitmap& bitmap, wxAnyButton::State which) = 0;
|
||||
wxSize m_bitmapSize;
|
||||
|
||||
bool m_bitmapSetExplicitly[wxAnyButton::State_Max];
|
||||
wxBitmapBundle m_bitmapBundles[wxAnyButton::State_Max];
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxButtonImageData);
|
||||
};
|
||||
@@ -168,11 +176,13 @@ const int OD_BUTTON_MARGIN = 4;
|
||||
class wxODButtonImageData : public wxButtonImageData
|
||||
{
|
||||
public:
|
||||
wxODButtonImageData(wxAnyButton *btn, const wxBitmap& bitmap)
|
||||
wxODButtonImageData(wxAnyButton *btn, const wxBitmapBundle& bitmapBundle)
|
||||
: wxButtonImageData(bitmapBundle.GetDefaultSize())
|
||||
{
|
||||
SetExplicitBitmap(bitmap, wxAnyButton::State_Normal);
|
||||
SetBitmapBundle(bitmapBundle, wxAnyButton::State_Normal);
|
||||
#if wxUSE_IMAGE
|
||||
SetBitmap(bitmap.ConvertToDisabled(), wxAnyButton::State_Disabled);
|
||||
SetBitmap(GetBitmapFromBundle(bitmapBundle).ConvertToDisabled(),
|
||||
wxAnyButton::State_Disabled);
|
||||
#endif
|
||||
m_dir = wxLEFT;
|
||||
|
||||
@@ -239,13 +249,20 @@ class wxXPButtonImageData : public wxButtonImageData
|
||||
public:
|
||||
// we must be constructed with the size of our images as we need to create
|
||||
// the image list
|
||||
wxXPButtonImageData(wxAnyButton *btn, const wxBitmap& bitmap)
|
||||
: m_iml(bitmap.GetWidth(), bitmap.GetHeight(),
|
||||
!bitmap.HasAlpha() /* use mask only if no alpha */,
|
||||
wxAnyButton::State_Max + 1 /* see "pulse" comment below */),
|
||||
wxXPButtonImageData(wxAnyButton *btn, const wxBitmapBundle& bitmapBundle)
|
||||
: wxButtonImageData(bitmapBundle.GetDefaultSize()),
|
||||
m_hwndBtn(GetHwndOf(btn))
|
||||
{
|
||||
// initialize all bitmaps except for the disabled one to normal state
|
||||
const wxBitmap bitmap = bitmapBundle.GetBitmap(wxDefaultSize);
|
||||
m_iml.Create
|
||||
(
|
||||
bitmap.GetWidth(),
|
||||
bitmap.GetHeight(),
|
||||
!bitmap.HasAlpha() /* use mask only if no alpha */,
|
||||
wxAnyButton::State_Max + 1 /* see "pulse" comment below */
|
||||
);
|
||||
|
||||
for ( int n = 0; n < wxAnyButton::State_Max; n++ )
|
||||
{
|
||||
#if wxUSE_IMAGE
|
||||
@@ -266,8 +283,8 @@ public:
|
||||
// just disappears during half of the time if the latter is not set so
|
||||
// we absolutely must set it.
|
||||
//
|
||||
// This also explains why we need to allocate an extra slot in the
|
||||
// image list ctor above, the slot State_Max is used for this one.
|
||||
// This also explains why we need to allocate an extra slot when creating
|
||||
// the image list above, the slot State_Max is used for this one.
|
||||
m_iml.Add(bitmap);
|
||||
|
||||
m_data.himl = GetHimagelistOf(&m_iml);
|
||||
@@ -546,7 +563,7 @@ void wxAnyButton::AdjustForBitmapSize(wxSize &size) const
|
||||
wxCHECK_RET( m_imageData, wxT("shouldn't be called if no image") );
|
||||
|
||||
// account for the bitmap size, including the user-specified margins
|
||||
const wxSize sizeBmp = m_imageData->GetImplicitBitmap(State_Normal).GetSize()
|
||||
const wxSize sizeBmp = m_imageData->GetBitmapSize()
|
||||
+ 2*m_imageData->GetBitmapMargins();
|
||||
const wxDirection dirBmp = m_imageData->GetBitmapPosition();
|
||||
if ( dirBmp == wxLEFT || dirBmp == wxRIGHT )
|
||||
@@ -701,7 +718,7 @@ WXLRESULT wxAnyButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPar
|
||||
if (
|
||||
IsEnabled() &&
|
||||
( wxUxThemeIsActive() ||
|
||||
(m_imageData && m_imageData->GetImplicitBitmap(State_Current).IsOk())
|
||||
(m_imageData && m_imageData->GetBitmap(State_Current).IsOk())
|
||||
)
|
||||
)
|
||||
{
|
||||
@@ -719,12 +736,22 @@ WXLRESULT wxAnyButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPar
|
||||
|
||||
wxBitmap wxAnyButton::DoGetBitmap(State which) const
|
||||
{
|
||||
return m_imageData ? m_imageData->GetExplicitBitmap(which) : wxBitmap();
|
||||
if ( !m_imageData )
|
||||
return wxBitmap();
|
||||
|
||||
const wxBitmapBundle& bitmapBundle = m_imageData->GetBitmapBundle(which);
|
||||
if ( !bitmapBundle.IsOk() )
|
||||
return wxBitmap();
|
||||
|
||||
// Not really sure if it's better to use the default or current size here,
|
||||
// but then this accessor is not that useful anyhow, so it probably doesn't
|
||||
// matter much.
|
||||
return bitmapBundle.GetBitmap(m_imageData->GetBitmapSize());
|
||||
}
|
||||
|
||||
void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
void wxAnyButton::DoSetBitmap(const wxBitmapBundle& bitmapBundle, State which)
|
||||
{
|
||||
if ( !bitmap.IsOk() )
|
||||
if ( !bitmapBundle.IsOk() )
|
||||
{
|
||||
if ( m_imageData )
|
||||
{
|
||||
@@ -737,9 +764,12 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalidate the current bundle, if any.
|
||||
m_imageData->SetBitmapBundle(bitmapBundle, which);
|
||||
|
||||
// Replace the removed bitmap with the normal one.
|
||||
wxBitmap bmpNormal = m_imageData->GetImplicitBitmap(State_Normal);
|
||||
m_imageData->SetImplicitBitmap(which == State_Disabled
|
||||
wxBitmap bmpNormal = m_imageData->GetBitmap(State_Normal);
|
||||
m_imageData->SetBitmap(which == State_Disabled
|
||||
? bmpNormal.ConvertToDisabled()
|
||||
: bmpNormal,
|
||||
which);
|
||||
@@ -755,7 +785,7 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
|
||||
// Check if we already had bitmaps of different size.
|
||||
if ( m_imageData &&
|
||||
bitmap.GetSize() != m_imageData->GetImplicitBitmap(State_Normal).GetSize() )
|
||||
bitmapBundle.GetDefaultSize() != m_imageData->GetBitmapSize() )
|
||||
{
|
||||
wxASSERT_MSG( which == State_Normal,
|
||||
"Must set normal bitmap with the new size first" );
|
||||
@@ -783,7 +813,7 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
// strategy for bitmap-only buttons
|
||||
if ( ShowsLabel() && wxUxThemeIsActive() )
|
||||
{
|
||||
m_imageData = new wxXPButtonImageData(this, bitmap);
|
||||
m_imageData = new wxXPButtonImageData(this, bitmapBundle);
|
||||
|
||||
if ( oldData )
|
||||
{
|
||||
@@ -802,13 +832,13 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
else
|
||||
#endif // wxUSE_UXTHEME
|
||||
{
|
||||
m_imageData = new wxODButtonImageData(this, bitmap);
|
||||
m_imageData = new wxODButtonImageData(this, bitmapBundle);
|
||||
MakeOwnerDrawn();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_imageData->SetExplicitBitmap(bitmap, which);
|
||||
m_imageData->SetBitmapBundle(bitmapBundle, which);
|
||||
|
||||
// if the focus bitmap is specified but current one isn't, use
|
||||
// the focus bitmap for hovering as well if this is consistent
|
||||
@@ -818,9 +848,9 @@ void wxAnyButton::DoSetBitmap(const wxBitmap& bitmap, State which)
|
||||
// and also makes it much easier to do "the right thing" for
|
||||
// all platforms (some of them, such as Windows, have "hot"
|
||||
// buttons while others don't)
|
||||
if ( which == State_Focused && !m_imageData->GetExplicitBitmap(State_Current).IsOk() )
|
||||
if ( which == State_Focused && !m_imageData->GetBitmapBundle(State_Current).IsOk() )
|
||||
{
|
||||
m_imageData->SetImplicitBitmap(bitmap, State_Current);
|
||||
m_imageData->SetBitmapFromBundle(bitmapBundle, State_Current);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,16 +1297,16 @@ void wxAnyButton::MakeOwnerDrawn()
|
||||
// if necessary.
|
||||
if ( m_imageData && wxDynamicCast(m_imageData, wxODButtonImageData) == NULL )
|
||||
{
|
||||
wxODButtonImageData* newData = new wxODButtonImageData(this, m_imageData->GetImplicitBitmap(State_Normal));
|
||||
wxODButtonImageData* newData = new wxODButtonImageData(this, m_imageData->GetBitmapBundle(State_Normal));
|
||||
for ( int n = 0; n < State_Max; n++ )
|
||||
{
|
||||
State st = static_cast<State>(n);
|
||||
|
||||
wxBitmap bmp = m_imageData->GetExplicitBitmap(st);
|
||||
wxBitmapBundle bmp = m_imageData->GetBitmapBundle(st);
|
||||
if ( bmp.IsOk() )
|
||||
newData->SetExplicitBitmap(bmp, st);
|
||||
newData->SetBitmapBundle(bmp, st);
|
||||
else
|
||||
newData->SetImplicitBitmap(m_imageData->GetImplicitBitmap(st), st);
|
||||
newData->SetBitmap(m_imageData->GetBitmap(st), st);
|
||||
}
|
||||
newData->SetBitmapPosition(m_imageData->GetBitmapPosition());
|
||||
wxSize margs = m_imageData->GetBitmapMargins();
|
||||
@@ -1436,9 +1466,9 @@ bool wxAnyButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
|
||||
// draw the image, if any
|
||||
if ( m_imageData )
|
||||
{
|
||||
wxBitmap bmp = m_imageData->GetImplicitBitmap(GetButtonState(this, state));
|
||||
wxBitmap bmp = m_imageData->GetBitmap(GetButtonState(this, state));
|
||||
if ( !bmp.IsOk() )
|
||||
bmp = m_imageData->GetImplicitBitmap(State_Normal);
|
||||
bmp = m_imageData->GetBitmap(State_Normal);
|
||||
|
||||
const wxSize sizeBmp = bmp.GetSize();
|
||||
const wxSize margin = m_imageData->GetBitmapMargins();
|
||||
|
||||
Reference in New Issue
Block a user