org.jhotdraw8.draw.figure.BezierPathFigure Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.jhotdraw8.draw Show documentation
Show all versions of org.jhotdraw8.draw Show documentation
JHotDraw8 Drawing Framework
The newest version!
/*
* @(#)BezierPathFigure.java
* Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
*/
package org.jhotdraw8.draw.figure;
import javafx.css.StyleOrigin;
import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import org.jhotdraw8.css.value.CssSize;
import org.jhotdraw8.draw.connector.Connector;
import org.jhotdraw8.draw.connector.PathConnector;
import org.jhotdraw8.draw.css.converter.BezierPathCssConverter;
import org.jhotdraw8.draw.css.value.CssPoint2D;
import org.jhotdraw8.draw.css.value.CssRectangle2D;
import org.jhotdraw8.draw.handle.BezierControlPointEditHandle;
import org.jhotdraw8.draw.handle.BezierNodeEditHandle;
import org.jhotdraw8.draw.handle.BezierNodeTangentHandle;
import org.jhotdraw8.draw.handle.BezierPathEditHandle;
import org.jhotdraw8.draw.handle.Handle;
import org.jhotdraw8.draw.handle.HandleType;
import org.jhotdraw8.draw.handle.PathIterableOutlineHandle;
import org.jhotdraw8.draw.key.NonNullObjectStyleableKey;
import org.jhotdraw8.draw.locator.BoundsLocator;
import org.jhotdraw8.draw.render.RenderContext;
import org.jhotdraw8.geom.FXShapes;
import org.jhotdraw8.geom.FXTransforms;
import org.jhotdraw8.geom.shape.BezierNode;
import org.jhotdraw8.geom.shape.BezierPath;
import org.jspecify.annotations.Nullable;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
import java.util.List;
/**
* A {@link Figure} which draws a {@link BezierPath}.
*
* @author Werner Randelshofer
*/
public class BezierPathFigure extends AbstractLeafFigure
implements StrokableFigure, FillableFigure, FillRulableFigure, TransformableFigure, HideableFigure,
StyleableFigure, LockableFigure, CompositableFigure, ResizableFigure, ConnectableFigure,
PathIterableFigure {
public static final NonNullObjectStyleableKey PATH = new NonNullObjectStyleableKey<>("path", BezierPath.class, new BezierPathCssConverter(false), BezierPath.of());
/**
* The CSS type selector for this object is {@value #TYPE_SELECTOR}.
*/
public static final String TYPE_SELECTOR = "Bezier";
public BezierPathFigure() {
setStyled(StyleOrigin.USER_AGENT, FILL, null);
}
@Override
public void createHandles(HandleType handleType, List list) {
if (handleType == HandleType.SELECT) {
list.add(new PathIterableOutlineHandle(this, true));
} else if (handleType == HandleType.POINT) {
list.add(new BezierPathEditHandle(this, PATH));
BezierPath nodes = get(PATH);
for (int i = 0, n = nodes.size(); i < n; i++) {
list.add(new BezierNodeTangentHandle(this, PATH, i));
list.add(new BezierNodeEditHandle(this, PATH, i));
list.add(new BezierControlPointEditHandle(this, PATH, i, BezierNode.IN_MASK));
list.add(new BezierControlPointEditHandle(this, PATH, i, BezierNode.OUT_MASK));
}
} else {
super.createHandles(handleType, list);
}
}
@Override
public Node createNode(RenderContext ctx) {
Path n = new Path();
n.setManaged(false);
return n;
}
@Override
public @Nullable Connector findConnector(Point2D p, Figure prototype, double tolerance) {
return new PathConnector(new BoundsLocator(getLayoutBounds(), p));
}
@Override
public Bounds getLayoutBounds() {
Rectangle2D b = getNonNull(PATH).getBounds2D();
return new BoundingBox(b.getX(), b.getY(), b.getWidth(), b.getHeight());
}
@Override
public CssRectangle2D getCssLayoutBounds() {
return new CssRectangle2D(getLayoutBounds());
}
public int getNodeCount() {
throw new UnsupportedOperationException("Not supported yet."); //To change body ofCollection generated methods, choose Tools | Templates.
}
@Override
public PathIterator getPathIterator(RenderContext ctx, @Nullable AffineTransform tx) {
return new BezierPath(getStyledNonNull(PATH), getStyled(FILL_RULE)).getPathIterator(tx);
}
public Point2D getPoint(int index, int coord) {
throw new UnsupportedOperationException("Not supported yet."); //To change body ofCollection generated methods, choose Tools | Templates.
}
public Point2D getPointOnPath(float f, int i) {
throw new UnsupportedOperationException("Not supported yet."); //To change body ofCollection generated methods, choose Tools | Templates.
}
@Override
public String getTypeSelector() {
return TYPE_SELECTOR;
}
@Override
public void reshapeInLocal(CssSize x, CssSize y, CssSize width, CssSize height) {
reshapeInLocal(x.getConvertedValue(), y.getConvertedValue(), width.getConvertedValue(), height.getConvertedValue());
}
@Override
public void reshapeInLocal(double x, double y, double width, double height) {
reshapeInLocal(FXTransforms.createReshapeTransform(getLayoutBounds(), x, y, width, height));
}
@Override
public void reshapeInLocal(Transform transform) {
BezierPath newP = getNonNull(PATH);
for (int i = 0, n = newP.size(); i < n; i++) {
newP = newP.set(i, newP.get(i).transform(transform));
}
set(PATH, newP);
}
@Override
public void translateInLocal(CssPoint2D t) {
Transform transform = new Translate(t.getX().getConvertedValue(), t.getY().getConvertedValue());
reshapeInLocal(transform);
}
@Override
public void updateNode(RenderContext ctx, Node node) {
Path pathNode = (Path) node;
applyHideableFigureProperties(ctx, node);
applyStyleableFigureProperties(ctx, node);
applyStrokableFigureProperties(ctx, pathNode);
applyFillableFigureProperties(ctx, pathNode);
applyFillRulableFigureProperties(ctx, pathNode);
applyTransformableFigureProperties(ctx, node);
applyCompositableFigureProperties(ctx, pathNode);
pathNode.setFillRule(getStyled(FILL_RULE));
final List elements =
FXShapes.awtPathIteratorToFXPathElements(
new BezierPath(getStyledNonNull(PATH),
getStyledNonNull(FILL_RULE)).getPathIterator(null));
if (!pathNode.getElements().equals(elements)) {
pathNode.getElements().setAll(elements);
}
}
}