X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/05a98b6d5d201eb8edea04b1ab022e4a9a46e9f0..1dab6da91b702ad41b249ecaf826a628bad05fce:/src/generic/animateg.cpp?ds=sidebyside diff --git a/src/generic/animateg.cpp b/src/generic/animateg.cpp index 7c156123b4..c7e55f4f92 100644 --- a/src/generic/animateg.cpp +++ b/src/generic/animateg.cpp @@ -15,7 +15,7 @@ #pragma hdrstop #endif //__BORLANDC__ -#if wxUSE_ANIMATIONCTRL +#if wxUSE_ANIMATIONCTRL && (!defined(__WXGTK20__) || defined(__WXUNIVERSAL__)) #include "wx/animate.h" @@ -288,7 +288,6 @@ bool wxAnimationCtrl::Create(wxWindow *parent, wxWindowID id, const wxAnimation& animation, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { - m_animation = animation; m_timer.SetOwner(this); if (!base_type::Create(parent, id, pos, size, style, wxDefaultValidator, name)) @@ -296,6 +295,9 @@ bool wxAnimationCtrl::Create(wxWindow *parent, wxWindowID id, // by default we get the same background colour of our parent SetBackgroundColour(parent->GetBackgroundColour()); + + SetAnimation(animation); + return true; } @@ -335,27 +337,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) +{ + m_bmpStatic = bmp; + + // if not playing, update the backing store now + if (!IsPlaying()) + UpdateBackingStoreWithStaticImage(); } void wxAnimationCtrl::FitToAnimation() @@ -370,9 +364,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) @@ -380,18 +375,18 @@ bool wxAnimationCtrl::Play(bool looped) if (!m_animation.IsOk()) return false; - int oldframe = m_currentFrame; m_looped = looped; m_currentFrame = 0; - // small optimization: if the back store was already updated to the - // first frame, don't rebuild it - if (oldframe != 0) - if (!RebuildBackingStoreUpToFrame(0)) - return false; + if (!RebuildBackingStoreUpToFrame(0)) + return false; 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 +500,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 +541,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 +582,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 +600,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 @@ -599,10 +628,21 @@ void wxAnimationCtrl::OnSize(wxSizeEvent &WXUNUSED(event)) { // NB: resizing an animation control may take a lot of time // for big animations as the backing store must be - // extended and rebuilt. Try to avoid it!! + // extended and rebuilt. Try to avoid it e.g. using + // a null proportion value for your wxAnimationCtrls + // when using them inside sizers. if (m_animation.IsOk()) + { + // be careful to change the backing store *only* if we are + // playing the animation as otherwise we may be displaying + // the inactive bitmap and overwriting the backing store + // with the last played frame is wrong in this case + if (IsPlaying()) + { if (!RebuildBackingStoreUpToFrame(m_currentFrame)) Stop(); // in case we are playing + } + } } #endif // wxUSE_ANIMATIONCTRL