/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.core.ui.model.graphic.imp.line; import java.awt.Shape; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.util.Optional; import javax.swing.Icon; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.weasis.core.api.gui.util.GeomUtil; import org.weasis.core.ui.model.graphic.AbstractDragGraphic; import org.weasis.core.ui.model.graphic.Graphic; import org.weasis.core.ui.model.utils.exceptions.InvalidShapeException; import org.weasis.core.ui.serialize.PointAdapter; import org.weasis.core.ui.util.MouseEventDouble; @XmlType(name = "lineWithGap") @XmlRootElement(name = "lineWithGap") public class LineWithGapGraphic extends AbstractDragGraphic { private static final long serialVersionUID = -9185126249920077267L; public static final Integer POINTS_NUMBER = 2; public static final Integer DEFAULT_GAP_SIZE = 0; protected Integer gapSize = DEFAULT_GAP_SIZE; // Let AB be a simple a line segment protected Point2D.Double ptA; protected Point2D.Double ptB; protected Point2D centerGap; // estimate if line segment is valid or not protected Boolean lineABvalid; public LineWithGapGraphic() { super(POINTS_NUMBER); } public LineWithGapGraphic(LineWithGapGraphic graphic) { super(graphic); } @Override public LineWithGapGraphic copy() { return new LineWithGapGraphic(this); } @Override protected void initCopy(Graphic graphic) { super.initCopy(graphic); this.gapSize = ((LineWithGapGraphic) graphic).gapSize; } @Override protected void prepareShape() throws InvalidShapeException { if (!isShapeValid()) { throw new InvalidShapeException("This shape cannot be drawn"); //$NON-NLS-1$ } buildShape(null); } @Override public boolean isShapeValid() { updateTool(); return super.isShapeValid(); } @XmlElement(name = "centerGap", required = false) @XmlJavaTypeAdapter(PointAdapter.Point2DAdapter.class) public Point2D getCenterGap() { return centerGap; } public void setCenterGap(Point2D centerGap) { this.centerGap = centerGap; } @XmlAttribute(name = "gapSize") public Integer getGapSize() { return gapSize; } public void setGapSize(Integer gapSize) { this.gapSize = Optional.ofNullable(gapSize).orElse(DEFAULT_GAP_SIZE); } protected void setHandlePointList(Point2D.Double ptStart, Point2D.Double ptEnd) { setHandlePoint(0, ptStart == null ? null : (Point2D.Double) ptStart.clone()); setHandlePoint(1, ptEnd == null ? null : (Point2D.Double) ptEnd.clone()); buildShape(null); } @Override public Icon getIcon() { return LineGraphic.ICON; } @Override public String getUIName() { return ""; //$NON-NLS-1$ } @Override public void buildShape(MouseEventDouble mouseEvent) { updateTool(); Shape newShape = null; if (lineABvalid) { if (centerGap == null) { centerGap = GeomUtil.getColinearPointWithRatio(ptA, ptB, 0.5); } double dist = ptA.distance(ptB); double distCenterGap = ptA.distance(centerGap); double distCenterB = ptB.distance(centerGap); Point2D ptap = null; Point2D ptbp = null; if (distCenterGap < dist && distCenterB < dist) { double distGap = 0.5 * gapSize / dist; ptap = GeomUtil.getColinearPointWithRatio(ptA, ptB, distCenterGap / dist - distGap); ptbp = GeomUtil.getColinearPointWithRatio(ptA, ptB, distCenterGap / dist + distGap); } Path2D path = new Path2D.Double(Path2D.WIND_NON_ZERO, 4); path.moveTo(ptA.getX(), ptA.getY()); if (ptap != null) { path.lineTo(ptap.getX(), ptap.getY()); path.moveTo(ptbp.getX(), ptbp.getY()); } path.lineTo(ptB.getX(), ptB.getY()); newShape = path; } setShape(newShape, mouseEvent); updateLabel(mouseEvent, getDefaultView2d(mouseEvent)); } protected void updateTool() { ptA = getHandlePoint(0); ptB = getHandlePoint(1); lineABvalid = ptA != null && ptB != null && !ptB.equals(ptA); } public Point2D getStartPoint() { updateTool(); return ptA == null ? null : (Point2D) ptA.clone(); } public Point2D getEndPoint() { updateTool(); return ptB == null ? null : (Point2D) ptB.clone(); } }