[ 1580776 ] wxAnimationCtrl::SetInactiveBitmap

Additionally call UnShare() in it.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42195 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling 2006-10-21 13:51:38 +00:00
parent 1a5e269be8
commit 8e458bb539
7 changed files with 147 additions and 49 deletions

View File

@ -110,6 +110,14 @@ of the animation is displayed.
Returns the animation associated with this control.
\membersection{wxAnimationCtrl::GetInactiveBitmap}\label{wxanimationctrlgetinactivebitmap}
\constfunc{wxBitmap}{GetInactiveBitmap}{\void}
Returns the inactive bitmap shown in this control when the;
see \helpref{SetInactiveBitmap}{wxanimationctrlsetinactivebitmap} for more info.
\membersection{wxAnimationCtrl::IsPlaying}\label{wxanimationctrlisplaying}
\constfunc{bool}{IsPlaying}{\void}
@ -143,17 +151,31 @@ displayed).
Sets the animation to play in this control.
If the previous animation is being played, it's \helpref{Stopped}{wxanimationctrlstop}.
Until \helpref{Play}{wxanimationctrlplay} isn't called, the first frame
of the animation is displayed.
Until \helpref{Play}{wxanimationctrlplay} isn't called, a static image, the first
frame of the given animation or the background colour will be shown
(see \helpref{SetInactiveBitmap}{wxanimationctrlsetinactivebitmap} for more info).
If {\tt wxNullAnimation} is given as animation, the control will be cleared to display
the background colour (see \helpref{wxWindow::GetBackgroundColour}{wxwindowgetbackgroundcolour}).
\membersection{wxAnimationCtrl::SetInactiveBitmap}\label{wxanimationctrlsetinactivebitmap}
\func{void}{SetInactiveBitmap}{\param{const wxBitmap\& }{bmp}}
Sets the bitmap to show on the control when it's not playing an animation.
If you set as inactive bitmap {\tt wxNullBitmap} (which is the default), then the
first frame of the animation is instead shown when the control is inactive; in this case,
if there's no valid animation associated with the control (see \helpref{SetAnimation}{wxanimationctrlsetanimation}),
then the background colour of the window is shown.
If the control is not playing the animation, the given bitmap will be immediately
shown, otherwise it will be shown as soon as \helpref{Stop}{wxanimationctrlstop}
is called.
\membersection{wxAnimationCtrl::Stop}\label{wxanimationctrlstop}
\func{void}{Stop}{\void}
Stops playing the animation.
The control will show the last frame rendered of the current animation until \helpref{Play}{wxanimationctrlplay} is called.
The control will show the first frame of the animation, a custom static image or
the window's background colour as specified by the
last \helpref{SetInactiveBitmap}{wxanimationctrlsetinactivebitmap} call.

View File

@ -19,6 +19,7 @@
#include "wx/animdecod.h"
#include "wx/control.h"
#include "wx/timer.h"
#include "wx/bitmap.h"
class WXDLLIMPEXP_ADV wxAnimation;
@ -64,7 +65,6 @@ protected:
// auto-resizes by default to fit the new animation when SetAnimation() is called
#define wxAC_DEFAULT_STYLE (wxNO_BORDER)
class WXDLLIMPEXP_ADV wxAnimationCtrlBase : public wxControl
{
public:
@ -82,6 +82,13 @@ public: // public API
virtual bool IsPlaying() const = 0;
virtual void SetInactiveBitmap(const wxBitmap &bmp);
wxBitmap GetInactiveBitmap() const
{ return m_bmpStatic; }
protected:
wxBitmap m_bmpStatic;
private:
DECLARE_ABSTRACT_CLASS(wxAnimationCtrlBase)
};

View File

@ -108,6 +108,8 @@ public:
wxAnimation GetAnimation() const
{ return m_animation; }
void SetInactiveBitmap(const wxBitmap &bmp);
public: // event handlers
void OnPaint(wxPaintEvent& event);
@ -140,9 +142,11 @@ protected: // internal utilities
void FitToAnimation();
// Draw the background; use this when e.g. previous frame had wxANIM_TOBACKGROUND disposal.
void DisposeToBackground();
void DisposeToBackground(wxDC& dc);
void DisposeToBackground(wxDC& dc, const wxPoint &pos, const wxSize &sz);
void UpdateBackingStoreWithStaticImage();
void IncrementalUpdateBackingStore();
bool RebuildBackingStoreUpToFrame(size_t);
void DrawFrame(wxDC &dc, size_t);

