X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5f8047a69b6396744c726ae52a388d898eab27d9..9e1fc0e42822fdf1159582f1b73cde0c7d15bc92:/src/generic/animateg.cpp diff --git a/src/generic/animateg.cpp b/src/generic/animateg.cpp index 1bda586467..dbdc6665d1 100644 --- a/src/generic/animateg.cpp +++ b/src/generic/animateg.cpp @@ -185,7 +185,6 @@ void wxAnimation::AddHandler( wxAnimationDecoder *handler ) // for preventing duplicate additions. If someone ever has // a good reason to add and remove duplicate handlers (and they // may) we should probably refcount the duplicates. - // also an issue in InsertHandler below. wxLogDebug( _T("Adding duplicate animation handler for '%d' type"), handler->GetType() ); @@ -288,7 +287,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 +294,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; } @@ -328,34 +329,33 @@ void wxAnimationCtrl::SetAnimation(const wxAnimation& animation) if (IsPlaying()) Stop(); + // set new animation even if it's wxNullAnimation m_animation = animation; + if (!m_animation.IsOk()) + { + DisplayStaticImage(); + return; + } if (m_animation.GetBackgroundColour() == wxNullColour) SetUseWindowBackgroundColour(); if (!this->HasFlag(wxAC_NO_AUTORESIZE)) FitToAnimation(); - // display first frame - m_currentFrame = 0; - if (m_animation.IsOk()) - { - if (!RebuildBackingStoreUpToFrame(0)) - { - m_animation = wxNullAnimation; - return; - } - } - else - { - // clear to - wxMemoryDC dc; - dc.SelectObject(m_backingStore); + DisplayStaticImage(); +} - // Draw the background - DisposeToBackground(dc); - } +void wxAnimationCtrl::SetInactiveBitmap(const wxBitmap &bmp) +{ + // if the bitmap has an associated mask, we need to set our background to + // the colour of our parent otherwise when calling DrawCurrentFrame() + // (which uses the bitmap's mask), our background colour would be used for + // transparent areas - and that's not what we want (at least for + // consistency with the GTK version) + if ( bmp.GetMask() != NULL && GetParent() != NULL ) + SetBackgroundColour(GetParent()->GetBackgroundColour()); - Refresh(); + wxAnimationCtrlBase::SetInactiveBitmap(bmp); } void wxAnimationCtrl::FitToAnimation() @@ -363,6 +363,19 @@ void wxAnimationCtrl::FitToAnimation() SetSize(m_animation.GetSize()); } +bool wxAnimationCtrl::SetBackgroundColour(const wxColour& colour) +{ + if ( !wxWindow::SetBackgroundColour(colour) ) + return false; + + // if not playing, then this change must be seen immediately (unless + // there's an inactive bitmap set which has higher priority than bg colour) + if ( !IsPlaying() ) + DisplayStaticImage(); + + return true; +} + // ---------------------------------------------------------------------------- // wxAnimationCtrl - stop/play methods @@ -370,9 +383,13 @@ void wxAnimationCtrl::FitToAnimation() void wxAnimationCtrl::Stop() { - // leave current frame displayed until Play() is called again m_timer.Stop(); m_isPlaying = false; + + // reset frame counter + m_currentFrame = 0; + + DisplayStaticImage(); } bool wxAnimationCtrl::Play(bool looped) @@ -380,18 +397,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 +522,41 @@ void wxAnimationCtrl::IncrementalUpdateBackingStore() dc.SelectObject(wxNullBitmap); } +void wxAnimationCtrl::DisplayStaticImage() +{ + wxASSERT(!IsPlaying()); + + // m_bmpStaticReal will be updated only if necessary... + UpdateStaticImage(); + + if (m_bmpStaticReal.IsOk()) + { + // copy the inactive bitmap in the backing store + // eventually using the mask if the static bitmap has one + if ( m_bmpStaticReal.GetMask() ) + { + wxMemoryDC temp; + temp.SelectObject(m_backingStore); + DisposeToBackground(temp); + temp.DrawBitmap(m_bmpStaticReal, 0, 0, true /* use mask */); + } + else + m_backingStore = m_bmpStaticReal; + } + 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 +575,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) @@ -531,6 +591,7 @@ void wxAnimationCtrl::DisposeToBackground(wxDC& dc) wxColour col = IsUsingWindowBackgroundColour() ? GetBackgroundColour() : m_animation.GetBackgroundColour(); + wxBrush brush(col); dc.SetBackground(brush); dc.Clear(); @@ -556,10 +617,19 @@ 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... + { + // NOTE: we draw the bitmap explicitely ignoring the mask (if any); + // i.e. we don't want to combine the backing store with the + // possibly wrong preexisting contents of the window! + dc.DrawBitmap(m_backingStore, 0, 0, false /* no mask */); + } + 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 +640,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 +668,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()) - if (!RebuildBackingStoreUpToFrame(m_currentFrame)) - Stop(); // in case we are playing + { + // 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