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

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

Issue 191783002: Reorder View Textfield and Omnibox overrides. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 int Textfield::GetBaseline() const { 305 int Textfield::GetBaseline() const {
306 return GetInsets().top() + GetRenderText()->GetBaseline(); 306 return GetInsets().top() + GetRenderText()->GetBaseline();
307 } 307 }
308 308
309 gfx::Size Textfield::GetPreferredSize() { 309 gfx::Size Textfield::GetPreferredSize() {
310 const gfx::Insets& insets = GetInsets(); 310 const gfx::Insets& insets = GetInsets();
311 return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) + 311 return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) +
312 insets.width(), GetFontList().GetHeight() + insets.height()); 312 insets.width(), GetFontList().GetHeight() + insets.height());
313 } 313 }
314 314
315 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) { 315 const char* Textfield::GetClassName() const {
316 SelectAll(false); 316 return kViewClassName;
317 } 317 }
318 318
319 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) { 319 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
320 // Skip any accelerator handling of backspace; textfields handle this key. 320 bool in_selection = GetRenderText()->IsPointInSelection(event.location());
321 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes. 321 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
322 return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode(); 322 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
323 return text_cursor ? ui::kCursorIBeam : ui::kCursorNull;
323 } 324 }
324 325
325 void Textfield::OnPaint(gfx::Canvas* canvas) { 326 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
326 OnPaintBackground(canvas); 327 TrackMouseClicks(event);
327 PaintTextAndCursor(canvas); 328
328 OnPaintBorder(canvas); 329 if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
329 if (NativeViewHost::kRenderNativeControlFocus) 330 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) {
330 Painter::PaintFocusPainter(this, canvas, focus_painter_.get()); 331 RequestFocus();
332 ShowImeIfNeeded();
333 }
334
335 if (event.IsOnlyLeftMouseButton()) {
336 OnBeforeUserAction();
337 initiating_drag_ = false;
338 switch (aggregated_clicks_) {
339 case 0:
340 if (GetRenderText()->IsPointInSelection(event.location()))
341 initiating_drag_ = true;
342 else
343 MoveCursorTo(event.location(), event.IsShiftDown());
344 break;
345 case 1:
346 model_->MoveCursorTo(event.location(), false);
347 model_->SelectWord();
348 UpdateAfterChange(false, true);
349 double_click_word_ = GetRenderText()->selection();
350 break;
351 case 2:
352 SelectAll(false);
353 break;
354 default:
355 NOTREACHED();
356 }
357 OnAfterUserAction();
358 }
359
360 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
361 if (event.IsOnlyMiddleMouseButton()) {
362 if (GetRenderText()->IsPointInSelection(event.location())) {
363 OnBeforeUserAction();
364 ClearSelection();
365 ui::ScopedClipboardWriter(
366 ui::Clipboard::GetForCurrentThread(),
367 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
368 OnAfterUserAction();
369 } else if(!read_only()) {
370 PasteSelectionClipboard(event);
371 }
372 }
373 #endif
374 }
375
376 touch_selection_controller_.reset();
377 return true;
378 }
379
380 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
381 // Don't adjust the cursor on a potential drag and drop, or if the mouse
382 // movement from the last mouse click does not exceed the drag threshold.
383 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
384 !ExceededDragThreshold(event.location() - last_click_location_)) {
385 return true;
386 }
387
388 OnBeforeUserAction();
389 model_->MoveCursorTo(event.location(), true);
390 if (aggregated_clicks_ == 1) {
391 model_->SelectWord();
392 // Expand the selection so the initially selected word remains selected.
393 gfx::Range selection = GetRenderText()->selection();
394 const size_t min = std::min(selection.GetMin(),
395 double_click_word_.GetMin());
396 const size_t max = std::max(selection.GetMax(),
397 double_click_word_.GetMax());
398 const bool reversed = selection.is_reversed();
399 selection.set_start(reversed ? max : min);
400 selection.set_end(reversed ? min : max);
401 model_->SelectRange(selection);
402 }
403 UpdateAfterChange(false, true);
404 OnAfterUserAction();
405 return true;
406 }
407
408 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
409 OnBeforeUserAction();
410 // Cancel suspected drag initiations, the user was clicking in the selection.
411 if (initiating_drag_)
412 MoveCursorTo(event.location(), false);
413 initiating_drag_ = false;
414 UpdateSelectionClipboard();
415 OnAfterUserAction();
331 } 416 }
332 417
333 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { 418 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
334 bool handled = controller_ && controller_->HandleKeyEvent(this, event); 419 bool handled = controller_ && controller_->HandleKeyEvent(this, event);
335 touch_selection_controller_.reset(); 420 touch_selection_controller_.reset();
336 if (handled) 421 if (handled)
337 return true; 422 return true;
338 423
339 // TODO(oshima): Refactor and consolidate with ExecuteCommand. 424 // TODO(oshima): Refactor and consolidate with ExecuteCommand.
340 if (event.type() == ui::ET_KEY_PRESSED) { 425 if (event.type() == ui::ET_KEY_PRESSED) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 536
452 // We must have input method in order to support text input. 537 // We must have input method in order to support text input.
453 DCHECK(GetInputMethod()); 538 DCHECK(GetInputMethod());
454 UpdateAfterChange(text_changed, cursor_changed); 539 UpdateAfterChange(text_changed, cursor_changed);
455 OnAfterUserAction(); 540 OnAfterUserAction();
456 return (text_changed || cursor_changed); 541 return (text_changed || cursor_changed);
457 } 542 }
458 return false; 543 return false;
459 } 544 }
460 545
461 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
462 TrackMouseClicks(event);
463
464 if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
465 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) {
466 RequestFocus();
467 ShowImeIfNeeded();
468 }
469
470 if (event.IsOnlyLeftMouseButton()) {
471 OnBeforeUserAction();
472 initiating_drag_ = false;
473 switch (aggregated_clicks_) {
474 case 0:
475 if (GetRenderText()->IsPointInSelection(event.location()))
476 initiating_drag_ = true;
477 else
478 MoveCursorTo(event.location(), event.IsShiftDown());
479 break;
480 case 1:
481 model_->MoveCursorTo(event.location(), false);
482 model_->SelectWord();
483 UpdateAfterChange(false, true);
484 double_click_word_ = GetRenderText()->selection();
485 break;
486 case 2:
487 SelectAll(false);
488 break;
489 default:
490 NOTREACHED();
491 }
492 OnAfterUserAction();
493 }
494
495 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
496 if (event.IsOnlyMiddleMouseButton()) {
497 if (GetRenderText()->IsPointInSelection(event.location())) {
498 OnBeforeUserAction();
499 ClearSelection();
500 ui::ScopedClipboardWriter(
501 ui::Clipboard::GetForCurrentThread(),
502 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
503 OnAfterUserAction();
504 } else if(!read_only()) {
505 PasteSelectionClipboard(event);
506 }
507 }
508 #endif
509 }
510
511 touch_selection_controller_.reset();
512 return true;
513 }
514
515 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
516 // Don't adjust the cursor on a potential drag and drop, or if the mouse
517 // movement from the last mouse click does not exceed the drag threshold.
518 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
519 !ExceededDragThreshold(event.location() - last_click_location_)) {
520 return true;
521 }
522
523 OnBeforeUserAction();
524 model_->MoveCursorTo(event.location(), true);
525 if (aggregated_clicks_ == 1) {
526 model_->SelectWord();
527 // Expand the selection so the initially selected word remains selected.
528 gfx::Range selection = GetRenderText()->selection();
529 const size_t min = std::min(selection.GetMin(),
530 double_click_word_.GetMin());
531 const size_t max = std::max(selection.GetMax(),
532 double_click_word_.GetMax());
533 const bool reversed = selection.is_reversed();
534 selection.set_start(reversed ? max : min);
535 selection.set_end(reversed ? min : max);
536 model_->SelectRange(selection);
537 }
538 UpdateAfterChange(false, true);
539 OnAfterUserAction();
540 return true;
541 }
542
543 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
544 OnBeforeUserAction();
545 // Cancel suspected drag initiations, the user was clicking in the selection.
546 if (initiating_drag_)
547 MoveCursorTo(event.location(), false);
548 initiating_drag_ = false;
549 UpdateSelectionClipboard();
550 OnAfterUserAction();
551 }
552
553 void Textfield::OnFocus() {
554 GetRenderText()->set_focused(true);
555 cursor_visible_ = true;
556 SchedulePaint();
557 GetInputMethod()->OnFocus();
558 OnCaretBoundsChanged();
559
560 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
561 if (caret_blink_ms != 0) {
562 cursor_repaint_timer_.Start(FROM_HERE,
563 base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
564 &Textfield::UpdateCursor);
565 }
566
567 View::OnFocus();
568 SchedulePaint();
569 }
570
571 void Textfield::OnBlur() {
572 GetRenderText()->set_focused(false);
573 GetInputMethod()->OnBlur();
574 cursor_repaint_timer_.Stop();
575 if (cursor_visible_) {
576 cursor_visible_ = false;
577 RepaintCursor();
578 }
579
580 touch_selection_controller_.reset();
581
582 // Border typically draws focus indicator.
583 SchedulePaint();
584 }
585
586 void Textfield::GetAccessibleState(ui::AXViewState* state) {
587 state->role = ui::AX_ROLE_TEXT_FIELD;
588 state->name = accessible_name_;
589 if (read_only())
590 state->state |= ui::AX_STATE_READ_ONLY;
591 if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
592 state->state |= ui::AX_STATE_PROTECTED;
593 state->value = text();
594
595 const gfx::Range range = GetSelectedRange();
596 state->selection_start = range.start();
597 state->selection_end = range.end();
598
599 if (!read_only()) {
600 state->set_value_callback =
601 base::Bind(&Textfield::AccessibilitySetValue,
602 weak_ptr_factory_.GetWeakPtr());
603 }
604 }
605
606 ui::TextInputClient* Textfield::GetTextInputClient() { 546 ui::TextInputClient* Textfield::GetTextInputClient() {
607 return read_only_ ? NULL : this; 547 return read_only_ ? NULL : this;
608 } 548 }
609 549
610 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
611 return GetCaretBounds().bottom_right();
612 }
613
614 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
615 UpdateColorsFromTheme(theme);
616 }
617
618 void Textfield::OnEnabledChanged() {
619 View::OnEnabledChanged();
620 if (GetInputMethod())
621 GetInputMethod()->OnTextInputTypeChanged(this);
622 SchedulePaint();
623 }
624
625 const char* Textfield::GetClassName() const {
626 return kViewClassName;
627 }
628
629 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
630 bool in_selection = GetRenderText()->IsPointInSelection(event.location());
631 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
632 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
633 return text_cursor ? ui::kCursorIBeam : ui::kCursorNull;
634 }
635
636 void Textfield::OnGestureEvent(ui::GestureEvent* event) { 550 void Textfield::OnGestureEvent(ui::GestureEvent* event) {
637 switch (event->type()) { 551 switch (event->type()) {
638 case ui::ET_GESTURE_TAP_DOWN: 552 case ui::ET_GESTURE_TAP_DOWN:
639 OnBeforeUserAction(); 553 OnBeforeUserAction();
640 RequestFocus(); 554 RequestFocus();
641 ShowImeIfNeeded(); 555 ShowImeIfNeeded();
642 556
643 // We don't deselect if the point is in the selection 557 // We don't deselect if the point is in the selection
644 // because TAP_DOWN may turn into a LONG_PRESS. 558 // because TAP_DOWN may turn into a LONG_PRESS.
645 if (!GetRenderText()->IsPointInSelection(event->location())) 559 if (!GetRenderText()->IsPointInSelection(event->location()))
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 // shown by the |touch_selection_controller_|, hence we mark the event 621 // shown by the |touch_selection_controller_|, hence we mark the event
708 // handled so views does not try to show context menu on it. 622 // handled so views does not try to show context menu on it.
709 if (touch_selection_controller_) 623 if (touch_selection_controller_)
710 event->SetHandled(); 624 event->SetHandled();
711 break; 625 break;
712 default: 626 default:
713 return; 627 return;
714 } 628 }
715 } 629 }
716 630
631 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
632 SelectAll(false);
633 }
634
635 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
636 // Skip any accelerator handling of backspace; textfields handle this key.
637 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
638 return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode();
639 }
640
717 bool Textfield::GetDropFormats( 641 bool Textfield::GetDropFormats(
718 int* formats, 642 int* formats,
719 std::set<OSExchangeData::CustomFormat>* custom_formats) { 643 std::set<OSExchangeData::CustomFormat>* custom_formats) {
720 if (!enabled() || read_only()) 644 if (!enabled() || read_only())
721 return false; 645 return false;
722 // TODO(msw): Can we support URL, FILENAME, etc.? 646 // TODO(msw): Can we support URL, FILENAME, etc.?
723 *formats = ui::OSExchangeData::STRING; 647 *formats = ui::OSExchangeData::STRING;
724 if (controller_) 648 if (controller_)
725 controller_->AppendDropFormats(formats, custom_formats); 649 controller_->AppendDropFormats(formats, custom_formats);
726 return true; 650 return true;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 UpdateAfterChange(true, true); 722 UpdateAfterChange(true, true);
799 OnAfterUserAction(); 723 OnAfterUserAction();
800 return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY; 724 return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
801 } 725 }
802 726
803 void Textfield::OnDragDone() { 727 void Textfield::OnDragDone() {
804 initiating_drag_ = false; 728 initiating_drag_ = false;
805 drop_cursor_visible_ = false; 729 drop_cursor_visible_ = false;
806 } 730 }
807 731
732 void Textfield::GetAccessibleState(ui::AXViewState* state) {
733 state->role = ui::AX_ROLE_TEXT_FIELD;
734 state->name = accessible_name_;
735 if (read_only())
736 state->state |= ui::AX_STATE_READ_ONLY;
737 if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
738 state->state |= ui::AX_STATE_PROTECTED;
739 state->value = text();
740
741 const gfx::Range range = GetSelectedRange();
742 state->selection_start = range.start();
743 state->selection_end = range.end();
744
745 if (!read_only()) {
746 state->set_value_callback =
747 base::Bind(&Textfield::AccessibilitySetValue,
748 weak_ptr_factory_.GetWeakPtr());
749 }
750 }
751
808 void Textfield::OnBoundsChanged(const gfx::Rect& previous_bounds) { 752 void Textfield::OnBoundsChanged(const gfx::Rect& previous_bounds) {
809 GetRenderText()->SetDisplayRect(GetContentsBounds()); 753 GetRenderText()->SetDisplayRect(GetContentsBounds());
810 OnCaretBoundsChanged(); 754 OnCaretBoundsChanged();
811 } 755 }
812 756
757 void Textfield::OnEnabledChanged() {
758 View::OnEnabledChanged();
759 if (GetInputMethod())
760 GetInputMethod()->OnTextInputTypeChanged(this);
761 SchedulePaint();
762 }
763
813 void Textfield::ViewHierarchyChanged( 764 void Textfield::ViewHierarchyChanged(
814 const ViewHierarchyChangedDetails& details) { 765 const ViewHierarchyChangedDetails& details) {
815 if (details.is_add && details.child == this) 766 if (details.is_add && details.child == this)
816 UpdateColorsFromTheme(GetNativeTheme()); 767 UpdateColorsFromTheme(GetNativeTheme());
817 } 768 }
818 769
770 void Textfield::OnPaint(gfx::Canvas* canvas) {
771 OnPaintBackground(canvas);
772 PaintTextAndCursor(canvas);
773 OnPaintBorder(canvas);
774 if (NativeViewHost::kRenderNativeControlFocus)
775 Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
776 }
777
778 void Textfield::OnFocus() {
779 GetRenderText()->set_focused(true);
780 cursor_visible_ = true;
781 SchedulePaint();
782 GetInputMethod()->OnFocus();
783 OnCaretBoundsChanged();
784
785 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
786 if (caret_blink_ms != 0) {
787 cursor_repaint_timer_.Start(FROM_HERE,
788 base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
789 &Textfield::UpdateCursor);
790 }
791
792 View::OnFocus();
793 SchedulePaint();
794 }
795
796 void Textfield::OnBlur() {
797 GetRenderText()->set_focused(false);
798 GetInputMethod()->OnBlur();
799 cursor_repaint_timer_.Stop();
800 if (cursor_visible_) {
801 cursor_visible_ = false;
802 RepaintCursor();
803 }
804
805 touch_selection_controller_.reset();
806
807 // Border typically draws focus indicator.
808 SchedulePaint();
809 }
810
811 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
812 return GetCaretBounds().bottom_right();
813 }
814
815 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
816 UpdateColorsFromTheme(theme);
817 }
818
819 //////////////////////////////////////////////////////////////////////////////// 819 ////////////////////////////////////////////////////////////////////////////////
820 // Textfield, TextfieldModel::Delegate overrides: 820 // Textfield, TextfieldModel::Delegate overrides:
821 821
822 void Textfield::OnCompositionTextConfirmedOrCleared() { 822 void Textfield::OnCompositionTextConfirmedOrCleared() {
823 if (!skip_input_method_cancel_composition_) 823 if (!skip_input_method_cancel_composition_)
824 GetInputMethod()->CancelComposition(this); 824 GetInputMethod()->CancelComposition(this);
825 } 825 }
826 826
827 //////////////////////////////////////////////////////////////////////////////// 827 ////////////////////////////////////////////////////////////////////////////////
828 // Textfield, ContextMenuController overrides: 828 // Textfield, ContextMenuController overrides:
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 const size_t length = selection_clipboard_text.length(); 1486 const size_t length = selection_clipboard_text.length();
1487 range = gfx::Range(range.start() + length, range.end() + length); 1487 range = gfx::Range(range.start() + length, range.end() + length);
1488 } 1488 }
1489 model_->MoveCursorTo(gfx::SelectionModel(range, affinity)); 1489 model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
1490 UpdateAfterChange(true, true); 1490 UpdateAfterChange(true, true);
1491 OnAfterUserAction(); 1491 OnAfterUserAction();
1492 } 1492 }
1493 } 1493 }
1494 1494
1495 } // namespace views 1495 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698