refactor for more symmetry in MoveUp and MoveDown
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/boxes/FakeContentBox.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/boxes/FakeContentBox.java
index e7db0cb..c84f409 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/boxes/FakeContentBox.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/boxes/FakeContentBox.java
@@ -93,6 +93,14 @@
return getEndOffset() - getStartOffset() <= 1;
}
+ public boolean isAtStart(final int offset) {
+ return getStartOffset() == offset;
+ }
+
+ public boolean isAtEnd(final int offset) {
+ return getEndOffset() == offset;
+ }
+
@Override
public Rectangle getPositionArea(final Graphics graphics, final int offset) {
return area;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IContentBox.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IContentBox.java
index eaf0b51..71af707 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IContentBox.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/IContentBox.java
@@ -24,6 +24,10 @@
boolean isEmpty();
+ boolean isAtStart(int offset);
+
+ boolean isAtEnd(int offset);
+
Rectangle getPositionArea(Graphics graphics, int offset);
int getOffsetForCoordinates(Graphics graphics, int x, int y);
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveDown.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveDown.java
index 30bb7d7..6d55ca4 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveDown.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveDown.java
@@ -21,6 +21,11 @@
public class MoveDown implements ICursorMove {
@Override
+ public boolean preferX() {
+ return false;
+ }
+
+ @Override
public int calculateNewOffset(final Graphics graphics, final ContentMap contentMap, final int currentOffset, final IContentBox currentBox, final Rectangle hotArea, final int preferredX) {
if (isAtStartOfEmptyBox(currentOffset, currentBox)) {
return currentBox.getEndOffset();
@@ -29,30 +34,15 @@
return getFirstChild(currentBox).getStartOffset();
}
- final int x = preferredX;
- final int y = hotArea.getY() + hotArea.getHeight() - 1;
- final IContentBox box = findClosestBoxBelow(contentMap, currentBox, x, y);
- if (box.isEmpty()) {
- return box.getStartOffset();
- }
- return box.getOffsetForCoordinates(graphics, x - box.getAbsoluteLeft(), y - box.getAbsoluteTop());
- }
-
- @Override
- public boolean preferX() {
- return false;
+ return findOffsetInNextBoxBelow(graphics, contentMap, currentBox, hotArea, preferredX);
}
private static boolean isAtStartOfEmptyBox(final int offset, final IContentBox box) {
- return isAtStartOfBox(offset, box) && box.isEmpty();
+ return box.isAtStart(offset) && box.isEmpty();
}
private static boolean isAtStartOfBoxWithChildren(final int offset, final IContentBox box) {
- return isAtStartOfBox(offset, box) && canHaveChildren(box);
- }
-
- private static boolean isAtStartOfBox(final int offset, final IContentBox box) {
- return offset == box.getStartOffset();
+ return box.isAtStart(offset) && canHaveChildren(box);
}
private static boolean canHaveChildren(final IContentBox box) {
@@ -73,6 +63,18 @@
});
}
+ private static IContentBox getParent(final IContentBox childBox) {
+ return childBox.accept(new ParentTraversal<IContentBox>() {
+ @Override
+ public IContentBox visit(final NodeReference box) {
+ if (box == childBox) {
+ return super.visit(box);
+ }
+ return box;
+ }
+ });
+ }
+
private static IContentBox getFirstChild(final IContentBox parent) {
return parent.accept(new DepthFirstTraversal<IContentBox>() {
@Override
@@ -90,7 +92,17 @@
});
}
- private static IContentBox findClosestBoxBelow(final ContentMap contentMap, final IContentBox currentBox, final int x, final int y) {
+ private int findOffsetInNextBoxBelow(final Graphics graphics, final ContentMap contentMap, final IContentBox currentBox, final Rectangle hotArea, final int preferredX) {
+ final int x = preferredX;
+ final int y = hotArea.getY() + hotArea.getHeight() - 1;
+ final IContentBox box = findNextBoxBelow(contentMap, currentBox, x, y);
+ if (box.isEmpty()) {
+ return box.getStartOffset();
+ }
+ return box.getOffsetForCoordinates(graphics, x - box.getAbsoluteLeft(), y - box.getAbsoluteTop());
+ }
+
+ private static IContentBox findNextBoxBelow(final ContentMap contentMap, final IContentBox currentBox, final int x, final int y) {
final Environment environment = contentMap.findEnvironmentForCoordinates(x, y, true);
final Neighbour neighbourBelow = environment.neighbours.getBelow();
if (neighbourBelow.box == null) {
@@ -116,19 +128,16 @@
}
});
- return currentBox.accept(new BaseBoxVisitorWithResult<IContentBox>() {
+ return currentBox.accept(new ParentTraversal<IContentBox>() {
@Override
public IContentBox visit(final NodeReference box) {
- if (box == getParent(boxBelow)) {
- return boxBelow;
+ if (box == currentBox) {
+ return super.visit(box);
}
- if (!isInLastLine(box, boxBelow)) {
- return boxBelow;
+ if (containerBottomCloserThanNeighbourBelow(box, neighbourBelow, y)) {
+ return box;
}
- if (boxBelow.isRightOf(x)) {
- return boxBelow;
- }
- return getParent(box);
+ return boxBelow;
}
@Override
@@ -138,7 +147,6 @@
}
return getParent(box);
}
-
});
}
@@ -162,20 +170,8 @@
});
}
- private static boolean isInLastLine(final IContentBox box, final IContentBox boxBelow) {
- return !(getParent(box) == getParent(boxBelow));
+ private static boolean containerBottomCloserThanNeighbourBelow(final IContentBox box, final Neighbour neighbourBelow, final int y) {
+ final int distanceToContainerBottom = box.getAbsoluteTop() + box.getHeight() - y;
+ return distanceToContainerBottom <= neighbourBelow.distance;
}
-
- private static IContentBox getParent(final IContentBox childBox) {
- return childBox.accept(new ParentTraversal<IContentBox>() {
- @Override
- public IContentBox visit(final NodeReference box) {
- if (box == childBox) {
- return super.visit(box);
- }
- return box;
- }
- });
- }
-
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveUp.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveUp.java
index 9358eac..7ffe0b5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveUp.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/MoveUp.java
@@ -21,6 +21,11 @@
public class MoveUp implements ICursorMove {
@Override
+ public boolean preferX() {
+ return false;
+ }
+
+ @Override
public int calculateNewOffset(final Graphics graphics, final ContentMap contentMap, final int currentOffset, final IContentBox currentBox, final Rectangle hotArea, final int preferredX) {
if (isAtEndOfEmptyBox(currentOffset, currentBox)) {
return currentBox.getStartOffset();
@@ -29,27 +34,15 @@
return getLastChild(currentBox).getEndOffset();
}
- final int x = preferredX;
- final int y = hotArea.getY();
- final IContentBox box = findClosestBoxAbove(contentMap, currentBox, x, y);
- return box.getOffsetForCoordinates(graphics, x - box.getAbsoluteLeft(), y - box.getAbsoluteTop());
- }
-
- @Override
- public boolean preferX() {
- return false;
+ return findOffsetInNextBoxAbove(graphics, contentMap, currentBox, hotArea, preferredX);
}
private static boolean isAtEndOfEmptyBox(final int offset, final IContentBox box) {
- return isAtEndOfBox(offset, box) && box.isEmpty();
+ return box.isAtEnd(offset) && box.isEmpty();
}
private static boolean isAtEndOfBoxWithChildren(final int offset, final IContentBox box) {
- return isAtEndOfBox(offset, box) && canHaveChildren(box);
- }
-
- private static boolean isAtEndOfBox(final int offset, final IContentBox box) {
- return offset == box.getEndOffset();
+ return box.isAtEnd(offset) && canHaveChildren(box);
}
private static boolean canHaveChildren(final IContentBox box) {
@@ -70,6 +63,18 @@
});
}
+ private static IContentBox getParent(final IContentBox childBox) {
+ return childBox.accept(new ParentTraversal<IContentBox>() {
+ @Override
+ public IContentBox visit(final NodeReference box) {
+ if (box == childBox) {
+ return super.visit(box);
+ }
+ return box;
+ }
+ });
+ }
+
private static IContentBox getLastChild(final IContentBox parent) {
return parent.accept(new DepthFirstTraversal<IContentBox>() {
private IContentBox lastChild;
@@ -92,13 +97,16 @@
});
}
- private static IContentBox findClosestBoxAbove(final ContentMap contentMap, final IContentBox currentBox, final int x, final int y) {
+ private int findOffsetInNextBoxAbove(final Graphics graphics, final ContentMap contentMap, final IContentBox currentBox, final Rectangle hotArea, final int preferredX) {
+ final int x = preferredX;
+ final int y = hotArea.getY();
+ final IContentBox box = findNextBoxAbove(contentMap, currentBox, x, y);
+ return box.getOffsetForCoordinates(graphics, x - box.getAbsoluteLeft(), y - box.getAbsoluteTop());
+ }
+
+ private static IContentBox findNextBoxAbove(final ContentMap contentMap, final IContentBox currentBox, final int x, final int y) {
final Environment environment = contentMap.findEnvironmentForCoordinates(x, y, true);
final Neighbour neighbourAbove = environment.neighbours.getAbove();
- if (environment.deepestContainer == null) {
- return currentBox;
- }
-
if (neighbourAbove.box == null) {
final IContentBox parent = getParent(currentBox);
if (parent == null) {
@@ -112,10 +120,7 @@
public IContentBox visit(final NodeReference box) {
if (box.canContainText()) {
final IContentBox lastChild = deepestLastChild(box);
- if (lastChild.isRightOf(x)) {
- return lastChild;
- }
- if (lastChild.containsX(x)) {
+ if (!lastChild.isLeftOf(x)) {
return lastChild;
}
}
@@ -134,8 +139,7 @@
if (box == currentBox) {
return super.visit(box);
}
- final int distanceToContainerTop = y - box.getAbsoluteTop();
- if (distanceToContainerTop <= neighbourAbove.distance) {
+ if (containerTopCloserThanNeighbourAbove(box, neighbourAbove, y)) {
return box;
}
return boxAbove;
@@ -143,18 +147,6 @@
});
}
- private static IContentBox getParent(final IContentBox childBox) {
- return childBox.accept(new ParentTraversal<IContentBox>() {
- @Override
- public IContentBox visit(final NodeReference box) {
- if (box == childBox) {
- return super.visit(box);
- }
- return box;
- }
- });
- }
-
private static IContentBox deepestLastChild(final IContentBox parentBox) {
return parentBox.accept(new DepthFirstTraversal<IContentBox>() {
private IContentBox lastChild;
@@ -178,4 +170,8 @@
});
}
+ private static boolean containerTopCloserThanNeighbourAbove(final IContentBox box, final Neighbour neighbourAbove, final int y) {
+ final int distanceToContainerTop = y - box.getAbsoluteTop();
+ return distanceToContainerTop <= neighbourAbove.distance;
+ }
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/NodeReference.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/NodeReference.java
index fad1e40..4b446fa 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/NodeReference.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/NodeReference.java
@@ -185,14 +185,14 @@
return getEndOffset() - getStartOffset() <= 1;
}
- public boolean isAtEnd(final int offset) {
- return getEndOffset() == offset;
- }
-
public boolean isAtStart(final int offset) {
return getStartOffset() == offset;
}
+ public boolean isAtEnd(final int offset) {
+ return getEndOffset() == offset;
+ }
+
@Override
public String toString() {
String result = "NodeReference{ ";
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
index 225d48d..898aaf2 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
@@ -259,6 +259,14 @@
return getEndOffset() - getStartOffset() <= 1;
}
+ public boolean isAtStart(final int offset) {
+ return getStartOffset() == offset;
+ }
+
+ public boolean isAtEnd(final int offset) {
+ return getEndOffset() == offset;
+ }
+
@Override
public Rectangle getPositionArea(final Graphics graphics, final int offset) {
if (startPosition.getOffset() > offset || endPosition.getOffset() < offset) {