Chromium Code Reviews| 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/native_textfield_views.h" | 5 #include "ui/views/controls/textfield/native_textfield_views.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/i18n/case_conversion.h" | |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 14 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 15 #include "grit/app_locale_settings.h" | 16 #include "grit/app_locale_settings.h" |
| 16 #include "grit/ui_strings.h" | 17 #include "grit/ui_strings.h" |
| 17 #include "ui/base/clipboard/clipboard.h" | 18 #include "ui/base/clipboard/clipboard.h" |
| 18 #include "ui/base/dragdrop/drag_drop_types.h" | 19 #include "ui/base/dragdrop/drag_drop_types.h" |
| 19 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
| 20 #include "ui/base/range/range.h" | 21 #include "ui/base/range/range.h" |
| 21 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/insets.h" | 23 #include "ui/gfx/insets.h" |
| 23 #include "ui/gfx/render_text.h" | 24 #include "ui/gfx/render_text.h" |
| 24 #include "ui/views/background.h" | 25 #include "ui/views/background.h" |
| 25 #include "ui/views/border.h" | 26 #include "ui/views/border.h" |
| 26 #include "ui/views/controls/focusable_border.h" | 27 #include "ui/views/controls/focusable_border.h" |
| 27 #include "ui/views/controls/menu/menu_item_view.h" | 28 #include "ui/views/controls/menu/menu_item_view.h" |
| 28 #include "ui/views/controls/menu/menu_model_adapter.h" | 29 #include "ui/views/controls/menu/menu_model_adapter.h" |
| 29 #include "ui/views/controls/menu/menu_runner.h" | 30 #include "ui/views/controls/menu/menu_runner.h" |
| 30 #include "ui/views/controls/textfield/textfield.h" | 31 #include "ui/views/controls/textfield/textfield.h" |
| 31 #include "ui/views/controls/textfield/textfield_controller.h" | 32 #include "ui/views/controls/textfield/textfield_controller.h" |
| 32 #include "ui/views/controls/textfield/textfield_views_model.h" | 33 #include "ui/views/controls/textfield/textfield_views_model.h" |
| 33 #include "ui/views/events/event.h" | 34 #include "ui/views/events/event.h" |
| 34 #include "ui/views/ime/input_method.h" | 35 #include "ui/views/ime/input_method.h" |
| 35 #include "ui/views/metrics.h" | 36 #include "ui/views/metrics.h" |
| 36 #include "ui/views/views_delegate.h" | 37 #include "ui/views/views_delegate.h" |
| 37 #include "ui/views/widget/widget.h" | 38 #include "ui/views/widget/widget.h" |
| 39 #include "unicode/uchar.h" | |
| 38 | 40 |
| 39 #if defined(OS_LINUX) | 41 #if defined(OS_LINUX) |
| 40 #include "ui/gfx/gtk_util.h" | 42 #include "ui/gfx/gtk_util.h" |
| 41 #endif | 43 #endif |
| 42 | 44 |
| 43 #if defined(USE_AURA) | 45 #if defined(USE_AURA) |
| 44 #include "ui/aura/cursor.h" | 46 #include "ui/aura/cursor.h" |
| 45 #endif | 47 #endif |
| 46 | 48 |
| 47 namespace { | 49 namespace { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 69 skip_input_method_cancel_composition_(false), | 71 skip_input_method_cancel_composition_(false), |
| 70 initiating_drag_(false), | 72 initiating_drag_(false), |
| 71 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)), | 73 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)), |
| 72 aggregated_clicks_(0), | 74 aggregated_clicks_(0), |
| 73 last_click_time_(), | 75 last_click_time_(), |
| 74 last_click_location_(), | 76 last_click_location_(), |
| 75 ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_( | 77 ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_( |
| 76 TouchSelectionController::create(this))) { | 78 TouchSelectionController::create(this))) { |
| 77 set_border(text_border_); | 79 set_border(text_border_); |
| 78 | 80 |
| 79 // Lowercase is not supported. | |
| 80 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); | |
| 81 | |
| 82 #if defined(OS_CHROMEOS) | 81 #if defined(OS_CHROMEOS) |
| 83 GetRenderText()->SetFontList(gfx::FontList(l10n_util::GetStringUTF8( | 82 GetRenderText()->SetFontList(gfx::FontList(l10n_util::GetStringUTF8( |
| 84 IDS_UI_FONT_FAMILY_CROS))); | 83 IDS_UI_FONT_FAMILY_CROS))); |
| 85 #else | 84 #else |
| 86 GetRenderText()->SetFontList(gfx::FontList(textfield_->font())); | 85 GetRenderText()->SetFontList(gfx::FontList(textfield_->font())); |
| 87 #endif | 86 #endif |
| 88 // Set the default text style. | 87 // Set the default text style. |
| 89 gfx::StyleRange default_style; | 88 gfx::StyleRange default_style; |
| 90 default_style.foreground = textfield_->text_color(); | 89 default_style.foreground = textfield_->text_color(); |
| 91 GetRenderText()->set_default_style(default_style); | 90 GetRenderText()->set_default_style(default_style); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 DCHECK(!initiating_drag_ || | 183 DCHECK(!initiating_drag_ || |
| 185 !GetRenderText()->IsPointInSelection(event.location())); | 184 !GetRenderText()->IsPointInSelection(event.location())); |
| 186 OnBeforeUserAction(); | 185 OnBeforeUserAction(); |
| 187 skip_input_method_cancel_composition_ = true; | 186 skip_input_method_cancel_composition_ = true; |
| 188 | 187 |
| 189 // TODO(msw): Remove final reference to FindCursorPosition. | 188 // TODO(msw): Remove final reference to FindCursorPosition. |
| 190 gfx::SelectionModel drop_destination = | 189 gfx::SelectionModel drop_destination = |
| 191 GetRenderText()->FindCursorPosition(event.location()); | 190 GetRenderText()->FindCursorPosition(event.location()); |
| 192 string16 text; | 191 string16 text; |
| 193 event.data().GetString(&text); | 192 event.data().GetString(&text); |
| 193 if (textfield_->style() & Textfield::STYLE_LOWERCASE) | |
| 194 text = base::i18n::ToLower(text); | |
|
xji
2012/02/17 22:38:24
I think we should do language specific case mappin
kochi
2012/02/23 10:49:07
According to the header file,
ToLower uses Unicode
xji
2012/02/23 21:59:17
You are right! sorry for the false alarm.
| |
| 194 | 195 |
| 195 // We'll delete the current selection for a drag and drop within this view. | 196 // We'll delete the current selection for a drag and drop within this view. |
| 196 bool move = initiating_drag_ && !event.IsControlDown() && | 197 bool move = initiating_drag_ && !event.IsControlDown() && |
| 197 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; | 198 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; |
| 198 if (move) { | 199 if (move) { |
| 199 gfx::SelectionModel selected; | 200 gfx::SelectionModel selected; |
| 200 model_->GetSelectionModel(&selected); | 201 model_->GetSelectionModel(&selected); |
| 201 // Adjust the drop destination if it is on or after the current selection. | 202 // Adjust the drop destination if it is on or after the current selection. |
| 202 size_t max_of_selected_range = std::max(selected.selection_start(), | 203 size_t max_of_selected_range = std::max(selected.selection_start(), |
| 203 selected.selection_end()); | 204 selected.selection_end()); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 } | 324 } |
| 324 | 325 |
| 325 ///////////////////////////////////////////////////////////////// | 326 ///////////////////////////////////////////////////////////////// |
| 326 // NativeTextfieldViews, NativeTextifieldWrapper overrides: | 327 // NativeTextfieldViews, NativeTextifieldWrapper overrides: |
| 327 | 328 |
| 328 string16 NativeTextfieldViews::GetText() const { | 329 string16 NativeTextfieldViews::GetText() const { |
| 329 return model_->GetText(); | 330 return model_->GetText(); |
| 330 } | 331 } |
| 331 | 332 |
| 332 void NativeTextfieldViews::UpdateText() { | 333 void NativeTextfieldViews::UpdateText() { |
| 333 model_->SetText(textfield_->text()); | 334 string16 text = textfield_->text(); |
| 335 if (textfield_->style() & Textfield::STYLE_LOWERCASE) | |
| 336 text = base::i18n::ToLower(text); | |
| 337 model_->SetText(text); | |
| 334 OnCaretBoundsChanged(); | 338 OnCaretBoundsChanged(); |
| 335 SchedulePaint(); | 339 SchedulePaint(); |
| 336 textfield_->GetWidget()->NotifyAccessibilityEvent( | 340 textfield_->GetWidget()->NotifyAccessibilityEvent( |
| 337 textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); | 341 textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); |
| 338 } | 342 } |
| 339 | 343 |
| 340 void NativeTextfieldViews::AppendText(const string16& text) { | 344 void NativeTextfieldViews::AppendText(const string16& text) { |
| 341 if (text.empty()) | 345 if (text.empty()) |
| 342 return; | 346 return; |
| 343 model_->Append(text); | 347 if (textfield_->style() & Textfield::STYLE_LOWERCASE) |
| 348 model_->Append(base::i18n::ToLower(text)); | |
| 349 else | |
| 350 model_->Append(text); | |
| 344 OnCaretBoundsChanged(); | 351 OnCaretBoundsChanged(); |
| 345 SchedulePaint(); | 352 SchedulePaint(); |
| 346 } | 353 } |
| 347 | 354 |
| 348 string16 NativeTextfieldViews::GetSelectedText() const { | 355 string16 NativeTextfieldViews::GetSelectedText() const { |
| 349 return model_->GetSelectedText(); | 356 return model_->GetSelectedText(); |
| 350 } | 357 } |
| 351 | 358 |
| 352 void NativeTextfieldViews::SelectAll() { | 359 void NativeTextfieldViews::SelectAll() { |
| 353 OnBeforeUserAction(); | 360 OnBeforeUserAction(); |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 OnAfterUserAction(); | 674 OnAfterUserAction(); |
| 668 } | 675 } |
| 669 | 676 |
| 670 void NativeTextfieldViews::InsertText(const string16& text) { | 677 void NativeTextfieldViews::InsertText(const string16& text) { |
| 671 // TODO(suzhe): Filter invalid characters. | 678 // TODO(suzhe): Filter invalid characters. |
| 672 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty()) | 679 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty()) |
| 673 return; | 680 return; |
| 674 | 681 |
| 675 OnBeforeUserAction(); | 682 OnBeforeUserAction(); |
| 676 skip_input_method_cancel_composition_ = true; | 683 skip_input_method_cancel_composition_ = true; |
| 684 | |
| 685 string16 new_text = text; | |
| 686 if (textfield_->style() & Textfield::STYLE_LOWERCASE) | |
| 687 new_text = base::i18n::ToLower(new_text); | |
|
xji
2012/02/17 22:38:24
nit: string16 new_text = (textfield_->style() & Te
msw
2012/02/18 00:32:38
why not just reassign to text? new_text seems redu
xji
2012/02/18 01:33:38
|text| is a 'const'.
kochi
2012/02/23 10:49:07
Done.
kochi
2012/02/23 10:49:07
Yes, that's right.
On 2012/02/18 01:33:38, xji wr
| |
| 688 | |
| 677 if (GetRenderText()->insert_mode()) | 689 if (GetRenderText()->insert_mode()) |
| 678 model_->InsertText(text); | 690 model_->InsertText(new_text); |
| 679 else | 691 else |
| 680 model_->ReplaceText(text); | 692 model_->ReplaceText(new_text); |
| 681 skip_input_method_cancel_composition_ = false; | 693 skip_input_method_cancel_composition_ = false; |
| 682 UpdateAfterChange(true, true); | 694 UpdateAfterChange(true, true); |
| 683 OnAfterUserAction(); | 695 OnAfterUserAction(); |
| 684 } | 696 } |
| 685 | 697 |
| 686 void NativeTextfieldViews::InsertChar(char16 ch, int flags) { | 698 void NativeTextfieldViews::InsertChar(char16 ch, int flags) { |
| 687 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || | 699 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || |
| 688 !ShouldInsertChar(ch, flags)) { | 700 !ShouldInsertChar(ch, flags)) { |
| 689 return; | 701 return; |
| 690 } | 702 } |
| 691 | 703 |
| 704 if (textfield_->style() & Textfield::STYLE_LOWERCASE) | |
| 705 ch = u_tolower(ch); | |
|
msw
2012/02/18 00:32:38
You should ensure this does the language specific
kochi
2012/02/23 10:49:07
This one doesn't seem to handle language-specific
| |
| 706 | |
| 692 OnBeforeUserAction(); | 707 OnBeforeUserAction(); |
| 693 skip_input_method_cancel_composition_ = true; | 708 skip_input_method_cancel_composition_ = true; |
| 694 if (GetRenderText()->insert_mode()) | 709 if (GetRenderText()->insert_mode()) |
| 695 model_->InsertChar(ch); | 710 model_->InsertChar(ch); |
| 696 else | 711 else |
| 697 model_->ReplaceChar(ch); | 712 model_->ReplaceChar(ch); |
| 698 skip_input_method_cancel_composition_ = false; | 713 skip_input_method_cancel_composition_ = false; |
| 699 UpdateAfterChange(true, true); | 714 UpdateAfterChange(true, true); |
| 700 OnAfterUserAction(); | 715 OnAfterUserAction(); |
| 701 } | 716 } |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1036 if (controller) | 1051 if (controller) |
| 1037 controller->OnAfterCutOrCopy(); | 1052 controller->OnAfterCutOrCopy(); |
| 1038 return true; | 1053 return true; |
| 1039 } | 1054 } |
| 1040 return false; | 1055 return false; |
| 1041 } | 1056 } |
| 1042 | 1057 |
| 1043 bool NativeTextfieldViews::Paste() { | 1058 bool NativeTextfieldViews::Paste() { |
| 1044 const bool success = model_->Paste(); | 1059 const bool success = model_->Paste(); |
| 1045 | 1060 |
| 1061 if (textfield_->style() & Textfield::STYLE_LOWERCASE) { | |
| 1062 string16 text = model_->GetText(); | |
| 1063 text = base::i18n::ToLower(text); | |
| 1064 model_->SetText(text); | |
| 1065 } | |
|
xji
2012/02/17 22:38:24
this should not be needed since model_->GetText()
kochi
2012/02/23 10:49:07
The model directly gets the text from clipboard
in
xji
2012/02/23 21:59:17
Ah, I see. I thought RenderText will always keep a
kochi
2012/04/09 06:34:20
OK, I agree this is not intuitive to understand.
A
| |
| 1066 | |
| 1046 // Calls TextfieldController::ContentsChanged() explicitly if the paste action | 1067 // Calls TextfieldController::ContentsChanged() explicitly if the paste action |
| 1047 // did not change the content at all. See http://crbug.com/79002 | 1068 // did not change the content at all. See http://crbug.com/79002 |
| 1048 if (success && GetText() == textfield_->text()) { | 1069 if (success && GetText() == textfield_->text()) { |
|
xji
2012/02/17 22:38:24
In case of STYLE_LOWERCASE, GetText() is lower-cas
kochi
2012/02/23 10:49:07
Right, will fix this.
kochi
2012/04/09 06:34:20
Ah, no.
GetText() in this class is just does mode
xji
2012/04/10 22:53:27
GetText() is lower-cased.
But isn't textfield_->te
kochi
2012/04/11 01:56:41
I see, sorry for misunderstanding again.
Done.
On
| |
| 1049 TextfieldController* controller = textfield_->GetController(); | 1070 TextfieldController* controller = textfield_->GetController(); |
| 1050 if (controller) | 1071 if (controller) |
| 1051 controller->ContentsChanged(textfield_, textfield_->text()); | 1072 controller->ContentsChanged(textfield_, textfield_->text()); |
| 1052 } | 1073 } |
| 1053 return success; | 1074 return success; |
| 1054 } | 1075 } |
| 1055 | 1076 |
| 1056 void NativeTextfieldViews::TrackMouseClicks(const MouseEvent& event) { | 1077 void NativeTextfieldViews::TrackMouseClicks(const MouseEvent& event) { |
| 1057 if (event.IsOnlyLeftMouseButton()) { | 1078 if (event.IsOnlyLeftMouseButton()) { |
| 1058 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; | 1079 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1117 | 1138 |
| 1118 #if defined(USE_AURA) | 1139 #if defined(USE_AURA) |
| 1119 // static | 1140 // static |
| 1120 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( | 1141 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( |
| 1121 Textfield* field) { | 1142 Textfield* field) { |
| 1122 return new NativeTextfieldViews(field); | 1143 return new NativeTextfieldViews(field); |
| 1123 } | 1144 } |
| 1124 #endif | 1145 #endif |
| 1125 | 1146 |
| 1126 } // namespace views | 1147 } // namespace views |
| OLD | NEW |