| 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_ = |
| 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() { 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |