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.
5 #include "chrome/browser/ui/views/extensions/media_galleries_dialog_views.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/ui/views/extensions/media_gallery_checkbox_view.h"
9 #include "components/web_modal/web_contents_modal_dialog_host.h"
10 #include "components/web_modal/web_contents_modal_dialog_manager.h"
11 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
12 #include "content/public/browser/web_contents.h"
13 #include "grit/generated_resources.h"
14 #include "grit/locale_settings.h"
15 #include "ui/base/l10n/l10n_util.h"
16 #include "ui/native_theme/native_theme.h"
17 #include "ui/views/border.h"
18 #include "ui/views/controls/button/checkbox.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"
31 using web_modal::WebContentsModalDialogManager
;
32 using web_modal::WebContentsModalDialogManagerDelegate
;
36 const int kScrollAreaHeight
= 192;
38 // This container has the right Layout() impl to use within a ScrollView.
39 class ScrollableView
: public views::View
{
42 virtual ~ScrollableView() {}
44 virtual void Layout() OVERRIDE
;
47 DISALLOW_COPY_AND_ASSIGN(ScrollableView
);
50 void ScrollableView::Layout() {
51 gfx::Size pref
= GetPreferredSize();
52 int width
= pref
.width();
53 int height
= pref
.height();
55 width
= parent()->width();
56 height
= std::max(parent()->height(), height
);
58 SetBounds(x(), y(), width
, height
);
60 views::View::Layout();
65 typedef MediaGalleriesDialogController::GalleryPermissionsVector
66 GalleryPermissionsVector
;
68 MediaGalleriesDialogViews::MediaGalleriesDialogViews(
69 MediaGalleriesDialogController
* controller
)
70 : controller_(controller
),
72 contents_(new views::View()),
73 add_gallery_button_(NULL
),
74 confirm_available_(false),
78 if (ControllerHasWebContents()) {
79 // Ownership of |contents_| is handed off by this call. |window_| will take
80 // care of deleting itself after calling DeleteDelegate().
81 WebContentsModalDialogManager
* web_contents_modal_dialog_manager
=
82 WebContentsModalDialogManager::FromWebContents(
83 controller
->web_contents());
84 DCHECK(web_contents_modal_dialog_manager
);
85 WebContentsModalDialogManagerDelegate
* modal_delegate
=
86 web_contents_modal_dialog_manager
->delegate();
87 DCHECK(modal_delegate
);
88 window_
= views::Widget::CreateWindowAsFramelessChild(
89 this, modal_delegate
->GetWebContentsModalDialogHost()->GetHostView());
90 web_contents_modal_dialog_manager
->ShowModalDialog(
91 window_
->GetNativeView());
95 MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {
96 if (!ControllerHasWebContents())
100 void MediaGalleriesDialogViews::InitChildViews() {
101 // Outer dialog layout.
102 contents_
->RemoveAllChildViews(true);
103 int dialog_content_width
= views::Widget::GetLocalizedContentsWidth(
104 IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS
);
105 views::GridLayout
* layout
= views::GridLayout::CreatePanel(contents_
);
106 contents_
->SetLayoutManager(layout
);
108 int column_set_id
= 0;
109 views::ColumnSet
* columns
= layout
->AddColumnSet(column_set_id
);
110 columns
->AddColumn(views::GridLayout::LEADING
,
111 views::GridLayout::LEADING
,
113 views::GridLayout::FIXED
,
114 dialog_content_width
,
118 views::Label
* subtext
= new views::Label(controller_
->GetSubtext());
119 subtext
->SetMultiLine(true);
120 subtext
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
121 layout
->StartRow(0, column_set_id
);
124 views::GridLayout::FILL
, views::GridLayout::LEADING
,
125 dialog_content_width
, subtext
->GetHeightForWidth(dialog_content_width
));
126 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
128 // Scrollable area for checkboxes.
129 ScrollableView
* scroll_container
= new ScrollableView();
130 scroll_container
->SetLayoutManager(new views::BoxLayout(
131 views::BoxLayout::kVertical
, 0, 0,
132 views::kRelatedControlSmallVerticalSpacing
));
133 scroll_container
->SetBorder(
134 views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing
,
136 views::kRelatedControlVerticalSpacing
,
139 // Add attached galleries checkboxes.
140 checkbox_map_
.clear();
141 GalleryPermissionsVector permissions
= controller_
->AttachedPermissions();
142 for (GalleryPermissionsVector::const_iterator iter
= permissions
.begin();
143 iter
!= permissions
.end(); ++iter
) {
145 if (iter
+ 1 == permissions
.end())
146 spacing
= views::kRelatedControlSmallVerticalSpacing
;
147 AddOrUpdateGallery(*iter
, scroll_container
, spacing
);
150 GalleryPermissionsVector unattached_permissions
=
151 controller_
->UnattachedPermissions();
153 if (!unattached_permissions
.empty()) {
155 views::Separator
* separator
= new views::Separator(
156 views::Separator::HORIZONTAL
);
157 scroll_container
->AddChildView(separator
);
159 // Unattached locations section.
160 views::Label
* unattached_text
= new views::Label(
161 controller_
->GetUnattachedLocationsHeader());
162 unattached_text
->SetMultiLine(true);
163 unattached_text
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
164 unattached_text
->SetBorder(
165 views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing
,
166 views::kPanelHorizMargin
,
167 views::kRelatedControlVerticalSpacing
,
169 scroll_container
->AddChildView(unattached_text
);
171 // Add unattached galleries checkboxes.
172 for (GalleryPermissionsVector::const_iterator iter
=
173 unattached_permissions
.begin();
174 iter
!= unattached_permissions
.end(); ++iter
) {
175 AddOrUpdateGallery(*iter
, scroll_container
, 0);
179 confirm_available_
= controller_
->IsAcceptAllowed();
181 // Add the scrollable area to the outer dialog view. It will squeeze against
182 // the title/subtitle and buttons to occupy all available space in the dialog.
183 views::ScrollView
* scroll_view
=
184 views::ScrollView::CreateScrollViewWithBorder();
185 scroll_view
->SetContents(scroll_container
);
186 layout
->StartRowWithPadding(1, column_set_id
,
187 0, views::kRelatedControlVerticalSpacing
);
188 layout
->AddView(scroll_view
, 1, 1,
189 views::GridLayout::FILL
, views::GridLayout::FILL
,
190 dialog_content_width
, kScrollAreaHeight
);
193 void MediaGalleriesDialogViews::UpdateGalleries() {
198 bool MediaGalleriesDialogViews::AddOrUpdateGallery(
199 const MediaGalleriesDialogController::GalleryPermission
& gallery
,
200 views::View
* container
,
201 int trailing_vertical_space
) {
202 base::string16 label
= gallery
.pref_info
.GetGalleryDisplayName();
203 base::string16 tooltip_text
= gallery
.pref_info
.GetGalleryTooltip();
204 base::string16 details
= gallery
.pref_info
.GetGalleryAdditionalDetails();
206 CheckboxMap::iterator iter
= checkbox_map_
.find(gallery
.gallery_id
);
207 if (iter
!= checkbox_map_
.end()) {
208 views::Checkbox
* checkbox
= iter
->second
->checkbox();
209 checkbox
->SetChecked(gallery
.allowed
);
210 checkbox
->SetText(label
);
211 checkbox
->SetTooltipText(tooltip_text
);
212 iter
->second
->secondary_text()->SetText(details
);
213 iter
->second
->secondary_text()->SetVisible(details
.length() > 0);
217 MediaGalleryCheckboxView
* gallery_view
=
218 new MediaGalleryCheckboxView(label
, tooltip_text
, details
, false,
219 trailing_vertical_space
, this, this);
220 gallery_view
->checkbox()->SetChecked(gallery
.allowed
);
221 container
->AddChildView(gallery_view
);
222 checkbox_map_
[gallery
.gallery_id
] = gallery_view
;
227 base::string16
MediaGalleriesDialogViews::GetWindowTitle() const {
228 return controller_
->GetHeader();
231 void MediaGalleriesDialogViews::DeleteDelegate() {
232 controller_
->DialogFinished(accepted_
);
235 views::Widget
* MediaGalleriesDialogViews::GetWidget() {
236 return contents_
->GetWidget();
239 const views::Widget
* MediaGalleriesDialogViews::GetWidget() const {
240 return contents_
->GetWidget();
243 views::View
* MediaGalleriesDialogViews::GetContentsView() {
247 base::string16
MediaGalleriesDialogViews::GetDialogButtonLabel(
248 ui::DialogButton button
) const {
249 return l10n_util::GetStringUTF16(button
== ui::DIALOG_BUTTON_OK
?
250 IDS_MEDIA_GALLERIES_DIALOG_CONFIRM
:
251 IDS_MEDIA_GALLERIES_DIALOG_CANCEL
);
254 bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
255 ui::DialogButton button
) const {
256 return button
!= ui::DIALOG_BUTTON_OK
|| confirm_available_
;
259 ui::ModalType
MediaGalleriesDialogViews::GetModalType() const {
261 return ui::MODAL_TYPE_CHILD
;
263 return views::WidgetDelegate::GetModalType();
267 views::View
* MediaGalleriesDialogViews::CreateExtraView() {
268 DCHECK(!add_gallery_button_
);
269 add_gallery_button_
= new views::LabelButton(this,
270 l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY
));
271 add_gallery_button_
->SetStyle(views::Button::STYLE_BUTTON
);
272 return add_gallery_button_
;
275 bool MediaGalleriesDialogViews::Cancel() {
279 bool MediaGalleriesDialogViews::Accept() {
285 void MediaGalleriesDialogViews::ButtonPressed(views::Button
* sender
,
286 const ui::Event
& /* event */) {
287 confirm_available_
= true;
289 if (ControllerHasWebContents())
290 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
292 if (sender
== add_gallery_button_
) {
293 controller_
->OnAddFolderClicked();
297 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
298 iter
!= checkbox_map_
.end(); ++iter
) {
299 if (sender
== iter
->second
->checkbox()) {
300 controller_
->DidToggleGallery(iter
->first
,
301 iter
->second
->checkbox()->checked());
307 void MediaGalleriesDialogViews::ShowContextMenuForView(
309 const gfx::Point
& point
,
310 ui::MenuSourceType source_type
) {
311 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
312 iter
!= checkbox_map_
.end(); ++iter
) {
313 if (iter
->second
->Contains(source
)) {
314 ShowContextMenu(point
, source_type
, iter
->first
);
320 void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point
& point
,
321 ui::MenuSourceType source_type
,
322 GalleryDialogId id
) {
323 context_menu_runner_
.reset(new views::MenuRunner(
324 controller_
->GetContextMenu(id
)));
326 if (context_menu_runner_
->RunMenuAt(
329 gfx::Rect(point
.x(), point
.y(), 0, 0),
330 views::MENU_ANCHOR_TOPLEFT
,
332 views::MenuRunner::HAS_MNEMONICS
| views::MenuRunner::CONTEXT_MENU
) ==
333 views::MenuRunner::MENU_DELETED
) {
338 bool MediaGalleriesDialogViews::ControllerHasWebContents() const {
339 return controller_
->web_contents() != NULL
;
342 // MediaGalleriesDialogViewsController -----------------------------------------
345 MediaGalleriesDialog
* MediaGalleriesDialog::Create(
346 MediaGalleriesDialogController
* controller
) {
347 return new MediaGalleriesDialogViews(controller
);