media_galleries_dialog_views.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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. 4 5#include "chrome/browser/ui/views/extensions/media_galleries_dialog_views.h" 6 7#include "base/strings/utf_string_conversions.h" 8#include "chrome/browser/ui/views/constrained_window_views.h" 9#include "chrome/browser/ui/views/extensions/media_gallery_checkbox_view.h" 10#include "components/web_modal/web_contents_modal_dialog_manager.h" 11#include "content/public/browser/web_contents.h" 12#include "grit/generated_resources.h" 13#include "grit/locale_settings.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" 30 31namespace { 32 33const int kScrollAreaHeight = 192; 34 35// This container has the right Layout() impl to use within a ScrollView. 36class ScrollableView : public views::View { 37 public: 38 ScrollableView() {} 39 virtual ~ScrollableView() {} 40 41 virtual void Layout() OVERRIDE; 42 43 private: 44 DISALLOW_COPY_AND_ASSIGN(ScrollableView); 45}; 46 47void ScrollableView::Layout() { 48 gfx::Size pref = GetPreferredSize(); 49 int width = pref.width(); 50 int height = pref.height(); 51 if (parent()) { 52 width = parent()->width(); 53 height = std::max(parent()->height(), height); 54 } 55 SetBounds(x(), y(), width, height); 56 57 views::View::Layout(); 58} 59 60} // namespace 61 62MediaGalleriesDialogViews::MediaGalleriesDialogViews( 63 MediaGalleriesDialogController* controller) 64 : controller_(controller), 65 contents_(new views::View()), 66 auxiliary_button_(NULL), 67 confirm_available_(false), 68 accepted_(false) { 69 InitChildViews(); 70 if (ControllerHasWebContents()) 71 ShowWebModalDialogViews(this, controller->WebContents()); 72} 73 74MediaGalleriesDialogViews::~MediaGalleriesDialogViews() { 75 if (!ControllerHasWebContents()) 76 delete contents_; 77} 78 79void MediaGalleriesDialogViews::AcceptDialogForTesting() { 80 accepted_ = true; 81 82 web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager = 83 web_modal::WebContentsModalDialogManager::FromWebContents( 84 controller_->WebContents()); 85 DCHECK(web_contents_modal_dialog_manager); 86 web_modal::WebContentsModalDialogManager::TestApi( 87 web_contents_modal_dialog_manager).CloseAllDialogs(); 88} 89 90void MediaGalleriesDialogViews::InitChildViews() { 91 // Outer dialog layout. 92 contents_->RemoveAllChildViews(true); 93 checkbox_map_.clear(); 94 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); 99 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, 104 1, 105 views::GridLayout::FIXED, 106 dialog_content_width, 107 0); 108 109 // Message text. 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); 114 layout->AddView( 115 subtext, 1, 1, 116 views::GridLayout::FILL, views::GridLayout::LEADING, 117 dialog_content_width, subtext->GetHeightForWidth(dialog_content_width)); 118 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 119 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, 127 0, 128 views::kRelatedControlVerticalSpacing, 129 0)); 130 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); 136 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); 142 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, 150 0)); 151 scroll_container->AddChildView(header); 152 } 153 154 // Checkboxes. 155 MediaGalleriesDialogController::Entries::const_iterator iter; 156 for (iter = entries.begin(); iter != entries.end(); ++iter) { 157 int spacing = 0; 158 if (iter + 1 == entries.end()) 159 spacing = views::kRelatedControlSmallVerticalSpacing; 160 AddOrUpdateGallery(*iter, scroll_container, spacing); 161 } 162 } 163 164 confirm_available_ = controller_->IsAcceptAllowed(); 165 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); 176} 177 178void MediaGalleriesDialogViews::UpdateGalleries() { 179 InitChildViews(); 180 contents_->Layout(); 181} 182 183bool MediaGalleriesDialogViews::AddOrUpdateGallery( 184 const MediaGalleriesDialogController::Entry& gallery, 185 views::View* container, 186 int trailing_vertical_space) { 187 base::string16 label = gallery.pref_info.GetGalleryDisplayName(); 188 base::string16 tooltip_text = gallery.pref_info.GetGalleryTooltip(); 189 base::string16 details = gallery.pref_info.GetGalleryAdditionalDetails(); 190 bool show_folder_viewer = controller_->ShouldShowFolderViewer(gallery); 191 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(label); 197 checkbox->SetTooltipText(tooltip_text); 198 iter->second->secondary_text()->SetText(details); 199 iter->second->secondary_text()->SetVisible(details.length() > 0); 200 iter->second->folder_viewer_button()->SetVisible(show_folder_viewer); 201 return false; 202 } 203 204 MediaGalleryCheckboxView* gallery_view = 205 new MediaGalleryCheckboxView(label, tooltip_text, details, 206 show_folder_viewer, trailing_vertical_space, 207 this, this); 208 gallery_view->checkbox()->SetChecked(gallery.selected); 209 container->AddChildView(gallery_view); 210 checkbox_map_[gallery.pref_info.pref_id] = gallery_view; 211 212 return true; 213} 214 215base::string16 MediaGalleriesDialogViews::GetWindowTitle() const { 216 return controller_->GetHeader(); 217} 218 219void MediaGalleriesDialogViews::DeleteDelegate() { 220 controller_->DialogFinished(accepted_); 221} 222 223views::Widget* MediaGalleriesDialogViews::GetWidget() { 224 return contents_->GetWidget(); 225} 226 227const views::Widget* MediaGalleriesDialogViews::GetWidget() const { 228 return contents_->GetWidget(); 229} 230 231views::View* MediaGalleriesDialogViews::GetContentsView() { 232 return contents_; 233} 234 235base::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); 240} 241 242bool MediaGalleriesDialogViews::IsDialogButtonEnabled( 243 ui::DialogButton button) const { 244 return button != ui::DIALOG_BUTTON_OK || confirm_available_; 245} 246 247ui::ModalType MediaGalleriesDialogViews::GetModalType() const { 248 return ui::MODAL_TYPE_CHILD; 249} 250 251views::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); 257 } 258 return auxiliary_button_; 259} 260 261bool MediaGalleriesDialogViews::Cancel() { 262 return true; 263} 264 265bool MediaGalleriesDialogViews::Accept() { 266 accepted_ = true; 267 return true; 268} 269 270void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender, 271 const ui::Event& /* event */) { 272 confirm_available_ = true; 273 274 if (ControllerHasWebContents()) 275 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons(); 276 277 if (sender == auxiliary_button_) { 278 controller_->DidClickAuxiliaryButton(); 279 return; 280 } 281 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()); 287 return; 288 } 289 if (sender == iter->second->folder_viewer_button()) { 290 controller_->DidClickOpenFolderViewer(iter->first); 291 return; 292 } 293 } 294} 295 296void MediaGalleriesDialogViews::ShowContextMenuForView( 297 views::View* source, 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); 304 return; 305 } 306 } 307} 308 309void 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 315 if (context_menu_runner_->RunMenuAt( 316 GetWidget(), 317 NULL, 318 gfx::Rect(point.x(), point.y(), 0, 0), 319 views::MENU_ANCHOR_TOPLEFT, 320 source_type, 321 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) == 322 views::MenuRunner::MENU_DELETED) { 323 return; 324 } 325} 326 327bool MediaGalleriesDialogViews::ControllerHasWebContents() const { 328 return controller_->WebContents() != NULL; 329} 330 331// MediaGalleriesDialogViewsController ----------------------------------------- 332 333// static 334MediaGalleriesDialog* MediaGalleriesDialog::Create( 335 MediaGalleriesDialogController* controller) { 336 return new MediaGalleriesDialogViews(controller); 337} 338