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

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

Issue 2541313002: RenderTextHarfBuzz: Add support for multi line text selection. (Closed)
Patch Set: Nits. Created 4 years 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
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 "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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698