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 "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/web_contents_modal_dialog_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"
33 const int kScrollAreaHeight
= 192;
35 // This container has the right Layout() impl to use within a ScrollView.
36 class ScrollableView
: public views::View
{
39 ~ScrollableView() override
{}
41 void Layout() override
;
44 DISALLOW_COPY_AND_ASSIGN(ScrollableView
);
47 void ScrollableView::Layout() {
48 gfx::Size pref
= GetPreferredSize();
49 int width
= pref
.width();
50 int height
= pref
.height();
52 width
= parent()->width();
53 height
= std::max(parent()->height(), height
);
55 SetBounds(x(), y(), width
, height
);
57 views::View::Layout();
62 MediaGalleriesDialogViews::MediaGalleriesDialogViews(
63 MediaGalleriesDialogController
* controller
)
64 : controller_(controller
),
65 contents_(new views::View()),
66 auxiliary_button_(NULL
),
67 confirm_available_(false),
70 if (ControllerHasWebContents()) {
71 constrained_window::ShowWebModalDialogViews(this,
72 controller
->WebContents());
76 MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {
77 if (!ControllerHasWebContents())
81 void MediaGalleriesDialogViews::AcceptDialogForTesting() {
84 web_modal::WebContentsModalDialogManager
* manager
=
85 web_modal::WebContentsModalDialogManager::FromWebContents(
86 controller_
->WebContents());
88 web_modal::WebContentsModalDialogManager::TestApi(manager
).CloseAllDialogs();
91 void MediaGalleriesDialogViews::InitChildViews() {
92 // Outer dialog layout.
93 contents_
->RemoveAllChildViews(true);
94 checkbox_map_
.clear();
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
);
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
,
106 views::GridLayout::FIXED
,
107 dialog_content_width
,
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
);
117 views::GridLayout::FILL
, views::GridLayout::LEADING
,
118 dialog_content_width
, subtext
->GetHeightForWidth(dialog_content_width
));
119 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
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(
127 views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing
,
129 views::kRelatedControlVerticalSpacing
,
132 std::vector
<base::string16
> section_headers
=
133 controller_
->GetSectionHeaders();
134 for (size_t i
= 0; i
< section_headers
.size(); i
++) {
135 MediaGalleriesDialogController::Entries entries
=
136 controller_
->GetSectionEntries(i
);
138 // Header and separator line.
139 if (!section_headers
[i
].empty() && !entries
.empty()) {
140 views::Separator
* separator
= new views::Separator(
141 views::Separator::HORIZONTAL
);
142 scroll_container
->AddChildView(separator
);
144 views::Label
* header
= new views::Label(section_headers
[i
]);
145 header
->SetMultiLine(true);
146 header
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
147 header
->SetBorder(views::Border::CreateEmptyBorder(
148 views::kRelatedControlVerticalSpacing
,
149 views::kPanelHorizMargin
,
150 views::kRelatedControlVerticalSpacing
,
152 scroll_container
->AddChildView(header
);
156 MediaGalleriesDialogController::Entries::const_iterator iter
;
157 for (iter
= entries
.begin(); iter
!= entries
.end(); ++iter
) {
159 if (iter
+ 1 == entries
.end())
160 spacing
= views::kRelatedControlSmallVerticalSpacing
;
161 AddOrUpdateGallery(*iter
, scroll_container
, spacing
);
165 confirm_available_
= controller_
->IsAcceptAllowed();
167 // Add the scrollable area to the outer dialog view. It will squeeze against
168 // the title/subtitle and buttons to occupy all available space in the dialog.
169 views::ScrollView
* scroll_view
=
170 views::ScrollView::CreateScrollViewWithBorder();
171 scroll_view
->SetContents(scroll_container
);
172 layout
->StartRowWithPadding(1, column_set_id
,
173 0, views::kRelatedControlVerticalSpacing
);
174 layout
->AddView(scroll_view
, 1, 1,
175 views::GridLayout::FILL
, views::GridLayout::FILL
,
176 dialog_content_width
, kScrollAreaHeight
);
179 void MediaGalleriesDialogViews::UpdateGalleries() {
183 if (ControllerHasWebContents())
184 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
187 bool MediaGalleriesDialogViews::AddOrUpdateGallery(
188 const MediaGalleriesDialogController::Entry
& gallery
,
189 views::View
* container
,
190 int trailing_vertical_space
) {
191 bool show_folder_viewer
= controller_
->ShouldShowFolderViewer(gallery
);
193 CheckboxMap::iterator iter
= checkbox_map_
.find(gallery
.pref_info
.pref_id
);
194 if (iter
!= checkbox_map_
.end()) {
195 views::Checkbox
* checkbox
= iter
->second
->checkbox();
196 checkbox
->SetChecked(gallery
.selected
);
197 checkbox
->SetText(gallery
.pref_info
.GetGalleryDisplayName());
198 checkbox
->SetTooltipText(gallery
.pref_info
.GetGalleryTooltip());
199 base::string16 details
= gallery
.pref_info
.GetGalleryAdditionalDetails();
200 iter
->second
->secondary_text()->SetText(details
);
201 iter
->second
->secondary_text()->SetVisible(details
.length() > 0);
202 iter
->second
->folder_viewer_button()->SetVisible(show_folder_viewer
);
206 MediaGalleryCheckboxView
* gallery_view
=
207 new MediaGalleryCheckboxView(gallery
.pref_info
, show_folder_viewer
,
208 trailing_vertical_space
, this, this);
209 gallery_view
->checkbox()->SetChecked(gallery
.selected
);
210 container
->AddChildView(gallery_view
);
211 checkbox_map_
[gallery
.pref_info
.pref_id
] = gallery_view
;
216 base::string16
MediaGalleriesDialogViews::GetWindowTitle() const {
217 return controller_
->GetHeader();
220 void MediaGalleriesDialogViews::DeleteDelegate() {
221 controller_
->DialogFinished(accepted_
);
224 views::Widget
* MediaGalleriesDialogViews::GetWidget() {
225 return contents_
->GetWidget();
228 const views::Widget
* MediaGalleriesDialogViews::GetWidget() const {
229 return contents_
->GetWidget();
232 views::View
* MediaGalleriesDialogViews::GetContentsView() {
236 base::string16
MediaGalleriesDialogViews::GetDialogButtonLabel(
237 ui::DialogButton button
) const {
238 if (button
== ui::DIALOG_BUTTON_OK
)
239 return controller_
->GetAcceptButtonText();
240 return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_CANCEL
);
243 bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
244 ui::DialogButton button
) const {
245 return button
!= ui::DIALOG_BUTTON_OK
|| confirm_available_
;
248 ui::ModalType
MediaGalleriesDialogViews::GetModalType() const {
249 return ui::MODAL_TYPE_CHILD
;
252 views::View
* MediaGalleriesDialogViews::CreateExtraView() {
253 DCHECK(!auxiliary_button_
);
254 base::string16 button_label
= controller_
->GetAuxiliaryButtonText();
255 if (!button_label
.empty()) {
256 auxiliary_button_
= new views::LabelButton(this, button_label
);
257 auxiliary_button_
->SetStyle(views::Button::STYLE_BUTTON
);
259 return auxiliary_button_
;
262 bool MediaGalleriesDialogViews::Cancel() {
266 bool MediaGalleriesDialogViews::Accept() {
271 void MediaGalleriesDialogViews::ButtonPressed(views::Button
* sender
,
272 const ui::Event
& /* event */) {
273 confirm_available_
= true;
275 if (ControllerHasWebContents())
276 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
278 if (sender
== auxiliary_button_
) {
279 controller_
->DidClickAuxiliaryButton();
283 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
284 iter
!= checkbox_map_
.end(); ++iter
) {
285 if (sender
== iter
->second
->checkbox()) {
286 controller_
->DidToggleEntry(iter
->first
,
287 iter
->second
->checkbox()->checked());
290 if (sender
== iter
->second
->folder_viewer_button()) {
291 controller_
->DidClickOpenFolderViewer(iter
->first
);
297 void MediaGalleriesDialogViews::ShowContextMenuForView(
299 const gfx::Point
& point
,
300 ui::MenuSourceType source_type
) {
301 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
302 iter
!= checkbox_map_
.end(); ++iter
) {
303 if (iter
->second
->Contains(source
)) {
304 ShowContextMenu(point
, source_type
, iter
->first
);
310 void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point
& point
,
311 ui::MenuSourceType source_type
,
312 MediaGalleryPrefId id
) {
313 context_menu_runner_
.reset(new views::MenuRunner(
314 controller_
->GetContextMenu(id
),
315 views::MenuRunner::HAS_MNEMONICS
| views::MenuRunner::CONTEXT_MENU
));
317 if (context_menu_runner_
->RunMenuAt(GetWidget(),
319 gfx::Rect(point
.x(), point
.y(), 0, 0),
320 views::MENU_ANCHOR_TOPLEFT
,
322 views::MenuRunner::MENU_DELETED
) {
327 bool MediaGalleriesDialogViews::ControllerHasWebContents() const {
328 return controller_
->WebContents() != NULL
;
331 // MediaGalleriesDialogViewsController -----------------------------------------
334 MediaGalleriesDialog
* MediaGalleriesDialog::Create(
335 MediaGalleriesDialogController
* controller
) {
336 return new MediaGalleriesDialogViews(controller
);