Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: chrome/browser/chromeos/setting_level_bubble.cc

Issue 7646004: chromeos: Improve brightness and volume animations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: hopefully fix windows compile and DCHECK Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/setting_level_bubble.h" 5 #include "chrome/browser/chromeos/setting_level_bubble.h"
6 6
7 #include <algorithm>
8
7 #include <gdk/gdk.h> 9 #include <gdk/gdk.h>
8 10
9 #include "base/timer.h"
10 #include "chrome/browser/chromeos/login/background_view.h" 11 #include "chrome/browser/chromeos/login/background_view.h"
11 #include "chrome/browser/chromeos/login/login_utils.h" 12 #include "chrome/browser/chromeos/login/login_utils.h"
12 #include "chrome/browser/chromeos/login/webui_login_display.h" 13 #include "chrome/browser/chromeos/login/webui_login_display.h"
13 #include "chrome/browser/chromeos/setting_level_bubble_view.h" 14 #include "chrome/browser/chromeos/setting_level_bubble_view.h"
14 #include "chrome/browser/profiles/profile_manager.h" 15 #include "chrome/browser/profiles/profile_manager.h"
15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_list.h" 17 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/browser/ui/browser_window.h" 18 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/views/bubble/bubble.h" 19 #include "chrome/browser/ui/views/bubble/bubble.h"
19 #include "ui/gfx/screen.h" 20 #include "ui/gfx/screen.h"
20 #include "views/widget/root_view.h" 21 #include "views/widget/root_view.h"
21 22
23 using base::TimeDelta;
24 using base::TimeTicks;
25 using std::max;
26 using std::min;
27
22 namespace { 28 namespace {
23 29
24 const int kBubbleShowTimeoutSec = 2; 30 // How long should the bubble be shown onscreen whenever the setting changes?
25 const int kAnimationDurationMs = 200; 31 const int kBubbleShowTimeoutMs = 1000;
32
33 // How long should the level initially take to move up or down when it changes?
34 // (The rate adapts to handle keyboard autorepeat.)
35 const int64 kInitialAnimationDurationMs = 200;
26 36
27 // Horizontal position of the center of the bubble on the screen: 0 is left 37 // Horizontal position of the center of the bubble on the screen: 0 is left
28 // edge, 0.5 is center, 1 is right edge. 38 // edge, 0.5 is center, 1 is right edge.
29 const double kBubbleXRatio = 0.5; 39 const double kBubbleXRatio = 0.5;
30 40
31 // Vertical gap from the bottom of the screen in pixels. 41 // Vertical gap from the bottom of the screen in pixels.
32 const int kBubbleBottomGap = 30; 42 const int kBubbleBottomGap = 30;
33 43
34 int LimitPercent(int percent) { 44 // Duration between animation frames.
35 if (percent < 0) 45 // Chosen to match ui::SlideAnimation's kDefaultFramerateHz.
36 percent = 0; 46 const int kAnimationIntervalMs = 1000 / 50;
37 else if (percent > 100) 47
38 percent = 100; 48 double LimitPercent(double percent) {
39 return percent; 49 return min(max(percent, 0.0), 100.0);
40 } 50 }
41 51
42 } // namespace 52 } // namespace
43 53
44 namespace chromeos { 54 namespace chromeos {
45 55
46 // Temporary helper routine. Tries to first return the widget from the 56 // Temporary helper routine. Tries to first return the widget from the
47 // most-recently-focused normal browser window, then from a login 57 // most-recently-focused normal browser window, then from a login
48 // background, and finally NULL if both of those fail. 58 // background, and finally NULL if both of those fail.
49 // TODO(glotov): remove this in favor of enabling Bubble class act 59 // TODO(glotov): remove this in favor of enabling Bubble class act
(...skipping 18 matching lines...) Expand all
68 78
69 if (window) 79 if (window)
70 return views::Widget::GetWidgetForNativeWindow(window); 80 return views::Widget::GetWidgetForNativeWindow(window);
71 else 81 else
72 return WebUILoginDisplay::GetLoginWindow(); 82 return WebUILoginDisplay::GetLoginWindow();
73 } 83 }
74 84
75 SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon, 85 SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
76 SkBitmap* decrease_icon, 86 SkBitmap* decrease_icon,
77 SkBitmap* disabled_icon) 87 SkBitmap* disabled_icon)
78 : previous_percent_(-1), 88 : current_percent_(-1.0),
79 current_percent_(-1), 89 target_percent_(-1.0),
80 increase_icon_(increase_icon), 90 increase_icon_(increase_icon),
81 decrease_icon_(decrease_icon), 91 decrease_icon_(decrease_icon),
82 disabled_icon_(disabled_icon), 92 disabled_icon_(disabled_icon),
83 bubble_(NULL), 93 bubble_(NULL),
84 view_(NULL), 94 view_(NULL),
85 animation_(this) { 95 is_animating_(false) {
86 animation_.SetSlideDuration(kAnimationDurationMs);
87 animation_.SetTweenType(ui::Tween::LINEAR);
88 } 96 }
89 97
90 SettingLevelBubble::~SettingLevelBubble() {} 98 SettingLevelBubble::~SettingLevelBubble() {}
91 99
92 void SettingLevelBubble::ShowBubble(int percent, bool enabled) { 100 void SettingLevelBubble::ShowBubble(double percent, bool enabled) {
93 percent = LimitPercent(percent); 101 const double old_target_percent = target_percent_;
94 if (previous_percent_ == -1) 102 UpdateTargetPercent(percent);
95 previous_percent_ = percent;
96 current_percent_ = percent;
97 103
98 SkBitmap* icon = increase_icon_; 104 SkBitmap* icon = increase_icon_;
99 if (!enabled || current_percent_ == 0) 105 if (!enabled || target_percent_ == 0)
100 icon = disabled_icon_; 106 icon = disabled_icon_;
101 else if (current_percent_ < previous_percent_) 107 else if (old_target_percent >= 0 && target_percent_ < old_target_percent)
102 icon = decrease_icon_; 108 icon = decrease_icon_;
103 109
104 if (!bubble_) { 110 if (!bubble_) {
105 views::Widget* parent_widget = GetToplevelWidget(); 111 views::Widget* parent_widget = GetToplevelWidget();
106 if (parent_widget == NULL) { 112 if (parent_widget == NULL) {
107 LOG(WARNING) << "Unable to locate parent widget to display a bubble"; 113 LOG(WARNING) << "Unable to locate parent widget to display a bubble";
108 return; 114 return;
109 } 115 }
110 DCHECK(view_ == NULL); 116 DCHECK(view_ == NULL);
111 view_ = new SettingLevelBubbleView; 117 view_ = new SettingLevelBubbleView;
112 view_->Init(icon, previous_percent_, enabled); 118 view_->Init(icon, current_percent_, enabled);
113 119
114 // Calculate the position in screen coordinates that the bubble should 120 // Calculate the position in screen coordinates that the bubble should
115 // "point" at (since we use BubbleBorder::FLOAT, this position actually 121 // "point" at (since we use BubbleBorder::FLOAT, this position actually
116 // specifies the center of the bubble). 122 // specifies the center of the bubble).
117 const gfx::Rect monitor_area = 123 const gfx::Rect monitor_area =
118 gfx::Screen::GetMonitorAreaNearestWindow( 124 gfx::Screen::GetMonitorAreaNearestWindow(
119 GTK_WIDGET(parent_widget->GetNativeWindow())); 125 GTK_WIDGET(parent_widget->GetNativeWindow()));
120 const gfx::Size view_size = view_->GetPreferredSize(); 126 const gfx::Size view_size = view_->GetPreferredSize();
121 const gfx::Rect position_relative_to( 127 const gfx::Rect position_relative_to(
122 monitor_area.x() + kBubbleXRatio * monitor_area.width(), 128 monitor_area.x() + kBubbleXRatio * monitor_area.width(),
123 monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap, 129 monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap,
124 0, 0); 130 0, 0);
125 131
126 // ShowFocusless doesn't set ESC accelerator.
127 bubble_ = Bubble::ShowFocusless(parent_widget, 132 bubble_ = Bubble::ShowFocusless(parent_widget,
128 position_relative_to, 133 position_relative_to,
129 BubbleBorder::FLOAT, 134 BubbleBorder::FLOAT,
130 view_, // contents 135 view_, // contents
131 this, // delegate 136 this, // delegate
132 true); // show while screen is locked 137 true); // show while screen is locked
133 bubble_->set_fade_away_on_close(true); 138 // TODO(derat): We probably shouldn't be using Bubble. It'd be nice to call
139 // bubble_->set_fade_away_on_close(true) here, but then, if ShowBubble()
140 // gets called while the bubble is fading away, we end up just adjusting the
141 // value on the disappearing bubble; ideally we'd have a way to cancel the
142 // fade and show the bubble at full opacity for another
143 // kBubbleShowTimeoutMs.
134 } else { 144 } else {
135 DCHECK(view_); 145 DCHECK(view_);
136 timeout_timer_.Stop(); 146 hide_timer_.Stop();
137 view_->SetIcon(icon); 147 view_->SetIcon(icon);
148 view_->SetEnabled(enabled);
138 } 149 }
139 150
140 view_->SetEnabled(enabled); 151 hide_timer_.Start(base::TimeDelta::FromMilliseconds(kBubbleShowTimeoutMs),
141 152 this, &SettingLevelBubble::OnHideTimeout);
142 if (animation_.is_animating())
143 animation_.End();
144 animation_.Reset();
145 animation_.Show();
146
147 timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec),
148 this, &SettingLevelBubble::OnTimeout);
149 } 153 }
150 154
151 void SettingLevelBubble::HideBubble() { 155 void SettingLevelBubble::HideBubble() {
152 if (bubble_) 156 if (bubble_)
153 bubble_->Close(); 157 bubble_->Close();
154 } 158 }
155 159
156 void SettingLevelBubble::UpdateWithoutShowingBubble(int percent, bool enabled) { 160 void SettingLevelBubble::UpdateWithoutShowingBubble(double percent,
161 bool enabled) {
162 UpdateTargetPercent(percent);
157 if (view_) 163 if (view_)
158 view_->SetEnabled(enabled); 164 view_->SetEnabled(enabled);
159
160 percent = LimitPercent(percent);
161
162 previous_percent_ =
163 animation_.is_animating() ?
164 animation_.GetCurrentValue() :
165 current_percent_;
166 if (previous_percent_ < 0)
167 previous_percent_ = percent;
168 current_percent_ = percent;
169
170 if (animation_.is_animating())
171 animation_.End();
172 animation_.Reset();
173 animation_.Show();
174 } 165 }
175 166
176 void SettingLevelBubble::OnTimeout() { 167 void SettingLevelBubble::OnHideTimeout() {
177 HideBubble(); 168 HideBubble();
178 } 169 }
179 170
171 void SettingLevelBubble::OnAnimationTimeout() {
172 const TimeTicks now = TimeTicks::Now();
173 const int64 remaining_ms = (target_time_ - now).InMilliseconds();
174
175 if (remaining_ms <= 0) {
176 current_percent_ = target_percent_;
177 StopAnimation();
178 } else {
179 // Figure out what fraction of the total time until we want to reach the
180 // target has elapsed since the last update.
181 const double remaining_percent = target_percent_ - current_percent_;
182 const int64 elapsed_ms =
183 (now - last_animation_update_time_).InMilliseconds();
184 current_percent_ +=
185 remaining_percent *
186 (static_cast<double>(elapsed_ms) / (elapsed_ms + remaining_ms));
187 }
188 last_animation_update_time_ = now;
189
190 if (view_)
191 view_->SetLevel(current_percent_);
192 }
193
180 void SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) { 194 void SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) {
181 DCHECK(bubble == bubble_); 195 DCHECK(bubble == bubble_);
182 timeout_timer_.Stop(); 196 hide_timer_.Stop();
183 animation_.Stop(); 197 StopAnimation();
184 bubble_ = NULL; 198 bubble_ = NULL;
185 view_ = NULL; 199 view_ = NULL;
200 current_percent_ = -1.0;
201 target_percent_ = -1.0;
202 target_time_ = TimeTicks();
203 last_animation_update_time_ = TimeTicks();
204 last_target_update_time_ = TimeTicks();
186 } 205 }
187 206
188 bool SettingLevelBubble::CloseOnEscape() { 207 bool SettingLevelBubble::CloseOnEscape() {
189 return true; 208 return true;
190 } 209 }
191 210
192 bool SettingLevelBubble::FadeInOnShow() { 211 bool SettingLevelBubble::FadeInOnShow() {
193 return false; 212 return false;
194 } 213 }
195 214
196 void SettingLevelBubble::AnimationEnded(const ui::Animation* animation) { 215 void SettingLevelBubble::UpdateTargetPercent(double percent) {
197 previous_percent_ = current_percent_; 216 target_percent_ = LimitPercent(percent);
217 const TimeTicks now = TimeTicks::Now();
218
219 if (current_percent_ < 0.0) {
220 // If we're setting the level for the first time, no need to animate.
221 current_percent_ = target_percent_;
222 if (view_)
223 view_->SetLevel(current_percent_);
224 } else {
225 // Use the time since the last request as a hint for the duration of the
226 // animation. This makes us automatically adapt to the repeat rate if a key
227 // is being held down to change a setting (which prevents us from lagging
228 // behind when the key is finally released).
229 int64 duration_ms = kInitialAnimationDurationMs;
230 if (!last_target_update_time_.is_null())
231 duration_ms = min(kInitialAnimationDurationMs,
232 (now - last_target_update_time_).InMilliseconds());
233 target_time_ = now + TimeDelta::FromMilliseconds(duration_ms);
234
235 if (!is_animating_) {
236 animation_timer_.Start(TimeDelta::FromMilliseconds(kAnimationIntervalMs),
237 this,
238 &SettingLevelBubble::OnAnimationTimeout);
239 is_animating_ = true;
240 last_animation_update_time_ = now;
241 }
242 }
243
244 last_target_update_time_ = now;
198 } 245 }
199 246
200 void SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) { 247 void SettingLevelBubble::StopAnimation() {
201 if (view_) { 248 animation_timer_.Stop();
202 view_->SetLevel( 249 is_animating_ = false;
203 ui::Tween::ValueBetween(animation->GetCurrentValue(),
204 previous_percent_,
205 current_percent_));
206 }
207 } 250 }
208 251
209 } // namespace chromeos 252 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/setting_level_bubble.h ('k') | chrome/browser/chromeos/setting_level_bubble_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698