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

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

Powered by Google App Engine
This is Rietveld 408576698