panel_bounds_animation.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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.
4
5#include "chrome/browser/ui/panels/panel_bounds_animation.h"
6
7#include "chrome/browser/ui/panels/panel.h"
8#include "chrome/browser/ui/panels/panel_manager.h"
9
10namespace {
11
12// These values are experimental and subjective.
13const int kDefaultFramerateHz = 50;
14const int kSetBoundsAnimationMs = 180;
15const int kSetBoundsAnimationBigMinimizeMs = 1500;
16
17}
18
19PanelBoundsAnimation::PanelBoundsAnimation(gfx::AnimationDelegate* target,
20                                           Panel* panel,
21                                           const gfx::Rect& initial_bounds,
22                                           const gfx::Rect& final_bounds)
23    : gfx::LinearAnimation(kDefaultFramerateHz, target),
24      panel_(panel),
25      for_big_minimize_(false),
26      animation_stop_to_show_titlebar_(0) {
27  // Detect animation that happens when expansion state is set to MINIMIZED
28  // and there is relatively big portion of the panel to hide from view.
29  // Initialize animation differently in this case, using fast-pause-slow
30  // method, see below for more details.
31  int duration = kSetBoundsAnimationMs;
32  if (initial_bounds.height() > final_bounds.height() &&
33      panel_->expansion_state() == Panel::MINIMIZED) {
34    double hidden_title_height =
35        panel_->TitleOnlyHeight() - final_bounds.height();
36    double distance_y = initial_bounds.height() - final_bounds.height();
37    animation_stop_to_show_titlebar_ = 1.0 - hidden_title_height / distance_y;
38    if (animation_stop_to_show_titlebar_ > 0.7) {  // Relatively big movement.
39      for_big_minimize_ = true;
40      duration = kSetBoundsAnimationBigMinimizeMs;
41    }
42  }
43  SetDuration(PanelManager::AdjustTimeInterval(duration));
44}
45
46PanelBoundsAnimation::~PanelBoundsAnimation() {
47}
48
49double PanelBoundsAnimation::GetCurrentValue() const {
50  return ComputeAnimationValue(gfx::LinearAnimation::GetCurrentValue(),
51                               for_big_minimize_,
52                               animation_stop_to_show_titlebar_);
53}
54
55double PanelBoundsAnimation::ComputeAnimationValue(double progress,
56    bool for_big_minimize, double animation_stop_to_show_titlebar) {
57  if (!for_big_minimize) {
58    // Cubic easing out.
59    double value = 1.0 - progress;
60    return 1.0 - value * value * value;
61  }
62
63  // Minimize animation is done in 3 steps:
64  // 1. Quickly (0 -> 0.15) make only titlebar visible.
65  // 2. Freeze for a little bit (0.15->0.6), just showing titlebar.
66  // 3. Slowly minimize to thin strip (0.6->1.0)
67  const double kProgressAtFreezeStart = 0.15;
68  const double kProgressAtFreezeEnd = 0.6;
69  double value;
70  if (progress <= kProgressAtFreezeStart) {
71    value = animation_stop_to_show_titlebar *
72        (progress / kProgressAtFreezeStart);
73  } else if (progress <= kProgressAtFreezeEnd) {
74    value = animation_stop_to_show_titlebar;
75  } else {
76    value = animation_stop_to_show_titlebar +
77        (1.0 - animation_stop_to_show_titlebar) *
78        ((progress - kProgressAtFreezeEnd) / (1.0 - kProgressAtFreezeEnd));
79  }
80  return value;
81}
82