media_galleries_dialog_views.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
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->StartRow(0, column_set_id);
131  layout->AddView(subtext);
132  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
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    int spacing = 0;
151    if (iter + 1 == permissions.end())
152      spacing = views::kRelatedControlSmallVerticalSpacing;
153    AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container,
154                       spacing);
155  }
156
157  // Separator line.
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, 0);
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      0,
206      views::kRelatedControlVerticalSpacing,
207      0));
208  add_gallery_container->AddChildView(add_gallery_button_);
209
210  layout->StartRowWithPadding(0, column_set_id,
211                              0, views::kRelatedControlVerticalSpacing);
212  layout->AddView(add_gallery_container);
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    int trailing_vertical_space) {
232  string16 label =
233      MediaGalleriesDialogController::GetGalleryDisplayNameNoAttachment(
234          gallery);
235  string16 tooltip_text =
236      MediaGalleriesDialogController::GetGalleryTooltip(gallery);
237  string16 details =
238      MediaGalleriesDialogController::GetGalleryAdditionalDetails(gallery);
239
240  CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_id);
241  if (iter != checkbox_map_.end()) {
242    views::Checkbox* checkbox = iter->second;
243    checkbox->SetChecked(permitted);
244    checkbox->SetText(label);
245    checkbox->SetTooltipText(tooltip_text);
246    // Replace the details string.
247    views::View* checkbox_view = checkbox->parent();
248    DCHECK_EQ(2, checkbox_view->child_count());
249    views::Label* secondary_text =
250        static_cast<views::Label*>(checkbox_view->child_at(1));
251    secondary_text->SetText(details);
252
253    // Why is this returning false? Looks like that will mean it doesn't paint.
254    return false;
255  }
256
257  views::Checkbox* checkbox = new views::Checkbox(label);
258  checkbox->set_listener(this);
259  checkbox->SetTooltipText(tooltip_text);
260  views::Label* secondary_text = new views::Label(details);
261  secondary_text->SetTooltipText(tooltip_text);
262  secondary_text->SetEnabledColor(kDeemphasizedTextColor);
263  secondary_text->SetTooltipText(tooltip_text);
264  secondary_text->set_border(views::Border::CreateEmptyBorder(
265      0,
266      views::kRelatedControlSmallHorizontalSpacing,
267      0,
268      views::kRelatedControlSmallHorizontalSpacing));
269
270  views::View* checkbox_view = new views::View();
271  checkbox_view->set_border(views::Border::CreateEmptyBorder(
272      0,
273      views::kPanelHorizMargin,
274      trailing_vertical_space,
275      0));
276  checkbox_view->SetLayoutManager(
277      new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
278  checkbox_view->AddChildView(checkbox);
279  checkbox_view->AddChildView(secondary_text);
280
281  container->AddChildView(checkbox_view);
282
283  checkbox->SetChecked(permitted);
284  checkbox_map_[gallery.pref_id] = checkbox;
285
286  return true;
287}
288
289string16 MediaGalleriesDialogViews::GetWindowTitle() const {
290  return controller_->GetHeader();
291}
292
293bool MediaGalleriesDialogViews::ShouldShowWindowTitle() const {
294  return DialogDelegate::UseNewStyle();
295}
296
297void MediaGalleriesDialogViews::DeleteDelegate() {
298  controller_->DialogFinished(accepted_);
299}
300
301views::Widget* MediaGalleriesDialogViews::GetWidget() {
302  return contents_->GetWidget();
303}
304
305const views::Widget* MediaGalleriesDialogViews::GetWidget() const {
306  return contents_->GetWidget();
307}
308
309views::View* MediaGalleriesDialogViews::GetContentsView() {
310  return contents_;
311}
312
313string16 MediaGalleriesDialogViews::GetDialogButtonLabel(
314    ui::DialogButton button) const {
315  return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ?
316      IDS_MEDIA_GALLERIES_DIALOG_CONFIRM :
317      IDS_MEDIA_GALLERIES_DIALOG_CANCEL);
318}
319
320bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
321    ui::DialogButton button) const {
322  return button != ui::DIALOG_BUTTON_OK || confirm_available_;
323}
324
325ui::ModalType MediaGalleriesDialogViews::GetModalType() const {
326#if defined(USE_ASH)
327  return ui::MODAL_TYPE_CHILD;
328#else
329  return views::WidgetDelegate::GetModalType();
330#endif
331}
332
333bool MediaGalleriesDialogViews::Cancel() {
334  return true;
335}
336
337bool MediaGalleriesDialogViews::Accept() {
338  accepted_ = true;
339
340  return true;
341}
342
343// TODO(wittman): Remove this override once we move to the new style frame view
344// on all dialogs.
345views::NonClientFrameView* MediaGalleriesDialogViews::CreateNonClientFrameView(
346    views::Widget* widget) {
347  return CreateConstrainedStyleNonClientFrameView(
348      widget,
349      controller_->web_contents()->GetBrowserContext());
350}
351
352void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender,
353                                              const ui::Event& event) {
354  confirm_available_ = true;
355  GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
356
357  if (sender == add_gallery_button_) {
358    controller_->OnAddFolderClicked();
359    return;
360  }
361
362  for (CheckboxMap::const_iterator iter = checkbox_map_.begin();
363       iter != checkbox_map_.end(); ++iter) {
364    if (sender == iter->second) {
365      controller_->DidToggleGalleryId(iter->first,
366                                      iter->second->checked());
367      return;
368    }
369  }
370}
371
372// MediaGalleriesDialogViewsController -----------------------------------------
373
374// static
375MediaGalleriesDialog* MediaGalleriesDialog::Create(
376    MediaGalleriesDialogController* controller) {
377  return new MediaGalleriesDialogViews(controller);
378}
379
380}  // namespace chrome
381