1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_ANIMATION_ANIMATION_H_
#define UI_GFX_ANIMATION_ANIMATION_H_
#include <optional>
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/gfx/animation/animation_export.h"
namespace gfx {
class Rect;
}
namespace gfx {
class AnimationContainer;
class AnimationDelegate;
class AnimationTestApi;
// Base class used in implementing animations. You only need use this class if
// you're implementing a new animation type, otherwise you'll likely want one of
// LinearAnimation, SlideAnimation, ThrobAnimation or MultiAnimation.
//
// To subclass override Step, which is invoked as the animation progresses and
// GetCurrentValue() to return the value appropriate to the animation.
class ANIMATION_EXPORT Animation : public AnimationContainerElement {
public:
// Used with SetRichAnimationRenderMode() to force enable/disable rich
// animations during tests.
enum class RichAnimationRenderMode {
PLATFORM,
FORCE_ENABLED,
FORCE_DISABLED
};
explicit Animation(base::TimeDelta timer_interval);
Animation(const Animation&) = delete;
Animation& operator=(const Animation&) = delete;
~Animation() override;
// Starts the animation. Does nothing if the animation is already running.
void Start();
// Stops the animation. Does nothing if the animation is not running.
void Stop();
// Gets the value for the current state, according to the animation
// curve in use.
virtual double GetCurrentValue() const = 0;
// Convenience for returning a value between |start| and |target| based on
// the current value. This is (target - start) * GetCurrentValue() + start.
double CurrentValueBetween(double start, double target) const;
int CurrentValueBetween(int start, int target) const;
gfx::Rect CurrentValueBetween(const gfx::Rect& start_bounds,
const gfx::Rect& target_bounds) const;
// Sets the delegate.
void set_delegate(AnimationDelegate* delegate) { delegate_ = delegate; }
// Sets the container used to manage the timer. A value of NULL results in
// creating a new AnimationContainer.
void SetContainer(AnimationContainer* container);
bool is_animating() const { return is_animating_; }
base::TimeDelta timer_interval() const { return timer_interval_; }
// Returns true if rich animations should be rendered.
// Looks at session type (e.g. remote desktop) and accessibility settings
// to give guidance for heavy animations such as "start download" arrow.
static bool ShouldRenderRichAnimation();
// Returns the duration a rich animation should use given the nominal
// `duration`. The return value is either `duration` or zero, depending on
// whether rich animations are currently enabled. NOTE: Since rich animations
// can be enabled and disabled dynamically, it is not appropriate to store the
// result of this call long-term; callers should re-set the animation duration
// before each animation run.
//
// TODO(pkasting): It may be clearer and safer to have an "is rich animation"
// bit on animations, and have the animation system adjust the duration
// internally automatically, e.g. in `AnimationStarted()` in each subclass.
static base::TimeDelta RichAnimationDuration(base::TimeDelta duration);
// Determines on a per-platform basis whether scroll animations (e.g. produced
// by home/end key) should be enabled. Should only be called from the browser
// process.
static bool ScrollAnimationsEnabledBySystem();
// Determines whether the user desires reduced motion based on platform APIs.
// Should only be called from the browser process, on the UI thread.
static bool PrefersReducedMotion();
static void UpdatePrefersReducedMotion();
#if BUILDFLAG(IS_CHROMEOS)
// This should only be used by the ChromeOS Accessibility system.
static void SetPrefersReducedMotionForA11y(bool prefers_reduced_motion);
#endif // BUILDFLAG(IS_CHROMEOS)
static void SetPrefersReducedMotionForTesting(bool prefers_reduced_motion) {
prefers_reduced_motion_ = prefers_reduced_motion;
}
protected:
// Invoked from Start to allow subclasses to prepare for the animation.
virtual void AnimationStarted() {}
// Invoked from Stop after we're removed from the container but before the
// delegate has been invoked.
virtual void AnimationStopped() {}
// Invoked from stop to determine if cancel should be invoked. If this returns
// true the delegate is notified the animation was canceled, otherwise the
// delegate is notified the animation stopped.
virtual bool ShouldSendCanceledFromStop();
AnimationContainer* container() { return container_.get(); }
base::TimeTicks start_time() const { return start_time_; }
AnimationDelegate* delegate() { return delegate_; }
// AnimationContainer::Element overrides
void SetStartTime(base::TimeTicks start_time) override;
void Step(base::TimeTicks time_now) override = 0;
base::TimeDelta GetTimerInterval() const override;
private:
friend class AnimationTestApi;
static bool ShouldRenderRichAnimationImpl();
// The mode in which to render rich animations.
static RichAnimationRenderMode rich_animation_rendering_mode_;
// Interval for the animation.
const base::TimeDelta timer_interval_;
// If true we're running.
bool is_animating_;
// Our delegate; may be null.
raw_ptr<AnimationDelegate, DanglingUntriaged> delegate_;
// Container we're in. If non-null we're animating.
scoped_refptr<AnimationContainer> container_;
// Time we started at.
base::TimeTicks start_time_;
// Obtaining the PrefersReducedMotion system setting can be expensive, so it
// is cached in this boolean.
static std::optional<bool> prefers_reduced_motion_;
};
} // namespace gfx
#endif // UI_GFX_ANIMATION_ANIMATION_H_
|