summaryrefslogtreecommitdiff
path: root/core/java/android/widget/SelectionActionModeHelper.java
diff options
context:
space:
mode:
authorPetar Šegina <psegina@google.com>2017-09-11 18:03:14 +0100
committerPetar Šegina <psegina@google.com>2017-09-28 20:06:32 +0100
commit7c8196f1dc0bed235dd80a1078f873430b74f8fb (patch)
treed64b1b0afa439cbabf119d27f2eabb01a313ead9 /core/java/android/widget/SelectionActionModeHelper.java
parent0debe0b7f59696d034471ec29e0eae244ea50a96 (diff)
Invert the animation over RTL selections
When smart select is performed over right-to-left text (either standalone or mixed with left-to-right text), the animation should flow in from the opposite side than what it does over left-to-right text. Test: manual - verify smart select still works Test: manual - manually set the layout flags to RTL and verify the animation behaves as expected Test: bit FrameworksCoreTests:android.widget.SelectionActionModeHelperTest Change-Id: I2e7766e7dfe74e0861e91fc50b061da74432aee0
Diffstat (limited to 'core/java/android/widget/SelectionActionModeHelper.java')
-rw-r--r--core/java/android/widget/SelectionActionModeHelper.java61
1 files changed, 42 insertions, 19 deletions
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index c7f22e6e8465..952c59ad7b27 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -43,9 +43,11 @@ import com.android.internal.util.Preconditions;
import java.text.BreakIterator;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
@@ -232,7 +234,7 @@ public final class SelectionActionModeHelper {
return;
}
- final List<RectF> selectionRectangles =
+ final List<SmartSelectSprite.RectangleWithTextSelectionLayout> selectionRectangles =
convertSelectionToRectangles(layout, result.mStart, result.mEnd);
final PointF touchPoint = new PointF(
@@ -240,7 +242,8 @@ public final class SelectionActionModeHelper {
mEditor.getLastUpPositionY());
final PointF animationStartPoint =
- movePointInsideNearestRectangle(touchPoint, selectionRectangles);
+ movePointInsideNearestRectangle(touchPoint, selectionRectangles,
+ SmartSelectSprite.RectangleWithTextSelectionLayout::getRectangle);
mSmartSelectSprite.startAnimation(
animationStartPoint,
@@ -248,38 +251,57 @@ public final class SelectionActionModeHelper {
onAnimationEndCallback);
}
- private List<RectF> convertSelectionToRectangles(final Layout layout, final int start,
- final int end) {
- final List<RectF> result = new ArrayList<>();
- layout.getSelection(start, end, (left, top, right, bottom, textSelectionLayout) ->
- mergeRectangleIntoList(result, new RectF(left, top, right, bottom)));
+ private List<SmartSelectSprite.RectangleWithTextSelectionLayout> convertSelectionToRectangles(
+ final Layout layout, final int start, final int end) {
+ final List<SmartSelectSprite.RectangleWithTextSelectionLayout> result = new ArrayList<>();
+
+ final Layout.SelectionRectangleConsumer consumer =
+ (left, top, right, bottom, textSelectionLayout) -> mergeRectangleIntoList(
+ result,
+ new RectF(left, top, right, bottom),
+ SmartSelectSprite.RectangleWithTextSelectionLayout::getRectangle,
+ r -> new SmartSelectSprite.RectangleWithTextSelectionLayout(r,
+ textSelectionLayout)
+ );
+
+ layout.getSelection(start, end, consumer);
+
+ result.sort(Comparator.comparing(
+ SmartSelectSprite.RectangleWithTextSelectionLayout::getRectangle,
+ SmartSelectSprite.RECTANGLE_COMPARATOR));
- result.sort(SmartSelectSprite.RECTANGLE_COMPARATOR);
return result;
}
/**
- * Merges a {@link RectF} into an existing list of rectangles. While merging, this method
- * makes sure that:
+ * Merges a {@link RectF} into an existing list of any objects which contain a rectangle.
+ * While merging, this method makes sure that:
*
* <ol>
* <li>No rectangle is redundant (contained within a bigger rectangle)</li>
* <li>Rectangles of the same height and vertical position that intersect get merged</li>
* </ol>
*
- * @param list the list of rectangles to merge the new rectangle in
+ * @param list the list of rectangles (or other rectangle containers) to merge the new
+ * rectangle into
* @param candidate the {@link RectF} to merge into the list
+ * @param extractor a function that can extract a {@link RectF} from an element of the given
+ * list
+ * @param packer a function that can wrap the resulting {@link RectF} into an element that
+ * the list contains
* @hide
*/
@VisibleForTesting
- public static void mergeRectangleIntoList(List<RectF> list, RectF candidate) {
+ public static <T> void mergeRectangleIntoList(final List<T> list,
+ final RectF candidate, final Function<T, RectF> extractor,
+ final Function<RectF, T> packer) {
if (candidate.isEmpty()) {
return;
}
final int elementCount = list.size();
for (int index = 0; index < elementCount; ++index) {
- final RectF existingRectangle = list.get(index);
+ final RectF existingRectangle = extractor.apply(list.get(index));
if (existingRectangle.contains(candidate)) {
return;
}
@@ -302,26 +324,27 @@ public final class SelectionActionModeHelper {
}
for (int index = elementCount - 1; index >= 0; --index) {
- if (list.get(index).isEmpty()) {
+ final RectF rectangle = extractor.apply(list.get(index));
+ if (rectangle.isEmpty()) {
list.remove(index);
}
}
- list.add(candidate);
+ list.add(packer.apply(candidate));
}
/** @hide */
@VisibleForTesting
- public static PointF movePointInsideNearestRectangle(final PointF point,
- final List<RectF> rectangles) {
+ public static <T> PointF movePointInsideNearestRectangle(final PointF point,
+ final List<T> list, final Function<T, RectF> extractor) {
float bestX = -1;
float bestY = -1;
double bestDistance = Double.MAX_VALUE;
- final int elementCount = rectangles.size();
+ final int elementCount = list.size();
for (int index = 0; index < elementCount; ++index) {
- final RectF rectangle = rectangles.get(index);
+ final RectF rectangle = extractor.apply(list.get(index));
final float candidateY = rectangle.centerY();
final float candidateX;