Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/native_textfield_gtk.h" | 21 #include "views/controls/textfield/native_textfield_gtk.h" |
| 19 #include "views/controls/textfield/textfield.h" | 22 #include "views/controls/textfield/textfield.h" |
| 20 #include "views/controls/textfield/textfield_views_model.h" | 23 #include "views/controls/textfield/textfield_views_model.h" |
| 21 #include "views/event.h" | 24 #include "views/event.h" |
| 25 #include "views/views_delegate.h" | |
| 22 | 26 |
| 23 namespace { | 27 namespace { |
| 24 | 28 |
| 25 // A global flag to switch the Textfield wrapper to TextfieldViews. | 29 // A global flag to switch the Textfield wrapper to TextfieldViews. |
| 26 bool textfield_view_enabled = false; | 30 bool textfield_view_enabled = false; |
| 27 | 31 |
| 28 // Color setttings for text, border, backgrounds and cursor. | 32 // Color setttings for text, border, backgrounds and cursor. |
| 29 // These are tentative, and should be derived from theme, system | 33 // These are tentative, and should be derived from theme, system |
| 30 // settings and current settings. | 34 // settings and current settings. |
| 31 const SkColor kSelectedTextColor = SK_ColorWHITE; | 35 const SkColor kSelectedTextColor = SK_ColorWHITE; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 56 text_offset_(0), | 60 text_offset_(0), |
| 57 insert_(true), | 61 insert_(true), |
| 58 is_cursor_visible_(false), | 62 is_cursor_visible_(false), |
| 59 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { | 63 ALLOW_THIS_IN_INITIALIZER_LIST(cursor_timer_(this)) { |
| 60 set_border(text_border_); | 64 set_border(text_border_); |
| 61 | 65 |
| 62 // Multiline is not supported. | 66 // Multiline is not supported. |
| 63 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); | 67 DCHECK_NE(parent->style(), Textfield::STYLE_MULTILINE); |
| 64 // Lowercase is not supported. | 68 // Lowercase is not supported. |
| 65 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); | 69 DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE); |
| 70 | |
| 71 SetContextMenuController(this); | |
| 66 } | 72 } |
| 67 | 73 |
| 68 NativeTextfieldViews::~NativeTextfieldViews() { | 74 NativeTextfieldViews::~NativeTextfieldViews() { |
| 69 } | 75 } |
| 70 | 76 |
| 71 //////////////////////////////////////////////////////////////////////////////// | 77 //////////////////////////////////////////////////////////////////////////////// |
| 72 // NativeTextfieldViews, View overrides: | 78 // NativeTextfieldViews, View overrides: |
| 73 | 79 |
| 74 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { | 80 bool NativeTextfieldViews::OnMousePressed(const views::MouseEvent& e) { |
| 75 textfield_->RequestFocus(); | 81 textfield_->RequestFocus(); |
| 76 size_t pos = FindCursorPosition(e.location()); | 82 if (e.IsLeftMouseButton()) { |
|
oshima
2011/01/12 18:46:25
q: should this be "Only"?
varunjain
2011/01/12 19:59:05
the behaviour of the current textfield in chrome's
| |
| 77 if (model_->MoveCursorTo(pos, false)) { | 83 size_t pos = FindCursorPosition(e.location()); |
| 78 UpdateCursorBoundsAndTextOffset(); | 84 if (model_->MoveCursorTo(pos, false)) { |
| 79 SchedulePaint(); | 85 UpdateCursorBoundsAndTextOffset(); |
| 86 SchedulePaint(); | |
| 87 } | |
|
sadrul
2011/01/12 19:09:16
Are there plans for middle-click-to-paste? Or is t
oshima
2011/01/12 19:25:31
It's X selection and different from cut&paste. I'v
| |
| 80 } | 88 } |
| 81 return true; | 89 return true; |
| 82 } | 90 } |
| 83 | 91 |
| 84 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { | 92 bool NativeTextfieldViews::OnMouseDragged(const views::MouseEvent& e) { |
| 85 size_t pos = FindCursorPosition(e.location()); | 93 size_t pos = FindCursorPosition(e.location()); |
| 86 if (model_->MoveCursorTo(pos, true)) { | 94 if (model_->MoveCursorTo(pos, true)) { |
| 87 UpdateCursorBoundsAndTextOffset(); | 95 UpdateCursorBoundsAndTextOffset(); |
| 88 SchedulePaint(); | 96 SchedulePaint(); |
| 89 } | 97 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 | 134 |
| 127 void NativeTextfieldViews::DidGainFocus() { | 135 void NativeTextfieldViews::DidGainFocus() { |
| 128 NOTREACHED(); | 136 NOTREACHED(); |
| 129 } | 137 } |
| 130 | 138 |
| 131 void NativeTextfieldViews::WillLoseFocus() { | 139 void NativeTextfieldViews::WillLoseFocus() { |
| 132 NOTREACHED(); | 140 NOTREACHED(); |
| 133 } | 141 } |
| 134 | 142 |
| 135 ///////////////////////////////////////////////////////////////// | 143 ///////////////////////////////////////////////////////////////// |
| 144 // NativeTextfieldViews, views::ContextMenuController overrides: | |
| 145 void NativeTextfieldViews::ShowContextMenu(View* source, | |
| 146 const gfx::Point& p, | |
| 147 bool is_mouse_gesture) { | |
| 148 if (!context_menu_menu_.get()) | |
| 149 CreateContextMenu(); | |
| 150 context_menu_menu_->RunContextMenuAt(p); | |
| 151 } | |
| 152 | |
| 153 ///////////////////////////////////////////////////////////////// | |
| 136 // NativeTextfieldViews, NativeTextifieldWrapper overrides: | 154 // NativeTextfieldViews, NativeTextifieldWrapper overrides: |
| 137 | 155 |
| 138 string16 NativeTextfieldViews::GetText() const { | 156 string16 NativeTextfieldViews::GetText() const { |
| 139 return model_->text(); | 157 return model_->text(); |
| 140 } | 158 } |
| 141 | 159 |
| 142 void NativeTextfieldViews::UpdateText() { | 160 void NativeTextfieldViews::UpdateText() { |
| 143 bool changed = model_->SetText(textfield_->text()); | 161 bool changed = model_->SetText(textfield_->text()); |
| 144 UpdateCursorBoundsAndTextOffset(); | 162 UpdateCursorBoundsAndTextOffset(); |
| 145 SchedulePaint(); | 163 SchedulePaint(); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 | 304 |
| 287 void NativeTextfieldViews::HandleWillLoseFocus() { | 305 void NativeTextfieldViews::HandleWillLoseFocus() { |
| 288 // Stop blinking cursor. | 306 // Stop blinking cursor. |
| 289 cursor_timer_.RevokeAll(); | 307 cursor_timer_.RevokeAll(); |
| 290 if (is_cursor_visible_) { | 308 if (is_cursor_visible_) { |
| 291 is_cursor_visible_ = false; | 309 is_cursor_visible_ = false; |
| 292 RepaintCursor(); | 310 RepaintCursor(); |
| 293 } | 311 } |
| 294 } | 312 } |
| 295 | 313 |
| 314 ///////////////////////////////////////////////////////////////// | |
| 315 // NativeTextfieldViews, menus::SimpleMenuModel::Delegate overrides: | |
| 316 | |
| 317 bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const { | |
| 318 return true; | |
| 319 } | |
| 320 | |
| 321 bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const { | |
| 322 string16 result; | |
| 323 switch (command_id) { | |
| 324 case IDS_APP_CUT: | |
| 325 return model_->HasSelection(); | |
| 326 case IDS_APP_COPY: | |
| 327 return model_->HasSelection(); | |
| 328 case IDS_APP_PASTE: | |
| 329 views::ViewsDelegate::views_delegate->GetClipboard() | |
| 330 ->ReadText(ui::Clipboard::BUFFER_STANDARD, &result); | |
| 331 return !result.empty(); | |
| 332 case IDS_APP_DELETE: | |
| 333 return model_->HasSelection(); | |
| 334 case IDS_APP_SELECT_ALL: | |
| 335 return true; | |
| 336 default: | |
| 337 return false; | |
| 338 } | |
| 339 return false; | |
| 340 } | |
| 341 | |
| 342 bool NativeTextfieldViews::GetAcceleratorForCommandId(int command_id, | |
| 343 menus::Accelerator* accelerator) { | |
| 344 return false; | |
| 345 } | |
| 346 | |
| 347 void NativeTextfieldViews::ExecuteCommand(int command_id) { | |
| 348 bool text_changed = false; | |
| 349 switch (command_id) { | |
| 350 case IDS_APP_CUT: | |
| 351 text_changed = model_->Cut(); | |
| 352 break; | |
| 353 case IDS_APP_COPY: | |
| 354 model_->Copy(); | |
| 355 break; | |
| 356 case IDS_APP_PASTE: | |
| 357 text_changed = model_->Paste(); | |
| 358 break; | |
| 359 case IDS_APP_DELETE: | |
| 360 text_changed = model_->Delete(); | |
| 361 break; | |
| 362 case IDS_APP_SELECT_ALL: | |
| 363 SelectAll(); | |
| 364 break; | |
| 365 default: | |
|
oshima
2011/01/12 18:46:25
NOTREACHED() << "unkonwn command:" << command_id;
varunjain
2011/01/12 19:59:05
Done.
| |
| 366 break; | |
| 367 } | |
| 368 if (text_changed) | |
| 369 PropagateTextChange(); | |
| 370 } | |
| 371 | |
| 296 // static | 372 // static |
| 297 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { | 373 bool NativeTextfieldViews::IsTextfieldViewsEnabled() { |
| 298 #if defined(TOUCH_UI) | 374 #if defined(TOUCH_UI) |
| 299 return true; | 375 return true; |
| 300 #else | 376 #else |
| 301 return textfield_view_enabled || | 377 return textfield_view_enabled || |
| 302 CommandLine::ForCurrentProcess()->HasSwitch( | 378 CommandLine::ForCurrentProcess()->HasSwitch( |
| 303 kEnableViewsBasedTextfieldSwitch); | 379 kEnableViewsBasedTextfieldSwitch); |
| 304 #endif | 380 #endif |
| 305 } | 381 } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 break; | 594 break; |
| 519 } | 595 } |
| 520 char16 print_char = GetPrintableChar(key_event); | 596 char16 print_char = GetPrintableChar(key_event); |
| 521 if (!control && print_char) { | 597 if (!control && print_char) { |
| 522 if (insert_) | 598 if (insert_) |
| 523 model_->Insert(print_char); | 599 model_->Insert(print_char); |
| 524 else | 600 else |
| 525 model_->Replace(print_char); | 601 model_->Replace(print_char); |
| 526 text_changed = true; | 602 text_changed = true; |
| 527 } | 603 } |
| 528 if (text_changed) { | 604 if (text_changed) |
| 529 textfield_->SyncText(); | 605 PropagateTextChange(); |
| 530 Textfield::Controller* controller = textfield_->GetController(); | |
| 531 if (controller) | |
| 532 controller->ContentsChanged(textfield_, GetText()); | |
| 533 } | |
| 534 if (cursor_changed) { | 606 if (cursor_changed) { |
| 535 is_cursor_visible_ = true; | 607 is_cursor_visible_ = true; |
| 536 RepaintCursor(); | 608 RepaintCursor(); |
| 537 } | 609 } |
| 538 if (text_changed || cursor_changed) { | 610 if (text_changed || cursor_changed) { |
| 539 UpdateCursorBoundsAndTextOffset(); | 611 UpdateCursorBoundsAndTextOffset(); |
| 540 SchedulePaint(); | 612 SchedulePaint(); |
| 541 return true; | 613 return true; |
| 542 } | 614 } |
| 543 } | 615 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 686 } else if (pivot == x) { | 758 } else if (pivot == x) { |
| 687 return pivot_pos; | 759 return pivot_pos; |
| 688 } else { | 760 } else { |
| 689 right = pivot; | 761 right = pivot; |
| 690 right_pos = pivot_pos; | 762 right_pos = pivot_pos; |
| 691 } | 763 } |
| 692 } | 764 } |
| 693 return left_pos; | 765 return left_pos; |
| 694 } | 766 } |
| 695 | 767 |
| 768 void NativeTextfieldViews::PropagateTextChange() { | |
| 769 textfield_->SyncText(); | |
| 770 Textfield::Controller* controller = textfield_->GetController(); | |
| 771 if (controller) | |
| 772 controller->ContentsChanged(textfield_, GetText()); | |
| 773 } | |
| 774 | |
| 775 void NativeTextfieldViews::CreateContextMenu() { | |
| 776 context_menu_contents_.reset(new menus::SimpleMenuModel(this)); | |
| 777 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); | |
|
sadrul
2011/01/12 19:09:16
IDC_xxx should be used for command-id, and IDS_xxx
varunjain
2011/01/12 19:59:05
I was confused by this... IDCs are defined in chro
sadrul
2011/01/12 20:24:59
I fixed up some cases of IDS_/IDC_ mixups in chrom
| |
| 778 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); | |
| 779 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); | |
| 780 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); | |
| 781 context_menu_contents_->AddSeparator(); | |
| 782 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, | |
| 783 IDS_APP_SELECT_ALL); | |
| 784 context_menu_menu_.reset(new Menu2(context_menu_contents_.get())); | |
| 785 } | |
| 786 | |
| 696 /////////////////////////////////////////////////////////////////////////////// | 787 /////////////////////////////////////////////////////////////////////////////// |
| 697 // NativeTextfieldWrapper: | 788 // NativeTextfieldWrapper: |
| 698 | 789 |
| 699 // static | 790 // static |
| 700 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( | 791 NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper( |
| 701 Textfield* field) { | 792 Textfield* field) { |
| 702 if (NativeTextfieldViews::IsTextfieldViewsEnabled()) { | 793 if (NativeTextfieldViews::IsTextfieldViewsEnabled()) { |
| 703 return new NativeTextfieldViews(field); | 794 return new NativeTextfieldViews(field); |
| 704 } else { | 795 } else { |
| 705 return new NativeTextfieldGtk(field); | 796 return new NativeTextfieldGtk(field); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 754 } | 845 } |
| 755 | 846 |
| 756 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, | 847 void NativeTextfieldViews::TextfieldBorder::SetInsets(int top, |
| 757 int left, | 848 int left, |
| 758 int bottom, | 849 int bottom, |
| 759 int right) { | 850 int right) { |
| 760 insets_.Set(top, left, bottom, right); | 851 insets_.Set(top, left, bottom, right); |
| 761 } | 852 } |
| 762 | 853 |
| 763 } // namespace views | 854 } // namespace views |
| OLD | NEW |