| Index: views/animation/screen_rotation.cc
|
| diff --git a/views/animation/screen_rotation.cc b/views/animation/screen_rotation.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c0ee7abbdb8e471f47aff688279c2a2c75ec8a69
|
| --- /dev/null
|
| +++ b/views/animation/screen_rotation.cc
|
| @@ -0,0 +1,140 @@
|
| +// Copyright (c) 2011 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 "views/animation/screen_rotation.h"
|
| +
|
| +#include "base/debug/trace_event.h"
|
| +#include "ui/base/animation/slide_animation.h"
|
| +#include "ui/gfx/interpolated_transform.h"
|
| +#include "ui/gfx/rect.h"
|
| +#include "ui/gfx/transform.h"
|
| +#include "views/view.h"
|
| +
|
| +namespace views {
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// ScreenRotation public:
|
| +//
|
| +
|
| +void ScreenRotation::Perform(View* root,
|
| + float old_degrees,
|
| + float new_degrees) {
|
| + if (old_degrees != new_degrees)
|
| + new ScreenRotation(root, old_degrees, new_degrees);
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// ScreenRotation private:
|
| +//
|
| +
|
| +ScreenRotation::ScreenRotation(View* root,
|
| + float old_degrees,
|
| + float new_degrees)
|
| + : root_(root),
|
| + old_degrees_(old_degrees),
|
| + new_degrees_(new_degrees) {
|
| + animation_.reset(new ui::SlideAnimation(this));
|
| + animation_->SetTweenType(ui::Tween::LINEAR);
|
| + animation_->SetSlideDuration(1000);
|
| + Start();
|
| +}
|
| +
|
| +void ScreenRotation::AnimationProgressed(const ui::Animation* anim) {
|
| + if (!interpolated_transform_.get())
|
| + return;
|
| +
|
| + float t = static_cast<float>(anim->GetCurrentValue());
|
| + if (root_->painting_enabled())
|
| + root_->set_painting_enabled(false);
|
| + root_->SetTransform(interpolated_transform_->Interpolate(t));
|
| + root_->ScheduleComposite();
|
| +}
|
| +
|
| +void ScreenRotation::AnimationEnded(const ui::Animation* anim) {
|
| + TRACE_EVENT_END0("ScreenRotation", "Start rotating");
|
| + // TODO(vollick) massage matrix so that entries sufficiently close
|
| + // to 0, 1, or -1 are clamped to these values. The idea is to fight
|
| + // accumulated numeric error due to successive rotations.
|
| + ui::Transform xform = root_->GetTransform();
|
| + gfx::Point origin;
|
| + xform.TransformPoint(origin);
|
| + ui::Transform translation;
|
| + translation.SetTranslate(new_origin_.x() - origin.x(),
|
| + new_origin_.y() - origin.y());
|
| + xform.ConcatTransform(translation);
|
| + root_->SetTransform(xform);
|
| + root_->SetBounds(0, 0, new_size_.width(), new_size_.height());
|
| + root_->set_painting_enabled(true);
|
| + root_->SchedulePaint();
|
| + delete this;
|
| +}
|
| +
|
| +int ScreenRotation::NormalizeAngle(int degrees) {
|
| + while (degrees <= -180) degrees += 360;
|
| + while (degrees > 180) degrees -= 360;
|
| + return degrees;
|
| +}
|
| +
|
| +void ScreenRotation::Start() {
|
| + TRACE_EVENT_BEGIN0("ScreenRotation", "Start rotating");
|
| + if (!root_->layer()) {
|
| + root_->SetPaintToLayer(true);
|
| + root_->SchedulePaint();
|
| + }
|
| +
|
| + int degrees = new_degrees_ - old_degrees_;
|
| + degrees = NormalizeAngle(degrees);
|
| +
|
| + // No rotation required.
|
| + if (degrees == 0)
|
| + return;
|
| +
|
| + gfx::Point old_pivot;
|
| + gfx::Point new_pivot;
|
| +
|
| + switch (degrees) {
|
| + case 90:
|
| + new_origin_ = old_pivot = gfx::Point(root_->width(), 0);
|
| + new_pivot.SetPoint(root_->width(), root_->height());
|
| + new_size_.SetSize(root_->height(), root_->width());
|
| + break;
|
| + case -90:
|
| + new_origin_ = new_pivot = gfx::Point(0, root_->height());
|
| + new_size_.SetSize(root_->height(), root_->width());
|
| + break;
|
| + case 180:
|
| + new_pivot = old_pivot = gfx::Point(root_->width() / 2,
|
| + root_->height() / 2);
|
| + new_origin_.SetPoint(root_->width(), root_->height());
|
| + new_size_.SetSize(root_->width(), root_->height());
|
| + break;
|
| + }
|
| +
|
| + // Convert points to world space.
|
| + const ui::Transform& xform = root_->GetTransform();
|
| + xform.TransformPoint(old_pivot);
|
| + xform.TransformPoint(new_pivot);
|
| + xform.TransformPoint(new_origin_);
|
| +
|
| + scoped_ptr<ui::InterpolatedTransform> rotation(
|
| + new ui::InterpolatedTransformAboutPivot(
|
| + old_pivot,
|
| + new ui::InterpolatedRotation(0, degrees)));
|
| +
|
| + scoped_ptr<ui::InterpolatedTransform> translation(
|
| + new ui::InterpolatedTranslation(
|
| + gfx::Point(0, 0),
|
| + gfx::Point(new_pivot.x() - old_pivot.x(),
|
| + new_pivot.y() - old_pivot.y())));
|
| +
|
| + interpolated_transform_.reset(
|
| + new ui::InterpolatedConstantTransform(xform));
|
| +
|
| + rotation->SetChild(translation.release());
|
| + interpolated_transform_->SetChild(rotation.release());
|
| +
|
| + animation_->Show();
|
| +}
|
| +
|
| +} // namespace views
|
|
|