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 |