File: apps_grid_row_change_animator.cc

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 (131 lines) | stat: -rw-r--r-- 4,918 bytes parent folder | download | duplicates (7)
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