Add support for specifying high DPI animations in XRC

Deprecate wxXmlResourceHandler::GetAnimation() function which returns
just a single animation and add a new GetAnimations() replacing it.

Use the new function in wxAnimationCtrl XRC handler to pass all the
animations defined in the XRC file to the control.
This commit is contained in:
Vadim Zeitlin 2023-08-25 20:19:56 +02:00
parent 27e80f81b4
commit cb99932114
5 changed files with 105 additions and 40 deletions

View file

@ -653,7 +653,9 @@ controls cannot have children.
@beginTable @beginTable
@hdr3col{property, type, description} @hdr3col{property, type, description}
@row3col{animation, @ref overview_xrcformat_type_url, @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, @row3col{inactive-bitmap, @ref overview_xrcformat_type_bitmap,
Bitmap to use when not playing the animation (default: the default).} Bitmap to use when not playing the animation (default: the default).}
@endTable @endTable

View file

@ -621,11 +621,19 @@ public:
wxImageList *GetImageList(const wxString& param = wxT("imagelist")) override; wxImageList *GetImageList(const wxString& param = wxT("imagelist")) override;
#if wxUSE_ANIMATIONCTRL #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 // Gets an animation creating it using the provided control (so that it
// will be compatible with it) if any. // will be compatible with it) if any.
wxAnimation* GetAnimation(const wxString& param = wxT("animation"), wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
wxAnimationCtrlBase* ctrl = nullptr) override; wxAnimationCtrlBase* ctrl = nullptr) override;
#endif #endif // WXWIN_COMPATIBILITY_3_2
#endif // wxUSE_ANIMATIONCTRL
// Gets a font. // Gets a font.
wxFont GetFont(const wxString& param = wxT("font"), wxWindow* parent = nullptr) override; wxFont GetFont(const wxString& param = wxT("font"), wxWindow* parent = nullptr) override;

View file

@ -22,6 +22,7 @@
#include "wx/window.h" #include "wx/window.h"
class WXDLLIMPEXP_FWD_CORE wxAnimation; class WXDLLIMPEXP_FWD_CORE wxAnimation;
class WXDLLIMPEXP_FWD_CORE wxAnimationBundle;
class WXDLLIMPEXP_FWD_CORE wxAnimationCtrlBase; class WXDLLIMPEXP_FWD_CORE wxAnimationCtrlBase;
class WXDLLIMPEXP_FWD_XML wxXmlNode; class WXDLLIMPEXP_FWD_XML wxXmlNode;
@ -109,9 +110,15 @@ public:
virtual wxImageList *GetImageList(const wxString& param = wxT("imagelist")) = 0; virtual wxImageList *GetImageList(const wxString& param = wxT("imagelist")) = 0;
#if wxUSE_ANIMATIONCTRL #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"), virtual wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
wxAnimationCtrlBase* ctrl = nullptr) = 0; 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 wxFont GetFont(const wxString& param = wxT("font"), wxWindow* parent = nullptr) = 0;
virtual bool GetBoolAttr(const wxString& attr, bool defaultv) = 0; virtual bool GetBoolAttr(const wxString& attr, bool defaultv) = 0;
@ -377,12 +384,14 @@ protected:
} }
#if wxUSE_ANIMATIONCTRL #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"), wxAnimation* GetAnimation(const wxString& param = wxT("animation"),
wxAnimationCtrlBase* ctrl = nullptr) wxAnimationCtrlBase* ctrl = nullptr);
{ #endif // WXWIN_COMPATIBILITY_3_2
return GetImpl()->GetAnimation(param, ctrl); #endif // wxUSE_ANIMATIONCTRL
}
#endif
wxFont GetFont(const wxString& param = wxT("font"), wxFont GetFont(const wxString& param = wxT("font"),
wxWindow* parent = nullptr) wxWindow* parent = nullptr)

View file

@ -58,9 +58,9 @@ wxObject *wxAnimationCtrlXmlHandler::DoCreateResource()
if ( GetBool("hidden", 0) == 1 ) if ( GetBool("hidden", 0) == 1 )
ctrl->Hide(); ctrl->Hide();
std::unique_ptr<wxAnimation> animation(GetAnimation("animation", ctrl)); const auto animations = GetAnimations("animation", ctrl);
if ( animation ) if ( animations.IsOk() )
ctrl->SetAnimation(*animation); ctrl->SetAnimation(animations);
// if no inactive-bitmap has been provided, GetBitmapBundle() will return // if no inactive-bitmap has been provided, GetBitmapBundle() will return
// an empty bundle, which just tells wxAnimationCtrl to use the default // an empty bundle, which just tells wxAnimationCtrl to use the default
@ -78,39 +78,61 @@ bool wxAnimationCtrlXmlHandler::CanHandle(wxXmlNode *node)
IsOfClass(node, wxT("wxGenericAnimationCtrl")); 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, wxAnimation* wxXmlResourceHandlerImpl::GetAnimation(const wxString& param,
wxAnimationCtrlBase* ctrl) wxAnimationCtrlBase* ctrl)
{ {
wxString name = GetFilePath(GetParamNode(param)); const auto animations = GetAnimations(param, ctrl);
if ( name.empty() )
return nullptr;
// load the animation from file return animations.IsOk() ? new wxAnimation(animations.GetAll()[0]) : nullptr;
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();
} }
#endif // WXWIN_COMPATIBILITY_3_2
#endif // wxUSE_XRC && wxUSE_ANIMATIONCTRL #endif // wxUSE_XRC && wxUSE_ANIMATIONCTRL

View file

@ -14,6 +14,10 @@
#include "wx/xrc/xmlreshandler.h" #include "wx/xrc/xmlreshandler.h"
#if wxUSE_ANIMATIONCTRL
#include "wx/animate.h"
#endif
wxIMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject); wxIMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject);
wxXmlResourceHandlerImplBase* wxXmlResourceHandler::GetImpl() const wxXmlResourceHandlerImplBase* wxXmlResourceHandler::GetImpl() const
@ -65,4 +69,24 @@ void wxXmlResourceHandler::AddWindowStyles()
XRC_ADD_STYLE(wxWS_EX_PROCESS_UI_UPDATES); 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 #endif // wxUSE_XRC