File: animation_builder.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (220 lines) | stat: -rw-r--r-- 9,579 bytes parent folder | download | duplicates (9)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// Copyright 2021 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_VIEWS_ANIMATION_ANIMATION_BUILDER_H_
#define UI_VIEWS_ANIMATION_ANIMATION_BUILDER_H_

#include <map>
#include <memory>
#include <optional>
#include <vector>

#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/views/animation/animation_key.h"
#include "ui/views/animation/animation_sequence_block.h"
#include "ui/views/views_export.h"

namespace ui {
class Layer;
}

namespace views {

class AnimationAbortHandle;

// Provides an unfinalized animation sequence block if any to build animations.

// Usage notes for callbacks set on AnimationBuilder:
// When setting callbacks for the animations note that the AnimationBuilder’s
// observer that calls these callbacks may outlive the callback's parameters.

// The OnEnded callback runs when all animations created on the AnimationBuilder
// have finished. The OnAborted callback runs when any one animation created on
// the AnimationBuilder has been aborted. Therefore, these callbacks and every
// object the callback accesses needs to outlive all the Layers/LayerOwners
// being animated on since the Layers ultimately own the objects that run the
// animation. Otherwise, developers may need to use weak pointers or force
// animations to be cancelled in the object’s destructor to prevent accessing
// destroyed objects. Note that aborted notifications can be sent during the
// destruction process. Therefore subclasses that own the Layers may actually be
// destroyed before the OnAborted callback is run.

class VIEWS_EXPORT AnimationBuilder {
 public:
  class Observer : public ui::LayerAnimationObserver {
   public:
    Observer();
    Observer(const Observer&) = delete;
    Observer& operator=(const Observer&) = delete;
    ~Observer() override;

    void SetOnStarted(base::OnceClosure callback);
    void SetOnEnded(base::OnceClosure callback, base::Location location);
    void SetOnWillRepeat(base::RepeatingClosure callback);
    void SetOnAborted(base::OnceClosure callback, base::Location location);
    void SetOnScheduled(base::OnceClosure callback);

    void SetAbortHandle(AnimationAbortHandle* abort_handle);

    // ui::LayerAnimationObserver:
    void OnLayerAnimationStarted(ui::LayerAnimationSequence* sequence) override;
    void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
    void OnLayerAnimationWillRepeat(
        ui::LayerAnimationSequence* sequence) override;
    void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override;
    void OnLayerAnimationScheduled(
        ui::LayerAnimationSequence* sequence) override;

    bool GetAttachedToSequence() const { return attached_to_sequence_; }

   protected:
    void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override;
    void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override;
    bool RequiresNotificationWhenAnimatorDestroyed() const override;

   private:
    using RepeatMap = base::flat_map<ui::LayerAnimationSequence*, int>;
    RepeatMap repeat_map_;
    base::OnceClosure on_started_;
    base::OnceClosure on_ended_;
    // Record where the on_ended_ callback was set from. Needed to debug a
    // bad callback crash (https://g-issues.chromium.org/issues/335902543).
    // TODO(b/335902543): Remove on_ended_location_.
    base::Location on_ended_location_;
    base::RepeatingClosure on_will_repeat_;
    base::OnceClosure on_aborted_;
    // Record where the on_aborted_ callback was set from. Needed to debug a
    // bad callback crash (https://g-issues.chromium.org/issues/335902543).
    // TODO(b/335902543): Remove on_aborted_location_.
    base::Location on_aborted_location_;
    base::OnceClosure on_scheduled_;

    bool attached_to_sequence_ = false;
    // Incremented when a sequence is attached and decremented when a sequence
    // ends. Does not account for aborted sequences. This provides a more
    // reliable way of tracking when all sequences have ended since IsFinished
    // can return true before a sequence is started if the duration is zero.
    int sequences_to_run_ = 0;
    raw_ptr<AnimationAbortHandle, DanglingUntriaged> abort_handle_ = nullptr;
  };

  AnimationBuilder();
  AnimationBuilder(AnimationBuilder&& rhs);
  AnimationBuilder& operator=(AnimationBuilder&& rhs);
  ~AnimationBuilder();

