summaryrefslogtreecommitdiffstats
path: root/ash/system/chromeos/network/tray_sms.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ash/system/chromeos/network/tray_sms.cc')
-rw-r--r--ash/system/chromeos/network/tray_sms.cc378
1 files changed, 378 insertions, 0 deletions
diff --git a/ash/system/chromeos/network/tray_sms.cc b/ash/system/chromeos/network/tray_sms.cc
new file mode 100644
index 0000000..65ff9c6
--- /dev/null
+++ b/ash/system/chromeos/network/tray_sms.cc
@@ -0,0 +1,378 @@
+// 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/chromeos/network/tray_sms.h"
+
+#include "ash/ash_switches.h"
+#include "ash/shell.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/tray_constants.h"
+#include "ash/system/tray/tray_details_view.h"
+#include "ash/system/tray/tray_item_more.h"
+#include "ash/system/tray/tray_item_view.h"
+#include "ash/system/tray/tray_notification_view.h"
+#include "ash/system/tray/tray_views.h"
+#include "base/command_line.h"
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/view.h"
+
+namespace {
+
+// Min height of the list of messages in the popup.
+const int kMessageListMinHeight = 200;
+// Top/bottom padding of the text items.
+const int kPaddingVertical = 10;
+
+bool GetMessageFromDictionary(const base::DictionaryValue* message,
+ std::string* number,
+ std::string* text) {
+ if (!message->GetStringWithoutPathExpansion(ash::kSmsNumberKey, number))
+ return false;
+ if (!message->GetStringWithoutPathExpansion(ash::kSmsTextKey, text))
+ return false;
+ return true;
+}
+
+} // namespace
+
+namespace ash {
+namespace internal {
+
+class TraySms::SmsDefaultView : public TrayItemMore {
+ public:
+ explicit SmsDefaultView(TraySms* tray)
+ : TrayItemMore(tray),
+ tray_(tray) {
+ SetImage(ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_AURA_UBER_TRAY_SMS));
+ Update();
+ }
+
+ virtual ~SmsDefaultView() {}
+
+ void Update() {
+ int message_count = tray_->messages().GetSize();
+ string16 label = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_SMS_MESSAGES, base::IntToString16(message_count));
+ SetLabel(label);
+ SetAccessibleName(label);
+ }
+
+ private:
+ TraySms* tray_;
+
+ DISALLOW_COPY_AND_ASSIGN(SmsDefaultView);
+};
+
+// An entry (row) in SmsDetailedView or NotificationView.
+class TraySms::SmsMessageView : public views::View,
+ public views::ButtonListener {
+ public:
+ enum ViewType {
+ VIEW_DETAILED,
+ VIEW_NOTIFICATION
+ };
+
+ SmsMessageView(TraySms* tray,
+ ViewType view_type,
+ size_t index,
+ const std::string& number,
+ const std::string& message)
+ : tray_(tray),
+ index_(index) {
+ number_label_ = new views::Label(
+ l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_SMS_NUMBER,
+ UTF8ToUTF16(number)));
+ number_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ number_label_->SetFont(
+ number_label_->font().DeriveFont(0, gfx::Font::BOLD));
+
+ message_label_ = new views::Label(UTF8ToUTF16(message));
+ message_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
+ message_label_->SetMultiLine(true);
+
+ if (view_type == VIEW_DETAILED)
+ LayoutDetailedView();
+ else
+ LayoutNotificationView();
+ }
+
+ virtual ~SmsMessageView() {
+ }
+
+ // Overridden from ButtonListener.
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ tray_->RemoveMessage(index_);
+ tray_->Update(false);
+ }
+
+ private:
+ void LayoutDetailedView() {
+ views::ImageButton* close_button = new views::ImageButton(this);
+ close_button->SetImage(views::CustomButton::BS_NORMAL,
+ ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_AURA_WINDOW_CLOSE));
+
+ int msg_width = kTrayPopupWidth - kNotificationIconWidth -
+ kTrayPopupPaddingHorizontal * 2;
+ message_label_->SizeToFit(msg_width);
+
+ views::GridLayout* layout = new views::GridLayout(this);
+ SetLayoutManager(layout);
+
+ views::ColumnSet* columns = layout->AddColumnSet(0);
+
+ // Message
+ columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal);
+ columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
+ 0 /* resize percent */,
+ views::GridLayout::FIXED, msg_width, msg_width);
+
+ // Close button
+ columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
+ 0, /* resize percent */
+ views::GridLayout::FIXED,
+ kNotificationIconWidth, kNotificationIconWidth);
+
+
+ layout->AddPaddingRow(0, kPaddingVertical);
+ layout->StartRow(0, 0);
+ layout->AddView(number_label_);
+ layout->AddView(close_button, 1, 2); // 2 rows for icon
+ layout->StartRow(0, 0);
+ layout->AddView(message_label_);
+
+ layout->AddPaddingRow(0, kPaddingVertical);
+ }
+
+ void LayoutNotificationView() {
+ SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
+ AddChildView(number_label_);
+ message_label_->SizeToFit(kTrayNotificationContentsWidth);
+ AddChildView(message_label_);
+ }
+
+ TraySms* tray_;
+ size_t index_;
+ views::Label* number_label_;
+ views::Label* message_label_;
+
+ DISALLOW_COPY_AND_ASSIGN(SmsMessageView);
+};
+
+class TraySms::SmsDetailedView : public TrayDetailsView,
+ public ViewClickListener {
+ public:
+ explicit SmsDetailedView(TraySms* tray)
+ : tray_(tray) {
+ Init();
+ Update();
+ }
+
+ virtual ~SmsDetailedView() {
+ }
+
+ void Init() {
+ CreateScrollableList();
+ CreateSpecialRow(IDS_ASH_STATUS_TRAY_SMS, this);
+ }
+
+ void Update() {
+ UpdateMessageList();
+ Layout();
+ SchedulePaint();
+ }
+
+ // Overridden from views::View.
+ gfx::Size GetPreferredSize() {
+ gfx::Size preferred_size = TrayDetailsView::GetPreferredSize();
+ if (preferred_size.height() < kMessageListMinHeight)
+ preferred_size.set_height(kMessageListMinHeight);
+ return preferred_size;
+ }
+
+ private:
+ void UpdateMessageList() {
+ const base::ListValue& messages = tray_->messages();
+ scroll_content()->RemoveAllChildViews(true);
+ for (size_t index = 0; index < messages.GetSize(); ++index) {
+ const base::DictionaryValue* message = NULL;
+ if (!messages.GetDictionary(index, &message)) {
+ LOG(ERROR) << "SMS message not a dictionary at: " << index;
+ continue;
+ }
+ std::string number, text;
+ if (!GetMessageFromDictionary(message, &number, &text)) {
+ LOG(ERROR) << "Error parsing SMS message";
+ continue;
+ }
+ SmsMessageView* msgview = new SmsMessageView(
+ tray_, SmsMessageView::VIEW_DETAILED, index, number, text);
+ scroll_content()->AddChildView(msgview);
+ }
+ scroller()->Layout();
+ }
+
+ // Overridden from ViewClickListener.
+ virtual void ClickedOn(views::View* sender) OVERRIDE {
+ if (sender == footer()->content())
+ Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
+ }
+
+ TraySms* tray_;
+
+ DISALLOW_COPY_AND_ASSIGN(SmsDetailedView);
+};
+
+class TraySms::SmsNotificationView : public TrayNotificationView {
+ public:
+ SmsNotificationView(TraySms* tray,
+ size_t message_index,
+ const std::string& number,
+ const std::string& text)
+ : TrayNotificationView(tray, IDR_AURA_UBER_TRAY_SMS),
+ message_index_(message_index) {
+ SmsMessageView* message_view = new SmsMessageView(
+ tray, SmsMessageView::VIEW_NOTIFICATION, message_index_, number, text);
+ InitView(message_view);
+ }
+
+ void Update(size_t message_index,
+ const std::string& number,
+ const std::string& text) {
+ SmsMessageView* message_view = new SmsMessageView(
+ tray_sms(), SmsMessageView::VIEW_NOTIFICATION,
+ message_index_, number, text);
+ UpdateView(message_view);
+ }
+
+ // Overridden from TrayNotificationView:
+ virtual void OnClose() OVERRIDE {
+ tray_sms()->RemoveMessage(message_index_);
+ }
+
+ virtual void OnClickAction() OVERRIDE {
+ tray()->PopupDetailedView(0, true);
+ }
+
+ private:
+ TraySms* tray_sms() {
+ return static_cast<TraySms*>(tray());
+ }
+
+ size_t message_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(SmsNotificationView);
+};
+
+TraySms::TraySms()
+ : default_(NULL),
+ detailed_(NULL),
+ notification_(NULL) {
+}
+
+TraySms::~TraySms() {
+}
+
+views::View* TraySms::CreateDefaultView(user::LoginStatus status) {
+ CHECK(default_ == NULL);
+ default_ = new SmsDefaultView(this);
+ default_->SetVisible(!messages_.empty());
+ return default_;
+}
+
+views::View* TraySms::CreateDetailedView(user::LoginStatus status) {
+ CHECK(detailed_ == NULL);
+ HideNotificationView();
+ if (messages_.empty())
+ return NULL;
+ detailed_ = new SmsDetailedView(this);
+ return detailed_;
+}
+
+views::View* TraySms::CreateNotificationView(user::LoginStatus status) {
+ CHECK(notification_ == NULL);
+ size_t index;
+ std::string number, text;
+ if (GetLatestMessage(&index, &number, &text))
+ notification_ = new SmsNotificationView(this, index, number, text);
+ return notification_;
+}
+
+void TraySms::DestroyDefaultView() {
+ default_ = NULL;
+}
+
+void TraySms::DestroyDetailedView() {
+ detailed_ = NULL;
+}
+
+void TraySms::DestroyNotificationView() {
+ notification_ = NULL;
+}
+
+void TraySms::AddMessage(const base::DictionaryValue& message) {
+ messages_.Append(message.DeepCopy());
+ Update(true);
+}
+
+bool TraySms::GetLatestMessage(size_t* index,
+ std::string* number,
+ std::string* text) {
+ if (messages_.empty())
+ return false;
+ DictionaryValue* message;
+ size_t message_index = messages_.GetSize() - 1;
+ if (!messages_.GetDictionary(message_index, &message))
+ return false;
+ if (!GetMessageFromDictionary(message, number, text))
+ return false;
+ *index = message_index;
+ return true;
+}
+
+void TraySms::RemoveMessage(size_t index) {
+ if (index < messages_.GetSize())
+ messages_.Remove(index, NULL);
+}
+
+void TraySms::Update(bool notify) {
+ if (messages_.empty()) {
+ if (default_)
+ default_->SetVisible(false);
+ if (detailed_)
+ HideDetailedView();
+ HideNotificationView();
+ } else {
+ if (default_) {
+ default_->SetVisible(true);
+ default_->Update();
+ }
+ if (detailed_)
+ detailed_->Update();
+ if (notification_) {
+ size_t index;
+ std::string number, text;
+ if (GetLatestMessage(&index, &number, &text))
+ notification_->Update(index, number, text);
+ } else if (notify) {
+ ShowNotificationView();
+ }
+ }
+}
+
+} // namespace internal
+} // namespace ash