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/textfield/textfield.h" | 5 #include "ui/views/controls/textfield/textfield.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 use_default_selection_background_color_(true), | 248 use_default_selection_background_color_(true), |
249 text_color_(SK_ColorBLACK), | 249 text_color_(SK_ColorBLACK), |
250 background_color_(SK_ColorWHITE), | 250 background_color_(SK_ColorWHITE), |
251 selection_text_color_(SK_ColorWHITE), | 251 selection_text_color_(SK_ColorWHITE), |
252 selection_background_color_(SK_ColorBLUE), | 252 selection_background_color_(SK_ColorBLUE), |
253 placeholder_text_color_(kDefaultPlaceholderTextColor), | 253 placeholder_text_color_(kDefaultPlaceholderTextColor), |
254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | 254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
255 text_input_flags_(0), | 255 text_input_flags_(0), |
256 performing_user_action_(false), | 256 performing_user_action_(false), |
257 skip_input_method_cancel_composition_(false), | 257 skip_input_method_cancel_composition_(false), |
258 cursor_visible_(false), | |
259 drop_cursor_visible_(false), | 258 drop_cursor_visible_(false), |
260 initiating_drag_(false), | 259 initiating_drag_(false), |
261 aggregated_clicks_(0), | 260 aggregated_clicks_(0), |
262 drag_start_display_offset_(0), | 261 drag_start_display_offset_(0), |
263 touch_handles_hidden_due_to_scroll_(false), | 262 touch_handles_hidden_due_to_scroll_(false), |
264 weak_ptr_factory_(this) { | 263 weak_ptr_factory_(this) { |
265 set_context_menu_controller(this); | 264 set_context_menu_controller(this); |
266 set_drag_controller(this); | 265 set_drag_controller(this); |
267 GetRenderText()->SetFontList(GetDefaultFontList()); | 266 GetRenderText()->SetFontList(GetDefaultFontList()); |
268 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 267 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 gfx::RenderText* render_text = GetRenderText(); | 847 gfx::RenderText* render_text = GetRenderText(); |
849 const gfx::Range& selection = render_text->selection(); | 848 const gfx::Range& selection = render_text->selection(); |
850 drop_cursor_position_ = render_text->FindCursorPosition(event.location()); | 849 drop_cursor_position_ = render_text->FindCursorPosition(event.location()); |
851 bool in_selection = !selection.is_empty() && | 850 bool in_selection = !selection.is_empty() && |
852 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); | 851 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); |
853 drop_cursor_visible_ = !in_selection; | 852 drop_cursor_visible_ = !in_selection; |
854 // TODO(msw): Pan over text when the user drags to the visible text edge. | 853 // TODO(msw): Pan over text when the user drags to the visible text edge. |
855 OnCaretBoundsChanged(); | 854 OnCaretBoundsChanged(); |
856 SchedulePaint(); | 855 SchedulePaint(); |
857 | 856 |
| 857 StopBlinkingCursor(); |
| 858 |
858 if (initiating_drag_) { | 859 if (initiating_drag_) { |
859 if (in_selection) | 860 if (in_selection) |
860 return ui::DragDropTypes::DRAG_NONE; | 861 return ui::DragDropTypes::DRAG_NONE; |
861 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY : | 862 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY : |
862 ui::DragDropTypes::DRAG_MOVE; | 863 ui::DragDropTypes::DRAG_MOVE; |
863 } | 864 } |
864 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE; | 865 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE; |
865 } | 866 } |
866 | 867 |
867 void Textfield::OnDragExited() { | 868 void Textfield::OnDragExited() { |
868 drop_cursor_visible_ = false; | 869 drop_cursor_visible_ = false; |
| 870 if (ShouldBlinkCursor()) |
| 871 StartBlinkingCursor(); |
869 SchedulePaint(); | 872 SchedulePaint(); |
870 } | 873 } |
871 | 874 |
872 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) { | 875 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) { |
873 DCHECK(CanDrop(event.data())); | 876 DCHECK(CanDrop(event.data())); |
874 drop_cursor_visible_ = false; | 877 drop_cursor_visible_ = false; |
875 | 878 |
876 if (controller_) { | 879 if (controller_) { |
877 int drag_operation = controller_->OnDrop(event.data()); | 880 int drag_operation = controller_->OnDrop(event.data()); |
878 if (drag_operation != ui::DragDropTypes::DRAG_NONE) | 881 if (drag_operation != ui::DragDropTypes::DRAG_NONE) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 } | 973 } |
971 | 974 |
972 void Textfield::OnPaint(gfx::Canvas* canvas) { | 975 void Textfield::OnPaint(gfx::Canvas* canvas) { |
973 OnPaintBackground(canvas); | 976 OnPaintBackground(canvas); |
974 PaintTextAndCursor(canvas); | 977 PaintTextAndCursor(canvas); |
975 OnPaintBorder(canvas); | 978 OnPaintBorder(canvas); |
976 } | 979 } |
977 | 980 |
978 void Textfield::OnFocus() { | 981 void Textfield::OnFocus() { |
979 GetRenderText()->set_focused(true); | 982 GetRenderText()->set_focused(true); |
980 cursor_visible_ = true; | 983 if (ShouldShowCursor()) |
| 984 GetRenderText()->set_cursor_visible(true); |
981 SchedulePaint(); | 985 SchedulePaint(); |
982 if (GetInputMethod()) | 986 if (GetInputMethod()) |
983 GetInputMethod()->SetFocusedTextInputClient(this); | 987 GetInputMethod()->SetFocusedTextInputClient(this); |
984 OnCaretBoundsChanged(); | 988 OnCaretBoundsChanged(); |
985 | 989 if (ShouldBlinkCursor()) |
986 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); | 990 StartBlinkingCursor(); |
987 if (caret_blink_ms != 0) { | |
988 cursor_repaint_timer_.Start(FROM_HERE, | |
989 base::TimeDelta::FromMilliseconds(caret_blink_ms), this, | |
990 &Textfield::UpdateCursor); | |
991 } | |
992 | |
993 View::OnFocus(); | 991 View::OnFocus(); |
994 SchedulePaint(); | 992 SchedulePaint(); |
995 } | 993 } |
996 | 994 |
997 void Textfield::OnBlur() { | 995 void Textfield::OnBlur() { |
998 GetRenderText()->set_focused(false); | 996 gfx::RenderText* render_text = GetRenderText(); |
| 997 render_text->set_focused(false); |
999 if (GetInputMethod()) | 998 if (GetInputMethod()) |
1000 GetInputMethod()->DetachTextInputClient(this); | 999 GetInputMethod()->DetachTextInputClient(this); |
1001 cursor_repaint_timer_.Stop(); | 1000 StopBlinkingCursor(); |
1002 if (cursor_visible_) { | 1001 if (render_text->cursor_visible()) { |
1003 cursor_visible_ = false; | 1002 render_text->set_cursor_visible(false); |
1004 RepaintCursor(); | 1003 RepaintCursor(); |
1005 } | 1004 } |
1006 | 1005 |
1007 DestroyTouchSelection(); | 1006 DestroyTouchSelection(); |
1008 | 1007 |
1009 // Border typically draws focus indicator. | 1008 // Border typically draws focus indicator. |
1010 SchedulePaint(); | 1009 SchedulePaint(); |
1011 } | 1010 } |
1012 | 1011 |
1013 gfx::Point Textfield::GetKeyboardContextMenuLocation() { | 1012 gfx::Point Textfield::GetKeyboardContextMenuLocation() { |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 SchedulePaint(); | 1793 SchedulePaint(); |
1795 } | 1794 } |
1796 | 1795 |
1797 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { | 1796 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { |
1798 if (text_changed) { | 1797 if (text_changed) { |
1799 if (controller_) | 1798 if (controller_) |
1800 controller_->ContentsChanged(this, text()); | 1799 controller_->ContentsChanged(this, text()); |
1801 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); | 1800 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); |
1802 } | 1801 } |
1803 if (cursor_changed) { | 1802 if (cursor_changed) { |
1804 cursor_visible_ = true; | 1803 GetRenderText()->set_cursor_visible(ShouldShowCursor()); |
1805 RepaintCursor(); | 1804 RepaintCursor(); |
1806 if (cursor_repaint_timer_.IsRunning()) | 1805 if (ShouldBlinkCursor()) |
1807 cursor_repaint_timer_.Reset(); | 1806 StartBlinkingCursor(); |
| 1807 else |
| 1808 StopBlinkingCursor(); |
1808 if (!text_changed) { | 1809 if (!text_changed) { |
1809 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire | 1810 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire |
1810 // this if only the selection changed. | 1811 // this if only the selection changed. |
1811 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); | 1812 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); |
1812 } | 1813 } |
1813 } | 1814 } |
1814 if (text_changed || cursor_changed) { | 1815 if (text_changed || cursor_changed) { |
1815 OnCaretBoundsChanged(); | 1816 OnCaretBoundsChanged(); |
1816 SchedulePaint(); | 1817 SchedulePaint(); |
1817 } | 1818 } |
1818 } | 1819 } |
1819 | 1820 |
1820 void Textfield::UpdateCursor() { | |
1821 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); | |
1822 cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0); | |
1823 RepaintCursor(); | |
1824 } | |
1825 | |
1826 void Textfield::RepaintCursor() { | 1821 void Textfield::RepaintCursor() { |
1827 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); | 1822 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); |
1828 r.Inset(-1, -1, -1, -1); | 1823 r.Inset(-1, -1, -1, -1); |
1829 SchedulePaintInRect(r); | 1824 SchedulePaintInRect(r); |
1830 } | 1825 } |
1831 | 1826 |
1832 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { | 1827 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { |
1833 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); | 1828 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); |
1834 canvas->Save(); | 1829 canvas->Save(); |
1835 | 1830 |
1836 // Draw placeholder text if needed. | 1831 // Draw placeholder text if needed. |
1837 gfx::RenderText* render_text = GetRenderText(); | 1832 gfx::RenderText* render_text = GetRenderText(); |
1838 if (text().empty() && !GetPlaceholderText().empty()) { | 1833 if (text().empty() && !GetPlaceholderText().empty()) { |
1839 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), | 1834 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), |
1840 ui::MaterialDesignController::IsSecondaryUiMaterial() | 1835 ui::MaterialDesignController::IsSecondaryUiMaterial() |
1841 ? SkColorSetA(GetTextColor(), 0x83) | 1836 ? SkColorSetA(GetTextColor(), 0x83) |
1842 : placeholder_text_color_, | 1837 : placeholder_text_color_, |
1843 render_text->display_rect()); | 1838 render_text->display_rect()); |
1844 } | 1839 } |
1845 | 1840 |
1846 // Draw the text, cursor, and selection. | |
1847 render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ && | |
1848 !HasSelection()); | |
1849 render_text->Draw(canvas); | 1841 render_text->Draw(canvas); |
1850 | 1842 |
1851 // Draw the detached drop cursor that marks where the text will be dropped. | 1843 // Draw the detached drop cursor that marks where the text will be dropped. |
1852 if (drop_cursor_visible_) | 1844 if (drop_cursor_visible_) |
1853 render_text->DrawCursor(canvas, drop_cursor_position_); | 1845 render_text->DrawCursor(canvas, drop_cursor_position_); |
1854 | 1846 |
1855 canvas->Restore(); | 1847 canvas->Restore(); |
1856 } | 1848 } |
1857 | 1849 |
1858 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | 1850 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2039 model_->InsertText(selection_clipboard_text); | 2031 model_->InsertText(selection_clipboard_text); |
2040 UpdateAfterChange(true, true); | 2032 UpdateAfterChange(true, true); |
2041 } | 2033 } |
2042 OnAfterUserAction(); | 2034 OnAfterUserAction(); |
2043 } | 2035 } |
2044 | 2036 |
2045 void Textfield::OnKeypressUnhandled() { | 2037 void Textfield::OnKeypressUnhandled() { |
2046 PlatformStyle::OnTextfieldKeypressUnhandled(); | 2038 PlatformStyle::OnTextfieldKeypressUnhandled(); |
2047 } | 2039 } |
2048 | 2040 |
| 2041 bool Textfield::ShouldShowCursor() const { |
| 2042 return HasFocus() && !HasSelection() && enabled() && !read_only() && |
| 2043 !drop_cursor_visible_; |
| 2044 } |
| 2045 |
| 2046 bool Textfield::ShouldBlinkCursor() const { |
| 2047 return ShouldShowCursor() && Textfield::GetCaretBlinkMs() != 0; |
| 2048 } |
| 2049 |
| 2050 void Textfield::StartBlinkingCursor() { |
| 2051 DCHECK(ShouldBlinkCursor()); |
| 2052 cursor_blink_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( |
| 2053 Textfield::GetCaretBlinkMs()), |
| 2054 this, &Textfield::OnCursorBlinkTimerFired); |
| 2055 } |
| 2056 |
| 2057 void Textfield::StopBlinkingCursor() { |
| 2058 cursor_blink_timer_.Stop(); |
| 2059 } |
| 2060 |
| 2061 void Textfield::OnCursorBlinkTimerFired() { |
| 2062 DCHECK(ShouldBlinkCursor()); |
| 2063 gfx::RenderText* render_text = GetRenderText(); |
| 2064 render_text->set_cursor_visible(!render_text->cursor_visible()); |
| 2065 RepaintCursor(); |
| 2066 } |
| 2067 |
2049 } // namespace views | 2068 } // namespace views |
OLD | NEW |