summaryrefslogtreecommitdiffstats
path: root/ash/system/session_length_limit
diff options
context:
space:
mode:
authorbartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-15 11:44:31 +0000
committerbartfab@chromium.org <bartfab@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-15 11:44:31 +0000
commit1682765344cb63cc02eef46f65e902c5aa5c1c3f (patch)
tree05ba1f3561338a9984e2b75ae2ba5881bafd791d /ash/system/session_length_limit
parente279d9ec38ba0dd798afbdc245aa58f3e1c8a55b (diff)
downloadchromium_src-1682765344cb63cc02eef46f65e902c5aa5c1c3f.zip
chromium_src-1682765344cb63cc02eef46f65e902c5aa5c1c3f.tar.gz
chromium_src-1682765344cb63cc02eef46f65e902c5aa5c1c3f.tar.bz2
Add countdown when session time is limited
This CL adds a countdown to the ash tray when the session time is limited. The UI can/will be improved further in the future. This is a first basic functional implementation. BUG=chromium-os:26957 TEST=Manual TBR=sky@chromium.org (for ash.gyp and ash_strings.grd changes) Review URL: https://codereview.chromium.org/11568036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173293 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/system/session_length_limit')
-rw-r--r--ash/system/session_length_limit/session_length_limit_observer.h27
-rw-r--r--ash/system/session_length_limit/tray_session_length_limit.cc307
-rw-r--r--ash/system/session_length_limit/tray_session_length_limit.h48
3 files changed, 382 insertions, 0 deletions
diff --git a/ash/system/session_length_limit/session_length_limit_observer.h b/ash/system/session_length_limit/session_length_limit_observer.h
new file mode 100644
index 0000000..52be2c4
--- /dev/null
+++ b/ash/system/session_length_limit/session_length_limit_observer.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 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.
+
+#ifndef ASH_SYSTEM_SESSION_LENGTH_LIMIT_SESSION_LENGTH_LIMIT_OBSERVER_H_
+#define ASH_SYSTEM_SESSION_LENGTH_LIMIT_SESSION_LENGTH_LIMIT_OBSERVER_H_
+
+#include "base/time.h"
+
+namespace ash {
+
+// Observer for the session length limit.
+class SessionLengthLimitObserver {
+ public:
+ virtual ~SessionLengthLimitObserver() {}
+
+ // Called when the session start time is updated.
+ virtual void OnSessionStartTimeChanged(
+ const base::Time& session_start_time) = 0;
+
+ // Called when the session length limit is updated.
+ virtual void OnSessionLengthLimitChanged(const base::TimeDelta& limit) = 0;
+};
+
+} // namespace ash
+
+#endif // ASH_SYSTEM_SESSION_LENGTH_LIMIT_SESSION_LENGTH_LIMIT_OBSERVER_H_
diff --git a/ash/system/session_length_limit/tray_session_length_limit.cc b/ash/system/session_length_limit/tray_session_length_limit.cc
new file mode 100644
index 0000000..3401d85
--- /dev/null
+++ b/ash/system/session_length_limit/tray_session_length_limit.cc
@@ -0,0 +1,307 @@
+// Copyright (c) 2012 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 "ash/system/session_length_limit/tray_session_length_limit.h"
+
+#include <cmath>
+
+#include "ash/shelf_types.h"
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/system/tray/tray_constants.h"
+#include "ash/system/tray/tray_views.h"
+#include "base/string16.h"
+#include "base/string_number_conversions.h"
+#include "base/time.h"
+#include "base/timer.h"
+#include "base/utf_string_conversions.h"
+#include "grit/ash_strings.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/text_constants.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/view.h"
+
+namespace ash {
+namespace internal {
+
+namespace tray {
+
+namespace {
+
+// Warning threshold for the remaining sessiont time.
+const int kRemainingTimeWarningThresholdInSeconds = 5 * 60; // 5 minutes.
+// Color in which the remaining session time is normally shown.
+const SkColor kRemainingTimeColor = SK_ColorWHITE;
+// Color in which the remaining session time is shown when it falls below the
+// warning threshold.
+const SkColor kRemainingTimeWarningColor = SK_ColorRED;
+
+views::Label* CreateAndSetupLabel() {
+ views::Label* label = new views::Label;
+ label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ SetupLabelForTray(label);
+ gfx::Font font = label->font();
+ label->SetFont(font.DeriveFont(0, font.GetStyle() & ~gfx::Font::BOLD));
+ return label;
+}
+
+string16 IntToTwoDigitString(int value) {
+ DCHECK_GE(value, 0);
+ DCHECK_LE(value, 99);
+ if (value < 10)
+ return ASCIIToUTF16("0") + base::IntToString16(value);
+ return base::IntToString16(value);
+}
+
+} // namespace
+
+class RemainingSessionTimeTrayView : public views::View {
+ public:
+ RemainingSessionTimeTrayView(const base::Time& session_start_time,
+ const base::TimeDelta& limit,
+ ShelfAlignment shelf_alignment);
+ virtual ~RemainingSessionTimeTrayView();
+
+ void SetSessionStartTime(const base::Time& session_start_time);
+ void SetSessionLengthLimit(const base::TimeDelta& limit);
+
+ void UpdateClockLayout(ShelfAlignment shelf_alignment);
+
+ private:
+ void SetBorder(ShelfAlignment shelf_alignment);
+
+ // Update the label text only.
+ void UpdateText();
+ // Update the timer state, label text and visibility.
+ void UpdateState();
+
+ views::Label* horizontal_layout_label_;
+ views::Label* vertical_layout_label_hours_left_;
+ views::Label* vertical_layout_label_hours_right_;
+ views::Label* vertical_layout_label_minutes_left_;
+ views::Label* vertical_layout_label_minutes_right_;
+ views::Label* vertical_layout_label_seconds_left_;
+ views::Label* vertical_layout_label_seconds_right_;
+
+ base::Time session_start_time_;
+ base::TimeDelta limit_;
+ base::RepeatingTimer<RemainingSessionTimeTrayView> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemainingSessionTimeTrayView);
+};
+
+RemainingSessionTimeTrayView::RemainingSessionTimeTrayView(
+ const base::Time& session_start_time,
+ const base::TimeDelta& limit,
+ ShelfAlignment shelf_alignment)
+ : horizontal_layout_label_(NULL),
+ vertical_layout_label_hours_left_(NULL),
+ vertical_layout_label_hours_right_(NULL),
+ vertical_layout_label_minutes_left_(NULL),
+ vertical_layout_label_minutes_right_(NULL),
+ vertical_layout_label_seconds_left_(NULL),
+ vertical_layout_label_seconds_right_(NULL),
+ session_start_time_(session_start_time),
+ limit_(limit) {
+ UpdateClockLayout(shelf_alignment);
+ UpdateState();
+}
+
+RemainingSessionTimeTrayView::~RemainingSessionTimeTrayView() {
+}
+
+void RemainingSessionTimeTrayView::SetSessionStartTime(
+ const base::Time& session_start_time) {
+ session_start_time_ = session_start_time;
+ UpdateState();
+}
+
+void RemainingSessionTimeTrayView::SetSessionLengthLimit(
+ const base::TimeDelta& limit) {
+ limit_ = limit;
+ UpdateState();
+}
+
+void RemainingSessionTimeTrayView::UpdateClockLayout(
+ ShelfAlignment shelf_alignment) {
+ SetBorder(shelf_alignment);
+ const bool horizontal_layout = shelf_alignment == SHELF_ALIGNMENT_BOTTOM;
+ if (horizontal_layout && !horizontal_layout_label_) {
+ // Remove labels used for vertical layout.
+ RemoveAllChildViews(true);
+ vertical_layout_label_hours_left_ = NULL;
+ vertical_layout_label_hours_right_ = NULL;
+ vertical_layout_label_minutes_left_ = NULL;
+ vertical_layout_label_minutes_right_ = NULL;
+ vertical_layout_label_seconds_left_ = NULL;
+ vertical_layout_label_seconds_right_ = NULL;
+
+ // Create label used for horizontal layout.
+ horizontal_layout_label_ = CreateAndSetupLabel();
+
+ // Construct layout.
+ SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
+ AddChildView(horizontal_layout_label_);
+
+ } else if (!horizontal_layout && horizontal_layout_label_) {
+ // Remove label used for horizontal layout.
+ RemoveAllChildViews(true);
+ horizontal_layout_label_ = NULL;
+
+ // Create labels used for vertical layout.
+ vertical_layout_label_hours_left_ = CreateAndSetupLabel();
+ vertical_layout_label_hours_right_ = CreateAndSetupLabel();
+ vertical_layout_label_minutes_left_ = CreateAndSetupLabel();
+ vertical_layout_label_minutes_right_ = CreateAndSetupLabel();
+ vertical_layout_label_seconds_left_ = CreateAndSetupLabel();
+ vertical_layout_label_seconds_right_ = CreateAndSetupLabel();
+
+ // Construct layout.
+ views::GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+ views::ColumnSet* columns = layout->AddColumnSet(0);
+ columns->AddPaddingColumn(0, 6);
+ columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
+ 0, views::GridLayout::USE_PREF, 0, 0);
+ columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
+ 0, views::GridLayout::USE_PREF, 0, 0);
+ layout->AddPaddingRow(0, kTrayLabelItemVerticalPaddingVeriticalAlignment);
+ layout->StartRow(0, 0);
+ layout->AddView(vertical_layout_label_hours_left_);
+ layout->AddView(vertical_layout_label_hours_right_);
+ layout->StartRow(0, 0);
+ layout->AddView(vertical_layout_label_minutes_left_);
+ layout->AddView(vertical_layout_label_minutes_right_);
+ layout->StartRow(0, 0);
+ layout->AddView(vertical_layout_label_seconds_left_);
+ layout->AddView(vertical_layout_label_seconds_right_);
+ layout->AddPaddingRow(0, kTrayLabelItemVerticalPaddingVeriticalAlignment);
+ }
+ UpdateText();
+}
+
+void RemainingSessionTimeTrayView::SetBorder(ShelfAlignment shelf_alignment) {
+ if (shelf_alignment == SHELF_ALIGNMENT_BOTTOM) {
+ set_border(views::Border::CreateEmptyBorder(
+ 0, kTrayLabelItemHorizontalPaddingBottomAlignment,
+ 0, kTrayLabelItemHorizontalPaddingBottomAlignment));
+ } else {
+ set_border(NULL);
+ }
+}
+
+void RemainingSessionTimeTrayView::UpdateText() {
+ if (!visible())
+ return;
+
+ // Calculate the remaining session time, clamping so that it never falls below
+ // zero or exceeds 99 hours.
+ int seconds =
+ round((limit_ - (base::Time::Now() - session_start_time_)).InSecondsF());
+ seconds = std::min(std::max(seconds, 0), 99 * 60 * 60);
+ int minutes = seconds / 60;
+ seconds %= 60;
+ const int hours = minutes / 60;
+ minutes %= 60;
+
+ const string16 hours_str = IntToTwoDigitString(hours);
+ const string16 minutes_str = IntToTwoDigitString(minutes);
+ const string16 seconds_str = IntToTwoDigitString(seconds);
+ const SkColor color = seconds < kRemainingTimeWarningThresholdInSeconds ?
+ kRemainingTimeWarningColor : kRemainingTimeColor;
+
+ if (horizontal_layout_label_) {
+ horizontal_layout_label_->SetText(l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_REMAINING_SESSION_TIME,
+ hours_str, minutes_str, seconds_str));
+ horizontal_layout_label_->SetEnabledColor(color);
+ } else if (vertical_layout_label_hours_left_) {
+ vertical_layout_label_hours_left_->SetText(hours_str.substr(0, 1));
+ vertical_layout_label_hours_right_->SetText(hours_str.substr(1, 1));
+ vertical_layout_label_minutes_left_->SetText(minutes_str.substr(0, 1));
+ vertical_layout_label_minutes_right_->SetText(minutes_str.substr(1, 1));
+ vertical_layout_label_seconds_left_->SetText(seconds_str.substr(0, 1));
+ vertical_layout_label_seconds_right_->SetText(seconds_str.substr(1, 1));
+ vertical_layout_label_hours_left_->SetEnabledColor(color);
+ vertical_layout_label_hours_right_->SetEnabledColor(color);
+ vertical_layout_label_minutes_left_->SetEnabledColor(color);
+ vertical_layout_label_minutes_right_->SetEnabledColor(color);
+ vertical_layout_label_seconds_left_->SetEnabledColor(color);
+ vertical_layout_label_seconds_right_->SetEnabledColor(color);
+ }
+
+ Layout();
+}
+
+void RemainingSessionTimeTrayView::UpdateState() {
+ const bool show = session_start_time_ != base::Time() &&
+ limit_ != base::TimeDelta();
+ SetVisible(show);
+ UpdateText();
+ if (show && !timer_.IsRunning()) {
+ // Set timer to update the text once per second.
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(1),
+ this,
+ &RemainingSessionTimeTrayView::UpdateText);
+ } else if (!show && timer_.IsRunning()) {
+ timer_.Stop();
+ }
+}
+
+} // namespace tray
+
+TraySessionLengthLimit::TraySessionLengthLimit(SystemTray* system_tray)
+ : SystemTrayItem(system_tray),
+ tray_view_(NULL) {
+ Shell::GetInstance()->system_tray_notifier()->
+ AddSessionLengthLimitObserver(this);
+}
+
+TraySessionLengthLimit::~TraySessionLengthLimit() {
+ Shell::GetInstance()->system_tray_notifier()->
+ RemoveSessionLengthLimitObserver(this);
+}
+
+views::View* TraySessionLengthLimit::CreateTrayView(user::LoginStatus status) {
+ CHECK(tray_view_ == NULL);
+ ash::SystemTrayDelegate* delegate =
+ ash::Shell::GetInstance()->system_tray_delegate();
+ tray_view_ = new tray::RemainingSessionTimeTrayView(
+ delegate->GetSessionStartTime(),
+ delegate->GetSessionLengthLimit(),
+ system_tray()->shelf_alignment());
+ return tray_view_;
+}
+
+void TraySessionLengthLimit::DestroyTrayView() {
+ tray_view_ = NULL;
+}
+
+void TraySessionLengthLimit::UpdateAfterShelfAlignmentChange(
+ ShelfAlignment alignment) {
+ if (tray_view_)
+ tray_view_->UpdateClockLayout(alignment);
+}
+
+void TraySessionLengthLimit::OnSessionStartTimeChanged(
+ const base::Time& start_time) {
+ tray_view_->SetSessionStartTime(start_time);
+}
+
+void TraySessionLengthLimit::OnSessionLengthLimitChanged(
+ const base::TimeDelta& limit) {
+ tray_view_->SetSessionLengthLimit(limit);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/session_length_limit/tray_session_length_limit.h b/ash/system/session_length_limit/tray_session_length_limit.h
new file mode 100644
index 0000000..0ee3f07
--- /dev/null
+++ b/ash/system/session_length_limit/tray_session_length_limit.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 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.
+
+#ifndef ASH_SYSTEM_SESSION_LENGTH_LIMIT_TRAY_SESSION_LENGTH_LIMIT_H_
+#define ASH_SYSTEM_SESSION_LENGTH_LIMIT_TRAY_SESSION_LENGTH_LIMIT_H_
+
+#include "ash/system/session_length_limit/session_length_limit_observer.h"
+#include "ash/system/tray/system_tray_item.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+namespace ash {
+namespace internal {
+
+namespace tray {
+class RemainingSessionTimeTrayView;
+}
+
+// Adds a countdown timer to the system tray if the session length is limited.
+class TraySessionLengthLimit : public SystemTrayItem,
+ public SessionLengthLimitObserver {
+ public:
+ explicit TraySessionLengthLimit(SystemTray* system_tray);
+ virtual ~TraySessionLengthLimit();
+
+ // SystemTrayItem:
+ virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE;
+ virtual void DestroyTrayView() OVERRIDE;
+ virtual void UpdateAfterShelfAlignmentChange(
+ ShelfAlignment alignment) OVERRIDE;
+
+ // SessionLengthLimitObserver:
+ virtual void OnSessionStartTimeChanged(
+ const base::Time& start_time) OVERRIDE;
+ virtual void OnSessionLengthLimitChanged(
+ const base::TimeDelta& limit) OVERRIDE;
+
+ private:
+ tray::RemainingSessionTimeTrayView* tray_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(TraySessionLengthLimit);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_SYSTEM_SESSION_LENGTH_LIMIT_TRAY_SESSION_LENGTH_LIMIT_H_