View File

@ -68,9 +68,6 @@ public: // used by GTK callbacks
protected:
GdkPixbufAnimation *m_pixbuf;
// used temporary by Load()
//bool m_bLoadComplete;
private:
void UnRef();
@ -132,12 +129,14 @@ public: // public API
virtual bool IsPlaying() const;
bool SetBackgroundColour( const wxColour &colour );
void SetInactiveBitmap(const wxBitmap &bmp);
protected:
virtual wxSize DoGetBestSize() const;
void FitToAnimation();
void ClearToBackgroundColour();
void DisplayStaticImage();
void ResetAnim();
void ResetIter();

View File

@ -20,16 +20,21 @@
#if wxUSE_ANIMATIONCTRL
#include "wx/animate.h"
#include "wx/bitmap.h"
const wxChar wxAnimationCtrlNameStr[] = wxT("animationctrl");
// global object
wxAnimation wxNullAnimation;
//wxIMPLEMENT_HANDLER_LIST_MANAGER(wxAnimation,
IMPLEMENT_ABSTRACT_CLASS(wxAnimationBase, wxObject)
IMPLEMENT_ABSTRACT_CLASS(wxAnimationCtrlBase, wxControl)
void wxAnimationCtrlBase::SetInactiveBitmap(const wxBitmap &bmp)
{
m_bmpStatic = bmp;
m_bmpStatic.UnShare();
}
#endif // wxUSE_ANIMATIONCTRL

View File

@ -335,27 +335,19 @@ void wxAnimationCtrl::SetAnimation(const wxAnimation& animation)
if (!this->HasFlag(wxAC_NO_AUTORESIZE))
FitToAnimation();
// display first frame
// reset frame counter
m_currentFrame = 0;
if (m_animation.IsOk())
{
if (!RebuildBackingStoreUpToFrame(0))
{
m_animation = wxNullAnimation;
return;
}
}
else
{
// clear to
wxMemoryDC dc;
dc.SelectObject(m_backingStore);
// Draw the background
DisposeToBackground(dc);
}
UpdateBackingStoreWithStaticImage();
}
Refresh();
void wxAnimationCtrl::SetInactiveBitmap(const wxBitmap &bmp)
{
wxAnimationCtrlBase::SetInactiveBitmap(bmp);
// if not playing, update the backing store now
if (!IsPlaying())
UpdateBackingStoreWithStaticImage();
}
void wxAnimationCtrl::FitToAnimation()
@ -370,9 +362,10 @@ void wxAnimationCtrl::FitToAnimation()
void wxAnimationCtrl::Stop()
{
// leave current frame displayed until Play() is called again
m_timer.Stop();
m_isPlaying = false;
UpdateBackingStoreWithStaticImage();
}
bool wxAnimationCtrl::Play(bool looped)
@ -392,6 +385,10 @@ bool wxAnimationCtrl::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();
// DrawCurrentFrame() will use our updated backing store
wxClientDC clientDC(this);
DrawCurrentFrame(clientDC);
@ -505,6 +502,29 @@ void wxAnimationCtrl::IncrementalUpdateBackingStore()
dc.SelectObject(wxNullBitmap);
}
void wxAnimationCtrl::UpdateBackingStoreWithStaticImage()
{
wxASSERT(!IsPlaying());
if (m_bmpStatic.IsOk())
{
// copy the inactive bitmap in the backing store
m_backingStore = m_bmpStatic;
}
else
{
// put in the backing store the first frame of the animation
if (!m_animation.IsOk() ||
!RebuildBackingStoreUpToFrame(0))
{
m_animation = wxNullAnimation;
DisposeToBackground();
}
}
Refresh();
}
void wxAnimationCtrl::DrawFrame(wxDC &dc, size_t frame)
{
// PERFORMANCE NOTE:
@ -523,7 +543,15 @@ void wxAnimationCtrl::DrawCurrentFrame(wxDC& dc)
wxASSERT( m_backingStore.IsOk() );
// m_backingStore always contains the current frame
dc.DrawBitmap(m_backingStore, 0, 0);
dc.DrawBitmap(m_backingStore, 0, 0, true /* use mask in case it's present */);
}
void wxAnimationCtrl::DisposeToBackground()
{
// clear the backing store
wxMemoryDC dc;
dc.SelectObject(m_backingStore);
DisposeToBackground(dc);
}
void wxAnimationCtrl::DisposeToBackground(wxDC& dc)
@ -556,10 +584,14 @@ void wxAnimationCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
// VERY IMPORTANT: the wxPaintDC *must* be created in any case
wxPaintDC dc(this);
// both if we are playing or not, we need to refresh the current frame
if ( m_backingStore.IsOk() )
DrawCurrentFrame(dc);
//else: m_animation is not valid and thus we don't have a valid backing store...
else
{
// m_animation is not valid and thus we don't have a valid backing store...
// clear then our area to the background colour
DisposeToBackground(dc);
}
}
void wxAnimationCtrl::OnTimer(wxTimerEvent &WXUNUSED(event))
@ -570,8 +602,7 @@ void wxAnimationCtrl::OnTimer(wxTimerEvent &WXUNUSED(event))
// Should a non-looped animation display the last frame?
if (!m_looped)
{
m_timer.Stop();
m_isPlaying = false;
Stop();
return;
}
else

