public void setSelection(int ix) { if(ix < 0) { caret.getElements().clear(); setCaretVisible(false); } else { if(caret.getParent() == null) { textField.getChildren().add(caret); } PathElement[] es = getCaretShape(ix, true); caret.getElements().setAll(es); setCaretVisible(true); } selectionIndex.set(ix); }
public CaretLocation getCaretLocation(Region parent, Marker pos) { if(pos != null) { LineBox b = getLineBox(pos.getLine()); if(b != null) { Region box = b.getCenter(); if(box instanceof CTextFlow) { PathElement[] es = ((CTextFlow)box).getCaretShape(pos.getCharIndex(), pos.isLeading()); if(es != null) { return EditorTools.translateCaretLocation(parent, box, es); } } } } return null; }
/** returns selection shape for a given range */ public PathElement[] getRange(int start, int end) { if(center instanceof CTextFlow) { CTextFlow t = (CTextFlow)center; return t.getRange(start, end); } else { double w = center.getWidth(); double h = center.getHeight(); return new PathElement[] { new MoveTo(0, 0), new LineTo(w, 0), new LineTo(w, h), new LineTo(0, h), new LineTo(0, 0) }; } }
/** returns selection shape for a given range */ public PathElement[] getCaretShape(int index, boolean leading) { if(center instanceof CTextFlow) { CTextFlow t = (CTextFlow)center; return t.getCaretShape(index, leading); } else { double x = leading ? 0 : center.getWidth(); double h = center.getHeight(); return new PathElement[] { new MoveTo(x, 0), new LineTo(x, h) }; } }
private void clearSmallPolygons(Path... paths){ validPaths = new ArrayList<>(); Point2D p0 = Point2D.ZERO; for (Path path : paths) { for (PathElement elem : path.getElements()) { if (elem instanceof MoveTo) { elements = new ArrayList<>(); elements.add(elem); listPoints = new ArrayList<>(); p0 = new Point2D(((MoveTo)elem).getX(), ((MoveTo)elem).getY()); listPoints.add(p0); } else if (elem instanceof CubicCurveTo) { elements.add(elem); Point2D ini = listPoints.size() > 0 ? listPoints.get(listPoints.size() - 1) : p0; listPoints.addAll(evalCubicCurve((CubicCurveTo) elem, ini, POINTS_CURVE)); } else if (elem instanceof ClosePath) { elements.add(elem); listPoints.add(p0); if (Math.abs(calculateArea()) > MINIMUM_AREA) { validPaths.add(new Path(elements)); } } } } }
private String pathsToSVGPath() { final StringBuilder sb = new StringBuilder(); for (Path path : validPaths) { for (PathElement element : path.getElements()) { if (element instanceof MoveTo) { sb.append("M ").append(((MoveTo) element).getX()).append(" ") .append(((MoveTo) element).getY()); } else if (element instanceof CubicCurveTo) { CubicCurveTo curve = (CubicCurveTo) element; sb.append(" C ") .append(curve.getControlX1()).append(" ").append(curve.getControlY1()).append(" ") .append(curve.getControlX2()).append(" ").append(curve.getControlY2()).append(" ") .append(curve.getX()).append(" ").append(curve.getY()); } else if (element instanceof ClosePath) { sb.append(" Z "); } } } return sb.toString(); }
public CaretLocation getCaretLocation(Region parent, Marker pos) { if(pos != null) { LineBox b = getLineBox(pos.getLine()); if(b != null) { Region box = b.getBox(); if(box instanceof CTextFlow) { PathElement[] es = ((CTextFlow)box).getCaretShape(pos.getCharIndex(), pos.isLeading()); if(es != null) { return EditorTools.translateCaretLocation(parent, box, es); } } } } return null; }
protected Rectangle2D getBounds(int start, int end) { PathElement[] shape = getShape(start, end); double minX = 0, minY = 0, maxX = 0, maxY = 0; for (PathElement pathElement : shape) { if (pathElement instanceof MoveTo) { MoveTo moveTo = (MoveTo) pathElement; minX = maxX = moveTo.getX(); minY = maxY = moveTo.getY(); } else if (pathElement instanceof LineTo) { LineTo lineTo = (LineTo) pathElement; double x = lineTo.getX(); double y = lineTo.getY(); minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); } } return new Rectangle2D(minX, minY, maxX - minX, maxY - minY); }
@Override public void Draw(Pane canvas) { double width = canvas.getWidth() * (GetDoubleAttribute("Width") / (double) MaximumX); double height = GetDoubleAttribute("Height") == 0 ? width : canvas.getHeight() * (GetDoubleAttribute("Height") / MaximumY); double left = canvas.getWidth() * (GetDoubleAttribute("X") / MaximumX) - width / 2; double top = canvas.getHeight() * (GetDoubleAttribute("Y") / MaximumY) - height / 2; Path path = new Path(new PathElement[] { new MoveTo(0, height / 2), new LineTo(width / 2, 0), new LineTo(width, height / 2), new LineTo(width / 2, height), new LineTo(0, height / 2) }); path.setFill(GetColorAttribute("Color")); path.setStrokeWidth(0); path.setLayoutX(left); path.setLayoutY(top); canvas.getChildren().add(path); }
@Override public void Draw(Pane canvas) { double widthX = canvas.getWidth() * (GetDoubleAttribute("Thickness") / MaximumX) / 2; double widthY = canvas.getHeight() * (GetDoubleAttribute("Thickness") / MaximumX) / 2; Path path = new Path(new PathElement[] { new MoveTo(widthX, 0), new LineTo(0, 0), new LineTo(0, widthY), new LineTo(canvas.getWidth() - widthX, canvas.getHeight()), new LineTo(canvas.getWidth(), canvas.getHeight()), new LineTo(canvas.getWidth(), canvas.getHeight() - widthY), new LineTo(widthX, 0) }); path.setFill(GetColorAttribute("Color")); path.setStrokeWidth(0); canvas.getChildren().add(path); }
@Override protected Shape[] Thumbnail() { return new Shape[] { new Path(new PathElement[] { new MoveTo(0, 5), new LineTo(30, 5), new LineTo(30, 25), new LineTo(0, 25), new LineTo(0, 5), new MoveTo(5, 10), new LineTo(5, 20), new LineTo(25, 20), new LineTo(25, 10), new LineTo(5, 10) }) }; }
@Override public void Draw(Pane canvas) { double widthX = canvas.getWidth() * (GetDoubleAttribute("Thickness") / MaximumX) / 2; double widthY = canvas.getHeight() * (GetDoubleAttribute("Thickness") / MaximumX) / 2; Path path = new Path(new PathElement[] { new MoveTo(canvas.getWidth() - widthX, 0), new LineTo(canvas.getWidth(), 0), new LineTo(canvas.getWidth(), widthY), new LineTo(widthX, canvas.getHeight()), new LineTo(0, canvas.getHeight()), new LineTo(0, canvas.getHeight() - widthY), new LineTo(canvas.getWidth() - widthX, 0) }); path.setFill(GetColorAttribute("Color")); path.setStrokeWidth(0); canvas.getChildren().add(path); }
@Override public void Draw(Pane canvas) { double height = canvas.getHeight(); double width = canvas.getWidth(); canvas.getChildren().add(new Rectangle(width, height, Colors[0])); Path p = new Path(new PathElement[] { new MoveTo(width, 0), new LineTo(width, height), new LineTo(0, height), new LineTo(width, 0) }); p.fillProperty().set(Colors[1]); p.strokeWidthProperty().set(0); canvas.getChildren().add(p); }
@Override public void Draw(Pane canvas) { double height = canvas.getHeight(); double width = canvas.getWidth(); canvas.getChildren().add(new Rectangle(width, height, Colors[0])); Path p = new Path(new PathElement[] { new MoveTo(0, height), new LineTo(width, 0), new LineTo(width, height), new LineTo(0, 0) }); p.fillProperty().set(Colors[1]); p.strokeWidthProperty().set(0); canvas.getChildren().add(p); }
@Override public void Draw(Pane canvas) { double height = canvas.getHeight(); double width = canvas.getWidth(); canvas.getChildren().add(new Rectangle(width, height, Colors[0])); Path p = new Path(new PathElement[] { new MoveTo(width, height), new LineTo(0, height), new LineTo(0, 0), new LineTo(width, height) }); p.fillProperty().set(Colors[1]); p.strokeWidthProperty().set(0); canvas.getChildren().add(p); }
MySVGShortHandCubicCurveTo(PathElement lastElement, float lastX, float lastY, float x2, float y2, float x, float y, Point2D lastPoint) { super( 0f, 0f, x2, y2, x, y); float x1 = lastX; float y1 = lastY; if (lastElement instanceof CubicCurveTo){ x1 = 2 * lastX - (float)((CubicCurveTo)lastElement).getControlX2(); y1 = 2 * lastY - (float)((CubicCurveTo)lastElement).getControlY2(); } this.setControlX1(x1); this.setControlY1(y1); this.lastPoint = new Point2D(lastPoint.getX(), lastPoint.getY()); pStartControl = new Point2D(x1, y1); pEndControl = new Point2D(x2, y2); pTo = new Point2D(x, y); }
/** * @param from The index of the first character. * @param to The index of the last character. * @return An array with the PathElement objects which define an * underline from the first to the last character. */ PathElement[] getUnderlineShape(int from, int to) { // get a Path for the text underline PathElement[] shape = textLayout().getRange(from, to, TextLayout.TYPE_UNDERLINE, 0, 0); // The shape is returned as a closed Path (a thin rectangle). // If we use the Path as it is, this causes rendering issues. // Hence we only use the MoveTo and the succeeding LineTo elements for the result // so that simple line segments instead of rectangles are returned. List<PathElement> result = new ArrayList<>(); boolean collect = false; for (PathElement elem : shape) { if (elem instanceof MoveTo) { // There seems to be no API to get the type of the PathElement result.add(elem); collect = true; } else if (elem instanceof LineTo) { if (collect) { result.add(elem); collect = false; } } } return result.toArray(new PathElement[0]); }
private void smooth(ObservableList<PathElement> strokeElements, ObservableList<PathElement> fillElements, final double HEIGHT) { if (fillElements.isEmpty()) return; // as we do not have direct access to the data, first recreate the list of all the data points we have final Point2D[] dataPoints = new Point2D[strokeElements.size()]; for (int i = 0; i < strokeElements.size(); i++) { final PathElement element = strokeElements.get(i); if (element instanceof MoveTo) { final MoveTo move = (MoveTo) element; dataPoints[i] = new Point2D(move.getX(), move.getY()); } else if (element instanceof LineTo) { final LineTo line = (LineTo) element; final double x = line.getX(), y = line.getY(); dataPoints[i] = new Point2D(x, y); } } double firstX = dataPoints[0].getX(); double lastX = dataPoints[dataPoints.length - 1].getX(); Point2D[] points = Helper.subdividePoints(dataPoints, getSubDivisions()); fillElements.clear(); fillElements.add(new MoveTo(firstX, HEIGHT)); strokeElements.clear(); strokeElements.add(new MoveTo(points[0].getX(), points[0].getY())); for (Point2D p : points) { if (Double.compare(p.getX(), firstX) >= 0) { fillElements.add(new LineTo(p.getX(), p.getY())); strokeElements.add(new LineTo(p.getX(), p.getY())); } } fillElements.add(new LineTo(lastX, HEIGHT)); fillElements.add(new LineTo(0, HEIGHT)); fillElements.add(new ClosePath()); }
private double[] getXYFromPathElement(final PathElement ELEMENT) { if (ELEMENT instanceof MoveTo) { return new double[]{ ((MoveTo) ELEMENT).getX(), ((MoveTo) ELEMENT).getY() }; } else if (ELEMENT instanceof LineTo) { return new double[] { ((LineTo) ELEMENT).getX(), ((LineTo) ELEMENT).getY() }; } else { return new double[] { -1, -1 }; } }
private double[] getXYFromPathElement(final PathElement ELEMENT) { if (ELEMENT instanceof MoveTo) { return new double[]{ ((MoveTo) ELEMENT).getX(), ((MoveTo) ELEMENT).getY() }; } else { return new double[] { ((LineTo) ELEMENT).getX(), ((LineTo) ELEMENT).getY() }; } }
private void smooth(ObservableList<PathElement> strokeElements, ObservableList<PathElement> fillElements, final double HEIGHT) { if (fillElements.isEmpty()) return; // as we do not have direct access to the data, first recreate the list of all the data points we have final Point[] dataPoints = new Point[strokeElements.size()]; for (int i = 0; i < strokeElements.size(); i++) { final PathElement element = strokeElements.get(i); if (element instanceof MoveTo) { final MoveTo move = (MoveTo) element; dataPoints[i] = new Point(move.getX(), move.getY()); } else if (element instanceof LineTo) { final LineTo line = (LineTo) element; final double x = line.getX(), y = line.getY(); dataPoints[i] = new Point(x, y); } } double firstX = dataPoints[0].getX(); double lastX = dataPoints[dataPoints.length - 1].getX(); Point[] points = Helper.subdividePoints(dataPoints, getSubDivisions()); fillElements.clear(); fillElements.add(new MoveTo(firstX, HEIGHT)); strokeElements.clear(); strokeElements.add(new MoveTo(points[0].getX(), points[0].getY())); for (Point p : points) { if (Double.compare(p.getX(), firstX) >= 0) { fillElements.add(new LineTo(p.getX(), p.getY())); strokeElements.add(new LineTo(p.getX(), p.getY())); } } fillElements.add(new LineTo(lastX, HEIGHT)); fillElements.add(new LineTo(0, HEIGHT)); fillElements.add(new ClosePath()); }
public static final Path smoothPath(final ObservableList<PathElement> ELEMENTS, final boolean FILLED) { if (ELEMENTS.isEmpty()) { return new Path(); } final Point[] dataPoints = new Point[ELEMENTS.size()]; for (int i = 0; i < ELEMENTS.size(); i++) { final PathElement element = ELEMENTS.get(i); if (element instanceof MoveTo) { MoveTo move = (MoveTo) element; dataPoints[i] = new Point(move.getX(), move.getY()); } else if (element instanceof LineTo) { LineTo line = (LineTo) element; dataPoints[i] = new Point(line.getX(), line.getY()); } } double zeroY = ((MoveTo) ELEMENTS.get(0)).getY(); List<PathElement> smoothedElements = new ArrayList<>(); Pair<Point[], Point[]> result = calcCurveControlPoints(dataPoints); Point[] firstControlPoints = result.getKey(); Point[] secondControlPoints = result.getValue(); // Start path dependent on filled or not if (FILLED) { smoothedElements.add(new MoveTo(dataPoints[0].getX(), zeroY)); smoothedElements.add(new LineTo(dataPoints[0].getX(), dataPoints[0].getY())); } else { smoothedElements.add(new MoveTo(dataPoints[0].getX(), dataPoints[0].getY())); } // Add curves for (int i = 2; i < dataPoints.length; i++) { final int ci = i - 1; smoothedElements.add(new CubicCurveTo( firstControlPoints[ci].getX(), firstControlPoints[ci].getY(), secondControlPoints[ci].getX(), secondControlPoints[ci].getY(), dataPoints[i].getX(), dataPoints[i].getY())); } // Close the path if filled if (FILLED) { smoothedElements.add(new LineTo(dataPoints[dataPoints.length - 1].getX(), zeroY)); smoothedElements.add(new ClosePath()); } return new Path(smoothedElements); }
public void process(PathElement[] elements) { for(PathElement em: elements) { double y = getY(em); setTop(y); setBottom(y); } }
public void generateTop(PathElement[] elements) { boolean include = false; double y; for(PathElement em: elements) { if(em instanceof LineTo) { if(include) { pathBuilder.add(em); } } else if(em instanceof MoveTo) { y = getY(em); if((y == topUp) || (y == topDn)) { pathBuilder.add(em); include = true; } else { include = false; } } } }
public void generateBottom(PathElement[] elements) { boolean include = false; double y; for(PathElement em: elements) { if(em instanceof LineTo) { if(include) { pathBuilder.add(em); } } else if(em instanceof MoveTo) { y = getY(em); if((y == botUp) || (y == botDn)) { pathBuilder.add(em); include = true; } else { include = false; } } } }
public PathElement[] getCaretShape(int index, boolean leading) { PathElement[] pe = FxHacks.get().getCaretShape(this, index, leading); // empty line generates a simple dot shape which is not what we need if(pe.length == 2) { PathElement p0 = pe[0]; PathElement p1 = pe[1]; if((p0 instanceof MoveTo) && (p1 instanceof LineTo)) { MoveTo m0 = (MoveTo)p0; LineTo m1 = (LineTo)p1; // close enough? if(Math.abs(m0.getY() - m1.getY()) < 0.01) { double x = m0.getX(); double y = m0.getY(); // little hack: using the text flow height pe[1] = new LineTo(x, y + getHeight()); } } } return pe; }
/** returns selection shape for a given range. negative 'end' value is equivalent to the offset of the last symbol in the text */ public PathElement[] getRange(int start, int end) { PathElement[] pe = FxHacks.get().getRange(this, start, end); if(pe.length == 0) { // happens with empty line pe = new PathElement[2]; pe[0] = new MoveTo(0, 0); pe[1] = new LineTo(0, getHeight()); } return pe; }
protected PathElement[] getRangeTop() { double w = getWidth(); return new PathElement[] { new MoveTo(0, -1), new LineTo(w, -1), new LineTo(w, 0), new LineTo(0, 0), new LineTo(0, -1) }; }
protected PathElement[] getRangeBottom() { double w = getWidth(); double h = getHeight(); double h1 = h + 1; return new PathElement[] { new MoveTo(0, h), new LineTo(w, h), new LineTo(w, h1), new LineTo(0, h1), new LineTo(0, h) }; }
protected PathElement[] getRangeShape(int line, int startOffset, int endOffset) { LineBox lineBox = layout.getLineBox(line); if(lineBox == null) { return null; } if(endOffset < 0) { endOffset = lineBox.getTextLength(); } PathElement[] pe; if(startOffset == endOffset) { // not a range, use caret shape instead pe = lineBox.getCaretShape(startOffset, false); } else { pe = lineBox.getRange(startOffset, endOffset); } if(pe == null) { return null; } else { return EditorTools.translatePath(this, lineBox.getCenter(), pe); } }
protected void add(PathElement em) { if(path == null) { path = newPath(); } path.getElements().add(em); }
protected void updateHighlights() { removeHighlights(); int ix = 0; for(HL h: highlights) { PathElement[] es = getRange(h.start, h.end); h.path = new Path(es); h.path.getStyleClass().add(h.style.getName()); getChildren().add(ix, h.path); ix++; } }
/** * Create a transition * * @param sourceElements * the source elements * @param targetElements * the target elements * @param duation * the duration * @param pathNode * the path not the morph is done on */ public PathMorphTransition(List<PathElement> sourceElements, List<PathElement> targetElements, Duration duation, Path pathNode) { this.pathNode = pathNode; setCycleDuration(duation); if (sourceElements.size() != targetElements.size()) { throw new IllegalArgumentException("Only equal paths are allowed"); //$NON-NLS-1$ } for (int i = 0; i < sourceElements.size(); i++) { PathElement sourceElement = sourceElements.get(i); PathElement targetElement = targetElements.get(i); if (sourceElement.getClass() != targetElement.getClass()) { throw new IllegalArgumentException("Only equal paths are allowed"); //$NON-NLS-1$ } if (sourceElement instanceof ArcTo) { this.interpolateList.add(new ArcToInterpolatable((ArcTo) sourceElement)); } else if (sourceElement instanceof CubicCurveTo) { this.interpolateList.add(new CubicCurveToInterpolatable((CubicCurveTo) sourceElement)); } else if (sourceElement instanceof HLineTo) { this.interpolateList.add(new HLineToInterpolatable((HLineTo) sourceElement)); } else if (sourceElement instanceof LineTo) { this.interpolateList.add(new LineToInterpolatable((LineTo) sourceElement)); } else if (sourceElement instanceof MoveTo) { this.interpolateList.add(new MoveToInterpolatable((MoveTo) sourceElement)); } else if (sourceElement instanceof QuadCurveTo) { this.interpolateList.add(new QuadCurveToInterpolatable((QuadCurveTo) sourceElement)); } else if (sourceElement instanceof VLineTo) { this.interpolateList.add(new VLineToInterpolatable((VLineTo) sourceElement)); } } this.sourceElements = sourceElements; this.targetElements = targetElements; }
@Override protected void interpolate(double frac) { List<PathElement> elements = new ArrayList<PathElement>(this.sourceElements.size()); for (int i = 0; i < this.interpolateList.size(); i++) { @SuppressWarnings("unchecked") Interpolatable<PathElement> interpolatable = (Interpolatable<PathElement>) this.interpolateList.get(i); elements.add(interpolatable.interpolate(this.targetElements.get(i), frac)); } this.pathNode.getElements().setAll(elements); }
/** * Gets the horizontal or vertical offset to the connection for the given cursor position. * * @param cursorSceneX the cursor x-position in the scene * @param cursorSceneY the cursor y-position in the scene * @return an offset to the nearest connection, or {@code null} if the cursor is too far away */ public Point2D getOffset(final double cursorSceneX, final double cursorSceneY) { // Scale factor only relevant if we are zoomed in. final double scaleFactor = backgroundPath.getLocalToSceneTransform().getMxx(); // This will be used as the largest acceptable offset value. final double offsetBound = Math.ceil(backgroundPath.getStrokeWidth() / 2) * scaleFactor; minOffsetX = offsetBound + 1; minOffsetY = offsetBound + 1; currentX = ((MoveTo) path.getElements().get(0)).getX(); currentY = ((MoveTo) path.getElements().get(0)).getY(); for (int i = 1; i < path.getElements().size(); i++) { final PathElement pathElement = path.getElements().get(i); calculateOffset(pathElement, cursorSceneX, cursorSceneY, offsetBound); } if (minOffsetX > offsetBound && minOffsetY > offsetBound) { return null; } else if (Math.abs(minOffsetX) <= Math.abs(minOffsetY)) { return new Point2D(minOffsetX, 0); } else { return new Point2D(0, minOffsetY); } }
private Node createTicks() { Path tickMarks = new Path(); ObservableList<PathElement> pathChildren = tickMarks.getElements(); for(int i = 0; i < 360; i += TICK_DEGREE) { pathChildren.add(new MoveTo(this.size, this.size)); pathChildren.add(new LineTo(this.size * Math.cos(Math.toRadians(i)) + this.size, this.size * Math.sin(Math.toRadians(i)) + this.size)); } return tickMarks; }