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" |
| (...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 gfx::Point GetCursorPoint(int index, bool rtl = false) { |
|
msw
2016/12/13 03:04:56
nit: can we check if the text is rtl instead of pa
karandeepb
2016/12/16 02:58:38
Done.
| |
| 183 return label() | 184 label()->GetRenderTextForSelectionController()->EnsureLayout(); |
| 184 ->GetRenderTextForSelectionController() | 185 const std::vector<gfx::Rect> bounds = |
| 185 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), | 186 label()->GetRenderTextForSelectionController()->GetSubstringBounds( |
| 186 false) | 187 gfx::Range(index, index + 1)); |
| 187 .origin(); | 188 DCHECK_EQ(1u, bounds.size()); |
| 189 // Return Point corresponding to the leading edge of the character. | |
| 190 return gfx::Point(rtl ? bounds[0].right() - 1 : bounds[0].x() + 1, | |
| 191 bounds[0].y() + bounds[0].height() / 2); | |
| 192 } | |
| 193 | |
| 194 size_t GetLineCount() { | |
| 195 label()->GetRenderTextForSelectionController()->EnsureLayout(); | |
| 196 return label()->GetRenderTextForSelectionController()->lines().size(); | |
| 188 } | 197 } |
| 189 | 198 |
| 190 base::string16 GetSelectedText() { return label()->GetSelectedText(); } | 199 base::string16 GetSelectedText() { return label()->GetSelectedText(); } |
| 191 | 200 |
| 192 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } | 201 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } |
| 193 | 202 |
| 194 bool IsMenuCommandEnabled(int command_id) { | 203 bool IsMenuCommandEnabled(int command_id) { |
| 195 return label()->IsCommandIdEnabled(command_id); | 204 return label()->IsCommandIdEnabled(command_id); |
| 196 } | 205 } |
| 197 | 206 |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds.height()); | 822 EXPECT_LT(label()->font_list().GetHeight(), focus_bounds.height()); |
| 814 } | 823 } |
| 815 | 824 |
| 816 TEST_F(LabelSelectionTest, Selectable) { | 825 TEST_F(LabelSelectionTest, Selectable) { |
| 817 // By default, labels don't support text selection. | 826 // By default, labels don't support text selection. |
| 818 EXPECT_FALSE(label()->selectable()); | 827 EXPECT_FALSE(label()->selectable()); |
| 819 | 828 |
| 820 ASSERT_TRUE(label()->SetSelectable(true)); | 829 ASSERT_TRUE(label()->SetSelectable(true)); |
| 821 EXPECT_TRUE(label()->selectable()); | 830 EXPECT_TRUE(label()->selectable()); |
| 822 | 831 |
| 823 // Verify that making a label multiline causes the label to not support text | 832 // Verify that making a label multiline still causes the label to support text |
| 824 // selection. | 833 // selection. |
| 825 label()->SetMultiLine(true); | 834 label()->SetMultiLine(true); |
| 826 EXPECT_FALSE(label()->selectable()); | |
| 827 | |
| 828 label()->SetMultiLine(false); | |
| 829 ASSERT_TRUE(label()->SetSelectable(true)); | |
| 830 EXPECT_TRUE(label()->selectable()); | 835 EXPECT_TRUE(label()->selectable()); |
| 831 | 836 |
| 832 // Verify that obscuring the label text causes the label to not support text | 837 // Verify that obscuring the label text causes the label to not support text |
| 833 // selection. | 838 // selection. |
| 834 label()->SetObscured(true); | 839 label()->SetObscured(true); |
| 835 EXPECT_FALSE(label()->selectable()); | 840 EXPECT_FALSE(label()->selectable()); |
| 836 } | 841 } |
| 837 | 842 |
| 838 // Verify that labels supporting text selection get focus on clicks. | 843 // Verify that labels supporting text selection get focus on clicks. |
| 839 TEST_F(LabelSelectionTest, FocusOnClick) { | 844 TEST_F(LabelSelectionTest, FocusOnClick) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 widget()->GetFocusManager()->AdvanceFocus(false); | 884 widget()->GetFocusManager()->AdvanceFocus(false); |
| 880 EXPECT_EQ(label(), GetFocusedView()); | 885 EXPECT_EQ(label(), GetFocusedView()); |
| 881 } | 886 } |
| 882 | 887 |
| 883 // Verify label text selection behavior on double and triple clicks. | 888 // Verify label text selection behavior on double and triple clicks. |
| 884 TEST_F(LabelSelectionTest, DoubleTripleClick) { | 889 TEST_F(LabelSelectionTest, DoubleTripleClick) { |
| 885 label()->SetText(ASCIIToUTF16("Label double click")); | 890 label()->SetText(ASCIIToUTF16("Label double click")); |
| 886 label()->SizeToPreferredSize(); | 891 label()->SizeToPreferredSize(); |
| 887 ASSERT_TRUE(label()->SetSelectable(true)); | 892 ASSERT_TRUE(label()->SetSelectable(true)); |
| 888 | 893 |
| 889 PerformClick(gfx::Point()); | 894 PerformClick(GetCursorPoint(0)); |
| 890 EXPECT_TRUE(GetSelectedText().empty()); | 895 EXPECT_TRUE(GetSelectedText().empty()); |
| 891 | 896 |
| 892 // Double clicking should select the word under cursor. | 897 // Double clicking should select the word under cursor. |
| 893 PerformClick(gfx::Point(), ui::EF_IS_DOUBLE_CLICK); | 898 PerformClick(GetCursorPoint(0), ui::EF_IS_DOUBLE_CLICK); |
| 894 EXPECT_STR_EQ("Label", GetSelectedText()); | 899 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 895 | 900 |
| 896 // Triple clicking should select all the text. | 901 // Triple clicking should select all the text. |
| 897 PerformClick(gfx::Point()); | 902 PerformClick(GetCursorPoint(0)); |
| 898 EXPECT_EQ(label()->text(), GetSelectedText()); | 903 EXPECT_EQ(label()->text(), GetSelectedText()); |
| 899 | 904 |
| 900 // Clicking again should alternate to double click. | 905 // Clicking again should alternate to double click. |
| 901 PerformClick(gfx::Point()); | 906 PerformClick(GetCursorPoint(0)); |
| 902 EXPECT_STR_EQ("Label", GetSelectedText()); | 907 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 903 | 908 |
| 904 // Clicking at another location should clear the selection. | 909 // Clicking at another location should clear the selection. |
| 905 PerformClick(GetCursorPoint(8)); | 910 PerformClick(GetCursorPoint(8)); |
| 906 EXPECT_TRUE(GetSelectedText().empty()); | 911 EXPECT_TRUE(GetSelectedText().empty()); |
| 907 PerformClick(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); | 912 PerformClick(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); |
| 908 EXPECT_STR_EQ("double", GetSelectedText()); | 913 EXPECT_STR_EQ("double", GetSelectedText()); |
| 909 } | 914 } |
| 910 | 915 |
| 911 // Verify label text selection behavior on mouse drag. | 916 // Verify label text selection behavior on mouse drag. |
| 912 TEST_F(LabelSelectionTest, MouseDrag) { | 917 TEST_F(LabelSelectionTest, MouseDrag) { |
| 913 label()->SetText(ASCIIToUTF16("Label mouse drag")); | 918 label()->SetText(ASCIIToUTF16("Label mouse drag")); |
| 914 label()->SizeToPreferredSize(); | 919 label()->SizeToPreferredSize(); |
| 915 ASSERT_TRUE(label()->SetSelectable(true)); | 920 ASSERT_TRUE(label()->SetSelectable(true)); |
| 916 | 921 |
| 917 PerformMousePress(GetCursorPoint(5)); | 922 PerformMousePress(GetCursorPoint(5)); |
| 918 PerformMouseDragTo(gfx::Point()); | 923 PerformMouseDragTo(GetCursorPoint(0)); |
| 919 EXPECT_STR_EQ("Label", GetSelectedText()); | 924 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 920 | 925 |
| 921 PerformMouseDragTo(GetCursorPoint(8)); | 926 PerformMouseDragTo(GetCursorPoint(8)); |
| 922 EXPECT_STR_EQ(" mo", GetSelectedText()); | 927 EXPECT_STR_EQ(" mo", GetSelectedText()); |
| 923 | 928 |
| 924 PerformMouseDragTo(gfx::Point(200, 0)); | 929 PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y())); |
| 925 PerformMouseRelease(gfx::Point(200, 0)); | 930 PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y())); |
| 926 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); | 931 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); |
| 927 | 932 |
| 928 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); | 933 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier); |
| 929 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); | 934 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE)); |
| 930 } | 935 } |
| 931 | 936 |
| 937 TEST_F(LabelSelectionTest, MouseDragMultilineLTR) { | |
| 938 label()->SetMultiLine(true); | |
| 939 label()->SetText(ASCIIToUTF16("abcd\nefgh")); | |
| 940 label()->SizeToPreferredSize(); | |
| 941 ASSERT_TRUE(label()->SetSelectable(true)); | |
| 942 ASSERT_EQ(2u, GetLineCount()); | |
| 943 | |
| 944 PerformMousePress(GetCursorPoint(2)); | |
| 945 PerformMouseDragTo(GetCursorPoint(0)); | |
| 946 EXPECT_STR_EQ("ab", GetSelectedText()); | |
| 947 | |
| 948 PerformMouseDragTo(GetCursorPoint(7)); | |
| 949 EXPECT_STR_EQ("cd\nef", GetSelectedText()); | |
| 950 | |
| 951 PerformMouseDragTo(gfx::Point(-5, GetCursorPoint(6).y())); | |
| 952 EXPECT_STR_EQ("cd\n", GetSelectedText()); | |
| 953 | |
| 954 PerformMouseDragTo(gfx::Point(100, GetCursorPoint(6).y())); | |
| 955 EXPECT_STR_EQ("cd\nefgh", GetSelectedText()); | |
| 956 | |
| 957 PerformMouseDragTo(gfx::Point(GetCursorPoint(3).x(), -5)); | |
| 958 EXPECT_STR_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? "ab" : "c", | |
| 959 GetSelectedText()); | |
| 960 | |
| 961 PerformMouseDragTo(gfx::Point(GetCursorPoint(7).x(), 100)); | |
| 962 EXPECT_STR_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds ? "cd\nefgh" | |
| 963 : "cd\nef", | |
| 964 GetSelectedText()); | |
| 965 } | |
| 966 | |
| 967 TEST_F(LabelSelectionTest, MouseDragMultilineRTL) { | |
| 968 label()->SetMultiLine(true); | |
| 969 label()->SetText(WideToUTF16(L"\x5d0\x5d1\x5d2\n\x5d3\x5d4\x5d5")); | |
| 970 label()->SizeToPreferredSize(); | |
| 971 ASSERT_TRUE(label()->SetSelectable(true)); | |
| 972 ASSERT_EQ(2u, GetLineCount()); | |
| 973 | |
| 974 PerformMousePress(GetCursorPoint(1, true)); | |
| 975 PerformMouseDragTo(GetCursorPoint(0, true)); | |
| 976 EXPECT_EQ(WideToUTF16(L"\x5d0"), GetSelectedText()); | |
| 977 | |
| 978 PerformMouseDragTo(GetCursorPoint(6, true)); | |
| 979 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4"), GetSelectedText()); | |
| 980 | |
| 981 PerformMouseDragTo(gfx::Point(-5, GetCursorPoint(6, true).y())); | |
| 982 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4\x5d5"), GetSelectedText()); | |
| 983 | |
| 984 PerformMouseDragTo(gfx::Point(100, GetCursorPoint(6, true).y())); | |
| 985 EXPECT_EQ(WideToUTF16(L"\x5d1\x5d2\n"), GetSelectedText()); | |
| 986 | |
| 987 PerformMouseDragTo(gfx::Point(GetCursorPoint(2, true).x(), -5)); | |
| 988 EXPECT_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds | |
| 989 ? WideToUTF16(L"\x5d0") | |
| 990 : WideToUTF16(L"\x5d1"), | |
| 991 GetSelectedText()); | |
| 992 | |
| 993 PerformMouseDragTo(gfx::Point(GetCursorPoint(6, true).x(), 100)); | |
| 994 EXPECT_EQ(gfx::RenderText::kDragToEndIfOutsideVerticalBounds | |
| 995 ? WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4\x5d5") | |
| 996 : WideToUTF16(L"\x5d1\x5d2\n\x5d3\x5d4"), | |
| 997 GetSelectedText()); | |
| 998 } | |
| 999 | |
| 932 // Verify the initially selected word on a double click, remains selected on | 1000 // Verify the initially selected word on a double click, remains selected on |
| 933 // mouse dragging. | 1001 // mouse dragging. |
| 934 TEST_F(LabelSelectionTest, MouseDragWord) { | 1002 TEST_F(LabelSelectionTest, MouseDragWord) { |
| 935 label()->SetText(ASCIIToUTF16("Label drag word")); | 1003 label()->SetText(ASCIIToUTF16("Label drag word")); |
| 936 label()->SizeToPreferredSize(); | 1004 label()->SizeToPreferredSize(); |
| 937 ASSERT_TRUE(label()->SetSelectable(true)); | 1005 ASSERT_TRUE(label()->SetSelectable(true)); |
| 938 | 1006 |
| 939 PerformClick(GetCursorPoint(8)); | 1007 PerformClick(GetCursorPoint(8)); |
| 940 PerformMousePress(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); | 1008 PerformMousePress(GetCursorPoint(8), ui::EF_IS_DOUBLE_CLICK); |
| 941 EXPECT_STR_EQ("drag", GetSelectedText()); | 1009 EXPECT_STR_EQ("drag", GetSelectedText()); |
| 942 | 1010 |
| 943 PerformMouseDragTo(gfx::Point()); | 1011 PerformMouseDragTo(GetCursorPoint(0)); |
| 944 EXPECT_STR_EQ("Label drag", GetSelectedText()); | 1012 EXPECT_STR_EQ("Label drag", GetSelectedText()); |
| 945 | 1013 |
| 946 PerformMouseDragTo(gfx::Point(200, 0)); | 1014 PerformMouseDragTo(gfx::Point(200, GetCursorPoint(0).y())); |
| 947 PerformMouseRelease(gfx::Point(200, 0)); | 1015 PerformMouseRelease(gfx::Point(200, GetCursorPoint(0).y())); |
| 948 EXPECT_STR_EQ("drag word", GetSelectedText()); | 1016 EXPECT_STR_EQ("drag word", GetSelectedText()); |
| 949 } | 1017 } |
| 950 | 1018 |
| 951 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 1019 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 952 // Verify selection clipboard behavior on text selection. | 1020 // Verify selection clipboard behavior on text selection. |
| 953 TEST_F(LabelSelectionTest, SelectionClipboard) { | 1021 TEST_F(LabelSelectionTest, SelectionClipboard) { |
| 954 label()->SetText(ASCIIToUTF16("Label selection clipboard")); | 1022 label()->SetText(ASCIIToUTF16("Label selection clipboard")); |
| 955 label()->SizeToPreferredSize(); | 1023 label()->SizeToPreferredSize(); |
| 956 ASSERT_TRUE(label()->SetSelectable(true)); | 1024 ASSERT_TRUE(label()->SetSelectable(true)); |
| 957 | 1025 |
| 958 // Verify programmatic modification of selection, does not modify the | 1026 // Verify programmatic modification of selection, does not modify the |
| 959 // selection clipboard. | 1027 // selection clipboard. |
| 960 label()->SelectRange(gfx::Range(2, 5)); | 1028 label()->SelectRange(gfx::Range(2, 5)); |
| 961 EXPECT_STR_EQ("bel", GetSelectedText()); | 1029 EXPECT_STR_EQ("bel", GetSelectedText()); |
| 962 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty()); | 1030 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty()); |
| 963 | 1031 |
| 964 // Verify text selection using the mouse updates the selection clipboard. | 1032 // Verify text selection using the mouse updates the selection clipboard. |
| 965 PerformMousePress(GetCursorPoint(5)); | 1033 PerformMousePress(GetCursorPoint(5)); |
| 966 PerformMouseDragTo(gfx::Point()); | 1034 PerformMouseDragTo(GetCursorPoint(0)); |
| 967 PerformMouseRelease(gfx::Point()); | 1035 PerformMouseRelease(GetCursorPoint(0)); |
| 968 EXPECT_STR_EQ("Label", GetSelectedText()); | 1036 EXPECT_STR_EQ("Label", GetSelectedText()); |
| 969 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION)); | 1037 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION)); |
| 970 } | 1038 } |
| 971 #endif | 1039 #endif |
| 972 | 1040 |
| 973 // Verify that keyboard shortcuts for Copy and Select All work when a selectable | 1041 // Verify that keyboard shortcuts for Copy and Select All work when a selectable |
| 974 // label is focused. | 1042 // label is focused. |
| 975 TEST_F(LabelSelectionTest, KeyboardActions) { | 1043 TEST_F(LabelSelectionTest, KeyboardActions) { |
| 976 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions"); | 1044 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions"); |
| 977 label()->SetText(initial_text); | 1045 label()->SetText(initial_text); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1034 label()->SetObscured(false); | 1102 label()->SetObscured(false); |
| 1035 | 1103 |
| 1036 // For an empty label, both COPY and SELECT_ALL should be disabled. | 1104 // For an empty label, both COPY and SELECT_ALL should be disabled. |
| 1037 label()->SetText(base::string16()); | 1105 label()->SetText(base::string16()); |
| 1038 ASSERT_TRUE(label()->SetSelectable(true)); | 1106 ASSERT_TRUE(label()->SetSelectable(true)); |
| 1039 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); | 1107 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); |
| 1040 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); | 1108 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); |
| 1041 } | 1109 } |
| 1042 | 1110 |
| 1043 } // namespace views | 1111 } // namespace views |
| OLD | NEW |