diff options
author | oshima <oshima@chromium.org> | 2015-02-23 08:38:08 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-23 16:38:35 +0000 |
commit | 3e0cc51a03d65bf057742ac0f1f5e0c8b633bda5 (patch) | |
tree | 221d4ab735aa13c8b666eac34bbc384f2bf922a8 /ui | |
parent | e5938a2d887bd71f1cf0df76d5d72e0a6318f888 (diff) | |
download | chromium_src-3e0cc51a03d65bf057742ac0f1f5e0c8b633bda5.zip chromium_src-3e0cc51a03d65bf057742ac0f1f5e0c8b633bda5.tar.gz chromium_src-3e0cc51a03d65bf057742ac0f1f5e0c8b633bda5.tar.bz2 |
Use RenderText directly to draw tooltip to imporove format and performance.
This replaces the old CL (https://codereview.chromium.org/340543004/). This runs faster and doesn't require the label caching CL. (for the example in 370226, this is 20x faster on arm. ~60ms total vs ~3ms total)
I'll look into switching to label once I get the performance data with label after label caching is enabled.
This depends on two CLs
1) https://codereview.chromium.org/916423002/ Tooltip Cleanup
2) https://codereview.chromium.org/915383003/ RTL format problem.
but this can be reviewed independently.
BUG=370226,451853
Review URL: https://codereview.chromium.org/924433002
Cr-Commit-Position: refs/heads/master@{#317590}
Diffstat (limited to 'ui')
-rw-r--r-- | ui/views/corewm/DEPS | 2 | ||||
-rw-r--r-- | ui/views/corewm/tooltip_aura.cc | 163 | ||||
-rw-r--r-- | ui/views/corewm/tooltip_aura.h | 19 | ||||
-rw-r--r-- | ui/views/corewm/tooltip_aura_unittest.cc | 131 | ||||
-rw-r--r-- | ui/views/corewm/tooltip_controller.cc | 2 | ||||
-rw-r--r-- | ui/views/views.gyp | 1 |
6 files changed, 75 insertions, 243 deletions
diff --git a/ui/views/corewm/DEPS b/ui/views/corewm/DEPS index a2d52d6..c50f694 100644 --- a/ui/views/corewm/DEPS +++ b/ui/views/corewm/DEPS @@ -16,6 +16,7 @@ specific_include_rules = { "+ui/views/background.h", "+ui/views/border.h", "+ui/views/widget/widget.h", + "+ui/views/view.h", ], "desktop_capture_controller_unittest.cc": [ @@ -38,7 +39,6 @@ specific_include_rules = { ], "tooltip_aura.h": [ - "+ui/views/controls/label.h", "+ui/views/widget/widget_observer.h", ], diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc index 3e98cf16..c0d3691 100644 --- a/ui/views/corewm/tooltip_aura.cc +++ b/ui/views/corewm/tooltip_aura.cc @@ -5,14 +5,18 @@ #include "ui/views/corewm/tooltip_aura.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/render_text.h" #include "ui/gfx/screen.h" #include "ui/gfx/text_elider.h" #include "ui/gfx/text_utils.h" #include "ui/native_theme/native_theme.h" #include "ui/views/background.h" #include "ui/views/border.h" +#include "ui/views/view.h" #include "ui/views/widget/widget.h" namespace { @@ -21,8 +25,6 @@ namespace { // be wrapped. const int kTooltipMaxWidthPixels = 400; -const size_t kMaxLines = 10; - // FIXME: get cursor offset from actual cursor size. const int kCursorOffsetX = 10; const int kCursorOffsetY = 15; @@ -47,16 +49,68 @@ views::Widget* CreateTooltipWidget(aura::Window* tooltip_window) { namespace views { namespace corewm { +// TODO(oshima): Consider to use views::Label. +class TooltipAura::TooltipView : public views::View { + public: + TooltipView() + : render_text_(gfx::RenderText::CreateInstance()), + max_width_(0) { + set_owned_by_client(); + render_text_->SetMultiline(true); + ResetDisplayRect(); + } + + ~TooltipView() override {} + + // views:View: + void OnPaint(gfx::Canvas* canvas) override { + OnPaintBackground(canvas); + render_text_->SetDisplayRect(gfx::Rect(size())); + render_text_->Draw(canvas); + OnPaintBorder(canvas); + } + + gfx::Size GetPreferredSize() const override { + return render_text_->GetStringSize(); + } + + const char* GetClassName() const override { + return "TooltipView"; + } + + void SetText(const base::string16& text) { + render_text_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); + render_text_->SetText(text); + } + + void SetForegroundColor(SkColor color) { + render_text_->SetColor(color); + } + + void SetMaxWidth(int width) { + max_width_ = width; + ResetDisplayRect(); + } + + private: + void ResetDisplayRect() { + render_text_->SetDisplayRect(gfx::Rect(0, 0, max_width_, 100000)); + } + + scoped_ptr<gfx::RenderText> render_text_; + int max_width_; + + DISALLOW_COPY_AND_ASSIGN(TooltipView); +}; + TooltipAura::TooltipAura() - : widget_(NULL), + : tooltip_view_(new TooltipView), + widget_(NULL), tooltip_window_(NULL) { - label_.set_owned_by_client(); - label_.SetMultiLine(true); - label_.SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); const int kHorizontalPadding = 3; const int kVerticalPadding = 2; - label_.SetBorder(Border::CreateEmptyBorder( + tooltip_view_->SetBorder(Border::CreateEmptyBorder( kVerticalPadding, kHorizontalPadding, kVerticalPadding, kHorizontalPadding)); } @@ -65,82 +119,6 @@ TooltipAura::~TooltipAura() { DestroyWidget(); } -// static -void TooltipAura::TrimTooltipToFit(const gfx::FontList& font_list, - int max_width, - base::string16* text, - int* width, - int* line_count) { - *width = 0; - *line_count = 0; - - // Determine the available width for the tooltip. - int available_width = std::min(kTooltipMaxWidthPixels, max_width); - - std::vector<base::string16> lines; - base::SplitString(*text, '\n', &lines); - std::vector<base::string16> result_lines; - - // Format each line to fit. - for (std::vector<base::string16>::iterator l = lines.begin(); - l != lines.end(); ++l) { - // We break the line at word boundaries, then stuff as many words as we can - // in the available width to the current line, and move the remaining words - // to a new line. - std::vector<base::string16> words; - base::SplitStringDontTrim(*l, ' ', &words); - int current_width = 0; - base::string16 line; - for (std::vector<base::string16>::iterator w = words.begin(); - w != words.end(); ++w) { - base::string16 word = *w; - if (w + 1 != words.end()) - word.push_back(' '); - int word_width = gfx::GetStringWidth(word, font_list); - if (current_width + word_width > available_width) { - // Current width will exceed the available width. Must start a new line. - if (!line.empty()) - result_lines.push_back(line); - current_width = 0; - line.clear(); - } - current_width += word_width; - line.append(word); - } - result_lines.push_back(line); - } - - // Clamp number of lines to |kMaxLines|. - if (result_lines.size() > kMaxLines) { - result_lines.resize(kMaxLines); - // Add ellipses character to last line. - result_lines[kMaxLines - 1] = gfx::TruncateString( - result_lines.back(), result_lines.back().length() - 1, gfx::WORD_BREAK); - } - *line_count = result_lines.size(); - - // Flatten the result. - base::string16 result; - for (std::vector<base::string16>::iterator l = result_lines.begin(); - l != result_lines.end(); ++l) { - if (!result.empty()) - result.push_back('\n'); - int line_width = gfx::GetStringWidth(*l, font_list); - // Since we only break at word boundaries, it could happen that due to some - // very long word, line_width is greater than the available_width. In such - // case, we simply truncate at available_width and add ellipses at the end. - if (line_width > available_width) { - *width = available_width; - result.append(gfx::ElideText(*l, font_list, available_width, - gfx::ELIDE_TAIL)); - } else { - *width = std::max(*width, line_width); - result.append(*l); - } - } - *text = result; -} - void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos, const gfx::Size& tooltip_size) { gfx::Rect tooltip_rect(mouse_pos, tooltip_size); @@ -183,30 +161,23 @@ void TooltipAura::SetText(aura::Window* window, const base::string16& tooltip_text, const gfx::Point& location) { tooltip_window_ = window; - int max_width = 0; - int line_count = 0; - base::string16 trimmed_text(tooltip_text); - TrimTooltipToFit(label_.font_list(), GetMaxWidth(location, window), - &trimmed_text, &max_width, &line_count); - label_.SetText(trimmed_text); + tooltip_view_->SetMaxWidth(GetMaxWidth(location, window)); + tooltip_view_->SetText(tooltip_text); if (!widget_) { widget_ = CreateTooltipWidget(tooltip_window_); - widget_->SetContentsView(&label_); + widget_->SetContentsView(tooltip_view_.get()); widget_->AddObserver(this); } - label_.SizeToFit(max_width + label_.GetInsets().width()); - SetTooltipBounds(location, label_.size()); + SetTooltipBounds(location, tooltip_view_->GetPreferredSize()); ui::NativeTheme* native_theme = widget_->GetNativeTheme(); - label_.set_background( + tooltip_view_->set_background( views::Background::CreateSolidBackground( native_theme->GetSystemColor( ui::NativeTheme::kColorId_TooltipBackground))); - - label_.SetAutoColorReadabilityEnabled(false); - label_.SetEnabledColor(native_theme->GetSystemColor( + tooltip_view_->SetForegroundColor(native_theme->GetSystemColor( ui::NativeTheme::kColorId_TooltipText)); } diff --git a/ui/views/corewm/tooltip_aura.h b/ui/views/corewm/tooltip_aura.h index ce92fa2..d1ef448 100644 --- a/ui/views/corewm/tooltip_aura.h +++ b/ui/views/corewm/tooltip_aura.h @@ -5,13 +5,14 @@ #ifndef UI_VIEWS_COREWM_TOOLTIP_AURA_H_ #define UI_VIEWS_COREWM_TOOLTIP_AURA_H_ +#include "base/memory/scoped_ptr.h" #include "ui/gfx/screen_type_delegate.h" -#include "ui/views/controls/label.h" #include "ui/views/corewm/tooltip.h" #include "ui/views/widget/widget_observer.h" namespace gfx { class FontList; +class Size; } // namespace gfx namespace views { @@ -26,17 +27,9 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver { TooltipAura(); ~TooltipAura() override; - // Trims the tooltip to fit in the width |max_width|, setting |text| to the - // clipped result, |width| to the width (in pixels) of the clipped text - // and |line_count| to the number of lines of text in the tooltip. |font_list| - // is used to layout |text|. |max_width| comes from GetMaxWidth(). - static void TrimTooltipToFit(const gfx::FontList& font_list, - int max_width, - base::string16* text, - int* width, - int* line_count); - private: + class TooltipView; + // Adjusts the bounds given by the arguments to fit inside the desktop // and applies the adjusted bounds to the label_. void SetTooltipBounds(const gfx::Point& mouse_pos, @@ -58,8 +51,8 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver { // WidgetObserver: void OnWidgetDestroying(Widget* widget) override; - // The label showing the tooltip. - Label label_; + // The view showing the tooltip. + scoped_ptr<TooltipView> tooltip_view_; // The widget containing the tooltip. May be NULL. Widget* widget_; diff --git a/ui/views/corewm/tooltip_aura_unittest.cc b/ui/views/corewm/tooltip_aura_unittest.cc deleted file mode 100644 index a77db2f..0000000 --- a/ui/views/corewm/tooltip_aura_unittest.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/views/corewm/tooltip_aura.h" - -#include "base/strings/utf_string_conversions.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/text_elider.h" -#include "ui/gfx/text_utils.h" - -using base::ASCIIToUTF16; -using base::UTF8ToUTF16; - -namespace views { -namespace corewm { - -typedef aura::test::AuraTestBase TooltipAuraTest; - -TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { - const gfx::FontList font_list; - const int max_width = 4000; - base::string16 tooltip; - int width, line_count, expect_lines; - int max_pixel_width = 400; // copied from constants in tooltip_controller.cc - int max_lines = 10; // copied from constants in tooltip_controller.cc - size_t tooltip_len; - - // Error in computed size vs. expected size should not be greater than the - // size of the longest word. - int error_in_pixel_width = gfx::GetStringWidth(ASCIIToUTF16("tooltip"), - font_list); - - // Long tooltips should wrap to next line - tooltip.clear(); - width = line_count = -1; - expect_lines = 3; - for (; gfx::GetStringWidth(tooltip, font_list) <= - (expect_lines - 1) * max_pixel_width;) - tooltip.append(ASCIIToUTF16("This is part of the tooltip")); - tooltip_len = tooltip.length(); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); - EXPECT_EQ(expect_lines, line_count); - EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length()); - - // More than |max_lines| lines should get truncated at 10 lines. - tooltip.clear(); - width = line_count = -1; - expect_lines = 13; - for (; gfx::GetStringWidth(tooltip, font_list) <= - (expect_lines - 1) * max_pixel_width;) - tooltip.append(ASCIIToUTF16("This is part of the tooltip")); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); - EXPECT_EQ(max_lines, line_count); - - // Long multi line tooltips should wrap individual lines. - tooltip.clear(); - width = line_count = -1; - expect_lines = 4; - for (; gfx::GetStringWidth(tooltip, font_list) <= - (expect_lines - 2) * max_pixel_width;) - tooltip.append(ASCIIToUTF16("This is part of the tooltip")); - tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n")); - tooltip_len = tooltip.length(); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); - EXPECT_EQ(expect_lines, line_count); - // We may have inserted the line break above near a space which will get - // trimmed. Hence we may be off by 1 in the final tooltip length calculation. - EXPECT_NEAR(tooltip_len + expect_lines - 2, tooltip.length(), 1); - -#if !defined(OS_WIN) - // Tooltip with really long word gets elided. - tooltip.clear(); - width = line_count = -1; - tooltip = UTF8ToUTF16(std::string('a', max_pixel_width)); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_NEAR(max_pixel_width, width, 5); - EXPECT_EQ(1, line_count); - EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), - font_list, max_pixel_width, gfx::ELIDE_TAIL), - tooltip); -#endif - - // Normal small tooltip should stay as is. - tooltip.clear(); - width = line_count = -1; - tooltip = ASCIIToUTF16("Small Tooltip"); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tooltip"), font_list), - width); - EXPECT_EQ(1, line_count); - EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip); - - // Normal small multi-line tooltip should stay as is. - tooltip.clear(); - width = line_count = -1; - tooltip = ASCIIToUTF16("Multi line\nTooltip"); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - int expected_width = gfx::GetStringWidth(ASCIIToUTF16("Multi line"), - font_list); - expected_width = std::max(expected_width, - gfx::GetStringWidth(ASCIIToUTF16("Tooltip"), - font_list)); - EXPECT_EQ(expected_width, width); - EXPECT_EQ(2, line_count); - EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip); - - // Whitespaces in tooltips are preserved. - tooltip.clear(); - width = line_count = -1; - tooltip = ASCIIToUTF16("Small Tool t\tip"); - TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, - &line_count); - EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tool t\tip"), font_list), - width); - EXPECT_EQ(1, line_count); - EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip); -} - -} // namespace corewm -} // namespace views diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc index 8af7199..bb28c54 100644 --- a/ui/views/corewm/tooltip_controller.cc +++ b/ui/views/corewm/tooltip_controller.cc @@ -28,7 +28,7 @@ namespace { const int kTooltipTimeoutMs = 500; const int kDefaultTooltipShownTimeoutMs = 10000; -const size_t kMaxTooltipLength = 1024; +const size_t kMaxTooltipLength = 2048; // Returns true if |target| is a valid window to get the tooltip from. // |event_target| is the original target from the event and |target| the window diff --git a/ui/views/views.gyp b/ui/views/views.gyp index c1a98ba..8b418b6 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -569,7 +569,6 @@ 'window/dialog_delegate_unittest.cc', ], 'views_unittests_aura_sources': [ - 'corewm/tooltip_aura_unittest.cc', 'corewm/tooltip_controller_unittest.cc', 'touchui/touch_selection_controller_impl_unittest.cc', ], |