desktop_media_picker_views.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Copyright 2013 The Chromium Authors. All rights reserved.
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Use of this source code is governed by a BSD-style license that can be
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// found in the LICENSE file.
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "chrome/browser/media/desktop_media_picker.h"
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ash/shell.h"
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "base/callback.h"
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "chrome/browser/media/desktop_media_picker_model.h"
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "content/public/browser/browser_thread.h"
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "grit/generated_resources.h"
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/base/keycodes/keyboard_codes.h"
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/base/l10n/l10n_util.h"
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/native_theme/native_theme.h"
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/controls/image_view.h"
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/controls/label.h"
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/controls/scroll_view.h"
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/corewm/shadow_types.h"
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/focus_border.h"
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/layout/box_layout.h"
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/layout/layout_constants.h"
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/widget/widget.h"
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/window/dialog_client_view.h"
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#include "ui/views/window/dialog_delegate.h"
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverusing content::DesktopMediaID;
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvernamespace {
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kThumbnailWidth = 160;
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kThumbnailHeight = 100;
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kThumbnailMargin = 10;
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kLabelHeight = 40;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kListItemWidth = kThumbnailMargin * 2 + kThumbnailWidth;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kListItemHeight =
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    kThumbnailMargin * 2 + kThumbnailHeight + kLabelHeight;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kListColumns = 3;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kTotalListWidth = kListColumns * kListItemWidth;
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst int kDesktopMediaSourceViewGroupId = 1;
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst char kDesktopMediaSourceViewClassName[] =
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    "DesktopMediaPicker_DesktopMediaSourceView";
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaListView;
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaPickerDialogView;
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaPickerViews;
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// View used for each item in DesktopMediaListView. Shows a single desktop media
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// source as a thumbnail with the title under it.
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaSourceView : public views::View {
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public:
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaSourceView(DesktopMediaListView* parent,
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                         DesktopMediaID source_id);
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual ~DesktopMediaSourceView();
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Updates thumbnail and title from |source|.
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void SetName(const string16& name);
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void SetThumbnail(const gfx::ImageSkia& thumbnail);
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Id for the source shown by this View.
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  const DesktopMediaID& source_id() const {
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return source_id_;
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Returns true if the source is selected.
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  bool is_selected() const { return selected_; }
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Updates selection state of the element. If |selected| is true then also
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // calls SetSelected(false) for the source view that was selected before that
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // (if any).
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void SetSelected(bool selected);
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // views::View interface.
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual const char* GetClassName() const OVERRIDE;
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void Layout() OVERRIDE;
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual views::View* GetSelectedViewForGroup(int group) OVERRIDE;
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual bool IsGroupFocusTraversable() const OVERRIDE;
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void OnFocus() OVERRIDE;
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private:
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaListView* parent_;
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaID source_id_;
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  views::ImageView* image_view_;
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  views::Label* label_;
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  bool selected_;
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DISALLOW_COPY_AND_ASSIGN(DesktopMediaSourceView);
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver};
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// View that shows list of desktop media sources available from
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// DesktopMediaPickerModel.
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaListView : public views::View,
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                             public DesktopMediaPickerModel::Observer {
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public:
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaListView(DesktopMediaPickerDialogView* parent,
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                       scoped_ptr<DesktopMediaPickerModel> model);
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual ~DesktopMediaListView();
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Called by DesktopMediaSourceView when selection has changed.
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void OnSelectionChanged();
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Returns currently selected source.
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaSourceView* GetSelection();
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // views::View overrides.
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual gfx::Size GetPreferredSize() OVERRIDE;
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void Layout() OVERRIDE;
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private:
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // DesktopMediaPickerModel::Observer interface
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void OnSourceAdded(int index) OVERRIDE;
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void OnSourceRemoved(int index) OVERRIDE;
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void OnSourceNameChanged(int index) OVERRIDE;
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void OnSourceThumbnailChanged(int index) OVERRIDE;
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaPickerDialogView* parent_;
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  scoped_ptr<DesktopMediaPickerModel> model_;
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DISALLOW_COPY_AND_ASSIGN(DesktopMediaListView);
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver};
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Dialog view used for DesktopMediaPickerViews.
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaPickerDialogView : public views::DialogDelegateView {
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public:
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaPickerDialogView(gfx::NativeWindow context,
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               gfx::NativeWindow parent_window,
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               DesktopMediaPickerViews* parent,
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               const string16& app_name,
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               scoped_ptr<DesktopMediaPickerModel> model);
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual ~DesktopMediaPickerDialogView();
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Called by parent (DesktopMediaPickerViews) when it's destroyed.
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void DetachParent();
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // Called by DesktopMediaListView.
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void OnSelectionChanged();
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // views::View overrides.
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual gfx::Size GetPreferredSize() OVERRIDE;
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void Layout() OVERRIDE;
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // views::DialogDelegateView overrides.
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual base::string16 GetWindowTitle() const OVERRIDE;
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual bool IsDialogButtonEnabled(ui::DialogButton button) const OVERRIDE;
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual bool Accept() OVERRIDE;
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void DeleteDelegate() OVERRIDE;
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private:
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaPickerViews* parent_;
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  string16 app_name_;
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  views::Label* label_;
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  views::ScrollView* scroll_view_;
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaListView* list_view_;
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerDialogView);
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver};
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver// Implementation of DesktopMediaPicker for Views.
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass DesktopMediaPickerViews : public DesktopMediaPicker {
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public:
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaPickerViews();
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual ~DesktopMediaPickerViews();
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  void NotifyDialogResult(DesktopMediaID source);
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // DesktopMediaPicker overrides.
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  virtual void Show(gfx::NativeWindow context,
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    gfx::NativeWindow parent,
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    const string16& app_name,
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    scoped_ptr<DesktopMediaPickerModel> model,
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    const DoneCallback& done_callback) OVERRIDE;
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver private:
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DoneCallback callback_;
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // The |dialog_| is owned by the corresponding views::Widget instance.
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // When DesktopMediaPickerViews is destroyed the |dialog_| is destroyed
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  // asynchronously by closing the widget.
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DesktopMediaPickerDialogView* dialog_;
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  DISALLOW_COPY_AND_ASSIGN(DesktopMediaPickerViews);
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver};
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
190324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDesktopMediaSourceView::DesktopMediaSourceView(
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaListView* parent,
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaID source_id)
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    : parent_(parent),
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      source_id_(source_id),
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      image_view_(new views::ImageView()),
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      label_(new views::Label()),
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      selected_(false)  {
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  AddChildView(image_view_);
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  AddChildView(label_);
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  set_focusable(true);
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
203324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDesktopMediaSourceView::~DesktopMediaSourceView() {}
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaSourceView::SetName(const string16& name) {
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  label_->SetText(name);
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaSourceView::SetThumbnail(const gfx::ImageSkia& thumbnail) {
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  image_view_->SetImage(thumbnail);
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaSourceView::SetSelected(bool selected) {
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (selected == selected_)
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return;
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  selected_ = selected;
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (selected) {
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    // Unselect all other sources.
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    Views neighbours;
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parent()->GetViewsInGroup(GetGroup(), &neighbours);
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    for (Views::iterator i(neighbours.begin()); i != neighbours.end(); ++i) {
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      if (*i != this) {
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        DCHECK_EQ((*i)->GetClassName(), kDesktopMediaSourceViewClassName);
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        DesktopMediaSourceView* source_view =
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            static_cast<DesktopMediaSourceView*>(*i);
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        source_view->SetSelected(false);
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      }
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    const SkColor bg_color = GetNativeTheme()->GetSystemColor(
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor);
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    set_background(views::Background::CreateSolidBackground(bg_color));
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    parent_->OnSelectionChanged();
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  } else {
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    set_background(NULL);
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  SchedulePaint();
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverconst char* DesktopMediaSourceView::GetClassName() const {
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return kDesktopMediaSourceViewClassName;
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaSourceView::Layout() {
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  image_view_->SetBounds(kThumbnailMargin, kThumbnailMargin,
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                         kThumbnailWidth, kThumbnailHeight);
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  label_->SetBounds(kThumbnailMargin, kThumbnailHeight + kThumbnailMargin,
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    kThumbnailWidth, kLabelHeight);
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  set_focus_border(views::FocusBorder::CreateDashedFocusBorder(
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      kThumbnailMargin / 2, kThumbnailMargin / 2,
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      kThumbnailMargin / 2, kThumbnailMargin / 2));
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverviews::View* DesktopMediaSourceView::GetSelectedViewForGroup(int group) {
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  Views neighbours;
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  parent()->GetViewsInGroup(group, &neighbours);
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (neighbours.empty())
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    return NULL;
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  for (Views::iterator i(neighbours.begin()); i != neighbours.end(); ++i) {
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DCHECK_EQ((*i)->GetClassName(), kDesktopMediaSourceViewClassName);
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaSourceView* source_view =
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        static_cast<DesktopMediaSourceView*>(*i);
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (source_view->selected_)
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return source_view;
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return NULL;
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbool DesktopMediaSourceView::IsGroupFocusTraversable() const {
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return false;
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaSourceView::OnFocus() {
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  View::OnFocus();
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  SetSelected(true);
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  ScrollRectToVisible(gfx::Rect(size()));
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbool DesktopMediaSourceView::OnMousePressed(const ui::MouseEvent& event) {
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  RequestFocus();
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return true;
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
289324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDesktopMediaListView::DesktopMediaListView(
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaPickerDialogView* parent,
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    scoped_ptr<DesktopMediaPickerModel> model)
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    : parent_(parent),
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      model_(model.Pass()) {
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  model_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight));
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  model_->StartUpdating(this);
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
298324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDesktopMediaListView::~DesktopMediaListView() {
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaListView::OnSelectionChanged() {
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  parent_->OnSelectionChanged();
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
305324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverDesktopMediaSourceView* DesktopMediaListView::GetSelection() {
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  for (int i = 0; i < child_count(); ++i) {
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaSourceView* source_view =
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        static_cast<DesktopMediaSourceView*>(child_at(i));
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DCHECK_EQ(source_view->GetClassName(), kDesktopMediaSourceViewClassName);
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (source_view->is_selected())
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return source_view;
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return NULL;
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvergfx::Size DesktopMediaListView::GetPreferredSize() {
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  int total_rows = (child_count() + kListColumns - 1) / kListColumns;
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  return gfx::Size(kTotalListWidth, kListItemHeight * total_rows);
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvervoid DesktopMediaListView::Layout() {
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  int x = 0;
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  int y = 0;
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  for (int i = 0; i < child_count(); ++i) {
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (x + kListItemWidth > kTotalListWidth) {
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      x = 0;
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      y += kListItemHeight;
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    View* source_view = child_at(i);
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    source_view->SetBounds(x, y, kListItemWidth, kListItemHeight);
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    x += kListItemWidth;
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  y += kListItemHeight;
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  SetSize(gfx::Size(kTotalListWidth, y));
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverbool DesktopMediaListView::OnKeyPressed(const ui::KeyEvent& event) {
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  int position_increment = 0;
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  switch (event.key_code()) {
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case ui::VKEY_UP:
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      position_increment = -kListColumns;
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      break;
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case ui::VKEY_DOWN:
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      position_increment = kListColumns;
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      break;
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case ui::VKEY_LEFT:
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      position_increment = -1;
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      break;
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    case ui::VKEY_RIGHT:
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      position_increment = 1;
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      break;
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    default:
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      return false;
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  }
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if (position_increment != 0) {
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaSourceView* selected = GetSelection();
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    DesktopMediaSourceView* new_selected = NULL;
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if (selected) {
367      int index = GetIndexOf(selected);
368      int new_index = index + position_increment;
369      if (new_index >= child_count())
370        new_index = child_count() - 1;
371      else if (new_index < 0)
372        new_index = 0;
373      if (index != new_index) {
374        new_selected =
375            static_cast<DesktopMediaSourceView*>(child_at(new_index));
376      }
377    } else if (has_children()) {
378      new_selected = static_cast<DesktopMediaSourceView*>(child_at(0));
379    }
380
381    if (new_selected) {
382      GetFocusManager()->SetFocusedView(new_selected);
383    }
384
385    return true;
386  }
387
388  return false;
389}
390
391void DesktopMediaListView::OnSourceAdded(int index) {
392  const DesktopMediaPickerModel::Source& source = model_->source(index);
393  DesktopMediaSourceView* source_view =
394      new DesktopMediaSourceView(this, source.id);
395  source_view->SetName(source.name);
396  source_view->SetGroup(kDesktopMediaSourceViewGroupId);
397  AddChildViewAt(source_view, index);
398  Layout();
399}
400
401void DesktopMediaListView::OnSourceRemoved(int index) {
402  DesktopMediaSourceView* view =
403      static_cast<DesktopMediaSourceView*>(child_at(index));
404  DCHECK(view);
405  DCHECK_EQ(view->GetClassName(), kDesktopMediaSourceViewClassName);
406  bool was_selected = view->is_selected();
407  RemoveChildView(view);
408  delete view;
409
410  if (was_selected)
411    OnSelectionChanged();
412
413  PreferredSizeChanged();
414}
415
416void DesktopMediaListView::OnSourceNameChanged(int index) {
417  const DesktopMediaPickerModel::Source& source = model_->source(index);
418  DesktopMediaSourceView* source_view =
419      static_cast<DesktopMediaSourceView*>(child_at(index));
420  source_view->SetName(source.name);
421}
422
423void DesktopMediaListView::OnSourceThumbnailChanged(int index) {
424  const DesktopMediaPickerModel::Source& source = model_->source(index);
425  DesktopMediaSourceView* source_view =
426      static_cast<DesktopMediaSourceView*>(child_at(index));
427  source_view->SetThumbnail(source.thumbnail);
428}
429
430DesktopMediaPickerDialogView::DesktopMediaPickerDialogView(
431    gfx::NativeWindow context,
432    gfx::NativeWindow parent_window,
433    DesktopMediaPickerViews* parent,
434    const string16& app_name,
435    scoped_ptr<DesktopMediaPickerModel> model)
436    : parent_(parent),
437      app_name_(app_name),
438      label_(new views::Label()),
439      scroll_view_(views::ScrollView::CreateScrollViewWithBorder()),
440      list_view_(new DesktopMediaListView(this, model.Pass())) {
441  label_->SetText(
442      l10n_util::GetStringFUTF16(IDS_DESKTOP_MEDIA_PICKER_TEXT, app_name_));
443  label_->SetMultiLine(true);
444  label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
445  AddChildView(label_);
446
447  scroll_view_->SetContents(list_view_);
448  AddChildView(scroll_view_);
449
450  DialogDelegate::CreateDialogWidget(this, context, parent_window);
451  GetWidget()->Show();
452}
453
454DesktopMediaPickerDialogView::~DesktopMediaPickerDialogView() {}
455
456void DesktopMediaPickerDialogView::DetachParent() {
457  parent_ = NULL;
458}
459
460gfx::Size DesktopMediaPickerDialogView::GetPreferredSize() {
461  return gfx::Size(600, 500);
462}
463
464void DesktopMediaPickerDialogView::Layout() {
465  gfx::Rect rect = GetLocalBounds();
466  rect.Inset(views::kPanelHorizMargin, views::kPanelVertMargin);
467
468  gfx::Rect label_rect(rect.x(), rect.y(), rect.width(),
469                       label_->GetHeightForWidth(rect.width()));
470  label_->SetBoundsRect(label_rect);
471
472  int scroll_view_top = label_rect.bottom() + views::kPanelVerticalSpacing;
473  scroll_view_->SetBounds(
474      rect.x(), scroll_view_top,
475      rect.width(), rect.height() - scroll_view_top);
476}
477
478base::string16 DesktopMediaPickerDialogView::GetWindowTitle() const {
479  return l10n_util::GetStringFUTF16(IDS_DESKTOP_MEDIA_PICKER_TITLE, app_name_);
480}
481
482bool DesktopMediaPickerDialogView::IsDialogButtonEnabled(
483    ui::DialogButton button) const {
484  if (button == ui::DIALOG_BUTTON_OK)
485    return list_view_->GetSelection() != NULL;
486  return true;
487}
488
489bool DesktopMediaPickerDialogView::Accept() {
490  DesktopMediaSourceView* selection = list_view_->GetSelection();
491
492  // Ok button should only be enabled when a source is selected.
493  DCHECK(selection);
494
495  DesktopMediaID source;
496  if (selection)
497    source = selection->source_id();
498
499  if (parent_)
500    parent_->NotifyDialogResult(source);
501
502  // Return true to close the window.
503  return true;
504}
505
506void DesktopMediaPickerDialogView::DeleteDelegate() {
507  // If the dialog is being closed then notify the parent about it.
508  if (parent_)
509    parent_->NotifyDialogResult(DesktopMediaID());
510  delete this;
511}
512
513void DesktopMediaPickerDialogView::OnSelectionChanged() {
514  GetDialogClientView()->UpdateDialogButtons();
515}
516
517DesktopMediaPickerViews::DesktopMediaPickerViews()
518    : dialog_(NULL) {
519}
520
521DesktopMediaPickerViews::~DesktopMediaPickerViews() {
522  if (dialog_) {
523    dialog_->DetachParent();
524    dialog_->GetWidget()->Close();
525  }
526}
527
528void DesktopMediaPickerViews::Show(gfx::NativeWindow context,
529                                   gfx::NativeWindow parent,
530                                   const string16& app_name,
531                                   scoped_ptr<DesktopMediaPickerModel> model,
532                                   const DoneCallback& done_callback) {
533  callback_ = done_callback;
534  dialog_ = new DesktopMediaPickerDialogView(
535      context, parent, this, app_name, model.Pass());
536}
537
538void DesktopMediaPickerViews::NotifyDialogResult(
539    DesktopMediaID source) {
540  // Once this method is called the |dialog_| will close and destroy itself.
541  dialog_->DetachParent();
542  dialog_ = NULL;
543
544  DCHECK(!callback_.is_null());
545
546  // Notify the |callback_| asynchronously because it may need to destroy
547  // DesktopMediaPicker.
548  content::BrowserThread::PostTask(
549      content::BrowserThread::UI, FROM_HERE,
550      base::Bind(callback_, source));
551  callback_.Reset();
552}
553
554}  // namespace
555
556// static
557scoped_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() {
558  return scoped_ptr<DesktopMediaPicker>(new DesktopMediaPickerViews());
559}
560