88ca64c44329c9b383f77bed2c1ed8034aa68a4e
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / extensions / media_galleries_dialog_views.cc
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/extensions/media_gallery_checkbox_view.h"
9 #include "chrome/grit/generated_resources.h"
10 #include "chrome/grit/locale_settings.h"
11 #include "components/constrained_window/constrained_window_views.h"
12 #include "components/web_modal/popup_manager.h"
13 #include "content/public/browser/web_contents.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/native_theme/native_theme.h"
16 #include "ui/views/border.h"
17 #include "ui/views/controls/button/checkbox.h"
18 #include "ui/views/controls/button/image_button.h"
19 #include "ui/views/controls/button/label_button.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/controls/menu/menu_runner.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
31 namespace {
32
33 const int kScrollAreaHeight = 192;
34
35 // This container has the right Layout() impl to use within a ScrollView.
36 class ScrollableView : public views::View {
37  public:
38   ScrollableView() {}
39   ~ScrollableView() override {}
40
41   void Layout() override;
42
43  private:
44   DISALLOW_COPY_AND_ASSIGN(ScrollableView);
45 };
46
47 void ScrollableView::Layout() {
48   gfx::Size pref = GetPreferredSize();
49   int width = pref.width();
50   int height = pref.height();
51   if (parent()) {
52     width = parent()->width();
53     height = std::max(parent()->height(), height);
54   }
55   SetBounds(x(), y(), width, height);
56
57   views::View::Layout();
58 }
59
60 }  // namespace
61
62 MediaGalleriesDialogViews::MediaGalleriesDialogViews(
63     MediaGalleriesDialogController* controller)
64     : controller_(controller),
65       contents_(new views::View()),
66       auxiliary_button_(NULL),
67       confirm_available_(false),
68       accepted_(false) {
69   InitChildViews();
70   if (ControllerHasWebContents())
71     ShowWebModalDialogViews(this, controller->WebContents());
72 }
73
74 MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {
75   if (!ControllerHasWebContents())
76     delete contents_;
77 }
78
79 void MediaGalleriesDialogViews::AcceptDialogForTesting() {
80   accepted_ = true;
81
82   web_modal::PopupManager* popup_manager =
83       web_modal::PopupManager::FromWebContents(controller_->WebContents());
84   DCHECK(popup_manager);
85   popup_manager->CloseAllDialogsForTesting(controller_->WebContents());
86 }
87
88 void MediaGalleriesDialogViews::InitChildViews() {
89   // Outer dialog layout.
90   contents_->RemoveAllChildViews(true);
91   checkbox_map_.clear();
92
93   int dialog_content_width = views::Widget::GetLocalizedContentsWidth(
94       IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS);
95   views::GridLayout* layout = views::GridLayout::CreatePanel(contents_);
96   contents_->SetLayoutManager(layout);
97
98   int column_set_id = 0;
99   views::ColumnSet* columns = layout->AddColumnSet(column_set_id);
100   columns->AddColumn(views::GridLayout::LEADING,
101                      views::GridLayout::LEADING,
102                      1,
103                      views::GridLayout::FIXED,
104                      dialog_content_width,
105                      0);
106
107   // Message text.
108   views::Label* subtext = new views::Label(controller_->GetSubtext());
109   subtext->SetMultiLine(true);
110   subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT);
111   layout->StartRow(0, column_set_id);
112   layout->AddView(
113       subtext, 1, 1,
114       views::GridLayout::FILL, views::GridLayout::LEADING,
115       dialog_content_width, subtext->GetHeightForWidth(dialog_content_width));
116   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
117
118   // Scrollable area for checkboxes.
119   ScrollableView* scroll_container = new ScrollableView();
120   scroll_container->SetLayoutManager(new views::BoxLayout(
121       views::BoxLayout::kVertical, 0, 0,
122       views::kRelatedControlSmallVerticalSpacing));
123   scroll_container->SetBorder(
124       views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing,
125                                        0,
126                                        views::kRelatedControlVerticalSpacing,
127                                        0));
128
129   std::vector<base::string16> section_headers =
130       controller_->GetSectionHeaders();
131   for (size_t i = 0; i < section_headers.size(); i++) {
132     MediaGalleriesDialogController::Entries entries =
133         controller_->GetSectionEntries(i);
134
135     // Header and separator line.
136     if (!section_headers[i].empty() && !entries.empty()) {
137       views::Separator* separator = new views::Separator(
138           views::Separator::HORIZONTAL);
139       scroll_container->AddChildView(separator);
140
141       views::Label* header = new views::Label(section_headers[i]);
142       header->SetMultiLine(true);
143       header->SetHorizontalAlignment(gfx::ALIGN_LEFT);
144       header->SetBorder(views::Border::CreateEmptyBorder(
145           views::kRelatedControlVerticalSpacing,
146           views::kPanelHorizMargin,
147           views::kRelatedControlVerticalSpacing,
148           0));
149       scroll_container->AddChildView(header);
150     }
151
152     // Checkboxes.
153     MediaGalleriesDialogController::Entries::const_iterator iter;
154     for (iter = entries.begin(); iter != entries.end(); ++iter) {
155       int spacing = 0;
156       if (iter + 1 == entries.end())
157         spacing = views::kRelatedControlSmallVerticalSpacing;
158       AddOrUpdateGallery(*iter, scroll_container, spacing);
159     }
160   }
161
162   confirm_available_ = controller_->IsAcceptAllowed();
163
164   // Add the scrollable area to the outer dialog view. It will squeeze against
165   // the title/subtitle and buttons to occupy all available space in the dialog.
166   views::ScrollView* scroll_view =
167       views::ScrollView::CreateScrollViewWithBorder();
168   scroll_view->SetContents(scroll_container);
169   layout->StartRowWithPadding(1, column_set_id,
170                               0, views::kRelatedControlVerticalSpacing);
171   layout->AddView(scroll_view, 1, 1,
172                   views::GridLayout::FILL, views::GridLayout::FILL,
173                   dialog_content_width, kScrollAreaHeight);
174 }
175
176 void MediaGalleriesDialogViews::UpdateGalleries() {
177   InitChildViews();
178   contents_->Layout();
179
180   if (ControllerHasWebContents())
181     GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
182 }
183
184 bool MediaGalleriesDialogViews::AddOrUpdateGallery(
185     const MediaGalleriesDialogController::Entry& gallery,
186     views::View* container,
187     int trailing_vertical_space) {
188   bool show_folder_viewer = controller_->ShouldShowFolderViewer(gallery);
189
190   CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_info.pref_id);
191   if (iter != checkbox_map_.end()) {
192     views::Checkbox* checkbox = iter->second->checkbox();
193     checkbox->SetChecked(gallery.selected);
194     checkbox->SetText(gallery.pref_info.GetGalleryDisplayName());
195     checkbox->SetTooltipText(gallery.pref_info.GetGalleryTooltip());
196     base::string16 details = gallery.pref_info.GetGalleryAdditionalDetails();
197     iter->second->secondary_text()->SetText(details);
198     iter->second->secondary_text()->SetVisible(details.length() > 0);
199     iter->second->folder_viewer_button()->SetVisible(show_folder_viewer);
200     return false;
201   }
202
203   MediaGalleryCheckboxView* gallery_view =
204       new MediaGalleryCheckboxView(gallery.pref_info, show_folder_viewer,
205                                    trailing_vertical_space, this, this);
206   gallery_view->checkbox()->SetChecked(gallery.selected);
207   container->AddChildView(gallery_view);
208   checkbox_map_[gallery.pref_info.pref_id] = gallery_view;
209
210   return true;
211 }
212
213 base::string16 MediaGalleriesDialogViews::GetWindowTitle() const {
214   return controller_->GetHeader();
215 }
216
217 void MediaGalleriesDialogViews::DeleteDelegate() {
218   controller_->DialogFinished(accepted_);
219 }
220
221 views::Widget* MediaGalleriesDialogViews::GetWidget() {
222   return contents_->GetWidget();
223 }
224
225 const views::Widget* MediaGalleriesDialogViews::GetWidget() const {
226   return contents_->GetWidget();
227 }
228
229 views::View* MediaGalleriesDialogViews::GetContentsView() {
230   return contents_;
231 }
232
233 base::string16 MediaGalleriesDialogViews::GetDialogButtonLabel(
234     ui::DialogButton button) const {
235   if (button == ui::DIALOG_BUTTON_OK)
236     return controller_->GetAcceptButtonText();
237   return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_CANCEL);
238 }
239
240 bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
241     ui::DialogButton button) const {
242   return button != ui::DIALOG_BUTTON_OK || confirm_available_;
243 }
244
245 ui::ModalType MediaGalleriesDialogViews::GetModalType() const {
246   return ui::MODAL_TYPE_CHILD;
247 }
248
249 views::View* MediaGalleriesDialogViews::CreateExtraView() {
250   DCHECK(!auxiliary_button_);
251   base::string16 button_label = controller_->GetAuxiliaryButtonText();
252   if (!button_label.empty()) {
253     auxiliary_button_ = new views::LabelButton(this, button_label);
254     auxiliary_button_->SetStyle(views::Button::STYLE_BUTTON);
255   }
256   return auxiliary_button_;
257 }
258
259 bool MediaGalleriesDialogViews::Cancel() {
260   return true;
261 }
262
263 bool MediaGalleriesDialogViews::Accept() {
264   accepted_ = true;
265   return true;
266 }
267
268 void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender,
269                                               const ui::Event& /* event */) {
270   confirm_available_ = true;
271
272   if (ControllerHasWebContents())
273     GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
274
275   if (sender == auxiliary_button_) {
276     controller_->DidClickAuxiliaryButton();
277     return;
278   }
279
280   for (CheckboxMap::const_iterator iter = checkbox_map_.begin();
281        iter != checkbox_map_.end(); ++iter) {
282     if (sender == iter->second->checkbox()) {
283       controller_->DidToggleEntry(iter->first,
284                                   iter->second->checkbox()->checked());
285       return;
286     }
287     if (sender == iter->second->folder_viewer_button()) {
288       controller_->DidClickOpenFolderViewer(iter->first);
289       return;
290     }
291   }
292 }
293
294 void MediaGalleriesDialogViews::ShowContextMenuForView(
295     views::View* source,
296     const gfx::Point& point,
297     ui::MenuSourceType source_type) {
298   for (CheckboxMap::const_iterator iter = checkbox_map_.begin();
299        iter != checkbox_map_.end(); ++iter) {
300     if (iter->second->Contains(source)) {
301       ShowContextMenu(point, source_type, iter->first);
302       return;
303     }
304   }
305 }
306
307 void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point& point,
308                                                 ui::MenuSourceType source_type,
309                                                 MediaGalleryPrefId id) {
310   context_menu_runner_.reset(new views::MenuRunner(
311       controller_->GetContextMenu(id),
312       views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU));
313
314   if (context_menu_runner_->RunMenuAt(GetWidget(),
315                                       NULL,
316                                       gfx::Rect(point.x(), point.y(), 0, 0),
317                                       views::MENU_ANCHOR_TOPLEFT,
318                                       source_type) ==
319       views::MenuRunner::MENU_DELETED) {
320     return;
321   }
322 }
323
324 bool MediaGalleriesDialogViews::ControllerHasWebContents() const {
325   return controller_->WebContents() != NULL;
326 }
327
328 // MediaGalleriesDialogViewsController -----------------------------------------
329
330 // static
331 MediaGalleriesDialog* MediaGalleriesDialog::Create(
332     MediaGalleriesDialogController* controller) {
333   return new MediaGalleriesDialogViews(controller);
334 }