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