OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "views/controls/textfield/native_textfield_views.h" | 5 #include "views/controls/textfield/native_textfield_views.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "gfx/canvas.h" | 13 #include "gfx/canvas.h" |
14 #include "gfx/canvas_skia.h" | 14 #include "gfx/canvas_skia.h" |
15 #include "gfx/insets.h" | 15 #include "gfx/insets.h" |
| 16 #include "grit/app_strings.h" |
| 17 #include "ui/base/clipboard/clipboard.h" |
16 #include "views/background.h" | 18 #include "views/background.h" |
17 #include "views/border.h" | 19 #include "views/border.h" |
| 20 #include "views/controls/menu/menu_2.h" |
18 #include "views/controls/textfield/textfield.h" | 21 #include "views/controls/textfield/textfield.h" |
19 #include "views/controls/textfield/textfield_views_model.h" | 22 #include "views/controls/textfield/textfield_views_model.h" |
20 #include "views/event.h" | 23 #include "views/event.h" |
| 24 #include "views/views_delegate.h" |
21 | 25 |
22 namespace { | 26 namespace { |
23 | 27 |
24 // A global flag to switch the Textfield wrapper to TextfieldViews. | 28 // A global flag to switch the Textfield wrapper to TextfieldViews. |
25 bool textfield_view_enabled = false; | 29 bool textfield_view_enabled = false; |
26 | 30 |
27 // Color setttings for text, border, backgrounds and cursor. | 31 // Color setttings for text, border, backgrounds and cursor. |
28 // These are tentative, and should be derived from theme, system | 32 // These are tentative, and should be derived from theme, system |
29 // settings and current settings. | 33 // settings and current settings. |
30 const SkColor kSelectedTextColor = SK_ColorWHITE; | 34 const SkColor kSelectedTextColor = SK_ColorWHITE; |
(...skipping 24 matching lines...) Expand all Loading... |
55 text_offset_(0), | 59 text_offset_(0), |
56 insert_(true), | 60 insert_(true), |
57 is_cursor_visible_(false), | 61 is_cursor_visible_(false), |
58 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { | 62 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { |
59 set_border(text_border_); | 63 set_border(text_border_); |
60 | 64 |
61 // Multiline is not supported. | 65 // Multiline is not supported. |
62 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); | 66 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); |
63 // Lowercase is not supported. | 67 // Lowercase is not supported. |
64 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); | 68 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); |
| 69 |
| 70 SetContextMenuController(this); |
65 } | 71 } |
66 | 72 |
67 NativeTextfieldViews::~NativeTextfieldViews() { | 73 NativeTextfieldViews::~NativeTextfieldViews() { |
68 } | 74 } |
69 | 75 |
70 //////////////////////////////////////////////////////////////////////////////// | 76 //////////////////////////////////////////////////////////////////////////////// |
71 // NativeTextfieldViews, View overrides: | 77 // NativeTextfieldViews, View overrides: |
72 | 78 |
73 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { | 79 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { |
74 textfield_->RequestFocus(); | 80 textfield_->RequestFocus(); |
75 size_t pos = FindCursorPosition(e.location()); | 81 if (e.IsLeftMouseButton()) { |
76 if (model_->MoveCursorTo(pos, false)) { | 82 size_t pos = FindCursorPosition(e.location()); |
77 UpdateCursorBoundsAndTextOffset(); | 83 if (model_->MoveCursorTo(pos, false)) { |
78 SchedulePaint(); | 84 UpdateCursorBoundsAndTextOffset(); |
| 85 SchedulePaint(); |
| 86 } |
79 } | 87 } |
80 return true; | 88 return true; |
81 } | 89 } |
82 | 90 |
83 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { | 91 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { |
84 size_t pos = FindCursorPosition(e.location()); | 92 size_t pos = FindCursorPosition(e.location()); |
85 if (model_->MoveCursorTo(pos, true)) { | 93 if (model_->MoveCursorTo(pos, true)) { |
86 UpdateCursorBoundsAndTextOffset(); | 94 UpdateCursorBoundsAndTextOffset(); |
87 SchedulePaint(); | 95 SchedulePaint(); |
88 } | 96 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 | 133 |
126 void NativeTextfieldViews::DidGainFocus() { | 134 void NativeTextfieldViews::DidGainFocus() { |
127 NOTREACHED(); | 135 NOTREACHED(); |
128 } | 136 } |
129 | 137 |
130 void NativeTextfieldViews::WillLoseFocus() { | 138 void NativeTextfieldViews::WillLoseFocus() { |
131 NOTREACHED(); | 139 NOTREACHED(); |
132 } | 140 } |
133 | 141 |
134 ///////////////////////////////////////////////////////////////// | 142 ///////////////////////////////////////////////////////////////// |
| 143 // NativeTextfieldViews, views::ContextMenuController overrides: |
| 144 void NativeTextfieldViews::ShowContextMenu(View* source, |
| 145 const gfx::Point& p, |
| 146 bool is_mouse_gesture) { |
| 147 InitContextMenuIfRequired(); |
| 148 context_menu_menu_->RunContextMenuAt(p); |
| 149 } |
| 150 |
| 151 ///////////////////////////////////////////////////////////////// |
135 // NativeTextfieldViews, NativeTextifieldWrapper overrides: | 152 // NativeTextfieldViews, NativeTextifieldWrapper overrides: |
136 | 153 |
137 string16 NativeTextfieldViews::GetText() const { | 154 string16 NativeTextfieldViews::GetText() const { |
138 return model_->text(); | 155 return model_->text(); |
139 } | 156 } |
140 | 157 |
141 void NativeTextfieldViews::UpdateText() { | 158 void NativeTextfieldViews::UpdateText() { |
142 bool changed = model_->SetText(textfield_->text()); | 159 bool changed = model_->SetText(textfield_->text()); |
143 UpdateCursorBoundsAndTextOffset(); | 160 UpdateCursorBoundsAndTextOffset(); |
144 SchedulePaint(); | 161 SchedulePaint(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 | 302 |
286 void NativeTextfieldViews::HandleWillLoseFocus() { | 303 void NativeTextfieldViews::HandleWillLoseFocus() { |
287 // Stop blinking cursor. | 304 // Stop blinking cursor. |
288 cursor_timer_.RevokeAll(); | 305 cursor_timer_.RevokeAll(); |
289 if (is_cursor_visible_) { | 306 if (is_cursor_visible_) { |
290 is_cursor_visible_ = false; | 307 is_cursor_visible_ = false; |
291 RepaintCursor(); | 308 RepaintCursor(); |
292 } | 309 } |
293 } | 310 } |
294 | 311 |
| 312 ///////////////////////////////////////////////////////////////// |
| 313 // NativeTextfieldViews, menus::SimpleMenuModel::Delegate overrides: |
| 314 |
| 315 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const { |
| 316 return true; |
| 317 } |
| 318 |
| 319 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const { |
| 320 string16 result; |
| 321 switch (command_id) { |
| 322 case IDS_APP_CUT: |
| 323 return model_->HasSelection(); |
| 324 case IDS_APP_COPY: |
| 325 return model_->HasSelection(); |
| 326 case IDS_APP_PASTE: |
| 327 views::ViewsDelegate::views_delegate->GetClipboard() |
| 328 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result); |
| 329 return !result.empty(); |
| 330 case IDS_APP_DELETE: |
| 331 return model_->HasSelection(); |
| 332 case IDS_APP_SELECT_ALL: |
| 333 return true; |
| 334 default: |
| 335 NOTREACHED(); |
| 336 return false; |
| 337 } |
| 338 } |
| 339 |
| 340 bool NativeTextfieldViews::GetAcceleratorForCommandId(int command_id, |
| 341 menus::Accelerator* accelerator) { |
| 342 return false; |
| 343 } |
| 344 |
| 345 void NativeTextfieldViews::ExecuteCommand(int command_id) { |
| 346 bool text_changed = false; |
| 347 switch (command_id) { |
| 348 case IDS_APP_CUT: |
| 349 text_changed = model_->Cut(); |
| 350 break; |
| 351 case IDS_APP_COPY: |
| 352 model_->Copy(); |
| 353 break; |
| 354 case IDS_APP_PASTE: |
| 355 text_changed = model_->Paste(); |
| 356 break; |
| 357 case IDS_APP_DELETE: |
| 358 text_changed = model_->Delete(); |
| 359 break; |
| 360 case IDS_APP_SELECT_ALL: |
| 361 SelectAll(); |
| 362 break; |
| 363 default: |
| 364 NOTREACHED() << "unknown command: " << command_id; |
| 365 break; |
| 366 } |
| 367 if (text_changed) |
| 368 PropagateTextChange(); |
| 369 } |
| 370 |
295 // static | 371 // static |
296 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { | 372 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { |
297 #if defined(TOUCH_UI) | 373 #if defined(TOUCH_UI) |
298 return true; | 374 return true; |
299 #else | 375 #else |
300 return textfield_view_enabled || | 376 return textfield_view_enabled || |
301 CommandLine::ForCurrentProcess()->HasSwitch( | 377 CommandLine::ForCurrentProcess()->HasSwitch( |
302 kEnableViewsBasedTextfieldSwitch); | 378 kEnableViewsBasedTextfieldSwitch); |
303 #endif | 379 #endif |
304 } | 380 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 break; | 591 break; |
516 } | 592 } |
517 char16 print_char = GetPrintableChar(key_event); | 593 char16 print_char = GetPrintableChar(key_event); |
518 if (!control && print_char) { | 594 if (!control && print_char) { |
519 if (insert_) | 595 if (insert_) |
520 model_->Insert(print_char); | 596 model_->Insert(print_char); |
521 else | 597 else |
522 model_->Replace(print_char); | 598 model_->Replace(print_char); |
523 text_changed = true; | 599 text_changed = true; |
524 } | 600 } |
525 if (text_changed) { | 601 if (text_changed) |
526 textfield_->SyncText(); | 602 PropagateTextChange(); |
527 Textfield::Controller* controller = textfield_->GetController(); | |
528 if (controller) | |
529 controller->ContentsChanged(textfield_, GetText()); | |
530 } | |
531 if (cursor_changed) { | 603 if (cursor_changed) { |
532 is_cursor_visible_ = true; | 604 is_cursor_visible_ = true; |
533 RepaintCursor(); | 605 RepaintCursor(); |
534 } | 606 } |
535 if (text_changed || cursor_changed) { | 607 if (text_changed || cursor_changed) { |
536 UpdateCursorBoundsAndTextOffset(); | 608 UpdateCursorBoundsAndTextOffset(); |
537 SchedulePaint(); | 609 SchedulePaint(); |
538 return true; | 610 return true; |
539 } | 611 } |
540 } | 612 } |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 } else if (pivot == x) { | 755 } else if (pivot == x) { |
684 return pivot_pos; | 756 return pivot_pos; |
685 } else { | 757 } else { |
686 right = pivot; | 758 right = pivot; |
687 right_pos = pivot_pos; | 759 right_pos = pivot_pos; |
688 } | 760 } |
689 } | 761 } |
690 return left_pos; | 762 return left_pos; |
691 } | 763 } |
692 | 764 |
| 765 void NativeTextfieldViews::PropagateTextChange() { |
| 766 textfield_->SyncText(); |
| 767 Textfield::Controller* controller = textfield_->GetController(); |
| 768 if (controller) |
| 769 controller->ContentsChanged(textfield_, GetText()); |
| 770 } |
| 771 |
| 772 void NativeTextfieldViews::InitContextMenuIfRequired() { |
| 773 if (context_menu_menu_.get()) |
| 774 return; |
| 775 context_menu_contents_.reset(new menus::SimpleMenuModel(this)); |
| 776 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); |
| 777 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); |
| 778 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); |
| 779 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); |
| 780 context_menu_contents_->AddSeparator(); |
| 781 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, |
| 782 IDS_APP_SELECT_ALL); |
| 783 context_menu_menu_.reset(new Menu2(context_menu_contents_.get())); |
| 784 } |
| 785 |
693 /////////////////////////////////////////////////////////////////////////////// | 786 /////////////////////////////////////////////////////////////////////////////// |
694 // | 787 // |
695 // TextifieldBorder | 788 // TextifieldBorder |
696 // | 789 // |
697 /////////////////////////////////////////////////////////////////////////////// | 790 /////////////////////////////////////////////////////////////////////////////// |
698 | 791 |
699 NativeTextfieldViews::TextfieldBorder::TextfieldBorder() | 792 NativeTextfieldViews::TextfieldBorder::TextfieldBorder() |
700 : has_focus_(false), | 793 : has_focus_(false), |
701 insets_(4, 4, 4, 4) { | 794 insets_(4, 4, 4, 4) { |
702 } | 795 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 } | 831 } |
739 | 832 |
740 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, | 833 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, |
741 int left, | 834 int left, |
742 int bottom, | 835 int bottom, |
743 int right) { | 836 int right) { |
744 insets_.Set(top, left, bottom, right); | 837 insets_.Set(top, left, bottom, right); |
745 } | 838 } |
746 | 839 |
747 } // namespace views | 840 } // namespace views |
OLD | NEW |