  // Options for the whole animation
  AnimationBuilder& SetPreemptionStrategy(
      ui::LayerAnimator::PreemptionStrategy preemption_strategy);
  // Registers |callback| to be called when the animation starts.
  // Must use before creating a sequence block.
  AnimationBuilder& OnStarted(base::OnceClosure callback);
  // Registers |callback| to be called when the animation ends. Not called if
  // animation is aborted.
  // Must use before creating a sequence block.
  AnimationBuilder& OnEnded(base::OnceClosure callback,
                            base::Location location = FROM_HERE);
  // Registers |callback| to be called when a sequence repetition ends and will
  // repeat. Not called if sequence is aborted.
  // Must use before creating a sequence block.
  AnimationBuilder& OnWillRepeat(base::RepeatingClosure callback);
  // Registers |callback| to be called if animation is aborted for any reason.
  // Should never do anything that may cause another animation to be started.
  // Must use before creating a sequence block.
  AnimationBuilder& OnAborted(base::OnceClosure callback,
                              base::Location location = FROM_HERE);
  // Registers |callback| to be called when the animation is scheduled.
  // Must use before creating a sequence block.
  AnimationBuilder& OnScheduled(base::OnceClosure callback);

  // Returns a handle that can be destroyed later to abort all running
  // animations. Must use before creating a sequence block.
  // Caveat: ALL properties will be aborted, including those not initiated
  // by the builder.
  std::unique_ptr<AnimationAbortHandle> GetAbortHandle();

  // Creates a new sequence (that optionally repeats).
  AnimationSequenceBlock& Once();
  AnimationSequenceBlock& Repeatedly();

  // Adds an animation element `element` for `key` at `start` to `values`.
  void AddLayerAnimationElement(
      base::PassKey<AnimationSequenceBlock>,
      AnimationKey key,
      base::TimeDelta start,
      base::TimeDelta original_duration,
      std::unique_ptr<ui::LayerAnimationElement> element);

  // Swaps `current_sequence_` with `new_sequence` and returns the old one.
  [[nodiscard]] std::unique_ptr<AnimationSequenceBlock> SwapCurrentSequence(
      base::PassKey<AnimationSequenceBlock>,
      std::unique_ptr<AnimationSequenceBlock> new_sequence);

  // Called when a block ends.  Ensures all animations in the sequence will run
  // until at least `end`.
  void BlockEndedAt(base::PassKey<AnimationSequenceBlock>, base::TimeDelta end);

  // Called when the sequence is ended. Converts `values_` to
  // `layer_animation_sequences_`.
  void TerminateSequence(base::PassKey<AnimationSequenceBlock>, bool repeating);

  // Returns a left value reference to the object held by `current_sequence_`.
  // Assumes that `current_sequence_` is set.
  // NOTE: be wary when keeping this method's return value because the current
  // sequence held by an `AnimationBuilder` instance could be destroyed during
  // `AnimationBuilder` instance's life cycle.
  AnimationSequenceBlock& GetCurrentSequence();

  static void SetObserverDeletedCallbackForTesting(
      base::RepeatingClosure deleted_closure);

 private:
  struct Value;

  Observer* GetObserver();

  // Resets data for the current sequence as necessary, creates a new sequence
  // block and returns the new block's left value reference.
  AnimationSequenceBlock& NewSequence(bool repeating);

  // Returns a reference to the observer deleted callback used for testing.
  static base::RepeatingClosure& GetObserverDeletedCallback();

  // Data for all sequences.
  std::multimap<ui::Layer*, std::unique_ptr<ui::LayerAnimationSequence>>
      layer_animation_sequences_;
  std::unique_ptr<Observer> animation_observer_;
  // Sets up observer callbacks before .Once() or .Repeatedly() is called to
  // start the sequence. next_animation_observer_ is moved to
  // animation_observer_ once .Once() or Repeatedly() is called.
  std::unique_ptr<Observer> next_animation_observer_;
  std::optional<ui::LayerAnimator::PreemptionStrategy> preemption_strategy_;

  // Data for the current sequence.
  base::TimeDelta end_;
  // Each vector is kept in sorted order.
  std::map<AnimationKey, std::vector<Value>> values_;

  raw_ptr<AnimationAbortHandle, DanglingUntriaged> abort_handle_ = nullptr;

  // An unfinalized sequence block currently used to build animations. NOTE: the
  // animation effects carried by `current_sequence_` attach to a layer only
  // after `current_sequence_` is destroyed.
  // The life cycle of `current_sequence_`:
  // (1) The old sequence is replaced by a new one. When being replaced, the
  // old sequence is destroyed.
  // (2) Gets destroyed when the host `AnimationBuilder` is destroyed.
  std::unique_ptr<AnimationSequenceBlock> current_sequence_;
};

}  // namespace views

#endif  // UI_VIEWS_ANIMATION_ANIMATION_BUILDER_H_