text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // 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/macros.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.
  // 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.
  class COMPOSITOR_EXPORT LayerAnimationSequence
      : public base::SupportsWeakPtr<LayerAnimationSequence> {
   public:
    LayerAnimationSequence();
    // Takes ownership of the given element and adds it to the sequence.
    explicit LayerAnimationSequence(
        std::unique_ptr<LayerAnimationElement> element);
    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
    // cyclic, updates the delegate to the end of one cycle 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 cyclic.
    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 be looped indefinitely.
    void set_is_cyclic(bool is_cyclic) { is_cyclic_ = is_cyclic; }
    bool is_cyclic() const { return is_cyclic_; }
  
    // 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();
  
    // Sets |animation_metrics_reporter_| and passes it to all |elements_|.
    void SetAnimationMetricsReporter(AnimationMetricsReporter* reporter);
  
    // 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;
  
   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 been aborted.
    void NotifyAborted();
  
    // The currently animating element.
    LayerAnimationElement* CurrentElement() 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_cyclic_;
  
    // 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> observers_;
  
    // Tracks the last_progressed_fraction() of the most recently progressed
    // element.
    double last_progressed_fraction_;
  
    // Used to tag animation elements to obtain metrics of animation performance.
    AnimationMetricsReporter* animation_metrics_reporter_;
  
    DISALLOW_COPY_AND_ASSIGN(LayerAnimationSequence);
  };
  
  }  // namespace ui
  
  #endif  // UI_COMPOSITOR_LAYER_ANIMATION_SEQUENCE_H_
  