/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
* LaTeXDraw is distributed without any warranty; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package net.sf.latexdraw.view.jfx;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.PathElement;
import net.sf.latexdraw.models.interfaces.shape.IBezierCurve;
import net.sf.latexdraw.models.interfaces.shape.IPoint;
import org.eclipse.jdt.annotation.NonNull;
/**
* The JFX shape view for Bézier curves.
* @author Arnaud Blouin
*/
public class ViewBezierCurve extends ViewPathShape<IBezierCurve> {
final MoveTo moveTo;
final List<CubicCurveTo> curvesTo;
final Group showPoint;
/**
* Creates the view.
* @param sh The model.
*/
ViewBezierCurve(final @NonNull IBezierCurve sh) {
super(sh);
ObservableList<PathElement> elts = border.getElements();
showPoint = new Group();
moveTo = ViewFactory.INSTANCE.createMoveTo(0d, 0d);
moveTo.xProperty().bind(sh.getPtAt(0).xProperty());
moveTo.yProperty().bind(sh.getPtAt(0).yProperty());
elts.add(moveTo);
curvesTo = new ArrayList<>();
addCurveTo(sh.getPtAt(1), model.getFirstCtrlPtAt(1), model.getFirstCtrlPtAt(1));
IntStream.range(2, sh.getNbPoints()).forEach(index ->
addCurveTo(sh.getPtAt(index), model.getSecondCtrlPtAt(index-1), model.getFirstCtrlPtAt(index)));
model.getPoints().addListener((ListChangeListener.Change<? extends IPoint> c) -> {
while(c.next()) {
if(c.wasAdded()) {
c.getAddedSubList().forEach(pt -> {
addCurveTo(pt, model.getSecondCtrlPtAt(model.getNbPoints()-2), model.getFirstCtrlPtAt(model.getNbPoints()-1));
});
}
}
});
}
private void addCurveTo(final IPoint pt, final IPoint ctrl1, final IPoint ctrl2) {
CubicCurveTo curveto = ViewFactory.INSTANCE.createCubicCurveTo(0d, 0d, 0d, 0d, 0d, 0d);
curveto.xProperty().bind(pt.xProperty());
curveto.yProperty().bind(pt.yProperty());
curveto.controlX1Property().bind(ctrl1.xProperty());
curveto.controlY1Property().bind(ctrl1.yProperty());
curveto.controlX2Property().bind(ctrl2.xProperty());
curveto.controlY2Property().bind(ctrl2.yProperty());
curvesTo.add(curveto);
border.getElements().add(curveto);
}
@Override
public void flush() {
moveTo.xProperty().unbind();
moveTo.yProperty().unbind();
curvesTo.forEach(to -> {
to.xProperty().unbind();
to.yProperty().unbind();
to.controlX1Property().unbind();
to.controlX2Property().unbind();
to.controlY1Property().unbind();
to.controlY2Property().unbind();
});
curvesTo.clear();
super.flush();
}
// @Override
// protected void setPath(final boolean close) {
// if(shape.getNbPoints()<2) return ;
//
// final List<IPoint> pts = shape.getPoints();
// final List<IPoint> ctrlPts1 = shape.getFirstCtrlPts();
// final List<IPoint> ctrlPts2 = shape.getSecondCtrlPts();
// IPoint ctrl1;
// final int size;
// final double[] coords = updatePoint4Arrows(pts.get(0).getX(), pts.get(0).getY(), shape.getArrowAt(0));
// final double[] coords2;
// if(pts.size()==2)
// // In this case the first curve contains the first and last points that must be modified.
// coords2 = updatePoint4Arrows(pts.get(1).getX(),pts.get(1).getY(), shape.getArrowAt(-1));
// else coords2 = new double[]{pts.get(1).getX(),pts.get(1).getY()};
//
// path.reset();
// path.moveTo(coords[0], coords[1]);
// path.curveTo(ctrlPts1.get(0).getX(), ctrlPts1.get(0).getY(),
// ctrlPts1.get(1).getX(), ctrlPts1.get(1).getY(),
// coords2[0], coords2[1]);
//
// if(shape.isClosed())
// size = pts.size();
// else size = pts.size()-1;
//
// for(int i=2; i<size; i++) {
// ctrl1 = ctrlPts2.get(i-1);
// path.curveTo(ctrl1.getX(), ctrl1.getY(),
// ctrlPts1.get(i).getX(), ctrlPts1.get(i).getY(),
// pts.get(i).getX(), pts.get(i).getY());
// }
//
// if(shape.isClosed()) {
// final IPoint ctrl1b = ctrlPts1.get(0).centralSymmetry(pts.get(0));
// final IPoint ctrl2b = ctrlPts1.get(ctrlPts1.size()-1).centralSymmetry(pts.get(pts.size()-1));
// path.curveTo(ctrl2b.getX(), ctrl2b.getY(), ctrl1b.getX(), ctrl1b.getY(), pts.get(0).getX(), pts.get(0).getY());
// path.closePath();
// }else {
// if(pts.size()>2) {
// ctrl1 = ctrlPts2.get(size-1);
// path.curveTo(ctrl1.getX(), ctrl1.getY(), ctrlPts1.get(size).getX(), ctrlPts1.get(size).getY(), pts.get(size).getX(), pts.get(size).getY());
// }
// }
// }
// @Override
// public void paintShowPointsDots(final Graphics2D g) {
// final boolean isClosed = shape.isClosed();
// final IArrow arr1 = shape.getArrowAt(0);
// final boolean arrow1Drawable = arr1.hasStyle() && shape.getNbPoints()>1;
// final boolean arrow2Drawable = shape.getArrowAt(-1).hasStyle() && shape.getNbPoints()>1 && !isClosed;
// final int size = shape.getNbPoints();
// final List<IPoint> pts = shape.getPoints();
// final List<IPoint> ctrlPts1 = shape.getFirstCtrlPts();
// final List<IPoint> ctrlPts2 = shape.getSecondCtrlPts();
// final double width = arr1.getDotSizeDim() + arr1.getDotSizeNum()*shape.getThickness();
// final Ellipse2D.Double d = new Ellipse2D.Double(0, 0, width, width);
// int i;
//
// g.setColor(shape.getLineColour());
//
// if(!arrow1Drawable || isClosed)
// fillCircle(d, pts.get(0), width, g);
//
// if(!arrow2Drawable || isClosed)
// fillCircle(d, pts.get(size-1), width, g);
//
// for(i=1; i<size-1; i++) {
// fillCircle(d, pts.get(i), width, g);
// fillCircle(d, ctrlPts2.get(i), width, g);
// }
//
// for(i=0; i<size; i++)
// fillCircle(d, ctrlPts1.get(i), width, g);
//
// if(shape.isClosed()) {
// fillCircle(d, ctrlPts2.get(ctrlPts2.size()-1), width, g);
// fillCircle(d, ctrlPts2.get(0), width, g);
// }
// }
//
//
//
// private void fillCircle(final Ellipse2D ell, final IPoint pt, final double width, final Graphics2D g) {
// ell.setFrame(pt.getX()-width/2., pt.getY()-width/2., width, width);
// g.fill(ell);
// }
//
//
//
// private void paintLine(final Line2D line, final IPoint pt1, final IPoint pt2, final Graphics2D g) {
// line.setLine(pt1.getX(), pt1.getY(), pt2.getX(), pt2.getY());
// g.draw(line);
// }
//
//
// @Override
// public void paintShowPointsLines(final Graphics2D g) {
// final int size = shape.getNbPoints();
// final List<IPoint> pts = shape.getPoints();
// final List<IPoint> ctrlPts1 = shape.getFirstCtrlPts();
// final List<IPoint> ctrlPts2 = shape.getSecondCtrlPts();
// final float thick = (float)(shape.hasDbleBord()? shape.getDbleBordSep()+shape.getThickness()*2. : shape.getThickness());
// final Line2D.Double line = new Line2D.Double();
// int i;
//
// g.setStroke(new BasicStroke(thick/2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
// 1.f, new float[]{(float)shape.getDashSepBlack(), (float)shape.getDashSepWhite()}, 0));
// g.setColor(shape.getLineColour());
//
// for(i=3; i<size; i+=2) {
// paintLine(line, pts.get(i-1), ctrlPts2.get(i-1), g);
// paintLine(line, ctrlPts2.get(i-1), ctrlPts1.get(i), g);
// paintLine(line, ctrlPts1.get(i), pts.get(i), g);
// }
//
// for(i=2; i<size; i+=2) {
// paintLine(line, pts.get(i-1), ctrlPts2.get(i-1), g);
// paintLine(line, ctrlPts2.get(i-1), ctrlPts1.get(i), g);
// paintLine(line, ctrlPts1.get(i), pts.get(i), g);
// }
//
// if(shape.isClosed()) {
// paintLine(line, pts.get(size-1), ctrlPts2.get(size-1), g);
// paintLine(line, ctrlPts2.get(size-1), ctrlPts2.get(0), g);
// paintLine(line, ctrlPts2.get(0), pts.get(0), g);
// }
//
// paintLine(line, pts.get(0), ctrlPts1.get(0), g);
// paintLine(line, ctrlPts1.get(0), ctrlPts1.get(1), g);
// paintLine(line, ctrlPts1.get(1), pts.get(1), g);
// }
//
//
// protected static double[] updatePoint4Arrows(final double x, final double y, final IArrow arr) {
// final double[] coords = {x, y};
//
// if(arr.getArrowStyle().isReducingShape()) {
// final ILine line = arr.getArrowLine();
//
// if(line!=null) {
// final IPoint[] ps = line.findPoints(line.getPoint1(), arr.getArrowShapeLength()/2.);
// if(ps!=null) {
// if(line.isInSegment(ps[0])) {
// coords[0] = ps[0].getX();
// coords[1] = ps[0].getY();
// }else {
// coords[0] = ps[1].getX();
// coords[1] = ps[1].getY();
// }
// }
// }
// }
// return coords;
// }
}