Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(498)

Side by Side Diff: ash/system/network/tray_sms.cc

Issue 10332152: Add TraySms for SMS messages. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix bubble sizing code Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ash/system/network/tray_sms.h ('k') | ash/system/tray/system_tray.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_views.h"
15 #include "base/command_line.h"
16 #include "base/string_number_conversions.h"
17 #include "base/utf_string_conversions.h"
18 #include "grit/ash_strings.h"
19 #include "grit/ui_resources.h"
20 #include "grit/ui_resources_standard.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 #if defined(OS_CHROMEOS)
31 #include "chromeos/network/network_sms_handler.h"
32 #endif
33
34 namespace {
35
36 // Min height of the list of messages in the popup.
37 const int kMessageListMinHeight = 200;
38 // Top/bottom padding of the text items.
39 const int kPaddingVertical = 10;
40 const int kSmsIconWidth = 50;
41
42 } // namespace
43
44 namespace ash {
45 namespace internal {
46
47 class SmsObserverBase {
48 public:
49 explicit SmsObserverBase(TraySms* tray) : tray_(tray) {}
50 virtual ~SmsObserverBase() {}
51
52 bool GetMessageFromDictionary(const base::DictionaryValue* message,
53 std::string* number,
54 std::string* text) {
55 if (!message->GetStringWithoutPathExpansion(
56 chromeos::NetworkSmsHandler::kNumberKey, number))
57 return false;
58 if (!message->GetStringWithoutPathExpansion(
59 chromeos::NetworkSmsHandler::kTextKey, text))
60 return false;
61 return true;
62 }
63
64 void RemoveMessage(size_t index) {
65 if (index < messages_.GetSize())
66 messages_.Remove(index, NULL);
67 }
68
69 const base::ListValue& messages() const { return messages_; }
70
71 protected:
72 base::ListValue messages_;
73 TraySms* tray_;
74
75 private:
76 DISALLOW_COPY_AND_ASSIGN(SmsObserverBase);
77 };
78
79 #if defined(OS_CHROMEOS)
80
81 class TraySms::SmsObserver : public SmsObserverBase,
82 public chromeos::NetworkSmsHandler::Observer {
83 public:
84 explicit SmsObserver(TraySms* tray) : SmsObserverBase(tray) {
85 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshNotify))
86 return;
87 sms_handler_.reset(new chromeos::NetworkSmsHandler());
88 sms_handler_->AddObserver(this);
89 sms_handler_->Init();
90 }
91
92 virtual ~SmsObserver() {
93 if (sms_handler_.get())
94 sms_handler_->RemoveObserver(this);
95 }
96
97 // Overridden from chromeos::NetworkSmsHandler::Observer
98 virtual void MessageReceived(const base::DictionaryValue& message) {
99 messages_.Append(message.DeepCopy());
100 tray_->Update(true);
101 }
102
103 // Requests an immediate check for new messages.
104 void RequestUpdate() {
105 if (sms_handler_.get())
106 sms_handler_->RequestUpdate();
107 }
108
109 private:
110 scoped_ptr<chromeos::NetworkSmsHandler> sms_handler_;
111
112 DISALLOW_COPY_AND_ASSIGN(SmsObserver);
113 };
114
115 #else // OS_CHROMEOS
116
117 class TraySms::SmsObserver : public SmsObserverBase {
118 public:
119 explicit SmsObserver(TraySms* tray) : SmsObserverBase(tray) {
120 }
121 virtual ~SmsObserver() {}
122
123 private:
124 DISALLOW_COPY_AND_ASSIGN(SmsObserver);
125 };
126
127 #endif // OS_CHROMEOS
128
129 class TraySms::SmsDefaultView : public TrayItemMore {
130 public:
131 explicit SmsDefaultView(TraySms* tray)
132 : TrayItemMore(tray),
133 tray_(tray) {
134 SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
135 IDR_AURA_UBER_TRAY_SMS));
136 Update();
137 }
138
139 virtual ~SmsDefaultView() {}
140
141 void Update() {
142 int message_count =
143 static_cast<int>(tray_->sms_observer()->messages().GetSize());
144 string16 label = l10n_util::GetStringFUTF16(
145 IDS_ASH_STATUS_TRAY_SMS_MESSAGES, base::IntToString16(message_count));
146 SetLabel(label);
147 SetAccessibleName(label);
148 }
149
150 private:
151 TraySms* tray_;
152
153 DISALLOW_COPY_AND_ASSIGN(SmsDefaultView);
154 };
155
156 // An entry (row) in SmsDetailedView or NotificationView.
157 class TraySms::SmsMessageView : public views::View,
158 public views::ButtonListener {
159 public:
160 enum ViewType {
161 VIEW_DETAILED,
162 VIEW_NOTIFICATION
163 };
164
165 SmsMessageView(TraySms* tray,
166 ViewType view_type,
167 size_t index,
168 const std::string& number,
169 const std::string& message)
170 : tray_(tray),
171 index_(index) {
172 number_label_ = new views::Label(
173 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_SMS_NUMBER,
174 UTF8ToUTF16(number)));
175 number_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
176
177 message_label_ = new views::Label(UTF8ToUTF16(message));
178 message_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
179 message_label_->SetMultiLine(true);
180
181 int msg_width;
182 if (view_type == VIEW_DETAILED)
183 msg_width = LayoutDetailedView();
184 else
185 msg_width = LayoutNotificationView();
186
187 message_label_->SizeToFit(msg_width);
188 }
189
190 virtual ~SmsMessageView() {
191 }
192
193 // Overridden from ButtonListener.
194 virtual void ButtonPressed(views::Button* sender,
195 const views::Event& event) OVERRIDE {
196 tray_->sms_observer()->RemoveMessage(index_);
197 tray_->Update(false);
198 }
199
200 private:
201 int LayoutDetailedView() {
202 views::ImageButton* close_button = new views::ImageButton(this);
203 close_button->SetImage(views::CustomButton::BS_NORMAL,
204 ResourceBundle::GetSharedInstance().GetBitmapNamed(
205 IDR_AURA_WINDOW_CLOSE));
206
207 int msg_width = kTrayPopupWidth - kNotificationCloseButtonWidth -
208 kTrayPopupPaddingHorizontal * 2;
209
210 views::GridLayout* layout = new views::GridLayout(this);
211 SetLayoutManager(layout);
212
213 views::ColumnSet* columns = layout->AddColumnSet(0);
214
215 // Message
216 columns->AddPaddingColumn(0, kTrayPopupPaddingHorizontal);
217 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
218 0 /* resize percent */,
219 views::GridLayout::FIXED, msg_width, msg_width);
220
221 // Close button
222 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
223 0, /* resize percent */
224 views::GridLayout::FIXED,
225 kNotificationCloseButtonWidth,
226 kNotificationCloseButtonWidth);
227
228
229 layout->AddPaddingRow(0, kPaddingVertical);
230 layout->StartRow(0, 0);
231 layout->AddView(number_label_);
232 layout->AddView(close_button, 1, 2); // 2 rows for icon
233 layout->StartRow(0, 0);
234 layout->AddView(message_label_);
235
236 layout->AddPaddingRow(0, kPaddingVertical);
237
238 return msg_width;
239 }
240
241 int LayoutNotificationView() {
242 icon_ = new views::ImageView;
243 icon_->SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
244 IDR_AURA_UBER_TRAY_SMS));
245
246 int msg_width = kTrayPopupWidth - kNotificationCloseButtonWidth -
247 kTrayPopupPaddingHorizontal - kSmsIconWidth;
248
249 views::GridLayout* layout = new views::GridLayout(this);
250 SetLayoutManager(layout);
251
252 views::ColumnSet* columns = layout->AddColumnSet(0);
253
254 // Icon
255 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
256 0 /* resize percent */,
257 views::GridLayout::FIXED, kSmsIconWidth, kSmsIconWidth);
258
259 // Message
260 columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
261 0 /* resize percent */,
262 views::GridLayout::FIXED, msg_width, msg_width);
263
264 layout->AddPaddingRow(0, kPaddingVertical);
265
266 layout->StartRow(0, 0);
267 layout->AddView(icon_, 1, 2); // 2 rows for icon
268 layout->AddView(number_label_);
269 layout->StartRow(0, 0);
270 layout->SkipColumns(1);
271 layout->AddView(message_label_);
272 layout->StartRow(0, 0);
273
274 layout->AddPaddingRow(0, kPaddingVertical);
275
276 return msg_width;
277 }
278
279 TraySms* tray_;
280 size_t index_;
281 views::Label* number_label_;
282 views::Label* message_label_;
283 views::ImageView* icon_;
284
285 DISALLOW_COPY_AND_ASSIGN(SmsMessageView);
286 };
287
288 class TraySms::SmsDetailedView : public TrayDetailsView,
289 public ViewClickListener {
290 public:
291 explicit SmsDetailedView(TraySms* tray)
292 : tray_(tray) {
293 Init();
294 Update();
295 }
296
297 virtual ~SmsDetailedView() {
298 }
299
300 void Init() {
301 CreateScrollableList();
302 CreateSpecialRow(IDS_ASH_STATUS_TRAY_SMS, this);
303 }
304
305 void Update() {
306 UpdateMessageList();
307 Layout();
308 SchedulePaint();
309 }
310
311 // Overridden from views::View.
312 gfx::Size GetPreferredSize() {
313 gfx::Size preferred_size = TrayDetailsView::GetPreferredSize();
314 if (preferred_size.height() < kMessageListMinHeight)
315 preferred_size.set_height(kMessageListMinHeight);
316 return preferred_size;
317 }
318
319 private:
320 void UpdateMessageList() {
321 const base::ListValue& messages = tray_->sms_observer()->messages();
322 scroll_content()->RemoveAllChildViews(true);
323 for (size_t index = 0; index < messages.GetSize(); ++index) {
324 base::DictionaryValue* message = NULL;
325 if (!messages.GetDictionary(index, &message)) {
326 LOG(ERROR) << "SMS message not a dictionary at: " << index;
327 continue;
328 }
329 std::string number, text;
330 if (!tray_->sms_observer()->GetMessageFromDictionary(
331 message, &number, &text)) {
332 LOG(ERROR) << "Error parsing SMS message";
333 continue;
334 }
335 SmsMessageView* msgview = new SmsMessageView(
336 tray_, SmsMessageView::VIEW_DETAILED, index, number, text);
337 scroll_content()->AddChildView(msgview);
338 }
339 scroller()->Layout();
340 }
341
342 // Overridden from ViewClickListener.
343 virtual void ClickedOn(views::View* sender) OVERRIDE {
344 if (sender == footer()->content())
345 Shell::GetInstance()->tray()->ShowDefaultView(BUBBLE_USE_EXISTING);
346 }
347
348 TraySms* tray_;
349
350 DISALLOW_COPY_AND_ASSIGN(SmsDetailedView);
351 };
352
353 class TraySms::SmsNotificationView : public TrayNotificationView {
354 public:
355 SmsNotificationView(TraySms* tray,
356 const std::string& number,
357 const std::string& text,
358 size_t message_index)
359 : tray_(tray),
360 message_index_(message_index) {
361 SmsMessageView* message_view_ = new SmsMessageView(
362 tray_, SmsMessageView::VIEW_NOTIFICATION, message_index, number, text);
363 InitView(message_view_);
364 }
365
366 // Overridden from views::View.
367 bool OnMousePressed(const views::MouseEvent& event) {
368 tray_->PopupDetailedView(0, true);
369 return true;
370 }
371
372 // Overridden from TrayNotificationView:
373 virtual void OnClose() OVERRIDE {
374 tray_->sms_observer()->RemoveMessage(message_index_);
375 tray_->HideNotificationView();
376 }
377
378 private:
379 TraySms* tray_;
380 SmsMessageView* message_view_;
381 size_t message_index_;
382
383 DISALLOW_COPY_AND_ASSIGN(SmsNotificationView);
384 };
385
386 TraySms::TraySms()
387 : TrayImageItem(IDR_AURA_UBER_TRAY_SMS),
388 default_(NULL),
389 detailed_(NULL),
390 notification_(NULL) {
391 sms_observer_.reset(new SmsObserver(this));
392 }
393
394 TraySms::~TraySms() {
395 }
396
397 bool TraySms::GetInitialVisibility() {
398 return !sms_observer()->messages().empty();
399 }
400
401 views::View* TraySms::CreateDefaultView(user::LoginStatus status) {
402 CHECK(default_ == NULL);
403 sms_observer()->RequestUpdate();
404 default_ = new SmsDefaultView(this);
405 default_->SetVisible(!sms_observer()->messages().empty());
406 return default_;
407 }
408
409 views::View* TraySms::CreateDetailedView(user::LoginStatus status) {
410 CHECK(detailed_ == NULL);
411 sms_observer()->RequestUpdate();
412 HideNotificationView();
413 if (sms_observer()->messages().empty())
414 return NULL;
415 detailed_ = new SmsDetailedView(this);
416 return detailed_;
417 }
418
419 views::View* TraySms::CreateNotificationView(user::LoginStatus status) {
420 CHECK(notification_ == NULL);
421 const base::ListValue& messages = sms_observer()->messages();
422 if (messages.empty())
423 return NULL;
424 DictionaryValue* message;
425 size_t message_index = messages.GetSize() - 1;
426 if (!messages.GetDictionary(message_index, &message))
427 return NULL;
428 std::string number, text;
429 if (!sms_observer()->GetMessageFromDictionary(message, &number, &text))
430 return NULL;
431 notification_ = new SmsNotificationView(this, number, text, message_index);
432 return notification_;
433 }
434
435 void TraySms::DestroyDefaultView() {
436 default_ = NULL;
437 }
438
439 void TraySms::DestroyDetailedView() {
440 detailed_ = NULL;
441 }
442
443 void TraySms::DestroyNotificationView() {
444 notification_ = NULL;
445 }
446
447 void TraySms::Update(bool notify) {
448 HideNotificationView();
449 if (sms_observer()->messages().empty()) {
450 if (tray_view())
451 tray_view()->SetVisible(false);
452 if (default_)
453 default_->SetVisible(false);
454 if (detailed_)
455 HideDetailedView();
456 } else {
457 if (tray_view())
458 tray_view()->SetVisible(true);
459 if (default_) {
460 default_->SetVisible(true);
461 default_->Update();
462 }
463 if (detailed_)
464 detailed_->Update();
465 else if (notify)
466 ShowNotificationView();
467 }
468 }
469
470 } // namespace internal
471 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/network/tray_sms.h ('k') | ash/system/tray/system_tray.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698