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

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

Issue 73403002: Views Textfield: copy-on-select and paste-on-middle-click. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make UpdateSelectionClipboard a Textfield member. Created 6 years, 11 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/textfield.h" 5 #include "ui/views/controls/textfield/textfield.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "grit/ui_strings.h" 10 #include "grit/ui_strings.h"
11 #include "ui/base/accessibility/accessible_view_state.h" 11 #include "ui/base/accessibility/accessible_view_state.h"
12 #include "ui/base/clipboard/scoped_clipboard_writer.h"
12 #include "ui/base/dragdrop/drag_drop_types.h" 13 #include "ui/base/dragdrop/drag_drop_types.h"
13 #include "ui/base/dragdrop/drag_utils.h" 14 #include "ui/base/dragdrop/drag_utils.h"
14 #include "ui/base/resource/resource_bundle.h" 15 #include "ui/base/resource/resource_bundle.h"
15 #include "ui/base/ui_base_switches_util.h" 16 #include "ui/base/ui_base_switches_util.h"
16 #include "ui/events/event.h" 17 #include "ui/events/event.h"
17 #include "ui/events/keycodes/keyboard_codes.h" 18 #include "ui/events/keycodes/keyboard_codes.h"
18 #include "ui/gfx/canvas.h" 19 #include "ui/gfx/canvas.h"
19 #include "ui/gfx/insets.h" 20 #include "ui/gfx/insets.h"
20 #include "ui/native_theme/native_theme.h" 21 #include "ui/native_theme/native_theme.h"
21 #include "ui/views/background.h" 22 #include "ui/views/background.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 OnCaretBoundsChanged(); 145 OnCaretBoundsChanged();
145 SchedulePaint(); 146 SchedulePaint();
146 } 147 }
147 148
148 base::i18n::TextDirection Textfield::GetTextDirection() const { 149 base::i18n::TextDirection Textfield::GetTextDirection() const {
149 return GetRenderText()->GetTextDirection(); 150 return GetRenderText()->GetTextDirection();
150 } 151 }
151 152
152 void Textfield::SelectAll(bool reversed) { 153 void Textfield::SelectAll(bool reversed) {
153 model_->SelectAll(reversed); 154 model_->SelectAll(reversed);
154 OnCaretBoundsChanged(); 155 UpdateSelectionClipboard();
155 SchedulePaint(); 156 UpdateAfterChange(false, true);
156 } 157 }
157 158
158 base::string16 Textfield::GetSelectedText() const { 159 base::string16 Textfield::GetSelectedText() const {
159 return model_->GetSelectedText(); 160 return model_->GetSelectedText();
160 } 161 }
161 162
162 void Textfield::ClearSelection() { 163 void Textfield::ClearSelection() {
163 model_->ClearSelection(); 164 model_->ClearSelection();
164 OnCaretBoundsChanged(); 165 UpdateAfterChange(false, true);
165 SchedulePaint();
166 } 166 }
167 167
168 bool Textfield::HasSelection() const { 168 bool Textfield::HasSelection() const {
169 return !GetSelectedRange().is_empty(); 169 return !GetSelectedRange().is_empty();
170 } 170 }
171 171
172 SkColor Textfield::GetTextColor() const { 172 SkColor Textfield::GetTextColor() const {
173 if (!use_default_text_color_) 173 if (!use_default_text_color_)
174 return text_color_; 174 return text_color_;
175 175
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 bool Textfield::IsIMEComposing() const { 234 bool Textfield::IsIMEComposing() const {
235 return model_->HasCompositionText(); 235 return model_->HasCompositionText();
236 } 236 }
237 237
238 const gfx::Range& Textfield::GetSelectedRange() const { 238 const gfx::Range& Textfield::GetSelectedRange() const {
239 return GetRenderText()->selection(); 239 return GetRenderText()->selection();
240 } 240 }
241 241
242 void Textfield::SelectRange(const gfx::Range& range) { 242 void Textfield::SelectRange(const gfx::Range& range) {
243 model_->SelectRange(range); 243 model_->SelectRange(range);
244 OnCaretBoundsChanged(); 244 UpdateAfterChange(false, true);
245 SchedulePaint();
246 NotifyAccessibilityEvent(
247 ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
248 } 245 }
249 246
250 const gfx::SelectionModel& Textfield::GetSelectionModel() const { 247 const gfx::SelectionModel& Textfield::GetSelectionModel() const {
251 return GetRenderText()->selection_model(); 248 return GetRenderText()->selection_model();
252 } 249 }
253 250
254 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) { 251 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
255 model_->SelectSelectionModel(sel); 252 model_->SelectSelectionModel(sel);
256 OnCaretBoundsChanged(); 253 UpdateAfterChange(false, true);
257 SchedulePaint();
258 } 254 }
259 255
260 size_t Textfield::GetCursorPosition() const { 256 size_t Textfield::GetCursorPosition() const {
261 return model_->GetCursorPosition(); 257 return model_->GetCursorPosition();
262 } 258 }
263 259
264 void Textfield::SetColor(SkColor value) { 260 void Textfield::SetColor(SkColor value) {
265 GetRenderText()->SetColor(value); 261 GetRenderText()->SetColor(value);
266 SchedulePaint(); 262 SchedulePaint();
267 } 263 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 else if (control && shift && !alt && editable) 359 else if (control && shift && !alt && editable)
364 cursor_changed = text_changed = model_->Redo(); 360 cursor_changed = text_changed = model_->Redo();
365 break; 361 break;
366 case ui::VKEY_Y: 362 case ui::VKEY_Y:
367 if (control && !alt && editable) 363 if (control && !alt && editable)
368 cursor_changed = text_changed = model_->Redo(); 364 cursor_changed = text_changed = model_->Redo();
369 break; 365 break;
370 case ui::VKEY_A: 366 case ui::VKEY_A:
371 if (control && !alt) { 367 if (control && !alt) {
372 model_->SelectAll(false); 368 model_->SelectAll(false);
369 UpdateSelectionClipboard();
373 cursor_changed = true; 370 cursor_changed = true;
374 } 371 }
375 break; 372 break;
376 case ui::VKEY_X: 373 case ui::VKEY_X:
377 if (control && !alt && editable && readable) 374 if (control && !alt && editable && readable)
378 cursor_changed = text_changed = Cut(); 375 cursor_changed = text_changed = Cut();
379 break; 376 break;
380 case ui::VKEY_C: 377 case ui::VKEY_C:
381 if (control && !alt && readable) 378 if (control && !alt && readable)
382 Copy(); 379 Copy();
383 break; 380 break;
384 case ui::VKEY_V: 381 case ui::VKEY_V:
385 if (control && !alt && editable) 382 if (control && !alt && editable)
386 cursor_changed = text_changed = Paste(); 383 cursor_changed = text_changed = Paste();
387 break; 384 break;
388 case ui::VKEY_RIGHT: 385 case ui::VKEY_RIGHT:
389 case ui::VKEY_LEFT: { 386 case ui::VKEY_LEFT: {
390 // We should ignore the alt-left/right keys because alt key doesn't make 387 // We should ignore the alt-left/right keys because alt key doesn't make
391 // any special effects for them and they can be shortcut keys such like 388 // any special effects for them and they can be shortcut keys such like
392 // forward/back of the browser history. 389 // forward/back of the browser history.
393 if (alt) 390 if (alt)
394 break; 391 break;
395 const gfx::Range selection_range = render_text->selection(); 392 const gfx::Range selection_range = render_text->selection();
396 model_->MoveCursor( 393 model_->MoveCursor(
397 control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK, 394 control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
398 (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT, 395 (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
399 shift); 396 shift);
397 UpdateSelectionClipboard();
400 cursor_changed = render_text->selection() != selection_range; 398 cursor_changed = render_text->selection() != selection_range;
401 break; 399 break;
402 } 400 }
403 case ui::VKEY_END: 401 case ui::VKEY_END:
404 case ui::VKEY_HOME: 402 case ui::VKEY_HOME:
405 if ((key_code == ui::VKEY_HOME) == 403 if ((key_code == ui::VKEY_HOME) ==
406 (render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT)) 404 (render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
407 model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift); 405 model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
408 else 406 else
409 model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift); 407 model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
408 UpdateSelectionClipboard();
410 cursor_changed = true; 409 cursor_changed = true;
411 break; 410 break;
412 case ui::VKEY_BACK: 411 case ui::VKEY_BACK:
413 case ui::VKEY_DELETE: 412 case ui::VKEY_DELETE:
414 if (!editable) 413 if (!editable)
415 break; 414 break;
416 if (!model_->HasSelection()) { 415 if (!model_->HasSelection()) {
417 gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ? 416 gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
418 gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT; 417 gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
419 if (shift && control) { 418 if (shift && control) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 // We must have input method in order to support text input. 452 // We must have input method in order to support text input.
454 DCHECK(GetInputMethod()); 453 DCHECK(GetInputMethod());
455 UpdateAfterChange(text_changed, cursor_changed); 454 UpdateAfterChange(text_changed, cursor_changed);
456 OnAfterUserAction(); 455 OnAfterUserAction();
457 return (text_changed || cursor_changed); 456 return (text_changed || cursor_changed);
458 } 457 }
459 return false; 458 return false;
460 } 459 }
461 460
462 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { 461 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
463 OnBeforeUserAction();
464 TrackMouseClicks(event); 462 TrackMouseClicks(event);
465 463
466 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { 464 if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
467 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) 465 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())
468 RequestFocus(); 466 RequestFocus();
469 467
470 if (event.IsOnlyLeftMouseButton()) { 468 if (event.IsOnlyLeftMouseButton()) {
469 OnBeforeUserAction();
471 initiating_drag_ = false; 470 initiating_drag_ = false;
472 bool can_drag = true;
473
474 switch (aggregated_clicks_) { 471 switch (aggregated_clicks_) {
475 case 0: 472 case 0:
476 if (can_drag && 473 if (GetRenderText()->IsPointInSelection(event.location()))
477 GetRenderText()->IsPointInSelection(event.location())) {
478 initiating_drag_ = true; 474 initiating_drag_ = true;
479 } else { 475 else
480 MoveCursorTo(event.location(), event.IsShiftDown()); 476 MoveCursorTo(event.location(), event.IsShiftDown());
481 }
482 break; 477 break;
483 case 1: 478 case 1:
484 MoveCursorTo(event.location(), false); 479 model_->MoveCursorTo(event.location(), false);
485 model_->SelectWord(); 480 model_->SelectWord();
481 UpdateAfterChange(false, true);
486 double_click_word_ = GetRenderText()->selection(); 482 double_click_word_ = GetRenderText()->selection();
487 OnCaretBoundsChanged();
488 break; 483 break;
489 case 2: 484 case 2:
490 model_->SelectAll(false); 485 SelectAll(false);
491 OnCaretBoundsChanged();
492 break; 486 break;
493 default: 487 default:
494 NOTREACHED(); 488 NOTREACHED();
495 } 489 }
490 OnAfterUserAction();
496 } 491 }
497 SchedulePaint(); 492
493 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
494 if (event.IsOnlyMiddleMouseButton()) {
495 if (GetRenderText()->IsPointInSelection(event.location())) {
496 OnBeforeUserAction();
497 ClearSelection();
498 ui::ScopedClipboardWriter(
499 ui::Clipboard::GetForCurrentThread(),
500 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
501 OnAfterUserAction();
502 } else if(!read_only()) {
503 PasteSelectionClipboard(event);
504 }
505 }
506 #endif
498 } 507 }
499 508
500 OnAfterUserAction();
501 touch_selection_controller_.reset(); 509 touch_selection_controller_.reset();
502 return true; 510 return true;
503 } 511 }
504 512
505 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { 513 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
506 // Don't adjust the cursor on a potential drag and drop, or if the mouse 514 // Don't adjust the cursor on a potential drag and drop, or if the mouse
507 // movement from the last mouse click does not exceed the drag threshold. 515 // movement from the last mouse click does not exceed the drag threshold.
508 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() || 516 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
509 !ExceededDragThreshold(event.location() - last_click_location_)) { 517 !ExceededDragThreshold(event.location() - last_click_location_)) {
510 return true; 518 return true;
511 } 519 }
512 520
513 if (!event.IsOnlyRightMouseButton()) { 521 OnBeforeUserAction();
514 OnBeforeUserAction(); 522 model_->MoveCursorTo(event.location(), true);
515 MoveCursorTo(event.location(), true); 523 if (aggregated_clicks_ == 1) {
516 if (aggregated_clicks_ == 1) { 524 model_->SelectWord();
517 model_->SelectWord(); 525 // Expand the selection so the initially selected word remains selected.
518 // Expand the selection so the initially selected word remains selected. 526 gfx::Range selection = GetRenderText()->selection();
519 gfx::Range selection = GetRenderText()->selection(); 527 const size_t min = std::min(selection.GetMin(),
520 const size_t min = std::min(selection.GetMin(), 528 double_click_word_.GetMin());
521 double_click_word_.GetMin()); 529 const size_t max = std::max(selection.GetMax(),
522 const size_t max = std::max(selection.GetMax(), 530 double_click_word_.GetMax());
523 double_click_word_.GetMax()); 531 const bool reversed = selection.is_reversed();
524 const bool reversed = selection.is_reversed(); 532 selection.set_start(reversed ? max : min);
525 selection.set_start(reversed ? max : min); 533 selection.set_end(reversed ? min : max);
526 selection.set_end(reversed ? min : max); 534 model_->SelectRange(selection);
527 model_->SelectRange(selection);
528 }
529 SchedulePaint();
530 OnAfterUserAction();
531 } 535 }
536 UpdateAfterChange(false, true);
537 OnAfterUserAction();
532 return true; 538 return true;
533 } 539 }
534 540
535 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { 541 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
536 OnBeforeUserAction(); 542 OnBeforeUserAction();
537 // Cancel suspected drag initiations, the user was clicking in the selection. 543 // Cancel suspected drag initiations, the user was clicking in the selection.
538 if (initiating_drag_ && MoveCursorTo(event.location(), false)) 544 if (initiating_drag_)
539 SchedulePaint(); 545 MoveCursorTo(event.location(), false);
540 initiating_drag_ = false; 546 initiating_drag_ = false;
547 UpdateSelectionClipboard();
541 OnAfterUserAction(); 548 OnAfterUserAction();
542 } 549 }
543 550
544 void Textfield::OnFocus() { 551 void Textfield::OnFocus() {
545 GetRenderText()->set_focused(true); 552 GetRenderText()->set_focused(true);
546 cursor_visible_ = true; 553 cursor_visible_ = true;
547 SchedulePaint(); 554 SchedulePaint();
548 GetInputMethod()->OnFocus(); 555 GetInputMethod()->OnFocus();
549 OnCaretBoundsChanged(); 556 OnCaretBoundsChanged();
550 557
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 #endif 637 #endif
631 } 638 }
632 639
633 void Textfield::OnGestureEvent(ui::GestureEvent* event) { 640 void Textfield::OnGestureEvent(ui::GestureEvent* event) {
634 switch (event->type()) { 641 switch (event->type()) {
635 case ui::ET_GESTURE_TAP_DOWN: 642 case ui::ET_GESTURE_TAP_DOWN:
636 OnBeforeUserAction(); 643 OnBeforeUserAction();
637 RequestFocus(); 644 RequestFocus();
638 // We don't deselect if the point is in the selection 645 // We don't deselect if the point is in the selection
639 // because TAP_DOWN may turn into a LONG_PRESS. 646 // because TAP_DOWN may turn into a LONG_PRESS.
640 if (!GetRenderText()->IsPointInSelection(event->location()) && 647 if (!GetRenderText()->IsPointInSelection(event->location()))
641 MoveCursorTo(event->location(), false)) 648 MoveCursorTo(event->location(), false);
642 SchedulePaint();
643 OnAfterUserAction(); 649 OnAfterUserAction();
644 event->SetHandled(); 650 event->SetHandled();
645 break; 651 break;
646 case ui::ET_GESTURE_SCROLL_UPDATE: 652 case ui::ET_GESTURE_SCROLL_UPDATE:
647 OnBeforeUserAction(); 653 OnBeforeUserAction();
648 if (MoveCursorTo(event->location(), true)) 654 MoveCursorTo(event->location(), true);
649 SchedulePaint();
650 OnAfterUserAction(); 655 OnAfterUserAction();
651 event->SetHandled(); 656 event->SetHandled();
652 break; 657 break;
653 case ui::ET_GESTURE_SCROLL_END: 658 case ui::ET_GESTURE_SCROLL_END:
654 case ui::ET_SCROLL_FLING_START: 659 case ui::ET_SCROLL_FLING_START:
655 CreateTouchSelectionControllerAndNotifyIt(); 660 CreateTouchSelectionControllerAndNotifyIt();
656 event->SetHandled(); 661 event->SetHandled();
657 break; 662 break;
658 case ui::ET_GESTURE_TAP: 663 case ui::ET_GESTURE_TAP:
659 if (event->details().tap_count() == 1) { 664 if (event->details().tap_count() == 1) {
(...skipping 15 matching lines...) Expand all
675 // |touch_selection_controller_|, hence we mark the event handled. 680 // |touch_selection_controller_|, hence we mark the event handled.
676 // Otherwise, the regular context menu will be shown by views). 681 // Otherwise, the regular context menu will be shown by views).
677 // If long press happens in selected text and touch drag drop is enabled, 682 // If long press happens in selected text and touch drag drop is enabled,
678 // we will turn off touch selection (if one exists) and let views do drag 683 // we will turn off touch selection (if one exists) and let views do drag
679 // drop. 684 // drop.
680 if (!GetRenderText()->IsPointInSelection(event->location())) { 685 if (!GetRenderText()->IsPointInSelection(event->location())) {
681 OnBeforeUserAction(); 686 OnBeforeUserAction();
682 model_->SelectWord(); 687 model_->SelectWord();
683 touch_selection_controller_.reset( 688 touch_selection_controller_.reset(
684 ui::TouchSelectionController::create(this)); 689 ui::TouchSelectionController::create(this));
685 OnCaretBoundsChanged(); 690 UpdateAfterChange(false, true);
686 SchedulePaint();
687 OnAfterUserAction(); 691 OnAfterUserAction();
688 if (touch_selection_controller_) 692 if (touch_selection_controller_)
689 event->SetHandled(); 693 event->SetHandled();
690 } else if (switches::IsTouchDragDropEnabled()) { 694 } else if (switches::IsTouchDragDropEnabled()) {
691 initiating_drag_ = true; 695 initiating_drag_ = true;
692 touch_selection_controller_.reset(); 696 touch_selection_controller_.reset();
693 } else { 697 } else {
694 if (!touch_selection_controller_) 698 if (!touch_selection_controller_)
695 CreateTouchSelectionControllerAndNotifyIt(); 699 CreateTouchSelectionControllerAndNotifyIt();
696 if (touch_selection_controller_) 700 if (touch_selection_controller_)
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 889 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
886 return; 890 return;
887 891
888 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); 892 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
889 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); 893 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
890 gfx::SelectionModel selection( 894 gfx::SelectionModel selection(
891 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), 895 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
892 end_caret.caret_affinity()); 896 end_caret.caret_affinity());
893 897
894 OnBeforeUserAction(); 898 OnBeforeUserAction();
895 model_->SelectSelectionModel(selection); 899 SelectSelectionModel(selection);
896 OnCaretBoundsChanged();
897 SchedulePaint();
898 OnAfterUserAction(); 900 OnAfterUserAction();
899 } 901 }
900 902
901 void Textfield::MoveCaretTo(const gfx::Point& point) { 903 void Textfield::MoveCaretTo(const gfx::Point& point) {
902 SelectRect(point, point); 904 SelectRect(point, point);
903 } 905 }
904 906
905 void Textfield::GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) { 907 void Textfield::GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) {
906 gfx::RenderText* render_text = GetRenderText(); 908 gfx::RenderText* render_text = GetRenderText();
907 const gfx::SelectionModel& sel = render_text->selection_model(); 909 const gfx::SelectionModel& sel = render_text->selection_model();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 ui::Accelerator* accelerator) { 973 ui::Accelerator* accelerator) {
972 return false; 974 return false;
973 } 975 }
974 976
975 void Textfield::ExecuteCommand(int command_id, int event_flags) { 977 void Textfield::ExecuteCommand(int command_id, int event_flags) {
976 touch_selection_controller_.reset(); 978 touch_selection_controller_.reset();
977 if (!IsCommandIdEnabled(command_id)) 979 if (!IsCommandIdEnabled(command_id))
978 return; 980 return;
979 981
980 bool text_changed = false; 982 bool text_changed = false;
983 OnBeforeUserAction();
981 switch (command_id) { 984 switch (command_id) {
982 case IDS_APP_UNDO: 985 case IDS_APP_UNDO:
983 OnBeforeUserAction();
984 text_changed = model_->Undo(); 986 text_changed = model_->Undo();
985 UpdateAfterChange(text_changed, text_changed);
986 OnAfterUserAction();
987 break; 987 break;
988 case IDS_APP_CUT: 988 case IDS_APP_CUT:
989 OnBeforeUserAction();
990 text_changed = Cut(); 989 text_changed = Cut();
991 UpdateAfterChange(text_changed, text_changed);
992 OnAfterUserAction();
993 break; 990 break;
994 case IDS_APP_COPY: 991 case IDS_APP_COPY:
995 OnBeforeUserAction();
996 Copy(); 992 Copy();
997 OnAfterUserAction();
998 break; 993 break;
999 case IDS_APP_PASTE: 994 case IDS_APP_PASTE:
1000 OnBeforeUserAction();
1001 text_changed = Paste(); 995 text_changed = Paste();
1002 UpdateAfterChange(text_changed, text_changed);
1003 OnAfterUserAction();
1004 break; 996 break;
1005 case IDS_APP_DELETE: 997 case IDS_APP_DELETE:
1006 OnBeforeUserAction();
1007 text_changed = model_->Delete(); 998 text_changed = model_->Delete();
1008 UpdateAfterChange(text_changed, text_changed);
1009 OnAfterUserAction();
1010 break; 999 break;
1011 case IDS_APP_SELECT_ALL: 1000 case IDS_APP_SELECT_ALL:
1012 OnBeforeUserAction();
1013 SelectAll(false); 1001 SelectAll(false);
1014 UpdateAfterChange(false, true);
1015 OnAfterUserAction();
1016 break; 1002 break;
1017 default: 1003 default:
1018 NOTREACHED(); 1004 NOTREACHED();
1019 break; 1005 break;
1020 } 1006 }
1007 UpdateAfterChange(text_changed, text_changed);
1008 OnAfterUserAction();
1021 } 1009 }
1022 1010
1023 //////////////////////////////////////////////////////////////////////////////// 1011 ////////////////////////////////////////////////////////////////////////////////
1024 // Textfield, ui::TextInputClient overrides: 1012 // Textfield, ui::TextInputClient overrides:
1025 1013
1026 void Textfield::SetCompositionText(const ui::CompositionText& composition) { 1014 void Textfield::SetCompositionText(const ui::CompositionText& composition) {
1027 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1015 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1028 return; 1016 return;
1029 1017
1030 OnBeforeUserAction(); 1018 OnBeforeUserAction();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 bool Textfield::GetSelectionRange(gfx::Range* range) const { 1174 bool Textfield::GetSelectionRange(gfx::Range* range) const {
1187 if (!ImeEditingAllowed()) 1175 if (!ImeEditingAllowed())
1188 return false; 1176 return false;
1189 *range = GetRenderText()->selection(); 1177 *range = GetRenderText()->selection();
1190 return true; 1178 return true;
1191 } 1179 }
1192 1180
1193 bool Textfield::SetSelectionRange(const gfx::Range& range) { 1181 bool Textfield::SetSelectionRange(const gfx::Range& range) {
1194 if (!ImeEditingAllowed() || !range.IsValid()) 1182 if (!ImeEditingAllowed() || !range.IsValid())
1195 return false; 1183 return false;
1196
1197 OnBeforeUserAction(); 1184 OnBeforeUserAction();
1198 SelectRange(range); 1185 SelectRange(range);
1199 OnAfterUserAction(); 1186 OnAfterUserAction();
1200 return true; 1187 return true;
1201 } 1188 }
1202 1189
1203 bool Textfield::DeleteRange(const gfx::Range& range) { 1190 bool Textfield::DeleteRange(const gfx::Range& range) {
1204 if (!ImeEditingAllowed() || range.is_empty()) 1191 if (!ImeEditingAllowed() || range.is_empty())
1205 return false; 1192 return false;
1206 1193
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1350 !HasSelection()); 1337 !HasSelection());
1351 render_text->Draw(canvas); 1338 render_text->Draw(canvas);
1352 1339
1353 // Draw the detached drop cursor that marks where the text will be dropped. 1340 // Draw the detached drop cursor that marks where the text will be dropped.
1354 if (drop_cursor_visible_) 1341 if (drop_cursor_visible_)
1355 render_text->DrawCursor(canvas, drop_cursor_position_); 1342 render_text->DrawCursor(canvas, drop_cursor_position_);
1356 1343
1357 canvas->Restore(); 1344 canvas->Restore();
1358 } 1345 }
1359 1346
1360 bool Textfield::MoveCursorTo(const gfx::Point& point, bool select) { 1347 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
1361 if (!model_->MoveCursorTo(point, select)) 1348 if (model_->MoveCursorTo(point, select))
1362 return false; 1349 UpdateAfterChange(false, true);
1363 OnCaretBoundsChanged();
1364 return true;
1365 } 1350 }
1366 1351
1367 void Textfield::OnCaretBoundsChanged() { 1352 void Textfield::OnCaretBoundsChanged() {
1368 if (GetInputMethod()) 1353 if (GetInputMethod())
1369 GetInputMethod()->OnCaretBoundsChanged(this); 1354 GetInputMethod()->OnCaretBoundsChanged(this);
1370 if (touch_selection_controller_) 1355 if (touch_selection_controller_)
1371 touch_selection_controller_->SelectionChanged(); 1356 touch_selection_controller_->SelectionChanged();
1372 } 1357 }
1373 1358
1374 void Textfield::OnBeforeUserAction() { 1359 void Textfield::OnBeforeUserAction() {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 1448
1464 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { 1449 void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
1465 if (!touch_selection_controller_) { 1450 if (!touch_selection_controller_) {
1466 touch_selection_controller_.reset( 1451 touch_selection_controller_.reset(
1467 ui::TouchSelectionController::create(this)); 1452 ui::TouchSelectionController::create(this));
1468 } 1453 }
1469 if (touch_selection_controller_) 1454 if (touch_selection_controller_)
1470 touch_selection_controller_->SelectionChanged(); 1455 touch_selection_controller_->SelectionChanged();
1471 } 1456 }
1472 1457
1458 void Textfield::UpdateSelectionClipboard() const {
1459 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1460 if (HasSelection()) {
1461 ui::ScopedClipboardWriter(
1462 ui::Clipboard::GetForCurrentThread(),
1463 ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
1464 }
1465 #endif
1466 }
1467
1468 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
1469 DCHECK(event.IsOnlyMiddleMouseButton());
1470 DCHECK(!read_only());
1471 base::string16 selection_clipboard_text;
1472 ui::Clipboard::GetForCurrentThread()->ReadText(
1473 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
1474 if (!selection_clipboard_text.empty()) {
1475 OnBeforeUserAction();
1476 gfx::Range range = GetSelectionModel().selection();
1477 gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity();
1478 const gfx::SelectionModel mouse =
1479 GetRenderText()->FindCursorPosition(event.location());
1480 model_->MoveCursorTo(mouse);
1481 model_->InsertText(selection_clipboard_text);
1482 // Update the new selection range as needed.
1483 if (range.GetMin() >= mouse.caret_pos()) {
1484 const size_t length = selection_clipboard_text.length();
1485 range = gfx::Range(range.start() + length, range.end() + length);
1486 }
1487 model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
1488 UpdateAfterChange(true, true);
1489 OnAfterUserAction();
1490 }
1491 }
1492
1473 } // namespace views 1493 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | ui/views/controls/textfield/textfield_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698