Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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/settings_reset_prompt_dialog.h" | |
| 6 | |
| 7 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prom pt_controller.h" | |
| 8 #include "chrome/browser/ui/browser.h" | |
| 9 #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" | |
| 10 #include "chrome/browser/ui/views/frame/browser_view.h" | |
| 11 #include "chrome/browser/ui/views/toolbar/app_menu_button.h" | |
| 12 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" | |
| 13 #include "components/constrained_window/constrained_window_views.h" | |
| 14 #include "components/web_modal/web_contents_modal_dialog_host.h" | |
| 15 #include "ui/gfx/color_palette.h" | |
| 16 #include "ui/gfx/image/image.h" | |
| 17 #include "ui/gfx/paint_vector_icon.h" | |
| 18 #include "ui/gfx/text_constants.h" | |
| 19 #include "ui/gfx/vector_icons_public.h" | |
| 20 #include "ui/views/bubble/bubble_border.h" | |
| 21 #include "ui/views/controls/label.h" | |
| 22 #include "ui/views/controls/link.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 | |
| 31 namespace safe_browsing { | |
| 32 | |
| 33 // static | |
| 34 void SettingsResetPromptController::ShowSettingsResetPrompt( | |
| 35 Browser* browser, | |
| 36 SettingsResetPromptController* controller) { | |
| 37 SettingsResetPromptDialog* dialog = new SettingsResetPromptDialog(controller); | |
| 38 // The dialog will delete itself, as implemented in | |
| 39 // |DialogDelegateView::DeleteDelegate()|, when its widget is closed. | |
| 40 dialog->Show(browser); | |
| 41 } | |
| 42 | |
| 43 } // namespace safe_browsing | |
| 44 | |
| 45 namespace { | |
| 46 | |
| 47 constexpr int kDialogWidth = 512; | |
| 48 constexpr int kDetailsSectionMaxHeight = 150; | |
| 49 constexpr int kBulletColumnWidth = 5; | |
| 50 | |
| 51 //////////////////////////////////////////////////////////////////////////////// | |
| 52 // SimpleMessageView | |
| 53 // | |
| 54 // A simple view that displays two types of labels: multiline labels or indented | |
| 55 // single-line labels that are indented and start with a bullet point. The | |
| 56 // indented text is intended to be used to display setting values (URLs) and is | |
| 57 // elided if the text is too wide to fit in its entirety. | |
| 58 class SimpleMessageView : public views::View { | |
|
sky
2017/02/23 04:27:31
Do you really need a view subclass here? It seems
alito
2017/02/23 05:37:08
SimpleMessageView is used both in the main dialog
sky
2017/02/23 18:44:52
My main concern here is your are subclassing but n
alito
2017/02/24 00:19:09
Ah, I see your point. Makes sense not to subclass
| |
| 59 public: | |
| 60 explicit SimpleMessageView(int top_vertical_spacing); | |
| 61 ~SimpleMessageView() override; | |
| 62 | |
| 63 void AddLabel(const safe_browsing::SettingsResetPromptController::LabelInfo& | |
| 64 label_info); | |
| 65 | |
| 66 private: | |
| 67 static constexpr int kMainColumSetId = 0; | |
| 68 static constexpr int kBulletColumnSetId = 1; | |
| 69 | |
| 70 views::GridLayout* layout_; | |
| 71 bool first_label_; | |
| 72 bool last_label_was_bullet_; | |
| 73 | |
| 74 DISALLOW_COPY_AND_ASSIGN(SimpleMessageView); | |
| 75 }; | |
| 76 | |
| 77 SimpleMessageView::SimpleMessageView(int top_vertical_spacing) | |
| 78 : layout_(new views::GridLayout(this)), | |
| 79 first_label_(true), | |
| 80 last_label_was_bullet_(false) { | |
| 81 SetLayoutManager(layout_); | |
| 82 | |
| 83 views::ColumnSet* main_column_set = layout_->AddColumnSet(kMainColumSetId); | |
| 84 main_column_set->AddColumn(views::GridLayout::FILL, | |
| 85 views::GridLayout::LEADING, | |
| 86 /*resize_percent=*/1, views::GridLayout::USE_PREF, | |
| 87 /*fixed_width=*/0, | |
| 88 /*min_width=*/0); | |
| 89 | |
| 90 views::ColumnSet* bullet_column_set_ = | |
| 91 layout_->AddColumnSet(kBulletColumnSetId); | |
| 92 bullet_column_set_->AddPaddingColumn( | |
| 93 /*resize_percent=*/0, views::kUnrelatedControlLargeHorizontalSpacing); | |
| 94 bullet_column_set_->AddColumn( | |
| 95 views::GridLayout::FILL, views::GridLayout::LEADING, | |
| 96 /*resize_percent=*/0, views::GridLayout::USE_PREF, | |
| 97 /*fixed_width=*/0, | |
| 98 /*min_width=*/0); | |
| 99 bullet_column_set_->AddPaddingColumn(/*resize_percent=*/0, | |
| 100 kBulletColumnWidth); | |
| 101 bullet_column_set_->AddColumn( | |
| 102 views::GridLayout::FILL, views::GridLayout::LEADING, | |
| 103 /*resize_percent=*/1, views::GridLayout::USE_PREF, | |
| 104 /*fixed_width=*/0, | |
| 105 /*min_width=*/0); | |
| 106 | |
| 107 if (top_vertical_spacing > 0) | |
| 108 layout_->AddPaddingRow(/*vertical_resize=*/0, top_vertical_spacing); | |
| 109 } | |
| 110 | |
| 111 SimpleMessageView::~SimpleMessageView() {} | |
| 112 | |
| 113 void SimpleMessageView::AddLabel( | |
| 114 const safe_browsing::SettingsResetPromptController::LabelInfo& label_info) { | |
| 115 static const base::char16 kBulletPoint[] = {0x2022, 0}; | |
| 116 | |
| 117 const bool is_bullet = | |
| 118 label_info.type == | |
| 119 safe_browsing::SettingsResetPromptController::LabelInfo::BULLET_ITEM; | |
| 120 views::Label* label = new views::Label(label_info.text); | |
| 121 label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 122 if (is_bullet) { | |
| 123 label->SetElideBehavior(gfx::ELIDE_TAIL); | |
| 124 } else { | |
| 125 label->SetMultiLine(true); | |
| 126 } | |
| 127 | |
| 128 // Do not add a padding row if | |
| 129 // - this is the first label being added, or | |
| 130 // - a bullet item is being added and the last label was also a bullet item. | |
| 131 if (!(first_label_ || (is_bullet && last_label_was_bullet_))) | |
| 132 layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
| 133 | |
| 134 layout_->StartRow(0, is_bullet ? kBulletColumnSetId : kMainColumSetId); | |
| 135 if (is_bullet) { | |
| 136 views::Label* bullet = new views::Label(base::string16(kBulletPoint)); | |
| 137 layout_->AddView(bullet); | |
| 138 } | |
| 139 layout_->AddView(label); | |
| 140 | |
| 141 last_label_was_bullet_ = is_bullet; | |
| 142 first_label_ = false; | |
| 143 } | |
| 144 | |
| 145 } // namespace | |
| 146 | |
| 147 //////////////////////////////////////////////////////////////////////////////// | |
| 148 // SettingsResetPromptDialog::ExpandableMessageView | |
| 149 // | |
| 150 // A view, whose visibilty can be toggled, and will be used for the details | |
| 151 // section the main dialog. | |
| 152 class SettingsResetPromptDialog::ExpandableMessageView : public views::View { | |
| 153 public: | |
| 154 ExpandableMessageView(); | |
| 155 ~ExpandableMessageView() override; | |
| 156 | |
| 157 void AddLabel(const safe_browsing::SettingsResetPromptController::LabelInfo& | |
| 158 label_info); | |
| 159 void ToggleShowView(); | |
| 160 bool visible() const; | |
| 161 gfx::Size GetPreferredSize() const override; | |
|
sky
2017/02/23 04:27:31
Prefix with where overrides come from.
alito
2017/02/23 05:37:08
Done.
| |
| 162 int GetHeightForWidth(int width) const override; | |
| 163 | |
| 164 private: | |
| 165 SimpleMessageView* message_view_; | |
| 166 bool visible_; | |
| 167 | |
| 168 DISALLOW_COPY_AND_ASSIGN(ExpandableMessageView); | |
| 169 }; | |
| 170 | |
| 171 SettingsResetPromptDialog::ExpandableMessageView::ExpandableMessageView() | |
| 172 : visible_(false) { | |
|
sky
2017/02/23 04:27:31
This is mildly confusing given View also has a Set
alito
2017/02/23 05:37:08
Done.
| |
| 173 views::GridLayout* layout = new views::GridLayout(this); | |
| 174 SetLayoutManager(layout); | |
| 175 | |
| 176 constexpr int kColumnId = 0; | |
| 177 views::ColumnSet* column_set = layout->AddColumnSet(kColumnId); | |
| 178 column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::LEADING, | |
| 179 /*resize_percent=*/1, views::GridLayout::USE_PREF, | |
| 180 /*fixed_width=*/0, | |
| 181 /*min_width=*/0); | |
| 182 | |
| 183 // Add a horizontal line separator. | |
| 184 layout->StartRowWithPadding( | |
| 185 /*vertical_resize=*/0, kColumnId, | |
| 186 /*padding_resize=*/0, views::kUnrelatedControlVerticalSpacing); | |
| 187 layout->AddView(new views::Separator()); | |
| 188 | |
| 189 // Add the main message view inside a scroll view. | |
| 190 message_view_ = | |
| 191 new SimpleMessageView(views::kUnrelatedControlVerticalSpacing); | |
|
sky
2017/02/23 04:27:31
Move to member initializer list.
alito
2017/02/23 05:37:08
Done.
| |
| 192 views::ScrollView* scroll_view = new views::ScrollView(); | |
| 193 scroll_view->ClipHeightTo(/*min_height=*/0, kDetailsSectionMaxHeight); | |
| 194 scroll_view->SetContents(message_view_); | |
| 195 layout->StartRow(0, kColumnId); | |
| 196 layout->AddView(scroll_view); | |
| 197 } | |
| 198 | |
| 199 SettingsResetPromptDialog::ExpandableMessageView::~ExpandableMessageView() {} | |
| 200 | |
| 201 void SettingsResetPromptDialog::ExpandableMessageView::AddLabel( | |
| 202 const safe_browsing::SettingsResetPromptController::LabelInfo& label_info) { | |
| 203 message_view_->AddLabel(label_info); | |
| 204 } | |
| 205 | |
| 206 void SettingsResetPromptDialog::ExpandableMessageView::ToggleShowView() { | |
| 207 visible_ = !visible_; | |
| 208 PreferredSizeChanged(); | |
| 209 } | |
| 210 | |
| 211 bool SettingsResetPromptDialog::ExpandableMessageView::visible() const { | |
| 212 return visible_; | |
| 213 } | |
| 214 | |
| 215 gfx::Size SettingsResetPromptDialog::ExpandableMessageView::GetPreferredSize() | |
| 216 const { | |
| 217 gfx::Size size = views::View::GetPreferredSize(); | |
| 218 return gfx::Size(size.width(), visible_ ? size.height() : 0); | |
| 219 } | |
| 220 | |
| 221 int SettingsResetPromptDialog::ExpandableMessageView::GetHeightForWidth( | |
| 222 int width) const { | |
| 223 return GetPreferredSize().height(); | |
| 224 } | |
| 225 | |
| 226 //////////////////////////////////////////////////////////////////////////////// | |
| 227 // SettingsResetPromptDialog | |
| 228 | |
| 229 SettingsResetPromptDialog::SettingsResetPromptDialog( | |
| 230 safe_browsing::SettingsResetPromptController* controller) | |
| 231 : browser_(nullptr), | |
| 232 controller_(controller), | |
| 233 details_link_(nullptr), | |
| 234 interaction_done_(false) { | |
| 235 DCHECK(controller_); | |
| 236 | |
| 237 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, | |
| 238 views::kButtonHEdgeMarginNew, | |
| 239 views::kPanelVertMargin, 0)); | |
| 240 | |
| 241 // Add the dialog's main message view. | |
| 242 SimpleMessageView* message_view = new SimpleMessageView(0); | |
| 243 for (const auto& label_info : controller_->GetMainText()) | |
| 244 message_view->AddLabel(label_info); | |
| 245 AddChildView(message_view); | |
| 246 | |
| 247 // Add the main details view that starts off not being visible. | |
| 248 details_view_ = new ExpandableMessageView(); | |
| 249 for (const auto& label_info : controller_->GetDetailsText()) | |
| 250 details_view_->AddLabel(label_info); | |
| 251 AddChildView(details_view_); | |
| 252 } | |
| 253 | |
| 254 SettingsResetPromptDialog::~SettingsResetPromptDialog() { | |
| 255 // Make sure the controller is correctly notified in case the dialog widget is | |
| 256 // closed by some other means than the dialog buttons. | |
| 257 Close(); | |
| 258 } | |
| 259 | |
| 260 void SettingsResetPromptDialog::Show(Browser* browser) { | |
| 261 DCHECK(browser); | |
| 262 browser_ = browser; | |
| 263 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); | |
| 264 constrained_window::CreateBrowserModalDialogViews( | |
| 265 this, browser_view->GetNativeWindow()) | |
| 266 ->Show(); | |
| 267 } | |
| 268 | |
| 269 // WidgetDelegate overrides. | |
| 270 | |
| 271 ui::ModalType SettingsResetPromptDialog::GetModalType() const { | |
| 272 return ui::MODAL_TYPE_WINDOW; | |
| 273 } | |
| 274 | |
| 275 bool SettingsResetPromptDialog::ShouldShowWindowIcon() const { | |
| 276 return true; | |
| 277 } | |
| 278 | |
| 279 gfx::ImageSkia SettingsResetPromptDialog::GetWindowIcon() { | |
| 280 return gfx::CreateVectorIcon(gfx::VectorIconId::WARNING, 32 /* Icon size. */, | |
| 281 gfx::kGoogleRed700); | |
| 282 } | |
| 283 | |
| 284 base::string16 SettingsResetPromptDialog::GetWindowTitle() const { | |
| 285 return controller_->GetWindowTitle(); | |
| 286 } | |
| 287 | |
| 288 // DialogModel overrides. | |
| 289 | |
| 290 int SettingsResetPromptDialog::GetDialogButtons() const { | |
| 291 return ui::DIALOG_BUTTON_OK; | |
| 292 } | |
| 293 | |
| 294 bool SettingsResetPromptDialog::ShouldDefaultButtonBeBlue() const { | |
| 295 return true; | |
| 296 } | |
| 297 | |
| 298 // DialogDelegate overrides. | |
| 299 | |
| 300 base::string16 SettingsResetPromptDialog::GetDialogButtonLabel( | |
| 301 ui::DialogButton button) const { | |
| 302 DCHECK_EQ(button, ui::DIALOG_BUTTON_OK); | |
| 303 return controller_->GetButtonLabel(); | |
| 304 } | |
| 305 | |
| 306 views::View* SettingsResetPromptDialog::CreateExtraView() { | |
| 307 // Add a "show details" link that toggles visibility of the details view. | |
| 308 details_link_ = new views::Link(controller_->GetShowDetailsLabel()); | |
| 309 details_link_->SetUnderline(false); | |
| 310 details_link_->set_listener(this); | |
| 311 return details_link_; | |
| 312 } | |
| 313 | |
| 314 bool SettingsResetPromptDialog::Accept() { | |
| 315 if (!interaction_done_) { | |
| 316 interaction_done_ = true; | |
| 317 controller_->Accept(); | |
| 318 } | |
| 319 return true; | |
| 320 } | |
| 321 | |
| 322 bool SettingsResetPromptDialog::Cancel() { | |
| 323 if (!interaction_done_) { | |
| 324 interaction_done_ = true; | |
| 325 controller_->Cancel(); | |
| 326 } | |
| 327 return true; | |
| 328 } | |
| 329 | |
| 330 bool SettingsResetPromptDialog::Close() { | |
| 331 return Cancel(); | |
| 332 } | |
| 333 | |
| 334 // View overrides. | |
| 335 | |
| 336 gfx::Size SettingsResetPromptDialog::GetPreferredSize() const { | |
| 337 return gfx::Size(kDialogWidth, GetHeightForWidth(kDialogWidth)); | |
| 338 } | |
| 339 | |
| 340 // LinkListener overrides. | |
| 341 | |
| 342 void SettingsResetPromptDialog::LinkClicked(views::Link* source, | |
| 343 int event_flags) { | |
| 344 DCHECK_EQ(source, details_link_); | |
| 345 DCHECK(browser_); | |
| 346 | |
| 347 details_view_->ToggleShowView(); | |
| 348 details_link_->SetText(details_view_->visible() | |
| 349 ? controller_->GetHideDetailsLabel() | |
| 350 : controller_->GetShowDetailsLabel()); | |
| 351 | |
| 352 ChromeWebModalDialogManagerDelegate* manager = browser_; | |
| 353 constrained_window::UpdateWidgetModalDialogPosition( | |
| 354 GetWidget(), manager->GetWebContentsModalDialogHost()); | |
| 355 } | |
| OLD | NEW |