123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- // Copyright 2021 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.
- #include "ui/views/animation/animation_sequence_block.h"
- #include <map>
- #include <memory>
- #include <utility>
- #include "base/callback.h"
- #include "base/check.h"
- #include "base/time/time.h"
- #include "base/types/pass_key.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/abseil-cpp/absl/types/variant.h"
- #include "third_party/skia/include/core/SkColor.h"
- #include "ui/compositor/layer_animation_element.h"
- #include "ui/compositor/layer_owner.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/rounded_corners_f.h"
- #include "ui/views/animation/animation_builder.h"
- #include "ui/views/animation/animation_key.h"
- namespace views {
- using PassKey = base::PassKey<AnimationSequenceBlock>;
- AnimationSequenceBlock::AnimationSequenceBlock(
- base::PassKey<AnimationBuilder> builder_key,
- AnimationBuilder* owner,
- base::TimeDelta start,
- bool repeating)
- : builder_key_(builder_key),
- owner_(owner),
- start_(start),
- repeating_(repeating) {}
- AnimationSequenceBlock::~AnimationSequenceBlock() {
- if (!finalized_) {
- TerminateBlock();
- owner_->TerminateSequence(PassKey(), repeating_);
- }
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetDuration(
- base::TimeDelta duration) {
- DCHECK(!finalized_) << "Do not access old blocks after creating new ones.";
- DCHECK(!duration_.has_value()) << "Duration may be set at most once.";
- duration_ = duration;
- return *this;
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetBounds(
- ui::Layer* target,
- const gfx::Rect& bounds,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::BOUNDS},
- Element(bounds, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetBounds(
- ui::LayerOwner* target,
- const gfx::Rect& bounds,
- gfx::Tween::Type tween_type) {
- return SetBounds(target->layer(), bounds, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetBrightness(
- ui::Layer* target,
- float brightness,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::BRIGHTNESS},
- Element(brightness, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetBrightness(
- ui::LayerOwner* target,
- float brightness,
- gfx::Tween::Type tween_type) {
- return SetBrightness(target->layer(), brightness, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetClipRect(
- ui::Layer* target,
- const gfx::Rect& clip_rect,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::CLIP},
- Element(clip_rect, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetClipRect(
- ui::LayerOwner* target,
- const gfx::Rect& clip_rect,
- gfx::Tween::Type tween_type) {
- return SetClipRect(target->layer(), clip_rect, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetColor(
- ui::Layer* target,
- SkColor color,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::COLOR},
- Element(color, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetColor(
- ui::LayerOwner* target,
- SkColor color,
- gfx::Tween::Type tween_type) {
- return SetColor(target->layer(), color, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetGrayscale(
- ui::Layer* target,
- float grayscale,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::GRAYSCALE},
- Element(grayscale, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetGrayscale(
- ui::LayerOwner* target,
- float grayscale,
- gfx::Tween::Type tween_type) {
- return SetGrayscale(target->layer(), grayscale, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetOpacity(
- ui::Layer* target,
- float opacity,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::OPACITY},
- Element(opacity, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetOpacity(
- ui::LayerOwner* target,
- float opacity,
- gfx::Tween::Type tween_type) {
- return SetOpacity(target->layer(), opacity, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetTransform(
- ui::Layer* target,
- gfx::Transform transform,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::TRANSFORM},
- Element(std::move(transform), tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetTransform(
- ui::LayerOwner* target,
- gfx::Transform transform,
- gfx::Tween::Type tween_type) {
- return SetTransform(target->layer(), std::move(transform), tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetRoundedCorners(
- ui::Layer* target,
- const gfx::RoundedCornersF& rounded_corners,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::ROUNDED_CORNERS},
- Element(rounded_corners, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetRoundedCorners(
- ui::LayerOwner* target,
- const gfx::RoundedCornersF& rounded_corners,
- gfx::Tween::Type tween_type) {
- return SetRoundedCorners(target->layer(), rounded_corners, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetGradientMask(
- ui::Layer* target,
- const gfx::LinearGradient& gradient_mask,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::GRADIENT_MASK},
- Element(gradient_mask, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetGradientMask(
- ui::LayerOwner* target,
- const gfx::LinearGradient& gradient_mask,
- gfx::Tween::Type tween_type) {
- return SetGradientMask(target->layer(), gradient_mask, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetVisibility(
- ui::Layer* target,
- bool visible,
- gfx::Tween::Type tween_type) {
- return AddAnimation({target, ui::LayerAnimationElement::VISIBILITY},
- Element(visible, tween_type));
- }
- AnimationSequenceBlock& AnimationSequenceBlock::SetVisibility(
- ui::LayerOwner* target,
- bool visible,
- gfx::Tween::Type tween_type) {
- return SetVisibility(target->layer(), visible, tween_type);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::At(
- base::TimeDelta since_sequence_start) {
- // NOTE: at the end of this function, this object is destroyed.
- DCHECK(!finalized_) << "Do not access old blocks after creating new ones.";
- TerminateBlock();
- finalized_ = true;
- // NOTE: `old_sequence` is actually the sequence block itself. Do not destruct
- // this object until the function end.
- auto old_sequence = owner_->SwapCurrentSequence(
- PassKey(), std::make_unique<AnimationSequenceBlock>(
- builder_key_, owner_, since_sequence_start, repeating_));
- return owner_->GetCurrentSequence();
- }
- AnimationSequenceBlock& AnimationSequenceBlock::Offset(
- base::TimeDelta since_last_block_start) {
- return At(start_ + since_last_block_start);
- }
- AnimationSequenceBlock& AnimationSequenceBlock::Then() {
- return Offset(duration_.value_or(base::TimeDelta()));
- }
- AnimationSequenceBlock::Element::Element(AnimationValue animation_value,
- gfx::Tween::Type tween_type)
- : animation_value_(std::move(animation_value)), tween_type_(tween_type) {}
- AnimationSequenceBlock::Element::~Element() = default;
- AnimationSequenceBlock::Element::Element(Element&&) = default;
- AnimationSequenceBlock::Element& AnimationSequenceBlock::Element::operator=(
- Element&&) = default;
- AnimationSequenceBlock& AnimationSequenceBlock::AddAnimation(AnimationKey key,
- Element element) {
- DCHECK(!finalized_) << "Do not access old blocks after creating new ones.";
- DCHECK(key.target) << "Animation targets must paint to a layer.";
- const auto result =
- elements_.insert(std::make_pair(std::move(key), std::move(element)));
- DCHECK(result.second) << "Animate (target, property) at most once per block.";
- return *this;
- }
- void AnimationSequenceBlock::TerminateBlock() {
- const auto duration = duration_.value_or(base::TimeDelta());
- for (auto& pair : elements_) {
- std::unique_ptr<ui::LayerAnimationElement> element;
- switch (pair.first.property) {
- case ui::LayerAnimationElement::TRANSFORM:
- element = ui::LayerAnimationElement::CreateTransformElement(
- absl::get<gfx::Transform>(std::move(pair.second.animation_value_)),
- duration);
- break;
- case ui::LayerAnimationElement::BOUNDS:
- element = ui::LayerAnimationElement::CreateBoundsElement(
- absl::get<gfx::Rect>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::OPACITY:
- element = ui::LayerAnimationElement::CreateOpacityElement(
- absl::get<float>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::VISIBILITY:
- element = ui::LayerAnimationElement::CreateVisibilityElement(
- absl::get<bool>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::BRIGHTNESS:
- element = ui::LayerAnimationElement::CreateBrightnessElement(
- absl::get<float>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::GRAYSCALE:
- element = ui::LayerAnimationElement::CreateGrayscaleElement(
- absl::get<float>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::COLOR:
- element = ui::LayerAnimationElement::CreateColorElement(
- absl::get<SkColor>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::CLIP:
- element = ui::LayerAnimationElement::CreateClipRectElement(
- absl::get<gfx::Rect>(pair.second.animation_value_), duration);
- break;
- case ui::LayerAnimationElement::ROUNDED_CORNERS:
- element = ui::LayerAnimationElement::CreateRoundedCornersElement(
- absl::get<gfx::RoundedCornersF>(pair.second.animation_value_),
- duration);
- break;
- case ui::LayerAnimationElement::GRADIENT_MASK:
- element = ui::LayerAnimationElement::CreateGradientMaskElement(
- absl::get<gfx::LinearGradient>(pair.second.animation_value_),
- duration);
- break;
- default:
- NOTREACHED();
- }
- element->set_tween_type(pair.second.tween_type_);
- owner_->AddLayerAnimationElement(PassKey(), pair.first, start_, duration,
- std::move(element));
- }
- owner_->BlockEndedAt(PassKey(), start_ + duration);
- elements_.clear();
- }
- } // namespace views
|