From 8e458bb53997706d4432d2dc0b9b516320709389 Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Sat, 21 Oct 2006 13:51:38 +0000 Subject: [PATCH] [ 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 --- docs/latex/wx/animatctrl.tex | 32 ++++++++++++--- include/wx/animate.h | 9 +++- include/wx/generic/animate.h | 4 ++ include/wx/gtk/animate.h | 5 +-- src/common/animatecmn.cpp | 7 +++- src/generic/animateg.cpp | 79 +++++++++++++++++++++++++----------- src/gtk/animate.cpp | 60 ++++++++++++++++++++------- 7 files changed, 147 insertions(+), 49 deletions(-) diff --git a/docs/latex/wx/animatctrl.tex b/docs/latex/wx/animatctrl.tex index 37036af48d..ba36f1f976 100644 --- a/docs/latex/wx/animatctrl.tex +++ b/docs/latex/wx/animatctrl.tex @@ -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). + + +\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. diff --git a/include/wx/animate.h b/include/wx/animate.h index 1e0d6fc039..583b1afc74 100644 --- a/include/wx/animate.h +++ b/include/wx/animate.h @@ -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) }; diff --git a/include/wx/generic/animate.h b/include/wx/generic/animate.h index 09b22bd593..f56056e595 100644 --- a/include/wx/generic/animate.h +++ b/include/wx/generic/animate.h @@ -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); diff --git a/include/wx/gtk/animate.h b/include/wx/gtk/animate.h index fcd39a3784..56dd791cf9 100644 --- a/include/wx/gtk/animate.h +++ b/include/wx/gtk/animate.h @@ -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(); diff --git a/src/common/animatecmn.cpp b/src/common/animatecmn.cpp index d3b69867f5..e9c0b8678a 100644 --- a/src/common/animatecmn.cpp +++ b/src/common/animatecmn.cpp @@ -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 diff --git a/src/generic/animateg.cpp b/src/generic/animateg.cpp index 1bda586467..2035cbb4f4 100644 --- a/src/generic/animateg.cpp +++ b/src/generic/animateg.cpp @@ -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 diff --git a/src/gtk/animate.cpp b/src/gtk/animate.cpp index cb596e7bd5..a2e17e22aa 100644 --- a/src/gtk/animate.cpp +++ b/src/gtk/animate.cpp @@ -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); } -- 2.47.2