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

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

Powered by Google App Engine
This is Rietveld 408576698