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

Side by Side Diff: ash/common/system/cast/tray_cast.cc

Issue 2463163002: Update chromeos system menu buttons for MD. (Closed)
Patch Set: boxlayout has some annoying dchecks Created 4 years, 1 month 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
« no previous file with comments | « ash/common/system/cast/tray_cast.h ('k') | ash/common/system/chromeos/cast/tray_cast.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 2015 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/common/system/cast/tray_cast.h"
6
7 #include "ash/common/material_design/material_design_controller.h"
8 #include "ash/common/session/session_state_delegate.h"
9 #include "ash/common/shelf/wm_shelf_util.h"
10 #include "ash/common/system/chromeos/screen_security/screen_tray_item.h"
11 #include "ash/common/system/tray/fixed_sized_image_view.h"
12 #include "ash/common/system/tray/fixed_sized_scroll_view.h"
13 #include "ash/common/system/tray/hover_highlight_view.h"
14 #include "ash/common/system/tray/system_tray.h"
15 #include "ash/common/system/tray/system_tray_delegate.h"
16 #include "ash/common/system/tray/throbber_view.h"
17 #include "ash/common/system/tray/tray_constants.h"
18 #include "ash/common/system/tray/tray_details_view.h"
19 #include "ash/common/system/tray/tray_item_more.h"
20 #include "ash/common/system/tray/tray_item_view.h"
21 #include "ash/common/system/tray/tray_popup_label_button.h"
22 #include "ash/common/wm_shell.h"
23 #include "ash/public/cpp/shelf_types.h"
24 #include "ash/resources/vector_icons/vector_icons.h"
25 #include "base/bind.h"
26 #include "grit/ash_resources.h"
27 #include "grit/ash_strings.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/gfx/image/image.h"
31 #include "ui/gfx/paint_vector_icon.h"
32 #include "ui/gfx/text_elider.h"
33 #include "ui/views/controls/button/button.h"
34 #include "ui/views/controls/image_view.h"
35 #include "ui/views/controls/label.h"
36 #include "ui/views/layout/box_layout.h"
37 #include "ui/views/layout/fill_layout.h"
38
39 namespace ash {
40
41 namespace {
42
43 const size_t kMaximumStatusStringLength = 100;
44 const int kStopButtonRightPadding = 18;
45
46 // Returns the active CastConfigDelegate instance.
47 CastConfigDelegate* GetCastConfigDelegate() {
48 return WmShell::Get()->system_tray_delegate()->GetCastConfigDelegate();
49 }
50
51 // Helper method to elide the given string to the maximum length. If a string is
52 // contains user-input and is displayed, we should elide it.
53 // TODO(jdufault): This does not properly trim unicode characters. We should
54 // implement this properly by using views::Label::SetElideBehavior(...). See
55 // crbug.com/532496.
56 base::string16 ElideString(const base::string16& text) {
57 base::string16 elided;
58 gfx::ElideString(text, kMaximumStatusStringLength, &elided);
59 return elided;
60 }
61
62 // Returns a vectorized version of the Cast icon. The icon's interior region is
63 // filled in if |is_casting| is true.
64 gfx::ImageSkia GetCastIconForSystemMenu(bool is_casting) {
65 return gfx::CreateVectorIcon(
66 kSystemMenuCastIcon, is_casting ? kMenuIconColor : SK_ColorTRANSPARENT);
67 }
68
69 } // namespace
70
71 namespace tray {
72
73 // This view is displayed in the system tray when the cast extension is active.
74 // It asks the user if they want to cast the desktop. If they click on the
75 // chevron, then a detail view will replace this view where the user will
76 // actually pick the cast receiver.
77 class CastSelectDefaultView : public TrayItemMore {
78 public:
79 CastSelectDefaultView(SystemTrayItem* owner, bool show_more);
80 ~CastSelectDefaultView() override;
81
82 private:
83 DISALLOW_COPY_AND_ASSIGN(CastSelectDefaultView);
84 };
85
86 CastSelectDefaultView::CastSelectDefaultView(SystemTrayItem* owner,
87 bool show_more)
88 : TrayItemMore(owner, show_more) {
89 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
90
91 // Update the image and label.
92 if (MaterialDesignController::IsSystemTrayMenuMaterial())
93 SetImage(GetCastIconForSystemMenu(false));
94 else
95 SetImage(*rb.GetImageNamed(IDR_AURA_UBER_TRAY_CAST).ToImageSkia());
96
97 base::string16 label =
98 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_DESKTOP);
99 SetLabel(label);
100 SetAccessibleName(label);
101 }
102
103 CastSelectDefaultView::~CastSelectDefaultView() {}
104
105 // This view is displayed when the screen is actively being casted; it allows
106 // the user to easily stop casting. It fully replaces the
107 // |CastSelectDefaultView| view inside of the |CastDuplexView|.
108 class CastCastView : public views::View, public views::ButtonListener {
109 public:
110 CastCastView();
111 ~CastCastView() override;
112
113 void StopCasting();
114
115 const std::string& displayed_activity_id() const {
116 return displayed_activity_id_;
117 }
118
119 // Updates the label for the stop view to include information about the
120 // current device that is being casted.
121 void UpdateLabel(
122 const CastConfigDelegate::ReceiversAndActivities& receivers_activities);
123
124 private:
125 // Overridden from views::View.
126 int GetHeightForWidth(int width) const override;
127 void Layout() override;
128
129 // Overridden from views::ButtonListener.
130 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
131
132 // The cast activity id that we are displaying. If the user stops a cast, we
133 // send this value to the config delegate so that we stop the right cast.
134 std::string displayed_activity_id_;
135
136 views::ImageView* icon_;
137 views::Label* label_;
138 TrayPopupLabelButton* stop_button_;
139
140 DISALLOW_COPY_AND_ASSIGN(CastCastView);
141 };
142
143 CastCastView::CastCastView() {
144 // We will initialize the primary tray view which shows a stop button here.
145
146 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
147 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
148 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
149 kTrayPopupPaddingHorizontal, 0,
150 kTrayPopupPaddingBetweenItems));
151 icon_ = new FixedSizedImageView(0, GetTrayConstant(TRAY_POPUP_ITEM_HEIGHT));
152 if (MaterialDesignController::IsSystemTrayMenuMaterial()) {
153 icon_->SetImage(GetCastIconForSystemMenu(true));
154 } else {
155 icon_->SetImage(
156 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_CAST_ENABLED).ToImageSkia());
157 }
158 AddChildView(icon_);
159
160 // The label which describes both what we are casting (ie, the desktop) and
161 // where we are casting it to.
162 label_ = new views::Label;
163 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
164 label_->SetMultiLine(true);
165 label_->SetText(
166 bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN));
167 AddChildView(label_);
168
169 // Add the stop bottom on the far-right. We customize how this stop button is
170 // displayed inside of |Layout()|.
171 base::string16 stop_button_text =
172 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
173 IDS_ASH_STATUS_TRAY_CAST_STOP);
174 stop_button_ = new TrayPopupLabelButton(this, stop_button_text);
175 AddChildView(stop_button_);
176 }
177
178 CastCastView::~CastCastView() {}
179
180 int CastCastView::GetHeightForWidth(int width) const {
181 // We are reusing the cached label_->bounds() calculation which was
182 // done inside of Layout(). Due to the way this object is initialized,
183 // Layout() will always get initially invoked with the dummy text
184 // (which will compute the proper label width) and then when we know
185 // the cast receiver we will update the label text, which will cause
186 // this method to get invoked.
187 return std::max(views::View::GetHeightForWidth(width),
188 kTrayPopupPaddingBetweenItems * 2 +
189 label_->GetHeightForWidth(label_->bounds().width()));
190 }
191
192 void CastCastView::Layout() {
193 views::View::Layout();
194
195 // Give the stop button the space it requests.
196 gfx::Size stop_size = stop_button_->GetPreferredSize();
197 gfx::Rect stop_bounds(stop_size);
198 stop_bounds.set_x(width() - stop_size.width() - kStopButtonRightPadding);
199 stop_bounds.set_y((height() - stop_size.height()) / 2);
200 stop_button_->SetBoundsRect(stop_bounds);
201
202 // Adjust the label's bounds in case it got cut off by |stop_button_|.
203 if (label_->bounds().Intersects(stop_button_->bounds())) {
204 gfx::Rect label_bounds = label_->bounds();
205 label_bounds.set_width(stop_button_->x() - kTrayPopupPaddingBetweenItems -
206 label_->x());
207 label_->SetBoundsRect(label_bounds);
208 }
209 }
210
211 void CastCastView::StopCasting() {
212 GetCastConfigDelegate()->StopCasting(displayed_activity_id_);
213 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_CAST_STOP_CAST);
214 }
215
216 void CastCastView::UpdateLabel(
217 const CastConfigDelegate::ReceiversAndActivities& receivers_activities) {
218 for (auto& i : receivers_activities) {
219 const CastConfigDelegate::Receiver& receiver = i.receiver;
220 const CastConfigDelegate::Activity& activity = i.activity;
221
222 if (!activity.id.empty()) {
223 displayed_activity_id_ = activity.id;
224
225 // We want to display different labels inside of the title depending on
226 // what we are actually casting - either the desktop, a tab, or a fallback
227 // that catches everything else (ie, an extension tab).
228 if (activity.tab_id == CastConfigDelegate::Activity::TabId::DESKTOP) {
229 label_->SetText(ElideString(l10n_util::GetStringFUTF16(
230 IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP, receiver.name)));
231 } else if (activity.tab_id >= 0) {
232 label_->SetText(ElideString(l10n_util::GetStringFUTF16(
233 IDS_ASH_STATUS_TRAY_CAST_CAST_TAB, activity.title, receiver.name)));
234 } else {
235 label_->SetText(
236 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN));
237 }
238
239 PreferredSizeChanged();
240 Layout();
241
242 // If this machine is the source of the activity, then we want to display
243 // it over any other activity. There can be multiple activities if other
244 // devices on the network are casting at the same time.
245 if (activity.is_local_source)
246 break;
247 }
248 }
249 }
250
251 void CastCastView::ButtonPressed(views::Button* sender,
252 const ui::Event& event) {
253 DCHECK(sender == stop_button_);
254 StopCasting();
255 }
256
257 // This view by itself does very little. It acts as a front-end for managing
258 // which of the two child views (|CastSelectDefaultView| and |CastCastView|)
259 // is active.
260 class CastDuplexView : public views::View {
261 public:
262 CastDuplexView(
263 SystemTrayItem* owner,
264 bool show_more,
265 const CastConfigDelegate::ReceiversAndActivities& receivers_activities);
266 ~CastDuplexView() override;
267
268 // Activate either the casting or select view.
269 void ActivateCastView();
270 void ActivateSelectView();
271
272 CastSelectDefaultView* select_view() { return select_view_; }
273 CastCastView* cast_view() { return cast_view_; }
274
275 private:
276 // Overridden from views::View.
277 void ChildPreferredSizeChanged(views::View* child) override;
278 void Layout() override;
279
280 // Only one of |select_view_| or |cast_view_| will be displayed at any given
281 // time. This will return the view is being displayed.
282 views::View* ActiveChildView();
283
284 CastSelectDefaultView* select_view_;
285 CastCastView* cast_view_;
286
287 DISALLOW_COPY_AND_ASSIGN(CastDuplexView);
288 };
289
290 CastDuplexView::CastDuplexView(
291 SystemTrayItem* owner,
292 bool show_more,
293 const CastConfigDelegate::ReceiversAndActivities& receivers_activities) {
294 select_view_ = new CastSelectDefaultView(owner, show_more);
295 cast_view_ = new CastCastView();
296 cast_view_->UpdateLabel(receivers_activities);
297 SetLayoutManager(new views::FillLayout());
298
299 ActivateSelectView();
300 }
301
302 CastDuplexView::~CastDuplexView() {
303 RemoveChildView(ActiveChildView());
304 delete select_view_;
305 delete cast_view_;
306 }
307
308 void CastDuplexView::ActivateCastView() {
309 if (ActiveChildView() == cast_view_)
310 return;
311
312 RemoveChildView(select_view_);
313 AddChildView(cast_view_);
314 InvalidateLayout();
315 }
316
317 void CastDuplexView::ActivateSelectView() {
318 if (ActiveChildView() == select_view_)
319 return;
320
321 RemoveChildView(cast_view_);
322 AddChildView(select_view_);
323 InvalidateLayout();
324 }
325
326 void CastDuplexView::ChildPreferredSizeChanged(views::View* child) {
327 PreferredSizeChanged();
328 }
329
330 void CastDuplexView::Layout() {
331 views::View::Layout();
332
333 select_view_->SetBoundsRect(GetContentsBounds());
334 cast_view_->SetBoundsRect(GetContentsBounds());
335 }
336
337 views::View* CastDuplexView::ActiveChildView() {
338 if (cast_view_->parent() == this)
339 return cast_view_;
340 if (select_view_->parent() == this)
341 return select_view_;
342 return nullptr;
343 }
344
345 // Exposes an icon in the tray. |TrayCast| manages the visiblity of this.
346 class CastTrayView : public TrayItemView {
347 public:
348 explicit CastTrayView(SystemTrayItem* tray_item);
349 ~CastTrayView() override;
350
351 private:
352 DISALLOW_COPY_AND_ASSIGN(CastTrayView);
353 };
354
355 CastTrayView::CastTrayView(SystemTrayItem* tray_item)
356 : TrayItemView(tray_item) {
357 CreateImageView();
358 if (MaterialDesignController::UseMaterialDesignSystemIcons()) {
359 image_view()->SetImage(
360 gfx::CreateVectorIcon(kSystemTrayCastIcon, kTrayIconColor));
361 } else {
362 image_view()->SetImage(ui::ResourceBundle::GetSharedInstance()
363 .GetImageNamed(IDR_AURA_UBER_TRAY_SCREENSHARE)
364 .ToImageSkia());
365 }
366 }
367
368 CastTrayView::~CastTrayView() {}
369
370 // This view displays a list of cast receivers that can be clicked on and casted
371 // to. It is activated by clicking on the chevron inside of
372 // |CastSelectDefaultView|.
373 class CastDetailedView : public TrayDetailsView {
374 public:
375 CastDetailedView(SystemTrayItem* owner,
376 LoginStatus login,
377 const CastConfigDelegate::ReceiversAndActivities&
378 receivers_and_activities);
379 ~CastDetailedView() override;
380
381 // Makes the detail view think the view associated with the given receiver_id
382 // was clicked. This will start a cast.
383 void SimulateViewClickedForTest(const std::string& receiver_id);
384
385 // Updates the list of available receivers.
386 void UpdateReceiverList(const CastConfigDelegate::ReceiversAndActivities&
387 new_receivers_and_activities);
388
389 private:
390 void CreateItems();
391
392 void UpdateReceiverListFromCachedData();
393 views::View* AddToReceiverList(
394 const CastConfigDelegate::ReceiverAndActivity& receiverActivity);
395
396 void AppendSettingsEntries();
397
398 // TrayDetailsView:
399 void HandleViewClicked(views::View* view) override;
400
401 LoginStatus login_;
402 views::View* options_ = nullptr;
403 // A mapping from the receiver id to the receiver/activity data.
404 std::map<std::string, CastConfigDelegate::ReceiverAndActivity>
405 receivers_and_activities_;
406 // A mapping from the view pointer to the associated activity id.
407 std::map<views::View*, std::string> receiver_activity_map_;
408
409 DISALLOW_COPY_AND_ASSIGN(CastDetailedView);
410 };
411
412 CastDetailedView::CastDetailedView(
413 SystemTrayItem* owner,
414 LoginStatus login,
415 const CastConfigDelegate::ReceiversAndActivities& receivers_and_activities)
416 : TrayDetailsView(owner), login_(login) {
417 CreateItems();
418 UpdateReceiverList(receivers_and_activities);
419 }
420
421 CastDetailedView::~CastDetailedView() {}
422
423 void CastDetailedView::SimulateViewClickedForTest(
424 const std::string& receiver_id) {
425 for (auto& it : receiver_activity_map_) {
426 if (it.second == receiver_id) {
427 HandleViewClicked(it.first);
428 break;
429 }
430 }
431 }
432
433 void CastDetailedView::CreateItems() {
434 CreateScrollableList();
435 if (GetCastConfigDelegate()->HasOptions())
436 AppendSettingsEntries();
437 CreateTitleRow(IDS_ASH_STATUS_TRAY_CAST);
438 }
439
440 void CastDetailedView::UpdateReceiverList(
441 const CastConfigDelegate::ReceiversAndActivities&
442 new_receivers_and_activities) {
443 // Add/update existing.
444 for (auto i = new_receivers_and_activities.begin();
445 i != new_receivers_and_activities.end(); ++i) {
446 receivers_and_activities_[i->receiver.id] = *i;
447 }
448
449 // Remove non-existent receivers. Removing an element invalidates all existing
450 // iterators.
451 auto i = receivers_and_activities_.begin();
452 while (i != receivers_and_activities_.end()) {
453 bool has_receiver = false;
454 for (auto receiver : new_receivers_and_activities) {
455 if (i->first == receiver.receiver.id)
456 has_receiver = true;
457 }
458
459 if (has_receiver)
460 ++i;
461 else
462 i = receivers_and_activities_.erase(i);
463 }
464
465 // Update UI.
466 UpdateReceiverListFromCachedData();
467 Layout();
468 }
469
470 void CastDetailedView::UpdateReceiverListFromCachedData() {
471 // Remove all of the existing views.
472 receiver_activity_map_.clear();
473 scroll_content()->RemoveAllChildViews(true);
474
475 // Add a view for each receiver.
476 for (auto& it : receivers_and_activities_) {
477 const CastConfigDelegate::ReceiverAndActivity& receiver_activity =
478 it.second;
479 views::View* container = AddToReceiverList(receiver_activity);
480 receiver_activity_map_[container] = it.first;
481 }
482
483 scroll_content()->SizeToPreferredSize();
484 static_cast<views::View*>(scroller())->Layout();
485 }
486
487 views::View* CastDetailedView::AddToReceiverList(
488 const CastConfigDelegate::ReceiverAndActivity& receiverActivity) {
489 HoverHighlightView* container = new HoverHighlightView(this);
490
491 const gfx::ImageSkia* image =
492 ui::ResourceBundle::GetSharedInstance()
493 .GetImageNamed(IDR_AURA_UBER_TRAY_CAST_DEVICE_ICON)
494 .ToImageSkia();
495 const base::string16& name = receiverActivity.receiver.name;
496 container->AddIconAndLabelCustomSize(
497 *image, name, false, kTrayPopupDetailsIconWidth,
498 kTrayPopupPaddingHorizontal, kTrayPopupPaddingBetweenItems);
499
500 scroll_content()->AddChildView(container);
501 return container;
502 }
503
504 void CastDetailedView::AppendSettingsEntries() {
505 if (MaterialDesignController::IsSystemTrayMenuMaterial())
506 return;
507
508 // Settings requires a browser window, hide it for non logged in user.
509 if (login_ == LoginStatus::NOT_LOGGED_IN || login_ == LoginStatus::LOCKED ||
510 WmShell::Get()->GetSessionStateDelegate()->IsInSecondaryLoginScreen()) {
511 return;
512 }
513
514 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
515 HoverHighlightView* container = new HoverHighlightView(this);
516 container->AddLabel(rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_CAST_OPTIONS),
517 gfx::ALIGN_LEFT, false /* highlight */);
518
519 AddChildView(container);
520 options_ = container;
521 }
522
523 void CastDetailedView::HandleViewClicked(views::View* view) {
524 if (view == options_) {
525 GetCastConfigDelegate()->LaunchCastOptions();
526 return;
527 }
528
529 // Find the receiver we are going to cast to.
530 auto it = receiver_activity_map_.find(view);
531 if (it != receiver_activity_map_.end()) {
532 GetCastConfigDelegate()->CastToReceiver(it->second);
533 WmShell::Get()->RecordUserMetricsAction(
534 UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST);
535 }
536 }
537
538 } // namespace tray
539
540 TrayCast::TrayCast(SystemTray* system_tray)
541 : SystemTrayItem(system_tray, UMA_CAST) {
542 WmShell::Get()->AddShellObserver(this);
543 }
544
545 TrayCast::~TrayCast() {
546 WmShell::Get()->RemoveShellObserver(this);
547 if (added_observer_)
548 GetCastConfigDelegate()->RemoveObserver(this);
549 }
550
551 void TrayCast::StartCastForTest(const std::string& receiver_id) {
552 if (detailed_ != nullptr)
553 detailed_->SimulateViewClickedForTest(receiver_id);
554 }
555
556 void TrayCast::StopCastForTest() {
557 default_->cast_view()->StopCasting();
558 }
559
560 const std::string& TrayCast::GetDisplayedCastId() {
561 return default_->cast_view()->displayed_activity_id();
562 }
563
564 const views::View* TrayCast::GetDefaultView() const {
565 return default_;
566 }
567
568 views::View* TrayCast::CreateTrayView(LoginStatus status) {
569 CHECK(tray_ == nullptr);
570 tray_ = new tray::CastTrayView(this);
571 tray_->SetVisible(is_casting_);
572 return tray_;
573 }
574
575 views::View* TrayCast::CreateDefaultView(LoginStatus status) {
576 CHECK(default_ == nullptr);
577
578 if (HasCastExtension()) {
579 CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate();
580
581 // Add the cast observer here instead of the ctor for two reasons:
582 // - The ctor gets called too early in the initialization cycle (at least
583 // for the tests); the correct profile hasn't been setup yet.
584 // - If we're using the cast extension backend (media router is disabled),
585 // then the user can install the extension at any point in time. The
586 // return value of HasCastExtension() can change, so only checking it in
587 // the ctor isn't enough.
588 if (!added_observer_) {
589 cast_config_delegate->AddObserver(this);
590 added_observer_ = true;
591 }
592
593 // The extension updates its view model whenever the popup is opened, so we
594 // probably should as well.
595 cast_config_delegate->RequestDeviceRefresh();
596 }
597
598 default_ = new tray::CastDuplexView(this, status != LoginStatus::LOCKED,
599 receivers_and_activities_);
600 default_->set_id(TRAY_VIEW);
601 default_->select_view()->set_id(SELECT_VIEW);
602 default_->cast_view()->set_id(CAST_VIEW);
603
604 UpdatePrimaryView();
605 return default_;
606 }
607
608 views::View* TrayCast::CreateDetailedView(LoginStatus status) {
609 WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_DETAILED_CAST_VIEW);
610 CHECK(detailed_ == nullptr);
611 detailed_ =
612 new tray::CastDetailedView(this, status, receivers_and_activities_);
613 return detailed_;
614 }
615
616 void TrayCast::DestroyTrayView() {
617 tray_ = nullptr;
618 }
619
620 void TrayCast::DestroyDefaultView() {
621 default_ = nullptr;
622 }
623
624 void TrayCast::DestroyDetailedView() {
625 detailed_ = nullptr;
626 }
627
628 bool TrayCast::HasCastExtension() {
629 CastConfigDelegate* cast_config_delegate = GetCastConfigDelegate();
630 return cast_config_delegate != nullptr &&
631 cast_config_delegate->HasCastExtension();
632 }
633
634 void TrayCast::OnDevicesUpdated(
635 const CastConfigDelegate::ReceiversAndActivities& receivers_activities) {
636 receivers_and_activities_ = receivers_activities;
637
638 if (default_) {
639 bool has_receivers = !receivers_and_activities_.empty();
640 default_->SetVisible(has_receivers);
641 default_->cast_view()->UpdateLabel(receivers_and_activities_);
642 }
643 if (detailed_)
644 detailed_->UpdateReceiverList(receivers_and_activities_);
645 }
646
647 void TrayCast::UpdatePrimaryView() {
648 if (HasCastExtension() && !receivers_and_activities_.empty()) {
649 if (default_) {
650 if (is_casting_)
651 default_->ActivateCastView();
652 else
653 default_->ActivateSelectView();
654 }
655
656 if (tray_)
657 tray_->SetVisible(is_casting_);
658 } else {
659 if (default_)
660 default_->SetVisible(false);
661 if (tray_)
662 tray_->SetVisible(false);
663 }
664 }
665
666 void TrayCast::OnCastingSessionStartedOrStopped(bool started) {
667 is_casting_ = started;
668 UpdatePrimaryView();
669 }
670
671 } // namespace ash
OLDNEW
« no previous file with comments | « ash/common/system/cast/tray_cast.h ('k') | ash/common/system/chromeos/cast/tray_cast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698