• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "ui/views/controls/textfield/textfield.h"
6 
7 #include <string>
8 
9 #include "base/command_line.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/base/accessibility/accessible_view_state.h"
13 #include "ui/base/ime/text_input_type.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/base/ui_base_switches.h"
16 #include "ui/events/event.h"
17 #include "ui/events/keycodes/keyboard_codes.h"
18 #include "ui/gfx/insets.h"
19 #include "ui/gfx/range/range.h"
20 #include "ui/gfx/selection_model.h"
21 #include "ui/native_theme/native_theme.h"
22 #include "ui/views/controls/native/native_view_host.h"
23 #include "ui/views/controls/textfield/native_textfield_views.h"
24 #include "ui/views/controls/textfield/native_textfield_wrapper.h"
25 #include "ui/views/controls/textfield/textfield_controller.h"
26 #include "ui/views/painter.h"
27 #include "ui/views/views_delegate.h"
28 #include "ui/views/widget/widget.h"
29 
30 namespace {
31 
32 // Default placeholder text color.
33 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
34 
GetDefaultFontList()35 gfx::FontList GetDefaultFontList() {
36   return ResourceBundle::GetSharedInstance().GetFontList(
37       ResourceBundle::BaseFont);
38 }
39 
40 }  // namespace
41 
42 namespace views {
43 
44 // static
45 const char Textfield::kViewClassName[] = "Textfield";
46 
47 // static
GetCaretBlinkMs()48 size_t Textfield::GetCaretBlinkMs() {
49   static const size_t default_value = 500;
50 #if defined(OS_WIN)
51   static const size_t system_value = ::GetCaretBlinkTime();
52   if (system_value != 0)
53     return (system_value == INFINITE) ? 0 : system_value;
54 #endif
55   return default_value;
56 }
57 
Textfield()58 Textfield::Textfield()
59     : native_wrapper_(NULL),
60       controller_(NULL),
61       style_(STYLE_DEFAULT),
62       font_list_(GetDefaultFontList()),
63       read_only_(false),
64       default_width_in_chars_(0),
65       draw_border_(true),
66       text_color_(SK_ColorBLACK),
67       use_default_text_color_(true),
68       background_color_(SK_ColorWHITE),
69       use_default_background_color_(true),
70       horizontal_margins_were_set_(false),
71       vertical_margins_were_set_(false),
72       placeholder_text_color_(kDefaultPlaceholderTextColor),
73       text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
74       weak_ptr_factory_(this) {
75   SetFocusable(true);
76 
77   if (ViewsDelegate::views_delegate) {
78     obscured_reveal_duration_ = ViewsDelegate::views_delegate->
79         GetDefaultTextfieldObscuredRevealDuration();
80   }
81 
82   if (NativeViewHost::kRenderNativeControlFocus)
83     focus_painter_ = Painter::CreateDashedFocusPainter();
84 }
85 
Textfield(StyleFlags style)86 Textfield::Textfield(StyleFlags style)
87     : native_wrapper_(NULL),
88       controller_(NULL),
89       style_(style),
90       font_list_(GetDefaultFontList()),
91       read_only_(false),
92       default_width_in_chars_(0),
93       draw_border_(true),
94       text_color_(SK_ColorBLACK),
95       use_default_text_color_(true),
96       background_color_(SK_ColorWHITE),
97       use_default_background_color_(true),
98       horizontal_margins_were_set_(false),
99       vertical_margins_were_set_(false),
100       placeholder_text_color_(kDefaultPlaceholderTextColor),
101       text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
102       weak_ptr_factory_(this) {
103   SetFocusable(true);
104   if (IsObscured())
105     SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
106 
107   if (ViewsDelegate::views_delegate) {
108     obscured_reveal_duration_ = ViewsDelegate::views_delegate->
109         GetDefaultTextfieldObscuredRevealDuration();
110   }
111 
112   if (NativeViewHost::kRenderNativeControlFocus)
113     focus_painter_ = Painter::CreateDashedFocusPainter();
114 }
115 
~Textfield()116 Textfield::~Textfield() {
117 }
118 
SetController(TextfieldController * controller)119 void Textfield::SetController(TextfieldController* controller) {
120   controller_ = controller;
121 }
122 
GetController() const123 TextfieldController* Textfield::GetController() const {
124   return controller_;
125 }
126 
SetReadOnly(bool read_only)127 void Textfield::SetReadOnly(bool read_only) {
128   // Update read-only without changing the focusable state (or active, etc.).
129   read_only_ = read_only;
130   if (native_wrapper_) {
131     native_wrapper_->UpdateReadOnly();
132     native_wrapper_->UpdateTextColor();
133     native_wrapper_->UpdateBackgroundColor();
134   }
135 }
136 
IsObscured() const137 bool Textfield::IsObscured() const {
138   return style_ & STYLE_OBSCURED;
139 }
140 
SetObscured(bool obscured)141 void Textfield::SetObscured(bool obscured) {
142   if (obscured) {
143     style_ = static_cast<StyleFlags>(style_ | STYLE_OBSCURED);
144     SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
145   } else {
146     style_ = static_cast<StyleFlags>(style_ & ~STYLE_OBSCURED);
147     SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
148   }
149   if (native_wrapper_)
150     native_wrapper_->UpdateIsObscured();
151 }
152 
GetTextInputType() const153 ui::TextInputType Textfield::GetTextInputType() const {
154   if (read_only() || !enabled())
155     return ui::TEXT_INPUT_TYPE_NONE;
156   return text_input_type_;
157 }
158 
SetTextInputType(ui::TextInputType type)159 void Textfield::SetTextInputType(ui::TextInputType type) {
160   text_input_type_ = type;
161   bool should_be_obscured = type == ui::TEXT_INPUT_TYPE_PASSWORD;
162   if (IsObscured() != should_be_obscured)
163     SetObscured(should_be_obscured);
164 }
165 
SetText(const string16 & text)166 void Textfield::SetText(const string16& text) {
167   text_ = text;
168   if (native_wrapper_)
169     native_wrapper_->UpdateText();
170 }
171 
AppendText(const string16 & text)172 void Textfield::AppendText(const string16& text) {
173   text_ += text;
174   if (native_wrapper_)
175     native_wrapper_->AppendText(text);
176 }
177 
InsertOrReplaceText(const string16 & text)178 void Textfield::InsertOrReplaceText(const string16& text) {
179   if (native_wrapper_) {
180     native_wrapper_->InsertOrReplaceText(text);
181     text_ = native_wrapper_->GetText();
182   }
183 }
184 
GetTextDirection() const185 base::i18n::TextDirection Textfield::GetTextDirection() const {
186   return native_wrapper_ ?
187       native_wrapper_->GetTextDirection() : base::i18n::UNKNOWN_DIRECTION;
188 }
189 
SelectAll(bool reversed)190 void Textfield::SelectAll(bool reversed) {
191   if (native_wrapper_)
192     native_wrapper_->SelectAll(reversed);
193 }
194 
GetSelectedText() const195 string16 Textfield::GetSelectedText() const {
196   return native_wrapper_ ? native_wrapper_->GetSelectedText() : string16();
197 }
198 
ClearSelection() const199 void Textfield::ClearSelection() const {
200   if (native_wrapper_)
201     native_wrapper_->ClearSelection();
202 }
203 
HasSelection() const204 bool Textfield::HasSelection() const {
205   return native_wrapper_ && !native_wrapper_->GetSelectedRange().is_empty();
206 }
207 
GetTextColor() const208 SkColor Textfield::GetTextColor() const {
209   if (!use_default_text_color_)
210     return text_color_;
211 
212   return GetNativeTheme()->GetSystemColor(read_only() ?
213       ui::NativeTheme::kColorId_TextfieldReadOnlyColor :
214       ui::NativeTheme::kColorId_TextfieldDefaultColor);
215 }
216 
SetTextColor(SkColor color)217 void Textfield::SetTextColor(SkColor color) {
218   text_color_ = color;
219   use_default_text_color_ = false;
220   if (native_wrapper_)
221     native_wrapper_->UpdateTextColor();
222 }
223 
UseDefaultTextColor()224 void Textfield::UseDefaultTextColor() {
225   use_default_text_color_ = true;
226   if (native_wrapper_)
227     native_wrapper_->UpdateTextColor();
228 }
229 
GetBackgroundColor() const230 SkColor Textfield::GetBackgroundColor() const {
231   if (!use_default_background_color_)
232     return background_color_;
233 
234   return GetNativeTheme()->GetSystemColor(read_only() ?
235       ui::NativeTheme::kColorId_TextfieldReadOnlyBackground :
236       ui::NativeTheme::kColorId_TextfieldDefaultBackground);
237 }
238 
SetBackgroundColor(SkColor color)239 void Textfield::SetBackgroundColor(SkColor color) {
240   background_color_ = color;
241   use_default_background_color_ = false;
242   if (native_wrapper_)
243     native_wrapper_->UpdateBackgroundColor();
244 }
245 
UseDefaultBackgroundColor()246 void Textfield::UseDefaultBackgroundColor() {
247   use_default_background_color_ = true;
248   if (native_wrapper_)
249     native_wrapper_->UpdateBackgroundColor();
250 }
251 
GetCursorEnabled() const252 bool Textfield::GetCursorEnabled() const {
253   return native_wrapper_ && native_wrapper_->GetCursorEnabled();
254 }
255 
SetCursorEnabled(bool enabled)256 void Textfield::SetCursorEnabled(bool enabled) {
257   if (native_wrapper_)
258     native_wrapper_->SetCursorEnabled(enabled);
259 }
260 
SetFontList(const gfx::FontList & font_list)261 void Textfield::SetFontList(const gfx::FontList& font_list) {
262   font_list_ = font_list;
263   if (native_wrapper_)
264     native_wrapper_->UpdateFont();
265   PreferredSizeChanged();
266 }
267 
GetPrimaryFont() const268 const gfx::Font& Textfield::GetPrimaryFont() const {
269   return font_list_.GetPrimaryFont();
270 }
271 
SetFont(const gfx::Font & font)272 void Textfield::SetFont(const gfx::Font& font) {
273   SetFontList(gfx::FontList(font));
274 }
275 
SetHorizontalMargins(int left,int right)276 void Textfield::SetHorizontalMargins(int left, int right) {
277   if (horizontal_margins_were_set_ &&
278       left == margins_.left() && right == margins_.right()) {
279     return;
280   }
281   margins_.Set(margins_.top(), left, margins_.bottom(), right);
282   horizontal_margins_were_set_ = true;
283   if (native_wrapper_)
284     native_wrapper_->UpdateHorizontalMargins();
285   PreferredSizeChanged();
286 }
287 
SetVerticalMargins(int top,int bottom)288 void Textfield::SetVerticalMargins(int top, int bottom) {
289   if (vertical_margins_were_set_ &&
290       top == margins_.top() && bottom == margins_.bottom()) {
291     return;
292   }
293   margins_.Set(top, margins_.left(), bottom, margins_.right());
294   vertical_margins_were_set_ = true;
295   if (native_wrapper_)
296     native_wrapper_->UpdateVerticalMargins();
297   PreferredSizeChanged();
298 }
299 
RemoveBorder()300 void Textfield::RemoveBorder() {
301   if (!draw_border_)
302     return;
303 
304   draw_border_ = false;
305   if (native_wrapper_)
306     native_wrapper_->UpdateBorder();
307 }
308 
GetPlaceholderText() const309 base::string16 Textfield::GetPlaceholderText() const {
310   return placeholder_text_;
311 }
312 
GetHorizontalMargins(int * left,int * right)313 bool Textfield::GetHorizontalMargins(int* left, int* right) {
314   if (!horizontal_margins_were_set_)
315     return false;
316 
317   *left = margins_.left();
318   *right = margins_.right();
319   return true;
320 }
321 
GetVerticalMargins(int * top,int * bottom)322 bool Textfield::GetVerticalMargins(int* top, int* bottom) {
323   if (!vertical_margins_were_set_)
324     return false;
325 
326   *top = margins_.top();
327   *bottom = margins_.bottom();
328   return true;
329 }
330 
UpdateAllProperties()331 void Textfield::UpdateAllProperties() {
332   if (native_wrapper_) {
333     native_wrapper_->UpdateText();
334     native_wrapper_->UpdateTextColor();
335     native_wrapper_->UpdateBackgroundColor();
336     native_wrapper_->UpdateReadOnly();
337     native_wrapper_->UpdateFont();
338     native_wrapper_->UpdateEnabled();
339     native_wrapper_->UpdateBorder();
340     native_wrapper_->UpdateIsObscured();
341     native_wrapper_->UpdateHorizontalMargins();
342     native_wrapper_->UpdateVerticalMargins();
343   }
344 }
345 
SyncText()346 void Textfield::SyncText() {
347   if (native_wrapper_) {
348     string16 new_text = native_wrapper_->GetText();
349     if (new_text != text_) {
350       text_ = new_text;
351       if (controller_)
352         controller_->ContentsChanged(this, text_);
353     }
354   }
355 }
356 
IsIMEComposing() const357 bool Textfield::IsIMEComposing() const {
358   return native_wrapper_ && native_wrapper_->IsIMEComposing();
359 }
360 
GetSelectedRange() const361 gfx::Range Textfield::GetSelectedRange() const {
362   return native_wrapper_->GetSelectedRange();
363 }
364 
SelectRange(const gfx::Range & range)365 void Textfield::SelectRange(const gfx::Range& range) {
366   native_wrapper_->SelectRange(range);
367 }
368 
GetSelectionModel() const369 gfx::SelectionModel Textfield::GetSelectionModel() const {
370   return native_wrapper_->GetSelectionModel();
371 }
372 
SelectSelectionModel(const gfx::SelectionModel & sel)373 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
374   native_wrapper_->SelectSelectionModel(sel);
375 }
376 
GetCursorPosition() const377 size_t Textfield::GetCursorPosition() const {
378   return native_wrapper_->GetCursorPosition();
379 }
380 
SetColor(SkColor value)381 void Textfield::SetColor(SkColor value) {
382   return native_wrapper_->SetColor(value);
383 }
384 
ApplyColor(SkColor value,const gfx::Range & range)385 void Textfield::ApplyColor(SkColor value, const gfx::Range& range) {
386   return native_wrapper_->ApplyColor(value, range);
387 }
388 
SetStyle(gfx::TextStyle style,bool value)389 void Textfield::SetStyle(gfx::TextStyle style, bool value) {
390   return native_wrapper_->SetStyle(style, value);
391 }
392 
ApplyStyle(gfx::TextStyle style,bool value,const gfx::Range & range)393 void Textfield::ApplyStyle(gfx::TextStyle style,
394                            bool value,
395                            const gfx::Range& range) {
396   return native_wrapper_->ApplyStyle(style, value, range);
397 }
398 
ClearEditHistory()399 void Textfield::ClearEditHistory() {
400   native_wrapper_->ClearEditHistory();
401 }
402 
SetAccessibleName(const string16 & name)403 void Textfield::SetAccessibleName(const string16& name) {
404   accessible_name_ = name;
405 }
406 
ExecuteCommand(int command_id)407 void Textfield::ExecuteCommand(int command_id) {
408   native_wrapper_->ExecuteTextCommand(command_id);
409 }
410 
SetFocusPainter(scoped_ptr<Painter> focus_painter)411 void Textfield::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
412   focus_painter_ = focus_painter.Pass();
413 }
414 
HasTextBeingDragged()415 bool Textfield::HasTextBeingDragged() {
416   return native_wrapper_->HasTextBeingDragged();
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 // Textfield, View overrides:
421 
Layout()422 void Textfield::Layout() {
423   if (native_wrapper_) {
424     native_wrapper_->GetView()->SetBoundsRect(GetContentsBounds());
425     native_wrapper_->GetView()->Layout();
426   }
427 }
428 
GetBaseline() const429 int Textfield::GetBaseline() const {
430   gfx::Insets insets = GetTextInsets();
431   const int baseline = native_wrapper_ ?
432       native_wrapper_->GetTextfieldBaseline() : font_list_.GetBaseline();
433   return insets.top() + baseline;
434 }
435 
GetPreferredSize()436 gfx::Size Textfield::GetPreferredSize() {
437   gfx::Insets insets = GetTextInsets();
438 
439   const int font_height = native_wrapper_ ? native_wrapper_->GetFontHeight() :
440                                             font_list_.GetHeight();
441   return gfx::Size(
442       GetPrimaryFont().GetExpectedTextWidth(default_width_in_chars_)
443       + insets.width(),
444       font_height + insets.height());
445 }
446 
AboutToRequestFocusFromTabTraversal(bool reverse)447 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
448   SelectAll(false);
449 }
450 
SkipDefaultKeyEventProcessing(const ui::KeyEvent & e)451 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
452   // Skip any accelerator handling of backspace; textfields handle this key.
453   // Also skip processing of [Alt]+<num-pad digit> Unicode alt key codes.
454   return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode();
455 }
456 
OnPaint(gfx::Canvas * canvas)457 void Textfield::OnPaint(gfx::Canvas* canvas) {
458   View::OnPaint(canvas);
459   if (NativeViewHost::kRenderNativeControlFocus)
460     Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
461 }
462 
OnKeyPressed(const ui::KeyEvent & e)463 bool Textfield::OnKeyPressed(const ui::KeyEvent& e) {
464   return native_wrapper_ && native_wrapper_->HandleKeyPressed(e);
465 }
466 
OnKeyReleased(const ui::KeyEvent & e)467 bool Textfield::OnKeyReleased(const ui::KeyEvent& e) {
468   return native_wrapper_ && native_wrapper_->HandleKeyReleased(e);
469 }
470 
OnMouseDragged(const ui::MouseEvent & e)471 bool Textfield::OnMouseDragged(const ui::MouseEvent& e) {
472   if (!e.IsOnlyRightMouseButton())
473     return View::OnMouseDragged(e);
474   return true;
475 }
476 
OnFocus()477 void Textfield::OnFocus() {
478   if (native_wrapper_)
479     native_wrapper_->HandleFocus();
480 
481   // Forward the focus to the wrapper if it exists.
482   if (!native_wrapper_ || !native_wrapper_->SetFocus()) {
483     // If there is no wrapper or the wrapper didn't take focus, call
484     // View::Focus to clear the native focus so that we still get
485     // keyboard messages.
486     View::OnFocus();
487   }
488 
489   // Border typically draws focus indicator.
490   SchedulePaint();
491 }
492 
OnBlur()493 void Textfield::OnBlur() {
494   if (native_wrapper_)
495     native_wrapper_->HandleBlur();
496 
497   // Border typically draws focus indicator.
498   SchedulePaint();
499 }
500 
GetAccessibleState(ui::AccessibleViewState * state)501 void Textfield::GetAccessibleState(ui::AccessibleViewState* state) {
502   state->role = ui::AccessibilityTypes::ROLE_TEXT;
503   state->name = accessible_name_;
504   if (read_only())
505     state->state |= ui::AccessibilityTypes::STATE_READONLY;
506   if (IsObscured())
507     state->state |= ui::AccessibilityTypes::STATE_PROTECTED;
508   state->value = text_;
509 
510   const gfx::Range range = native_wrapper_->GetSelectedRange();
511   state->selection_start = range.start();
512   state->selection_end = range.end();
513 
514   if (!read_only()) {
515     state->set_value_callback =
516         base::Bind(&Textfield::AccessibilitySetValue,
517                    weak_ptr_factory_.GetWeakPtr());
518   }
519 }
520 
GetTextInputClient()521 ui::TextInputClient* Textfield::GetTextInputClient() {
522   return native_wrapper_ ? native_wrapper_->GetTextInputClient() : NULL;
523 }
524 
GetKeyboardContextMenuLocation()525 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
526   return native_wrapper_ ? native_wrapper_->GetContextMenuLocation() :
527                            View::GetKeyboardContextMenuLocation();
528 }
529 
OnEnabledChanged()530 void Textfield::OnEnabledChanged() {
531   View::OnEnabledChanged();
532   if (native_wrapper_)
533     native_wrapper_->UpdateEnabled();
534 }
535 
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)536 void Textfield::ViewHierarchyChanged(
537     const ViewHierarchyChangedDetails& details) {
538   if (details.is_add && !native_wrapper_ && GetWidget()) {
539     // The native wrapper's lifetime will be managed by the view hierarchy after
540     // we call AddChildView.
541     native_wrapper_ = NativeTextfieldWrapper::CreateWrapper(this);
542     AddChildViewAt(native_wrapper_->GetView(), 0);
543     Layout();
544     UpdateAllProperties();
545   }
546 }
547 
GetClassName() const548 const char* Textfield::GetClassName() const {
549   return kViewClassName;
550 }
551 
552 ////////////////////////////////////////////////////////////////////////////////
553 // Textfield, private:
554 
GetTextInsets() const555 gfx::Insets Textfield::GetTextInsets() const {
556   gfx::Insets insets = GetInsets();
557   if (draw_border_ && native_wrapper_)
558     insets += native_wrapper_->CalculateInsets();
559   return insets;
560 }
561 
AccessibilitySetValue(const string16 & new_value)562 void Textfield::AccessibilitySetValue(const string16& new_value) {
563   if (!read_only()) {
564     SetText(new_value);
565     ClearSelection();
566   }
567 }
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 // NativeTextfieldWrapper, public:
571 
572 // static
CreateWrapper(Textfield * field)573 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper(
574     Textfield* field) {
575   return new NativeTextfieldViews(field);
576 }
577 
578 }  // namespace views
579