Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: chrome/browser/ui/views/settings_reset_prompt_dialog.cc

Issue 2701313002: Adds a modal dialog implementation of the settings reset prompt. (Closed)
Patch Set: Addressed sky@'s comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698