| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "ash/system/network/tray_sms.h" | |
| 6 | |
| 7 #include "ash/ash_switches.h" | |
| 8 #include "ash/shell.h" | |
| 9 #include "ash/system/tray/system_tray.h" | |
| 10 #include "ash/system/tray/tray_constants.h" | |
| 11 #include "ash/system/tray/tray_details_view.h" | |
| 12 #include "ash/system/tray/tray_item_more.h" | |
| 13 #include "ash/system/tray/tray_item_view.h" | |
| 14 #include "ash/system/tray/tray_notification_view.h" | |
| 15 #include "ash/system/tray/tray_views.h" | |
| 16 #include "base/command_line.h" | |
| 17 #include "base/string_number_conversions.h" | |
| 18 #include "base/utf_string_conversions.h" | |
| 19 #include "grit/ash_resources.h" | |
| 20 #include "grit/ash_strings.h" | |
| 21 #include "ui/base/l10n/l10n_util.h" | |
| 22 #include "ui/base/resource/resource_bundle.h" | |
| 23 #include "ui/views/controls/image_view.h" | |
| 24 #include "ui/views/controls/label.h" | |
| 25 #include "ui/views/layout/box_layout.h" | |
| 26 #include "ui/views/layout/fill_layout.h" | |
| 27 #include "ui/views/layout/grid_layout.h" | |
| 28 #include "ui/views/view.h" | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 // Min height of the list of messages in the popup. | |
| 33 const int kMessageListMinHeight = 200; | |
| 34 // Top/bottom padding of the text items. | |
| 35 const int kPaddingVertical = 10; | |
| 36 | |
| 37 bool GetMessageFromDictionary(const base::DictionaryValue* message, | |
| 38 std::string* number, | |
| 39 std::string* text) { | |
| 40 if (!message->GetStringWithoutPathExpansion(ash::kSmsNumberKey, number)) | |
| 41 return false; | |
| 42 if (!message->GetStringWithoutPathExpansion(ash::kSmsTextKey, text)) | |
| 43 return false; | |
| 44 return true; | |
| 45 } | |
| 46 | |
| 47 } // namespace | |
| 48 | |
| 49 namespace ash { | |
| 50 namespace internal { | |
| 51 | |
| 52 class TraySms::SmsDefaultView : public TrayItemMore { | |
| 53 public: | |
| 54 explicit SmsDefaultView(TraySms* tray) | |
| 55 : TrayItemMore(tray), | |
| 56 tray_(tray) { | |
| 57 SetImage(ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 58 IDR_AURA_UBER_TRAY_SMS)); | |
| 59 Update(); | |
| 60 } | |
| 61 | |
| 62 virtual ~SmsDefaultView() {} | |
| 63 | |
| 64 void Update() { | |
| 65 int message_count = tray_->messages().GetSize(); | |
| 66 string16 label = l10n_util::GetStringFUTF16( | |
| 67 IDS_ASH_STATUS_TRAY_SMS_MESSAGES, base::IntToString16(message_count)); | |
| 68 SetLabel(label); | |
| 69 SetAccessibleName(label); | |
| 70 } | |
| 71 | |
| 72 private: | |
| 73 TraySms* tray_; | |
| 74 | |
| 75 DISALLOW_COPY_AND_ASSIGN(SmsDefaultView); | |
| 76 }; | |
| 77 | |
| 78 // An entry (row) in SmsDetailedView or NotificationView. | |
| 79 class TraySms::SmsMessageView : public views::View, | |
| 80 public views::ButtonListener { | |
| 81 public: | |
| 82 enum ViewType { | |
| 83 VIEW_DETAILED, | |
| 84 VIEW_NOTIFICATION | |
| 85 }; | |
| 86 | |
| 87 SmsMessageView(TraySms* tray, | |
| 88 ViewType view_type, | |
| 89 size_t index, | |
| 90 const std::string& number, | |
| 91 const std::string& message) | |
| 92 : tray_(tray), | |
| 93 index_(index) { | |
| 94 number_label_ = new views::Label( | |
| 95 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_SMS_NUMBER, | |
| 96 UTF8ToUTF16(number))); | |
| 97 number_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 98 number_label_->SetFont( | |
| 99 number_label_->font().DeriveFont(0, gfx::Font::BOLD)); | |
| 100 | |
| 101 message_label_ = new views::Label(UTF8ToUTF16(message)); | |
| 102 message_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | |
| 103 message_label_->SetMultiLine(true); | |
| 104 | |
| 105 if (view_type == VIEW_DETAILED) | |
| 106 LayoutDetailedView(); | |
| 107 else | |
| 108 LayoutNotificationView(); | |
| 109 } | |
| 110 | |
| 111 virtual ~SmsMessageView() { | |
| 112 } | |
| 113 | |
| 114 // Overridden from ButtonListener. | |
| 115 virtual void ButtonPressed(views::Button* sender, | |
| 116 const ui::Event& event) OVERRIDE { | |
| 117 tray_->RemoveMessage(index_); | |
| 118 tray_->Update(false); | |
| 119 } | |
| 120 | |
| 121 private: | |
| 122 void LayoutDetailedView() { | |
| 123 views::ImageButton* close_button = new views::ImageButton(this); | |
| 124 close_button->SetImage(views::CustomButton::BS_NORMAL, | |
| 125 ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 126 IDR_AURA_WINDOW_CLOSE)); | |
| 127 | |
| 128 int msg_width = kTrayPopupWidth - kNotificationIconWidth - | |
| 129 kTrayPopupPaddingHorizontal * 2; | |
| 130 message_label_->SizeToFit(msg_width); | |
| 131 | |
| 132 views::GridLayout* layout = new views::GridLayout(this); | |
| 133 SetLayoutManager(layout); | |
| 134 | |
| 135 views::ColumnSet* columns = layout->AddColumnSet(0); | |
| 136 | |
| 137 // Message | |
| 138 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal); | |
| 139 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, | |
| 140 0 /* resize percent */, | |
| 141 views::GridLayout::FIXED, msg_width, msg_width); | |
| 142 | |
| 143 // Close button | |
| 144 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, | |
| 145 0, /* resize percent */ | |
| 146 views::GridLayout::FIXED, | |
| 147 kNotificationIconWidth, kNotificationIconWidth); | |
| 148 | |
| 149 | |
| 150 layout->AddPaddingRow(0, kPaddingVertical); | |
| 151 layout->StartRow(0, 0); | |
| 152 layout->AddView(number_label_); | |
| 153 layout->AddView(close_button, 1, 2); // 2 rows for icon | |
| 154 layout->StartRow(0, 0); | |
| 155 layout->AddView(message_label_); | |
| 156 | |
| 157 layout->AddPaddingRow(0, kPaddingVertical); | |
| 158 } | |
| 159 | |
| 160 void LayoutNotificationView() { | |
| 161 SetLayoutManager( | |
| 162 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1)); | |
| 163 AddChildView(number_label_); | |
| 164 message_label_->SizeToFit(kTrayNotificationContentsWidth); | |
| 165 AddChildView(message_label_); | |
| 166 } | |
| 167 | |
| 168 TraySms* tray_; | |
| 169 size_t index_; | |
| 170 views::Label* number_label_; | |
| 171 views::Label* message_label_; | |
| 172 | |
| 173 DISALLOW_COPY_AND_ASSIGN(SmsMessageView); | |
| 174 }; | |
| 175 | |
| 176 class TraySms::SmsDetailedView : public TrayDetailsView, | |
| 177 public ViewClickListener { | |
| 178 public: | |
| 179 explicit SmsDetailedView(TraySms* tray) | |
| 180 : tray_(tray) { | |
| 181 Init(); | |
| 182 Update(); | |
| 183 } | |
| 184 | |
| 185 virtual ~SmsDetailedView() { | |
| 186 } | |
| 187 | |
| 188 void Init() { | |
| 189 CreateScrollableList(); | |
| 190 CreateSpecialRow(IDS_ASH_STATUS_TRAY_SMS, this); | |
| 191 } | |
| 192 | |
| 193 void Update() { | |
| 194 UpdateMessageList(); | |
| 195 Layout(); | |
| 196 SchedulePaint(); | |
| 197 } | |
| 198 | |
| 199 // Overridden from views::View. | |
| 200 gfx::Size GetPreferredSize() { | |
| 201 gfx::Size preferred_size = TrayDetailsView::GetPreferredSize(); | |
| 202 if (preferred_size.height() < kMessageListMinHeight) | |
| 203 preferred_size.set_height(kMessageListMinHeight); | |
| 204 return preferred_size; | |
| 205 } | |
| 206 | |
| 207 private: | |
| 208 void UpdateMessageList() { | |
| 209 const base::ListValue& messages = tray_->messages(); | |
| 210 scroll_content()->RemoveAllChildViews(true); | |
| 211 for (size_t index = 0; index < messages.GetSize(); ++index) { | |
| 212 const base::DictionaryValue* message = NULL; | |
| 213 if (!messages.GetDictionary(index, &message)) { | |
| 214 LOG(ERROR) << "SMS message not a dictionary at: " << index; | |
| 215 continue; | |
| 216 } | |
| 217 std::string number, text; | |
| 218 if (!GetMessageFromDictionary(message, &number, &text)) { | |
| 219 LOG(ERROR) << "Error parsing SMS message"; | |
| 220 continue; | |
| 221 } | |
| 222 SmsMessageView* msgview = new SmsMessageView( | |
| 223 tray_, SmsMessageView::VIEW_DETAILED, index, number, text); | |
| 224 scroll_content()->AddChildView(msgview); | |
| 225 } | |
| 226 scroller()->Layout(); | |
| 227 } | |
| 228 | |
| 229 // Overridden from ViewClickListener. | |
| 230 virtual void ClickedOn(views::View* sender) OVERRIDE { | |
| 231 if (sender == footer()->content()) | |
| 232 Shell::GetInstance()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING); | |
| 233 } | |
| 234 | |
| 235 TraySms* tray_; | |
| 236 | |
| 237 DISALLOW_COPY_AND_ASSIGN(SmsDetailedView); | |
| 238 }; | |
| 239 | |
| 240 class TraySms::SmsNotificationView : public TrayNotificationView { | |
| 241 public: | |
| 242 SmsNotificationView(TraySms* tray, | |
| 243 size_t message_index, | |
| 244 const std::string& number, | |
| 245 const std::string& text) | |
| 246 : TrayNotificationView(tray, IDR_AURA_UBER_TRAY_SMS), | |
| 247 message_index_(message_index) { | |
| 248 SmsMessageView* message_view = new SmsMessageView( | |
| 249 tray, SmsMessageView::VIEW_NOTIFICATION, message_index_, number, text); | |
| 250 InitView(message_view); | |
| 251 } | |
| 252 | |
| 253 void Update(size_t message_index, | |
| 254 const std::string& number, | |
| 255 const std::string& text) { | |
| 256 SmsMessageView* message_view = new SmsMessageView( | |
| 257 tray_sms(), SmsMessageView::VIEW_NOTIFICATION, | |
| 258 message_index_, number, text); | |
| 259 UpdateView(message_view); | |
| 260 } | |
| 261 | |
| 262 // Overridden from TrayNotificationView: | |
| 263 virtual void OnClose() OVERRIDE { | |
| 264 tray_sms()->RemoveMessage(message_index_); | |
| 265 } | |
| 266 | |
| 267 virtual void OnClickAction() OVERRIDE { | |
| 268 tray()->PopupDetailedView(0, true); | |
| 269 } | |
| 270 | |
| 271 private: | |
| 272 TraySms* tray_sms() { | |
| 273 return static_cast<TraySms*>(tray()); | |
| 274 } | |
| 275 | |
| 276 size_t message_index_; | |
| 277 | |
| 278 DISALLOW_COPY_AND_ASSIGN(SmsNotificationView); | |
| 279 }; | |
| 280 | |
| 281 TraySms::TraySms() | |
| 282 : default_(NULL), | |
| 283 detailed_(NULL), | |
| 284 notification_(NULL) { | |
| 285 } | |
| 286 | |
| 287 TraySms::~TraySms() { | |
| 288 } | |
| 289 | |
| 290 views::View* TraySms::CreateDefaultView(user::LoginStatus status) { | |
| 291 CHECK(default_ == NULL); | |
| 292 default_ = new SmsDefaultView(this); | |
| 293 default_->SetVisible(!messages_.empty()); | |
| 294 return default_; | |
| 295 } | |
| 296 | |
| 297 views::View* TraySms::CreateDetailedView(user::LoginStatus status) { | |
| 298 CHECK(detailed_ == NULL); | |
| 299 HideNotificationView(); | |
| 300 if (messages_.empty()) | |
| 301 return NULL; | |
| 302 detailed_ = new SmsDetailedView(this); | |
| 303 return detailed_; | |
| 304 } | |
| 305 | |
| 306 views::View* TraySms::CreateNotificationView(user::LoginStatus status) { | |
| 307 CHECK(notification_ == NULL); | |
| 308 size_t index; | |
| 309 std::string number, text; | |
| 310 if (GetLatestMessage(&index, &number, &text)) | |
| 311 notification_ = new SmsNotificationView(this, index, number, text); | |
| 312 return notification_; | |
| 313 } | |
| 314 | |
| 315 void TraySms::DestroyDefaultView() { | |
| 316 default_ = NULL; | |
| 317 } | |
| 318 | |
| 319 void TraySms::DestroyDetailedView() { | |
| 320 detailed_ = NULL; | |
| 321 } | |
| 322 | |
| 323 void TraySms::DestroyNotificationView() { | |
| 324 notification_ = NULL; | |
| 325 } | |
| 326 | |
| 327 void TraySms::AddMessage(const base::DictionaryValue& message) { | |
| 328 messages_.Append(message.DeepCopy()); | |
| 329 Update(true); | |
| 330 } | |
| 331 | |
| 332 bool TraySms::GetLatestMessage(size_t* index, | |
| 333 std::string* number, | |
| 334 std::string* text) { | |
| 335 if (messages_.empty()) | |
| 336 return false; | |
| 337 DictionaryValue* message; | |
| 338 size_t message_index = messages_.GetSize() - 1; | |
| 339 if (!messages_.GetDictionary(message_index, &message)) | |
| 340 return false; | |
| 341 if (!GetMessageFromDictionary(message, number, text)) | |
| 342 return false; | |
| 343 *index = message_index; | |
| 344 return true; | |
| 345 } | |
| 346 | |
| 347 void TraySms::RemoveMessage(size_t index) { | |
| 348 if (index < messages_.GetSize()) | |
| 349 messages_.Remove(index, NULL); | |
| 350 } | |
| 351 | |
| 352 void TraySms::Update(bool notify) { | |
| 353 if (messages_.empty()) { | |
| 354 if (default_) | |
| 355 default_->SetVisible(false); | |
| 356 if (detailed_) | |
| 357 HideDetailedView(); | |
| 358 HideNotificationView(); | |
| 359 } else { | |
| 360 if (default_) { | |
| 361 default_->SetVisible(true); | |
| 362 default_->Update(); | |
| 363 } | |
| 364 if (detailed_) | |
| 365 detailed_->Update(); | |
| 366 if (notification_) { | |
| 367 size_t index; | |
| 368 std::string number, text; | |
| 369 if (GetLatestMessage(&index, &number, &text)) | |
| 370 notification_->Update(index, number, text); | |
| 371 } else if (notify) { | |
| 372 ShowNotificationView(); | |
| 373 } | |
| 374 } | |
| 375 } | |
| 376 | |
| 377 } // namespace internal | |
| 378 } // namespace ash | |
| OLD | NEW |