172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be
321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file.
421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/chromeos/setting_level_bubble.h"
621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <gdk/gdk.h>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/timer.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/login/background_view.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/login/login_utils.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/chromeos/setting_level_bubble_view.h"
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h"
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/browser.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/views/bubble/bubble.h"
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "views/widget/root_view.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace {
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int kBubbleShowTimeoutSec = 2;
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int kAnimationDurationMs = 200;
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Horizontal relative position: 0 - leftmost, 0.5 - center, 1 - rightmost.
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst double kBubbleXRatio = 0.5;
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Vertical gap from the bottom of the screen in pixels.
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int kBubbleBottomGap = 30;
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint LimitPercent(int percent) {
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (percent < 0)
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    percent = 0;
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else if (percent > 100)
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    percent = 100;
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return percent;
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace chromeos {
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Temporary helper routine. Tries to first return the widget from the
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// most-recently-focused normal browser window, then from a login
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// background, and finally NULL if both of those fail.
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// TODO(glotov): remove this in favor of enabling Bubble class act
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// without |parent| specified. crosbug.com/4025
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic views::Widget* GetToplevelWidget() {
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GtkWindow* window = NULL;
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // We just use the default profile here -- this gets overridden as needed
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // in Chrome OS depending on whether the user is logged in or not.
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  Browser* browser =
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      BrowserList::FindBrowserWithType(
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          ProfileManager::GetDefaultProfile(),
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          Browser::TYPE_NORMAL,
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          true);  // match_incognito
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (browser) {
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window = GTK_WINDOW(browser->window()->GetNativeHandle());
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Otherwise, see if there's a background window that we can use.
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BackgroundView* background = LoginUtils::Get()->GetBackgroundView();
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (background)
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      window = GTK_WINDOW(background->GetNativeWindow());
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!window)
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return NULL;
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  views::NativeWidget* native_widget =
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      views::NativeWidget::GetNativeWidgetForNativeWindow(window);
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return native_widget->GetWidget();
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                       SkBitmap* decrease_icon,
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                       SkBitmap* zero_icon)
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : previous_percent_(-1),
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      current_percent_(-1),
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      increase_icon_(increase_icon),
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      decrease_icon_(decrease_icon),
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      zero_icon_(zero_icon),
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      bubble_(NULL),
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      view_(NULL),
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      animation_(this) {
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  animation_.SetSlideDuration(kAnimationDurationMs);
873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  animation_.SetTweenType(ui::Tween::LINEAR);
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SettingLevelBubble::ShowBubble(int percent) {
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  percent = LimitPercent(percent);
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (previous_percent_ == -1)
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    previous_percent_ = percent;
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  current_percent_ = percent;
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SkBitmap* icon = increase_icon_;
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (current_percent_ == 0)
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    icon = zero_icon_;
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  else if (current_percent_ < previous_percent_)
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    icon = decrease_icon_;
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!bubble_) {
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    views::Widget* widget = GetToplevelWidget();
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (widget == NULL)
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return;
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(view_ == NULL);
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    view_ = new SettingLevelBubbleView;
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    view_->Init(icon, previous_percent_);
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Calculate position of the bubble.
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    gfx::Rect bounds = widget->GetClientAreaScreenBounds();
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const gfx::Size view_size = view_->GetPreferredSize();
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Note that (x, y) is the point of the center of the bubble.
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const int x = view_size.width() / 2 +
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        kBubbleXRatio * (bounds.width() - view_size.width());
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const int y = bounds.height() - view_size.height() / 2 - kBubbleBottomGap;
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bubble_ = Bubble::ShowFocusless(widget,  // parent
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    gfx::Rect(x, y, 0, 20),
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    BubbleBorder::FLOAT,
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    view_,  // contents
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    this,   // delegate
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                    true);  // show while screen is locked
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    DCHECK(view_);
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    timeout_timer_.Stop();
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    view_->SetIcon(icon);
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (animation_.is_animating())
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    animation_.End();
12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  animation_.Reset();
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  animation_.Show();
13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec),
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                       this, &SettingLevelBubble::OnTimeout);
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SettingLevelBubble::HideBubble() {
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (bubble_)
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bubble_->Close();
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SettingLevelBubble::UpdateWithoutShowingBubble(int percent) {
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  percent = LimitPercent(percent);
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  previous_percent_ =
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      animation_.is_animating() ?
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      animation_.GetCurrentValue() :
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      current_percent_;
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (previous_percent_ < 0)
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    previous_percent_ = percent;
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  current_percent_ = percent;
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (animation_.is_animating())
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    animation_.End();
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  animation_.Reset();
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  animation_.Show();
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SettingLevelBubble::OnTimeout() {
15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  HideBubble();
15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SettingLevelBubble::BubbleClosing(Bubble* bubble, bool) {
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(bubble == bubble_);
16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  timeout_timer_.Stop();
16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  animation_.Stop();
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bubble_ = NULL;
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  view_ = NULL;
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SettingLevelBubble::AnimationEnded(const ui::Animation* animation) {
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  previous_percent_ = current_percent_;
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) {
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (view_) {
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    view_->Update(
1763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        ui::Tween::ValueBetween(animation->GetCurrentValue(),
1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                previous_percent_,
1783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                current_percent_));
17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace chromeos
183