| 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 |