OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 IntRect objectRect = pixelSnappedIntRect(elementRect()); | 647 IntRect objectRect = pixelSnappedIntRect(elementRect()); |
648 objectRect.setLocation(IntPoint()); | 648 objectRect.setLocation(IntPoint()); |
649 scrollToMakeVisibleWithSubFocus(objectRect); | 649 scrollToMakeVisibleWithSubFocus(objectRect); |
650 } | 650 } |
651 | 651 |
652 // This is a 1-dimensional scroll offset helper function that's applied | 652 // This is a 1-dimensional scroll offset helper function that's applied |
653 // separately in the horizontal and vertical directions, because the | 653 // separately in the horizontal and vertical directions, because the |
654 // logic is the same. The goal is to compute the best scroll offset | 654 // logic is the same. The goal is to compute the best scroll offset |
655 // in order to make an object visible within a viewport. | 655 // in order to make an object visible within a viewport. |
656 // | 656 // |
| 657 // If the object is already fully visible, returns the same scroll |
| 658 // offset. |
| 659 // |
657 // In case the whole object cannot fit, you can specify a | 660 // In case the whole object cannot fit, you can specify a |
658 // subfocus - a smaller region within the object that should | 661 // subfocus - a smaller region within the object that should |
659 // be prioritized. If the whole object can fit, the subfocus is | 662 // be prioritized. If the whole object can fit, the subfocus is |
660 // ignored. | 663 // ignored. |
661 // | 664 // |
662 // Example: the viewport is scrolled to the right just enough | 665 // If possible, the object and subfocus are centered within the |
663 // that the object is in view. | 666 // viewport. |
| 667 // |
| 668 // Example 1: the object is already visible, so nothing happens. |
| 669 // +----------Viewport---------+ |
| 670 // +---Object---+ |
| 671 // +--SubFocus--+ |
| 672 // |
| 673 // Example 2: the object is not fully visible, so it's centered |
| 674 // within the viewport. |
664 // Before: | 675 // Before: |
665 // +----------Viewport---------+ | 676 // +----------Viewport---------+ |
666 // +---Object---+ | 677 // +---Object---+ |
667 // +--SubFocus--+ | 678 // +--SubFocus--+ |
668 // | 679 // |
669 // After: | 680 // After: |
670 // +----------Viewport---------+ | 681 // +----------Viewport---------+ |
671 // +---Object---+ | 682 // +---Object---+ |
672 // +--SubFocus--+ | 683 // +--SubFocus--+ |
673 // | 684 // |
| 685 // Example 3: the object is larger than the viewport, so the |
| 686 // viewport moves to show as much of the object as possible, |
| 687 // while also trying to center the subfocus. |
| 688 // Before: |
| 689 // +----------Viewport---------+ |
| 690 // +---------------Object--------------+ |
| 691 // +-SubFocus-+ |
| 692 // |
| 693 // After: |
| 694 // +----------Viewport---------+ |
| 695 // +---------------Object--------------+ |
| 696 // +-SubFocus-+ |
| 697 // |
674 // When constraints cannot be fully satisfied, the min | 698 // When constraints cannot be fully satisfied, the min |
675 // (left/top) position takes precedence over the max (right/bottom). | 699 // (left/top) position takes precedence over the max (right/bottom). |
676 // | 700 // |
677 // Note that the return value represents the ideal new scroll offset. | 701 // Note that the return value represents the ideal new scroll offset. |
678 // This may be out of range - the calling function should clip this | 702 // This may be out of range - the calling function should clip this |
679 // to the available range. | 703 // to the available range. |
680 static int computeBestScrollOffset(int currentScrollOffset, int subfocusMin, int
subfocusMax, int objectMin, int objectMax, int viewportMin, int viewportMax) | 704 static int computeBestScrollOffset(int currentScrollOffset, int subfocusMin, int
subfocusMax, int objectMin, int objectMax, int viewportMin, int viewportMax) |
681 { | 705 { |
682 int viewportSize = viewportMax - viewportMin; | 706 int viewportSize = viewportMax - viewportMin; |
683 | 707 |
684 // If the focus size is larger than the viewport size, shrink it in the | 708 // If the object size is larger than the viewport size, consider |
685 // direction of subfocus. | 709 // only a portion that's as large as the viewport, centering on |
| 710 // the subfocus as much as possible. |
686 if (objectMax - objectMin > viewportSize) { | 711 if (objectMax - objectMin > viewportSize) { |
687 // Subfocus must be within focus: | 712 // Subfocus must be within focus: |
688 subfocusMin = std::max(subfocusMin, objectMin); | 713 subfocusMin = std::max(subfocusMin, objectMin); |
689 subfocusMax = std::min(subfocusMax, objectMax); | 714 subfocusMax = std::min(subfocusMax, objectMax); |
690 | 715 |
691 // Subfocus must be no larger than the viewport size; favor top/left. | 716 // Subfocus must be no larger than the viewport size; favor top/left. |
692 if (subfocusMax - subfocusMin > viewportSize) | 717 if (subfocusMax - subfocusMin > viewportSize) |
693 subfocusMax = subfocusMin + viewportSize; | 718 subfocusMax = subfocusMin + viewportSize; |
694 | 719 |
695 if (subfocusMin + viewportSize > objectMax) { | 720 // Compute the size of an object centered on the subfocus, the size of t
he viewport. |
696 objectMin = objectMax - viewportSize; | 721 int centeredObjectMin = (subfocusMin + subfocusMax - viewportSize) / 2; |
697 } else { | 722 int centeredObjectMax = centeredObjectMin + viewportSize; |
698 objectMin = subfocusMin; | 723 |
699 objectMax = subfocusMin + viewportSize; | 724 objectMin = std::max(objectMin, centeredObjectMin); |
700 } | 725 objectMax = std::min(objectMax, centeredObjectMax); |
701 } | 726 } |
702 | 727 |
703 // Exit now if the focus is already within the viewport. | 728 // Exit now if the focus is already within the viewport. |
704 if (objectMin - currentScrollOffset >= viewportMin | 729 if (objectMin - currentScrollOffset >= viewportMin |
705 && objectMax - currentScrollOffset <= viewportMax) | 730 && objectMax - currentScrollOffset <= viewportMax) |
706 return currentScrollOffset; | 731 return currentScrollOffset; |
707 | 732 |
708 // Scroll left if we're too far to the right. | 733 // Center the object in the viewport. |
709 if (objectMax - currentScrollOffset > viewportMax) | 734 return (objectMin + objectMax - viewportMin - viewportMax) / 2; |
710 return objectMax - viewportMax; | |
711 | |
712 // Scroll right if we're too far to the left. | |
713 if (objectMin - currentScrollOffset < viewportMin) | |
714 return objectMin - viewportMin; | |
715 | |
716 ASSERT_NOT_REACHED(); | |
717 | |
718 // This shouldn't happen. | |
719 return currentScrollOffset; | |
720 } | 735 } |
721 | 736 |
722 void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const | 737 void AXObject::scrollToMakeVisibleWithSubFocus(const IntRect& subfocus) const |
723 { | 738 { |
724 // Search up the parent chain until we find the first one that's scrollable. | 739 // Search up the parent chain until we find the first one that's scrollable. |
725 AXObject* scrollParent = parentObject(); | 740 AXObject* scrollParent = parentObject(); |
726 ScrollableArea* scrollableArea = 0; | 741 ScrollableArea* scrollableArea = 0; |
727 while (scrollParent) { | 742 while (scrollParent) { |
728 scrollableArea = scrollParent->getScrollableAreaIfScrollable(); | 743 scrollableArea = scrollParent->getScrollableAreaIfScrollable(); |
729 if (scrollableArea) | 744 if (scrollableArea) |
(...skipping 13 matching lines...) Expand all Loading... |
743 objectRect.x(), objectRect.maxX(), | 758 objectRect.x(), objectRect.maxX(), |
744 0, scrollVisibleRect.width()); | 759 0, scrollVisibleRect.width()); |
745 int desiredY = computeBestScrollOffset( | 760 int desiredY = computeBestScrollOffset( |
746 scrollPosition.y(), | 761 scrollPosition.y(), |
747 objectRect.y() + subfocus.y(), objectRect.y() + subfocus.maxY(), | 762 objectRect.y() + subfocus.y(), objectRect.y() + subfocus.maxY(), |
748 objectRect.y(), objectRect.maxY(), | 763 objectRect.y(), objectRect.maxY(), |
749 0, scrollVisibleRect.height()); | 764 0, scrollVisibleRect.height()); |
750 | 765 |
751 scrollParent->scrollTo(IntPoint(desiredX, desiredY)); | 766 scrollParent->scrollTo(IntPoint(desiredX, desiredY)); |
752 | 767 |
| 768 // Convert the subfocus into the coordinates of the scroll parent. |
| 769 IntRect newSubfocus = subfocus; |
| 770 IntRect newElementRect = pixelSnappedIntRect(elementRect()); |
| 771 IntRect scrollParentRect = pixelSnappedIntRect(scrollParent->elementRect()); |
| 772 newSubfocus.move(newElementRect.x(), newElementRect.y()); |
| 773 newSubfocus.move(-scrollParentRect.x(), -scrollParentRect.y()); |
| 774 |
753 // Recursively make sure the scroll parent itself is visible. | 775 // Recursively make sure the scroll parent itself is visible. |
754 if (scrollParent->parentObject()) | 776 if (scrollParent->parentObject()) |
755 scrollParent->scrollToMakeVisible(); | 777 scrollParent->scrollToMakeVisibleWithSubFocus(newSubfocus); |
756 } | 778 } |
757 | 779 |
758 void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const | 780 void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const |
759 { | 781 { |
760 // Search up the parent chain and create a vector of all scrollable parent o
bjects | 782 // Search up the parent chain and create a vector of all scrollable parent o
bjects |
761 // and ending with this object itself. | 783 // and ending with this object itself. |
762 Vector<const AXObject*> objects; | 784 Vector<const AXObject*> objects; |
763 AXObject* parentObject; | 785 AXObject* parentObject; |
764 for (parentObject = this->parentObject(); parentObject; parentObject = paren
tObject->parentObject()) { | 786 for (parentObject = this->parentObject(); parentObject; parentObject = paren
tObject->parentObject()) { |
765 if (parentObject->getScrollableAreaIfScrollable()) | 787 if (parentObject->getScrollableAreaIfScrollable()) |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 return ToggleButtonRole; | 918 return ToggleButtonRole; |
897 if (ariaHasPopup()) | 919 if (ariaHasPopup()) |
898 return PopUpButtonRole; | 920 return PopUpButtonRole; |
899 // We don't contemplate RadioButtonRole, as it depends on the input | 921 // We don't contemplate RadioButtonRole, as it depends on the input |
900 // type. | 922 // type. |
901 | 923 |
902 return ButtonRole; | 924 return ButtonRole; |
903 } | 925 } |
904 | 926 |
905 } // namespace blink | 927 } // namespace blink |
OLD | NEW |