1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/rotator/window_rotation.h"
7 #include "base/time/time.h"
8 #include "ui/compositor/layer.h"
9 #include "ui/gfx/geometry/rect.h"
10 #include "ui/gfx/interpolated_transform.h"
11 #include "ui/gfx/transform.h"
17 const int k90DegreeTransitionDurationMs
= 350;
18 const int k180DegreeTransitionDurationMs
= 550;
19 const int k360DegreeTransitionDurationMs
= 750;
21 base::TimeDelta
GetTransitionDuration(int degrees
) {
23 return base::TimeDelta::FromMilliseconds(k360DegreeTransitionDurationMs
);
25 return base::TimeDelta::FromMilliseconds(k180DegreeTransitionDurationMs
);
27 return base::TimeDelta::FromMilliseconds(0);
28 return base::TimeDelta::FromMilliseconds(k90DegreeTransitionDurationMs
);
33 WindowRotation::WindowRotation(int degrees
, ui::Layer
* layer
)
34 : ui::LayerAnimationElement(LayerAnimationElement::TRANSFORM
,
35 GetTransitionDuration(degrees
)),
40 WindowRotation::~WindowRotation() {
43 void WindowRotation::InitTransform(ui::Layer
* layer
) {
44 // No rotation required, use the identity transform.
46 interpolated_transform_
.reset(
47 new ui::InterpolatedConstantTransform(gfx::Transform()));
51 // Use the target transform/bounds in case the layer is already animating.
52 const gfx::Transform
& current_transform
= layer
->GetTargetTransform();
53 const gfx::Rect
& bounds
= layer
->GetTargetBounds();
58 int width
= bounds
.width();
59 int height
= bounds
.height();
63 new_origin_
= new_pivot
= gfx::Point(width
, 0);
66 new_origin_
= new_pivot
= gfx::Point(0, height
);
70 new_pivot
= old_pivot
= gfx::Point(width
/ 2, height
/ 2);
71 new_origin_
.SetPoint(width
, height
);
75 // Convert points to world space.
76 current_transform
.TransformPoint(&old_pivot
);
77 current_transform
.TransformPoint(&new_pivot
);
78 current_transform
.TransformPoint(&new_origin_
);
80 scoped_ptr
<ui::InterpolatedTransform
> rotation(
81 new ui::InterpolatedTransformAboutPivot(
82 old_pivot
, new ui::InterpolatedRotation(0, degrees_
)));
84 scoped_ptr
<ui::InterpolatedTransform
> translation(
85 new ui::InterpolatedTranslation(
86 gfx::Point(0, 0), gfx::Point(new_pivot
.x() - old_pivot
.x(),
87 new_pivot
.y() - old_pivot
.y())));
89 float scale_factor
= 0.9f
;
90 scoped_ptr
<ui::InterpolatedTransform
> scale_down(
91 new ui::InterpolatedScale(1.0f
, scale_factor
, 0.0f
, 0.5f
));
93 scoped_ptr
<ui::InterpolatedTransform
> scale_up(
94 new ui::InterpolatedScale(1.0f
, 1.0f
/ scale_factor
, 0.5f
, 1.0f
));
96 interpolated_transform_
.reset(
97 new ui::InterpolatedConstantTransform(current_transform
));
99 scale_up
->SetChild(scale_down
.release());
100 translation
->SetChild(scale_up
.release());
101 rotation
->SetChild(translation
.release());
102 interpolated_transform_
->SetChild(rotation
.release());
105 void WindowRotation::OnStart(ui::LayerAnimationDelegate
* delegate
) {
108 bool WindowRotation::OnProgress(double t
,
109 ui::LayerAnimationDelegate
* delegate
) {
110 delegate
->SetTransformFromAnimation(interpolated_transform_
->Interpolate(t
));
114 void WindowRotation::OnGetTarget(TargetValue
* target
) const {
115 target
->transform
= interpolated_transform_
->Interpolate(1.0);
118 void WindowRotation::OnAbort(ui::LayerAnimationDelegate
* delegate
) {