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}
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).
+
+
+\membersection{wxAnimationCtrl::SetInactiveBitmap}\label{wxanimationctrlsetinactivebitmap}
+
+\func{void}{SetInactiveBitmap}{\param{const wxBitmap\& }{bmp}}
-If {\tt wxNullAnimation} is given as animation, the control will be cleared to display
-the background colour (see \helpref{wxWindow::GetBackgroundColour}{wxwindowgetbackgroundcolour}).
+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.
#include "wx/animdecod.h"
#include "wx/control.h"
#include "wx/timer.h"
+#include "wx/bitmap.h"
class WXDLLIMPEXP_ADV wxAnimation;
// 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:
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)
};
wxAnimation GetAnimation() const
{ return m_animation; }
+ void SetInactiveBitmap(const wxBitmap &bmp);
+
public: // event handlers
void OnPaint(wxPaintEvent& event);
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);
protected:
GdkPixbufAnimation *m_pixbuf;
- // used temporary by Load()
- //bool m_bLoadComplete;
-
private:
void UnRef();
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();
#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
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()
void wxAnimationCtrl::Stop()
{
- // leave current frame displayed until Play() is called again
m_timer.Stop();
m_isPlaying = false;
+
+ UpdateBackingStoreWithStaticImage();
}
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);
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:
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)
// 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))
// Should a non-looped animation display the last frame?
if (!m_looped)
{
- m_timer.Stop();
- m_isPlaying = false;
+ Stop();
return;
}
else
// 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())
{
wxLogDebug(wxT("Could not close the loader"));
return false;
}
- //m_bLoadComplete = true;
// wait until we get the last area_updated signal
return true;
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()
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);
}
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
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);
}