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
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/app_list/apps_grid_row_change_animator.h"
#include <utility>
#include "ash/app_list/views/apps_grid_view.h"
#include "base/auto_reset.h"
#include "base/i18n/rtl.h"
#include "base/time/time.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/transform_util.h"
namespace ash {
AppsGridRowChangeAnimator::AppsGridRowChangeAnimator(
AppsGridView* apps_grid_view)
: apps_grid_view_(apps_grid_view) {}
AppsGridRowChangeAnimator::~AppsGridRowChangeAnimator() = default;
void AppsGridRowChangeAnimator::AnimateBetweenRows(
AppListItemView* view,
const gfx::Rect& current,
const gfx::Rect& target,
views::AnimationSequenceBlock* animation_sequence) {
base::AutoReset<bool> auto_reset(&setting_up_animation_, true);
// The direction used to calculate the offset for animating the item view into
// and the layer copy out of the grid. Reversed for RTL.
int dir = current.y() < target.y() ? 1 : -1;
if (base::i18n::IsRTL())
dir *= -1;
int offset =
apps_grid_view_->GetTotalTileSize(apps_grid_view_->GetSelectedPage())
.width();
// Calculate where offscreen the layer copy will animate to.
gfx::Rect current_out = current;
current_out.Offset(dir * offset, 0);
// The transform for moving the layer copy out and off screen.
gfx::Transform layer_copy_transform;
// The bounds where `view` will begin animating to `target`.
gfx::RectF target_in;
// The layer copy of the view which is animating between rows.
std::unique_ptr<ui::Layer> row_change_layer;
if (row_change_layers_.count(view)) {
row_change_layer = std::move(row_change_layers_[view]);
row_change_layers_.erase(view);
// Reverse existing row change animation, by swapping the positions of the
// mid-animation layer copy and `view`. Then animate each to the correct
// target.
// Calculate 'target_in' so that 'view' can start its animation in the place
// of the layer copy.
target_in = row_change_layer->transform().MapRect(
gfx::RectF(row_change_layer->bounds()));
// Calculate the current bounds of `view` including its layer transform.
gfx::RectF current_bounds_in_animation =
view->layer()->transform().MapRect(gfx::RectF(current));
// Set the bounds of the layer copy to the current bounds of'view'.
row_change_layer->SetBounds(
gfx::ToRoundedRect(current_bounds_in_animation));
row_change_layer->SetTransform(gfx::Transform());
layer_copy_transform = gfx::TransformBetweenRects(
current_bounds_in_animation, gfx::RectF(current_out));
// Swap the opacity of the layer copy and the item view.
const float layer_copy_opacity = row_change_layer->opacity();
row_change_layer->SetOpacity(view->layer()->opacity());
view->layer()->SetOpacity(layer_copy_opacity);
} else {
// Create the row change animation for this view. `view` will animate from
// offscreen into the 'target' location, while a layer copy of 'view' will
// animate from the original `view` bounds to offscreen.
view->EnsureLayer();
row_change_layer = view->RecreateLayer();
layer_copy_transform = gfx::TransformBetweenRects(gfx::RectF(current),
gfx::RectF(current_out));
view->layer()->SetOpacity(0.0f);
// Calculate offscreen position to begin animating `view` from.
target_in = gfx::RectF(target);
const int target_in_direction = current.y() < target.y() ? -1 : 1;
target_in.Offset(target_in_direction * offset, 0);
target_in =
gfx::RectF(apps_grid_view_->GetMirroredRect(ToRoundedRect(target_in)));
}
// Set the transform for the item view before animating it into the target
// grid position.
view->layer()->SetTransform(gfx::TransformBetweenRects(
gfx::RectF(apps_grid_view_->GetMirroredRect(target)), target_in));
view->SetBoundsRect(target);
// Fade out and animate out the copied layer. Fade in the real item view.
animation_sequence
->SetTransform(row_change_layer.get(), layer_copy_transform,
gfx::Tween::ACCEL_40_DECEL_100_3)
.SetOpacity(row_change_layer.get(), 0.0f,
gfx::Tween::ACCEL_40_DECEL_100_3)
.SetOpacity(view->layer(), 1.0f, gfx::Tween::ACCEL_40_DECEL_100_3)
.SetTransform(view->layer(), gfx::Transform(),
gfx::Tween::ACCEL_40_DECEL_100_3);
row_change_layers_[view] = std::move(row_change_layer);
}
void AppsGridRowChangeAnimator::CancelAnimation(views::View* view) {
row_change_layers_.erase(view);
}
bool AppsGridRowChangeAnimator::IsAnimating() const {
return !row_change_layers_.empty() || setting_up_animation_;
}
} // namespace ash
|