Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / extensions / media_galleries_scan_result_dialog_views.cc
1 // Copyright 2014 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_scan_result_dialog_views.h"
6
7 #include "components/web_modal/web_contents_modal_dialog_host.h"
8 #include "components/web_modal/web_contents_modal_dialog_manager.h"
9 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
10 #include "content/public/browser/web_contents.h"
11 #include "grit/generated_resources.h"
12 #include "grit/locale_settings.h"
13 #include "grit/theme_resources.h"
14 #include "grit/ui_resources.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/views/border.h"
19 #include "ui/views/controls/button/checkbox.h"
20 #include "ui/views/controls/button/image_button.h"
21 #include "ui/views/controls/label.h"
22 #include "ui/views/controls/menu/menu_runner.h"
23 #include "ui/views/controls/scroll_view.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 typedef MediaGalleriesScanResultDialogController::OrderedScanResults
32     OrderedScanResults;
33
34 namespace {
35
36 // TODO(vandebo) move this to a common place.
37 // Equal to the #969696 color used in spec (note WebUI color is #999).
38 const SkColor kDeemphasizedTextColor = SkColorSetRGB(159, 159, 159);
39
40 const int kScrollAreaHeight = 192;
41
42 // This container has the right Layout() impl to use within a ScrollView.
43 class ScrollableView : public views::View {
44  public:
45   ScrollableView() {}
46   virtual ~ScrollableView() {}
47
48   virtual void Layout() OVERRIDE;
49
50  private:
51   DISALLOW_COPY_AND_ASSIGN(ScrollableView);
52 };
53
54 void ScrollableView::Layout() {
55   gfx::Size pref = GetPreferredSize();
56   int width = pref.width();
57   int height = pref.height();
58   if (parent()) {
59     width = std::max(parent()->width(), width);
60     height = std::max(parent()->height(), height);
61   }
62   SetBounds(x(), y(), width, height);
63
64   views::View::Layout();
65 }
66
67 }  // namespace
68
69 MediaGalleriesScanResultDialogViews::MediaGalleriesScanResultDialogViews(
70     MediaGalleriesScanResultDialogController* controller)
71     : controller_(controller),
72       window_(NULL),
73       contents_(new views::View()),
74       accepted_(false) {
75   InitChildViews();
76
77   // Ownership of |contents_| is handed off by this call. |window_| will take
78   // care of deleting itself after calling DeleteDelegate().
79   web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager =
80       web_modal::WebContentsModalDialogManager::FromWebContents(
81           controller->web_contents());
82   DCHECK(web_contents_modal_dialog_manager);
83   web_modal::WebContentsModalDialogManagerDelegate* modal_delegate =
84       web_contents_modal_dialog_manager->delegate();
85   DCHECK(modal_delegate);
86   window_ = views::Widget::CreateWindowAsFramelessChild(
87       this, modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
88   web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView());
89 }
90
91 MediaGalleriesScanResultDialogViews::~MediaGalleriesScanResultDialogViews() {}
92
93 void MediaGalleriesScanResultDialogViews::InitChildViews() {
94   // Outer dialog layout.
95   contents_->RemoveAllChildViews(true);
96   int dialog_content_width = views::Widget::GetLocalizedContentsWidth(
97       IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS);
98   views::GridLayout* layout = views::GridLayout::CreatePanel(contents_);
99   contents_->SetLayoutManager(layout);
100
101   int column_set_id = 0;
102   views::ColumnSet* columns = layout->AddColumnSet(column_set_id);
103   columns->AddColumn(views::GridLayout::LEADING,
104                      views::GridLayout::LEADING,
105                      1,
106                      views::GridLayout::FIXED,
107                      dialog_content_width,
108                      0);
109
110   // Message text.
111   views::Label* subtext = new views::Label(controller_->GetSubtext());
112   subtext->SetMultiLine(true);
113   subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT);
114   layout->StartRow(0, column_set_id);
115   layout->AddView(
116       subtext, 1, 1,
117       views::GridLayout::FILL, views::GridLayout::LEADING,
118       dialog_content_width, subtext->GetHeightForWidth(dialog_content_width));
119   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
120
121   // Scrollable area for checkboxes.
122   ScrollableView* scroll_container = new ScrollableView();
123   scroll_container->SetLayoutManager(new views::BoxLayout(
124       views::BoxLayout::kVertical, 0, 0,
125       views::kRelatedControlSmallVerticalSpacing));
126   scroll_container->SetBorder(views::Border::CreateEmptyBorder(
127       views::kRelatedControlVerticalSpacing,
128       0,
129       views::kRelatedControlVerticalSpacing,
130       0));
131
132   // Add attached galleries checkboxes.
133   gallery_view_map_.clear();
134   OrderedScanResults scan_results = controller_->GetGalleryList();
135   for (OrderedScanResults::const_iterator it = scan_results.begin();
136        it != scan_results.end();
137        ++it) {
138     int spacing = 0;
139     if (it + 1 == scan_results.end())
140       spacing = views::kRelatedControlSmallVerticalSpacing;
141     AddOrUpdateScanResult(it->pref_info, it->selected, scroll_container,
142                           spacing);
143   }
144
145   // Add the scrollable area to the outer dialog view. It will squeeze against
146   // the title/subtitle and buttons to occupy all available space in the dialog.
147   views::ScrollView* scroll_view =
148       views::ScrollView::CreateScrollViewWithBorder();
149   scroll_view->SetContents(scroll_container);
150   layout->StartRowWithPadding(1, column_set_id,
151                               0, views::kRelatedControlVerticalSpacing);
152   layout->AddView(scroll_view, 1, 1,
153                   views::GridLayout::FILL, views::GridLayout::FILL,
154                   dialog_content_width, kScrollAreaHeight);
155 }
156
157 void MediaGalleriesScanResultDialogViews::UpdateResults() {
158   InitChildViews();
159   contents_->Layout();
160 }
161
162 bool MediaGalleriesScanResultDialogViews::AddOrUpdateScanResult(
163     const MediaGalleryPrefInfo& gallery,
164     bool selected,
165     views::View* container,
166     int trailing_vertical_space) {
167   base::string16 label = gallery.GetGalleryDisplayName();
168   base::string16 tooltip_text = gallery.GetGalleryTooltip();
169   base::string16 details = gallery.GetGalleryAdditionalDetails();
170   bool is_attached = gallery.IsGalleryAvailable();
171
172   GalleryViewMap::iterator it = gallery_view_map_.find(gallery.pref_id);
173   if (it != gallery_view_map_.end()) {
174     views::Checkbox* checkbox = it->second.checkbox;
175     checkbox->SetChecked(selected);
176     checkbox->SetText(label);
177     checkbox->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
178     checkbox->SetTooltipText(tooltip_text);
179     // Replace the details string.
180     it->second.folder_viewer_button->SetVisible(is_attached);
181     it->second.secondary_text->SetText(details);
182     return false;
183   }
184
185   views::Checkbox* checkbox = new views::Checkbox(label);
186   checkbox->set_listener(this);
187   checkbox->set_context_menu_controller(this);
188   checkbox->SetTooltipText(tooltip_text);
189
190   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
191   views::ImageButton* folder_viewer_button = new views::ImageButton(this);
192   folder_viewer_button->set_context_menu_controller(this);
193   folder_viewer_button->SetImage(views::ImageButton::STATE_NORMAL,
194                                  rb.GetImageSkiaNamed(IDR_FILE_FOLDER));
195   folder_viewer_button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
196                                           views::ImageButton::ALIGN_MIDDLE);
197   folder_viewer_button->SetAccessibleName(l10n_util::GetStringUTF16(
198       IDS_MEDIA_GALLERIES_SCAN_RESULT_OPEN_FOLDER_VIEW_ACCESSIBILITY_NAME));
199   folder_viewer_button->SetFocusable(true);
200   folder_viewer_button->SetVisible(is_attached);
201
202   views::Label* secondary_text = new views::Label(details);
203   secondary_text->set_context_menu_controller(this);
204   secondary_text->SetTooltipText(tooltip_text);
205   secondary_text->SetEnabledColor(kDeemphasizedTextColor);
206   secondary_text->SetTooltipText(tooltip_text);
207   secondary_text->SetBorder(views::Border::CreateEmptyBorder(
208       0,
209       views::kRelatedControlSmallHorizontalSpacing,
210       0,
211       views::kRelatedControlSmallHorizontalSpacing));
212
213   views::View* checkbox_view = new views::View();
214   checkbox_view->SetBorder(views::Border::CreateEmptyBorder(
215       0, views::kPanelHorizMargin, trailing_vertical_space, 0));
216   checkbox_view->set_context_menu_controller(this);
217   checkbox_view->SetLayoutManager(
218       new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
219   checkbox_view->AddChildView(checkbox);
220   checkbox_view->AddChildView(folder_viewer_button);
221   checkbox_view->AddChildView(secondary_text);
222
223   container->AddChildView(checkbox_view);
224
225   checkbox->SetChecked(selected);
226   gallery_view_map_[gallery.pref_id].checkbox = checkbox;
227   gallery_view_map_[gallery.pref_id].folder_viewer_button =
228       folder_viewer_button;
229   gallery_view_map_[gallery.pref_id].secondary_text = secondary_text;
230
231   return true;
232 }
233
234 base::string16 MediaGalleriesScanResultDialogViews::GetWindowTitle() const {
235   return controller_->GetHeader();
236 }
237
238 void MediaGalleriesScanResultDialogViews::DeleteDelegate() {
239   controller_->DialogFinished(accepted_);
240 }
241
242 views::Widget* MediaGalleriesScanResultDialogViews::GetWidget() {
243   return contents_->GetWidget();
244 }
245
246 const views::Widget* MediaGalleriesScanResultDialogViews::GetWidget() const {
247   return contents_->GetWidget();
248 }
249
250 views::View* MediaGalleriesScanResultDialogViews::GetContentsView() {
251   return contents_;
252 }
253
254 base::string16 MediaGalleriesScanResultDialogViews::GetDialogButtonLabel(
255     ui::DialogButton button) const {
256   return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ?
257       IDS_MEDIA_GALLERIES_DIALOG_CONFIRM :
258       IDS_MEDIA_GALLERIES_DIALOG_CANCEL);
259 }
260
261 ui::ModalType MediaGalleriesScanResultDialogViews::GetModalType() const {
262 #if defined(USE_ASH)
263   return ui::MODAL_TYPE_CHILD;
264 #else
265   return views::WidgetDelegate::GetModalType();
266 #endif
267 }
268
269 bool MediaGalleriesScanResultDialogViews::Cancel() {
270   return true;
271 }
272
273 bool MediaGalleriesScanResultDialogViews::Accept() {
274   accepted_ = true;
275
276   return true;
277 }
278
279 void MediaGalleriesScanResultDialogViews::ButtonPressed(
280     views::Button* sender,
281     const ui::Event& event) {
282   GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
283
284   for (GalleryViewMap::const_iterator it = gallery_view_map_.begin();
285        it != gallery_view_map_.end(); ++it) {
286     if (sender == it->second.checkbox) {
287       controller_->DidToggleGalleryId(it->first,
288                                       it->second.checkbox->checked());
289       return;
290     }
291     if (sender == it->second.folder_viewer_button) {
292       controller_->DidClickOpenFolderViewer(it->first);
293       return;
294     }
295   }
296 }
297
298 void MediaGalleriesScanResultDialogViews::ShowContextMenuForView(
299     views::View* source,
300     const gfx::Point& point,
301     ui::MenuSourceType source_type) {
302   for (GalleryViewMap::const_iterator it = gallery_view_map_.begin();
303        it != gallery_view_map_.end(); ++it) {
304     if (it->second.checkbox->parent()->Contains(source)) {
305       ShowContextMenu(point, source_type, it->first);
306       return;
307     }
308   }
309   NOTREACHED();
310 }
311
312 void MediaGalleriesScanResultDialogViews::ShowContextMenu(
313     const gfx::Point& point,
314     ui::MenuSourceType source_type,
315     MediaGalleryPrefId id) {
316   context_menu_runner_.reset(new views::MenuRunner(
317       controller_->GetContextMenu(id)));
318
319   if (context_menu_runner_->RunMenuAt(
320           GetWidget(), NULL, gfx::Rect(point.x(), point.y(), 0, 0),
321           views::MenuItemView::TOPLEFT, source_type,
322           views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
323       views::MenuRunner::MENU_DELETED) {
324     return;
325   }
326 }
327
328 // MediaGalleriesScanResultDialogViewsController -------------------------------
329
330 // static
331 MediaGalleriesScanResultDialog* MediaGalleriesScanResultDialog::Create(
332     MediaGalleriesScanResultDialogController* controller) {
333   return new MediaGalleriesScanResultDialogViews(controller);
334 }