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

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

Issue 12317109: Add a dialog for getting user consent in the echo redeem flow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: forgot to add echo_dialog_listener file Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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/echo_dialog_views_chromeos.h"
6
7 #include "chrome/browser/ui/echo_dialog_listener_chromeos.h"
8 #include "grit/generated_resources.h"
9 #include "ui/base/l10n/l10n_util.h"
10 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/base/text/text_elider.h"
12 #include "ui/views/controls/label.h"
13 #include "ui/views/controls/link.h"
14 #include "ui/views/layout/box_layout.h"
15 #include "ui/views/widget/widget.h"
16 #include "ui/views/window/dialog_client_view.h"
17
18 namespace {
19
20 const int kDialogContentWidth = 350;
21
22 const int kDialogContentTopInset = 20;
23 const int kDialogContentLeftInset = 20;
24 const int kDialogContentBottomInset = 20;
25 const int kDialogContentRightInset = 100;
26
27 const int kLinkLeftInset = 5;
28
29 // Dialog text has medium sized font.
30 gfx::Font GetDefaultFontForEcho() {
31 return ui::ResourceBundle::GetSharedInstance().GetFont(
32 ui::ResourceBundle::MediumFont);
33 }
34
35 // Label that shows the service name label.
36 // The label should have underlined text and display tooltip on hover.
37 class EchoServiceNameLabel : public views::Label {
38 public:
39 EchoServiceNameLabel(const string16& label, const string16& tooltip)
40 : views::Label(label) {
41 SetTooltipText(tooltip);
42 SetMultiLine(false);
43 SetFont(GetDefaultFontForEcho().DeriveFont(0, gfx::Font::UNDERLINE));
44 }
45 virtual ~EchoServiceNameLabel() {}
46
47 // views::Label override.
48 // Label have HitTestRect return false by default. To be able to show a
49 // tooltip, this should be overriden.
50 virtual bool HitTestRect(const gfx::Rect& rect) const {
sky 2013/02/26 21:28:48 This is a bug in Label, it should be fixed there.
tbarzic 2013/02/26 23:08:50 ok, I'll upload a cl to fix this in label
tbarzic 2013/03/18 18:21:58 Done.
51 return GetLocalBounds().Intersects(rect);
52 }
53
54 private:
55 DISALLOW_COPY_AND_ASSIGN(EchoServiceNameLabel);
56 };
57
58 // A helper view that contains horizontal set of labels representing one row of
59 // the dialog text content. The number of labels is not limited, but their
60 // combined width will be smaller than |kDialogContentWidth|.
61 class EchoDialogContentRowView : public views::View {
62 public:
63 EchoDialogContentRowView() {
64 SetLayoutManager(
65 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
66 }
67
68 virtual ~EchoDialogContentRowView() {}
69
70 private:
71 DISALLOW_COPY_AND_ASSIGN(EchoDialogContentRowView);
72 };
73
74 // View representing text content of the dialog. It consists of set of
75 // vertically laid out |EchoDialogContentRowView| views with limited width. The
76 // rows are filled with text pieces that should be displayed using different
77 // styles.
78 class EchoDialogContentView : public views::View {
sky 2013/02/26 21:28:48 Is there a reason not to use label directly? If yo
tbarzic 2013/02/26 23:08:50 It's also the label types are different: only part
sky 2013/02/27 00:38:35 2013/02/26 23:08:50, tbarzic wrote:
79 public:
80 explicit EchoDialogContentView(views::LinkListener* listener);
81 virtual ~EchoDialogContentView() {}
82
83 // Creates text pieces that represent the content shown in the dialog when
84 // echo extension is enabled to redeem offers.
85 //
86 // General layout of the dialog in this case is:
87 //
88 // --------------------------------------------------------------
89 // | ----------------- ---------------- ----------------- |
90 // | | normal text 1 | | service name | | normal text 2 | |
91 // | ----------------- ---------------- ----------------- |
92 // | ---------------------------------------------------------- |
93 // | | normal text 2 | |
94 // | ---------------------------------------------------------- |
95 // | ----------------- --------------------- |
96 // | | normal text 2 | | 'More info' link | |
97 // | ----------------- --------------------- |
98 // --------------------------------------------------------------
99 //
100 // Where 'normal text' is predetermined text of type TEXT_PIECE_LABEL,
101 // 'service name' equals |service_name| and is of type
102 // TEXT_PIECE_SERVICE_NAME_LABEL. Hovering over the 'service name' label will
103 // display tooltip whose content equals |origin|.
104 // Note that the labels may be broken up, preferably at word delimiters (this
105 // is not possible for words that are too long).
106 void InitializeForEnabledEcho(const string16& service_name,
107 const string16& origin);
108
109 // Creates text pieces that represent the content shown in the dialog when
110 // echo extension is not allowed to redeem offers.
111 //
112 // General layout of the dialog in this case is:
113 //
114 // --------------------------------------------------------------
115 // | ---------------------------------------------------------- |
116 // | | normal text 1 | |
117 // | ---------------------------------------------------------- |
118 // | ----------------- --------------------- |
119 // | | normal text 1 | | 'More info' link | |
120 // | ----------------- --------------------- |
121 // --------------------------------------------------------------
122 //
123 // With the same parts as for the enabled echo.
124 void InitializeForDisabledEcho();
125
126 // Creates layout with text pieces initialized in
127 // |InitializeFor{Disabled|Enabled}Echo|.
128 void SetupLayout();
129
130 private:
131 enum TextPieceType {
132 TEXT_PIECE_INVALID,
133 TEXT_PIECE_LABEL,
134 TEXT_PIECE_SERVICE_NAME_LABEL,
135 TEXT_PIECE_LINK
136 };
137
138 // Information about a text piece that should be shown in the dialog.
139 struct TextPieceInfo {
140 TextPieceInfo() : type(TEXT_PIECE_INVALID) {}
141 TextPieceInfo(const string16& label,
142 TextPieceType type)
143 : label(label),
144 type(type) {
145 }
146
147 string16 label;
148 TextPieceType type;
149 };
150
151 // Adds text piece described with |info| to the |current_row|.
152 // If the whole text piece doesn't fit in the row, the row is filled with as
153 // much of words from the text piece as possible. New row are created and
154 // filled with text pieces content until the whole text piece is added to the
155 // layout.
156 // Upon completion |current_row| will be set to the last added row.
157 void SetupTextPieceLayout(const TextPieceInfo& info,
158 EchoDialogContentRowView** current_row);
159 // Creates a label view for text piece of type |type| with content |text|.
160 // |at_row_start| is set if the text_piece would be the first text piece in
161 // the row. Links are added additional padding if they are not at the row
162 // start.
163 views::Label* CreateTextPieceView(TextPieceType type,
164 const string16& label,
165 bool at_row_start);
166
167 string16 service_origin_;
168 // Listener invoked when a label of type link is clicked.
169 views::LinkListener* link_listener_;
170 // Dialog content divided into pieces with different display stype.
171 std::vector<TextPieceInfo> text_pieces_;
172
173 DISALLOW_COPY_AND_ASSIGN(EchoDialogContentView);
174 };
175
176 EchoDialogContentView::EchoDialogContentView(views::LinkListener* link_listener)
177 : link_listener_(link_listener) {
178 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0 ,0));
179 }
180
181 void EchoDialogContentView::InitializeForEnabledEcho(
182 const string16& service_name,
183 const string16& origin) {
184 service_origin_ = origin;
185
186 size_t service_name_offset = 0;
187 string16 text = l10n_util::GetStringFUTF16(IDS_ECHO_CONSENT_DIALOG_TEXT,
188 service_name,
189 &service_name_offset);
190
191 text_pieces_.push_back(
192 TextPieceInfo(text.substr(0, service_name_offset), TEXT_PIECE_LABEL));
193 text_pieces_.push_back(
194 TextPieceInfo(service_name, TEXT_PIECE_SERVICE_NAME_LABEL));
195 text_pieces_.push_back(
196 TextPieceInfo(text.substr(service_name_offset + service_name.length()),
197 TEXT_PIECE_LABEL));
198 text_pieces_.push_back(TextPieceInfo(
199 l10n_util::GetStringUTF16(IDS_OFFERS_CONSENT_INFOBAR_LABEL_LEARN_MORE),
200 TEXT_PIECE_LINK));
201 }
202
203 void EchoDialogContentView::InitializeForDisabledEcho() {
204 text_pieces_.push_back(TextPieceInfo(
205 l10n_util::GetStringUTF16(IDS_ECHO_DISABLED_CONSENT_DIALOG_TEXT),
206 TEXT_PIECE_LABEL));
207 text_pieces_.push_back(TextPieceInfo(
208 l10n_util::GetStringUTF16(IDS_OFFERS_CONSENT_INFOBAR_LABEL_LEARN_MORE),
209 TEXT_PIECE_LINK));
210 }
211
212 void EchoDialogContentView::SetupLayout() {
213 EchoDialogContentRowView* current_row = new EchoDialogContentRowView();
214 AddChildView(current_row);
215 for (size_t i= 0; i < text_pieces_.size(); ++i)
216 SetupTextPieceLayout(text_pieces_[i], &current_row);
217
218 set_border(views::Border::CreateEmptyBorder(kDialogContentTopInset,
219 kDialogContentLeftInset,
220 kDialogContentBottomInset,
221 kDialogContentRightInset));
222 }
223
224 void EchoDialogContentView::SetupTextPieceLayout(
225 const TextPieceInfo& info,
226 EchoDialogContentRowView** current_row) {
227 if (info.label.empty())
228 return;
229
230 gfx::Size current_size = (*current_row)->GetPreferredSize();
231
232 scoped_ptr<views::Label> text_piece(
233 CreateTextPieceView(info.type, info.label, current_size.width() == 0));
234 gfx::Size text_piece_size = text_piece->GetPreferredSize();
235
236 // If the while label can fit in the free space in the current row, just add
237 // it and return.
238 if (text_piece_size.width() + current_size.width() < kDialogContentWidth) {
239 (*current_row)->AddChildView(text_piece.release());
240 return;
241 }
242
243 string16 residue = info.label;
244 gfx::Font text_piece_font = text_piece->font();
245 std::vector<string16> lines;
246
247 // Fill up the free space in the current row. |IGNORE_LONG_WORDS| is used to
248 // ensure words don't get broken in pieces. This step can be skipped if the
249 // current row is empty.
250 if (current_size.width() > 0) {
251 ui::ElideRectangleText(info.label, text_piece_font,
252 kDialogContentWidth - current_size.width(), text_piece_size.height(),
253 ui::IGNORE_LONG_WORDS, &lines);
254 if (!lines[0].empty()) {
255 text_piece->SetText(lines[0]);
256 (*current_row)->AddChildView(text_piece.release());
257
258 // Compute the part of the text piece that still has to be added to the
259 // view layout.
260 residue = info.label.substr(lines[0].length());
261 TrimWhitespace(residue, TRIM_LEADING, &residue);
262 }
263 }
264
265 // Brake up the rest of the text piece into lines shorter than
266 // |kEchoPromtWidth|, so they can fit in a single row. Use INT_MAX so the
267 // number of lines is not limited.
268 ui::ElideRectangleText(residue, text_piece_font, kDialogContentWidth, INT_MAX,
269 ui::WRAP_LONG_WORDS, &lines);
270
271 // Add lines one by one to the layout.
272 for (size_t i = 0; i < lines.size(); ++i) {
273 if ((*current_row)->GetPreferredSize().width() > 0) {
274 *current_row = new EchoDialogContentRowView();
275 AddChildView(*current_row);
276 }
277 (*current_row)->AddChildView(CreateTextPieceView(info.type, lines[i],
278 true));
279 }
280 }
281
282 views::Label* EchoDialogContentView::CreateTextPieceView(TextPieceType type,
283 const string16& text,
284 bool at_row_start) {
285 switch (type) {
286 case TEXT_PIECE_LABEL:
287 {
288 views::Label* label = new views::Label(text);
289 label->SetMultiLine(false);
290 label->SetFont(GetDefaultFontForEcho());
291 return label;
292 }
293 case TEXT_PIECE_SERVICE_NAME_LABEL:
294 return new EchoServiceNameLabel(text, service_origin_);
295 case TEXT_PIECE_LINK:
296 {
297 views::Link* link = new views::Link(text);
298 link->set_listener(link_listener_);
299 link->SetUnderline(false);
300 link->SetFont(GetDefaultFontForEcho());
301 if (!at_row_start) {
302 link->set_border(
303 views::Border::CreateEmptyBorder(0, kLinkLeftInset, 0, 0));
304 }
305 return link;
306 }
307 default:
308 NOTREACHED();
309 return NULL;
310 }
311 }
312
313 } // namespace
314
315 EchoDialogView::EchoDialogView(EchoDialogListener* listener)
316 : listener_(listener),
317 ok_button_label_id_(0),
318 cancel_button_label_id_(0) {
319 SetLayoutManager(
320 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0 ,0));
321 }
322
323 EchoDialogView::~EchoDialogView() {}
324
325 void EchoDialogView::InitForEnabledEcho(const string16& service_name,
326 const string16& origin) {
327 ok_button_label_id_ = IDS_OFFERS_CONSENT_INFOBAR_ENABLE_BUTTON;
328 cancel_button_label_id_ = IDS_OFFERS_CONSENT_INFOBAR_DISABLE_BUTTON;
329
330 EchoDialogContentView* dialog_content = new EchoDialogContentView(this);
331 dialog_content->InitializeForEnabledEcho(service_name, origin);
332 dialog_content->SetupLayout();
333
334 AddChildView(dialog_content);
335 }
336
337 void EchoDialogView::InitForDisabledEcho() {
338 ok_button_label_id_ = 0;
339 cancel_button_label_id_ = IDS_ECHO_CONSENT_DISMISS_BUTTON;
340
341 EchoDialogContentView* dialog_content = new EchoDialogContentView(this);
342 dialog_content->InitializeForDisabledEcho();
343 dialog_content->SetupLayout();
344
345 AddChildView(dialog_content);
346 }
347
348 void EchoDialogView::Show(gfx::NativeWindow parent) {
349 DCHECK(cancel_button_label_id_);
350
351 views::DialogDelegateView::CreateDialogWidget(this, parent, parent);
352 set_border(views::Border::CreateEmptyBorder(0, 0, 10, 0));
353 GetWidget()->Show();
354 }
355
356 int EchoDialogView::GetDefaultDialogButton() const {
357 return ui::DIALOG_BUTTON_NONE;
358 }
359
360 int EchoDialogView::GetDialogButtons() const {
361 int buttons = ui::DIALOG_BUTTON_NONE;
362 if (ok_button_label_id_)
363 buttons |= ui::DIALOG_BUTTON_OK;
364 if (cancel_button_label_id_)
365 buttons |= ui::DIALOG_BUTTON_CANCEL;
366 return buttons;
367 }
368
369 bool EchoDialogView::Accept() {
370 if (listener_) {
371 listener_->OnAccept();
372 listener_ = NULL;
373 }
374 return true;
375 }
376
377 bool EchoDialogView::Cancel() {
378 if (listener_) {
379 listener_->OnCancel();
380 listener_ = NULL;
381 }
382 return true;
383 }
384
385 string16 EchoDialogView::GetDialogButtonLabel(ui::DialogButton button) const {
386 if (button == ui::DIALOG_BUTTON_OK && ok_button_label_id_)
387 return l10n_util::GetStringUTF16(ok_button_label_id_);
388 if (button == ui::DIALOG_BUTTON_CANCEL && cancel_button_label_id_)
389 return l10n_util::GetStringUTF16(cancel_button_label_id_);
390 return string16();
391 }
392
393 ui::ModalType EchoDialogView::GetModalType() const {
394 return ui::MODAL_TYPE_WINDOW;
395 }
396
397 bool EchoDialogView::ShouldShowWindowTitle() const {
398 return false;
399 }
400
401 bool EchoDialogView::ShouldShowWindowIcon() const {
402 return false;
403 }
404
405 void EchoDialogView::LinkClicked(views::Link* source, int event_flags) {
406 if (!listener_)
407 return;
408 listener_->OnMoreInfoLinkClicked();
409 }
410
411 EchoDialog* EchoDialog::Create(EchoDialogListener* listener) {
412 return new EchoDialogView(listener);
413 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698