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

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

Issue 2422993002: views::Label: Implement context menu, keyboard shortcuts for copy/select all. (Closed)
Patch Set: Address comments. Created 4 years, 1 month 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
« no previous file with comments | « ui/views/controls/label.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
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
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_ =
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
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() { return event_generator_.get(); }
131 return render_text->GetTextFromRange(render_text->selection()); 193
194 bool IsMenuCommandEnabled(int command_id) {
195 return label()->IsCommandIdEnabled(command_id);
132 } 196 }
133 197
134 private: 198 private:
199 std::unique_ptr<ui::test::EventGenerator> event_generator_;
200
135 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest); 201 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest);
136 }; 202 };
137 203
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 204 // Crashes on Linux only. http://crbug.com/612406
190 #if defined(OS_LINUX) 205 #if defined(OS_LINUX)
191 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol 206 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol
192 #else 207 #else
193 #define MAYBE_FontPropertySymbol FontPropertySymbol 208 #define MAYBE_FontPropertySymbol FontPropertySymbol
194 #endif 209 #endif
195 TEST_F(LabelTest, MAYBE_FontPropertySymbol) { 210 TEST_F(LabelTest, MAYBE_FontPropertySymbol) {
196 std::string font_name("symbol"); 211 std::string font_name("symbol");
197 gfx::Font font(font_name, 26); 212 gfx::Font font(font_name, 26);
198 label()->SetFontList(gfx::FontList(font)); 213 label()->SetFontList(gfx::FontList(font));
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 // By default, labels don't support text selection. 817 // By default, labels don't support text selection.
803 EXPECT_FALSE(label()->selectable()); 818 EXPECT_FALSE(label()->selectable());
804 819
805 ASSERT_TRUE(label()->SetSelectable(true)); 820 ASSERT_TRUE(label()->SetSelectable(true));
806 EXPECT_TRUE(label()->selectable()); 821 EXPECT_TRUE(label()->selectable());
807 822
808 // Verify that making a label multiline causes the label to not support text 823 // Verify that making a label multiline causes the label to not support text
809 // selection. 824 // selection.
810 label()->SetMultiLine(true); 825 label()->SetMultiLine(true);
811 EXPECT_FALSE(label()->selectable()); 826 EXPECT_FALSE(label()->selectable());
827
828 label()->SetMultiLine(false);
829 ASSERT_TRUE(label()->SetSelectable(true));
830 EXPECT_TRUE(label()->selectable());
831
832 // Verify that obscuring the label text causes the label to not support text
833 // selection.
834 label()->SetObscured(true);
835 EXPECT_FALSE(label()->selectable());
812 } 836 }
813 837
814 // Verify that labels supporting text selection get focus on clicks. 838 // Verify that labels supporting text selection get focus on clicks.
815 TEST_F(LabelSelectionTest, FocusOnClick) { 839 TEST_F(LabelSelectionTest, FocusOnClick) {
816 label()->SetText(ASCIIToUTF16("text")); 840 label()->SetText(ASCIIToUTF16("text"));
817 label()->SizeToPreferredSize(); 841 label()->SizeToPreferredSize();
818 842
819 // By default, labels don't get focus on click. 843 // By default, labels don't get focus on click.
820 PerformClick(gfx::Point()); 844 PerformClick(gfx::Point());
821 EXPECT_NE(label(), GetFocusedView()); 845 EXPECT_NE(label(), GetFocusedView());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 PerformMousePress(GetCursorPoint(5)); 917 PerformMousePress(GetCursorPoint(5));
894 PerformMouseDragTo(gfx::Point()); 918 PerformMouseDragTo(gfx::Point());
895 EXPECT_STR_EQ("Label", GetSelectedText()); 919 EXPECT_STR_EQ("Label", GetSelectedText());
896 920
897 PerformMouseDragTo(GetCursorPoint(8)); 921 PerformMouseDragTo(GetCursorPoint(8));
898 EXPECT_STR_EQ(" mo", GetSelectedText()); 922 EXPECT_STR_EQ(" mo", GetSelectedText());
899 923
900 PerformMouseDragTo(gfx::Point(200, 0)); 924 PerformMouseDragTo(gfx::Point(200, 0));
901 PerformMouseRelease(gfx::Point(200, 0)); 925 PerformMouseRelease(gfx::Point(200, 0));
902 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); 926 EXPECT_STR_EQ(" mouse drag", GetSelectedText());
927
928 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
929 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
903 } 930 }
904 931
905 // Verify the initially selected word on a double click, remains selected on 932 // Verify the initially selected word on a double click, remains selected on
906 // mouse dragging. 933 // mouse dragging.
907 TEST_F(LabelSelectionTest, MouseDragWord) { 934 TEST_F(LabelSelectionTest, MouseDragWord) {
908 label()->SetText(ASCIIToUTF16("Label drag word")); 935 label()->SetText(ASCIIToUTF16("Label drag word"));
909 label()->SizeToPreferredSize(); 936 label()->SizeToPreferredSize();
910 ASSERT_TRUE(label()->SetSelectable(true)); 937 ASSERT_TRUE(label()->SetSelectable(true));
911 938
912 PerformClick(GetCursorPoint(8)); 939 PerformClick(GetCursorPoint(8));
(...skipping 12 matching lines...) Expand all
925 // Verify selection clipboard behavior on text selection. 952 // Verify selection clipboard behavior on text selection.
926 TEST_F(LabelSelectionTest, SelectionClipboard) { 953 TEST_F(LabelSelectionTest, SelectionClipboard) {
927 label()->SetText(ASCIIToUTF16("Label selection clipboard")); 954 label()->SetText(ASCIIToUTF16("Label selection clipboard"));
928 label()->SizeToPreferredSize(); 955 label()->SizeToPreferredSize();
929 ASSERT_TRUE(label()->SetSelectable(true)); 956 ASSERT_TRUE(label()->SetSelectable(true));
930 957
931 // Verify programmatic modification of selection, does not modify the 958 // Verify programmatic modification of selection, does not modify the
932 // selection clipboard. 959 // selection clipboard.
933 label()->SelectRange(gfx::Range(2, 5)); 960 label()->SelectRange(gfx::Range(2, 5));
934 EXPECT_STR_EQ("bel", GetSelectedText()); 961 EXPECT_STR_EQ("bel", GetSelectedText());
935 EXPECT_TRUE(GetSelectionClipboardText().empty()); 962 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
936 963
937 // Verify text selection using the mouse updates the selection clipboard. 964 // Verify text selection using the mouse updates the selection clipboard.
938 PerformMousePress(GetCursorPoint(5)); 965 PerformMousePress(GetCursorPoint(5));
939 PerformMouseDragTo(gfx::Point()); 966 PerformMouseDragTo(gfx::Point());
940 PerformMouseRelease(gfx::Point()); 967 PerformMouseRelease(gfx::Point());
941 EXPECT_STR_EQ("Label", GetSelectedText()); 968 EXPECT_STR_EQ("Label", GetSelectedText());
942 EXPECT_STR_EQ("Label", GetSelectionClipboardText()); 969 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
943 } 970 }
944 #endif 971 #endif
945 972
973 // Verify that keyboard shortcuts for Copy and Select All work when a selectable
974 // label is focused.
975 TEST_F(LabelSelectionTest, KeyboardActions) {
976 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions");
977 label()->SetText(initial_text);
978 label()->SizeToPreferredSize();
979 ASSERT_TRUE(label()->SetSelectable(true));
980
981 PerformClick(gfx::Point());
982 EXPECT_EQ(label(), GetFocusedView());
983
984 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier);
985 EXPECT_EQ(initial_text, GetSelectedText());
986
987 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
988 EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
989
990 // The selection should get cleared on changing the text, but focus should not
991 // be affected.
992 const base::string16 new_text = ASCIIToUTF16("Label obscured text");
993 label()->SetText(new_text);
994 EXPECT_FALSE(label()->HasSelection());
995 EXPECT_EQ(label(), GetFocusedView());
996
997 // Obscured labels do not support text selection.
998 label()->SetObscured(true);
999 EXPECT_FALSE(label()->selectable());
1000 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier);
1001 EXPECT_EQ(base::string16(), GetSelectedText());
1002 }
1003
1004 // Verify the context menu options are enabled and disabled appropriately.
1005 TEST_F(LabelSelectionTest, ContextMenuContents) {
1006 label()->SetText(ASCIIToUTF16("Label context menu"));
1007 label()->SizeToPreferredSize();
1008
1009 // A non-selectable label would not show a context menu and both COPY and
1010 // SELECT_ALL context menu items should be disabled for it.
1011 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY));
1012 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
1013
1014 // For a selectable label with no selection, only SELECT_ALL should be
1015 // enabled.
1016 ASSERT_TRUE(label()->SetSelectable(true));
1017 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY));
1018 EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
1019
1020 // For a selectable label with a selection, both COPY and SELECT_ALL should be
1021 // enabled.
1022 label()->SelectRange(gfx::Range(0, 4));
1023 EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_COPY));
1024 EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
1025 // Ensure unsupported commands like PASTE are not enabled.
1026 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_PASTE));
1027
1028 // An obscured label would not show a context menu and both COPY and
1029 // SELECT_ALL should be disabled for it.
1030 label()->SetObscured(true);
1031 EXPECT_FALSE(label()->selectable());
1032 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY));
1033 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
1034 label()->SetObscured(false);
1035
1036 // For an empty label, both COPY and SELECT_ALL should be disabled.
1037 label()->SetText(base::string16());
1038 ASSERT_TRUE(label()->SetSelectable(true));
1039 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY));
1040 EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
1041 }
1042
946 } // namespace views 1043 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/label.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698