// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/views/extensions/media_galleries_dialog_views.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/views/constrained_window_views.h" #include "chrome/browser/ui/views/extensions/media_gallery_checkbox_view.h" #include "components/web_modal/popup_manager.h" #include "content/public/browser/web_contents.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/native_theme/native_theme.h" #include "ui/views/border.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/layout/layout_constants.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_client_view.h" namespace { const int kScrollAreaHeight = 192; // This container has the right Layout() impl to use within a ScrollView. class ScrollableView : public views::View { public: ScrollableView() {} virtual ~ScrollableView() {} virtual void Layout() OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(ScrollableView); }; void ScrollableView::Layout() { gfx::Size pref = GetPreferredSize(); int width = pref.width(); int height = pref.height(); if (parent()) { width = parent()->width(); height = std::max(parent()->height(), height); } SetBounds(x(), y(), width, height); views::View::Layout(); } } // namespace MediaGalleriesDialogViews::MediaGalleriesDialogViews( MediaGalleriesDialogController* controller) : controller_(controller), contents_(new views::View()), auxiliary_button_(NULL), confirm_available_(false), accepted_(false) { InitChildViews(); if (ControllerHasWebContents()) ShowWebModalDialogViews(this, controller->WebContents()); } MediaGalleriesDialogViews::~MediaGalleriesDialogViews() { if (!ControllerHasWebContents()) delete contents_; } void MediaGalleriesDialogViews::AcceptDialogForTesting() { accepted_ = true; web_modal::PopupManager* popup_manager = web_modal::PopupManager::FromWebContents(controller_->WebContents()); DCHECK(popup_manager); popup_manager->CloseAllDialogsForTesting(controller_->WebContents()); } void MediaGalleriesDialogViews::InitChildViews() { // Outer dialog layout. contents_->RemoveAllChildViews(true); checkbox_map_.clear(); int dialog_content_width = views::Widget::GetLocalizedContentsWidth( IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS); views::GridLayout* layout = views::GridLayout::CreatePanel(contents_); contents_->SetLayoutManager(layout); int column_set_id = 0; views::ColumnSet* columns = layout->AddColumnSet(column_set_id); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 1, views::GridLayout::FIXED, dialog_content_width, 0); // Message text. views::Label* subtext = new views::Label(controller_->GetSubtext()); subtext->SetMultiLine(true); subtext->SetHorizontalAlignment(gfx::ALIGN_LEFT); layout->StartRow(0, column_set_id); layout->AddView( subtext, 1, 1, views::GridLayout::FILL, views::GridLayout::LEADING, dialog_content_width, subtext->GetHeightForWidth(dialog_content_width)); layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); // Scrollable area for checkboxes. ScrollableView* scroll_container = new ScrollableView(); scroll_container->SetLayoutManager(new views::BoxLayout( views::BoxLayout::kVertical, 0, 0, views::kRelatedControlSmallVerticalSpacing)); scroll_container->SetBorder( views::Border::CreateEmptyBorder(views::kRelatedControlVerticalSpacing, 0, views::kRelatedControlVerticalSpacing, 0)); std::vector section_headers = controller_->GetSectionHeaders(); for (size_t i = 0; i < section_headers.size(); i++) { MediaGalleriesDialogController::Entries entries = controller_->GetSectionEntries(i); // Header and separator line. if (!section_headers[i].empty() && !entries.empty()) { views::Separator* separator = new views::Separator( views::Separator::HORIZONTAL); scroll_container->AddChildView(separator); views::Label* header = new views::Label(section_headers[i]); header->SetMultiLine(true); header->SetHorizontalAlignment(gfx::ALIGN_LEFT); header->SetBorder(views::Border::CreateEmptyBorder( views::kRelatedControlVerticalSpacing, views::kPanelHorizMargin, views::kRelatedControlVerticalSpacing, 0)); scroll_container->AddChildView(header); } // Checkboxes. MediaGalleriesDialogController::Entries::const_iterator iter; for (iter = entries.begin(); iter != entries.end(); ++iter) { int spacing = 0; if (iter + 1 == entries.end()) spacing = views::kRelatedControlSmallVerticalSpacing; AddOrUpdateGallery(*iter, scroll_container, spacing); } } confirm_available_ = controller_->IsAcceptAllowed(); // Add the scrollable area to the outer dialog view. It will squeeze against // the title/subtitle and buttons to occupy all available space in the dialog. views::ScrollView* scroll_view = views::ScrollView::CreateScrollViewWithBorder(); scroll_view->SetContents(scroll_container); layout->StartRowWithPadding(1, column_set_id, 0, views::kRelatedControlVerticalSpacing); layout->AddView(scroll_view, 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, dialog_content_width, kScrollAreaHeight); } void MediaGalleriesDialogViews::UpdateGalleries() { InitChildViews(); contents_->Layout(); if (ControllerHasWebContents()) GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons(); } bool MediaGalleriesDialogViews::AddOrUpdateGallery( const MediaGalleriesDialogController::Entry& gallery, views::View* container, int trailing_vertical_space) { bool show_folder_viewer = controller_->ShouldShowFolderViewer(gallery); CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_info.pref_id); if (iter != checkbox_map_.end()) { views::Checkbox* checkbox = iter->second->checkbox(); checkbox->SetChecked(gallery.selected); checkbox->SetText(gallery.pref_info.GetGalleryDisplayName()); checkbox->SetTooltipText(gallery.pref_info.GetGalleryTooltip()); base::string16 details = gallery.pref_info.GetGalleryAdditionalDetails(); iter->second->secondary_text()->SetText(details); iter->second->secondary_text()->SetVisible(details.length() > 0); iter->second->folder_viewer_button()->SetVisible(show_folder_viewer); return false; } MediaGalleryCheckboxView* gallery_view = new MediaGalleryCheckboxView(gallery.pref_info, show_folder_viewer, trailing_vertical_space, this, this); gallery_view->checkbox()->SetChecked(gallery.selected); container->AddChildView(gallery_view); checkbox_map_[gallery.pref_info.pref_id] = gallery_view; return true; } base::string16 MediaGalleriesDialogViews::GetWindowTitle() const { return controller_->GetHeader(); } void MediaGalleriesDialogViews::DeleteDelegate() { controller_->DialogFinished(accepted_); } views::Widget* MediaGalleriesDialogViews::GetWidget() { return contents_->GetWidget(); } const views::Widget* MediaGalleriesDialogViews::GetWidget() const { return contents_->GetWidget(); } views::View* MediaGalleriesDialogViews::GetContentsView() { return contents_; } base::string16 MediaGalleriesDialogViews::GetDialogButtonLabel( ui::DialogButton button) const { if (button == ui::DIALOG_BUTTON_OK) return controller_->GetAcceptButtonText(); return l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_CANCEL); } bool MediaGalleriesDialogViews::IsDialogButtonEnabled( ui::DialogButton button) const { return button != ui::DIALOG_BUTTON_OK || confirm_available_; } ui::ModalType MediaGalleriesDialogViews::GetModalType() const { return ui::MODAL_TYPE_CHILD; } views::View* MediaGalleriesDialogViews::CreateExtraView() { DCHECK(!auxiliary_button_); base::string16 button_label = controller_->GetAuxiliaryButtonText(); if (!button_label.empty()) { auxiliary_button_ = new views::LabelButton(this, button_label); auxiliary_button_->SetStyle(views::Button::STYLE_BUTTON); } return auxiliary_button_; } bool MediaGalleriesDialogViews::Cancel() { return true; } bool MediaGalleriesDialogViews::Accept() { accepted_ = true; return true; } void MediaGalleriesDialogViews::ButtonPressed(views::Button* sender, const ui::Event& /* event */) { confirm_available_ = true; if (ControllerHasWebContents()) GetWidget()->client_view()->AsDialogClientView()->UpdateDialogButtons(); if (sender == auxiliary_button_) { controller_->DidClickAuxiliaryButton(); return; } for (CheckboxMap::const_iterator iter = checkbox_map_.begin(); iter != checkbox_map_.end(); ++iter) { if (sender == iter->second->checkbox()) { controller_->DidToggleEntry(iter->first, iter->second->checkbox()->checked()); return; } if (sender == iter->second->folder_viewer_button()) { controller_->DidClickOpenFolderViewer(iter->first); return; } } } void MediaGalleriesDialogViews::ShowContextMenuForView( views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { for (CheckboxMap::const_iterator iter = checkbox_map_.begin(); iter != checkbox_map_.end(); ++iter) { if (iter->second->Contains(source)) { ShowContextMenu(point, source_type, iter->first); return; } } } void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point& point, ui::MenuSourceType source_type, MediaGalleryPrefId id) { context_menu_runner_.reset(new views::MenuRunner( controller_->GetContextMenu(id), views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU)); if (context_menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point.x(), point.y(), 0, 0), views::MENU_ANCHOR_TOPLEFT, source_type) == views::MenuRunner::MENU_DELETED) { return; } } bool MediaGalleriesDialogViews::ControllerHasWebContents() const { return controller_->WebContents() != NULL; } // MediaGalleriesDialogViewsController ----------------------------------------- // static MediaGalleriesDialog* MediaGalleriesDialog::Create( MediaGalleriesDialogController* controller) { return new MediaGalleriesDialogViews(controller); }