Chromium Code Reviews| Index: chrome/browser/ui/views/settings_reset_prompt_dialog.cc |
| diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..71396782bce2fb64a4f94af481409f64b9c14f17 |
| --- /dev/null |
| +++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc |
| @@ -0,0 +1,351 @@ |
| +// Copyright 2017 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/settings_reset_prompt_dialog.h" |
| + |
| +#include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_controller.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" |
| +#include "chrome/browser/ui/views/frame/browser_view.h" |
| +#include "chrome/browser/ui/views/toolbar/app_menu_button.h" |
| +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" |
| +#include "components/constrained_window/constrained_window_views.h" |
| +#include "components/web_modal/web_contents_modal_dialog_host.h" |
| +#include "ui/gfx/color_palette.h" |
| +#include "ui/gfx/image/image.h" |
| +#include "ui/gfx/paint_vector_icon.h" |
| +#include "ui/gfx/text_constants.h" |
| +#include "ui/gfx/vector_icons_public.h" |
| +#include "ui/views/bubble/bubble_border.h" |
| +#include "ui/views/controls/label.h" |
| +#include "ui/views/controls/link.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" |
| + |
| +namespace safe_browsing { |
| + |
| +// static |
| +void SettingsResetPromptController::ShowSettingsResetPrompt( |
| + Browser* browser, |
| + SettingsResetPromptController* controller) { |
| + SettingsResetPromptDialog* dialog = new SettingsResetPromptDialog(controller); |
| + // The dialog will delete itself, as implemented in |
| + // |DialogDelegateView::DeleteDelegate()|, when its widget is closed. |
| + dialog->Show(browser); |
| +} |
| + |
| +} // namespace safe_browsing |
| + |
| +namespace { |
| + |
| +constexpr int kDialogWidth = 448; |
| +constexpr int kDetailsSectionMaxHeight = 150; |
| +constexpr int kBulletColumnWidth = 5; |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SimpleMessageView |
| +// |
| +// A simple view that displays two types of labels: multiline labels or indented |
| +// single-line labels that are indented and start with a bullet point. The |
|
sky
2017/02/21 17:37:28
How do you know the single-line label doesn't need
alito
2017/02/23 02:31:59
The indented (and bulleted) labels are used only f
|
| +// indented text is elided if the text is too wide to fit in its entirety. |
| +class SimpleMessageView : public views::View { |
| + public: |
| + explicit SimpleMessageView(int width, int top_vertical_spacing); |
| + ~SimpleMessageView() override; |
| + |
| + void AddLabel(const safe_browsing::SettingsResetPromptController::LabelInfo& |
| + label_info); |
| + gfx::Size GetPreferredSize() const override; |
| + |
| + private: |
| + static constexpr int kMainColumSetId = 0; |
| + static constexpr int kBulletColumnSetId = 1; |
| + |
| + views::GridLayout* layout_; |
| + int width_; |
| + bool first_label_; |
| + bool last_label_was_bullet_; |
| +}; |
|
sky
2017/02/21 17:37:28
DISALLOW...
alito
2017/02/23 02:31:59
Done.
|
| + |
| +SimpleMessageView::SimpleMessageView(int width, int top_vertical_spacing) |
| + : layout_(new views::GridLayout(this)), |
| + width_(width), |
| + first_label_(true), |
| + last_label_was_bullet_(false) { |
| + SetLayoutManager(layout_); |
| + |
| + views::ColumnSet* main_column_set = layout_->AddColumnSet(kMainColumSetId); |
| + main_column_set->AddColumn(views::GridLayout::FILL, |
| + views::GridLayout::LEADING, |
| + /*resize_percent=*/1, views::GridLayout::USE_PREF, |
| + /*fixed_width=*/0, |
| + /*min_width=*/0); |
| + |
| + views::ColumnSet* bullet_column_set_ = |
| + layout_->AddColumnSet(kBulletColumnSetId); |
| + bullet_column_set_->AddPaddingColumn( |
| + /*resize_percent=*/0, views::kUnrelatedControlLargeHorizontalSpacing); |
| + bullet_column_set_->AddColumn( |
| + views::GridLayout::FILL, views::GridLayout::LEADING, |
| + /*resize_percent=*/0, views::GridLayout::USE_PREF, |
| + /*fixed_width=*/0, |
| + /*min_width=*/0); |
| + bullet_column_set_->AddPaddingColumn(/*resize_percent=*/0, |
| + kBulletColumnWidth); |
| + bullet_column_set_->AddColumn( |
| + views::GridLayout::FILL, views::GridLayout::LEADING, |
| + /*resize_percent=*/1, views::GridLayout::USE_PREF, |
| + /*fixed_width=*/0, |
| + /*min_width=*/0); |
| + |
| + if (top_vertical_spacing > 0) |
| + layout_->AddPaddingRow(/*vertical_resize=*/0, top_vertical_spacing); |
| +} |
| + |
| +SimpleMessageView::~SimpleMessageView() {} |
| + |
| +void SimpleMessageView::AddLabel( |
| + const safe_browsing::SettingsResetPromptController::LabelInfo& label_info) { |
| + static const base::char16 kBulletPoint[] = {0x2022, 0}; |
| + |
| + const bool is_bullet = |
| + label_info.type == |
| + safe_browsing::SettingsResetPromptController::LabelInfo::BULLET_ITEM; |
| + views::Label* label = new views::Label(label_info.text); |
| + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| + if (is_bullet) { |
| + label->SetElideBehavior(gfx::ELIDE_TAIL); |
| + } else { |
| + label->SetMultiLine(true); |
| + } |
| + |
| + // Do not add a padding row if |
| + // - this is the first label being added, or |
| + // - a bullet item is being added and the last label was also a bullet item. |
| + if (!(first_label_ || (is_bullet && last_label_was_bullet_))) |
| + layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| + |
| + layout_->StartRow(0, is_bullet ? kBulletColumnSetId : kMainColumSetId); |
| + if (is_bullet) { |
| + views::Label* bullet = new views::Label(base::string16(kBulletPoint)); |
| + layout_->AddView(bullet); |
| + } |
| + layout_->AddView(label); |
| + |
| + last_label_was_bullet_ = is_bullet; |
| + first_label_ = false; |
| +} |
| + |
| +gfx::Size SimpleMessageView::GetPreferredSize() const { |
| + return gfx::Size(width_, views::View::GetHeightForWidth(width_)); |
| +} |
| + |
| +} // namespace |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SettingsResetPromptDialog::ExpandableMessageView |
| +// |
| +// A view, whose visibilty can be toggled, and will be used for the details |
| +// section the main dialog. |
| +class SettingsResetPromptDialog::ExpandableMessageView : public views::View { |
| + public: |
| + explicit ExpandableMessageView(int width); |
| + ~ExpandableMessageView() override; |
| + |
| + void AddLabel(const safe_browsing::SettingsResetPromptController::LabelInfo& |
| + label_info); |
| + void ToggleShowView(); |
| + bool visible() const; |
| + gfx::Size GetPreferredSize() const override; |
| + int GetHeightForWidth(int width) const override; |
| + |
| + private: |
| + SimpleMessageView* message_view_; |
| + bool visible_; |
| +}; |
| + |
| +SettingsResetPromptDialog::ExpandableMessageView::ExpandableMessageView( |
| + int width) |
| + : visible_(false) { |
| + views::GridLayout* layout = new views::GridLayout(this); |
| + SetLayoutManager(layout); |
| + |
| + constexpr int kColumnId = 0; |
| + views::ColumnSet* column_set = layout->AddColumnSet(kColumnId); |
| + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::LEADING, |
| + /*resize_percent=*/1, views::GridLayout::USE_PREF, |
| + /*fixed_width=*/0, |
| + /*min_width=*/0); |
| + |
| + // Add a horizontal line separator. |
| + layout->StartRowWithPadding( |
| + /*vertical_resize=*/0, kColumnId, |
| + /*padding_resize=*/0, views::kUnrelatedControlVerticalSpacing); |
| + layout->AddView(new views::Separator()); |
| + |
| + // Add the main message view inside a scroll view. |
| + message_view_ = |
| + new SimpleMessageView(width, views::kUnrelatedControlVerticalSpacing); |
| + views::ScrollView* scroll_view = new views::ScrollView(); |
| + scroll_view->ClipHeightTo(/*min_height=*/0, kDetailsSectionMaxHeight); |
| + scroll_view->SetContents(message_view_); |
| + layout->StartRow(0, kColumnId); |
| + layout->AddView(scroll_view); |
| +} |
| + |
| +SettingsResetPromptDialog::ExpandableMessageView::~ExpandableMessageView() {} |
| + |
| +void SettingsResetPromptDialog::ExpandableMessageView::AddLabel( |
| + const safe_browsing::SettingsResetPromptController::LabelInfo& label_info) { |
| + message_view_->AddLabel(label_info); |
| +} |
| + |
| +void SettingsResetPromptDialog::ExpandableMessageView::ToggleShowView() { |
| + visible_ = !visible_; |
| + PreferredSizeChanged(); |
| +} |
| + |
| +bool SettingsResetPromptDialog::ExpandableMessageView::visible() const { |
| + return visible_; |
| +} |
| + |
| +gfx::Size SettingsResetPromptDialog::ExpandableMessageView::GetPreferredSize() |
| + const { |
| + gfx::Size size = views::View::GetPreferredSize(); |
| + return gfx::Size(size.width(), visible_ ? size.height() : 0); |
| +} |
| + |
| +int SettingsResetPromptDialog::ExpandableMessageView::GetHeightForWidth( |
| + int width) const { |
| + return GetPreferredSize().height(); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// SettingsResetPromptDialog |
| + |
| +SettingsResetPromptDialog::SettingsResetPromptDialog( |
| + safe_browsing::SettingsResetPromptController* controller) |
| + : browser_(nullptr), controller_(controller), details_link_(nullptr) { |
| + DCHECK(controller_); |
| + |
| + SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, |
| + views::kButtonHEdgeMarginNew, |
| + views::kPanelVertMargin, 0)); |
| + |
| + // Add the dialog's main message view. |
| + SimpleMessageView* message_view = new SimpleMessageView(ContentWidth(), 0); |
| + for (const auto& label_info : controller_->GetMainText()) |
| + message_view->AddLabel(label_info); |
| + AddChildView(message_view); |
| + |
| + // Add the main details view that starts off not being visible. |
| + details_view_ = new ExpandableMessageView(ContentWidth()); |
|
sky
2017/02/21 17:37:28
Why do you need to supply the width? Shouldn't Exp
alito
2017/02/23 02:31:59
You are right. Since I'm explicitly setting the wi
|
| + for (const auto& label_info : controller_->GetDetailsText()) |
| + details_view_->AddLabel(label_info); |
| + AddChildView(details_view_); |
| +} |
| + |
| +SettingsResetPromptDialog::~SettingsResetPromptDialog() {} |
|
sky
2017/02/21 17:37:28
What happens if you get here and neither accept no
alito
2017/02/23 02:31:59
I added a call to the controller's Cancel() here.
|
| + |
| +void SettingsResetPromptDialog::Show(Browser* browser) { |
| + DCHECK(browser); |
| + browser_ = browser; |
| + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); |
| + constrained_window::CreateBrowserModalDialogViews( |
| + this, browser_view->GetNativeWindow()) |
| + ->Show(); |
| +} |
| + |
| +// WidgetDelegate overrides. |
| + |
| +ui::ModalType SettingsResetPromptDialog::GetModalType() const { |
| + return ui::MODAL_TYPE_WINDOW; |
| +} |
| + |
| +bool SettingsResetPromptDialog::ShouldShowWindowIcon() const { |
| + return true; |
| +} |
| + |
| +gfx::ImageSkia SettingsResetPromptDialog::GetWindowIcon() { |
| + return gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 32 /* Icon size. */, |
| + gfx::kGoogleRed700); |
| +} |
| + |
| +base::string16 SettingsResetPromptDialog::GetWindowTitle() const { |
| + return controller_->GetWindowTitle(); |
| +} |
| + |
| +// DialogModel overrides. |
| + |
| +int SettingsResetPromptDialog::GetDialogButtons() const { |
| + return ui::DIALOG_BUTTON_OK; |
| +} |
| + |
| +bool SettingsResetPromptDialog::ShouldDefaultButtonBeBlue() const { |
| + return true; |
| +} |
| + |
| +// DialogDelegate overrides. |
| + |
| +base::string16 SettingsResetPromptDialog::GetDialogButtonLabel( |
| + ui::DialogButton button) const { |
| + DCHECK_EQ(button, ui::DIALOG_BUTTON_OK); |
| + return controller_->GetButtonLabel(); |
| +} |
| + |
| +views::View* SettingsResetPromptDialog::CreateExtraView() { |
| + // Add a "show details" link that toggles visibility of the details view. |
| + details_link_ = new views::Link(controller_->GetShowDetailsLabel()); |
| + details_link_->SetUnderline(false); |
| + details_link_->set_listener(this); |
| + return details_link_; |
| +} |
| + |
| +bool SettingsResetPromptDialog::Accept() { |
| + controller_->Accept(); |
| + return true; |
| +} |
| + |
| +bool SettingsResetPromptDialog::Cancel() { |
| + controller_->Cancel(); |
| + return true; |
| +} |
| + |
| +bool SettingsResetPromptDialog::Close() { |
| + return Cancel(); |
|
sky
2017/02/21 17:37:28
This is the default implementation.
alito
2017/02/23 02:31:59
Actually, that is the default implementation only
|
| +} |
| + |
| +// View overrides. |
| + |
| +gfx::Size SettingsResetPromptDialog::GetPreferredSize() const { |
| + return gfx::Size(ContentWidth(), GetHeightForWidth(ContentWidth())); |
| +} |
| + |
| +// LinkListener overrides. |
| + |
| +void SettingsResetPromptDialog::LinkClicked(views::Link* source, |
| + int event_flags) { |
| + DCHECK_EQ(source, details_link_); |
| + DCHECK(browser_); |
| + |
| + details_view_->ToggleShowView(); |
| + details_link_->SetText(details_view_->visible() |
| + ? controller_->GetHideDetailsLabel() |
| + : controller_->GetShowDetailsLabel()); |
| + |
| + ChromeWebModalDialogManagerDelegate* manager = browser_; |
| + constrained_window::UpdateWidgetModalDialogPosition( |
| + GetWidget(), manager->GetWebContentsModalDialogHost()); |
| +} |
| + |
| +// Private methods. |
| + |
| +int SettingsResetPromptDialog::ContentWidth() const { |
|
sky
2017/02/21 17:37:28
Why do you need a member function for this functio
alito
2017/02/23 02:31:59
Removed.
|
| + return kDialogWidth; |
| +} |