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" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
22 #include "ui/gfx/render_text.h" | 22 #include "ui/gfx/render_text.h" |
23 #include "ui/gfx/switches.h" | 23 #include "ui/gfx/switches.h" |
24 #include "ui/strings/grit/ui_strings.h" | 24 #include "ui/strings/grit/ui_strings.h" |
25 #include "ui/views/border.h" | 25 #include "ui/views/border.h" |
26 #include "ui/views/test/focus_manager_test.h" | 26 #include "ui/views/test/focus_manager_test.h" |
27 #include "ui/views/test/views_test_base.h" | 27 #include "ui/views/test/views_test_base.h" |
28 #include "ui/views/widget/widget.h" | 28 #include "ui/views/widget/widget.h" |
29 | 29 |
30 using base::ASCIIToUTF16; | 30 using base::ASCIIToUTF16; |
31 using base::WideToUTF16; | |
31 | 32 |
32 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) | 33 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) |
33 | 34 |
34 namespace views { | 35 namespace views { |
35 | 36 |
36 namespace { | 37 namespace { |
37 | 38 |
38 #if defined(OS_MACOSX) | 39 #if defined(OS_MACOSX) |
39 const int kControlCommandModifier = ui::EF_COMMAND_DOWN; | 40 const int kControlCommandModifier = ui::EF_COMMAND_DOWN; |
40 #else | 41 #else |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
172 PerformMousePress(point, extra_flags); | 173 PerformMousePress(point, extra_flags); |
173 PerformMouseRelease(point); | 174 PerformMouseRelease(point); |
174 } | 175 } |
175 | 176 |
176 void PerformMouseDragTo(const gfx::Point& point) { | 177 void PerformMouseDragTo(const gfx::Point& point) { |
177 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point, point, | 178 ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point, point, |
178 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); | 179 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); |
179 label()->OnMouseDragged(drag); | 180 label()->OnMouseDragged(drag); |
180 } | 181 } |
181 | 182 |
182 gfx::Point GetCursorPoint(int cursor_pos) { | 183 void SimulatePaint() { |
msw
2016/12/19 22:27:43
nit: add a comment, explain that this is used to e
karandeepb
2016/12/21 14:23:44
Done.
| |
183 return label() | 184 gfx::Canvas canvas; |
184 ->GetRenderTextForSelectionController() | 185 label()->OnPaint(&canvas); |
185 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), | 186 } |
186 false) | 187 |
187 .origin(); | 188 gfx::Point GetCursorPoint(int index) { |
189 SimulatePaint(); | |
190 const std::vector<gfx::Rect> bounds = | |
191 label() | |
192 ->GetRenderTextForSelectionController() | |
msw
2016/12/19 22:27:43
optional nit: cache the RenderText pointer
karandeepb
2016/12/21 14:23:44
Done.
| |
193 ->GetSubstringBoundsForTesting(gfx::Range(index, index + 1)); | |
194 DCHECK_EQ(1u, bounds.size()); | |
195 | |
196 const bool rtl = | |
197 label() | |
198 ->GetRenderTextForSelectionController() | |
199 ->GetDisplayTextDirection() == base::i18n::RIGHT_TO_LEFT; | |
200 // Return Point corresponding to the leading edge of the character. | |
201 return gfx::Point(rtl ? bounds[0].right() - 1 : bounds[0].x() + 1, | |
202 bounds[0].y() + bounds[0].height() / 2); | |
203 } | |
204 | |
205 size_t GetLineCount() { | |
206 SimulatePaint(); | |
207 return label()->GetRenderTextForSelectionController()->GetNumLines(); | |
188 } | 208 } |
189 | 209 |
190 base::string16 GetSelectedText() { return label()->GetSelectedText(); } | 210 base::string16 GetSelectedText() { return label()->GetSelectedText(); } |
191 | 211 |
192 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } | 212 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } |
193 | 213 |
194 bool IsMenuCommandEnabled(int command_id) { | 214 bool IsMenuCommandEnabled(int command_id) { |
195 return label()->IsCommandIdEnabled(command_id); | 215 return label()->IsCommandIdEnabled(command_id); |
196 } | 216 } |
197 | 217 |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
813 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds.height()); | 833 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds.height()); |
814 } | 834 } |
815 | 835 |
816 TEST_F(LabelSelectionTest, Selectable) { | 836 TEST_F(LabelSelectionTest, Selectable) { |
817 // By default, labels don't support text selection. | 837 // By default, labels don't support text selection. |
818 EXPECT_FALSE(label()->selectable()); | 838 EXPECT_FALSE(label()->selectable()); |
819 | 839 |
820 ASSERT_TRUE(label()->SetSelectable(true)); | 840 ASSERT_TRUE(label()->SetSelectable(true)); |
821 EXPECT_TRUE(label()->selectable()); | 841 EXPECT_TRUE(label()->selectable()); |
822 | 842 |
823 // Verify that making a label multiline causes the label to not support text | 843 // Verify that making a label multiline still causes the label to support text |
824 // selection. | 844 // selection. |
825 label()->SetMultiLine(true); | 845 label()->SetMultiLine(true); |
826 EXPECT_FALSE(label()->selectable()); | |
827 | |
828 label()->SetMultiLine(false); | |
829 ASSERT_TRUE(label()->SetSelectable(true)); | |
830 EXPECT_TRUE(label()->selectable()); | 846 EXPECT_TRUE(label()->selectable()); |
831 | 847 |
832 // Verify that obscuring the label text causes the label to not support text | 848 // Verify that obscuring the label text causes the label to not support text |
833 // selection. | 849 // selection. |
834 label()->SetObscured(true); | 850 label()->SetObscured(true); |
835 EXPECT_FALSE(label()->selectable()); | 851 EXPECT_FALSE(label()->selectable()); |
836 } | 852 } |
837 | 853 |
838 // Verify that labels supporting text selection get focus on clicks. | 854 // Verify that labels supporting text selection get focus on clicks. |
839 TEST_F(LabelSelectionTest, FocusOnClick) { | 855 TEST_F(LabelSelectionTest, FocusOnClick) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
879 widget()->GetFocusManager()->AdvanceFocus(false); | 895 widget()->GetFocusManager()->AdvanceFocus(false); |
880 EXPECT_EQ(label(), GetFocusedView()); | 896 EXPECT_EQ(label(), GetFocusedView()); |
881 } | 897 } |
882 | 898 |
883 // Verify label text selection behavior on double and triple clicks. | 899 // Verify label text selection behavior on double and triple clicks. |
884 TEST_F(LabelSelectionTest, DoubleTripleClick) { | 900 TEST_F(LabelSelectionTest, DoubleTripleClick) { |
885 label()->SetText(ASCIIToUTF16("Label double click")); | 901 label()->SetText(ASCIIToUTF16("Label double click")); |
886 label()->SizeToPreferredSize(); | 902 label()->SizeToPreferredSize(); |
887 ASSERT_TRUE(label()->SetSelectable(true)); | 903 ASSERT_TRUE(label()->SetSelectable(true)); |
888 | 904 |
889 PerformClick(gfx::Point()); | 905 PerformClick(GetCursorPoint(0)); |
890 EXPECT_TRUE(GetSelectedText().empty()); | 906 EXPECT_TRUE(GetSelectedText().empty()); |
891 | 907 |
892 // Double clicking should select the word under cursor. | 908 // Double clicking should select the word under cursor. |
893 PerformClick(gfx::Point(), ui::EF_IS_DOUBLE_CLICK); | 909 PerformClick(GetCursorPoint(0), ui::EF_IS_DOUBLE_CLICK); |
894 EXPECT_STR_EQ("Label", GetSelectedText()); | 910 EXPECT_STR_EQ("Label", GetSelectedText()); |
895 | 911 |
896 // Triple clicking should select all the text. | 912 // Triple clicking should select all the text. |
897 PerformClick(gfx::Point()); | 913 PerformClick(GetCursorPoint(0)); |
898 EXPECT_EQ(label()->text(), GetSelectedText()); | 914 EXPECT_EQ(label()->text(), GetSelectedText()); |
899 | 915 |
900 // Clicking again should alternate to double click. | 916 // Clicking again should alternate to double click. |
901 PerformClick(gfx::Point()); | 917 PerformClick(GetCursorPoint(0)); |
902 EXPECT_STR_EQ("Label", GetSelectedText()); | 918 EXPECT_STR_EQ("Label", GetSelectedText()); |
903 | 919 |
904 // Clicking at another location should clear the selection. | 920 // Clicking at another location should clear the selection. |
905 PerformClick(GetCursorPoint(8)); | 921 PerformClick(GetCursorPoint(8)); |
906 EXPECT_TRUE(GetSelectedText().empty()); | 922 EXPECT_TRUE(GetSelectedText().empty()); |
907 PerformClick(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); | 923 PerformClick(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); |
908 EXPECT_STR_EQ("double", GetSelectedText()); | 924 EXPECT_STR_EQ("double", GetSelectedText()); |
909 } | 925 } |
910 | 926 |
911 // Verify label text selection behavior on mouse drag. | 927 // Verify label text selection behavior on mouse drag. |
912 TEST_F(LabelSelectionTest, MouseDrag) { | 928 TEST_F(LabelSelectionTest, MouseDrag) { |
913 label()->SetText(ASCIIToUTF16("Label mouse drag")); | 929 label()->SetText(ASCIIToUTF16("Label mouse drag")); |
914 label()->SizeToPreferredSize(); | 930 label()->SizeToPreferredSize(); |
915 ASSERT_TRUE(label()->SetSelectable(true)); | 931 ASSERT_TRUE(label()->SetSelectable(true)); |
916 | 932 |
917 PerformMousePress(GetCursorPoint(5)); | 933 PerformMousePress(GetCursorPoint(5)); |
918 PerformMouseDragTo(gfx::Point()); | 934 PerformMouseDragTo(GetCursorPoint(0)); |
919 EXPECT_STR_EQ("Label", GetSelectedText()); | 935 EXPECT_STR_EQ("Label", GetSelectedText()); |
920 | 936 |
921 PerformMouseDragTo(GetCursorPoint(8)); | 937 PerformMouseDragTo(GetCursorPoint(8)); |
922 EXPECT_STR_EQ(" mo", GetSelectedText()); | 938 EXPECT_STR_EQ(" mo", GetSelectedText()); |
923 | 939 |
924 PerformMouseDragTo(gfx::Point(200, 0)); | 940 PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y())); |
925 PerformMouseRelease(gfx::Point(200, 0)); | 941 PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y())); |
926 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); | 942 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); |
927 | 943 |
928 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); | 944 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); |
929 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); | 945 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); |
930 } | 946 } |
931 | 947 |
948 TEST_F(LabelSelectionTest, MouseDragMultilineLTR) { | |
949 label()->SetMultiLine(true); | |
950 label()->SetText(ASCIIToUTF16("abcd\nefgh")); | |
951 label()->SizeToPreferredSize(); | |
952 ASSERT_TRUE(label()->SetSelectable(true)); | |
953 ASSERT_EQ(2u, GetLineCount()); | |
954 | |
955 PerformMousePress(GetCursorPoint(2)); | |
956 PerformMouseDragTo(GetCursorPoint(0)); | |
957 EXPECT_STR_EQ("ab", GetSelectedText()); | |
958 | |
959 PerformMouseDragTo(GetCursorPoint(7)); | |
960 EXPECT_STR_EQ("cd\nef", GetSelectedText()); | |
961 | |
962 PerformMouseDragTo(gfx::Point(-5, GetCursorPoint(6).y())); | |
963 EXPECT_STR_EQ("cd\n", GetSelectedText()); | |
964 | |
965 PerformMouseDragTo(gfx::Point(100, GetCursorPoint(6).y())); | |
966 EXPECT_STR_EQ("cd\nefgh", GetSelectedText()); | |
967 | |
968 PerformMouseDragTo(gfx::Point(GetCursorPoint(3).x(), -5)); | |
969 EXPECT_STR_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? "ab" : "c", | |
970 GetSelectedText()); | |
971 | |
972 PerformMouseDragTo(gfx::Point(GetCursorPoint(7).x(), 100)); | |
973 EXPECT_STR_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? "cd\nefgh" | |
974 : "cd\nef", | |
975 GetSelectedText()); | |
976 } | |
977 | |
978 TEST_F(LabelSelectionTest, MouseDragMultilineRTL) { | |
979 label()->SetMultiLine(true); | |
980 label()->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\n\x5d3\x5d4\x5d5")); | |
981 label()->SizeToPreferredSize(); | |
982 ASSERT_TRUE(label()->SetSelectable(true)); | |
983 ASSERT_EQ(2u, GetLineCount()); | |
984 | |
985 PerformMousePress(GetCursorPoint(1)); | |
986 PerformMouseDragTo(GetCursorPoint(0)); | |
987 EXPECT_EQ(WideToUTF16(L"\x5d0"), GetSelectedText()); | |
988 | |
989 PerformMouseDragTo(GetCursorPoint(6)); | |
990 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4"), GetSelectedText()); | |
991 | |
992 PerformMouseDragTo(gfx::Point(-5, GetCursorPoint(6).y())); | |
993 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4\x5d5"), GetSelectedText()); | |
994 | |
995 PerformMouseDragTo(gfx::Point(100, GetCursorPoint(6).y())); | |
996 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n"), GetSelectedText()); | |
997 | |
998 PerformMouseDragTo(gfx::Point(GetCursorPoint(2).x(), -5)); | |
999 EXPECT_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds | |
1000 ? WideToUTF16(L"\x5d0") | |
1001 : WideToUTF16(L"\x5d1"), | |
1002 GetSelectedText()); | |
1003 | |
1004 PerformMouseDragTo(gfx::Point(GetCursorPoint(6).x(), 100)); | |
1005 EXPECT_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds | |
1006 ? WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4\x5d5") | |
1007 : WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4"), | |
1008 GetSelectedText()); | |
1009 } | |
1010 | |
932 // Verify the initially selected word on a double click, remains selected on | 1011 // Verify the initially selected word on a double click, remains selected on |
933 // mouse dragging. | 1012 // mouse dragging. |
934 TEST_F(LabelSelectionTest, MouseDragWord) { | 1013 TEST_F(LabelSelectionTest, MouseDragWord) { |
935 label()->SetText(ASCIIToUTF16("Label drag word")); | 1014 label()->SetText(ASCIIToUTF16("Label drag word")); |
936 label()->SizeToPreferredSize(); | 1015 label()->SizeToPreferredSize(); |
937 ASSERT_TRUE(label()->SetSelectable(true)); | 1016 ASSERT_TRUE(label()->SetSelectable(true)); |
938 | 1017 |
939 PerformClick(GetCursorPoint(8)); | 1018 PerformClick(GetCursorPoint(8)); |
940 PerformMousePress(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); | 1019 PerformMousePress(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); |
941 EXPECT_STR_EQ("drag", GetSelectedText()); | 1020 EXPECT_STR_EQ("drag", GetSelectedText()); |
942 | 1021 |
943 PerformMouseDragTo(gfx::Point()); | 1022 PerformMouseDragTo(GetCursorPoint(0)); |
944 EXPECT_STR_EQ("Label drag", GetSelectedText()); | 1023 EXPECT_STR_EQ("Label drag", GetSelectedText()); |
945 | 1024 |
946 PerformMouseDragTo(gfx::Point(200, 0)); | 1025 PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y())); |
947 PerformMouseRelease(gfx::Point(200, 0)); | 1026 PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y())); |
948 EXPECT_STR_EQ("drag word", GetSelectedText()); | 1027 EXPECT_STR_EQ("drag word", GetSelectedText()); |
949 } | 1028 } |
950 | 1029 |
951 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 1030 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
952 // Verify selection clipboard behavior on text selection. | 1031 // Verify selection clipboard behavior on text selection. |
953 TEST_F(LabelSelectionTest, SelectionClipboard) { | 1032 TEST_F(LabelSelectionTest, SelectionClipboard) { |
954 label()->SetText(ASCIIToUTF16("Label selection clipboard")); | 1033 label()->SetText(ASCIIToUTF16("Label selection clipboard")); |
955 label()->SizeToPreferredSize(); | 1034 label()->SizeToPreferredSize(); |
956 ASSERT_TRUE(label()->SetSelectable(true)); | 1035 ASSERT_TRUE(label()->SetSelectable(true)); |
957 | 1036 |
958 // Verify programmatic modification of selection, does not modify the | 1037 // Verify programmatic modification of selection, does not modify the |
959 // selection clipboard. | 1038 // selection clipboard. |
960 label()->SelectRange(gfx::Range(2, 5)); | 1039 label()->SelectRange(gfx::Range(2, 5)); |
961 EXPECT_STR_EQ("bel", GetSelectedText()); | 1040 EXPECT_STR_EQ("bel", GetSelectedText()); |
962 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty()); | 1041 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty()); |
963 | 1042 |
964 // Verify text selection using the mouse updates the selection clipboard. | 1043 // Verify text selection using the mouse updates the selection clipboard. |
965 PerformMousePress(GetCursorPoint(5)); | 1044 PerformMousePress(GetCursorPoint(5)); |
966 PerformMouseDragTo(gfx::Point()); | 1045 PerformMouseDragTo(GetCursorPoint(0)); |
967 PerformMouseRelease(gfx::Point()); | 1046 PerformMouseRelease(GetCursorPoint(0)); |
968 EXPECT_STR_EQ("Label", GetSelectedText()); | 1047 EXPECT_STR_EQ("Label", GetSelectedText()); |
969 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION)); | 1048 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION)); |
970 } | 1049 } |
971 #endif | 1050 #endif |
972 | 1051 |
973 // Verify that keyboard shortcuts for Copy and Select All work when a selectable | 1052 // Verify that keyboard shortcuts for Copy and Select All work when a selectable |
974 // label is focused. | 1053 // label is focused. |
975 TEST_F(LabelSelectionTest, KeyboardActions) { | 1054 TEST_F(LabelSelectionTest, KeyboardActions) { |
976 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions"); | 1055 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions"); |
977 label()->SetText(initial_text); | 1056 label()->SetText(initial_text); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 label()->SetObscured(false); | 1113 label()->SetObscured(false); |
1035 | 1114 |
1036 // For an empty label, both COPY and SELECT_ALL should be disabled. | 1115 // For an empty label, both COPY and SELECT_ALL should be disabled. |
1037 label()->SetText(base::string16()); | 1116 label()->SetText(base::string16()); |
1038 ASSERT_TRUE(label()->SetSelectable(true)); | 1117 ASSERT_TRUE(label()->SetSelectable(true)); |
1039 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); | 1118 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); |
1040 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); | 1119 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); |
1041 } | 1120 } |
1042 | 1121 |
1043 } // namespace views | 1122 } // namespace views |
OLD | NEW |