View File

@ -117,7 +117,6 @@ bool wxAnimation::Load(wxInputStream &stream, wxAnimationType type)
// connect to loader signals
g_signal_connect(loader, "area-updated", G_CALLBACK(gdk_pixbuf_area_updated), this);
//m_bLoadComplete = false;
guchar buf[2048];
while (stream.IsOk())
{
@ -139,7 +138,6 @@ bool wxAnimation::Load(wxInputStream &stream, wxAnimationType type)
wxLogDebug(wxT("Could not close the loader"));
return false;
}
//m_bLoadComplete = true;
// wait until we get the last area_updated signal
return true;
@ -259,16 +257,9 @@ void wxAnimationCtrl::SetAnimation(const wxAnimation &anim)
if (!this->HasFlag(wxAC_NO_AUTORESIZE))
FitToAnimation();
}
// display first frame
gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget),
gdk_pixbuf_animation_get_static_image(m_anim));
}
else
{
// we need to clear the control to the background colour
ClearToBackgroundColour();
}
DisplayStaticImage();
}
void wxAnimationCtrl::FitToAnimation()
@ -280,8 +271,6 @@ void wxAnimationCtrl::FitToAnimation()
h = gdk_pixbuf_animation_get_height(m_anim);
// update our size to fit animation
//if (w > 0 && h > 0)
// gtk_widget_set_size_request(m_widget, w, h);
SetSize(w, h);
}
@ -324,6 +313,49 @@ void wxAnimationCtrl::Stop()
if (IsPlaying())
m_timer.Stop();
m_bPlaying = false;
ResetIter();
DisplayStaticImage();
}
void wxAnimationCtrl::SetInactiveBitmap(const wxBitmap &bmp)
{
wxAnimationCtrlBase::SetInactiveBitmap(bmp);
// update the pixbuf associated with m_widget now...
if (!IsPlaying())
DisplayStaticImage();
}
void wxAnimationCtrl::DisplayStaticImage()
{
wxASSERT(!IsPlaying());
if (m_bmpStatic.IsOk())
{
// show inactive bitmap
GdkBitmap *mask = (GdkBitmap *) NULL;
if (m_bmpStatic.GetMask())
mask = m_bmpStatic.GetMask()->GetBitmap();
if (m_bmpStatic.HasPixbuf())
{
gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget),
m_bmpStatic.GetPixbuf());
}
else
{
gtk_image_set_from_pixmap(GTK_IMAGE(m_widget),
m_bmpStatic.GetPixmap(), mask);
}
}
else
{
// even if not clearly documented, gdk_pixbuf_animation_get_static_image()
// always returns the first frame of the animation
gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget),
gdk_pixbuf_animation_get_static_image(m_anim));
}
}
bool wxAnimationCtrl::IsPlaying() const
@ -358,8 +390,6 @@ void wxAnimationCtrl::ClearToBackgroundColour()
guint32 col = (clr.Red() << 24) | (clr.Green() << 16) | (clr.Blue() << 8);
gdk_pixbuf_fill(newpix, col);
wxLogDebug(wxT("Clearing to background %s"), clr.GetAsString().c_str());
gtk_image_set_from_pixbuf(GTK_IMAGE(m_widget), newpix);
g_object_unref(newpix);
}