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/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"
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::PopupManager
* popup_manager
=
85 web_modal::PopupManager::FromWebContents(controller_
->WebContents());
86 DCHECK(popup_manager
);
87 popup_manager
->CloseAllDialogsForTesting(controller_
->WebContents());
90 void MediaGalleriesDialogViews::InitChildViews() {
91 // Outer dialog layout.
92 contents_
->RemoveAllChildViews(true);
93 checkbox_map_
.clear();
95 int dialog_content_width
= views::Widget::GetLocalizedContentsWidth(
96 IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS
);
97 views::GridLayout
* layout
= views::GridLayout::CreatePanel(contents_
);
98 contents_
->SetLayoutManager(layout
);
100 int column_set_id
= 0;
101 views::ColumnSet
* columns
= layout
->AddColumnSet(column_set_id
);
102 columns
->AddColumn(views::GridLayout::LEADING
,
103 views::GridLayout::LEADING
,
105 views::GridLayout::FIXED
,
106 dialog_content_width
,
110 views::Label
* subtext
= new views::Label(controller_
->GetSubtext());
111 subtext
->SetMultiLine(true);
112 subtext
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
113 layout
->StartRow(0, column_set_id
);
116 views::GridLayout::FILL
, views::GridLayout::LEADING
,
117 dialog_content_width
, subtext
->GetHeightForWidth(dialog_content_width
));
118 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
120 // Scrollable area for checkboxes.
121 ScrollableView
* scroll_container
= new ScrollableView();
122 scroll_container
->SetLayoutManager(new views::BoxLayout(
123 views::BoxLayout::kVertical
, 0, 0,
124 views::kRelatedControlSmallVerticalSpacing
));
125 scroll_container
->SetBorder(
126 views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing
,
128 views::kRelatedControlVerticalSpacing
,
131 std::vector
<base::string16
> section_headers
=
132 controller_
->GetSectionHeaders();
133 for (size_t i
= 0; i
< section_headers
.size(); i
++) {
134 MediaGalleriesDialogController::Entries entries
=
135 controller_
->GetSectionEntries(i
);
137 // Header and separator line.
138 if (!section_headers
[i
].empty() && !entries
.empty()) {
139 views::Separator
* separator
= new views::Separator(
140 views::Separator::HORIZONTAL
);
141 scroll_container
->AddChildView(separator
);
143 views::Label
* header
= new views::Label(section_headers
[i
]);
144 header
->SetMultiLine(true);
145 header
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
146 header
->SetBorder(views::Border::CreateEmptyBorder(
147 views::kRelatedControlVerticalSpacing
,
148 views::kPanelHorizMargin
,
149 views::kRelatedControlVerticalSpacing
,
151 scroll_container
->AddChildView(header
);
155 MediaGalleriesDialogController::Entries::const_iterator iter
;
156 for (iter
= entries
.begin(); iter
!= entries
.end(); ++iter
) {
158 if (iter
+ 1 == entries
.end())
159 spacing
= views::kRelatedControlSmallVerticalSpacing
;
160 AddOrUpdateGallery(*iter
, scroll_container
, spacing
);
164 confirm_available_
= controller_
->IsAcceptAllowed();
166 // Add the scrollable area to the outer dialog view. It will squeeze against
167 // the title/subtitle and buttons to occupy all available space in the dialog.
168 views::ScrollView
* scroll_view
=
169 views::ScrollView::CreateScrollViewWithBorder();
170 scroll_view
->SetContents(scroll_container
);
171 layout
->StartRowWithPadding(1, column_set_id
,
172 0, views::kRelatedControlVerticalSpacing
);
173 layout
->AddView(scroll_view
, 1, 1,
174 views::GridLayout::FILL
, views::GridLayout::FILL
,
175 dialog_content_width
, kScrollAreaHeight
);
178 void MediaGalleriesDialogViews::UpdateGalleries() {
182 if (ControllerHasWebContents())
183 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
186 bool MediaGalleriesDialogViews::AddOrUpdateGallery(
187 const MediaGalleriesDialogController::Entry
& gallery
,
188 views::View
* container
,
189 int trailing_vertical_space
) {
190 bool show_folder_viewer
= controller_
->ShouldShowFolderViewer(gallery
);
192 CheckboxMap::iterator iter
= checkbox_map_
.find(gallery
.pref_info
.pref_id
);
193 if (iter
!= checkbox_map_
.end()) {
194 views::Checkbox
* checkbox
= iter
->second
->checkbox();
195 checkbox
->SetChecked(gallery
.selected
);
196 checkbox
->SetText(gallery
.pref_info
.GetGalleryDisplayName());
197 checkbox
->SetTooltipText(gallery
.pref_info
.GetGalleryTooltip());
198 base::string16 details
= gallery
.pref_info
.GetGalleryAdditionalDetails();
199 iter
->second
->secondary_text()->SetText(details
);
200 iter
->second
->secondary_text()->SetVisible(details
.length() > 0);
201 iter
->second
->folder_viewer_button()->SetVisible(show_folder_viewer
);
205 MediaGalleryCheckboxView
* gallery_view
=
206 new MediaGalleryCheckboxView(gallery
.pref_info
, show_folder_viewer
,
207 trailing_vertical_space
, this, this);
208 gallery_view
->checkbox()->SetChecked(gallery
.selected
);
209 container
->AddChildView(gallery_view
);
210 checkbox_map_
[gallery
.pref_info
.pref_id
] = gallery_view
;
215 base::string16
MediaGalleriesDialogViews::GetWindowTitle() const {
216 return controller_
->GetHeader();
219 void MediaGalleriesDialogViews::DeleteDelegate() {
220 controller_
->DialogFinished(accepted_
);
223 views::Widget
* MediaGalleriesDialogViews::GetWidget() {
224 return contents_
->GetWidget();
227 const views::Widget
* MediaGalleriesDialogViews::GetWidget() const {
228 return contents_
->GetWidget();
231 views::View
* MediaGalleriesDialogViews::GetContentsView() {
235 base::string16
MediaGalleriesDialogViews::GetDialogButtonLabel(
236 ui::DialogButton button
) const {
237 if (button
== ui::DIALOG_BUTTON_OK
)
238 return controller_
->GetAcceptButtonText();
239 return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_CANCEL
);
242 bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
243 ui::DialogButton button
) const {
244 return button
!= ui::DIALOG_BUTTON_OK
|| confirm_available_
;
247 ui::ModalType
MediaGalleriesDialogViews::GetModalType() const {
248 return ui::MODAL_TYPE_CHILD
;
251 views::View
* MediaGalleriesDialogViews::CreateExtraView() {
252 DCHECK(!auxiliary_button_
);
253 base::string16 button_label
= controller_
->GetAuxiliaryButtonText();
254 if (!button_label
.empty()) {
255 auxiliary_button_
= new views::LabelButton(this, button_label
);
256 auxiliary_button_
->SetStyle(views::Button::STYLE_BUTTON
);
258 return auxiliary_button_
;
261 bool MediaGalleriesDialogViews::Cancel() {
265 bool MediaGalleriesDialogViews::Accept() {
270 void MediaGalleriesDialogViews::ButtonPressed(views::Button
* sender
,
271 const ui::Event
& /* event */) {
272 confirm_available_
= true;
274 if (ControllerHasWebContents())
275 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
277 if (sender
== auxiliary_button_
) {
278 controller_
->DidClickAuxiliaryButton();
282 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
283 iter
!= checkbox_map_
.end(); ++iter
) {
284 if (sender
== iter
->second
->checkbox()) {
285 controller_
->DidToggleEntry(iter
->first
,
286 iter
->second
->checkbox()->checked());
289 if (sender
== iter
->second
->folder_viewer_button()) {
290 controller_
->DidClickOpenFolderViewer(iter
->first
);
296 void MediaGalleriesDialogViews::ShowContextMenuForView(
298 const gfx::Point
& point
,
299 ui::MenuSourceType source_type
) {
300 for (CheckboxMap::const_iterator iter
= checkbox_map_
.begin();
301 iter
!= checkbox_map_
.end(); ++iter
) {
302 if (iter
->second
->Contains(source
)) {
303 ShowContextMenu(point
, source_type
, iter
->first
);
309 void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point
& point
,
310 ui::MenuSourceType source_type
,
311 MediaGalleryPrefId id
) {
312 context_menu_runner_
.reset(new views::MenuRunner(
313 controller_
->GetContextMenu(id
),
314 views::MenuRunner::HAS_MNEMONICS
| views::MenuRunner::CONTEXT_MENU
));
316 if (context_menu_runner_
->RunMenuAt(GetWidget(),
318 gfx::Rect(point
.x(), point
.y(), 0, 0),
319 views::MENU_ANCHOR_TOPLEFT
,
321 views::MenuRunner::MENU_DELETED
) {
326 bool MediaGalleriesDialogViews::ControllerHasWebContents() const {
327 return controller_
->WebContents() != NULL
;
330 // MediaGalleriesDialogViewsController -----------------------------------------
333 MediaGalleriesDialog
* MediaGalleriesDialog::Create(
334 MediaGalleriesDialogController
* controller
) {
335 return new MediaGalleriesDialogViews(controller
);