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