| 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 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/i18n/case_conversion.h" | |
| 11 #include "grit/ui_strings.h" | 10 #include "grit/ui_strings.h" |
| 12 #include "ui/base/accessibility/accessible_view_state.h" | 11 #include "ui/base/accessibility/accessible_view_state.h" |
| 13 #include "ui/base/dragdrop/drag_drop_types.h" | 12 #include "ui/base/dragdrop/drag_drop_types.h" |
| 14 #include "ui/base/dragdrop/drag_utils.h" | 13 #include "ui/base/dragdrop/drag_utils.h" |
| 15 #include "ui/base/resource/resource_bundle.h" | 14 #include "ui/base/resource/resource_bundle.h" |
| 16 #include "ui/base/ui_base_switches_util.h" | 15 #include "ui/base/ui_base_switches_util.h" |
| 17 #include "ui/events/event.h" | 16 #include "ui/events/event.h" |
| 18 #include "ui/events/keycodes/keyboard_codes.h" | 17 #include "ui/events/keycodes/keyboard_codes.h" |
| 19 #include "ui/gfx/canvas.h" | 18 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/insets.h" | 19 #include "ui/gfx/insets.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 static const size_t system_value = ::GetCaretBlinkTime(); | 67 static const size_t system_value = ::GetCaretBlinkTime(); |
| 69 if (system_value != 0) | 68 if (system_value != 0) |
| 70 return (system_value == INFINITE) ? 0 : system_value; | 69 return (system_value == INFINITE) ? 0 : system_value; |
| 71 #endif | 70 #endif |
| 72 return default_value; | 71 return default_value; |
| 73 } | 72 } |
| 74 | 73 |
| 75 Textfield::Textfield() | 74 Textfield::Textfield() |
| 76 : model_(new TextfieldModel(this)), | 75 : model_(new TextfieldModel(this)), |
| 77 controller_(NULL), | 76 controller_(NULL), |
| 78 style_(STYLE_DEFAULT), | |
| 79 read_only_(false), | 77 read_only_(false), |
| 80 default_width_in_chars_(0), | 78 default_width_in_chars_(0), |
| 81 text_color_(SK_ColorBLACK), | 79 text_color_(SK_ColorBLACK), |
| 82 use_default_text_color_(true), | 80 use_default_text_color_(true), |
| 83 background_color_(SK_ColorWHITE), | 81 background_color_(SK_ColorWHITE), |
| 84 use_default_background_color_(true), | 82 use_default_background_color_(true), |
| 85 placeholder_text_color_(kDefaultPlaceholderTextColor), | 83 placeholder_text_color_(kDefaultPlaceholderTextColor), |
| 86 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | 84 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
| 87 skip_input_method_cancel_composition_(false), | 85 skip_input_method_cancel_composition_(false), |
| 88 is_cursor_visible_(false), | 86 is_cursor_visible_(false), |
| 89 is_drop_cursor_visible_(false), | 87 is_drop_cursor_visible_(false), |
| 90 initiating_drag_(false), | 88 initiating_drag_(false), |
| 91 aggregated_clicks_(0), | 89 aggregated_clicks_(0), |
| 92 weak_ptr_factory_(this) { | 90 weak_ptr_factory_(this) { |
| 93 set_context_menu_controller(this); | 91 set_context_menu_controller(this); |
| 94 set_drag_controller(this); | 92 set_drag_controller(this); |
| 95 set_border(new FocusableBorder()); | 93 set_border(new FocusableBorder()); |
| 96 SetFocusable(true); | 94 SetFocusable(true); |
| 97 | 95 |
| 98 if (ViewsDelegate::views_delegate) { | 96 if (ViewsDelegate::views_delegate) { |
| 99 obscured_reveal_duration_ = ViewsDelegate::views_delegate-> | 97 password_reveal_duration_ = ViewsDelegate::views_delegate-> |
| 100 GetDefaultTextfieldObscuredRevealDuration(); | 98 GetDefaultTextfieldObscuredRevealDuration(); |
| 101 } | 99 } |
| 102 | 100 |
| 103 if (NativeViewHost::kRenderNativeControlFocus) | 101 if (NativeViewHost::kRenderNativeControlFocus) |
| 104 focus_painter_ = Painter::CreateDashedFocusPainter(); | 102 focus_painter_ = Painter::CreateDashedFocusPainter(); |
| 105 } | 103 } |
| 106 | 104 |
| 107 Textfield::Textfield(StyleFlags style) | 105 Textfield::~Textfield() {} |
| 108 : model_(new TextfieldModel(this)), | |
| 109 controller_(NULL), | |
| 110 style_(style), | |
| 111 read_only_(false), | |
| 112 default_width_in_chars_(0), | |
| 113 text_color_(SK_ColorBLACK), | |
| 114 use_default_text_color_(true), | |
| 115 background_color_(SK_ColorWHITE), | |
| 116 use_default_background_color_(true), | |
| 117 placeholder_text_color_(kDefaultPlaceholderTextColor), | |
| 118 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | |
| 119 skip_input_method_cancel_composition_(false), | |
| 120 is_cursor_visible_(false), | |
| 121 is_drop_cursor_visible_(false), | |
| 122 initiating_drag_(false), | |
| 123 aggregated_clicks_(0), | |
| 124 weak_ptr_factory_(this) { | |
| 125 set_context_menu_controller(this); | |
| 126 set_drag_controller(this); | |
| 127 set_border(new FocusableBorder()); | |
| 128 SetFocusable(true); | |
| 129 | |
| 130 if (IsObscured()) | |
| 131 SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | |
| 132 | |
| 133 if (ViewsDelegate::views_delegate) { | |
| 134 obscured_reveal_duration_ = ViewsDelegate::views_delegate-> | |
| 135 GetDefaultTextfieldObscuredRevealDuration(); | |
| 136 } | |
| 137 | |
| 138 if (NativeViewHost::kRenderNativeControlFocus) | |
| 139 focus_painter_ = Painter::CreateDashedFocusPainter(); | |
| 140 } | |
| 141 | |
| 142 Textfield::~Textfield() { | |
| 143 } | |
| 144 | |
| 145 void Textfield::SetController(TextfieldController* controller) { | |
| 146 controller_ = controller; | |
| 147 } | |
| 148 | |
| 149 TextfieldController* Textfield::GetController() const { | |
| 150 return controller_; | |
| 151 } | |
| 152 | 106 |
| 153 void Textfield::SetReadOnly(bool read_only) { | 107 void Textfield::SetReadOnly(bool read_only) { |
| 154 // Update read-only without changing the focusable state (or active, etc.). | 108 // Update read-only without changing the focusable state (or active, etc.). |
| 155 read_only_ = read_only; | 109 read_only_ = read_only; |
| 156 if (GetInputMethod()) | 110 if (GetInputMethod()) |
| 157 GetInputMethod()->OnTextInputTypeChanged(this); | 111 GetInputMethod()->OnTextInputTypeChanged(this); |
| 158 SetColor(GetTextColor()); | 112 SetColor(GetTextColor()); |
| 159 UpdateBackgroundColor(); | 113 UpdateBackgroundColor(); |
| 160 } | 114 } |
| 161 | 115 |
| 162 bool Textfield::IsObscured() const { | 116 void Textfield::SetTextInputType(ui::TextInputType type) { |
| 163 return style_ & STYLE_OBSCURED; | 117 GetRenderText()->SetObscured(type == ui::TEXT_INPUT_TYPE_PASSWORD); |
| 164 } | 118 text_input_type_ = type; |
| 165 | |
| 166 void Textfield::SetObscured(bool obscured) { | |
| 167 if (obscured) { | |
| 168 style_ = static_cast<StyleFlags>(style_ | STYLE_OBSCURED); | |
| 169 SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | |
| 170 } else { | |
| 171 style_ = static_cast<StyleFlags>(style_ & ~STYLE_OBSCURED); | |
| 172 SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT); | |
| 173 } | |
| 174 GetRenderText()->SetObscured(obscured); | |
| 175 OnCaretBoundsChanged(); | 119 OnCaretBoundsChanged(); |
| 176 if (GetInputMethod()) | 120 if (GetInputMethod()) |
| 177 GetInputMethod()->OnTextInputTypeChanged(this); | 121 GetInputMethod()->OnTextInputTypeChanged(this); |
| 178 SchedulePaint(); | 122 SchedulePaint(); |
| 179 } | 123 } |
| 180 | 124 |
| 181 void Textfield::SetTextInputType(ui::TextInputType type) { | |
| 182 text_input_type_ = type; | |
| 183 bool should_be_obscured = type == ui::TEXT_INPUT_TYPE_PASSWORD; | |
| 184 if (IsObscured() != should_be_obscured) | |
| 185 SetObscured(should_be_obscured); | |
| 186 } | |
| 187 | |
| 188 void Textfield::SetText(const base::string16& new_text) { | 125 void Textfield::SetText(const base::string16& new_text) { |
| 189 model_->SetText(GetTextForDisplay(new_text)); | 126 model_->SetText(new_text); |
| 190 OnCaretBoundsChanged(); | 127 OnCaretBoundsChanged(); |
| 191 SchedulePaint(); | 128 SchedulePaint(); |
| 192 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); | 129 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); |
| 193 } | 130 } |
| 194 | 131 |
| 195 void Textfield::AppendText(const base::string16& new_text) { | 132 void Textfield::AppendText(const base::string16& new_text) { |
| 196 if (new_text.empty()) | 133 if (new_text.empty()) |
| 197 return; | 134 return; |
| 198 model_->Append(GetTextForDisplay(new_text)); | 135 model_->Append(new_text); |
| 199 OnCaretBoundsChanged(); | 136 OnCaretBoundsChanged(); |
| 200 SchedulePaint(); | 137 SchedulePaint(); |
| 201 } | 138 } |
| 202 | 139 |
| 203 void Textfield::InsertOrReplaceText(const base::string16& new_text) { | 140 void Textfield::InsertOrReplaceText(const base::string16& new_text) { |
| 204 if (new_text.empty()) | 141 if (new_text.empty()) |
| 205 return; | 142 return; |
| 206 model_->InsertText(new_text); | 143 model_->InsertText(new_text); |
| 207 OnCaretBoundsChanged(); | 144 OnCaretBoundsChanged(); |
| 208 SchedulePaint(); | 145 SchedulePaint(); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 return true; | 341 return true; |
| 405 | 342 |
| 406 // TODO(oshima): Refactor and consolidate with ExecuteCommand. | 343 // TODO(oshima): Refactor and consolidate with ExecuteCommand. |
| 407 if (event.type() == ui::ET_KEY_PRESSED) { | 344 if (event.type() == ui::ET_KEY_PRESSED) { |
| 408 ui::KeyboardCode key_code = event.key_code(); | 345 ui::KeyboardCode key_code = event.key_code(); |
| 409 if (key_code == ui::VKEY_TAB || event.IsUnicodeKeyCode()) | 346 if (key_code == ui::VKEY_TAB || event.IsUnicodeKeyCode()) |
| 410 return false; | 347 return false; |
| 411 | 348 |
| 412 gfx::RenderText* render_text = GetRenderText(); | 349 gfx::RenderText* render_text = GetRenderText(); |
| 413 const bool editable = !read_only(); | 350 const bool editable = !read_only(); |
| 414 const bool readable = !IsObscured(); | 351 const bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD; |
| 415 const bool shift = event.IsShiftDown(); | 352 const bool shift = event.IsShiftDown(); |
| 416 const bool control = event.IsControlDown(); | 353 const bool control = event.IsControlDown(); |
| 417 const bool alt = event.IsAltDown() || event.IsAltGrDown(); | 354 const bool alt = event.IsAltDown() || event.IsAltGrDown(); |
| 418 bool text_changed = false; | 355 bool text_changed = false; |
| 419 bool cursor_changed = false; | 356 bool cursor_changed = false; |
| 420 | 357 |
| 421 OnBeforeUserAction(); | 358 OnBeforeUserAction(); |
| 422 switch (key_code) { | 359 switch (key_code) { |
| 423 case ui::VKEY_Z: | 360 case ui::VKEY_Z: |
| 424 if (control && !shift && !alt && editable) | 361 if (control && !shift && !alt && editable) |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 | 572 |
| 636 // Border typically draws focus indicator. | 573 // Border typically draws focus indicator. |
| 637 SchedulePaint(); | 574 SchedulePaint(); |
| 638 } | 575 } |
| 639 | 576 |
| 640 void Textfield::GetAccessibleState(ui::AccessibleViewState* state) { | 577 void Textfield::GetAccessibleState(ui::AccessibleViewState* state) { |
| 641 state->role = ui::AccessibilityTypes::ROLE_TEXT; | 578 state->role = ui::AccessibilityTypes::ROLE_TEXT; |
| 642 state->name = accessible_name_; | 579 state->name = accessible_name_; |
| 643 if (read_only()) | 580 if (read_only()) |
| 644 state->state |= ui::AccessibilityTypes::STATE_READONLY; | 581 state->state |= ui::AccessibilityTypes::STATE_READONLY; |
| 645 if (IsObscured()) | 582 if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD) |
| 646 state->state |= ui::AccessibilityTypes::STATE_PROTECTED; | 583 state->state |= ui::AccessibilityTypes::STATE_PROTECTED; |
| 647 state->value = text(); | 584 state->value = text(); |
| 648 | 585 |
| 649 const gfx::Range range = GetSelectedRange(); | 586 const gfx::Range range = GetSelectedRange(); |
| 650 state->selection_start = range.start(); | 587 state->selection_start = range.start(); |
| 651 state->selection_end = range.end(); | 588 state->selection_end = range.end(); |
| 652 | 589 |
| 653 if (!read_only()) { | 590 if (!read_only()) { |
| 654 state->set_value_callback = | 591 state->set_value_callback = |
| 655 base::Bind(&Textfield::AccessibilitySetValue, | 592 base::Bind(&Textfield::AccessibilitySetValue, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 gfx::RenderText* render_text = GetRenderText(); | 771 gfx::RenderText* render_text = GetRenderText(); |
| 835 DCHECK(!initiating_drag_ || | 772 DCHECK(!initiating_drag_ || |
| 836 !render_text->IsPointInSelection(event.location())); | 773 !render_text->IsPointInSelection(event.location())); |
| 837 OnBeforeUserAction(); | 774 OnBeforeUserAction(); |
| 838 skip_input_method_cancel_composition_ = true; | 775 skip_input_method_cancel_composition_ = true; |
| 839 | 776 |
| 840 gfx::SelectionModel drop_destination_model = | 777 gfx::SelectionModel drop_destination_model = |
| 841 render_text->FindCursorPosition(event.location()); | 778 render_text->FindCursorPosition(event.location()); |
| 842 base::string16 new_text; | 779 base::string16 new_text; |
| 843 event.data().GetString(&new_text); | 780 event.data().GetString(&new_text); |
| 844 new_text = GetTextForDisplay(new_text); | |
| 845 | 781 |
| 846 // Delete the current selection for a drag and drop within this view. | 782 // Delete the current selection for a drag and drop within this view. |
| 847 const bool move = initiating_drag_ && !event.IsControlDown() && | 783 const bool move = initiating_drag_ && !event.IsControlDown() && |
| 848 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; | 784 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; |
| 849 if (move) { | 785 if (move) { |
| 850 // Adjust the drop destination if it is on or after the current selection. | 786 // Adjust the drop destination if it is on or after the current selection. |
| 851 size_t pos = drop_destination_model.caret_pos(); | 787 size_t pos = drop_destination_model.caret_pos(); |
| 852 pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length(); | 788 pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length(); |
| 853 model_->DeleteSelectionAndInsertTextAt(new_text, pos); | 789 model_->DeleteSelectionAndInsertTextAt(new_text, pos); |
| 854 } else { | 790 } else { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 drag_utils::SetDragImageOnDataObject(*canvas, size(), | 853 drag_utils::SetDragImageOnDataObject(*canvas, size(), |
| 918 press_pt.OffsetFromOrigin(), | 854 press_pt.OffsetFromOrigin(), |
| 919 data); | 855 data); |
| 920 if (controller_) | 856 if (controller_) |
| 921 controller_->OnWriteDragData(data); | 857 controller_->OnWriteDragData(data); |
| 922 } | 858 } |
| 923 | 859 |
| 924 int Textfield::GetDragOperationsForView(views::View* sender, | 860 int Textfield::GetDragOperationsForView(views::View* sender, |
| 925 const gfx::Point& p) { | 861 const gfx::Point& p) { |
| 926 int drag_operations = ui::DragDropTypes::DRAG_COPY; | 862 int drag_operations = ui::DragDropTypes::DRAG_COPY; |
| 927 if (!enabled() || IsObscured() || !GetRenderText()->IsPointInSelection(p)) | 863 if (!enabled() || text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD || |
| 864 !GetRenderText()->IsPointInSelection(p)) { |
| 928 drag_operations = ui::DragDropTypes::DRAG_NONE; | 865 drag_operations = ui::DragDropTypes::DRAG_NONE; |
| 929 else if (sender == this && !read_only()) | 866 } else if (sender == this && !read_only()) { |
| 930 drag_operations = | 867 drag_operations = |
| 931 ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY; | 868 ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY; |
| 869 } |
| 932 if (controller_) | 870 if (controller_) |
| 933 controller_->OnGetDragOperationsForTextfield(&drag_operations); | 871 controller_->OnGetDragOperationsForTextfield(&drag_operations); |
| 934 return drag_operations; | 872 return drag_operations; |
| 935 } | 873 } |
| 936 | 874 |
| 937 bool Textfield::CanStartDragForView(View* sender, | 875 bool Textfield::CanStartDragForView(View* sender, |
| 938 const gfx::Point& press_pt, | 876 const gfx::Point& press_pt, |
| 939 const gfx::Point& p) { | 877 const gfx::Point& p) { |
| 940 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); | 878 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); |
| 941 } | 879 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 //////////////////////////////////////////////////////////////////////////////// | 939 //////////////////////////////////////////////////////////////////////////////// |
| 1002 // Textfield, ui::SimpleMenuModel::Delegate overrides: | 940 // Textfield, ui::SimpleMenuModel::Delegate overrides: |
| 1003 | 941 |
| 1004 bool Textfield::IsCommandIdChecked(int command_id) const { | 942 bool Textfield::IsCommandIdChecked(int command_id) const { |
| 1005 return true; | 943 return true; |
| 1006 } | 944 } |
| 1007 | 945 |
| 1008 bool Textfield::IsCommandIdEnabled(int command_id) const { | 946 bool Textfield::IsCommandIdEnabled(int command_id) const { |
| 1009 base::string16 result; | 947 base::string16 result; |
| 1010 bool editable = !read_only(); | 948 bool editable = !read_only(); |
| 949 bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD; |
| 1011 switch (command_id) { | 950 switch (command_id) { |
| 1012 case IDS_APP_UNDO: | 951 case IDS_APP_UNDO: |
| 1013 return editable && model_->CanUndo(); | 952 return editable && model_->CanUndo(); |
| 1014 case IDS_APP_CUT: | 953 case IDS_APP_CUT: |
| 1015 return editable && model_->HasSelection() && !IsObscured(); | 954 return editable && readable && model_->HasSelection(); |
| 1016 case IDS_APP_COPY: | 955 case IDS_APP_COPY: |
| 1017 return model_->HasSelection() && !IsObscured(); | 956 return readable && model_->HasSelection(); |
| 1018 case IDS_APP_PASTE: | 957 case IDS_APP_PASTE: |
| 1019 ui::Clipboard::GetForCurrentThread()->ReadText( | 958 ui::Clipboard::GetForCurrentThread()->ReadText( |
| 1020 ui::CLIPBOARD_TYPE_COPY_PASTE, &result); | 959 ui::CLIPBOARD_TYPE_COPY_PASTE, &result); |
| 1021 return editable && !result.empty(); | 960 return editable && !result.empty(); |
| 1022 case IDS_APP_DELETE: | 961 case IDS_APP_DELETE: |
| 1023 return editable && model_->HasSelection(); | 962 return editable && model_->HasSelection(); |
| 1024 case IDS_APP_SELECT_ALL: | 963 case IDS_APP_SELECT_ALL: |
| 1025 return !text().empty(); | 964 return !text().empty(); |
| 1026 default: | 965 default: |
| 1027 return false; | 966 return false; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 } | 1060 } |
| 1122 | 1061 |
| 1123 void Textfield::InsertText(const base::string16& new_text) { | 1062 void Textfield::InsertText(const base::string16& new_text) { |
| 1124 // TODO(suzhe): Filter invalid characters. | 1063 // TODO(suzhe): Filter invalid characters. |
| 1125 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || new_text.empty()) | 1064 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || new_text.empty()) |
| 1126 return; | 1065 return; |
| 1127 | 1066 |
| 1128 OnBeforeUserAction(); | 1067 OnBeforeUserAction(); |
| 1129 skip_input_method_cancel_composition_ = true; | 1068 skip_input_method_cancel_composition_ = true; |
| 1130 if (GetRenderText()->insert_mode()) | 1069 if (GetRenderText()->insert_mode()) |
| 1131 model_->InsertText(GetTextForDisplay(new_text)); | 1070 model_->InsertText(new_text); |
| 1132 else | 1071 else |
| 1133 model_->ReplaceText(GetTextForDisplay(new_text)); | 1072 model_->ReplaceText(new_text); |
| 1134 skip_input_method_cancel_composition_ = false; | 1073 skip_input_method_cancel_composition_ = false; |
| 1135 UpdateAfterChange(true, true); | 1074 UpdateAfterChange(true, true); |
| 1136 OnAfterUserAction(); | 1075 OnAfterUserAction(); |
| 1137 } | 1076 } |
| 1138 | 1077 |
| 1139 void Textfield::InsertChar(base::char16 ch, int flags) { | 1078 void Textfield::InsertChar(base::char16 ch, int flags) { |
| 1140 // Filter out all control characters, including tab and new line characters, | 1079 // Filter out all control characters, including tab and new line characters, |
| 1141 // and all characters with Alt modifier. But allow characters with the AltGr | 1080 // and all characters with Alt modifier. But allow characters with the AltGr |
| 1142 // modifier. On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a | 1081 // modifier. On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a |
| 1143 // different flag that we don't care about. | 1082 // different flag that we don't care about. |
| 1144 const bool should_insert_char = ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) && | 1083 const bool should_insert_char = ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) && |
| 1145 (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN; | 1084 (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN; |
| 1146 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || !should_insert_char) | 1085 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || !should_insert_char) |
| 1147 return; | 1086 return; |
| 1148 | 1087 |
| 1149 OnBeforeUserAction(); | 1088 OnBeforeUserAction(); |
| 1150 skip_input_method_cancel_composition_ = true; | 1089 skip_input_method_cancel_composition_ = true; |
| 1151 if (GetRenderText()->insert_mode()) | 1090 if (GetRenderText()->insert_mode()) |
| 1152 model_->InsertChar(ch); | 1091 model_->InsertChar(ch); |
| 1153 else | 1092 else |
| 1154 model_->ReplaceChar(ch); | 1093 model_->ReplaceChar(ch); |
| 1155 skip_input_method_cancel_composition_ = false; | 1094 skip_input_method_cancel_composition_ = false; |
| 1156 | 1095 |
| 1157 model_->SetText(GetTextForDisplay(text())); | |
| 1158 | |
| 1159 UpdateAfterChange(true, true); | 1096 UpdateAfterChange(true, true); |
| 1160 OnAfterUserAction(); | 1097 OnAfterUserAction(); |
| 1161 | 1098 |
| 1162 if (IsObscured() && obscured_reveal_duration_ != base::TimeDelta()) { | 1099 if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD && |
| 1100 password_reveal_duration_ != base::TimeDelta()) { |
| 1163 const size_t change_offset = model_->GetCursorPosition(); | 1101 const size_t change_offset = model_->GetCursorPosition(); |
| 1164 DCHECK_GT(change_offset, 0u); | 1102 DCHECK_GT(change_offset, 0u); |
| 1165 RevealObscuredChar(change_offset - 1, obscured_reveal_duration_); | 1103 RevealPasswordChar(change_offset - 1); |
| 1166 } | 1104 } |
| 1167 } | 1105 } |
| 1168 | 1106 |
| 1169 gfx::NativeWindow Textfield::GetAttachedWindow() const { | 1107 gfx::NativeWindow Textfield::GetAttachedWindow() const { |
| 1170 // Imagine the following hierarchy. | 1108 // Imagine the following hierarchy. |
| 1171 // [NativeWidget A] - FocusManager | 1109 // [NativeWidget A] - FocusManager |
| 1172 // [View] | 1110 // [View] |
| 1173 // [NativeWidget B] | 1111 // [NativeWidget B] |
| 1174 // [View] | 1112 // [View] |
| 1175 // [View X] | 1113 // [View X] |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1328 //////////////////////////////////////////////////////////////////////////////// | 1266 //////////////////////////////////////////////////////////////////////////////// |
| 1329 // Textfield, protected: | 1267 // Textfield, protected: |
| 1330 | 1268 |
| 1331 gfx::RenderText* Textfield::GetRenderText() const { | 1269 gfx::RenderText* Textfield::GetRenderText() const { |
| 1332 return model_->render_text(); | 1270 return model_->render_text(); |
| 1333 } | 1271 } |
| 1334 | 1272 |
| 1335 //////////////////////////////////////////////////////////////////////////////// | 1273 //////////////////////////////////////////////////////////////////////////////// |
| 1336 // Textfield, private: | 1274 // Textfield, private: |
| 1337 | 1275 |
| 1338 base::string16 Textfield::GetTextForDisplay(const base::string16& raw) { | |
| 1339 return style_ & Textfield::STYLE_LOWERCASE ? base::i18n::ToLower(raw) : raw; | |
| 1340 } | |
| 1341 | |
| 1342 void Textfield::AccessibilitySetValue(const base::string16& new_value) { | 1276 void Textfield::AccessibilitySetValue(const base::string16& new_value) { |
| 1343 if (!read_only()) { | 1277 if (!read_only()) { |
| 1344 SetText(new_value); | 1278 SetText(new_value); |
| 1345 ClearSelection(); | 1279 ClearSelection(); |
| 1346 } | 1280 } |
| 1347 } | 1281 } |
| 1348 | 1282 |
| 1349 void Textfield::UpdateBackgroundColor() { | 1283 void Textfield::UpdateBackgroundColor() { |
| 1350 const SkColor color = GetBackgroundColor(); | 1284 const SkColor color = GetBackgroundColor(); |
| 1351 set_background(Background::CreateSolidBackground(color)); | 1285 set_background(Background::CreateSolidBackground(color)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 if (controller_) | 1373 if (controller_) |
| 1440 controller_->OnBeforeUserAction(this); | 1374 controller_->OnBeforeUserAction(this); |
| 1441 } | 1375 } |
| 1442 | 1376 |
| 1443 void Textfield::OnAfterUserAction() { | 1377 void Textfield::OnAfterUserAction() { |
| 1444 if (controller_) | 1378 if (controller_) |
| 1445 controller_->OnAfterUserAction(this); | 1379 controller_->OnAfterUserAction(this); |
| 1446 } | 1380 } |
| 1447 | 1381 |
| 1448 bool Textfield::Cut() { | 1382 bool Textfield::Cut() { |
| 1449 if (!read_only() && !IsObscured() && model_->Cut()) { | 1383 if (!read_only() && text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && |
| 1384 model_->Cut()) { |
| 1450 if (controller_) | 1385 if (controller_) |
| 1451 controller_->OnAfterCutOrCopy(); | 1386 controller_->OnAfterCutOrCopy(); |
| 1452 return true; | 1387 return true; |
| 1453 } | 1388 } |
| 1454 return false; | 1389 return false; |
| 1455 } | 1390 } |
| 1456 | 1391 |
| 1457 bool Textfield::Copy() { | 1392 bool Textfield::Copy() { |
| 1458 if (!IsObscured() && model_->Copy()) { | 1393 if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) { |
| 1459 if (controller_) | 1394 if (controller_) |
| 1460 controller_->OnAfterCutOrCopy(); | 1395 controller_->OnAfterCutOrCopy(); |
| 1461 return true; | 1396 return true; |
| 1462 } | 1397 } |
| 1463 return false; | 1398 return false; |
| 1464 } | 1399 } |
| 1465 | 1400 |
| 1466 bool Textfield::Paste() { | 1401 bool Textfield::Paste() { |
| 1467 if (read_only()) | 1402 if (!read_only() && model_->Paste()) { |
| 1468 return false; | |
| 1469 | |
| 1470 const base::string16 original_text = text(); | |
| 1471 if (model_->Paste()) { | |
| 1472 // As Paste is handled in model_->Paste(), the RenderText may contain | |
| 1473 // upper case characters. This is not consistent with other places | |
| 1474 // which keeps RenderText only containing lower case characters. | |
| 1475 base::string16 new_text = GetTextForDisplay(text()); | |
| 1476 model_->SetText(new_text); | |
| 1477 if (controller_) | 1403 if (controller_) |
| 1478 controller_->OnAfterPaste(); | 1404 controller_->OnAfterPaste(); |
| 1479 return true; | 1405 return true; |
| 1480 } | 1406 } |
| 1481 return false; | 1407 return false; |
| 1482 } | 1408 } |
| 1483 | 1409 |
| 1484 void Textfield::UpdateContextMenu() { | 1410 void Textfield::UpdateContextMenu() { |
| 1485 if (!context_menu_contents_.get()) { | 1411 if (!context_menu_contents_.get()) { |
| 1486 context_menu_contents_.reset(new ui::SimpleMenuModel(this)); | 1412 context_menu_contents_.reset(new ui::SimpleMenuModel(this)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1515 last_click_location_ = event.location(); | 1441 last_click_location_ = event.location(); |
| 1516 } | 1442 } |
| 1517 } | 1443 } |
| 1518 | 1444 |
| 1519 bool Textfield::ImeEditingAllowed() const { | 1445 bool Textfield::ImeEditingAllowed() const { |
| 1520 // Disallow input method editing of password fields. | 1446 // Disallow input method editing of password fields. |
| 1521 ui::TextInputType t = GetTextInputType(); | 1447 ui::TextInputType t = GetTextInputType(); |
| 1522 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 1448 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 1523 } | 1449 } |
| 1524 | 1450 |
| 1525 void Textfield::RevealObscuredChar(int index, const base::TimeDelta& duration) { | 1451 void Textfield::RevealPasswordChar(int index) { |
| 1526 GetRenderText()->SetObscuredRevealIndex(index); | 1452 GetRenderText()->SetObscuredRevealIndex(index); |
| 1527 SchedulePaint(); | 1453 SchedulePaint(); |
| 1528 | 1454 |
| 1529 if (index != -1) { | 1455 if (index != -1) { |
| 1530 obscured_reveal_timer_.Start(FROM_HERE, duration, | 1456 password_reveal_timer_.Start(FROM_HERE, password_reveal_duration_, |
| 1531 base::Bind(&Textfield::RevealObscuredChar, base::Unretained(this), | 1457 base::Bind(&Textfield::RevealPasswordChar, |
| 1532 -1, base::TimeDelta())); | 1458 weak_ptr_factory_.GetWeakPtr(), -1)); |
| 1533 } | 1459 } |
| 1534 } | 1460 } |
| 1535 | 1461 |
| 1536 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { | 1462 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { |
| 1537 if (!touch_selection_controller_) { | 1463 if (!touch_selection_controller_) { |
| 1538 touch_selection_controller_.reset( | 1464 touch_selection_controller_.reset( |
| 1539 ui::TouchSelectionController::create(this)); | 1465 ui::TouchSelectionController::create(this)); |
| 1540 } | 1466 } |
| 1541 if (touch_selection_controller_) | 1467 if (touch_selection_controller_) |
| 1542 touch_selection_controller_->SelectionChanged(); | 1468 touch_selection_controller_->SelectionChanged(); |
| 1543 } | 1469 } |
| 1544 | 1470 |
| 1545 } // namespace views | 1471 } // namespace views |
| OLD | NEW |