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 "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
| 11 #include "base/memory/ptr_util.h" | |
| 11 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 12 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "ui/accessibility/ax_node_data.h" | 15 #include "ui/accessibility/ax_node_data.h" |
| 15 #include "ui/base/clipboard/clipboard.h" | 16 #include "ui/base/clipboard/clipboard.h" |
| 16 #include "ui/base/l10n/l10n_util.h" | 17 #include "ui/base/l10n/l10n_util.h" |
| 17 #include "ui/compositor/canvas_painter.h" | 18 #include "ui/compositor/canvas_painter.h" |
| 18 #include "ui/events/base_event_utils.h" | 19 #include "ui/events/base_event_utils.h" |
| 20 #include "ui/events/test/event_generator.h" | |
| 19 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/render_text.h" | 22 #include "ui/gfx/render_text.h" |
| 21 #include "ui/gfx/switches.h" | 23 #include "ui/gfx/switches.h" |
| 24 #include "ui/strings/grit/ui_strings.h" | |
| 22 #include "ui/views/border.h" | 25 #include "ui/views/border.h" |
| 23 #include "ui/views/test/focus_manager_test.h" | 26 #include "ui/views/test/focus_manager_test.h" |
| 24 #include "ui/views/test/views_test_base.h" | 27 #include "ui/views/test/views_test_base.h" |
| 25 #include "ui/views/widget/widget.h" | 28 #include "ui/views/widget/widget.h" |
| 26 | 29 |
| 27 using base::ASCIIToUTF16; | 30 using base::ASCIIToUTF16; |
| 28 | 31 |
| 29 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) | 32 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) |
| 30 | 33 |
| 31 namespace views { | 34 namespace views { |
| 32 | 35 |
| 36 namespace { | |
| 37 | |
| 38 #if defined(OS_MACOSX) | |
| 39 const int kControlCommandModifier = ui::EF_COMMAND_DOWN; | |
| 40 #else | |
| 41 const int kControlCommandModifier = ui::EF_CONTROL_DOWN; | |
| 42 #endif | |
| 43 | |
| 44 // All text sizing measurements (width and height) should be greater than this. | |
| 45 const int kMinTextDimension = 4; | |
| 46 | |
| 47 class TestLabel : public Label { | |
| 48 public: | |
| 49 TestLabel() : Label(ASCIIToUTF16("TestLabel")) { SizeToPreferredSize(); } | |
| 50 | |
| 51 int schedule_paint_count() const { return schedule_paint_count_; } | |
| 52 | |
| 53 void SimulatePaint() { | |
| 54 gfx::Canvas canvas(bounds().size(), 1.0, false /* is_opaque */); | |
| 55 Paint(ui::CanvasPainter(&canvas, 1.f).context()); | |
| 56 } | |
| 57 | |
| 58 // View: | |
| 59 void SchedulePaintInRect(const gfx::Rect& r) override { | |
| 60 ++schedule_paint_count_; | |
| 61 Label::SchedulePaintInRect(r); | |
| 62 } | |
| 63 | |
| 64 private: | |
| 65 int schedule_paint_count_ = 0; | |
| 66 | |
| 67 DISALLOW_COPY_AND_ASSIGN(TestLabel); | |
| 68 }; | |
| 69 | |
| 70 // A test utility function to set the application default text direction. | |
| 71 void SetRTL(bool rtl) { | |
| 72 // Override the current locale/direction. | |
| 73 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en"); | |
| 74 EXPECT_EQ(rtl, base::i18n::IsRTL()); | |
| 75 } | |
| 76 | |
| 77 // Returns true if |current| is bigger than |last|. Sets |last| to |current|. | |
| 78 bool Increased(int current, int* last) { | |
| 79 bool increased = current > *last; | |
| 80 *last = current; | |
| 81 return increased; | |
| 82 } | |
| 83 | |
| 84 base::string16 GetClipboardText(ui::ClipboardType clipboard_type) { | |
| 85 base::string16 clipboard_text; | |
| 86 ui::Clipboard::GetForCurrentThread()->ReadText(clipboard_type, | |
| 87 &clipboard_text); | |
| 88 return clipboard_text; | |
| 89 } | |
| 90 | |
| 91 } // namespace | |
| 92 | |
| 33 class LabelTest : public ViewsTestBase { | 93 class LabelTest : public ViewsTestBase { |
| 34 public: | 94 public: |
| 35 LabelTest() {} | 95 LabelTest() {} |
| 36 | 96 |
| 37 // ViewsTestBase overrides: | 97 // ViewsTestBase overrides: |
| 38 void SetUp() override { | 98 void SetUp() override { |
| 39 ViewsTestBase::SetUp(); | 99 ViewsTestBase::SetUp(); |
| 40 | 100 |
| 41 Widget::InitParams params = | 101 Widget::InitParams params = |
| 42 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); | 102 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 void SetUp() override { | 138 void SetUp() override { |
| 79 #if defined(OS_MACOSX) | 139 #if defined(OS_MACOSX) |
| 80 // On Mac, by default RenderTextMac is used for labels which does not | 140 // On Mac, by default RenderTextMac is used for labels which does not |
| 81 // support text selection. Instead use RenderTextHarfBuzz for selection | 141 // support text selection. Instead use RenderTextHarfBuzz for selection |
| 82 // related tests. TODO(crbug.com/661394): Remove this once Mac also uses | 142 // related tests. TODO(crbug.com/661394): Remove this once Mac also uses |
| 83 // RenderTextHarfBuzz for Labels. | 143 // RenderTextHarfBuzz for Labels. |
| 84 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 144 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 85 switches::kEnableHarfBuzzRenderText); | 145 switches::kEnableHarfBuzzRenderText); |
| 86 #endif | 146 #endif |
| 87 LabelTest::SetUp(); | 147 LabelTest::SetUp(); |
| 148 event_generator_ = | |
|
karandeepb
2016/11/15 10:54:32
Since we are now using EventGenerator anyway, if i
msw
2016/11/15 20:06:45
Acknowledged.
| |
| 149 base::MakeUnique<ui::test::EventGenerator>(widget()->GetNativeWindow()); | |
| 88 } | 150 } |
| 89 | 151 |
| 90 protected: | 152 protected: |
| 91 View* GetFocusedView() { | 153 View* GetFocusedView() { |
| 92 return widget()->GetFocusManager()->GetFocusedView(); | 154 return widget()->GetFocusManager()->GetFocusedView(); |
| 93 } | 155 } |
| 94 | 156 |
| 95 void PerformMousePress(const gfx::Point& point, int extra_flags = 0) { | 157 void PerformMousePress(const gfx::Point& point, int extra_flags = 0) { |
| 96 ui::MouseEvent pressed_event = ui::MouseEvent( | 158 ui::MouseEvent pressed_event = ui::MouseEvent( |
| 97 ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(), | 159 ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(), |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 118 } | 180 } |
| 119 | 181 |
| 120 gfx::Point GetCursorPoint(int cursor_pos) { | 182 gfx::Point GetCursorPoint(int cursor_pos) { |
| 121 return label() | 183 return label() |
| 122 ->GetRenderTextForSelectionController() | 184 ->GetRenderTextForSelectionController() |
| 123 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), | 185 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), |
| 124 false) | 186 false) |
| 125 .origin(); | 187 .origin(); |
| 126 } | 188 } |
| 127 | 189 |
| 128 base::string16 GetSelectedText() { | 190 base::string16 GetSelectedText() { return label()->GetSelectedText(); } |
| 129 const gfx::RenderText* render_text = | 191 |
| 130 label()->GetRenderTextForSelectionController(); | 192 ui::test::EventGenerator* event_generator() { |
| 131 return render_text->GetTextFromRange(render_text->selection()); | 193 return event_generator_.get(); |
| 132 } | 194 }; |
|
msw
2016/11/15 20:06:45
nit: no trailing semi
karandeepb
2016/11/16 07:48:29
Done.
| |
| 133 | 195 |
| 134 private: | 196 private: |
| 197 std::unique_ptr<ui::test::EventGenerator> event_generator_; | |
| 198 | |
| 135 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest); | 199 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest); |
| 136 }; | 200 }; |
| 137 | 201 |
| 138 namespace { | |
| 139 | |
| 140 // All text sizing measurements (width and height) should be greater than this. | |
| 141 const int kMinTextDimension = 4; | |
| 142 | |
| 143 class TestLabel : public Label { | |
| 144 public: | |
| 145 TestLabel() : Label(ASCIIToUTF16("TestLabel")) { SizeToPreferredSize(); } | |
| 146 | |
| 147 int schedule_paint_count() const { return schedule_paint_count_; } | |
| 148 | |
| 149 void SimulatePaint() { | |
| 150 gfx::Canvas canvas(bounds().size(), 1.0, false /* is_opaque */); | |
| 151 Paint(ui::CanvasPainter(&canvas, 1.f).context()); | |
| 152 } | |
| 153 | |
| 154 // View: | |
| 155 void SchedulePaintInRect(const gfx::Rect& r) override { | |
| 156 ++schedule_paint_count_; | |
| 157 Label::SchedulePaintInRect(r); | |
| 158 } | |
| 159 | |
| 160 private: | |
| 161 int schedule_paint_count_ = 0; | |
| 162 | |
| 163 DISALLOW_COPY_AND_ASSIGN(TestLabel); | |
| 164 }; | |
| 165 | |
| 166 // A test utility function to set the application default text direction. | |
| 167 void SetRTL(bool rtl) { | |
| 168 // Override the current locale/direction. | |
| 169 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en"); | |
| 170 EXPECT_EQ(rtl, base::i18n::IsRTL()); | |
| 171 } | |
| 172 | |
| 173 // Returns true if |current| is bigger than |last|. Sets |last| to |current|. | |
| 174 bool Increased(int current, int* last) { | |
| 175 bool increased = current > *last; | |
| 176 *last = current; | |
| 177 return increased; | |
| 178 } | |
| 179 | |
| 180 base::string16 GetSelectionClipboardText() { | |
| 181 base::string16 selection_clipboard_text; | |
| 182 ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_SELECTION, | |
| 183 &selection_clipboard_text); | |
| 184 return selection_clipboard_text; | |
| 185 } | |
| 186 | |
| 187 } // namespace | |
| 188 | |
| 189 // Crashes on Linux only. http://crbug.com/612406 | 202 // Crashes on Linux only. http://crbug.com/612406 |
| 190 #if defined(OS_LINUX) | 203 #if defined(OS_LINUX) |
| 191 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol | 204 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol |
| 192 #else | 205 #else |
| 193 #define MAYBE_FontPropertySymbol FontPropertySymbol | 206 #define MAYBE_FontPropertySymbol FontPropertySymbol |
| 194 #endif | 207 #endif |
| 195 TEST_F(LabelTest, MAYBE_FontPropertySymbol) { | 208 TEST_F(LabelTest, MAYBE_FontPropertySymbol) { |
| 196 std::string font_name("symbol"); | 209 std::string font_name("symbol"); |
| 197 gfx::Font font(font_name, 26); | 210 gfx::Font font(font_name, 26); |
| 198 label()->SetFontList(gfx::FontList(font)); | 211 label()->SetFontList(gfx::FontList(font)); |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 PerformMousePress(GetCursorPoint(5)); | 906 PerformMousePress(GetCursorPoint(5)); |
| 894 PerformMouseDragTo(gfx::Point()); | 907 PerformMouseDragTo(gfx::Point()); |
| 895 EXPECT_STR_EQ("Label", GetSelectedText()); | 908 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 896 | 909 |
| 897 PerformMouseDragTo(GetCursorPoint(8)); | 910 PerformMouseDragTo(GetCursorPoint(8)); |
| 898 EXPECT_STR_EQ(" mo", GetSelectedText()); | 911 EXPECT_STR_EQ(" mo", GetSelectedText()); |
| 899 | 912 |
| 900 PerformMouseDragTo(gfx::Point(200, 0)); | 913 PerformMouseDragTo(gfx::Point(200, 0)); |
| 901 PerformMouseRelease(gfx::Point(200, 0)); | 914 PerformMouseRelease(gfx::Point(200, 0)); |
| 902 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); | 915 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); |
| 916 | |
| 917 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); | |
| 918 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); | |
|
msw
2016/11/15 20:06:45
Avoid testing the system clipboard in unit tests.
tapted
2016/11/16 02:45:19
Yah - there is http://crbug.com/623442 about this
karandeepb
2016/11/16 07:48:29
Have created https://codereview.chromium.org/24993
| |
| 903 } | 919 } |
| 904 | 920 |
| 905 // Verify the initially selected word on a double click, remains selected on | 921 // Verify the initially selected word on a double click, remains selected on |
| 906 // mouse dragging. | 922 // mouse dragging. |
| 907 TEST_F(LabelSelectionTest, MouseDragWord) { | 923 TEST_F(LabelSelectionTest, MouseDragWord) { |
| 908 label()->SetText(ASCIIToUTF16("Label drag word")); | 924 label()->SetText(ASCIIToUTF16("Label drag word")); |
| 909 label()->SizeToPreferredSize(); | 925 label()->SizeToPreferredSize(); |
| 910 ASSERT_TRUE(label()->SetSelectable(true)); | 926 ASSERT_TRUE(label()->SetSelectable(true)); |
| 911 | 927 |
| 912 PerformClick(GetCursorPoint(8)); | 928 PerformClick(GetCursorPoint(8)); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 926 // http://crbug.com/396477. | 942 // http://crbug.com/396477. |
| 927 TEST_F(LabelSelectionTest, DISABLED_SelectionClipboard) { | 943 TEST_F(LabelSelectionTest, DISABLED_SelectionClipboard) { |
| 928 label()->SetText(ASCIIToUTF16("Label selection clipboard")); | 944 label()->SetText(ASCIIToUTF16("Label selection clipboard")); |
| 929 label()->SizeToPreferredSize(); | 945 label()->SizeToPreferredSize(); |
| 930 ASSERT_TRUE(label()->SetSelectable(true)); | 946 ASSERT_TRUE(label()->SetSelectable(true)); |
| 931 | 947 |
| 932 // Verify programmatic modification of selection, does not modify the | 948 // Verify programmatic modification of selection, does not modify the |
| 933 // selection clipboard. | 949 // selection clipboard. |
| 934 label()->SelectRange(gfx::Range(2, 5)); | 950 label()->SelectRange(gfx::Range(2, 5)); |
| 935 EXPECT_STR_EQ("bel", GetSelectedText()); | 951 EXPECT_STR_EQ("bel", GetSelectedText()); |
| 936 EXPECT_TRUE(GetSelectionClipboardText().empty()); | 952 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty()); |
| 937 | 953 |
| 938 // Verify text selection using the mouse updates the selection clipboard. | 954 // Verify text selection using the mouse updates the selection clipboard. |
| 939 PerformMousePress(GetCursorPoint(5)); | 955 PerformMousePress(GetCursorPoint(5)); |
| 940 PerformMouseDragTo(gfx::Point()); | 956 PerformMouseDragTo(gfx::Point()); |
| 941 PerformMouseRelease(gfx::Point()); | 957 PerformMouseRelease(gfx::Point()); |
| 942 EXPECT_STR_EQ("Label", GetSelectedText()); | 958 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 943 EXPECT_STR_EQ("Label", GetSelectionClipboardText()); | 959 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION)); |
| 944 } | 960 } |
| 945 #endif | 961 #endif |
| 946 | 962 |
| 963 // Verify that keyboard shortcuts for Copy and Select All work when a selectable | |
| 964 // label is focused. | |
| 965 TEST_F(LabelSelectionTest, KeyboardActions) { | |
| 966 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions"); | |
| 967 label()->SetText(initial_text); | |
| 968 label()->SizeToPreferredSize(); | |
| 969 ASSERT_TRUE(label()->SetSelectable(true)); | |
| 970 | |
| 971 PerformClick(gfx::Point()); | |
| 972 EXPECT_EQ(label(), GetFocusedView()); | |
| 973 | |
| 974 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier); | |
| 975 EXPECT_EQ(initial_text, GetSelectedText()); | |
| 976 | |
| 977 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); | |
| 978 EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); | |
|
msw
2016/11/15 20:06:45
You'll need to modify/disable this test for the sa
karandeepb
2016/11/16 07:48:29
Have created https://codereview.chromium.org/24993
| |
| 979 | |
| 980 // The selection should get cleared on changing the text, but focus should not | |
| 981 // be affected. | |
| 982 const base::string16 new_text = ASCIIToUTF16("Label obscured text"); | |
| 983 label()->SetText(new_text); | |
| 984 EXPECT_FALSE(label()->HasSelection()); | |
| 985 EXPECT_EQ(label(), GetFocusedView()); | |
| 986 | |
| 987 label()->SetObscured(true); | |
| 988 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier); | |
| 989 EXPECT_EQ(new_text, GetSelectedText()); | |
| 990 | |
| 991 // Since the text is obscured, clipboard text should not change. | |
| 992 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); | |
| 993 EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); | |
| 994 } | |
| 995 | |
| 996 // Verify the context menu options are enabled and disabled appropriately. | |
| 997 TEST_F(LabelSelectionTest, ContextMenuContents) { | |
| 998 label()->SetText(ASCIIToUTF16("Label context menu")); | |
| 999 label()->SizeToPreferredSize(); | |
| 1000 | |
| 1001 // A non-selectable label would not show a context menu and both COPY and | |
| 1002 // SELECT_ALL context menu items should be disabled for it. | |
| 1003 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY)); | |
| 1004 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL)); | |
| 1005 | |
| 1006 // For a selectable label with no selection, only SELECT_ALL should be | |
| 1007 // enabled. | |
| 1008 ASSERT_TRUE(label()->SetSelectable(true)); | |
| 1009 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY)); | |
| 1010 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL)); | |
| 1011 | |
| 1012 // For a selectable label with a selection, both COPY and SELECT_ALL should be | |
|
msw
2016/11/15 20:06:45
nit: also check that some unhandled command (eg. p
karandeepb
2016/11/16 07:48:29
Done.
| |
| 1013 // enabled. | |
| 1014 label()->SelectRange(gfx::Range(0, 4)); | |
| 1015 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_COPY)); | |
| 1016 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL)); | |
| 1017 | |
| 1018 // For an obscured selectable label, only SELECT_ALL should be enabled. | |
|
msw
2016/11/15 20:06:45
I wonder if we should disable select-all (or even
karandeepb
2016/11/16 07:48:29
Yeah I agree making obscured labels selectable doe
| |
| 1019 label()->SetObscured(true); | |
| 1020 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY)); | |
| 1021 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL)); | |
| 1022 | |
| 1023 // For an empty label, both COPY and SELECT_ALL should be disabled. | |
| 1024 label()->SetText(base::string16()); | |
| 1025 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY)); | |
| 1026 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL)); | |
| 1027 } | |
| 1028 | |
| 947 } // namespace views | 1029 } // namespace views |
| OLD | NEW |