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

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

Issue 2379993005: Label selection experiment (Closed)
Patch Set: -- Created 4 years, 2 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
« no previous file with comments | « ui/views/controls/label.h ('k') | ui/views/controls/link.h » ('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 <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
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
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
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
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
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
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
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
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);
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
OLDNEW
« no previous file with comments | « ui/views/controls/label.h ('k') | ui/views/controls/link.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698