media_galleries_dialog_views.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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 "chrome/browser/ui/views/extensions/media_galleries_dialog_views.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/browser/ui/views/constrained_window_views.h"
9#include "components/web_modal/web_contents_modal_dialog_manager.h"
10#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
11#include "content/public/browser/web_contents.h"
12#include "content/public/browser/web_contents_view.h"
13#include "grit/generated_resources.h"
14#include "grit/locale_settings.h"
15#include "third_party/skia/include/core/SkColor.h"
16#include "ui/base/l10n/l10n_util.h"
17#include "ui/base/resource/resource_bundle.h"
18#include "ui/native_theme/native_theme.h"
19#include "ui/views/controls/button/checkbox.h"
20#include "ui/views/controls/button/label_button.h"
21#include "ui/views/controls/label.h"
22#include "ui/views/controls/scroll_view.h"
23#include "ui/views/controls/separator.h"
24#include "ui/views/layout/box_layout.h"
25#include "ui/views/layout/grid_layout.h"
26#include "ui/views/layout/layout_constants.h"
27#include "ui/views/view.h"
28#include "ui/views/widget/widget.h"
29#include "ui/views/window/dialog_client_view.h"
30
31using web_modal::WebContentsModalDialogManager;
32
33namespace {
34
35// Equal to the #969696 color used in spec (note WebUI color is #999).
36const SkColor kDeemphasizedTextColor = SkColorSetRGB(159, 159, 159);
37
38const int kScrollAreaHeight = 192;
39
40// This container has the right Layout() impl to use within a ScrollView.
41class ScrollableView : public views::View {
42 public:
43  ScrollableView() {}
44  virtual ~ScrollableView() {}
45
46  virtual void Layout() OVERRIDE;
47
48 private:
49  DISALLOW_COPY_AND_ASSIGN(ScrollableView);
50};
51
52void ScrollableView::Layout() {
53  gfx::Size pref = GetPreferredSize();
54  int width = pref.width();
55  int height = pref.height();
56  if (parent()) {
57    width = std::max(parent()->width(), width);
58    height = std::max(parent()->height(), height);
59  }
60  SetBounds(x(), y(), width, height);
61
62  views::View::Layout();
63}
64
65}  // namespace
66
67namespace chrome {
68
69typedef MediaGalleriesDialogController::GalleryPermissionsVector
70    GalleryPermissionsVector;
71
72MediaGalleriesDialogViews::MediaGalleriesDialogViews(
73    MediaGalleriesDialogController* controller)
74    : controller_(controller),
75      window_(NULL),
76      contents_(new views::View()),
77      add_gallery_button_(NULL),
78      confirm_available_(false),
79      accepted_(false) {
80  InitChildViews();
81
82  // Ownership of |contents_| is handed off by this call. |window_| will take
83  // care of deleting itself after calling DeleteDelegate().
84  WebContentsModalDialogManager* web_contents_modal_dialog_manager =
85      WebContentsModalDialogManager::FromWebContents(
86          controller->web_contents());
87  DCHECK(web_contents_modal_dialog_manager);
88  DCHECK(web_contents_modal_dialog_manager->delegate());
89  window_ = CreateWebContentsModalDialogViews(
90      this,
91      controller->web_contents()->GetView()->GetNativeView(),
92      web_contents_modal_dialog_manager->delegate()->
93          GetWebContentsModalDialogHost());
94  web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView());
95}
96
97MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {}
98
99void MediaGalleriesDialogViews::InitChildViews() {
100  // Outer dialog layout.
101  contents_->RemoveAllChildViews(true);
102  int dialog_content_width = views::Widget::GetLocalizedContentsWidth(
103      IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS);
104  views::GridLayout* layout = views::GridLayout::CreatePanel(contents_);
105  contents_->SetLayoutManager(layout);
106
107  int column_set_id = 0;
108  views::ColumnSet* columns = layout->AddColumnSet(column_set_id);
109  columns->AddColumn(views::GridLayout::LEADING,
110                     views::GridLayout::LEADING,
111                     1,
112                     views::GridLayout::FIXED,
113                     dialog_content_width,
114                     0);
115
116  if (!DialogDelegate::UseNewStyle()) {
117    // Header text.
118    views::Label* header = new views::Label(controller_->GetHeader());
119    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
120    header->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
121    header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
122    layout->StartRow(0, column_set_id);
123    layout->AddView(header);
124  }
125
126  // Message text.
127  views::Label* subtext = new views::Label(controller_->GetSubtext());
128  subtext->SetMultiLine(true);
129  subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT);
130  layout->StartRowWithPadding(0, column_set_id,
131                              0, views::kRelatedControlVerticalSpacing);
132  layout->AddView(subtext);
133
134  // Scrollable area for checkboxes.
135  ScrollableView* scroll_container = new ScrollableView();
136  scroll_container->SetLayoutManager(new views::BoxLayout(
137      views::BoxLayout::kVertical, 0, 0,
138      views::kRelatedControlSmallVerticalSpacing));
139  scroll_container->set_border(views::Border::CreateEmptyBorder(
140      views::kRelatedControlVerticalSpacing,
141      0,
142      views::kRelatedControlVerticalSpacing,
143      0));
144
145  // Add attached galleries checkboxes.
146  checkbox_map_.clear();
147  GalleryPermissionsVector permissions = controller_->AttachedPermissions();
148  for (GalleryPermissionsVector::const_iterator iter = permissions.begin();
149       iter != permissions.end(); ++iter) {
150    AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container);
151  }
152
153  // Separator line.
154  views::View* strut = new views::View;
155  strut->set_border(views::Border::CreateEmptyBorder(
156      views::kRelatedControlVerticalSpacing, 0, 0, 0));
157  scroll_container->AddChildView(strut);
158  views::Separator* separator = new views::Separator(
159      views::Separator::HORIZONTAL);
160  scroll_container->AddChildView(separator);
161
162  // Unattached locations section.
163  views::Label* unattached_text = new views::Label(
164      controller_->GetUnattachedLocationsHeader());
165  unattached_text->SetMultiLine(true);
166  unattached_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
167  unattached_text->set_border(views::Border::CreateEmptyBorder(
168      views::kRelatedControlVerticalSpacing,
169      views::kPanelHorizMargin,
170      views::kRelatedControlVerticalSpacing,
171      0));
172  scroll_container->AddChildView(unattached_text);
173
174  // Add unattached galleries checkboxes.
175  GalleryPermissionsVector unattached_permissions =
176      controller_->UnattachedPermissions();
177  for (GalleryPermissionsVector::const_iterator iter =
178           unattached_permissions.begin();
179       iter != unattached_permissions.end(); ++iter) {
180    AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container);
181  }
182
183  confirm_available_ = controller_->HasPermittedGalleries();
184
185  // Add the scrollable area to the outer dialog view. It will squeeze against
186  // the title/subtitle and buttons to occupy all available space in the dialog.
187  views::ScrollView* scroll_view =
188      views::ScrollView::CreateScrollViewWithBorder();
189  scroll_view->SetContents(scroll_container);
190  layout->StartRowWithPadding(1, column_set_id,
191                              0, views::kRelatedControlVerticalSpacing);
192  layout->AddView(scroll_view, 1, 1,
193                  views::GridLayout::FILL, views::GridLayout::FILL,
194                  dialog_content_width, kScrollAreaHeight);
195
196  // Add location button.
197  add_gallery_button_ = new views::LabelButton(this,
198      l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY));
199  add_gallery_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
200  views::View* add_gallery_container = new views::View();
201  add_gallery_container->SetLayoutManager(
202      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
203  add_gallery_container->set_border(views::Border::CreateEmptyBorder(
204      views::kRelatedControlVerticalSpacing,
205      views::kPanelHorizMargin,
206      views::kRelatedControlVerticalSpacing,
207      0));
208  add_gallery_container->AddChildView(add_gallery_button_);
209  layout->StartRowWithPadding(0, column_set_id,
210                              0, views::kRelatedControlVerticalSpacing);
211  layout->AddView(add_gallery_container, 1, 1,
212                  views::GridLayout::LEADING, views::GridLayout::LEADING);
213}
214
215void MediaGalleriesDialogViews::UpdateGallery(
216    const MediaGalleryPrefInfo& gallery,
217    bool permitted) {
218  InitChildViews();
219  contents_->Layout();
220}
221
222void MediaGalleriesDialogViews::ForgetGallery(MediaGalleryPrefId gallery) {
223  InitChildViews();
224  contents_->Layout();
225}
226
227bool MediaGalleriesDialogViews::AddOrUpdateGallery(
228    const MediaGalleryPrefInfo& gallery,
229    bool permitted,
230    views::View* container) {
231  string16 label =
232      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
233          gallery);
234  string16 tooltip_text =
235      MediaGalleriesDialogController::GetGalleryTooltip(gallery);
236  string16 details =
237      MediaGalleriesDialogController::GetGalleryAdditionalDetails(gallery);
238
239  CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_id);
240  if (iter != checkbox_map_.end()) {
241    views::Checkbox* checkbox = iter->second;
242    checkbox->SetChecked(permitted);
243    checkbox->SetText(label);
244    checkbox->SetTooltipText(tooltip_text);
245    // Replace the details string.
246    views::View* checkbox_view = checkbox->parent();
247    DCHECK_EQ(2, checkbox_view->child_count());
248    views::Label* secondary_text =
249        static_cast<views::Label*>(checkbox_view->child_at(1));
250    secondary_text->SetText(details);
251
252    // Why is this returning false? Looks like that will mean it doesn't paint.
253    return false;
254  }
255
256  views::Checkbox* checkbox = new views::Checkbox(label);
257  checkbox->set_listener(this);
258  checkbox->SetTooltipText(tooltip_text);
259  views::Label* secondary_text = new views::Label(details);
260  secondary_text->SetTooltipText(tooltip_text);
261  secondary_text->SetEnabledColor(kDeemphasizedTextColor);
262  secondary_text->SetTooltipText(tooltip_text);
263  secondary_text->set_border(views::Border::CreateEmptyBorder(
264      0,
265      views::kRelatedControlSmallHorizontalSpacing,
266      0,
267      views::kRelatedControlSmallHorizontalSpacing));
268
269  views::View* checkbox_view = new views::View();
270  checkbox_view->set_border(views::Border::CreateEmptyBorder(
271      0,
272      views::kPanelHorizMargin,
273      0,
274      0));
275  checkbox_view->SetLayoutManager(
276      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
277  checkbox_view->AddChildView(checkbox);
278  checkbox_view->AddChildView(secondary_text);
279
280  container->AddChildView(checkbox_view);
281
282  checkbox->SetChecked(permitted);
283  checkbox_map_[gallery.pref_id] = checkbox;
284
285  return true;
286}
287
288string16 MediaGalleriesDialogViews::GetWindowTitle() const {
289  return controller_->GetHeader();
290}
291
292bool MediaGalleriesDialogViews::ShouldShowWindowTitle() const {
293  return DialogDelegate::UseNewStyle();
294}
295
296void MediaGalleriesDialogViews::DeleteDelegate() {
297  controller_->DialogFinished(accepted_);
298}
299
300views::Widget* MediaGalleriesDialogViews::GetWidget() {
301  return contents_->GetWidget();
302}
303
304const views::Widget* MediaGalleriesDialogViews::GetWidget() const {
305  return contents_->GetWidget();
306}
307
308views::View* MediaGalleriesDialogViews::GetContentsView() {
309  return contents_;
310}
311
312string16 MediaGalleriesDialogViews::GetDialogButtonLabel(
313    ui::DialogButton button) const {
314  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ?
315      IDS_MEDIA_GALLERIES_DIALOG_CONFIRM :
316      IDS_MEDIA_GALLERIES_DIALOG_CANCEL);
317}
318
319bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
320    ui::DialogButton button) const {
321  return button != ui::DIALOG_BUTTON_OK || confirm_available_;
322}
323
324ui::ModalType MediaGalleriesDialogViews::GetModalType() const {
325#if defined(USE_ASH)
326  return ui::MODAL_TYPE_CHILD;
327#else
328  return views::WidgetDelegate::GetModalType();
329#endif
330}
331
332bool MediaGalleriesDialogViews::Cancel() {
333  return true;
334}
335
336bool MediaGalleriesDialogViews::Accept() {
337  accepted_ = true;
338
339  return true;
340}
341
342// TODO(wittman): Remove this override once we move to the new style frame view
343// on all dialogs.
344views::NonClientFrameView* MediaGalleriesDialogViews::CreateNonClientFrameView(
345    views::Widget* widget) {
346  return CreateConstrainedStyleNonClientFrameView(
347      widget,
348      controller_->web_contents()->GetBrowserContext());
349}
350
351void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender,
352                                              const ui::Event& event) {
353  confirm_available_ = true;
354  GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
355
356  if (sender == add_gallery_button_) {
357    controller_->OnAddFolderClicked();
358    return;
359  }
360
361  for (CheckboxMap::const_iterator iter = checkbox_map_.begin();
362       iter != checkbox_map_.end(); ++iter) {
363    if (sender == iter->second) {
364      controller_->DidToggleGalleryId(iter->first,
365                                      iter->second->checked());
366      return;
367    }
368  }
369}
370
371// MediaGalleriesDialogViewsController -----------------------------------------
372
373// static
374MediaGalleriesDialog* MediaGalleriesDialog::Create(
375    MediaGalleriesDialogController* controller) {
376  return new MediaGalleriesDialogViews(controller);
377}
378
379}  // namespace chrome
380