media_galleries_dialog_views.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 "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 "content/public/browser/web_contents_view.h" 14#include "grit/generated_resources.h" 15#include "grit/locale_settings.h" 16#include "third_party/skia/include/core/SkColor.h" 17#include "ui/base/l10n/l10n_util.h" 18#include "ui/base/resource/resource_bundle.h" 19#include "ui/native_theme/native_theme.h" 20#include "ui/views/controls/button/checkbox.h" 21#include "ui/views/controls/button/label_button.h" 22#include "ui/views/controls/label.h" 23#include "ui/views/controls/scroll_view.h" 24#include "ui/views/controls/separator.h" 25#include "ui/views/layout/box_layout.h" 26#include "ui/views/layout/grid_layout.h" 27#include "ui/views/layout/layout_constants.h" 28#include "ui/views/view.h" 29#include "ui/views/widget/widget.h" 30#include "ui/views/window/dialog_client_view.h" 31 32using web_modal::WebContentsModalDialogManager; 33using web_modal::WebContentsModalDialogManagerDelegate; 34 35namespace { 36 37// Equal to the #969696 color used in spec (note WebUI color is #999). 38const SkColor kDeemphasizedTextColor = SkColorSetRGB(159, 159, 159); 39 40const int kScrollAreaHeight = 192; 41 42// This container has the right Layout() impl to use within a ScrollView. 43class ScrollableView : public views::View { 44 public: 45 ScrollableView() {} 46 virtual ~ScrollableView() {} 47 48 virtual void Layout() OVERRIDE; 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(ScrollableView); 52}; 53 54void ScrollableView::Layout() { 55 gfx::Size pref = GetPreferredSize(); 56 int width = pref.width(); 57 int height = pref.height(); 58 if (parent()) { 59 width = std::max(parent()->width(), width); 60 height = std::max(parent()->height(), height); 61 } 62 SetBounds(x(), y(), width, height); 63 64 views::View::Layout(); 65} 66 67} // namespace 68 69typedef MediaGalleriesDialogController::GalleryPermissionsVector 70 GalleryPermissionsVector; 71 72MediaGalleriesDialogViews::MediaGalleriesDialogViews( 73 MediaGalleriesDialogController* controller) 74 : controller_(controller), 75 window_(NULL), 76 contents_(new views::View()), 77 add_gallery_button_(NULL), 78 confirm_available_(false), 79 accepted_(false) { 80 InitChildViews(); 81 82 // Ownership of |contents_| is handed off by this call. |window_| will take 83 // care of deleting itself after calling DeleteDelegate(). 84 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 85 WebContentsModalDialogManager::FromWebContents( 86 controller->web_contents()); 87 DCHECK(web_contents_modal_dialog_manager); 88 WebContentsModalDialogManagerDelegate* modal_delegate = 89 web_contents_modal_dialog_manager->delegate(); 90 DCHECK(modal_delegate); 91 window_ = views::Widget::CreateWindowAsFramelessChild( 92 this, 93 controller->web_contents()->GetView()->GetNativeView(), 94 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); 95 web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView()); 96 web_contents_modal_dialog_manager->SetCloseOnInterstitialWebUI( 97 window_->GetNativeView(), true); 98} 99 100MediaGalleriesDialogViews::~MediaGalleriesDialogViews() {} 101 102void MediaGalleriesDialogViews::InitChildViews() { 103 // Outer dialog layout. 104 contents_->RemoveAllChildViews(true); 105 int dialog_content_width = views::Widget::GetLocalizedContentsWidth( 106 IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS); 107 views::GridLayout* layout = views::GridLayout::CreatePanel(contents_); 108 contents_->SetLayoutManager(layout); 109 110 int column_set_id = 0; 111 views::ColumnSet* columns = layout->AddColumnSet(column_set_id); 112 columns->AddColumn(views::GridLayout::LEADING, 113 views::GridLayout::LEADING, 114 1, 115 views::GridLayout::FIXED, 116 dialog_content_width, 117 0); 118 119 if (!DialogDelegate::UseNewStyle()) { 120 // Header text. 121 views::Label* header = new views::Label(controller_->GetHeader()); 122 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 123 header->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); 124 header->SetHorizontalAlignment(gfx::ALIGN_LEFT); 125 layout->StartRow(0, column_set_id); 126 layout->AddView(header); 127 } 128 129 // Message text. 130 views::Label* subtext = new views::Label(controller_->GetSubtext()); 131 subtext->SetMultiLine(true); 132 subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT); 133 layout->StartRow(0, column_set_id); 134 layout->AddView( 135 subtext, 1, 1, 136 views::GridLayout::FILL, views::GridLayout::LEADING, 137 dialog_content_width, subtext->GetHeightForWidth(dialog_content_width)); 138 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 139 140 // Scrollable area for checkboxes. 141 ScrollableView* scroll_container = new ScrollableView(); 142 scroll_container->SetLayoutManager(new views::BoxLayout( 143 views::BoxLayout::kVertical, 0, 0, 144 views::kRelatedControlSmallVerticalSpacing)); 145 scroll_container->set_border(views::Border::CreateEmptyBorder( 146 views::kRelatedControlVerticalSpacing, 147 0, 148 views::kRelatedControlVerticalSpacing, 149 0)); 150 151 // Add attached galleries checkboxes. 152 checkbox_map_.clear(); 153 GalleryPermissionsVector permissions = controller_->AttachedPermissions(); 154 for (GalleryPermissionsVector::const_iterator iter = permissions.begin(); 155 iter != permissions.end(); ++iter) { 156 int spacing = 0; 157 if (iter + 1 == permissions.end()) 158 spacing = views::kRelatedControlSmallVerticalSpacing; 159 AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container, 160 spacing); 161 } 162 163 GalleryPermissionsVector unattached_permissions = 164 controller_->UnattachedPermissions(); 165 166 if (!unattached_permissions.empty()) { 167 // Separator line. 168 views::Separator* separator = new views::Separator( 169 views::Separator::HORIZONTAL); 170 scroll_container->AddChildView(separator); 171 172 // Unattached locations section. 173 views::Label* unattached_text = new views::Label( 174 controller_->GetUnattachedLocationsHeader()); 175 unattached_text->SetMultiLine(true); 176 unattached_text->SetHorizontalAlignment(gfx::ALIGN_LEFT); 177 unattached_text->set_border(views::Border::CreateEmptyBorder( 178 views::kRelatedControlVerticalSpacing, 179 views::kPanelHorizMargin, 180 views::kRelatedControlVerticalSpacing, 181 0)); 182 scroll_container->AddChildView(unattached_text); 183 184 // Add unattached galleries checkboxes. 185 for (GalleryPermissionsVector::const_iterator iter = 186 unattached_permissions.begin(); 187 iter != unattached_permissions.end(); ++iter) { 188 AddOrUpdateGallery(iter->pref_info, iter->allowed, scroll_container, 0); 189 } 190 } 191 192 confirm_available_ = controller_->HasPermittedGalleries(); 193 194 // Add the scrollable area to the outer dialog view. It will squeeze against 195 // the title/subtitle and buttons to occupy all available space in the dialog. 196 views::ScrollView* scroll_view = 197 views::ScrollView::CreateScrollViewWithBorder(); 198 scroll_view->SetContents(scroll_container); 199 layout->StartRowWithPadding(1, column_set_id, 200 0, views::kRelatedControlVerticalSpacing); 201 layout->AddView(scroll_view, 1, 1, 202 views::GridLayout::FILL, views::GridLayout::FILL, 203 dialog_content_width, kScrollAreaHeight); 204} 205 206void MediaGalleriesDialogViews::UpdateGallery( 207 const MediaGalleryPrefInfo& gallery, 208 bool permitted) { 209 InitChildViews(); 210 contents_->Layout(); 211} 212 213void MediaGalleriesDialogViews::ForgetGallery(MediaGalleryPrefId gallery) { 214 InitChildViews(); 215 contents_->Layout(); 216} 217 218bool MediaGalleriesDialogViews::AddOrUpdateGallery( 219 const MediaGalleryPrefInfo& gallery, 220 bool permitted, 221 views::View* container, 222 int trailing_vertical_space) { 223 string16 label = gallery.GetGalleryDisplayName(); 224 string16 tooltip_text = gallery.GetGalleryTooltip(); 225 string16 details = gallery.GetGalleryAdditionalDetails(); 226 227 CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_id); 228 if (iter != checkbox_map_.end()) { 229 views::Checkbox* checkbox = iter->second; 230 checkbox->SetChecked(permitted); 231 checkbox->SetText(label); 232 checkbox->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE); 233 checkbox->SetTooltipText(tooltip_text); 234 // Replace the details string. 235 views::View* checkbox_view = checkbox->parent(); 236 DCHECK_EQ(2, checkbox_view->child_count()); 237 views::Label* secondary_text = 238 static_cast<views::Label*>(checkbox_view->child_at(1)); 239 secondary_text->SetText(details); 240 241 // Why is this returning false? Looks like that will mean it doesn't paint. 242 return false; 243 } 244 245 views::Checkbox* checkbox = new views::Checkbox(label); 246 checkbox->set_listener(this); 247 checkbox->SetTooltipText(tooltip_text); 248 views::Label* secondary_text = new views::Label(details); 249 secondary_text->SetTooltipText(tooltip_text); 250 secondary_text->SetEnabledColor(kDeemphasizedTextColor); 251 secondary_text->SetTooltipText(tooltip_text); 252 secondary_text->set_border(views::Border::CreateEmptyBorder( 253 0, 254 views::kRelatedControlSmallHorizontalSpacing, 255 0, 256 views::kRelatedControlSmallHorizontalSpacing)); 257 258 views::View* checkbox_view = new views::View(); 259 checkbox_view->set_border(views::Border::CreateEmptyBorder( 260 0, 261 views::kPanelHorizMargin, 262 trailing_vertical_space, 263 0)); 264 checkbox_view->SetLayoutManager( 265 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); 266 checkbox_view->AddChildView(checkbox); 267 checkbox_view->AddChildView(secondary_text); 268 269 container->AddChildView(checkbox_view); 270 271 checkbox->SetChecked(permitted); 272 checkbox_map_[gallery.pref_id] = checkbox; 273 274 return true; 275} 276 277string16 MediaGalleriesDialogViews::GetWindowTitle() const { 278 return controller_->GetHeader(); 279} 280 281bool MediaGalleriesDialogViews::ShouldShowWindowTitle() const { 282 return DialogDelegate::UseNewStyle(); 283} 284 285void MediaGalleriesDialogViews::DeleteDelegate() { 286 controller_->DialogFinished(accepted_); 287} 288 289views::Widget* MediaGalleriesDialogViews::GetWidget() { 290 return contents_->GetWidget(); 291} 292 293const views::Widget* MediaGalleriesDialogViews::GetWidget() const { 294 return contents_->GetWidget(); 295} 296 297views::View* MediaGalleriesDialogViews::GetContentsView() { 298 return contents_; 299} 300 301string16 MediaGalleriesDialogViews::GetDialogButtonLabel( 302 ui::DialogButton button) const { 303 return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK ? 304 IDS_MEDIA_GALLERIES_DIALOG_CONFIRM : 305 IDS_MEDIA_GALLERIES_DIALOG_CANCEL); 306} 307 308bool MediaGalleriesDialogViews::IsDialogButtonEnabled( 309 ui::DialogButton button) const { 310 return button != ui::DIALOG_BUTTON_OK || confirm_available_; 311} 312 313ui::ModalType MediaGalleriesDialogViews::GetModalType() const { 314#if defined(USE_ASH) 315 return ui::MODAL_TYPE_CHILD; 316#else 317 return views::WidgetDelegate::GetModalType(); 318#endif 319} 320 321views::View* MediaGalleriesDialogViews::CreateExtraView() { 322 DCHECK(!add_gallery_button_); 323 add_gallery_button_ = new views::LabelButton(this, 324 l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY)); 325 add_gallery_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 326 return add_gallery_button_; 327} 328 329bool MediaGalleriesDialogViews::Cancel() { 330 return true; 331} 332 333bool MediaGalleriesDialogViews::Accept() { 334 accepted_ = true; 335 336 return true; 337} 338 339// TODO(wittman): Remove this override once we move to the new style frame view 340// on all dialogs. 341views::NonClientFrameView* MediaGalleriesDialogViews::CreateNonClientFrameView( 342 views::Widget* widget) { 343 return CreateConstrainedStyleNonClientFrameView( 344 widget, 345 controller_->web_contents()->GetBrowserContext()); 346} 347 348void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender, 349 const ui::Event& event) { 350 confirm_available_ = true; 351 GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons(); 352 353 if (sender == add_gallery_button_) { 354 controller_->OnAddFolderClicked(); 355 return; 356 } 357 358 for (CheckboxMap::const_iterator iter = checkbox_map_.begin(); 359 iter != checkbox_map_.end(); ++iter) { 360 if (sender == iter->second) { 361 controller_->DidToggleGalleryId(iter->first, 362 iter->second->checked()); 363 return; 364 } 365 } 366} 367 368// MediaGalleriesDialogViewsController ----------------------------------------- 369 370// static 371MediaGalleriesDialog* MediaGalleriesDialog::Create( 372 MediaGalleriesDialogController* controller) { 373 return new MediaGalleriesDialogViews(controller); 374} 375