Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: ui/views/controls/textfield/native_textfield_views.cc

Issue 9358049: Implement STYLE_LOWERCASE style for Aura NativeTextfield. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update for comments. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "third_party/skia/include/core/SkColor.h" 18 #include "third_party/skia/include/core/SkColor.h"
18 #include "ui/base/clipboard/clipboard.h" 19 #include "ui/base/clipboard/clipboard.h"
19 #include "ui/base/dragdrop/drag_drop_types.h" 20 #include "ui/base/dragdrop/drag_drop_types.h"
20 #include "ui/base/l10n/l10n_util.h" 21 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/range/range.h" 22 #include "ui/base/range/range.h"
22 #include "ui/gfx/canvas.h" 23 #include "ui/gfx/canvas.h"
23 #include "ui/gfx/compositor/layer.h" 24 #include "ui/gfx/compositor/layer.h"
24 #include "ui/gfx/insets.h" 25 #include "ui/gfx/insets.h"
25 #include "ui/gfx/render_text.h" 26 #include "ui/gfx/render_text.h"
26 #include "ui/views/background.h" 27 #include "ui/views/background.h"
27 #include "ui/views/border.h" 28 #include "ui/views/border.h"
28 #include "ui/views/controls/focusable_border.h" 29 #include "ui/views/controls/focusable_border.h"
29 #include "ui/views/controls/menu/menu_item_view.h" 30 #include "ui/views/controls/menu/menu_item_view.h"
30 #include "ui/views/controls/menu/menu_model_adapter.h" 31 #include "ui/views/controls/menu/menu_model_adapter.h"
31 #include "ui/views/controls/menu/menu_runner.h" 32 #include "ui/views/controls/menu/menu_runner.h"
32 #include "ui/views/controls/textfield/textfield.h" 33 #include "ui/views/controls/textfield/textfield.h"
33 #include "ui/views/controls/textfield/textfield_controller.h" 34 #include "ui/views/controls/textfield/textfield_controller.h"
34 #include "ui/views/controls/textfield/textfield_views_model.h" 35 #include "ui/views/controls/textfield/textfield_views_model.h"
35 #include "ui/views/events/event.h" 36 #include "ui/views/events/event.h"
36 #include "ui/views/ime/input_method.h" 37 #include "ui/views/ime/input_method.h"
37 #include "ui/views/metrics.h" 38 #include "ui/views/metrics.h"
38 #include "ui/views/views_delegate.h" 39 #include "ui/views/views_delegate.h"
39 #include "ui/views/widget/widget.h" 40 #include "ui/views/widget/widget.h"
41 #include "unicode/uchar.h"
40 42
41 #if defined(USE_AURA) 43 #if defined(USE_AURA)
42 #include "ui/base/cursor/cursor.h" 44 #include "ui/base/cursor/cursor.h"
43 #endif 45 #endif
44 46
45 namespace { 47 namespace {
46 48
47 // Text color for read only. 49 // Text color for read only.
48 const SkColor kReadonlyTextColor = SK_ColorDKGRAY; 50 const SkColor kReadonlyTextColor = SK_ColorDKGRAY;
49 51
(...skipping 20 matching lines...) Expand all
70 skip_input_method_cancel_composition_(false), 72 skip_input_method_cancel_composition_(false),
71 initiating_drag_(false), 73 initiating_drag_(false),
72 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)), 74 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)),
73 aggregated_clicks_(0), 75 aggregated_clicks_(0),
74 last_click_time_(), 76 last_click_time_(),
75 last_click_location_(), 77 last_click_location_(),
76 ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_( 78 ALLOW_THIS_IN_INITIALIZER_LIST(touch_selection_controller_(
77 TouchSelectionController::create(this))) { 79 TouchSelectionController::create(this))) {
78 set_border(text_border_); 80 set_border(text_border_);
79 81
80 // Lowercase is not supported.
81 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE);
82
83 #if defined(OS_CHROMEOS) 82 #if defined(OS_CHROMEOS)
84 GetRenderText()->SetFontList(gfx::FontList(l10n_util::GetStringUTF8( 83 GetRenderText()->SetFontList(gfx::FontList(l10n_util::GetStringUTF8(
85 IDS_UI_FONT_FAMILY_CROS))); 84 IDS_UI_FONT_FAMILY_CROS)));
86 #else 85 #else
87 GetRenderText()->SetFontList(gfx::FontList(textfield_->font())); 86 GetRenderText()->SetFontList(gfx::FontList(textfield_->font()));
88 #endif 87 #endif
89 // Set the default text style. 88 // Set the default text style.
90 gfx::StyleRange default_style; 89 gfx::StyleRange default_style;
91 default_style.foreground = textfield_->text_color(); 90 default_style.foreground = textfield_->text_color();
92 GetRenderText()->set_default_style(default_style); 91 GetRenderText()->set_default_style(default_style);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 DCHECK(CanDrop(event.data())); 190 DCHECK(CanDrop(event.data()));
192 DCHECK(!initiating_drag_ || 191 DCHECK(!initiating_drag_ ||
193 !GetRenderText()->IsPointInSelection(event.location())); 192 !GetRenderText()->IsPointInSelection(event.location()));
194 OnBeforeUserAction(); 193 OnBeforeUserAction();
195 skip_input_method_cancel_composition_ = true; 194 skip_input_method_cancel_composition_ = true;
196 195
197 gfx::SelectionModel drop_destination_model = 196 gfx::SelectionModel drop_destination_model =
198 GetRenderText()->FindCursorPosition(event.location()); 197 GetRenderText()->FindCursorPosition(event.location());
199 string16 text; 198 string16 text;
200 event.data().GetString(&text); 199 event.data().GetString(&text);
200 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
201 text = base::i18n::ToLower(text);
201 202
202 // We'll delete the current selection for a drag and drop within this view. 203 // We'll delete the current selection for a drag and drop within this view.
203 bool move = initiating_drag_ && !event.IsControlDown() && 204 bool move = initiating_drag_ && !event.IsControlDown() &&
204 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; 205 event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
205 if (move) { 206 if (move) {
206 gfx::SelectionModel selected; 207 gfx::SelectionModel selected;
207 model_->GetSelectionModel(&selected); 208 model_->GetSelectionModel(&selected);
208 // Adjust the drop destination if it is on or after the current selection. 209 // Adjust the drop destination if it is on or after the current selection.
209 size_t drop_destination = drop_destination_model.caret_pos(); 210 size_t drop_destination = drop_destination_model.caret_pos();
210 drop_destination -= 211 drop_destination -=
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 } 315 }
315 316
316 ///////////////////////////////////////////////////////////////// 317 /////////////////////////////////////////////////////////////////
317 // NativeTextfieldViews, NativeTextifieldWrapper overrides: 318 // NativeTextfieldViews, NativeTextifieldWrapper overrides:
318 319
319 string16 NativeTextfieldViews::GetText() const { 320 string16 NativeTextfieldViews::GetText() const {
320 return model_->GetText(); 321 return model_->GetText();
321 } 322 }
322 323
323 void NativeTextfieldViews::UpdateText() { 324 void NativeTextfieldViews::UpdateText() {
324 model_->SetText(textfield_->text()); 325 string16 text = textfield_->text();
326 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
327 text = base::i18n::ToLower(text);
328 model_->SetText(text);
325 OnCaretBoundsChanged(); 329 OnCaretBoundsChanged();
326 SchedulePaint(); 330 SchedulePaint();
327 textfield_->GetWidget()->NotifyAccessibilityEvent( 331 textfield_->GetWidget()->NotifyAccessibilityEvent(
328 textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true); 332 textfield_, ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
329 } 333 }
330 334
331 void NativeTextfieldViews::AppendText(const string16& text) { 335 void NativeTextfieldViews::AppendText(const string16& text) {
332 if (text.empty()) 336 if (text.empty())
333 return; 337 return;
334 model_->Append(text); 338 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
339 model_->Append(base::i18n::ToLower(text));
340 else
341 model_->Append(text);
335 OnCaretBoundsChanged(); 342 OnCaretBoundsChanged();
336 SchedulePaint(); 343 SchedulePaint();
337 } 344 }
338 345
339 string16 NativeTextfieldViews::GetSelectedText() const { 346 string16 NativeTextfieldViews::GetSelectedText() const {
340 return model_->GetSelectedText(); 347 return model_->GetSelectedText();
341 } 348 }
342 349
343 void NativeTextfieldViews::SelectAll() { 350 void NativeTextfieldViews::SelectAll() {
344 OnBeforeUserAction(); 351 OnBeforeUserAction();
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 OnAfterUserAction(); 668 OnAfterUserAction();
662 } 669 }
663 670
664 void NativeTextfieldViews::InsertText(const string16& text) { 671 void NativeTextfieldViews::InsertText(const string16& text) {
665 // TODO(suzhe): Filter invalid characters. 672 // TODO(suzhe): Filter invalid characters.
666 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty()) 673 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty())
667 return; 674 return;
668 675
669 OnBeforeUserAction(); 676 OnBeforeUserAction();
670 skip_input_method_cancel_composition_ = true; 677 skip_input_method_cancel_composition_ = true;
678
679 string16 new_text = text;
680 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
681 new_text = base::i18n::ToLower(new_text);
682
671 if (GetRenderText()->insert_mode()) 683 if (GetRenderText()->insert_mode())
672 model_->InsertText(text); 684 model_->InsertText(new_text);
673 else 685 else
674 model_->ReplaceText(text); 686 model_->ReplaceText(new_text);
675 skip_input_method_cancel_composition_ = false; 687 skip_input_method_cancel_composition_ = false;
676 UpdateAfterChange(true, true); 688 UpdateAfterChange(true, true);
677 OnAfterUserAction(); 689 OnAfterUserAction();
678 } 690 }
679 691
680 void NativeTextfieldViews::InsertChar(char16 ch, int flags) { 692 void NativeTextfieldViews::InsertChar(char16 ch, int flags) {
681 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || 693 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE ||
682 !ShouldInsertChar(ch, flags)) { 694 !ShouldInsertChar(ch, flags)) {
683 return; 695 return;
684 } 696 }
685 697
686 OnBeforeUserAction(); 698 OnBeforeUserAction();
687 skip_input_method_cancel_composition_ = true; 699 skip_input_method_cancel_composition_ = true;
688 if (GetRenderText()->insert_mode()) 700 if (GetRenderText()->insert_mode())
689 model_->InsertChar(ch); 701 model_->InsertChar(ch);
690 else 702 else
691 model_->ReplaceChar(ch); 703 model_->ReplaceChar(ch);
692 skip_input_method_cancel_composition_ = false; 704 skip_input_method_cancel_composition_ = false;
705
706 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
707 model_->SetText(base::i18n::ToLower(GetText()));
708
693 UpdateAfterChange(true, true); 709 UpdateAfterChange(true, true);
694 OnAfterUserAction(); 710 OnAfterUserAction();
695 } 711 }
696 712
697 ui::TextInputType NativeTextfieldViews::GetTextInputType() const { 713 ui::TextInputType NativeTextfieldViews::GetTextInputType() const {
698 return textfield_->GetTextInputType(); 714 return textfield_->GetTextInputType();
699 } 715 }
700 716
701 bool NativeTextfieldViews::CanComposeInline() const { 717 bool NativeTextfieldViews::CanComposeInline() const {
702 return true; 718 return true;
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 if (controller) 1051 if (controller)
1036 controller->OnAfterCutOrCopy(); 1052 controller->OnAfterCutOrCopy();
1037 return true; 1053 return true;
1038 } 1054 }
1039 return false; 1055 return false;
1040 } 1056 }
1041 1057
1042 bool NativeTextfieldViews::Paste() { 1058 bool NativeTextfieldViews::Paste() {
1043 const bool success = model_->Paste(); 1059 const bool success = model_->Paste();
1044 1060
1045 // Calls TextfieldController::ContentsChanged() explicitly if the paste action 1061 if (success) {
1046 // did not change the content at all. See http://crbug.com/79002 1062 // As Paste is handled in model_->Paste(), the RenderText may contain
1047 if (success && GetText() == textfield_->text()) { 1063 // lower-case characters. This is not consistent with other places
msw 2012/04/09 18:29:24 I think you mean "upper case" here, not "lower-cas
kochi 2012/04/10 07:38:11 Good catch, thanks!
1048 TextfieldController* controller = textfield_->GetController(); 1064 // which keeps RenderText only containing lower case characters.
1049 if (controller) 1065 if (textfield_->style() & Textfield::STYLE_LOWERCASE)
1050 controller->ContentsChanged(textfield_, textfield_->text()); 1066 model_->SetText(base::i18n::ToLower(GetText()));
1067
1068 // Calls TextfieldController::ContentsChanged() explicitly if the paste
1069 // action did not change the content at all. See http://crbug.com/79002
msw 2012/04/09 18:29:24 This isn't part of your change, but I don't unders
kochi 2012/04/10 07:38:11 I suppose that this case is for when you have sele
msw 2012/04/10 07:50:25 Yes, that's the intent, but TextfieldViewsModel::P
xji 2012/04/10 22:53:27 Looks like it is the wrong comment. As long as the
kochi 2012/04/11 01:56:41 OK, I changed the original comment in TextfieldVie
1070 if (GetText() == textfield_->text()) {
1071 TextfieldController* controller = textfield_->GetController();
1072 if (controller)
1073 controller->ContentsChanged(textfield_, textfield_->text());
1074 }
1051 } 1075 }
1052 return success; 1076 return success;
1053 } 1077 }
1054 1078
1055 void NativeTextfieldViews::TrackMouseClicks(const MouseEvent& event) { 1079 void NativeTextfieldViews::TrackMouseClicks(const MouseEvent& event) {
1056 if (event.IsOnlyLeftMouseButton()) { 1080 if (event.IsOnlyLeftMouseButton()) {
1057 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; 1081 base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
1058 if (time_delta.InMilliseconds() <= GetDoubleClickInterval() && 1082 if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
1059 !ExceededDragThresholdFromLastClickLocation(event)) { 1083 !ExceededDragThresholdFromLastClickLocation(event)) {
1060 aggregated_clicks_ = (aggregated_clicks_ + 1) % 3; 1084 aggregated_clicks_ = (aggregated_clicks_ + 1) % 3;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 1139
1116 #if defined(USE_AURA) 1140 #if defined(USE_AURA)
1117 // static 1141 // static
1118 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( 1142 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper(
1119 Textfield* field) { 1143 Textfield* field) {
1120 return new NativeTextfieldViews(field); 1144 return new NativeTextfieldViews(field);
1121 } 1145 }
1122 #endif 1146 #endif
1123 1147
1124 } // namespace views 1148 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698