modules/graphics/src/main/java/com/sun/javafx/scene/traversal/Hueristic2D.java

Print this page

        

*** 77,104 **** else { newNode = traversalNodeStack.pop(); } } Bounds currentB = node.localToScene(node.getLayoutBounds()); - if (cacheStartTraversalNode != null) { Bounds cachedB = cacheStartTraversalNode.localToScene(cacheStartTraversalNode.getLayoutBounds()); switch (dir) { case UP: case DOWN: ! newNode = getNearestNodeUpOrDown(currentB, cachedB, engine, node, newNode, dir); break; case LEFT: case RIGHT: ! newNode = getNearestNodeLeftOrRight(currentB, cachedB, engine, node, newNode, dir); break; default: break; } } } if (focusLogger.isLoggable(Level.FINER)) { if (newNode != null) { focusLogger.finer("new focus owner : "+newNode+", bounds : "+engine.getBounds(newNode)); } --- 77,105 ---- else { newNode = traversalNodeStack.pop(); } } + if (newNode == null) { Bounds currentB = node.localToScene(node.getLayoutBounds()); if (cacheStartTraversalNode != null) { Bounds cachedB = cacheStartTraversalNode.localToScene(cacheStartTraversalNode.getLayoutBounds()); switch (dir) { case UP: case DOWN: ! newNode = getNearestNodeUpOrDown(currentB, cachedB, engine, node, dir); break; case LEFT: case RIGHT: ! newNode = getNearestNodeLeftOrRight(currentB, cachedB, engine, node, dir); break; default: break; } } } + } if (focusLogger.isLoggable(Level.FINER)) { if (newNode != null) { focusLogger.finer("new focus owner : "+newNode+", bounds : "+engine.getBounds(newNode)); }
*** 445,466 **** public Double apply(Bounds t) { return t.getMaxY(); } }; ! protected Node getNearestNodeUpOrDown(Bounds currentB, Bounds originB, TraversalEngine engine, Node node, Node reversingNode, Direction dir) { List<Node> nodes = engine.getAllTargetNodes(); Function<Bounds, Double> ySideInDirection = dir == DOWN ? BOUNDS_BOTTOM_SIDE : BOUNDS_TOP_SIDE; Function<Bounds, Double> ySideInOpositeDirection = dir == DOWN ? BOUNDS_TOP_SIDE : BOUNDS_BOTTOM_SIDE; Bounds biasedB = new BoundingBox(originB.getMinX(), currentB.getMinY(), originB.getWidth(), currentB.getHeight()); ! Point2D currentMid2D = new Point2D(currentB.getMinX()+(currentB.getWidth()/2), currentB.getMinY()); ! Point2D currenLeftCorner2D = new Point2D(currentB.getMinX(),ySideInDirection.apply(currentB)); Point2D currentRightCorner2D = new Point2D(currentB.getMaxX(), ySideInDirection.apply(currentB)); Point2D originLeftCorner2D = new Point2D(originB.getMinX(), ySideInDirection.apply(originB)); TargetNode targetNode = new TargetNode(); TargetNode nearestNodeCurrentSimple2D = null; --- 446,470 ---- public Double apply(Bounds t) { return t.getMaxY(); } }; ! protected Node getNearestNodeUpOrDown(Bounds currentB, Bounds originB, TraversalEngine engine, Node node, Direction dir) { List<Node> nodes = engine.getAllTargetNodes(); Function<Bounds, Double> ySideInDirection = dir == DOWN ? BOUNDS_BOTTOM_SIDE : BOUNDS_TOP_SIDE; Function<Bounds, Double> ySideInOpositeDirection = dir == DOWN ? BOUNDS_TOP_SIDE : BOUNDS_BOTTOM_SIDE; Bounds biasedB = new BoundingBox(originB.getMinX(), currentB.getMinY(), originB.getWidth(), currentB.getHeight()); ! Point2D currentMid2D = new Point2D(currentB.getMinX()+(currentB.getWidth()/2), ySideInDirection.apply(currentB)); ! Point2D biasedMid2D = new Point2D(originB.getMinX()+(originB.getWidth()/2), ySideInDirection.apply(currentB)); ! Point2D currentLeftCorner2D = new Point2D(currentB.getMinX(),ySideInDirection.apply(currentB)); ! Point2D biasedLeftCorner2D = new Point2D(originB.getMinX(),ySideInDirection.apply(currentB)); Point2D currentRightCorner2D = new Point2D(currentB.getMaxX(), ySideInDirection.apply(currentB)); + Point2D biasedRightCorner2D = new Point2D(originB.getMaxX(), ySideInDirection.apply(currentB)); Point2D originLeftCorner2D = new Point2D(originB.getMinX(), ySideInDirection.apply(originB)); TargetNode targetNode = new TargetNode(); TargetNode nearestNodeCurrentSimple2D = null;
*** 469,558 **** TargetNode nearestNodeOnOriginX = null; TargetNode nearestNodeOnCurrentX = null; TargetNode nearestNodeLeft = null; TargetNode nearestNodeAnythingAnywhere = null; - if (nodes.size() > 0) { - /* - ** we've just changed direction, and have a node on stack. - ** there is a strong preference for this node, just make sure - ** it's not a bad choice, as sometimes we got here as a last-chance - */ - if (reversingNode != null) { - return reversingNode; - } - for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) { final Node n = nodes.get(nodeIndex); Bounds targetBounds = n.localToScene(n.getLayoutBounds()); /* ** check that the target node starts after we ** and the target node ends after we end */ ! if (dir == UP ? (currentB.getMinY() > targetBounds.getMaxY()) : ! currentB.getMaxY() < targetBounds.getMinY()) { targetNode.node = n; targetNode.bounds = targetBounds; /* ! ** closest biased : simple 2d */ ! double outdB = outDistance(dir, biasedB, targetBounds); if (isOnAxis(dir, biasedB, targetBounds)) { targetNode.biased2DMetric = outdB + centerSideDistance(dir, biasedB, targetBounds) / 100; ! } ! else { final double cosd = cornerSideDistance(dir, biasedB, targetBounds); ! targetNode.biased2DMetric = 100000 + outdB*outdB + 9*cosd*cosd; } /* ! ** closest current : simple 2d */ ! double outdC = outDistance(dir, currentB, targetBounds); if (isOnAxis(dir, currentB, targetBounds)) { targetNode.current2DMetric = outdC + centerSideDistance(dir, currentB, targetBounds) / 100; ! } ! else { final double cosd = cornerSideDistance(dir, currentB, targetBounds); ! targetNode.current2DMetric = 100000 + outdC*outdC + 9*cosd*cosd; } ! targetNode.leftCornerDistance = currenLeftCorner2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! targetNode.midDistance = currentMid2D.distance(targetBounds.getMinX()+(originB.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! targetNode.rightCornerDistance = currentRightCorner2D.distance(originB.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! double currentTopLeftToTargetMidDistance = currenLeftCorner2D.distance(targetBounds.getMinX()+(targetBounds.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! double currentTopLeftToTargetBottomRightDistance = currenLeftCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentTopRightToTargetBottomLeftDistance = currentRightCorner2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentTopRightToTargetMidDistance = currentRightCorner2D.distance(targetBounds.getMinX()+(targetBounds.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! double currentTopRightToTargetBottomRightDistance = currentRightCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetBottomLeftDistance = currentMid2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetMidDistance = currentMid2D.distance(targetBounds.getMinX()+(targetBounds.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetBottomRightDistance = currentMid2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! double biasTopLeftToTargetMidDistance = currenLeftCorner2D.distance(targetBounds.getMinX()+(originB.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! double biasTopLeftToTargetBottomRightDistance = currenLeftCorner2D.distance(originB.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double biasTopRightToTargetMidDistance = currentRightCorner2D.distance(targetBounds.getMinX()+(originB.getWidth()/2), ySideInOpositeDirection.apply(targetBounds)); ! double biasMidToTargetBottomRightDistance = currentMid2D.distance(originB.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! targetNode.averageDistance = ! (targetNode.leftCornerDistance+biasTopLeftToTargetMidDistance+biasTopLeftToTargetBottomRightDistance+ ! currentTopRightToTargetBottomLeftDistance+targetNode.rightCornerDistance+biasTopRightToTargetMidDistance+targetNode.midDistance)/7; ! ! targetNode.biasShortestDistance = ! findMin(targetNode.leftCornerDistance, biasTopLeftToTargetMidDistance, biasTopLeftToTargetBottomRightDistance, ! currentTopRightToTargetBottomLeftDistance, biasTopRightToTargetMidDistance, targetNode.rightCornerDistance, ! currentMidToTargetBottomLeftDistance, targetNode.midDistance, biasMidToTargetBottomRightDistance); ! ! targetNode.shortestDistance = ! findMin(targetNode.leftCornerDistance, currentTopLeftToTargetMidDistance, currentTopLeftToTargetBottomRightDistance, ! currentTopRightToTargetBottomLeftDistance, currentTopRightToTargetMidDistance, currentTopRightToTargetBottomRightDistance, ! currentMidToTargetBottomLeftDistance, currentMidToTargetMidDistance, currentMidToTargetBottomRightDistance); /* ** closest biased : simple 2d */ if (outdB >= 0.0) { --- 473,552 ---- TargetNode nearestNodeOnOriginX = null; TargetNode nearestNodeOnCurrentX = null; TargetNode nearestNodeLeft = null; TargetNode nearestNodeAnythingAnywhere = null; for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) { final Node n = nodes.get(nodeIndex); Bounds targetBounds = n.localToScene(n.getLayoutBounds()); /* ** check that the target node starts after we ** and the target node ends after we end */ ! if (dir == UP ? (currentB.getMinY() > targetBounds.getMaxY()) ! : currentB.getMaxY() < targetBounds.getMinY()) { targetNode.node = n; targetNode.bounds = targetBounds; /* ! * closest biased : simple 2d ! * Negative means the Node is on the same Y axis. This will result in outdB == 0, making this a preferred Node. */ ! double outdB = Math.max(0, outDistance(dir, biasedB, targetBounds)); if (isOnAxis(dir, biasedB, targetBounds)) { targetNode.biased2DMetric = outdB + centerSideDistance(dir, biasedB, targetBounds) / 100; ! } else { final double cosd = cornerSideDistance(dir, biasedB, targetBounds); ! targetNode.biased2DMetric = 100000 + outdB * outdB + 9 * cosd * cosd; } /* ! * closest current : simple 2d ! * Negative means the Node is on the same Y axis. This will result in outdB == 0, making this a preferred Node. */ ! double outdC = Math.max(0, outDistance(dir, currentB, targetBounds)); if (isOnAxis(dir, currentB, targetBounds)) { targetNode.current2DMetric = outdC + centerSideDistance(dir, currentB, targetBounds) / 100; ! } else { final double cosd = cornerSideDistance(dir, currentB, targetBounds); ! targetNode.current2DMetric = 100000 + outdC * outdC + 9 * cosd * cosd; } ! targetNode.leftCornerDistance = currentLeftCorner2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! targetNode.rightCornerDistance = currentRightCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! double midDistance = currentMid2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double currentLeftToTargetMidDistance = currentLeftCorner2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double currentLeftToTargetRightDistance = currentLeftCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentRightToTargetLeftDistance = currentRightCorner2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentRightToTargetMidDistance = currentRightCorner2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double currentRightToTargetRightDistance = currentRightCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetLeftDistance = currentMid2D.distance(targetBounds.getMinX(), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetMidDistance = currentMid2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double currentMidToTargetRightDistance = currentMid2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! double biasLeftToTargetMidDistance = biasedLeftCorner2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double biasLeftToTargetRightDistance = biasedLeftCorner2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! double biasRightToTargetMidDistance = biasedRightCorner2D.distance(targetBounds.getMinX() + (targetBounds.getWidth() / 2), ySideInOpositeDirection.apply(targetBounds)); ! double biasMidToTargetRightDistance = biasedMid2D.distance(targetBounds.getMaxX(), ySideInOpositeDirection.apply(targetBounds)); ! ! targetNode.averageDistance ! = (targetNode.leftCornerDistance + biasLeftToTargetMidDistance + biasLeftToTargetRightDistance ! + currentRightToTargetLeftDistance + targetNode.rightCornerDistance + biasRightToTargetMidDistance + midDistance) / 7; ! ! targetNode.biasShortestDistance ! = findMin(targetNode.leftCornerDistance, biasLeftToTargetMidDistance, biasLeftToTargetRightDistance, ! currentRightToTargetLeftDistance, biasRightToTargetMidDistance, targetNode.rightCornerDistance, ! currentMidToTargetLeftDistance, midDistance, biasMidToTargetRightDistance); ! ! targetNode.shortestDistance ! = findMin(targetNode.leftCornerDistance, currentLeftToTargetMidDistance, currentLeftToTargetRightDistance, ! currentRightToTargetLeftDistance, currentRightToTargetMidDistance, currentRightToTargetRightDistance, ! currentMidToTargetLeftDistance, currentMidToTargetMidDistance, currentMidToTargetRightDistance); /* ** closest biased : simple 2d */ if (outdB >= 0.0) {
*** 602,624 **** } /* ** Closest top left / bottom left corners. */ if (nearestNodeLeft == null || nearestNodeLeft.leftCornerDistance > targetNode.leftCornerDistance) { ! if (((originB.getMinX() >= currentB.getMinX()) && (targetBounds.getMinX() >= currentB.getMinX())) || ! ((originB.getMinX() <= currentB.getMinX()) && (targetBounds.getMinX() <= currentB.getMinX()))) { if (nearestNodeLeft == null) { nearestNodeLeft = new TargetNode(); } nearestNodeLeft.copy(targetNode); } } if (nearestNodeAverage == null || nearestNodeAverage.averageDistance > targetNode.averageDistance) { ! if (((originB.getMinX() >= currentB.getMinX()) && (targetBounds.getMinX() >= currentB.getMinX())) || ! ((originB.getMinX() <= currentB.getMinX()) && (targetBounds.getMinX() <= currentB.getMinX()))) { if (nearestNodeAverage == null) { nearestNodeAverage = new TargetNode(); } nearestNodeAverage.copy(targetNode); --- 596,618 ---- } /* ** Closest top left / bottom left corners. */ if (nearestNodeLeft == null || nearestNodeLeft.leftCornerDistance > targetNode.leftCornerDistance) { ! if (((originB.getMinX() >= currentB.getMinX()) && (targetBounds.getMinX() >= currentB.getMinX())) ! || ((originB.getMinX() <= currentB.getMinX()) && (targetBounds.getMinX() <= currentB.getMinX()))) { if (nearestNodeLeft == null) { nearestNodeLeft = new TargetNode(); } nearestNodeLeft.copy(targetNode); } } if (nearestNodeAverage == null || nearestNodeAverage.averageDistance > targetNode.averageDistance) { ! if (((originB.getMinX() >= currentB.getMinX()) && (targetBounds.getMinX() >= currentB.getMinX())) ! || ((originB.getMinX() <= currentB.getMinX()) && (targetBounds.getMinX() <= currentB.getMinX()))) { if (nearestNodeAverage == null) { nearestNodeAverage = new TargetNode(); } nearestNodeAverage.copy(targetNode);
*** 632,642 **** } nearestNodeAnythingAnywhere.copy(targetNode); } } } - } nodes.clear(); if (nearestNodeOnOriginX != null) { nearestNodeOnOriginX.originLeftCornerDistance = originLeftCorner2D.distance(nearestNodeOnOriginX.bounds.getMinX(), ySideInOpositeDirection.apply(nearestNodeOnOriginX.bounds)); } --- 626,635 ----
*** 671,681 **** if (nearestNodeAnythingAnywhere != null) { focusLogger.finer("nearestNodeAnythingAnywhereUp.node : "+nearestNodeAnythingAnywhere.node); } } ! if (nearestNodeOnOriginX != null && nearestNodeOnOriginX.biasShortestDistance < Double.MAX_VALUE) { /* ** there's a preference, all else being equal, to return nearestNodeOnOriginX */ if (nearestNodeOnCurrentX != null && nearestNodeOnOriginX.node == nearestNodeOnCurrentX.node && ((nearestNodeAverage != null && nearestNodeOnOriginX.node == nearestNodeAverage.node) --- 664,674 ---- if (nearestNodeAnythingAnywhere != null) { focusLogger.finer("nearestNodeAnythingAnywhereUp.node : "+nearestNodeAnythingAnywhere.node); } } ! if (nearestNodeOnOriginX != null) { /* ** there's a preference, all else being equal, to return nearestNodeOnOriginX */ if (nearestNodeOnCurrentX != null && nearestNodeOnOriginX.node == nearestNodeOnCurrentX.node && ((nearestNodeAverage != null && nearestNodeOnOriginX.node == nearestNodeAverage.node)
*** 686,723 **** } if (nearestNodeAverage != null && nearestNodeOnOriginX.node == nearestNodeAverage.node) { return nearestNodeOnOriginX.node; } ! if (nearestNodeOnCurrentX != null && nearestNodeOnCurrentX.biasShortestDistance < Double.MAX_VALUE) { if ((nearestNodeOnCurrentX.leftCornerDistance < nearestNodeOnOriginX.leftCornerDistance) && (nearestNodeOnCurrentX.originLeftCornerDistance < nearestNodeOnOriginX.originLeftCornerDistance) && ! (nearestNodeOnCurrentX.bounds.getMinX() - currenLeftCorner2D.getX()) < (nearestNodeOnOriginX.bounds.getMinX() - currenLeftCorner2D.getX())) { return nearestNodeOnCurrentX.node; } else if (nearestNodeAverage == null || nearestNodeOnOriginX.averageDistance < nearestNodeAverage.averageDistance) { return nearestNodeOnOriginX.node; } } } else { ! if (nearestNodeOnOriginX == null && nearestNodeOnCurrentX == null && nearestNodeCurrentSimple2D != null) { if (nearestNodeAverage != null && nearestNodeLeft != null && (nearestNodeAverage.node == nearestNodeLeft.node && nearestNodeAverage.node == nearestNodeAnythingAnywhere.node)) { return nearestNodeAverage.node; } return nearestNodeCurrentSimple2D.node; } else if (nearestNodeAverage != null && nearestNodeLeft != null && nearestNodeAnythingAnywhere != null && nearestNodeAverage.biasShortestDistance == nearestNodeLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance == nearestNodeAnythingAnywhere.biasShortestDistance && nearestNodeAverage.biasShortestDistance < Double.MAX_VALUE) { - if (nearestNodeOnOriginX != null && nearestNodeOnOriginX.originLeftCornerDistance < nearestNodeAverage.originLeftCornerDistance) { - return nearestNodeOnOriginX.node; - } else { return nearestNodeAverage.node; } } - } /* ** is the average closer? */ if (nearestNodeAverage != null && (nearestNodeOnOriginX == null || (nearestNodeAverage.biasShortestDistance < nearestNodeOnOriginX.biasShortestDistance))) { --- 679,712 ---- } if (nearestNodeAverage != null && nearestNodeOnOriginX.node == nearestNodeAverage.node) { return nearestNodeOnOriginX.node; } ! if (nearestNodeOnCurrentX != null) { if ((nearestNodeOnCurrentX.leftCornerDistance < nearestNodeOnOriginX.leftCornerDistance) && (nearestNodeOnCurrentX.originLeftCornerDistance < nearestNodeOnOriginX.originLeftCornerDistance) && ! (nearestNodeOnCurrentX.bounds.getMinX() - currentLeftCorner2D.getX()) < (nearestNodeOnOriginX.bounds.getMinX() - currentLeftCorner2D.getX())) { return nearestNodeOnCurrentX.node; } else if (nearestNodeAverage == null || nearestNodeOnOriginX.averageDistance < nearestNodeAverage.averageDistance) { return nearestNodeOnOriginX.node; } } } else { ! if (nearestNodeOnCurrentX == null && nearestNodeCurrentSimple2D != null) { if (nearestNodeAverage != null && nearestNodeLeft != null && (nearestNodeAverage.node == nearestNodeLeft.node && nearestNodeAverage.node == nearestNodeAnythingAnywhere.node)) { return nearestNodeAverage.node; } return nearestNodeCurrentSimple2D.node; } else if (nearestNodeAverage != null && nearestNodeLeft != null && nearestNodeAnythingAnywhere != null && nearestNodeAverage.biasShortestDistance == nearestNodeLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance == nearestNodeAnythingAnywhere.biasShortestDistance && nearestNodeAverage.biasShortestDistance < Double.MAX_VALUE) { return nearestNodeAverage.node; } } /* ** is the average closer? */ if (nearestNodeAverage != null && (nearestNodeOnOriginX == null || (nearestNodeAverage.biasShortestDistance < nearestNodeOnOriginX.biasShortestDistance))) {
*** 787,808 **** public Double apply(Bounds t) { return t.getMaxX(); } }; ! protected Node getNearestNodeLeftOrRight(Bounds currentB, Bounds originB, TraversalEngine engine, Node node, Node reversingNode, Direction dir) { List<Node> nodes = engine.getAllTargetNodes(); Function<Bounds, Double> xSideInDirection = dir == LEFT ? BOUNDS_LEFT_SIDE : BOUNDS_RIGHT_SIDE; Function<Bounds, Double> xSideInOpositeDirection = dir == LEFT ? BOUNDS_RIGHT_SIDE : BOUNDS_LEFT_SIDE; ! Bounds biasedB = new BoundingBox(xSideInDirection.apply(currentB), originB.getMinY(), currentB.getWidth(), originB.getHeight()); Point2D currentMid2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMinY()+(currentB.getHeight()/2)); Point2D currentTopCorner2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMinY()); Point2D currentBottomCorner2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMaxY()); Point2D originTopCorner2D = new Point2D(xSideInDirection.apply(originB), originB.getMinY()); TargetNode targetNode = new TargetNode(); TargetNode nearestNodeCurrentSimple2D = null; --- 776,800 ---- public Double apply(Bounds t) { return t.getMaxX(); } }; ! protected Node getNearestNodeLeftOrRight(Bounds currentB, Bounds originB, TraversalEngine engine, Node node, Direction dir) { List<Node> nodes = engine.getAllTargetNodes(); Function<Bounds, Double> xSideInDirection = dir == LEFT ? BOUNDS_LEFT_SIDE : BOUNDS_RIGHT_SIDE; Function<Bounds, Double> xSideInOpositeDirection = dir == LEFT ? BOUNDS_RIGHT_SIDE : BOUNDS_LEFT_SIDE; ! Bounds biasedB = new BoundingBox(currentB.getMinX(), originB.getMinY(), currentB.getWidth(), originB.getHeight()); Point2D currentMid2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMinY()+(currentB.getHeight()/2)); + Point2D biasedMid2D = new Point2D(xSideInDirection.apply(currentB), originB.getMinY()+(originB.getHeight()/2)); Point2D currentTopCorner2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMinY()); + Point2D biasedTopCorner2D = new Point2D(xSideInDirection.apply(currentB), originB.getMinY()); Point2D currentBottomCorner2D = new Point2D(xSideInDirection.apply(currentB), currentB.getMaxY()); + Point2D biasedBottomCorner2D = new Point2D(xSideInDirection.apply(currentB), originB.getMaxY()); Point2D originTopCorner2D = new Point2D(xSideInDirection.apply(originB), originB.getMinY()); TargetNode targetNode = new TargetNode(); TargetNode nearestNodeCurrentSimple2D = null;
*** 811,900 **** TargetNode nearestNodeOnOriginY = null; TargetNode nearestNodeOnCurrentY = null; TargetNode nearestNodeTopLeft = null; TargetNode nearestNodeAnythingAnywhereLeft = null; - if (nodes.size() > 0) { - /* - ** we've just changed direction, and have a node on stack. - ** there is a strong preference for this node, just make sure - ** it's not a bad choice, as sometimes we got here as a last-chance - */ - if (reversingNode != null) { - return reversingNode; - } - for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) { final Node n = nodes.get(nodeIndex); Bounds targetBounds = n.localToScene(n.getLayoutBounds()); /* ** check that the target node starts after we start ** and the target node ends after we end */ ! if (dir == LEFT ? currentB.getMinX() > targetBounds.getMinX() : ! currentB.getMaxX() < targetBounds.getMaxX()) { targetNode.node = n; targetNode.bounds = targetBounds; /* ! ** closest biased : simple 2d */ ! double outdB = outDistance(dir, biasedB, targetBounds); if (isOnAxis(dir, biasedB, targetBounds)) { targetNode.biased2DMetric = outdB + centerSideDistance(dir, biasedB, targetBounds) / 100; ! } ! else { final double cosd = cornerSideDistance(dir, biasedB, targetBounds); ! targetNode.biased2DMetric = 100000 + outdB*outdB + 9*cosd*cosd; } /* ! ** closest current : simple 2d */ ! double outdC = outDistance(dir, currentB, targetBounds); if (isOnAxis(dir, currentB, targetBounds)) { targetNode.current2DMetric = outdC + centerSideDistance(dir, currentB, targetBounds) / 100; ! } ! else { final double cosd = cornerSideDistance(dir, currentB, targetBounds); ! targetNode.current2DMetric = 100000 + outdC*outdC + 9*cosd*cosd; } targetNode.topCornerDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! targetNode.midDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(originB.getHeight()/2)); ! targetNode.bottomCornerDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(originB), targetBounds.getMaxY()); ! double currentTopLeftToTargetBottomRightDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentTopLeftToTargetMidDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(targetBounds.getHeight()/2)); ! double currentBottomLeftToTargetTopRightDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! double currentBottomLeftToTargetBottomRightDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentBottomLeftToTargetMidDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(targetBounds.getHeight()/2)); ! double currentMidToTargetTopRightDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! double currentMidToTargetBottomRightDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentMidToTargetMidDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(targetBounds.getHeight()/2)); ! ! double biasTopLeftToTargetBottomRightDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(originB), targetBounds.getMaxY()); ! double biasTopLeftToTargetMidDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(originB.getHeight()/2)); ! double biasBottomLeftToTargetMidDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()+(originB.getHeight()/2)); ! double biasMidToTargetBottomRightDistance = currentMid2D.distance(xSideInOpositeDirection.apply(originB), targetBounds.getMaxY()); ! ! targetNode.averageDistance = ! (targetNode.topCornerDistance+biasTopLeftToTargetBottomRightDistance+biasTopLeftToTargetMidDistance+ ! currentBottomLeftToTargetTopRightDistance+targetNode.bottomCornerDistance+biasBottomLeftToTargetMidDistance)/7; ! ! targetNode.biasShortestDistance = ! findMin(targetNode.topCornerDistance, biasTopLeftToTargetBottomRightDistance, biasTopLeftToTargetMidDistance, ! currentBottomLeftToTargetTopRightDistance, targetNode.bottomCornerDistance, biasBottomLeftToTargetMidDistance, ! currentMidToTargetTopRightDistance, biasMidToTargetBottomRightDistance, targetNode.midDistance); ! ! targetNode.shortestDistance = ! findMin(targetNode.topCornerDistance, currentTopLeftToTargetBottomRightDistance, currentTopLeftToTargetMidDistance, ! currentBottomLeftToTargetTopRightDistance, currentBottomLeftToTargetBottomRightDistance, currentBottomLeftToTargetMidDistance, ! currentMidToTargetTopRightDistance, currentMidToTargetBottomRightDistance, currentMidToTargetMidDistance); /* ** closest biased : simple 2d */ if (outdB >= 0.0) { --- 803,882 ---- TargetNode nearestNodeOnOriginY = null; TargetNode nearestNodeOnCurrentY = null; TargetNode nearestNodeTopLeft = null; TargetNode nearestNodeAnythingAnywhereLeft = null; for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) { final Node n = nodes.get(nodeIndex); Bounds targetBounds = n.localToScene(n.getLayoutBounds()); /* ** check that the target node starts after we start ** and the target node ends after we end */ ! if (dir == LEFT ? currentB.getMinX() > targetBounds.getMinX() ! : currentB.getMaxX() < targetBounds.getMaxX()) { targetNode.node = n; targetNode.bounds = targetBounds; /* ! * closest biased : simple 2d. ! * Negative means the Node is on the same Y axis. This will result in outdB == 0, making this a preferred Node. */ ! double outdB = Math.max(0, outDistance(dir, biasedB, targetBounds)); if (isOnAxis(dir, biasedB, targetBounds)) { targetNode.biased2DMetric = outdB + centerSideDistance(dir, biasedB, targetBounds) / 100; ! } else { final double cosd = cornerSideDistance(dir, biasedB, targetBounds); ! targetNode.biased2DMetric = 100000 + outdB * outdB + 9 * cosd * cosd; } /* ! * closest current : simple 2d ! *Negative means the Node is on the same Y axis. This will result in outdB == 0, making this a preferred Node. */ ! double outdC = Math.max(0, outDistance(dir, currentB, targetBounds)); if (isOnAxis(dir, currentB, targetBounds)) { targetNode.current2DMetric = outdC + centerSideDistance(dir, currentB, targetBounds) / 100; ! } else { final double cosd = cornerSideDistance(dir, currentB, targetBounds); ! targetNode.current2DMetric = 100000 + outdC * outdC + 9 * cosd * cosd; } targetNode.topCornerDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! targetNode.bottomCornerDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double midDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! double currentTopToTargetBottomDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentTopToTargetMidDistance = currentTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! double currentBottomToTargetTopDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! double currentBottomToTargetBottomDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentBottomToTargetMidDistance = currentBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! double currentMidToTargetTopDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY()); ! double currentMidToTargetBottomDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double currentMidToTargetMidDistance = currentMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! ! double biasTopToTargetBottomDistance = biasedTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! double biasTopToTargetMidDistance = biasedTopCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! double biasBottomToTargetMidDistance = biasedBottomCorner2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMinY() + (targetBounds.getHeight() / 2)); ! double biasMidToTargetBottomDistance = biasedMid2D.distance(xSideInOpositeDirection.apply(targetBounds), targetBounds.getMaxY()); ! ! targetNode.averageDistance ! = (targetNode.topCornerDistance + biasTopToTargetBottomDistance + biasTopToTargetMidDistance ! + currentBottomToTargetTopDistance + targetNode.bottomCornerDistance + biasBottomToTargetMidDistance + midDistance) / 7; ! ! targetNode.biasShortestDistance ! = findMin(targetNode.topCornerDistance, biasTopToTargetBottomDistance, biasTopToTargetMidDistance, ! currentBottomToTargetTopDistance, targetNode.bottomCornerDistance, biasBottomToTargetMidDistance, ! currentMidToTargetTopDistance, biasMidToTargetBottomDistance, midDistance); ! ! targetNode.shortestDistance ! = findMin(targetNode.topCornerDistance, currentTopToTargetBottomDistance, currentTopToTargetMidDistance, ! currentBottomToTargetTopDistance, currentBottomToTargetBottomDistance, currentBottomToTargetMidDistance, ! currentMidToTargetTopDistance, currentMidToTargetBottomDistance, currentMidToTargetMidDistance); /* ** closest biased : simple 2d */ if (outdB >= 0.0) {
*** 968,978 **** } nearestNodeAnythingAnywhereLeft.copy(targetNode); } } } - } nodes.clear(); if (nearestNodeOnOriginY != null) { nearestNodeOnOriginY.originTopCornerDistance = originTopCorner2D.distance(xSideInOpositeDirection.apply(nearestNodeOnOriginY.bounds), nearestNodeOnOriginY.bounds.getMinY()); } --- 950,959 ----
*** 1014,1024 **** if (nearestNodeAnythingAnywhereLeft != null) { focusLogger.finer("nearestNodeAnythingAnywhereLeft.node : "+nearestNodeAnythingAnywhereLeft.node); } } ! if (nearestNodeOnOriginY != null && nearestNodeOnOriginY.biasShortestDistance < Double.MAX_VALUE) { /* ** there's a preference, all else being equal, to return nearestNodeOnOriginY */ if (nearestNodeOnCurrentY != null && nearestNodeOnOriginY.node == nearestNodeOnCurrentY.node && ((nearestNodeAverage != null && nearestNodeOnOriginY.node == nearestNodeAverage.node) --- 995,1005 ---- if (nearestNodeAnythingAnywhereLeft != null) { focusLogger.finer("nearestNodeAnythingAnywhereLeft.node : "+nearestNodeAnythingAnywhereLeft.node); } } ! if (nearestNodeOnOriginY != null) { /* ** there's a preference, all else being equal, to return nearestNodeOnOriginY */ if (nearestNodeOnCurrentY != null && nearestNodeOnOriginY.node == nearestNodeOnCurrentY.node && ((nearestNodeAverage != null && nearestNodeOnOriginY.node == nearestNodeAverage.node)
*** 1029,1067 **** if (nearestNodeAverage != null && nearestNodeOnOriginY.node == nearestNodeAverage.node) { return nearestNodeOnOriginY.node; } ! if (nearestNodeOnCurrentY != null && nearestNodeOnCurrentY.biasShortestDistance < Double.MAX_VALUE) { if ((nearestNodeOnCurrentY.bottomCornerDistance < nearestNodeOnOriginY.bottomCornerDistance) && (nearestNodeOnCurrentY.originTopCornerDistance < nearestNodeOnOriginY.originTopCornerDistance) && (nearestNodeOnCurrentY.bounds.getMinY() - currentTopCorner2D.getY()) < (nearestNodeOnOriginY.bounds.getMinY() - currentTopCorner2D.getY())) { return nearestNodeOnCurrentY.node; } else if (nearestNodeAverage == null || nearestNodeOnOriginY.averageDistance < nearestNodeAverage.averageDistance) { return nearestNodeOnOriginY.node; } } } else { ! if (nearestNodeOnOriginY == null && nearestNodeOnCurrentY == null && nearestNodeCurrentSimple2D != null) { if (nearestNodeAverage != null && nearestNodeTopLeft != null && nearestNodeAverage.node == nearestNodeTopLeft.node && nearestNodeAverage.node == nearestNodeAnythingAnywhereLeft.node) { return nearestNodeAverage.node; } return nearestNodeCurrentSimple2D.node; } else if (nearestNodeAverage != null && nearestNodeTopLeft != null && nearestNodeAnythingAnywhereLeft != null && nearestNodeAverage.biasShortestDistance == nearestNodeTopLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance == nearestNodeAnythingAnywhereLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance < Double.MAX_VALUE) { - - if (nearestNodeOnOriginY != null && nearestNodeOnOriginY.originTopCornerDistance < nearestNodeAverage.originTopCornerDistance) { - return nearestNodeOnOriginY.node; - } else { return nearestNodeAverage.node; } } - } /* ** is the average closer? */ if (nearestNodeAverage != null && (nearestNodeOnOriginY == null || nearestNodeAverage.biasShortestDistance < nearestNodeOnOriginY.biasShortestDistance)) { --- 1010,1043 ---- if (nearestNodeAverage != null && nearestNodeOnOriginY.node == nearestNodeAverage.node) { return nearestNodeOnOriginY.node; } ! if (nearestNodeOnCurrentY != null) { if ((nearestNodeOnCurrentY.bottomCornerDistance < nearestNodeOnOriginY.bottomCornerDistance) && (nearestNodeOnCurrentY.originTopCornerDistance < nearestNodeOnOriginY.originTopCornerDistance) && (nearestNodeOnCurrentY.bounds.getMinY() - currentTopCorner2D.getY()) < (nearestNodeOnOriginY.bounds.getMinY() - currentTopCorner2D.getY())) { return nearestNodeOnCurrentY.node; } else if (nearestNodeAverage == null || nearestNodeOnOriginY.averageDistance < nearestNodeAverage.averageDistance) { return nearestNodeOnOriginY.node; } } } else { ! if (nearestNodeOnCurrentY == null && nearestNodeCurrentSimple2D != null) { if (nearestNodeAverage != null && nearestNodeTopLeft != null && nearestNodeAverage.node == nearestNodeTopLeft.node && nearestNodeAverage.node == nearestNodeAnythingAnywhereLeft.node) { return nearestNodeAverage.node; } return nearestNodeCurrentSimple2D.node; } else if (nearestNodeAverage != null && nearestNodeTopLeft != null && nearestNodeAnythingAnywhereLeft != null && nearestNodeAverage.biasShortestDistance == nearestNodeTopLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance == nearestNodeAnythingAnywhereLeft.biasShortestDistance && nearestNodeAverage.biasShortestDistance < Double.MAX_VALUE) { return nearestNodeAverage.node; } } /* ** is the average closer? */ if (nearestNodeAverage != null && (nearestNodeOnOriginY == null || nearestNodeAverage.biasShortestDistance < nearestNodeOnOriginY.biasShortestDistance)) {
*** 1124,1134 **** Bounds bounds = null; double biased2DMetric = Double.MAX_VALUE; double current2DMetric = Double.MAX_VALUE; double leftCornerDistance = Double.MAX_VALUE; - double midDistance = Double.MAX_VALUE; double rightCornerDistance = Double.MAX_VALUE; double topCornerDistance = Double.MAX_VALUE; double bottomCornerDistance = Double.MAX_VALUE; double shortestDistance = Double.MAX_VALUE; --- 1100,1109 ----
*** 1143,1153 **** bounds = source.bounds; biased2DMetric = source.biased2DMetric; current2DMetric = source.current2DMetric; leftCornerDistance = source.leftCornerDistance; - midDistance = source.midDistance; rightCornerDistance = source.rightCornerDistance; shortestDistance = source.shortestDistance; biasShortestDistance = source.biasShortestDistance; averageDistance = source.averageDistance; --- 1118,1127 ----