Merge branch 'animation-hidpi'
Add support for specifying multiple animations to allow automatically showing a higher resolution version when using high DPI, just as it was already possible with the bitmaps. See #23817.
This commit is contained in:
commit
00366cbaae
22 changed files with 383 additions and 85 deletions
|
|
@ -8,7 +8,7 @@
|
|||
#############################################################################
|
||||
|
||||
wx_add_sample(access accesstest.cpp DEPENDS wxUSE_ACCESSIBILITY)
|
||||
wx_add_sample(animate anitest.cpp anitest.h DATA throbber.gif hourglass.ani DEPENDS wxUSE_ANIMATIONCTRL)
|
||||
wx_add_sample(animate anitest.cpp anitest.h DATA throbber.gif throbber_2x.gif hourglass.ani DEPENDS wxUSE_ANIMATIONCTRL)
|
||||
wx_add_sample(archive CONSOLE)
|
||||
wx_add_sample(artprov arttest.cpp artbrows.cpp artbrows.h)
|
||||
wx_add_sample(aui auidemo.cpp LIBRARIES wxaui wxhtml NAME auidemo DEPENDS wxUSE_AUI)
|
||||
|
|
|
|||
|
|
@ -653,7 +653,9 @@ controls cannot have children.
|
|||
@beginTable
|
||||
@hdr3col{property, type, description}
|
||||
@row3col{animation, @ref overview_xrcformat_type_url,
|
||||
Animation file to load into the control (default: none).}
|
||||
Animation file to load into the control or, since wxWindow 3.3.0, multiple
|
||||
semicolon-separated files in order of increasing size, corresponding to
|
||||
multiple versions of the animation for different resolutions (default: none).}
|
||||
@row3col{inactive-bitmap, @ref overview_xrcformat_type_bitmap,
|
||||
Bitmap to use when not playing the animation (default: the default).}
|
||||
@endTable
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include "wx/timer.h"
|
||||
#include "wx/bmpbndl.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxAnimation;
|
||||
class wxAnimationImpl;
|
||||
|
||||
|
|
@ -80,6 +82,64 @@ private:
|
|||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxAnimationBundle is one or more animations in different resolutions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using wxAnimations = std::vector<wxAnimation>;
|
||||
|
||||
// This class is conceptually similar to wxBitmapBundle but much simpler.
|
||||
class WXDLLIMPEXP_CORE wxAnimationBundle
|
||||
{
|
||||
public:
|
||||
// Default ctor, call Add() later.
|
||||
wxAnimationBundle() = default;
|
||||
|
||||
// Implicit ctor for backwards compatibility: this allows to pass a single
|
||||
// wxAnimation to wxAnimationCtrl::SetAnimation(), just as before.
|
||||
wxAnimationBundle(const wxAnimation& anim)
|
||||
{
|
||||
// Allow the animation to be invalid here, also for compatibility.
|
||||
if ( anim.IsOk() )
|
||||
m_animations.push_back(anim);
|
||||
}
|
||||
|
||||
// Another implicit ctor for backwards compatibility: this one allows to
|
||||
// create an animation from the given file.
|
||||
wxAnimationBundle(const wxString& filename,
|
||||
wxAnimationType type = wxANIMATION_TYPE_ANY)
|
||||
{
|
||||
wxAnimation anim(filename, type);
|
||||
if ( anim.IsOk() )
|
||||
m_animations.push_back(anim);
|
||||
}
|
||||
|
||||
wxAnimationBundle(const wxAnimationBundle&) = default;
|
||||
wxAnimationBundle& operator=(const wxAnimationBundle&) = default;
|
||||
|
||||
~wxAnimationBundle() = default;
|
||||
|
||||
|
||||
// Add an animation in another, bigger, size.
|
||||
void Add(const wxAnimation& anim);
|
||||
|
||||
void Add(const wxString& filename,
|
||||
wxAnimationType type = wxANIMATION_TYPE_ANY)
|
||||
{
|
||||
Add(wxAnimation(filename, type));
|
||||
}
|
||||
|
||||
// Check if this bundle contains any animations (if it has any, they must
|
||||
// be valid).
|
||||
bool IsOk() const { return !m_animations.empty(); }
|
||||
|
||||
// Just provide access to all the elements.
|
||||
const wxAnimations& GetAll() const { return m_animations; }
|
||||
|
||||
private:
|
||||
wxAnimations m_animations;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxAnimationCtrlBase
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -102,7 +162,7 @@ public:
|
|||
virtual bool Load(wxInputStream& stream,
|
||||
wxAnimationType type = wxANIMATION_TYPE_ANY) = 0;
|
||||
|
||||
virtual void SetAnimation(const wxAnimation &anim) = 0;
|
||||
virtual void SetAnimation(const wxAnimationBundle& animations) = 0;
|
||||
wxAnimation GetAnimation() const { return m_animation; }
|
||||
|
||||
virtual bool Play() = 0;
|
||||
|
|
@ -130,7 +190,10 @@ protected:
|
|||
wxAnimationImpl* GetAnimImpl() const
|
||||
{ return m_animation.GetImpl(); }
|
||||
|
||||
// The associated animation, possibly invalid/empty.
|
||||
// All animations that we have.
|
||||
wxAnimations m_animations;
|
||||
|
||||
// The animation being currently used, possibly invalid/empty.
|
||||
wxAnimation m_animation;
|
||||
|
||||
// the inactive bitmap as it was set by the user
|
||||
|
|
|
|||
|
|
@ -332,6 +332,10 @@ public:
|
|||
|
||||
bool IsFullySpecified() const { return x != wxDefaultCoord && y != wxDefaultCoord; }
|
||||
|
||||
// Check that this size object is at least as big as the other one in both
|
||||
// directions.
|
||||
bool IsAtLeast(const wxSize& sz) const { return x >= sz.x && y >= sz.y; }
|
||||
|
||||
// combine this size with the other one replacing the default (i.e. equal
|
||||
// to wxDefaultCoord) components of this object with those of the other
|
||||
void SetDefaults(const wxSize& size)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual bool IsPlaying() const override
|
||||
{ return m_isPlaying; }
|
||||
|
||||
void SetAnimation(const wxAnimation &animation) override;
|
||||
void SetAnimation(const wxAnimationBundle &animations) override;
|
||||
|
||||
virtual void SetInactiveBitmap(const wxBitmapBundle &bmp) override;
|
||||
|
||||
|
|
@ -140,6 +140,9 @@ protected:
|
|||
// on the screen
|
||||
|
||||
private:
|
||||
// True if we need to show the next frame after painting the current one.
|
||||
bool m_needToShowNextFrame = false;
|
||||
|
||||
typedef wxAnimationCtrlBase base_type;
|
||||
wxDECLARE_DYNAMIC_CLASS(wxGenericAnimationCtrl);
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public: // public API
|
|||
virtual bool LoadFile(const wxString& filename, wxAnimationType type = wxANIMATION_TYPE_ANY) override;
|
||||
virtual bool Load(wxInputStream& stream, wxAnimationType type = wxANIMATION_TYPE_ANY) override;
|
||||
|
||||
void SetAnimation(const wxAnimation &anim) override;
|
||||
void SetAnimation(const wxAnimationBundle& anim) override;
|
||||
|
||||
virtual bool Play() override;
|
||||
virtual void Stop() override;
|
||||
|
|
|
|||
|
|
@ -621,11 +621,19 @@ public:
|
|||
wxImageList *GetImageList(const wxString& param = wxT("imagelist")) override;
|
||||
|
||||
#if wxUSE_ANIMATIONCTRL
|
||||
// Get all the animations defined in the given parameter which may contain
|
||||
// more than one semicolon-separated paths.
|
||||
wxAnimationBundle GetAnimations(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr) override;
|
||||
|
||||
#if WXWIN_COMPATIBILITY_3_2
|
||||
wxDEPRECATED_MSG("Use GetAnimations() instead")
|
||||
// Gets an animation creating it using the provided control (so that it
|
||||
// will be compatible with it) if any.
|
||||
wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr) override;
|
||||
#endif
|
||||
#endif // WXWIN_COMPATIBILITY_3_2
|
||||
#endif // wxUSE_ANIMATIONCTRL
|
||||
|
||||
// Gets a font.
|
||||
wxFont GetFont(const wxString& param = wxT("font"), wxWindow* parent = nullptr) override;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "wx/window.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxAnimation;
|
||||
class WXDLLIMPEXP_FWD_CORE wxAnimationBundle;
|
||||
class WXDLLIMPEXP_FWD_CORE wxAnimationCtrlBase;
|
||||
|
||||
class WXDLLIMPEXP_FWD_XML wxXmlNode;
|
||||
|
|
@ -109,9 +110,15 @@ public:
|
|||
virtual wxImageList *GetImageList(const wxString& param = wxT("imagelist")) = 0;
|
||||
|
||||
#if wxUSE_ANIMATIONCTRL
|
||||
virtual wxAnimationBundle GetAnimations(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr) = 0;
|
||||
|
||||
#if WXWIN_COMPATIBILITY_3_2
|
||||
wxDEPRECATED_BUT_USED_INTERNALLY_MSG("Use GetAnimations() instead")
|
||||
virtual wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr) = 0;
|
||||
#endif
|
||||
#endif // WXWIN_COMPATIBILITY_3_2
|
||||
#endif // wxUSE_ANIMATIONCTRL
|
||||
|
||||
virtual wxFont GetFont(const wxString& param = wxT("font"), wxWindow* parent = nullptr) = 0;
|
||||
virtual bool GetBoolAttr(const wxString& attr, bool defaultv) = 0;
|
||||
|
|
@ -377,12 +384,14 @@ protected:
|
|||
}
|
||||
|
||||
#if wxUSE_ANIMATIONCTRL
|
||||
wxAnimationBundle GetAnimations(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr);
|
||||
|
||||
#if WXWIN_COMPATIBILITY_3_2
|
||||
wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
|
||||
wxAnimationCtrlBase* ctrl = nullptr)
|
||||
{
|
||||
return GetImpl()->GetAnimation(param, ctrl);
|
||||
}
|
||||
#endif
|
||||
wxAnimationCtrlBase* ctrl = nullptr);
|
||||
#endif // WXWIN_COMPATIBILITY_3_2
|
||||
#endif // wxUSE_ANIMATIONCTRL
|
||||
|
||||
wxFont GetFont(const wxString& param = wxT("font"),
|
||||
wxWindow* parent = nullptr)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,82 @@ enum wxAnimationType
|
|||
#define wxAC_DEFAULT_STYLE (wxBORDER_NONE)
|
||||
|
||||
|
||||
/**
|
||||
Container for possible multiple versions of the same animation in different
|
||||
resolutions.
|
||||
|
||||
This class is used to pass either one or multiple animations to use in
|
||||
wxAnimationCtrl. If it contains multiple elements, they must be added to it
|
||||
using its Add() function in ascending size order and, in particular, the
|
||||
first element defines the size of the animation in standard DPI, with the
|
||||
other elements containing versions of the animation to use in higher DPI.
|
||||
|
||||
Example of using this class to pass a normal and high DPI version of a
|
||||
"throbbing" animation to the control and let it choose the one most
|
||||
appropriate to the current resolution automatically:
|
||||
|
||||
@code
|
||||
auto animationCtrl = new wxAnimationCtrl(parent, wxID_ANY);
|
||||
wxAnimationBundle animations;
|
||||
animations.Add("throbber.gif");
|
||||
animations.Add("throbber_2x.gif");
|
||||
if ( animationCtrl->SetAnimation(animations) )
|
||||
animationCtrl->Play();
|
||||
@endcode
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
class wxAnimationBundle
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Default constructor creates an empty bundle.
|
||||
|
||||
Call Add() later.
|
||||
*/
|
||||
wxAnimationBundle() = default;
|
||||
|
||||
/**
|
||||
Implicit ctor from wxAnimation for backwards compatibility.
|
||||
*/
|
||||
wxAnimationBundle(const wxAnimation& anim);
|
||||
|
||||
/**
|
||||
Implicit ctor from animation file name for backwards compatibility.
|
||||
*/
|
||||
wxAnimationBundle(const wxString& filename,
|
||||
wxAnimationType type = wxANIMATION_TYPE_ANY);
|
||||
|
||||
wxAnimationBundle(const wxAnimationBundle&) = default;
|
||||
wxAnimationBundle& operator=(const wxAnimationBundle&) = default;
|
||||
|
||||
~wxAnimationBundle() = default;
|
||||
|
||||
|
||||
/**
|
||||
Add an animation in another, bigger, size.
|
||||
*/
|
||||
void Add(const wxAnimation& anim);
|
||||
|
||||
/// @overload
|
||||
void Add(const wxString& filename,
|
||||
wxAnimationType type = wxANIMATION_TYPE_ANY);
|
||||
|
||||
/**
|
||||
Get vector containing all animations in this bundle.
|
||||
|
||||
The vector can be empty.
|
||||
*/
|
||||
const std::vector<wxAnimation>& GetAll() const;
|
||||
|
||||
/**
|
||||
Return true if this animation bundle is not empty.
|
||||
|
||||
Notice that any elements of the bundle are always valid animations.
|
||||
*/
|
||||
bool IsOk() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@class wxAnimationCtrl
|
||||
|
||||
|
|
@ -175,8 +251,24 @@ public:
|
|||
Until Play() isn't called, a static image, the first frame of the given
|
||||
animation or the background colour will be shown
|
||||
(see SetInactiveBitmap() for more info).
|
||||
|
||||
Note that while this function takes wxAnimationBundle parameter, it is
|
||||
possible to pass just a single wxAnimation to it too, as it is
|
||||
implicitly converted to a bundle. Moreover, is it also possible to call
|
||||
this function with just the name of the animation file, e.g.
|
||||
|
||||
@code
|
||||
animationCtrl->SetAnimation("progress.gif");
|
||||
@endcode
|
||||
|
||||
due to the existence of another implicit constructor, however this
|
||||
doesn't allow to check for errors when creating the animation and is
|
||||
not recommended.
|
||||
|
||||
If the animation bundle contains more than one animation, the one
|
||||
appropriate for the current display resolution is chosen.
|
||||
*/
|
||||
virtual void SetAnimation(const wxAnimation& anim);
|
||||
virtual void SetAnimation(const wxAnimationBundle& animations);
|
||||
|
||||
/**
|
||||
Sets the bitmap to show on the control when it's not playing an animation.
|
||||
|
|
|
|||
|
|
@ -1037,6 +1037,14 @@ public:
|
|||
*/
|
||||
void IncTo(const wxSize& size);
|
||||
|
||||
/**
|
||||
Returns @true if this size is at least as big as the other one in both
|
||||
directions.
|
||||
|
||||
@since 3.3.0
|
||||
*/
|
||||
bool IsAtLeast(const wxSize& size) const;
|
||||
|
||||
/**
|
||||
Returns @true if neither of the size object components is equal to -1,
|
||||
which is used as default for the size values in wxWidgets (hence the
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ anitest$(EXEEXT): $(ANITEST_OBJECTS) $(__anitest___win32rc)
|
|||
|
||||
catalog:
|
||||
@mkdir -p .
|
||||
@for f in throbber.gif hourglass.ani; do \
|
||||
@for f in throbber.gif throbber_2x.gif hourglass.ani; do \
|
||||
if test ! -f ./$$f -a ! -d ./$$f ; \
|
||||
then x=yep ; \
|
||||
else x=`find $(srcdir)/$$f -newer ./$$f -print` ; \
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
</exe>
|
||||
|
||||
<wx-data id="catalog">
|
||||
<files>throbber.gif hourglass.ani</files>
|
||||
<files>throbber.gif throbber_2x.gif hourglass.ani</files>
|
||||
</wx-data>
|
||||
|
||||
</makefile>
|
||||
|
|
|
|||
|
|
@ -174,8 +174,21 @@ MyFrame::MyFrame(wxWindow *parent,
|
|||
wxSizerFlags().Centre().Border());
|
||||
|
||||
m_animationCtrl = new wxAnimationCtrl(this, wxID_ANY);
|
||||
if (m_animationCtrl->LoadFile("throbber.gif"))
|
||||
|
||||
wxAnimationBundle animations;
|
||||
|
||||
wxAnimation throbber("throbber.gif");
|
||||
if (throbber.IsOk())
|
||||
animations.Add(throbber);
|
||||
wxAnimation throbber2x("throbber_2x.gif");
|
||||
if (throbber2x.IsOk())
|
||||
animations.Add(throbber2x);
|
||||
|
||||
if (animations.IsOk())
|
||||
{
|
||||
m_animationCtrl->SetAnimation(animations);
|
||||
m_animationCtrl->Play();
|
||||
}
|
||||
|
||||
sz->Add(m_animationCtrl, wxSizerFlags().Centre().Border());
|
||||
SetSizer(sz);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ $(OBJS)\anitest.exe: $(ANITEST_OBJECTS) $(OBJS)\anitest_sample_rc.o
|
|||
|
||||
catalog:
|
||||
if not exist $(OBJS) mkdir $(OBJS)
|
||||
for %%f in (throbber.gif hourglass.ani) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS)
|
||||
for %%f in (throbber.gif throbber_2x.gif hourglass.ani) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS)
|
||||
|
||||
$(OBJS)\anitest_sample_rc.o: ./../../samples/sample.rc
|
||||
$(WINDRES) -i$< -o$@ --define __WXMSW__ $(__WXUNIV_DEFINE_p_1) $(__DEBUG_DEFINE_p_1) $(__NDEBUG_DEFINE_p_1) $(__EXCEPTIONS_DEFINE_p_1) $(__RTTI_DEFINE_p_1) $(__THREAD_DEFINE_p_1) --include-dir $(SETUPHDIR) --include-dir ./../../include $(__CAIRO_INCLUDEDIR_p) --include-dir . $(__DLLFLAG_p_1) --define wxUSE_DPI_AWARE_MANIFEST=$(USE_DPI_AWARE_MANIFEST) --include-dir ./../../samples --define NOPCH
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ $(OBJS)\anitest.exe: $(ANITEST_OBJECTS) $(OBJS)\anitest_sample.res
|
|||
|
||||
catalog:
|
||||
if not exist $(OBJS) mkdir $(OBJS)
|
||||
for %f in (throbber.gif hourglass.ani) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
|
||||
for %f in (throbber.gif throbber_2x.gif hourglass.ani) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
|
||||
|
||||
$(OBJS)\anitest_sample.res: .\..\..\samples\sample.rc
|
||||
rc /fo$@ /d WIN32 $(____DEBUGRUNTIME_3_p_1) /d _CRT_SECURE_NO_DEPRECATE=1 /d _CRT_NON_CONFORMING_SWPRINTFS=1 /d _SCL_SECURE_NO_WARNINGS=1 $(__NO_VC_CRTDBG_p_1) $(__TARGET_CPU_COMPFLAG_p_1) /d __WXMSW__ $(__WXUNIV_DEFINE_p_1) $(__DEBUG_DEFINE_p_1) $(__NDEBUG_DEFINE_p_1) $(__EXCEPTIONS_DEFINE_p_1) $(__RTTI_DEFINE_p_1) $(__THREAD_DEFINE_p_1) /i $(SETUPHDIR) /i .\..\..\include $(____CAIRO_INCLUDEDIR_FILENAMES_1_p) /i . $(__DLLFLAG_p_1) /d _WINDOWS /i .\..\..\samples /d NOPCH .\..\..\samples\sample.rc
|
||||
|
|
|
|||
BIN
samples/animate/throbber_2x.gif
Normal file
BIN
samples/animate/throbber_2x.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
|
|
@ -126,6 +126,31 @@ bool wxAnimation::Load(wxInputStream& stream, wxAnimationType type)
|
|||
return GetImpl()->Load(stream, type);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxAnimationBundle
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxAnimationBundle::Add(const wxAnimation& anim)
|
||||
{
|
||||
// It's ok to have empty animation bundle, but any animations added to
|
||||
// it should be valid.
|
||||
wxCHECK_RET( anim.IsOk(), "shouldn't add invalid animations" );
|
||||
|
||||
if ( !m_animations.empty() )
|
||||
{
|
||||
// They also should be added in increasing size.
|
||||
const wxSize thisSize = anim.GetSize();
|
||||
const wxSize lastSize = m_animations.back().GetSize();
|
||||
|
||||
wxCHECK_RET( thisSize != lastSize,
|
||||
"shouldn't have multiple animations of the same size" );
|
||||
|
||||
wxCHECK_RET( thisSize.IsAtLeast(lastSize),
|
||||
"should be added in order of increasing size" );
|
||||
}
|
||||
|
||||
m_animations.push_back(anim);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxAnimationCtrlBase
|
||||
|
|
|
|||
|
|
@ -241,20 +241,32 @@ wxSize wxGenericAnimationCtrl::DoGetBestSize() const
|
|||
return FromDIP(wxSize(100, 100));
|
||||
}
|
||||
|
||||
void wxGenericAnimationCtrl::SetAnimation(const wxAnimation& animation)
|
||||
void wxGenericAnimationCtrl::SetAnimation(const wxAnimationBundle& animations)
|
||||
{
|
||||
if (IsPlaying())
|
||||
Stop();
|
||||
|
||||
// set new animation even if it's wxNullAnimation
|
||||
m_animation = animation;
|
||||
if (!m_animation.IsOk())
|
||||
m_animations = animations.GetAll();
|
||||
|
||||
// Reset animation if we don't have any valid ones.
|
||||
if ( m_animations.empty() )
|
||||
{
|
||||
m_animation.UnRef();
|
||||
DisplayStaticImage();
|
||||
return;
|
||||
}
|
||||
|
||||
wxCHECK_RET(animation.IsCompatibleWith(GetClassInfo()),
|
||||
// Otherwise choose the animation of the size most appropriate for the
|
||||
// current resolution.
|
||||
const wxSize wantedSize = m_animations[0].GetSize()*GetDPIScaleFactor();
|
||||
for ( const auto& anim: m_animations )
|
||||
{
|
||||
m_animation = anim;
|
||||
if ( m_animation.GetSize().IsAtLeast(wantedSize) )
|
||||
break;
|
||||
}
|
||||
|
||||
wxCHECK_RET(m_animation.IsCompatibleWith(GetClassInfo()),
|
||||
wxT("incompatible animation") );
|
||||
|
||||
if (AnimationImplGetBackgroundColour() == wxNullColour)
|
||||
|
|
@ -325,19 +337,9 @@ bool wxGenericAnimationCtrl::Play(bool looped)
|
|||
|
||||
m_isPlaying = true;
|
||||
|
||||
// do a ClearBackground() to avoid that e.g. the custom static bitmap which
|
||||
// was eventually shown previously remains partially drawn
|
||||
ClearBackground();
|
||||
m_needToShowNextFrame = true;
|
||||
|
||||
// DrawCurrentFrame() will use our updated backing store
|
||||
wxClientDC clientDC(this);
|
||||
DrawCurrentFrame(clientDC);
|
||||
|
||||
// start the timer
|
||||
int delay = m_animation.GetDelay(0);
|
||||
if (delay == 0)
|
||||
delay = 1; // 0 is invalid timeout for wxTimer.
|
||||
m_timer.Start(delay, true);
|
||||
Refresh();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -385,7 +387,6 @@ bool wxGenericAnimationCtrl::RebuildBackingStoreUpToFrame(unsigned int frame)
|
|||
|
||||
// finally draw this frame
|
||||
DrawFrame(dc, frame);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -439,7 +440,6 @@ void wxGenericAnimationCtrl::IncrementalUpdateBackingStore()
|
|||
|
||||
// now just draw the current frame on the top of the backing store
|
||||
DrawFrame(dc, m_currentFrame);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
}
|
||||
|
||||
void wxGenericAnimationCtrl::DisplayStaticImage()
|
||||
|
|
@ -552,6 +552,17 @@ void wxGenericAnimationCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
|
|||
// clear then our area to the background colour
|
||||
DisposeToBackground(dc);
|
||||
}
|
||||
|
||||
if ( m_needToShowNextFrame )
|
||||
{
|
||||
m_needToShowNextFrame = false;
|
||||
|
||||
// Set the timer for the next frame
|
||||
int delay = m_animation.GetDelay(m_currentFrame);
|
||||
if (delay == 0)
|
||||
delay = 1; // 0 is invalid timeout for wxTimer.
|
||||
m_timer.StartOnce(delay);
|
||||
}
|
||||
}
|
||||
|
||||
void wxGenericAnimationCtrl::OnTimer(wxTimerEvent &WXUNUSED(event))
|
||||
|
|
@ -571,19 +582,9 @@ void wxGenericAnimationCtrl::OnTimer(wxTimerEvent &WXUNUSED(event))
|
|||
|
||||
IncrementalUpdateBackingStore();
|
||||
|
||||
wxClientDC dc(this);
|
||||
DrawCurrentFrame(dc);
|
||||
m_needToShowNextFrame = true;
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// without this, the animation currently doesn't redraw under Mac
|
||||
Refresh();
|
||||
#endif // __WXMAC__
|
||||
|
||||
// Set the timer for the next frame
|
||||
int delay = m_animation.GetDelay(m_currentFrame);
|
||||
if (delay == 0)
|
||||
delay = 1; // 0 is invalid timeout for wxTimer.
|
||||
m_timer.Start(delay, true);
|
||||
}
|
||||
|
||||
void wxGenericAnimationCtrl::OnSize(wxSizeEvent &WXUNUSED(event))
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ wxAnimationImpl* wxAnimationCtrl::DoCreateAnimationImpl() const
|
|||
return new wxAnimationGTKImpl();
|
||||
}
|
||||
|
||||
void wxAnimationCtrl::SetAnimation(const wxAnimation &anim)
|
||||
void wxAnimationCtrl::SetAnimation(const wxAnimationBundle& animations)
|
||||
{
|
||||
if (IsPlaying())
|
||||
Stop();
|
||||
|
|
@ -283,15 +283,26 @@ void wxAnimationCtrl::SetAnimation(const wxAnimation &anim)
|
|||
ResetAnim();
|
||||
ResetIter();
|
||||
|
||||
m_animation = anim;
|
||||
if (!m_animation.IsOk())
|
||||
m_animations = animations.GetAll();
|
||||
|
||||
// Reset animation if we don't have any valid ones.
|
||||
if ( m_animations.empty() )
|
||||
{
|
||||
m_animation.UnRef();
|
||||
m_anim = nullptr;
|
||||
DisplayStaticImage();
|
||||
return;
|
||||
}
|
||||
|
||||
wxCHECK_RET(anim.IsCompatibleWith(GetClassInfo()),
|
||||
// TODO: Support higher resolution animations. Currently we always take the
|
||||
// animation for the standard resolution, which will be scaled if
|
||||
// necessary, we would need to create the pixbuf using the correct
|
||||
// animation when it's actually needed (by which time we will also have the
|
||||
// correct scale factor, which is not the case yet if we're called before
|
||||
// the control is shown, as is usually the case).
|
||||
m_animation = m_animations[0];
|
||||
|
||||
wxCHECK_RET(m_animation.IsCompatibleWith(GetClassInfo()),
|
||||
wxT("incompatible animation") );
|
||||
|
||||
// copy underlying GdkPixbuf object
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ wxObject *wxAnimationCtrlXmlHandler::DoCreateResource()
|
|||
if ( GetBool("hidden", 0) == 1 )
|
||||
ctrl->Hide();
|
||||
|
||||
std::unique_ptr<wxAnimation> animation(GetAnimation("animation", ctrl));
|
||||
if ( animation )
|
||||
ctrl->SetAnimation(*animation);
|
||||
const auto animations = GetAnimations("animation", ctrl);
|
||||
if ( animations.IsOk() )
|
||||
ctrl->SetAnimation(animations);
|
||||
|
||||
// if no inactive-bitmap has been provided, GetBitmapBundle() will return
|
||||
// an empty bundle, which just tells wxAnimationCtrl to use the default
|
||||
|
|
@ -78,39 +78,61 @@ bool wxAnimationCtrlXmlHandler::CanHandle(wxXmlNode *node)
|
|||
IsOfClass(node, wxT("wxGenericAnimationCtrl"));
|
||||
}
|
||||
|
||||
wxAnimationBundle
|
||||
wxXmlResourceHandlerImpl::GetAnimations(const wxString& param,
|
||||
wxAnimationCtrlBase* ctrl)
|
||||
{
|
||||
wxString paths = GetFilePath(GetParamNode(param));
|
||||
if ( paths.empty() )
|
||||
return {};
|
||||
|
||||
wxAnimationBundle animations;
|
||||
for ( const auto& name: wxSplit(paths, ';', '\0') )
|
||||
{
|
||||
// create compatible animation object
|
||||
wxAnimation ani;
|
||||
if ( ctrl )
|
||||
ani = ctrl->CreateAnimation();
|
||||
|
||||
// load the animation from file
|
||||
#if wxUSE_FILESYSTEM
|
||||
wxFSFile * const
|
||||
fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
|
||||
if ( fsfile )
|
||||
{
|
||||
ani.Load(*fsfile->GetStream());
|
||||
delete fsfile;
|
||||
}
|
||||
#else
|
||||
ani.LoadFile(name);
|
||||
#endif
|
||||
|
||||
if ( !ani.IsOk() )
|
||||
{
|
||||
ReportParamError
|
||||
(
|
||||
param,
|
||||
wxString::Format("cannot create animation from \"%s\"", name)
|
||||
);
|
||||
return {};
|
||||
}
|
||||
|
||||
animations.Add(ani);
|
||||
}
|
||||
|
||||
return animations;
|
||||
}
|
||||
|
||||
#if WXWIN_COMPATIBILITY_3_2
|
||||
|
||||
wxAnimation* wxXmlResourceHandlerImpl::GetAnimation(const wxString& param,
|
||||
wxAnimationCtrlBase* ctrl)
|
||||
{
|
||||
wxString name = GetFilePath(GetParamNode(param));
|
||||
if ( name.empty() )
|
||||
return nullptr;
|
||||
const auto animations = GetAnimations(param, ctrl);
|
||||
|
||||
// load the animation from file
|
||||
std::unique_ptr<wxAnimation> ani(ctrl ? new wxAnimation(ctrl->CreateAnimation())
|
||||
: new wxAnimation);
|
||||
#if wxUSE_FILESYSTEM
|
||||
wxFSFile * const
|
||||
fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
|
||||
if ( fsfile )
|
||||
{
|
||||
ani->Load(*fsfile->GetStream());
|
||||
delete fsfile;
|
||||
}
|
||||
#else
|
||||
ani->LoadFile(name);
|
||||
#endif
|
||||
|
||||
if ( !ani->IsOk() )
|
||||
{
|
||||
ReportParamError
|
||||
(
|
||||
param,
|
||||
wxString::Format("cannot create animation from \"%s\"", name)
|
||||
);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ani.release();
|
||||
return animations.IsOk() ? new wxAnimation(animations.GetAll()[0]) : nullptr;
|
||||
}
|
||||
|
||||
#endif // WXWIN_COMPATIBILITY_3_2
|
||||
|
||||
#endif // wxUSE_XRC && wxUSE_ANIMATIONCTRL
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#include "wx/xrc/xmlreshandler.h"
|
||||
|
||||
#if wxUSE_ANIMATIONCTRL
|
||||
#include "wx/animate.h"
|
||||
#endif
|
||||
|
||||
wxIMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject);
|
||||
|
||||
wxXmlResourceHandlerImplBase* wxXmlResourceHandler::GetImpl() const
|
||||
|
|
@ -65,4 +69,24 @@ void wxXmlResourceHandler::AddWindowStyles()
|
|||
XRC_ADD_STYLE(wxWS_EX_PROCESS_UI_UPDATES);
|
||||
}
|
||||
|
||||
#if wxUSE_ANIMATIONCTRL
|
||||
|
||||
wxAnimationBundle
|
||||
wxXmlResourceHandler::GetAnimations(const wxString& param,
|
||||
wxAnimationCtrlBase* ctrl)
|
||||
{
|
||||
return GetImpl()->GetAnimations(param, ctrl);
|
||||
}
|
||||
|
||||
#if WXWIN_COMPATIBILITY_3_2
|
||||
wxAnimation*
|
||||
wxXmlResourceHandler::GetAnimation(const wxString& param,
|
||||
wxAnimationCtrlBase* ctrl)
|
||||
{
|
||||
return GetImpl()->GetAnimation(param, ctrl);
|
||||
}
|
||||
#endif // WXWIN_COMPATIBILITY_3_2
|
||||
|
||||
#endif // wxUSE_ANIMATIONCTRL
|
||||
|
||||
#endif // wxUSE_XRC
|
||||
|
|
|
|||
|
|
@ -51,3 +51,16 @@ TEST_CASE("wxSize::Operators", "[size]")
|
|||
|
||||
CHECK( wxSize(6, 9) / 1.5 == wxSize(4, 6) );
|
||||
}
|
||||
|
||||
TEST_CASE("wxSize::Functions", "[size]")
|
||||
{
|
||||
CHECK( wxSize(10, 10).IsAtLeast(wxDefaultSize) );
|
||||
CHECK( wxSize(10, 10).IsAtLeast(wxSize()) );
|
||||
CHECK( wxSize(10, 10).IsAtLeast(wxSize(10, 5)) );
|
||||
CHECK( wxSize(10, 10).IsAtLeast(wxSize(10, 10)) );
|
||||
|
||||
CHECK_FALSE( wxSize(10, 10).IsAtLeast(wxSize(11, 10)) );
|
||||
CHECK_FALSE( wxSize(10, 10).IsAtLeast(wxSize(10, 11)) );
|
||||
CHECK_FALSE( wxSize(10, 10).IsAtLeast(wxSize(11, 11)) );
|
||||
CHECK_FALSE( wxDefaultSize.IsAtLeast(wxSize()) );
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue