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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cmath> | 10 #include <cmath> |
| 11 #include <limits> | 11 #include <limits> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/i18n/rtl.h" | 15 #include "base/i18n/rtl.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/profiler/scoped_tracker.h" | 17 #include "base/profiler/scoped_tracker.h" |
| 18 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 20 #include "ui/accessibility/ax_view_state.h" | 20 #include "ui/accessibility/ax_view_state.h" |
| 21 #include "ui/base/clipboard/scoped_clipboard_writer.h" | |
| 22 #include "ui/base/cursor/cursor.h" | |
| 21 #include "ui/base/default_style.h" | 23 #include "ui/base/default_style.h" |
| 22 #include "ui/base/material_design/material_design_controller.h" | 24 #include "ui/base/material_design/material_design_controller.h" |
| 23 #include "ui/base/resource/resource_bundle.h" | 25 #include "ui/base/resource/resource_bundle.h" |
| 24 #include "ui/gfx/canvas.h" | 26 #include "ui/gfx/canvas.h" |
| 25 #include "ui/gfx/color_utils.h" | 27 #include "ui/gfx/color_utils.h" |
| 26 #include "ui/gfx/geometry/insets.h" | 28 #include "ui/gfx/geometry/insets.h" |
| 27 #include "ui/gfx/text_elider.h" | 29 #include "ui/gfx/text_elider.h" |
| 28 #include "ui/native_theme/native_theme.h" | 30 #include "ui/native_theme/native_theme.h" |
| 31 #include "ui/views/focus/focus_manager.h" | |
| 32 #include "ui/views/native_cursor.h" | |
| 29 | 33 |
| 30 namespace views { | 34 namespace views { |
| 31 // static | 35 // static |
| 32 const char Label::kViewClassName[] = "Label"; | 36 const char Label::kViewClassName[] = "Label"; |
| 33 const int Label::kFocusBorderPadding = 1; | 37 const int Label::kFocusBorderPadding = 1; |
| 34 | 38 |
| 35 Label::Label() : Label(base::string16()) { | 39 Label::Label() : Label(base::string16()) { |
| 36 } | 40 } |
| 37 | 41 |
| 38 Label::Label(const base::string16& text) : Label(text, GetDefaultFontList()) { | 42 Label::Label(const base::string16& text) : Label(text, GetDefaultFontList()) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 | 97 |
| 94 void Label::SetBackgroundColor(SkColor color) { | 98 void Label::SetBackgroundColor(SkColor color) { |
| 95 if (background_color_set_ && background_color_ == color) | 99 if (background_color_set_ && background_color_ == color) |
| 96 return; | 100 return; |
| 97 is_first_paint_text_ = true; | 101 is_first_paint_text_ = true; |
| 98 background_color_ = color; | 102 background_color_ = color; |
| 99 background_color_set_ = true; | 103 background_color_set_ = true; |
| 100 RecalculateColors(); | 104 RecalculateColors(); |
| 101 } | 105 } |
| 102 | 106 |
| 107 void Label::SetSelectionTextColor(SkColor color) { | |
| 108 if (selection_text_color_set_ && requested_selection_text_color_ == color) | |
| 109 return; | |
| 110 is_first_paint_text_ = true; | |
| 111 requested_selection_text_color_ = color; | |
| 112 selection_text_color_set_ = true; | |
| 113 RecalculateColors(); | |
| 114 } | |
| 115 | |
| 116 void Label::SetSelectionBackgroundColor(SkColor color) { | |
| 117 if (selection_background_color_set_ && selection_background_color_ == color) | |
| 118 return; | |
| 119 is_first_paint_text_ = true; | |
| 120 selection_background_color_ = color; | |
| 121 selection_background_color_set_ = true; | |
| 122 RecalculateColors(); | |
| 123 } | |
| 124 | |
| 103 void Label::SetShadows(const gfx::ShadowValues& shadows) { | 125 void Label::SetShadows(const gfx::ShadowValues& shadows) { |
| 104 // TODO(mukai): early exit if the specified shadows are same. | 126 // TODO(mukai): early exit if the specified shadows are same. |
| 105 is_first_paint_text_ = true; | 127 is_first_paint_text_ = true; |
| 106 render_text_->set_shadows(shadows); | 128 render_text_->set_shadows(shadows); |
| 107 ResetLayout(); | 129 ResetLayout(); |
| 108 } | 130 } |
| 109 | 131 |
| 110 void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) { | 132 void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) { |
| 111 if (subpixel_rendering_enabled_ == subpixel_rendering_enabled) | 133 if (subpixel_rendering_enabled_ == subpixel_rendering_enabled) |
| 112 return; | 134 return; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 140 void Label::SetMultiLine(bool multi_line) { | 162 void Label::SetMultiLine(bool multi_line) { |
| 141 DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL || | 163 DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL || |
| 142 elide_behavior_ == gfx::NO_ELIDE)); | 164 elide_behavior_ == gfx::NO_ELIDE)); |
| 143 if (this->multi_line() == multi_line) | 165 if (this->multi_line() == multi_line) |
| 144 return; | 166 return; |
| 145 is_first_paint_text_ = true; | 167 is_first_paint_text_ = true; |
| 146 multi_line_ = multi_line; | 168 multi_line_ = multi_line; |
| 147 if (render_text_->MultilineSupported()) | 169 if (render_text_->MultilineSupported()) |
| 148 render_text_->SetMultiline(multi_line); | 170 render_text_->SetMultiline(multi_line); |
| 149 render_text_->SetReplaceNewlineCharsWithSymbols(!multi_line); | 171 render_text_->SetReplaceNewlineCharsWithSymbols(!multi_line); |
| 172 if (multi_line) | |
| 173 SetSelectable(false); | |
| 150 ResetLayout(); | 174 ResetLayout(); |
| 151 } | 175 } |
| 152 | 176 |
| 153 void Label::SetObscured(bool obscured) { | 177 void Label::SetObscured(bool obscured) { |
| 154 if (this->obscured() == obscured) | 178 if (this->obscured() == obscured) |
| 155 return; | 179 return; |
| 156 is_first_paint_text_ = true; | 180 is_first_paint_text_ = true; |
| 157 render_text_->SetObscured(obscured); | 181 render_text_->SetObscured(obscured); |
| 158 ResetLayout(); | 182 ResetLayout(); |
| 159 } | 183 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 } | 221 } |
| 198 | 222 |
| 199 void Label::SetMaximumWidth(int max_width) { | 223 void Label::SetMaximumWidth(int max_width) { |
| 200 DCHECK(multi_line()); | 224 DCHECK(multi_line()); |
| 201 DCHECK_EQ(0, fixed_width_); | 225 DCHECK_EQ(0, fixed_width_); |
| 202 max_width_ = max_width; | 226 max_width_ = max_width; |
| 203 SizeToPreferredSize(); | 227 SizeToPreferredSize(); |
| 204 } | 228 } |
| 205 | 229 |
| 206 base::string16 Label::GetDisplayTextForTesting() { | 230 base::string16 Label::GetDisplayTextForTesting() { |
| 207 lines_.clear(); | 231 ClearLines(); |
| 208 MaybeBuildRenderTextLines(); | 232 MaybeBuildRenderTextLines(); |
| 209 base::string16 result; | 233 base::string16 result; |
| 210 if (lines_.empty()) | 234 if (lines_.empty()) |
| 211 return result; | 235 return result; |
| 212 result.append(lines_[0]->GetDisplayText()); | 236 result.append(lines_[0]->GetDisplayText()); |
| 213 for (size_t i = 1; i < lines_.size(); ++i) { | 237 for (size_t i = 1; i < lines_.size(); ++i) { |
| 214 result.append(1, '\n'); | 238 result.append(1, '\n'); |
| 215 result.append(lines_[i]->GetDisplayText()); | 239 result.append(lines_[i]->GetDisplayText()); |
| 216 } | 240 } |
| 217 return result; | 241 return result; |
| 218 } | 242 } |
| 219 | 243 |
| 244 bool Label::IsSelectionSupported() const { | |
| 245 return !multi_line() && render_text_->IsSelectionSupported(); | |
| 246 } | |
| 247 | |
| 248 bool Label::SetSelectable(bool value) { | |
| 249 if (value == selectable()) | |
| 250 return true; | |
| 251 | |
| 252 if (value && !IsSelectionSupported()) | |
| 253 return false; | |
| 254 | |
| 255 ClearSelection(); | |
| 256 selection_controller_.reset(value ? new SelectionController(this) : nullptr); | |
| 257 return true; | |
| 258 } | |
| 259 | |
| 260 bool Label::HasSelection() { | |
| 261 gfx::RenderText* render_text = GetRenderTextForSelection(); | |
| 262 return render_text ? !render_text->selection().is_empty() : false; | |
| 263 } | |
| 264 | |
| 265 void Label::SelectAll() { | |
| 266 if (!GetRenderTextForSelection()) | |
| 267 return; | |
| 268 GetRenderTextForSelection()->SelectAll(false); | |
| 269 OnSelectionUpdated(); | |
| 270 } | |
| 271 | |
| 272 void Label::ClearSelection() { | |
| 273 if (!GetRenderTextForSelection()) | |
| 274 return; | |
| 275 GetRenderTextForSelection()->ClearSelection(); | |
| 276 OnSelectionUpdated(); | |
| 277 } | |
| 278 | |
| 279 void Label::SelectRange(const gfx::Range& range) { | |
| 280 if (!GetRenderTextForSelection()) | |
| 281 return; | |
| 282 if (GetRenderTextForSelection()->SelectRange(range)) | |
| 283 OnSelectionUpdated(); | |
| 284 } | |
| 285 | |
| 220 gfx::Insets Label::GetInsets() const { | 286 gfx::Insets Label::GetInsets() const { |
| 221 gfx::Insets insets = View::GetInsets(); | 287 gfx::Insets insets = View::GetInsets(); |
| 222 if (focus_behavior() != FocusBehavior::NEVER) { | 288 if (focus_behavior() != FocusBehavior::NEVER) { |
| 223 insets += gfx::Insets(kFocusBorderPadding, kFocusBorderPadding, | 289 insets += gfx::Insets(kFocusBorderPadding, kFocusBorderPadding, |
| 224 kFocusBorderPadding, kFocusBorderPadding); | 290 kFocusBorderPadding, kFocusBorderPadding); |
| 225 } | 291 } |
| 226 return insets; | 292 return insets; |
| 227 } | 293 } |
| 228 | 294 |
| 229 int Label::GetBaseline() const { | 295 int Label::GetBaseline() const { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 height = render_text_->GetStringSize().height(); | 355 height = render_text_->GetStringSize().height(); |
| 290 } else { | 356 } else { |
| 291 std::vector<base::string16> lines = GetLinesForWidth(w); | 357 std::vector<base::string16> lines = GetLinesForWidth(w); |
| 292 height = lines.size() * std::max(line_height(), font_list().GetHeight()); | 358 height = lines.size() * std::max(line_height(), font_list().GetHeight()); |
| 293 } | 359 } |
| 294 height -= gfx::ShadowValue::GetMargin(render_text_->shadows()).height(); | 360 height -= gfx::ShadowValue::GetMargin(render_text_->shadows()).height(); |
| 295 return height + GetInsets().height(); | 361 return height + GetInsets().height(); |
| 296 } | 362 } |
| 297 | 363 |
| 298 void Label::Layout() { | 364 void Label::Layout() { |
| 299 lines_.clear(); | 365 ClearLines(); |
| 300 } | 366 } |
| 301 | 367 |
| 302 const char* Label::GetClassName() const { | 368 const char* Label::GetClassName() const { |
| 303 return kViewClassName; | 369 return kViewClassName; |
| 304 } | 370 } |
| 305 | 371 |
| 306 View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) { | 372 View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) { |
| 307 if (!handles_tooltips_ || | 373 if (!handles_tooltips_ || |
| 308 (tooltip_text_.empty() && !ShouldShowDefaultTooltip())) | 374 (tooltip_text_.empty() && !ShouldShowDefaultTooltip())) |
| 309 return NULL; | 375 return NULL; |
| 310 | 376 |
| 311 return HitTestPoint(point) ? this : NULL; | 377 return HitTestPoint(point) ? this : NULL; |
| 312 } | 378 } |
| 313 | 379 |
| 314 bool Label::CanProcessEventsWithinSubtree() const { | 380 bool Label::CanProcessEventsWithinSubtree() const { |
| 315 // Send events to the parent view for handling. | 381 return selectable(); |
| 316 return false; | |
| 317 } | 382 } |
| 318 | 383 |
| 319 void Label::GetAccessibleState(ui::AXViewState* state) { | 384 void Label::GetAccessibleState(ui::AXViewState* state) { |
| 320 state->role = ui::AX_ROLE_STATIC_TEXT; | 385 state->role = ui::AX_ROLE_STATIC_TEXT; |
| 321 state->AddStateFlag(ui::AX_STATE_READ_ONLY); | 386 state->AddStateFlag(ui::AX_STATE_READ_ONLY); |
| 322 // Note that |render_text_| is never elided (see the comment in Init() too). | 387 // Note that |render_text_| is never elided (see the comment in Init() too). |
| 323 state->name = render_text_->GetDisplayText(); | 388 state->name = render_text_->GetDisplayText(); |
| 324 } | 389 } |
| 325 | 390 |
| 326 bool Label::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { | 391 bool Label::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 382 // TODO(ckocagil): Remove ScopedTracker below once crbug.com/441028 is | 447 // TODO(ckocagil): Remove ScopedTracker below once crbug.com/441028 is |
| 383 // fixed. | 448 // fixed. |
| 384 tracked_objects::ScopedTracker tracking_profile( | 449 tracked_objects::ScopedTracker tracking_profile( |
| 385 FROM_HERE_WITH_EXPLICIT_FUNCTION("441028 First PaintText()")); | 450 FROM_HERE_WITH_EXPLICIT_FUNCTION("441028 First PaintText()")); |
| 386 | 451 |
| 387 is_first_paint_text_ = false; | 452 is_first_paint_text_ = false; |
| 388 PaintText(canvas); | 453 PaintText(canvas); |
| 389 } else { | 454 } else { |
| 390 PaintText(canvas); | 455 PaintText(canvas); |
| 391 } | 456 } |
| 392 if (HasFocus() && !ui::MaterialDesignController::IsSecondaryUiMaterial()) | 457 |
| 458 // Check for IsAccessibilityFocusable() to prevent drawing a focus rect for | |
| 459 // non-focusable labels with selection, which are given focus explicitly in | |
| 460 // OnMousePressed. | |
| 461 if (HasFocus() && !ui::MaterialDesignController::IsSecondaryUiMaterial() && | |
| 462 IsAccessibilityFocusable()) { | |
| 393 canvas->DrawFocusRect(GetFocusBounds()); | 463 canvas->DrawFocusRect(GetFocusBounds()); |
| 464 } | |
| 394 } | 465 } |
| 395 | 466 |
| 396 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { | 467 void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) { |
| 397 UpdateColorsFromTheme(theme); | 468 UpdateColorsFromTheme(theme); |
| 398 } | 469 } |
| 399 | 470 |
| 471 gfx::NativeCursor Label::GetCursor(const ui::MouseEvent& event) { | |
| 472 return GetRenderTextForSelection() ? GetNativeIBeamCursor() | |
| 473 : gfx::kNullCursor; | |
| 474 } | |
| 475 | |
| 476 void Label::OnFocus() { | |
| 477 if (GetRenderTextForSelection()) { | |
| 478 GetRenderTextForSelection()->set_focused(true); | |
| 479 SchedulePaint(); | |
| 480 } | |
| 481 View::OnFocus(); | |
| 482 } | |
| 483 | |
| 484 void Label::OnBlur() { | |
| 485 if (GetRenderTextForSelection()) { | |
| 486 GetRenderTextForSelection()->set_focused(false); | |
| 487 SchedulePaint(); | |
| 488 } | |
| 489 View::OnBlur(); | |
| 490 } | |
| 491 | |
| 492 bool Label::OnMousePressed(const ui::MouseEvent& event) { | |
| 493 DCHECK(selectable()); | |
| 494 if (!GetRenderTextForSelection()) | |
| 495 return false; | |
| 496 | |
| 497 // RequestFocus() won't work when the label has FocusBehavior::NEVER. Hence | |
| 498 // explicitly set the focused view. | |
| 499 // Todo(karandeepb): If a widget with a label having FocusBehavior::NEVER as | |
| 500 // the currently focused view (due to selection) was to lose focus, focus | |
|
karandeepb
2016/10/14 09:31:33
See the linked doc for some possible approaches to
| |
| 501 // won't be restored to the label (and hence a text selection won't be drawn) | |
| 502 // when the widget gets focus again. Fix this. | |
| 503 // Todo is giving focus to a view with FocusBehavior::NEVER ok? | |
| 504 if (GetFocusManager()) | |
| 505 GetFocusManager()->SetFocusedView(this); | |
| 506 return selection_controller_->OnMousePressed(event, false); | |
| 507 } | |
| 508 | |
| 509 bool Label::OnMouseDragged(const ui::MouseEvent& event) { | |
| 510 DCHECK(GetRenderTextForSelection()); | |
| 511 return selection_controller_->OnMouseDragged(event); | |
| 512 } | |
| 513 | |
| 514 void Label::OnMouseReleased(const ui::MouseEvent& event) { | |
| 515 DCHECK(GetRenderTextForSelection()); | |
| 516 selection_controller_->OnMouseReleased(event); | |
| 517 } | |
| 518 | |
| 400 void Label::OnDeviceScaleFactorChanged(float device_scale_factor) { | 519 void Label::OnDeviceScaleFactorChanged(float device_scale_factor) { |
| 401 View::OnDeviceScaleFactorChanged(device_scale_factor); | 520 View::OnDeviceScaleFactorChanged(device_scale_factor); |
| 402 // When the device scale factor is changed, some font rendering parameters is | 521 // When the device scale factor is changed, some font rendering parameters is |
| 403 // changed (especially, hinting). The bounding box of the text has to be | 522 // changed (especially, hinting). The bounding box of the text has to be |
| 404 // re-computed based on the new parameters. See crbug.com/441439 | 523 // re-computed based on the new parameters. See crbug.com/441439 |
| 405 ResetLayout(); | 524 ResetLayout(); |
| 406 } | 525 } |
| 407 | 526 |
| 408 void Label::VisibilityChanged(View* starting_from, bool is_visible) { | 527 void Label::VisibilityChanged(View* starting_from, bool is_visible) { |
| 409 if (!is_visible) | 528 if (!is_visible) |
| 410 lines_.clear(); | 529 ClearLines(); |
| 530 } | |
| 531 | |
| 532 gfx::RenderText* Label::GetRenderTextForSelection() { | |
| 533 if (!selectable()) | |
| 534 return nullptr; | |
| 535 DCHECK(IsSelectionSupported()); | |
| 536 MaybeBuildRenderTextLines(); | |
| 537 if (lines_.empty()) | |
| 538 return nullptr; | |
| 539 DCHECK_EQ(1u, lines_.size()); | |
| 540 return lines_[0].get(); | |
| 541 } | |
| 542 | |
| 543 bool Label::IsReadOnly() const { | |
| 544 return true; | |
| 545 } | |
| 546 | |
| 547 bool Label::SupportsDrag() const { | |
| 548 return false; | |
| 549 } | |
| 550 | |
| 551 bool Label::HasTextBeingDragged() const { | |
| 552 return false; | |
| 553 } | |
| 554 | |
| 555 void Label::SetTextBeingDragged(bool value) {} | |
| 556 | |
| 557 int Label::GetViewHeight() const { | |
| 558 return height(); | |
| 559 } | |
| 560 | |
| 561 int Label::GetViewWidth() const { | |
| 562 return width(); | |
| 563 } | |
| 564 | |
| 565 int Label::GetDragSelectionDelay() const { | |
| 566 // Labels don't need to use a repeating timer to update drag selection. Since | |
| 567 // the cursor is disabled for labels, a selection outside the display area | |
| 568 // won't change the text in the display area. It is expected that all the text | |
| 569 // will fit in the display area for labels anyway. | |
| 570 return 0; | |
| 571 } | |
| 572 | |
| 573 void Label::OnBeforeMouseAction() { | |
| 574 DCHECK(!performing_mouse_action_); | |
| 575 DCHECK(GetRenderTextForSelection()); | |
| 576 performing_mouse_action_ = true; | |
| 577 } | |
| 578 | |
| 579 void Label::OnAfterMouseAction(bool text_changed, bool selection_changed) { | |
| 580 DCHECK(!text_changed); | |
| 581 DCHECK(performing_mouse_action_); | |
| 582 DCHECK(GetRenderTextForSelection()); | |
| 583 performing_mouse_action_ = false; | |
| 584 if (selection_changed) | |
| 585 OnSelectionUpdated(); | |
| 586 } | |
| 587 | |
| 588 void Label::OnBeforeSelectionUpdated() { | |
| 589 DCHECK(performing_mouse_action_); | |
| 590 } | |
| 591 | |
| 592 void Label::OnAfterSelectionUpdated() { | |
| 593 DCHECK(performing_mouse_action_); | |
| 594 OnSelectionUpdated(); | |
| 595 } | |
| 596 | |
| 597 void Label::PasteSelectionClipboard(const ui::MouseEvent& event) {} | |
| 598 | |
| 599 void Label::UpdateSelectionClipboard() { | |
| 600 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 601 gfx::RenderText* render_text = GetRenderTextForSelection(); | |
| 602 if (performing_mouse_action_ && !obscured() && render_text) { | |
| 603 base::string16 selected_text = | |
| 604 render_text->GetTextFromRange(render_text->selection()); | |
| 605 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) | |
| 606 .WriteText(selected_text); | |
| 607 } | |
| 608 #endif | |
| 411 } | 609 } |
| 412 | 610 |
| 413 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { | 611 void Label::Init(const base::string16& text, const gfx::FontList& font_list) { |
| 414 render_text_.reset(gfx::RenderText::CreateInstance()); | 612 render_text_.reset(gfx::RenderText::CreateInstance()); |
| 415 render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); | 613 render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); |
| 416 render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT); | 614 render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT); |
| 417 // NOTE: |render_text_| should not be elided at all. This is used to keep some | 615 // NOTE: |render_text_| should not be elided at all. This is used to keep some |
| 418 // properties and to compute the size of the string. | 616 // properties and to compute the size of the string. |
| 419 render_text_->SetElideBehavior(gfx::NO_ELIDE); | 617 render_text_->SetElideBehavior(gfx::NO_ELIDE); |
| 420 render_text_->SetFontList(font_list); | 618 render_text_->SetFontList(font_list); |
| 421 render_text_->SetCursorEnabled(false); | 619 render_text_->SetCursorEnabled(false); |
| 422 render_text_->SetWordWrapBehavior(gfx::TRUNCATE_LONG_WORDS); | 620 render_text_->SetWordWrapBehavior(gfx::TRUNCATE_LONG_WORDS); |
| 423 | 621 |
| 424 elide_behavior_ = gfx::ELIDE_TAIL; | 622 elide_behavior_ = gfx::ELIDE_TAIL; |
| 425 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; | 623 enabled_color_set_ = disabled_color_set_ = background_color_set_ = false; |
| 624 selection_text_color_set_ = selection_background_color_set_ = false; | |
| 426 subpixel_rendering_enabled_ = true; | 625 subpixel_rendering_enabled_ = true; |
| 427 auto_color_readability_ = true; | 626 auto_color_readability_ = true; |
| 428 multi_line_ = false; | 627 multi_line_ = false; |
| 429 UpdateColorsFromTheme(GetNativeTheme()); | 628 UpdateColorsFromTheme(GetNativeTheme()); |
| 430 handles_tooltips_ = true; | 629 handles_tooltips_ = true; |
| 431 collapse_when_hidden_ = false; | 630 collapse_when_hidden_ = false; |
| 432 fixed_width_ = 0; | 631 fixed_width_ = 0; |
| 433 max_width_ = 0; | 632 max_width_ = 0; |
| 434 is_first_paint_text_ = true; | 633 is_first_paint_text_ = true; |
| 634 performing_mouse_action_ = false; | |
| 435 SetText(text); | 635 SetText(text); |
| 436 } | 636 } |
| 437 | 637 |
| 438 void Label::ResetLayout() { | 638 void Label::ResetLayout() { |
| 439 InvalidateLayout(); | 639 InvalidateLayout(); |
| 440 PreferredSizeChanged(); | 640 PreferredSizeChanged(); |
| 441 SchedulePaint(); | 641 SchedulePaint(); |
| 442 lines_.clear(); | 642 ClearLines(); |
| 443 } | 643 } |
| 444 | 644 |
| 445 void Label::MaybeBuildRenderTextLines() { | 645 void Label::MaybeBuildRenderTextLines() { |
| 446 if (!lines_.empty()) | 646 if (!lines_.empty()) |
| 447 return; | 647 return; |
| 448 | 648 |
| 449 gfx::Rect rect = GetContentsBounds(); | 649 gfx::Rect rect = GetContentsBounds(); |
| 450 if (focus_behavior() != FocusBehavior::NEVER) | 650 if (focus_behavior() != FocusBehavior::NEVER) |
| 451 rect.Inset(kFocusBorderPadding, kFocusBorderPadding); | 651 rect.Inset(kFocusBorderPadding, kFocusBorderPadding); |
| 452 if (rect.IsEmpty()) | 652 if (rect.IsEmpty()) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 486 std::unique_ptr<gfx::RenderText> line = | 686 std::unique_ptr<gfx::RenderText> line = |
| 487 CreateRenderText(lines[i], alignment, directionality, elide_behavior); | 687 CreateRenderText(lines[i], alignment, directionality, elide_behavior); |
| 488 line->SetDisplayRect(rect); | 688 line->SetDisplayRect(rect); |
| 489 lines_.push_back(std::move(line)); | 689 lines_.push_back(std::move(line)); |
| 490 rect.set_y(rect.y() + rect.height()); | 690 rect.set_y(rect.y() + rect.height()); |
| 491 } | 691 } |
| 492 // Append the remaining text to the last visible line. | 692 // Append the remaining text to the last visible line. |
| 493 for (size_t i = lines_.size(); i < lines.size(); ++i) | 693 for (size_t i = lines_.size(); i < lines.size(); ++i) |
| 494 lines_.back()->SetText(lines_.back()->text() + lines[i]); | 694 lines_.back()->SetText(lines_.back()->text() + lines[i]); |
| 495 } | 695 } |
| 696 | |
| 697 if (GetRenderTextForSelection()) | |
| 698 GetRenderTextForSelection()->set_focused(HasFocus()); | |
| 699 | |
| 700 if (last_selection_range_) { | |
| 701 SelectRange(last_selection_range_.value()); | |
| 702 last_selection_range_.reset(); | |
| 703 } | |
| 704 | |
| 496 ApplyTextColors(); | 705 ApplyTextColors(); |
| 497 } | 706 } |
| 498 | 707 |
| 499 gfx::Rect Label::GetFocusBounds() { | 708 gfx::Rect Label::GetFocusBounds() { |
| 500 MaybeBuildRenderTextLines(); | 709 MaybeBuildRenderTextLines(); |
| 501 | 710 |
| 502 gfx::Rect focus_bounds; | 711 gfx::Rect focus_bounds; |
| 503 if (lines_.empty()) { | 712 if (lines_.empty()) { |
| 504 focus_bounds = gfx::Rect(GetTextSize()); | 713 focus_bounds = gfx::Rect(GetTextSize()); |
| 505 } else { | 714 } else { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 | 773 |
| 565 void Label::RecalculateColors() { | 774 void Label::RecalculateColors() { |
| 566 actual_enabled_color_ = auto_color_readability_ ? | 775 actual_enabled_color_ = auto_color_readability_ ? |
| 567 color_utils::GetReadableColor(requested_enabled_color_, | 776 color_utils::GetReadableColor(requested_enabled_color_, |
| 568 background_color_) : | 777 background_color_) : |
| 569 requested_enabled_color_; | 778 requested_enabled_color_; |
| 570 actual_disabled_color_ = auto_color_readability_ ? | 779 actual_disabled_color_ = auto_color_readability_ ? |
| 571 color_utils::GetReadableColor(requested_disabled_color_, | 780 color_utils::GetReadableColor(requested_disabled_color_, |
| 572 background_color_) : | 781 background_color_) : |
| 573 requested_disabled_color_; | 782 requested_disabled_color_; |
| 783 actual_selection_text_color_ = | |
| 784 auto_color_readability_ | |
| 785 ? color_utils::GetReadableColor(requested_selection_text_color_, | |
| 786 selection_background_color_) | |
| 787 : requested_selection_text_color_; | |
| 574 | 788 |
| 575 ApplyTextColors(); | 789 ApplyTextColors(); |
| 576 SchedulePaint(); | 790 SchedulePaint(); |
| 577 } | 791 } |
| 578 | 792 |
| 579 void Label::ApplyTextColors() { | 793 void Label::ApplyTextColors() { |
| 580 SkColor color = enabled() ? actual_enabled_color_ : actual_disabled_color_; | 794 SkColor color = enabled() ? actual_enabled_color_ : actual_disabled_color_; |
| 581 bool subpixel_rendering_suppressed = | 795 bool subpixel_rendering_suppressed = |
| 582 SkColorGetA(background_color_) != 0xFF || !subpixel_rendering_enabled_; | 796 SkColorGetA(background_color_) != 0xFF || !subpixel_rendering_enabled_; |
| 583 for (size_t i = 0; i < lines_.size(); ++i) { | 797 for (size_t i = 0; i < lines_.size(); ++i) { |
| 584 lines_[i]->SetColor(color); | 798 lines_[i]->SetColor(color); |
| 799 lines_[i]->set_selection_color(actual_selection_text_color_); | |
| 800 lines_[i]->set_selection_background_focused_color( | |
| 801 selection_background_color_); | |
| 585 lines_[i]->set_subpixel_rendering_suppressed(subpixel_rendering_suppressed); | 802 lines_[i]->set_subpixel_rendering_suppressed(subpixel_rendering_suppressed); |
| 586 } | 803 } |
| 587 } | 804 } |
| 588 | 805 |
| 589 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { | 806 void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) { |
| 590 if (!enabled_color_set_) { | 807 if (!enabled_color_set_) { |
| 591 requested_enabled_color_ = theme->GetSystemColor( | 808 requested_enabled_color_ = theme->GetSystemColor( |
| 592 ui::NativeTheme::kColorId_LabelEnabledColor); | 809 ui::NativeTheme::kColorId_LabelEnabledColor); |
| 593 } | 810 } |
| 594 if (!disabled_color_set_) { | 811 if (!disabled_color_set_) { |
| 595 requested_disabled_color_ = theme->GetSystemColor( | 812 requested_disabled_color_ = theme->GetSystemColor( |
| 596 ui::NativeTheme::kColorId_LabelDisabledColor); | 813 ui::NativeTheme::kColorId_LabelDisabledColor); |
| 597 } | 814 } |
| 598 if (!background_color_set_) { | 815 if (!background_color_set_) { |
| 599 background_color_ = | 816 background_color_ = |
| 600 theme->GetSystemColor(ui::NativeTheme::kColorId_DialogBackground); | 817 theme->GetSystemColor(ui::NativeTheme::kColorId_DialogBackground); |
| 601 } | 818 } |
| 819 if (!selection_text_color_set_) { | |
| 820 // Todo create new default for labels or rename Textfield to Text? | |
| 821 requested_selection_text_color_ = theme->GetSystemColor( | |
| 822 ui::NativeTheme::kColorId_TextfieldSelectionColor); | |
|
karandeepb
2016/10/14 09:31:33
Would it be ok to use the same colors for Textfiel
| |
| 823 } | |
| 824 if (!selection_background_color_set_) { | |
| 825 selection_background_color_ = theme->GetSystemColor( | |
| 826 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused); | |
| 827 } | |
| 602 RecalculateColors(); | 828 RecalculateColors(); |
| 603 } | 829 } |
| 604 | 830 |
| 605 bool Label::ShouldShowDefaultTooltip() const { | 831 bool Label::ShouldShowDefaultTooltip() const { |
| 606 const gfx::Size text_size = GetTextSize(); | 832 const gfx::Size text_size = GetTextSize(); |
| 607 const gfx::Size size = GetContentsBounds().size(); | 833 const gfx::Size size = GetContentsBounds().size(); |
| 608 return !obscured() && (text_size.width() > size.width() || | 834 return !obscured() && (text_size.width() > size.width() || |
| 609 (multi_line() && text_size.height() > size.height())); | 835 (multi_line() && text_size.height() > size.height())); |
| 610 } | 836 } |
| 611 | 837 |
| 838 void Label::OnSelectionUpdated() { | |
| 839 if (performing_mouse_action_) | |
| 840 return; | |
| 841 SchedulePaint(); | |
| 842 } | |
| 843 | |
| 844 void Label::ClearLines() { | |
| 845 // Persist the selection range if there is an active selection. | |
| 846 if (HasSelection()) | |
| 847 last_selection_range_ = GetRenderTextForSelection()->selection(); | |
| 848 lines_.clear(); | |
| 849 } | |
| 850 | |
| 612 } // namespace views | 851 } // namespace views |
| OLD | NEW |