910e62b5创建于 1月15日历史提交
// Copyright 2012 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_COMPOSITOR_LAYER_ANIMATION_SEQUENCE_H_
#define UI_COMPOSITOR_LAYER_ANIMATION_SEQUENCE_H_

#include <stddef.h>

#include <memory>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/layer_animation_element.h"

namespace ui {

class LayerAnimationDelegate;
class LayerAnimationObserver;

// Contains a collection of layer animation elements to be played one after
// another. Although it has a similar interface to LayerAnimationElement, it is
// not a LayerAnimationElement (i.e., it is not permitted to have a sequence in
// a sequence). Sequences own their elements, and sequences are themselves owned
// by a LayerAnimator.
//
// TODO(vollick) Create a 'blended' sequence for transitioning between
// sequences.
class COMPOSITOR_EXPORT LayerAnimationSequence {
 public:
  LayerAnimationSequence();
  // Takes ownership of the given element and adds it to the sequence.
  explicit LayerAnimationSequence(
      std::unique_ptr<LayerAnimationElement> element);

  LayerAnimationSequence(const LayerAnimationSequence&) = delete;
  LayerAnimationSequence& operator=(const LayerAnimationSequence&) = delete;

  virtual ~LayerAnimationSequence();

  // Sets the start time for the animation. This must be called before the
  // first call to {Start, IsFinished}. Once the animation is finished, this
  // must be called again in order to restart the animation.
  void set_start_time(base::TimeTicks start_time) { start_time_ = start_time; }
  base::TimeTicks start_time() const { return start_time_; }

  // Sets a flag indicating that this sequence will start together with other
  // sequences, and at least one of the sequences in this group has a threaded
  // first element.
  void set_waiting_for_group_start(bool waiting) {
    waiting_for_group_start_ = waiting;
  }
  bool waiting_for_group_start() { return waiting_for_group_start_; }

  // This must be called before the first call to Progress. If starting the
  // animation involves dispatching to another thread, then this will proceed
  // with that dispatch, ultimately resulting in the animation getting an
  // effective start time (the time the animation starts on the other thread).
  void Start(LayerAnimationDelegate* delegate);

  // Updates the delegate to the appropriate value for |now|. Requests a
  // redraw if it is required.
  void Progress(base::TimeTicks now, LayerAnimationDelegate* delegate);

  // Returns true if calling Progress now, with the given time, will finish
  // the animation.
  bool IsFinished(base::TimeTicks time);

  // Updates the delegate to the end of the animation; if this sequence is
  // repeating, updates the delegate to the end of one repetition of the
  // sequence.
  void ProgressToEnd(LayerAnimationDelegate* delegate);

  // Sets the target value to the value that would have been set had
  // the sequence completed. Does nothing if the sequence is repeating.
  void GetTargetValue(LayerAnimationElement::TargetValue* target) const;

  // Aborts the given animation.
  void Abort(LayerAnimationDelegate* delegate);

  // All properties modified by the sequence.
  LayerAnimationElement::AnimatableProperties properties() const {
    return properties_;
  }

  // Adds an element to the sequence. The sequences takes ownership of this
  // element.
  void AddElement(std::unique_ptr<LayerAnimationElement> element);

  // Sequences can repeat indefinitely.
  void set_is_repeating(bool is_repeating) { is_repeating_ = is_repeating; }
  bool is_repeating() const { return is_repeating_; }

  // Returns true if this sequence has at least one element conflicting with a
  // property in |other|.
  bool HasConflictingProperty(
      LayerAnimationElement::AnimatableProperties other) const;

  // Returns true if the first element animates on the compositor thread.
  bool IsFirstElementThreaded(LayerAnimationDelegate* delegate) const;

  // Used to identify groups of sequences that are supposed to start together.
  // Once started, used to identify the sequence that owns a particular
  // threaded animation.
  int animation_group_id() const { return animation_group_id_; }
  void set_animation_group_id(int id) { animation_group_id_ = id; }

  // These functions are used for adding or removing observers from the observer
  // list. The observers are notified when animations end.
  void AddObserver(LayerAnimationObserver* observer);
  void RemoveObserver(LayerAnimationObserver* observer);

  // Called when a threaded animation is actually started.
  void OnThreadedAnimationStarted(base::TimeTicks monotonic_time,
                                  cc::TargetProperty::Type target_property,
                                  int group_id);

  // Called when the animator schedules this sequence.
  void OnScheduled();

  // Called when the animator is destroyed.
  void OnAnimatorDestroyed();

  // Called when the animator is attached to/detached from a Compositor.
  void OnAnimatorAttached(LayerAnimationDelegate* delegate);
  void OnAnimatorDetached();

  // The last_progressed_fraction of the element most recently progressed by
  // by this sequence. Returns 0.0 if no elements have been progressed.
  double last_progressed_fraction() const { return last_progressed_fraction_; }

  size_t size() const;

  LayerAnimationElement* FirstElement() const;

  std::string ToString() const;

  base::WeakPtr<LayerAnimationSequence> AsWeakPtr() {
    return weak_ptr_factory_.GetWeakPtr();
  }

 private:
  friend class LayerAnimatorTestController;

  using Elements = std::vector<std::unique_ptr<LayerAnimationElement>>;

  FRIEND_TEST_ALL_PREFIXES(LayerAnimatorTest,
                           ObserverReleasedBeforeAnimationSequenceEnds);

  std::string ElementsToString() const;

  // Notifies the observers that this sequence has been scheduled.
  void NotifyScheduled();

  // Notifies the observers that this sequence has been started.
  void NotifyStarted();

  // Notifies the observers that this sequence has ended.
  void NotifyEnded();

  // Notifies the observers that this sequence has ended and will repeat.
  void NotifyWillRepeat();

  // Notifies the observers that this sequence has been aborted.
  void NotifyAborted();

  // The currently animating element.
  LayerAnimationElement* CurrentElement() const;

  // Returns the total duration of all `LayerAnimationElement`s in the sequence.
  base::TimeDelta GetTotalDurationOfAllElements() const;

  // The union of all the properties modified by all elements in the sequence.
  LayerAnimationElement::AnimatableProperties properties_;

  // The elements in the sequence.
  Elements elements_;

  // True if the sequence should be looped forever.
  bool is_repeating_;

  // These are used when animating to efficiently find the next element.
  size_t last_element_;
  base::TimeTicks last_start_;

  // The start time of the current run of the sequence.
  base::TimeTicks start_time_;

  // True if this sequence will start together with other sequences, and at
  // least one of the sequences in this group has a threaded first element.
  bool waiting_for_group_start_;

  // Identifies groups of sequences that are supposed to start together.
  // Also used to identify the owner of a particular threaded animation; any
  // in-progress threaded animation owned by this sequence will have this
  // group id.
  int animation_group_id_;

  // These parties are notified when layer animations end.
  base::ObserverList<LayerAnimationObserver>::UncheckedAndDanglingUntriaged
      observers_;

  // Tracks the last_progressed_fraction() of the most recently progressed
  // element.
  double last_progressed_fraction_;

  // TODO(vollick) Eventually, the LayerAnimator will switch to a model where
  // new work is scheduled rather than calling methods directly. This should
  // make it impossible for temporary pointers to running animations to go
  // stale. When this happens, there will be no need for LayerAnimationSequences
  // to support weak pointers.
  base::WeakPtrFactory<LayerAnimationSequence> weak_ptr_factory_{this};
};

}  // namespace ui

#endif  // UI_COMPOSITOR_LAYER_ANIMATION_SEQUENCE_H_