| // 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 "chrome/browser/chromeos/setting_level_bubble.h" |
| |
| #include <gdk/gdk.h> |
| |
| #include "base/timer.h" |
| #include "chrome/browser/chromeos/login/background_view.h" |
| #include "chrome/browser/chromeos/login/login_utils.h" |
| #include "chrome/browser/chromeos/setting_level_bubble_view.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/browser/ui/browser_window.h" |
| #include "chrome/browser/ui/views/bubble/bubble.h" |
| #include "views/widget/root_view.h" |
| |
| namespace { |
| |
| const int kBubbleShowTimeoutSec = 2; |
| const int kAnimationDurationMs = 200; |
| |
| // Horizontal relative position: 0 - leftmost, 0.5 - center, 1 - rightmost. |
| const double kBubbleXRatio = 0.5; |
| |
| // Vertical gap from the bottom of the screen in pixels. |
| const int kBubbleBottomGap = 30; |
| |
| int LimitPercent(int percent) { |
| if (percent < 0) |
| percent = 0; |
| else if (percent > 100) |
| percent = 100; |
| return percent; |
| } |
| |
| } // namespace |
| |
| namespace chromeos { |
| |
| // Temporary helper routine. Tries to first return the widget from the |
| // most-recently-focused normal browser window, then from a login |
| // background, and finally NULL if both of those fail. |
| // TODO(glotov): remove this in favor of enabling Bubble class act |
| // without |parent| specified. crosbug.com/4025 |
| static views::Widget* GetToplevelWidget() { |
| GtkWindow* window = NULL; |
| |
| // We just use the default profile here -- this gets overridden as needed |
| // in Chrome OS depending on whether the user is logged in or not. |
| Browser* browser = |
| BrowserList::FindBrowserWithType( |
| ProfileManager::GetDefaultProfile(), |
| Browser::TYPE_NORMAL, |
| true); // match_incognito |
| if (browser) { |
| window = GTK_WINDOW(browser->window()->GetNativeHandle()); |
| } else { |
| // Otherwise, see if there's a background window that we can use. |
| BackgroundView* background = LoginUtils::Get()->GetBackgroundView(); |
| if (background) |
| window = GTK_WINDOW(background->GetNativeWindow()); |
| } |
| |
| if (!window) |
| return NULL; |
| |
| views::NativeWidget* native_widget = |
| views::NativeWidget::GetNativeWidgetForNativeWindow(window); |
| return native_widget->GetWidget(); |
| } |
| |
| SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon, |
| SkBitmap* decrease_icon, |
| SkBitmap* zero_icon) |
| : previous_percent_(-1), |
| current_percent_(-1), |
| increase_icon_(increase_icon), |
| decrease_icon_(decrease_icon), |
| zero_icon_(zero_icon), |
| bubble_(NULL), |
| view_(NULL), |
| animation_(this) { |
| animation_.SetSlideDuration(kAnimationDurationMs); |
| animation_.SetTweenType(ui::Tween::LINEAR); |
| } |
| |
| void SettingLevelBubble::ShowBubble(int percent) { |
| percent = LimitPercent(percent); |
| if (previous_percent_ == -1) |
| previous_percent_ = percent; |
| current_percent_ = percent; |
| |
| SkBitmap* icon = increase_icon_; |
| if (current_percent_ == 0) |
| icon = zero_icon_; |
| else if (current_percent_ < previous_percent_) |
| icon = decrease_icon_; |
| |
| if (!bubble_) { |
| views::Widget* widget = GetToplevelWidget(); |
| if (widget == NULL) |
| return; |
| DCHECK(view_ == NULL); |
| view_ = new SettingLevelBubbleView; |
| view_->Init(icon, previous_percent_); |
| // Calculate position of the bubble. |
| gfx::Rect bounds = widget->GetClientAreaScreenBounds(); |
| const gfx::Size view_size = view_->GetPreferredSize(); |
| // Note that (x, y) is the point of the center of the bubble. |
| const int x = view_size.width() / 2 + |
| kBubbleXRatio * (bounds.width() - view_size.width()); |
| const int y = bounds.height() - view_size.height() / 2 - kBubbleBottomGap; |
| bubble_ = Bubble::ShowFocusless(widget, // parent |
| gfx::Rect(x, y, 0, 20), |
| BubbleBorder::FLOAT, |
| view_, // contents |
| this, // delegate |
| true); // show while screen is locked |
| } else { |
| DCHECK(view_); |
| timeout_timer_.Stop(); |
| view_->SetIcon(icon); |
| } |
| if (animation_.is_animating()) |
| animation_.End(); |
| animation_.Reset(); |
| animation_.Show(); |
| timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec), |
| this, &SettingLevelBubble::OnTimeout); |
| } |
| |
| void SettingLevelBubble::HideBubble() { |
| if (bubble_) |
| bubble_->Close(); |
| } |
| |
| void SettingLevelBubble::UpdateWithoutShowingBubble(int percent) { |
| percent = LimitPercent(percent); |
| |
| previous_percent_ = |
| animation_.is_animating() ? |
| animation_.GetCurrentValue() : |
| current_percent_; |
| if (previous_percent_ < 0) |
| previous_percent_ = percent; |
| current_percent_ = percent; |
| |
| if (animation_.is_animating()) |
| animation_.End(); |
| animation_.Reset(); |
| animation_.Show(); |
| } |
| |
| void SettingLevelBubble::OnTimeout() { |
| HideBubble(); |
| } |
| |
| void SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) { |
| DCHECK(bubble == bubble_); |
| timeout_timer_.Stop(); |
| animation_.Stop(); |
| bubble_ = NULL; |
| view_ = NULL; |
| } |
| |
| void SettingLevelBubble::AnimationEnded(const ui::Animation* animation) { |
| previous_percent_ = current_percent_; |
| } |
| |
| void SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) { |
| if (view_) { |
| view_->Update( |
| ui::Tween::ValueBetween(animation->GetCurrentValue(), |
| previous_percent_, |
| current_percent_)); |
| } |
| } |
| |
| } // namespace chromeos |