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

Side by Side Diff: ui/views/controls/label.cc

Issue 222033002: Add an 'obscured' flag to views::Label. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Test. Created 6 years, 8 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/label.h" 5 #include "ui/views/controls/label.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/i18n/rtl.h" 12 #include "base/i18n/rtl.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/strings/string_split.h" 14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
17 #include "ui/accessibility/ax_view_state.h" 17 #include "ui/accessibility/ax_view_state.h"
18 #include "ui/base/resource/resource_bundle.h" 18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/canvas.h" 19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/color_utils.h" 20 #include "ui/gfx/color_utils.h"
21 #include "ui/gfx/insets.h" 21 #include "ui/gfx/insets.h"
22 #include "ui/gfx/shadow_value.h" 22 #include "ui/gfx/shadow_value.h"
23 #include "ui/gfx/text_elider.h" 23 #include "ui/gfx/text_elider.h"
24 #include "ui/gfx/text_utils.h" 24 #include "ui/gfx/text_utils.h"
25 #include "ui/gfx/utf16_indexing.h"
25 #include "ui/native_theme/native_theme.h" 26 #include "ui/native_theme/native_theme.h"
26 #include "ui/views/background.h" 27 #include "ui/views/background.h"
27 28
28 namespace { 29 namespace {
29 30
30 const int kCachedSizeLimit = 10; 31 const int kCachedSizeLimit = 10;
32 const base::char16 kPasswordReplacementChar = '*';
31 33
32 } // namespace 34 } // namespace
33 35
34 namespace views { 36 namespace views {
35 37
36 // static 38 // static
37 const char Label::kViewClassName[] = "Label"; 39 const char Label::kViewClassName[] = "Label";
38 const int Label::kFocusBorderPadding = 1; 40 const int Label::kFocusBorderPadding = 1;
39 41
40 Label::Label() { 42 Label::Label() {
(...skipping 12 matching lines...) Expand all
53 } 55 }
54 56
55 void Label::SetFontList(const gfx::FontList& font_list) { 57 void Label::SetFontList(const gfx::FontList& font_list) {
56 font_list_ = font_list; 58 font_list_ = font_list;
57 ResetCachedSize(); 59 ResetCachedSize();
58 PreferredSizeChanged(); 60 PreferredSizeChanged();
59 SchedulePaint(); 61 SchedulePaint();
60 } 62 }
61 63
62 void Label::SetText(const base::string16& text) { 64 void Label::SetText(const base::string16& text) {
63 if (text == text_) 65 if (text == text_)
msw 2014/04/03 18:27:48 nit: flip the condition and drop the return statem
Mike West 2014/04/04 07:05:16 Done.
64 return; 66 return;
67 SetTextInternal(text);
68 }
69
70 void Label::SetTextInternal(const base::string16& text) {
65 text_ = text; 71 text_ = text;
72
73 if (is_obscured_) {
74 size_t obscured_text_length =
75 static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length()));
76 layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
77 } else {
78 layout_text_ = text_;
79 }
80
66 ResetCachedSize(); 81 ResetCachedSize();
67 PreferredSizeChanged(); 82 PreferredSizeChanged();
68 SchedulePaint(); 83 SchedulePaint();
69 } 84 }
70 85
71 void Label::SetAutoColorReadabilityEnabled(bool enabled) { 86 void Label::SetAutoColorReadabilityEnabled(bool enabled) {
72 auto_color_readability_ = enabled; 87 auto_color_readability_ = enabled;
73 RecalculateColors(); 88 RecalculateColors();
74 } 89 }
75 90
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 DCHECK(!multi_line || (elide_behavior_ != ELIDE_IN_MIDDLE && 148 DCHECK(!multi_line || (elide_behavior_ != ELIDE_IN_MIDDLE &&
134 elide_behavior_ != ELIDE_AT_BEGINNING)); 149 elide_behavior_ != ELIDE_AT_BEGINNING));
135 if (multi_line != is_multi_line_) { 150 if (multi_line != is_multi_line_) {
136 is_multi_line_ = multi_line; 151 is_multi_line_ = multi_line;
137 ResetCachedSize(); 152 ResetCachedSize();
138 PreferredSizeChanged(); 153 PreferredSizeChanged();
139 SchedulePaint(); 154 SchedulePaint();
140 } 155 }
141 } 156 }
142 157
158 void Label::SetObscured(bool obscured) {
159 if (obscured != is_obscured_) {
160 is_obscured_ = obscured;
161 SetTextInternal(text_);
162 }
163 }
164
143 void Label::SetAllowCharacterBreak(bool allow_character_break) { 165 void Label::SetAllowCharacterBreak(bool allow_character_break) {
144 if (allow_character_break != allow_character_break_) { 166 if (allow_character_break != allow_character_break_) {
145 allow_character_break_ = allow_character_break; 167 allow_character_break_ = allow_character_break;
146 ResetCachedSize(); 168 ResetCachedSize();
147 PreferredSizeChanged(); 169 PreferredSizeChanged();
148 SchedulePaint(); 170 SchedulePaint();
149 } 171 }
150 } 172 }
151 173
152 void Label::SetElideBehavior(ElideBehavior elide_behavior) { 174 void Label::SetElideBehavior(ElideBehavior elide_behavior) {
153 DCHECK(elide_behavior != ELIDE_IN_MIDDLE || !is_multi_line_); 175 DCHECK(elide_behavior != ELIDE_IN_MIDDLE || !is_multi_line_);
154 if (elide_behavior != elide_behavior_) { 176 if (elide_behavior != elide_behavior_) {
155 elide_behavior_ = elide_behavior; 177 elide_behavior_ = elide_behavior;
156 ResetCachedSize(); 178 ResetCachedSize();
157 PreferredSizeChanged(); 179 PreferredSizeChanged();
158 SchedulePaint(); 180 SchedulePaint();
159 } 181 }
160 } 182 }
161 183
162 void Label::SetTooltipText(const base::string16& tooltip_text) { 184 void Label::SetTooltipText(const base::string16& tooltip_text) {
163 tooltip_text_ = tooltip_text; 185 tooltip_text_ = tooltip_text;
164 } 186 }
165 187
166 void Label::SizeToFit(int max_width) { 188 void Label::SizeToFit(int max_width) {
167 DCHECK(is_multi_line_); 189 DCHECK(is_multi_line_);
168 190
169 std::vector<base::string16> lines; 191 std::vector<base::string16> lines;
170 base::SplitString(text_, '\n', &lines); 192 base::SplitString(layout_text(), '\n', &lines);
171 193
172 int label_width = 0; 194 int label_width = 0;
173 for (std::vector<base::string16>::const_iterator iter = lines.begin(); 195 for (std::vector<base::string16>::const_iterator iter = lines.begin();
174 iter != lines.end(); ++iter) { 196 iter != lines.end(); ++iter) {
175 label_width = std::max(label_width, gfx::GetStringWidth(*iter, font_list_)); 197 label_width = std::max(label_width, gfx::GetStringWidth(*iter, font_list_));
176 } 198 }
177 199
178 label_width += GetInsets().width(); 200 label_width += GetInsets().width();
179 201
180 if (max_width > 0) 202 if (max_width > 0)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 for (size_t i = 0; i < cached_heights_.size(); ++i) { 257 for (size_t i = 0; i < cached_heights_.size(); ++i) {
236 const gfx::Size& s = cached_heights_[i]; 258 const gfx::Size& s = cached_heights_[i];
237 if (s.width() == w) 259 if (s.width() == w)
238 return s.height() + GetInsets().height(); 260 return s.height() + GetInsets().height();
239 } 261 }
240 262
241 int cache_width = w; 263 int cache_width = w;
242 264
243 int h = font_list_.GetHeight(); 265 int h = font_list_.GetHeight();
244 const int flags = ComputeDrawStringFlags(); 266 const int flags = ComputeDrawStringFlags();
245 gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags); 267 gfx::Canvas::SizeStringInt(
268 layout_text(), font_list_, &w, &h, line_height_, flags);
246 cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h); 269 cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h);
247 cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit; 270 cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit;
248 return h + GetInsets().height(); 271 return h + GetInsets().height();
249 } 272 }
250 273
251 const char* Label::GetClassName() const { 274 const char* Label::GetClassName() const {
252 return kViewClassName; 275 return kViewClassName;
253 } 276 }
254 277
255 View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) { 278 View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) {
(...skipping 19 matching lines...) Expand all
275 DCHECK(tooltip); 298 DCHECK(tooltip);
276 299
277 // If a tooltip has been explicitly set, use it. 300 // If a tooltip has been explicitly set, use it.
278 if (!tooltip_text_.empty()) { 301 if (!tooltip_text_.empty()) {
279 tooltip->assign(tooltip_text_); 302 tooltip->assign(tooltip_text_);
280 return true; 303 return true;
281 } 304 }
282 305
283 // Show the full text if the text does not fit. 306 // Show the full text if the text does not fit.
284 if (ShouldShowDefaultTooltip()) { 307 if (ShouldShowDefaultTooltip()) {
285 *tooltip = text_; 308 *tooltip = layout_text();
286 return true; 309 return true;
287 } 310 }
288 311
289 return false; 312 return false;
290 } 313 }
291 314
292 void Label::GetAccessibleState(ui::AXViewState* state) { 315 void Label::GetAccessibleState(ui::AXViewState* state) {
293 state->role = ui::AX_ROLE_STATIC_TEXT; 316 state->role = ui::AX_ROLE_STATIC_TEXT;
294 state->AddStateFlag(ui::AX_STATE_READ_ONLY); 317 state->AddStateFlag(ui::AX_STATE_READ_ONLY);
295 state->name = text_; 318 state->name = layout_text();
296 } 319 }
297 320
298 void Label::PaintText(gfx::Canvas* canvas, 321 void Label::PaintText(gfx::Canvas* canvas,
299 const base::string16& text, 322 const base::string16& text,
300 const gfx::Rect& text_bounds, 323 const gfx::Rect& text_bounds,
301 int flags) { 324 int flags) {
302 gfx::ShadowValues shadows; 325 gfx::ShadowValues shadows;
303 if (has_shadow_) 326 if (has_shadow_)
304 shadows.push_back(gfx::ShadowValue(shadow_offset_, 0, 327 shadows.push_back(gfx::ShadowValue(shadow_offset_, 0,
305 enabled() ? enabled_shadow_color_ : disabled_shadow_color_)); 328 enabled() ? enabled_shadow_color_ : disabled_shadow_color_));
(...skipping 15 matching lines...) Expand all
321 // SizeStringInt() to calculate the desired width, it doesn't seem to work 344 // SizeStringInt() to calculate the desired width, it doesn't seem to work
322 // on Linux. 345 // on Linux.
323 int w = is_multi_line_ ? 346 int w = is_multi_line_ ?
324 GetAvailableRect().width() : std::numeric_limits<int>::max(); 347 GetAvailableRect().width() : std::numeric_limits<int>::max();
325 int h = font_list_.GetHeight(); 348 int h = font_list_.GetHeight();
326 // For single-line strings, ignore the available width and calculate how 349 // For single-line strings, ignore the available width and calculate how
327 // wide the text wants to be. 350 // wide the text wants to be.
328 int flags = ComputeDrawStringFlags(); 351 int flags = ComputeDrawStringFlags();
329 if (!is_multi_line_) 352 if (!is_multi_line_)
330 flags |= gfx::Canvas::NO_ELLIPSIS; 353 flags |= gfx::Canvas::NO_ELLIPSIS;
331 gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags); 354 gfx::Canvas::SizeStringInt(
355 layout_text(), font_list_, &w, &h, line_height_, flags);
332 text_size_.SetSize(w, h); 356 text_size_.SetSize(w, h);
333 text_size_valid_ = true; 357 text_size_valid_ = true;
334 } 358 }
335 359
336 return text_size_; 360 return text_size_;
337 } 361 }
338 362
339 void Label::OnBoundsChanged(const gfx::Rect& previous_bounds) { 363 void Label::OnBoundsChanged(const gfx::Rect& previous_bounds) {
340 text_size_valid_ &= !is_multi_line_; 364 text_size_valid_ &= !is_multi_line_;
341 } 365 }
(...skipping 17 matching lines...) Expand all
359 } 383 }
360 384
361 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { 385 void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
362 font_list_ = font_list; 386 font_list_ = font_list;
363 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; 387 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false;
364 auto_color_readability_ = true; 388 auto_color_readability_ = true;
365 UpdateColorsFromTheme(ui::NativeTheme::instance()); 389 UpdateColorsFromTheme(ui::NativeTheme::instance());
366 horizontal_alignment_ = gfx::ALIGN_CENTER; 390 horizontal_alignment_ = gfx::ALIGN_CENTER;
367 line_height_ = 0; 391 line_height_ = 0;
368 is_multi_line_ = false; 392 is_multi_line_ = false;
393 is_obscured_ = false;
369 allow_character_break_ = false; 394 allow_character_break_ = false;
370 elide_behavior_ = ELIDE_AT_END; 395 elide_behavior_ = ELIDE_AT_END;
371 collapse_when_hidden_ = false; 396 collapse_when_hidden_ = false;
372 directionality_mode_ = USE_UI_DIRECTIONALITY; 397 directionality_mode_ = USE_UI_DIRECTIONALITY;
373 enabled_shadow_color_ = 0; 398 enabled_shadow_color_ = 0;
374 disabled_shadow_color_ = 0; 399 disabled_shadow_color_ = 0;
375 shadow_offset_.SetPoint(1, 1); 400 shadow_offset_.SetPoint(1, 1);
376 has_shadow_ = false; 401 has_shadow_ = false;
377 cached_heights_.resize(kCachedSizeLimit); 402 cached_heights_.resize(kCachedSizeLimit);
378 ResetCachedSize(); 403 ResetCachedSize();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 448
424 int Label::ComputeDrawStringFlags() const { 449 int Label::ComputeDrawStringFlags() const {
425 int flags = 0; 450 int flags = 0;
426 451
427 // We can't use subpixel rendering if the background is non-opaque. 452 // We can't use subpixel rendering if the background is non-opaque.
428 if (SkColorGetA(background_color_) != 0xFF) 453 if (SkColorGetA(background_color_) != 0xFF)
429 flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING; 454 flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
430 455
431 if (directionality_mode_ == AUTO_DETECT_DIRECTIONALITY) { 456 if (directionality_mode_ == AUTO_DETECT_DIRECTIONALITY) {
432 base::i18n::TextDirection direction = 457 base::i18n::TextDirection direction =
433 base::i18n::GetFirstStrongCharacterDirection(text_); 458 base::i18n::GetFirstStrongCharacterDirection(layout_text());
434 if (direction == base::i18n::RIGHT_TO_LEFT) 459 if (direction == base::i18n::RIGHT_TO_LEFT)
435 flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY; 460 flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
436 else 461 else
437 flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 462 flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
438 } 463 }
439 464
440 switch (horizontal_alignment_) { 465 switch (horizontal_alignment_) {
441 case gfx::ALIGN_LEFT: 466 case gfx::ALIGN_LEFT:
442 flags |= gfx::Canvas::TEXT_ALIGN_LEFT; 467 flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
443 break; 468 break;
(...skipping 30 matching lines...) Expand all
474 } 499 }
475 500
476 void Label::CalculateDrawStringParams(base::string16* paint_text, 501 void Label::CalculateDrawStringParams(base::string16* paint_text,
477 gfx::Rect* text_bounds, 502 gfx::Rect* text_bounds,
478 int* flags) const { 503 int* flags) const {
479 DCHECK(paint_text && text_bounds && flags); 504 DCHECK(paint_text && text_bounds && flags);
480 505
481 // TODO(msw): Use ElideRectangleText to support eliding multi-line text. Once 506 // TODO(msw): Use ElideRectangleText to support eliding multi-line text. Once
482 // this is done, we can set NO_ELLIPSIS unconditionally at the bottom. 507 // this is done, we can set NO_ELLIPSIS unconditionally at the bottom.
483 if (is_multi_line_ || (elide_behavior_ == NO_ELIDE)) { 508 if (is_multi_line_ || (elide_behavior_ == NO_ELIDE)) {
484 *paint_text = text_; 509 *paint_text = layout_text();
485 } else if (elide_behavior_ == ELIDE_AT_BEGINNING) { 510 } else if (elide_behavior_ == ELIDE_AT_BEGINNING) {
486 *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(), 511 *paint_text = gfx::ElideText(layout_text(),
512 font_list_,
513 GetAvailableRect().width(),
487 gfx::ELIDE_AT_BEGINNING); 514 gfx::ELIDE_AT_BEGINNING);
488 } else if (elide_behavior_ == ELIDE_IN_MIDDLE) { 515 } else if (elide_behavior_ == ELIDE_IN_MIDDLE) {
489 *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(), 516 *paint_text = gfx::ElideText(layout_text(),
517 font_list_,
518 GetAvailableRect().width(),
490 gfx::ELIDE_IN_MIDDLE); 519 gfx::ELIDE_IN_MIDDLE);
491 } else if (elide_behavior_ == ELIDE_AT_END) { 520 } else if (elide_behavior_ == ELIDE_AT_END) {
492 *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(), 521 *paint_text = gfx::ElideText(layout_text(),
522 font_list_,
523 GetAvailableRect().width(),
493 gfx::ELIDE_AT_END); 524 gfx::ELIDE_AT_END);
494 } else { 525 } else {
495 DCHECK_EQ(ELIDE_AS_EMAIL, elide_behavior_); 526 DCHECK_EQ(ELIDE_AS_EMAIL, elide_behavior_);
496 *paint_text = gfx::ElideEmail(text_, font_list_, 527 *paint_text =
497 GetAvailableRect().width()); 528 gfx::ElideEmail(layout_text(), font_list_, GetAvailableRect().width());
498 } 529 }
499 530
500 *text_bounds = GetTextBounds(); 531 *text_bounds = GetTextBounds();
501 *flags = ComputeDrawStringFlags(); 532 *flags = ComputeDrawStringFlags();
502 if (!is_multi_line_ || (elide_behavior_ == NO_ELIDE)) 533 if (!is_multi_line_ || (elide_behavior_ == NO_ELIDE))
503 *flags |= gfx::Canvas::NO_ELLIPSIS; 534 *flags |= gfx::Canvas::NO_ELLIPSIS;
504 } 535 }
505 536
506 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { 537 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
507 if (!enabled_color_set_) { 538 if (!enabled_color_set_) {
(...skipping 12 matching lines...) Expand all
520 } 551 }
521 552
522 void Label::ResetCachedSize() { 553 void Label::ResetCachedSize() {
523 text_size_valid_ = false; 554 text_size_valid_ = false;
524 cached_heights_cursor_ = 0; 555 cached_heights_cursor_ = 0;
525 for (int i = 0; i < kCachedSizeLimit; ++i) 556 for (int i = 0; i < kCachedSizeLimit; ++i)
526 cached_heights_[i] = gfx::Size(); 557 cached_heights_[i] = gfx::Size();
527 } 558 }
528 559
529 bool Label::ShouldShowDefaultTooltip() const { 560 bool Label::ShouldShowDefaultTooltip() const {
530 return !is_multi_line_ && 561 return !is_multi_line_ && !is_obscured_ &&
531 gfx::GetStringWidth(text_, font_list_) > GetAvailableRect().width(); 562 gfx::GetStringWidth(layout_text(), font_list_) >
563 GetAvailableRect().width();
532 } 564 }
533 565
534 } // namespace views 566 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698