media_galleries_dialog_views.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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/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" 30 31using web_modal::WebContentsModalDialogManager; 32using web_modal::WebContentsModalDialogManagerDelegate; 33 34namespace { 35 36const int kScrollAreaHeight = 192; 37 38// This container has the right Layout() impl to use within a ScrollView. 39class ScrollableView : public views::View { 40 public: 41 ScrollableView() {} 42 virtual ~ScrollableView() {} 43 44 virtual void Layout() OVERRIDE; 45 46 private: 47 DISALLOW_COPY_AND_ASSIGN(ScrollableView); 48}; 49 50void ScrollableView::Layout() { 51 gfx::Size pref = GetPreferredSize(); 52 int width = pref.width(); 53 int height = pref.height(); 54 if (parent()) { 55 width = parent()->width(); 56 height = std::max(parent()->height(), height); 57 } 58 SetBounds(x(), y(), width, height); 59 60 views::View::Layout(); 61} 62 63} // namespace 64 65typedef MediaGalleriesDialogController::GalleryPermissionsVector 66 GalleryPermissionsVector; 67 68MediaGalleriesDialogViews::MediaGalleriesDialogViews( 69 MediaGalleriesDialogController* controller) 70 : controller_(controller), 71 window_(NULL), 72 contents_(new views::View()), 73 add_gallery_button_(NULL), 74 confirm_available_(false), 75 accepted_(false) { 76 InitChildViews(); 77 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()); 92 } 93} 94 95MediaGalleriesDialogViews::~MediaGalleriesDialogViews() { 96 if (!ControllerHasWebContents()) 97 delete contents_; 98} 99 100void 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); 107 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, 112 1, 113 views::GridLayout::FIXED, 114 dialog_content_width, 115 0); 116 117 // Message text. 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); 122 layout->AddView( 123 subtext, 1, 1, 124 views::GridLayout::FILL, views::GridLayout::LEADING, 125 dialog_content_width, subtext->GetHeightForWidth(dialog_content_width)); 126 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 127 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, 135 0, 136 views::kRelatedControlVerticalSpacing, 137 0)); 138 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) { 144 int spacing = 0; 145 if (iter + 1 == permissions.end()) 146 spacing = views::kRelatedControlSmallVerticalSpacing; 147 AddOrUpdateGallery(*iter, scroll_container, spacing); 148 } 149 150 GalleryPermissionsVector unattached_permissions = 151 controller_->UnattachedPermissions(); 152 153 if (!unattached_permissions.empty()) { 154 // Separator line. 155 views::Separator* separator = new views::Separator( 156 views::Separator::HORIZONTAL); 157 scroll_container->AddChildView(separator); 158 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, 168 0)); 169 scroll_container->AddChildView(unattached_text); 170 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); 176 } 177 } 178 179 confirm_available_ = controller_->IsAcceptAllowed(); 180 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); 191} 192 193void MediaGalleriesDialogViews::UpdateGalleries() { 194 InitChildViews(); 195 contents_->Layout(); 196} 197 198bool 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(); 205 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); 214 return false; 215 } 216 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; 223 224 return true; 225} 226 227base::string16 MediaGalleriesDialogViews::GetWindowTitle() const { 228 return controller_->GetHeader(); 229} 230 231void MediaGalleriesDialogViews::DeleteDelegate() { 232 controller_->DialogFinished(accepted_); 233} 234 235views::Widget* MediaGalleriesDialogViews::GetWidget() { 236 return contents_->GetWidget(); 237} 238 239const views::Widget* MediaGalleriesDialogViews::GetWidget() const { 240 return contents_->GetWidget(); 241} 242 243views::View* MediaGalleriesDialogViews::GetContentsView() { 244 return contents_; 245} 246 247base::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); 252} 253 254bool MediaGalleriesDialogViews::IsDialogButtonEnabled( 255 ui::DialogButton button) const { 256 return button != ui::DIALOG_BUTTON_OK || confirm_available_; 257} 258 259ui::ModalType MediaGalleriesDialogViews::GetModalType() const { 260#if defined(USE_ASH) 261 return ui::MODAL_TYPE_CHILD; 262#else 263 return views::WidgetDelegate::GetModalType(); 264#endif 265} 266 267views::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_; 273} 274 275bool MediaGalleriesDialogViews::Cancel() { 276 return true; 277} 278 279bool MediaGalleriesDialogViews::Accept() { 280 accepted_ = true; 281 282 return true; 283} 284 285void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender, 286 const ui::Event& /* event */) { 287 confirm_available_ = true; 288 289 if (ControllerHasWebContents()) 290 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons(); 291 292 if (sender == add_gallery_button_) { 293 controller_->OnAddFolderClicked(); 294 return; 295 } 296 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()); 302 return; 303 } 304 } 305} 306 307void MediaGalleriesDialogViews::ShowContextMenuForView( 308 views::View* source, 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); 315 return; 316 } 317 } 318} 319 320void 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))); 325 326 if (context_menu_runner_->RunMenuAt( 327 GetWidget(), 328 NULL, 329 gfx::Rect(point.x(), point.y(), 0, 0), 330 views::MENU_ANCHOR_TOPLEFT, 331 source_type, 332 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) == 333 views::MenuRunner::MENU_DELETED) { 334 return; 335 } 336} 337 338bool MediaGalleriesDialogViews::ControllerHasWebContents() const { 339 return controller_->web_contents() != NULL; 340} 341 342// MediaGalleriesDialogViewsController ----------------------------------------- 343 344// static 345MediaGalleriesDialog* MediaGalleriesDialog::Create( 346 MediaGalleriesDialogController* controller) { 347 return new MediaGalleriesDialogViews(controller); 348} 349