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 ShowWebModalDialogViews(this, controller->WebContents());
74 MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {
75 if (!ControllerHasWebContents())
79 void MediaGalleriesDialogViews::AcceptDialogForTesting() {
82 web_modal::PopupManager* popup_manager =
83 web_modal::PopupManager::FromWebContents(controller_->WebContents());
84 DCHECK(popup_manager);
85 popup_manager->CloseAllDialogsForTesting(controller_->WebContents());
88 void MediaGalleriesDialogViews::InitChildViews() {
89 // Outer dialog layout.
90 contents_->RemoveAllChildViews(true);
91 checkbox_map_.clear();
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);
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,
103 views::GridLayout::FIXED,
104 dialog_content_width,
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);
114 views::GridLayout::FILL, views::GridLayout::LEADING,
115 dialog_content_width, subtext->GetHeightForWidth(dialog_content_width));
116 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
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,
126 views::kRelatedControlVerticalSpacing,
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);
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);
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,
149 scroll_container->AddChildView(header);
153 MediaGalleriesDialogController::Entries::const_iterator iter;
154 for (iter = entries.begin(); iter != entries.end(); ++iter) {
156 if (iter + 1 == entries.end())
157 spacing = views::kRelatedControlSmallVerticalSpacing;
158 AddOrUpdateGallery(*iter, scroll_container, spacing);
162 confirm_available_ = controller_->IsAcceptAllowed();
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);
176 void MediaGalleriesDialogViews::UpdateGalleries() {
180 if (ControllerHasWebContents())
181 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
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);
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);
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;
213 base::string16 MediaGalleriesDialogViews::GetWindowTitle() const {
214 return controller_->GetHeader();
217 void MediaGalleriesDialogViews::DeleteDelegate() {
218 controller_->DialogFinished(accepted_);
221 views::Widget* MediaGalleriesDialogViews::GetWidget() {
222 return contents_->GetWidget();
225 const views::Widget* MediaGalleriesDialogViews::GetWidget() const {
226 return contents_->GetWidget();
229 views::View* MediaGalleriesDialogViews::GetContentsView() {
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);
240 bool MediaGalleriesDialogViews::IsDialogButtonEnabled(
241 ui::DialogButton button) const {
242 return button != ui::DIALOG_BUTTON_OK || confirm_available_;
245 ui::ModalType MediaGalleriesDialogViews::GetModalType() const {
246 return ui::MODAL_TYPE_CHILD;
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);
256 return auxiliary_button_;
259 bool MediaGalleriesDialogViews::Cancel() {
263 bool MediaGalleriesDialogViews::Accept() {
268 void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender,
269 const ui::Event& /* event */) {
270 confirm_available_ = true;
272 if (ControllerHasWebContents())
273 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons();
275 if (sender == auxiliary_button_) {
276 controller_->DidClickAuxiliaryButton();
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());
287 if (sender == iter->second->folder_viewer_button()) {
288 controller_->DidClickOpenFolderViewer(iter->first);
294 void MediaGalleriesDialogViews::ShowContextMenuForView(
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);
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));
314 if (context_menu_runner_->RunMenuAt(GetWidget(),
316 gfx::Rect(point.x(), point.y(), 0, 0),
317 views::MENU_ANCHOR_TOPLEFT,
319 views::MenuRunner::MENU_DELETED) {
324 bool MediaGalleriesDialogViews::ControllerHasWebContents() const {
325 return controller_->WebContents() != NULL;
328 // MediaGalleriesDialogViewsController -----------------------------------------
331 MediaGalleriesDialog* MediaGalleriesDialog::Create(
332 MediaGalleriesDialogController* controller) {
333 return new MediaGalleriesDialogViews(controller);