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

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

Issue 8319008: aura: brightness and volume bubble. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 2 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/setting_level_bubble_view_views.h"
6
7 #include <algorithm>
8
9 #include "chrome/browser/chromeos/login/background_view.h"
10 #include "chrome/browser/chromeos/login/login_utils.h"
11 #include "chrome/browser/chromeos/login/webui_login_display.h"
12 #include "chrome/browser/chromeos/setting_level_bubble_view.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_list.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/views/bubble/bubble.h" // for kBackgroundColor
18 #include "ui/gfx/screen.h"
19 #include "views/widget/root_view.h"
20
21 using base::TimeDelta;
22 using base::TimeTicks;
23 using std::max;
24 using std::min;
25
26 namespace {
27
28 // How long should the bubble be shown onscreen whenever the setting changes?
29 const int kBubbleShowTimeoutMs = 1000;
30
31 // How long should the level initially take to move up or down when it changes?
32 // (The rate adapts to handle keyboard autorepeat.)
33 const int64 kInitialAnimationDurationMs = 200;
34
35 // Horizontal position of the center of the bubble on the screen: 0 is left
36 // edge, 0.5 is center, 1 is right edge.
37 const double kBubbleXRatio = 0.5;
38
39 // Vertical gap from the bottom of the screen in pixels.
40 const int kBubbleBottomGap = 30;
41
42 // Duration between animation frames.
43 // Chosen to match ui::SlideAnimation's kDefaultFramerateHz.
44 const int kAnimationIntervalMs = 1000 / 50;
45
46 double LimitPercent(double percent) {
47 return min(max(percent, 0.0), 100.0);
48 }
49
50 } // namespace
51
52 namespace chromeos {
53
54 // Temporary helper routine. Tries to first return the widget from the
55 // most-recently-focused normal browser window, then from a login
56 // background, and finally NULL if both of those fail.
57 // TODO(glotov): remove this in favor of enabling Bubble class act
58 // without |parent| specified. crosbug.com/4025
59 static views::Widget* GetToplevelWidget() {
60 #if defined(USE_AURA)
61 // TODO(saintlou): Need to fix in PureViews..... how?
62 return WebUILoginDisplay::GetLoginWindow();
63 #else
64 GtkWindow* window = NULL;
65
66 // We just use the default profile here -- this gets overridden as needed
67 // in Chrome OS depending on whether the user is logged in or not.
68 Browser* browser =
69 BrowserList::FindTabbedBrowser(
70 ProfileManager::GetDefaultProfile(),
71 true); // match_incognito
72 if (browser) {
73 window = GTK_WINDOW(browser->window()->GetNativeHandle());
74 } else {
75 // Otherwise, see if there's a background window that we can use.
76 BackgroundView* background = LoginUtils::Get()->GetBackgroundView();
77 if (background)
78 window = GTK_WINDOW(background->GetNativeWindow());
79 }
80
81 if (window)
82 return views::Widget::GetWidgetForNativeWindow(window);
83 else
84 return WebUILoginDisplay::GetLoginWindow();
85 #endif
86 }
87
88 // SettingLevelBubbleViewViews -------------------------------------------------
89 // static
90 views::Widget* SettingLevelBubbleViewViews::ConstructSettingLevelBubble(
91 SkBitmap* increase_icon,
92 SkBitmap* decrease_icon,
93 SkBitmap* zero_icon,
94 double percent,
95 bool enabled) {
96 views::Widget* parent = GetToplevelWidget();
97 SettingLevelBubbleViewViews* delegate =
98 new SettingLevelBubbleViewViews(increase_icon, decrease_icon, zero_icon);
99 delegate->UpdateSettingLevel(percent, enabled);
100 // Construct and initialize settings.
101 return views::BubbleDelegateView::ConstructBubble(delegate, parent);
102 }
103
104 SettingLevelBubbleViewViews::SettingLevelBubbleViewViews(
105 SkBitmap* increase_icon,
106 SkBitmap* decrease_icon,
107 SkBitmap* disabled_icon)
108 : current_percent_(-1.0),
109 target_percent_(-1.0),
110 increase_icon_(increase_icon),
111 decrease_icon_(decrease_icon),
112 disabled_icon_(disabled_icon),
113 current_icon_(NULL),
114 enabled_(false),
115 view_(NULL),
116 is_animating_(false) {
117 }
118
119 SettingLevelBubbleViewViews::~SettingLevelBubbleViewViews() {
120 WindowClosing();
121 }
122
123 void SettingLevelBubbleViewViews::Init() {
124 SettingLevelBubbleView* view = new SettingLevelBubbleView();
125 view->SetIcon(current_icon_);
126 view->SetEnabled(enabled_);
127
128 // Calculate the position in screen coordinates that the bubble should
129 // "point" at (since we use BubbleBorder::FLOAT, this position actually
130 // specifies the center of the bubble).
131 const gfx::Rect monitor_area =
132 gfx::Screen::GetMonitorAreaNearestWindow(
133 GetWidget()->GetTopLevelWidget()->GetNativeView());
134 const gfx::Size view_size = view->GetPreferredSize();
135 position_relative_to_ = gfx::Rect(
136 monitor_area.x() + kBubbleXRatio * monitor_area.width(),
137 monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap,
138 0, 0);
139 view->Init(current_icon_, current_percent_, enabled_);
140 AddChildView(view);
141 }
142
143 views::BubbleBorder::ArrowLocation
144 SettingLevelBubbleViewViews::GetArrowLocation() const {
145 return views::BubbleBorder::FLOAT;
146 }
147
148 SkColor SettingLevelBubbleViewViews::GetColor() const {
149 return Bubble::kBackgroundColor;
150 }
151
152 bool SettingLevelBubbleViewViews::GetEnableAccelerator() const {
153 return false;
154 }
155
156 void SettingLevelBubbleViewViews::WindowClosing() {
157 StopAnimation();
158 current_percent_ = target_percent_;
159 target_time_ = TimeTicks();
160 last_animation_update_time_ = TimeTicks();
161 last_target_update_time_ = TimeTicks();
162 }
163
164 void SettingLevelBubbleViewViews::UpdateSettingLevel(double percent,
165 bool enabled) {
166 enabled_ = enabled;
167 const double old_target_percent = target_percent_;
168 UpdateTargetPercent(percent);
169 current_icon_ = increase_icon_;
170 if (!enabled || target_percent_ == 0)
171 current_icon_ = disabled_icon_;
172 else if (old_target_percent >= 0 && target_percent_ < old_target_percent)
173 current_icon_ = decrease_icon_;
174 }
175
176 void SettingLevelBubbleViewViews::UpdateWithoutShowingBubble(
177 double percent,
178 bool enabled) {
179 UpdateTargetPercent(percent);
180 if (view_)
181 view_->SetEnabled(enabled);
182 }
183
184 void SettingLevelBubbleViewViews::StartHideTimer() {
185 hide_timer_.Stop();
186 hide_timer_.Start(FROM_HERE,
187 base::TimeDelta::FromMilliseconds(kBubbleShowTimeoutMs),
188 this, &SettingLevelBubbleViewViews::OnHideTimeout);
189 }
190
191 void SettingLevelBubbleViewViews::OnHideTimeout() {
192 GetWidget()->Close();
193 }
194
195 void SettingLevelBubbleViewViews::OnAnimationTimeout() {
196 const TimeTicks now = TimeTicks::Now();
197 const int64 remaining_ms = (target_time_ - now).InMilliseconds();
198
199 if (remaining_ms <= 0) {
200 current_percent_ = target_percent_;
201 StopAnimation();
202 } else {
203 // Figure out what fraction of the total time until we want to reach the
204 // target has elapsed since the last update.
205 const double remaining_percent = target_percent_ - current_percent_;
206 const int64 elapsed_ms =
207 (now - last_animation_update_time_).InMilliseconds();
208 current_percent_ +=
209 remaining_percent *
210 (static_cast<double>(elapsed_ms) / (elapsed_ms + remaining_ms));
211 }
212 last_animation_update_time_ = now;
213
214 if (view_)
215 view_->SetLevel(current_percent_);
216 }
217
218
219 void SettingLevelBubbleViewViews::UpdateTargetPercent(double percent) {
220 target_percent_ = LimitPercent(percent);
221 const TimeTicks now = TimeTicks::Now();
222
223 if (current_percent_ < 0.0) {
224 // If we're setting the level for the first time, no need to animate.
225 current_percent_ = target_percent_;
226 if (view_)
227 view_->SetLevel(current_percent_);
228 } else {
229 // Use the time since the last request as a hint for the duration of the
230 // animation. This makes us automatically adapt to the repeat rate if a key
231 // is being held down to change a setting (which prevents us from lagging
232 // behind when the key is finally released).
233 int64 duration_ms = kInitialAnimationDurationMs;
234 if (!last_target_update_time_.is_null())
235 duration_ms = min(kInitialAnimationDurationMs,
236 (now - last_target_update_time_).InMilliseconds());
237 target_time_ = now + TimeDelta::FromMilliseconds(duration_ms);
238
239 if (!is_animating_) {
240 animation_timer_.Start(FROM_HERE,
241 TimeDelta::FromMilliseconds(kAnimationIntervalMs),
242 this,
243 &SettingLevelBubbleViewViews::OnAnimationTimeout);
244 is_animating_ = true;
245 last_animation_update_time_ = now;
246 }
247 }
248
249 last_target_update_time_ = now;
250 }
251
252 void SettingLevelBubbleViewViews::StopAnimation() {
253 animation_timer_.Stop();
254 is_animating_ = false;
255 }
256
257 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698