| OLD | NEW |
| 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/base/gestures/gesture_sequence.h" | 5 #include "ui/base/gestures/gesture_sequence.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 gfx::Point p2 = GetPointByPointId(1)->last_touch_position(); | 544 gfx::Point p2 = GetPointByPointId(1)->last_touch_position(); |
| 545 double max_distance = | 545 double max_distance = |
| 546 ui::GestureConfiguration::max_distance_for_two_finger_tap_in_pixels(); | 546 ui::GestureConfiguration::max_distance_for_two_finger_tap_in_pixels(); |
| 547 double distance = (p1.x() - p2.x()) * (p1.x() - p2.x()) + | 547 double distance = (p1.x() - p2.x()) * (p1.x() - p2.x()) + |
| 548 (p1.y() - p2.y()) * (p1.y() - p2.y()); | 548 (p1.y() - p2.y()) * (p1.y() - p2.y()); |
| 549 if (distance < max_distance * max_distance) | 549 if (distance < max_distance * max_distance) |
| 550 return true; | 550 return true; |
| 551 return false; | 551 return false; |
| 552 } | 552 } |
| 553 | 553 |
| 554 GestureEvent* GestureSequence::CreateGestureEvent( |
| 555 const GestureEventDetails& details, |
| 556 const gfx::Point& location, |
| 557 int flags, |
| 558 base::Time timestamp, |
| 559 unsigned int touch_id_bitmask) { |
| 560 GestureEventDetails gesture_details(details); |
| 561 gesture_details.set_touch_points(point_count_); |
| 562 return helper_->CreateGestureEvent(gesture_details, location, flags, |
| 563 timestamp, touch_id_bitmask); |
| 564 } |
| 565 |
| 554 void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, | 566 void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, |
| 555 Gestures* gestures) { | 567 Gestures* gestures) { |
| 556 gestures->push_back(helper_->CreateGestureEvent( | 568 gestures->push_back(CreateGestureEvent( |
| 557 ui::ET_GESTURE_TAP_DOWN, | 569 GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0), |
| 558 point.first_touch_position(), | 570 point.first_touch_position(), |
| 559 flags_, | 571 flags_, |
| 560 base::Time::FromDoubleT(point.last_touch_time()), | 572 base::Time::FromDoubleT(point.last_touch_time()), |
| 561 0, 0.f, 1 << point.touch_id())); | 573 1 << point.touch_id())); |
| 562 } | 574 } |
| 563 | 575 |
| 564 void GestureSequence::AppendBeginGestureEvent(const GesturePoint& point, | 576 void GestureSequence::AppendBeginGestureEvent(const GesturePoint& point, |
| 565 Gestures* gestures) { | 577 Gestures* gestures) { |
| 566 gestures->push_back(helper_->CreateGestureEvent( | 578 gestures->push_back(CreateGestureEvent( |
| 567 ui::ET_GESTURE_BEGIN, | 579 GestureEventDetails(ui::ET_GESTURE_BEGIN, point_count_, 0), |
| 568 point.first_touch_position(), | 580 point.first_touch_position(), |
| 569 flags_, | 581 flags_, |
| 570 base::Time::FromDoubleT(point.last_touch_time()), | 582 base::Time::FromDoubleT(point.last_touch_time()), |
| 571 point_count_, 0.f, 1 << point.touch_id())); | 583 1 << point.touch_id())); |
| 572 } | 584 } |
| 573 | 585 |
| 574 void GestureSequence::AppendEndGestureEvent(const GesturePoint& point, | 586 void GestureSequence::AppendEndGestureEvent(const GesturePoint& point, |
| 575 Gestures* gestures) { | 587 Gestures* gestures) { |
| 576 gestures->push_back(helper_->CreateGestureEvent( | 588 gestures->push_back(CreateGestureEvent( |
| 577 ui::ET_GESTURE_END, | 589 GestureEventDetails(ui::ET_GESTURE_END, point_count_, 0), |
| 578 point.first_touch_position(), | 590 point.first_touch_position(), |
| 579 flags_, | 591 flags_, |
| 580 base::Time::FromDoubleT(point.last_touch_time()), | 592 base::Time::FromDoubleT(point.last_touch_time()), |
| 581 point_count_, 0.f, 1 << point.touch_id())); | 593 1 << point.touch_id())); |
| 582 } | 594 } |
| 583 | 595 |
| 584 void GestureSequence::AppendClickGestureEvent(const GesturePoint& point, | 596 void GestureSequence::AppendClickGestureEvent(const GesturePoint& point, |
| 585 Gestures* gestures) { | 597 Gestures* gestures) { |
| 586 gfx::Rect er = point.enclosing_rectangle(); | 598 gfx::Rect er = point.enclosing_rectangle(); |
| 587 gfx::Point center = er.CenterPoint(); | 599 gfx::Point center = er.CenterPoint(); |
| 588 gestures->push_back(helper_->CreateGestureEvent( | 600 gestures->push_back(CreateGestureEvent( |
| 589 ui::ET_GESTURE_TAP, | 601 GestureEventDetails(ui::ET_GESTURE_TAP, er.width() / 2, er.height() / 2), |
| 590 center, | 602 center, |
| 591 flags_, | 603 flags_, |
| 592 base::Time::FromDoubleT(point.last_touch_time()), | 604 base::Time::FromDoubleT(point.last_touch_time()), |
| 593 er.width() / 2, | |
| 594 er.height() / 2, | |
| 595 1 << point.touch_id())); | 605 1 << point.touch_id())); |
| 596 } | 606 } |
| 597 | 607 |
| 598 void GestureSequence::AppendDoubleClickGestureEvent(const GesturePoint& point, | 608 void GestureSequence::AppendDoubleClickGestureEvent(const GesturePoint& point, |
| 599 Gestures* gestures) { | 609 Gestures* gestures) { |
| 600 gestures->push_back(helper_->CreateGestureEvent( | 610 gestures->push_back(CreateGestureEvent( |
| 601 ui::ET_GESTURE_DOUBLE_TAP, | 611 GestureEventDetails(ui::ET_GESTURE_DOUBLE_TAP, 0, 0), |
| 602 point.first_touch_position(), | 612 point.first_touch_position(), |
| 603 flags_, | 613 flags_, |
| 604 base::Time::FromDoubleT(point.last_touch_time()), | 614 base::Time::FromDoubleT(point.last_touch_time()), |
| 605 0.f, 0.f, 1 << point.touch_id())); | 615 1 << point.touch_id())); |
| 606 } | 616 } |
| 607 | 617 |
| 608 void GestureSequence::AppendScrollGestureBegin(const GesturePoint& point, | 618 void GestureSequence::AppendScrollGestureBegin(const GesturePoint& point, |
| 609 const gfx::Point& location, | 619 const gfx::Point& location, |
| 610 Gestures* gestures) { | 620 Gestures* gestures) { |
| 611 gestures->push_back(helper_->CreateGestureEvent( | 621 gestures->push_back(CreateGestureEvent( |
| 612 ui::ET_GESTURE_SCROLL_BEGIN, | 622 GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0), |
| 613 location, | 623 location, |
| 614 flags_, | 624 flags_, |
| 615 base::Time::FromDoubleT(point.last_touch_time()), | 625 base::Time::FromDoubleT(point.last_touch_time()), |
| 616 0.f, 0.f, 1 << point.touch_id())); | 626 1 << point.touch_id())); |
| 617 } | 627 } |
| 618 | 628 |
| 619 void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point, | 629 void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point, |
| 620 const gfx::Point& location, | 630 const gfx::Point& location, |
| 621 Gestures* gestures, | 631 Gestures* gestures, |
| 622 float x_velocity, | 632 float x_velocity, |
| 623 float y_velocity) { | 633 float y_velocity) { |
| 624 float railed_x_velocity = x_velocity; | 634 float railed_x_velocity = x_velocity; |
| 625 float railed_y_velocity = y_velocity; | 635 float railed_y_velocity = y_velocity; |
| 626 | 636 |
| 627 if (scroll_type_ == ST_HORIZONTAL) | 637 if (scroll_type_ == ST_HORIZONTAL) |
| 628 railed_y_velocity = 0; | 638 railed_y_velocity = 0; |
| 629 else if (scroll_type_ == ST_VERTICAL) | 639 else if (scroll_type_ == ST_VERTICAL) |
| 630 railed_x_velocity = 0; | 640 railed_x_velocity = 0; |
| 631 | 641 |
| 632 // TODO(rjkroege): It is conceivable that we could suppress sending the | 642 // TODO(rjkroege): It is conceivable that we could suppress sending the |
| 633 // GestureScrollEnd if it is immediately followed by a GestureFlingStart. | 643 // GestureScrollEnd if it is immediately followed by a GestureFlingStart. |
| 634 gestures->push_back(helper_->CreateGestureEvent( | 644 gestures->push_back(CreateGestureEvent( |
| 635 ui::ET_GESTURE_SCROLL_END, | 645 GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0), |
| 636 location, | 646 location, |
| 637 flags_, | 647 flags_, |
| 638 base::Time::FromDoubleT(point.last_touch_time()), | 648 base::Time::FromDoubleT(point.last_touch_time()), |
| 639 0., 0., 1 << point.touch_id())); | 649 1 << point.touch_id())); |
| 640 | 650 |
| 641 if (railed_x_velocity != 0 || railed_y_velocity != 0) { | 651 if (railed_x_velocity != 0 || railed_y_velocity != 0) { |
| 642 // TODO(sad|rjkroege): fling-curve is currently configured to work well with | 652 // TODO(sad|rjkroege): fling-curve is currently configured to work well with |
| 643 // touchpad scroll-events. This curve needs to be adjusted to work correctly | 653 // touchpad scroll-events. This curve needs to be adjusted to work correctly |
| 644 // with both touchpad and touchscreen. Until then, scale quadratically. | 654 // with both touchpad and touchscreen. Until then, scale quadratically. |
| 645 // http://crbug.com/120154 | 655 // http://crbug.com/120154 |
| 646 const float velocity_scaling = 1.f / 900.f; | 656 const float velocity_scaling = 1.f / 900.f; |
| 647 | 657 |
| 648 gestures->push_back(helper_->CreateGestureEvent( | 658 gestures->push_back(CreateGestureEvent( |
| 649 ui::ET_SCROLL_FLING_START, | 659 GestureEventDetails(ui::ET_SCROLL_FLING_START, |
| 660 velocity_scaling * railed_x_velocity * fabsf(railed_x_velocity), |
| 661 velocity_scaling * railed_y_velocity * fabsf(railed_y_velocity)), |
| 650 location, | 662 location, |
| 651 flags_, | 663 flags_, |
| 652 base::Time::FromDoubleT(point.last_touch_time()), | 664 base::Time::FromDoubleT(point.last_touch_time()), |
| 653 velocity_scaling * railed_x_velocity * fabsf(railed_x_velocity), | |
| 654 velocity_scaling * railed_y_velocity * fabsf(railed_y_velocity), | |
| 655 1 << point.touch_id())); | 665 1 << point.touch_id())); |
| 656 } | 666 } |
| 657 } | 667 } |
| 658 | 668 |
| 659 void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, | 669 void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, |
| 660 const gfx::Point& location, | 670 const gfx::Point& location, |
| 661 Gestures* gestures) { | 671 Gestures* gestures) { |
| 662 int dx = location.x() - bounding_box_last_center_.x(); | 672 int dx = location.x() - bounding_box_last_center_.x(); |
| 663 int dy = location.y() - bounding_box_last_center_.y(); | 673 int dy = location.y() - bounding_box_last_center_.y(); |
| 664 if (dx == 0 && dy == 0) | 674 if (dx == 0 && dy == 0) |
| 665 return; | 675 return; |
| 666 if (scroll_type_ == ST_HORIZONTAL) | 676 if (scroll_type_ == ST_HORIZONTAL) |
| 667 dy = 0; | 677 dy = 0; |
| 668 else if (scroll_type_ == ST_VERTICAL) | 678 else if (scroll_type_ == ST_VERTICAL) |
| 669 dx = 0; | 679 dx = 0; |
| 670 | 680 |
| 671 gestures->push_back(helper_->CreateGestureEvent( | 681 gestures->push_back(CreateGestureEvent( |
| 672 ui::ET_GESTURE_SCROLL_UPDATE, | 682 GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, dx, dy), |
| 673 location, | 683 location, |
| 674 flags_, | 684 flags_, |
| 675 base::Time::FromDoubleT(point.last_touch_time()), | 685 base::Time::FromDoubleT(point.last_touch_time()), |
| 676 dx, dy, ComputeTouchBitmask(points_))); | 686 ComputeTouchBitmask(points_))); |
| 677 } | 687 } |
| 678 | 688 |
| 679 void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1, | 689 void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1, |
| 680 const GesturePoint& p2, | 690 const GesturePoint& p2, |
| 681 Gestures* gestures) { | 691 Gestures* gestures) { |
| 682 gfx::Point center = bounding_box_.CenterPoint(); | 692 gfx::Point center = bounding_box_.CenterPoint(); |
| 683 gestures->push_back(helper_->CreateGestureEvent( | 693 gestures->push_back(CreateGestureEvent( |
| 684 ui::ET_GESTURE_PINCH_BEGIN, | 694 GestureEventDetails(ui::ET_GESTURE_PINCH_BEGIN, 0, 0), |
| 685 center, | 695 center, |
| 686 flags_, | 696 flags_, |
| 687 base::Time::FromDoubleT(p1.last_touch_time()), | 697 base::Time::FromDoubleT(p1.last_touch_time()), |
| 688 0.f, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); | 698 1 << p1.touch_id() | 1 << p2.touch_id())); |
| 689 } | 699 } |
| 690 | 700 |
| 691 void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1, | 701 void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1, |
| 692 const GesturePoint& p2, | 702 const GesturePoint& p2, |
| 693 float scale, | 703 float scale, |
| 694 Gestures* gestures) { | 704 Gestures* gestures) { |
| 695 gfx::Point center = bounding_box_.CenterPoint(); | 705 gfx::Point center = bounding_box_.CenterPoint(); |
| 696 gestures->push_back(helper_->CreateGestureEvent( | 706 gestures->push_back(CreateGestureEvent( |
| 697 ui::ET_GESTURE_PINCH_END, | 707 GestureEventDetails(ui::ET_GESTURE_PINCH_END, 0, 0), |
| 698 center, | 708 center, |
| 699 flags_, | 709 flags_, |
| 700 base::Time::FromDoubleT(p1.last_touch_time()), | 710 base::Time::FromDoubleT(p1.last_touch_time()), |
| 701 0.f, 0.f, | |
| 702 1 << p1.touch_id() | 1 << p2.touch_id())); | 711 1 << p1.touch_id() | 1 << p2.touch_id())); |
| 703 } | 712 } |
| 704 | 713 |
| 705 void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, | 714 void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, |
| 706 float scale, | 715 float scale, |
| 707 Gestures* gestures) { | 716 Gestures* gestures) { |
| 708 // TODO(sad): Compute rotation and include it in delta_y. | 717 // TODO(sad): Compute rotation and include it in delta_y. |
| 709 // http://crbug.com/113145 | 718 // http://crbug.com/113145 |
| 710 gestures->push_back(helper_->CreateGestureEvent( | 719 gestures->push_back(CreateGestureEvent( |
| 711 ui::ET_GESTURE_PINCH_UPDATE, | 720 GestureEventDetails(ui::ET_GESTURE_PINCH_UPDATE, scale, 0), |
| 712 bounding_box_.CenterPoint(), | 721 bounding_box_.CenterPoint(), |
| 713 flags_, | 722 flags_, |
| 714 base::Time::FromDoubleT(point.last_touch_time()), | 723 base::Time::FromDoubleT(point.last_touch_time()), |
| 715 scale, 0.f, | |
| 716 ComputeTouchBitmask(points_))); | 724 ComputeTouchBitmask(points_))); |
| 717 } | 725 } |
| 718 | 726 |
| 719 void GestureSequence::AppendSwipeGesture(const GesturePoint& point, | 727 void GestureSequence::AppendSwipeGesture(const GesturePoint& point, |
| 720 int swipe_x, | 728 int swipe_x, |
| 721 int swipe_y, | 729 int swipe_y, |
| 722 Gestures* gestures) { | 730 Gestures* gestures) { |
| 723 gestures->push_back(helper_->CreateGestureEvent( | 731 gestures->push_back(CreateGestureEvent( |
| 724 ui::ET_GESTURE_MULTIFINGER_SWIPE, | 732 GestureEventDetails(ui::ET_GESTURE_MULTIFINGER_SWIPE, swipe_x, swipe_y), |
| 725 bounding_box_.CenterPoint(), | 733 bounding_box_.CenterPoint(), |
| 726 flags_, | 734 flags_, |
| 727 base::Time::FromDoubleT(point.last_touch_time()), | 735 base::Time::FromDoubleT(point.last_touch_time()), |
| 728 swipe_x, swipe_y, ComputeTouchBitmask(points_))); | 736 ComputeTouchBitmask(points_))); |
| 729 } | 737 } |
| 730 | 738 |
| 731 void GestureSequence::AppendTwoFingerTapGestureEvent(Gestures* gestures) { | 739 void GestureSequence::AppendTwoFingerTapGestureEvent(Gestures* gestures) { |
| 732 const GesturePoint* point = GetPointByPointId(0); | 740 const GesturePoint* point = GetPointByPointId(0); |
| 733 gestures->push_back(helper_->CreateGestureEvent( | 741 gestures->push_back(CreateGestureEvent( |
| 734 ui::ET_GESTURE_TWO_FINGER_TAP, | 742 GestureEventDetails(ui::ET_GESTURE_TWO_FINGER_TAP, 0, 0), |
| 735 point->enclosing_rectangle().CenterPoint(), | 743 point->enclosing_rectangle().CenterPoint(), |
| 736 flags_, | 744 flags_, |
| 737 base::Time::FromDoubleT(point->last_touch_time()), | 745 base::Time::FromDoubleT(point->last_touch_time()), |
| 738 0.f, 0.f, 1 << point->touch_id())); | 746 1 << point->touch_id())); |
| 739 } | 747 } |
| 740 | 748 |
| 741 bool GestureSequence::Click(const TouchEvent& event, | 749 bool GestureSequence::Click(const TouchEvent& event, |
| 742 const GesturePoint& point, Gestures* gestures) { | 750 const GesturePoint& point, Gestures* gestures) { |
| 743 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); | 751 DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); |
| 744 if (point.IsInClickWindow(event)) { | 752 if (point.IsInClickWindow(event)) { |
| 745 AppendClickGestureEvent(point, gestures); | 753 AppendClickGestureEvent(point, gestures); |
| 746 if (point.IsInDoubleClickWindow(event)) | 754 if (point.IsInDoubleClickWindow(event)) |
| 747 AppendDoubleClickGestureEvent(point, gestures); | 755 AppendDoubleClickGestureEvent(point, gestures); |
| 748 return true; | 756 return true; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 base::TimeDelta time_delta = event.GetTimestamp() - second_touch_time_; | 845 base::TimeDelta time_delta = event.GetTimestamp() - second_touch_time_; |
| 838 base::TimeDelta max_delta = base::TimeDelta::FromMilliseconds(1000 * | 846 base::TimeDelta max_delta = base::TimeDelta::FromMilliseconds(1000 * |
| 839 ui::GestureConfiguration::max_touch_down_duration_in_seconds_for_click()); | 847 ui::GestureConfiguration::max_touch_down_duration_in_seconds_for_click()); |
| 840 if (time_delta < max_delta && point.IsInsideManhattanSquare(event)) | 848 if (time_delta < max_delta && point.IsInsideManhattanSquare(event)) |
| 841 AppendTwoFingerTapGestureEvent(gestures); | 849 AppendTwoFingerTapGestureEvent(gestures); |
| 842 return true; | 850 return true; |
| 843 } | 851 } |
| 844 | 852 |
| 845 void GestureSequence::AppendLongPressGestureEvent() { | 853 void GestureSequence::AppendLongPressGestureEvent() { |
| 846 const GesturePoint* point = GetPointByPointId(0); | 854 const GesturePoint* point = GetPointByPointId(0); |
| 847 scoped_ptr<GestureEvent> gesture(helper_->CreateGestureEvent( | 855 scoped_ptr<GestureEvent> gesture(CreateGestureEvent( |
| 848 ui::ET_GESTURE_LONG_PRESS, | 856 GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 0, 0), |
| 849 point->first_touch_position(), | 857 point->first_touch_position(), |
| 850 flags_, | 858 flags_, |
| 851 base::Time::FromDoubleT(point->last_touch_time()), | 859 base::Time::FromDoubleT(point->last_touch_time()), |
| 852 0.f, 0.f, 1 << point->touch_id())); | 860 1 << point->touch_id())); |
| 853 helper_->DispatchLongPressGestureEvent(gesture.get()); | 861 helper_->DispatchLongPressGestureEvent(gesture.get()); |
| 854 } | 862 } |
| 855 | 863 |
| 856 bool GestureSequence::ScrollEnd(const TouchEvent& event, | 864 bool GestureSequence::ScrollEnd(const TouchEvent& event, |
| 857 GesturePoint& point, Gestures* gestures) { | 865 GesturePoint& point, Gestures* gestures) { |
| 858 DCHECK(state_ == GS_SCROLL); | 866 DCHECK(state_ == GS_SCROLL); |
| 859 if (point.IsInFlickWindow(event)) { | 867 if (point.IsInFlickWindow(event)) { |
| 860 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, | 868 AppendScrollGestureEnd(point, point.last_touch_position(), gestures, |
| 861 point.XVelocity(), point.YVelocity()); | 869 point.XVelocity(), point.YVelocity()); |
| 862 } else { | 870 } else { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 return; | 1007 return; |
| 1000 | 1008 |
| 1001 // Since long press timer has been started, there should be a non-NULL point. | 1009 // Since long press timer has been started, there should be a non-NULL point. |
| 1002 const GesturePoint* point = GetPointByPointId(0); | 1010 const GesturePoint* point = GetPointByPointId(0); |
| 1003 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), | 1011 if (!ui::gestures::IsInsideManhattanSquare(point->first_touch_position(), |
| 1004 event.GetLocation())) | 1012 event.GetLocation())) |
| 1005 long_press_timer_->Stop(); | 1013 long_press_timer_->Stop(); |
| 1006 } | 1014 } |
| 1007 | 1015 |
| 1008 } // namespace ui | 1016 } // namespace ui |
| OLD | NEW |