protected CubicPath[] getCubicPaths(ShapeCreationPanel scp) { CubicPath[] paths = (CubicPath[]) scp.getClientProperty(SHAPES_MIRROR); if (paths == null) { List<CubicPath> mirrorList = new ArrayList<CubicPath>(); Shape[] dataModel = scp.getDataModel().getShapes(); for (int a = 0; a < dataModel.length; a++) { CubicPath copy = new CubicPath(); copy.append(dataModel[a]); mirrorList.add(copy); } paths = mirrorList.toArray(new CubicPath[mirrorList.size()]); scp.putClientProperty(SHAPES_MIRROR, paths); refreshScaleFactor(scp); } return paths; }
/** @param mouseLoc the mouse location, relative to the panel (pre-transform) */ private Selection getSelection(ShapeCreationPanel scp, Point2D mouseLoc) { AffineTransform tx = scp.getTransform(); CubicPath[] paths = getCubicPaths(scp); Integer shapeIntersection = null; int r = scp.getHandleSize() / 2; Active active = scp.getHandlesActive(); for (int shapeIndex = paths.length - 1; shapeIndex >= 0; shapeIndex--) { if (active.supports(scp, shapeIndex)) { CubicPath path = paths[shapeIndex]; for (int nodeIndex = 0; nodeIndex < path.getNodeCount(); nodeIndex++) { Point2D p2 = path.getPrevControlForNode(nodeIndex, null); if (p2 != null) { tx.transform(p2, p2); if (hit(scp, mouseLoc, p2)) { return new Selection(shapeIndex, nodeIndex, Handle.PREVIOUS_CONTROL); } } p2 = path.getNode(nodeIndex, null); if (p2 != null) { tx.transform(p2, p2); if (hit(scp, mouseLoc, p2)) { return new Selection(shapeIndex, nodeIndex, Handle.PRIMARY); } } p2 = path.getNextControlForNode(nodeIndex, null); if (p2 != null) { tx.transform(p2, p2); if (hit(scp, mouseLoc, p2)) { return new Selection(shapeIndex, nodeIndex, Handle.NEXT_CONTROL); } } } if (shapeIntersection == null) { Shape outline = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND) .createStrokedShape(path); if (outline.intersects(mouseLoc.getX() - r, mouseLoc.getY() - r, 2 * r, 2 * r)) { shapeIntersection = shapeIndex; } } } } return getSelectedShape(scp, mouseLoc); }
@Override public void mousePressed(MouseEvent e) { ShapeCreationPanel scp = (ShapeCreationPanel) e.getComponent(); scp.requestFocus(); boolean isCreating = ShapeCreationPanel.MODE_CREATE.equals(scp.getMode()); if (e.getClickCount() > 1 && isCreating) { scp.setMode(ShapeCreationPanel.MODE_DEFAULT); return; } lastUntransformedX = e.getX(); lastUntransformedY = e.getY(); Point2D p = new Point2D.Double(e.getX(), e.getY()); try { scp.getTransform().createInverse().transform(p, p); } catch (NoninvertibleTransformException e2) { throw new RuntimeException(e2); } float x = (float) p.getX(); float y = (float) p.getY(); clickX = x; clickY = y; if (isCreating) { int selectedShape = scp.getSelectionModel().getSelection().getShapeIndex(); if (selectedShape == -1) { GeneralPath path = new GeneralPath(); path.moveTo(x, y); int newIndex = scp.getDataModel().addShape(path); scp.getSelectionModel().select(newIndex, 0, Handle.NEXT_CONTROL); } else { /** * We didn't give a next control point to the *last* node yet. Now we do. If the last * node in a path has a next control point: that path will be closed. */ CubicPath[] paths = getCubicPaths(scp); CubicPath path = paths[selectedShape]; int i = path.getNodeCount() - 1; Point2D lastPoint = path.getNode(i, null); Point2D lastPointCtrlPoint = path.getPrevControlForNode(i, null); if (lastPointCtrlPoint == null) lastPointCtrlPoint = lastPoint; double dx = lastPoint.getX() - lastPointCtrlPoint.getX(); double dy = lastPoint.getY() - lastPointCtrlPoint.getY(); path.setNextControlForNode( i, new Point2D.Double(lastPoint.getX() + dx, lastPoint.getY() + dy)); path.lineTo(x, y); changingDataModel.add(Thread.currentThread()); try { scp.getDataModel().setShape(selectedShape, path); } finally { changingDataModel.remove(Thread.currentThread()); } } } else { Selection selection = getSelection(scp, e.getPoint()); scp.getSelectionModel().select(selection); } }
@Override protected void paintControls(Graphics2D g, ShapeCreationPanel scp) { g = (Graphics2D) g.create(); Rectangle2D r = new Rectangle2D.Float(); Ellipse2D e = new Ellipse2D.Float(); Line2D line = new Line2D.Float(); double z = ((double) scp.getHandleSize()) / 2.0; AffineTransform tx = scp.getTransform(); try { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(Color.black); g.setStroke(new BasicStroke(1)); CubicPath[] paths = getCubicPaths(scp); Selection selection = scp.getSelectionModel().getSelection(); Selection indication = scp.getSelectionModel().getIndication(); for (int shapeIndex = 0; shapeIndex < paths.length; shapeIndex++) { if (scp.getHandlesActive().supports(scp, shapeIndex)) { CubicPath path = paths[shapeIndex]; if (path != null && path.isEmpty() == false) { for (int nodeIndex = 0; nodeIndex < path.getNodeCount(); nodeIndex++) { Point2D nodePoint = path.getNode(nodeIndex, null); nodePoint = tx.transform(nodePoint, null); Point2D p = path.getPrevControlForNode(nodeIndex, null); if (p != null) { p = tx.transform(p, null); g.setColor(Color.lightGray); line.setLine(nodePoint, p); g.draw(line); e.setFrame(p.getX() - z, p.getY() - z, 2 * z, 2 * z); if (selection.getShapeIndex() == shapeIndex && selection.getNodeIndex() == nodeIndex && Handle.PREVIOUS_CONTROL.equals(selection.getHandle())) { g.setColor(Color.black); } else if (indication.getShapeIndex() == shapeIndex && indication.getNodeIndex() == nodeIndex && Handle.PREVIOUS_CONTROL.equals(indication.getHandle())) { g.setColor(Color.gray); } else { g.setColor(Color.white); } g.fill(e); g.setColor(Color.black); g.draw(e); } p = path.getNextControlForNode(nodeIndex, null); if (p != null) { p = tx.transform(p, null); g.setColor(Color.lightGray); line.setLine(nodePoint, p); g.draw(line); e.setFrame(p.getX() - z, p.getY() - z, 2 * z, 2 * z); if (selection.getShapeIndex() == shapeIndex && selection.getNodeIndex() == nodeIndex && Handle.NEXT_CONTROL.equals(selection.getHandle())) { g.setColor(Color.black); } else if (indication.getShapeIndex() == shapeIndex && indication.getNodeIndex() == nodeIndex && Handle.NEXT_CONTROL.equals(indication.getHandle())) { } else { g.setColor(Color.white); } g.fill(e); g.setColor(Color.black); g.draw(e); } r.setFrame(nodePoint.getX() - z, nodePoint.getY() - z, 2 * z, 2 * z); if (selection.getShapeIndex() == shapeIndex && selection.getNodeIndex() == nodeIndex && Handle.PRIMARY.equals(selection.getHandle())) { g.setColor(Color.black); } else if (indication.getShapeIndex() == shapeIndex && indication.getNodeIndex() == nodeIndex && Handle.PRIMARY.equals(indication.getHandle())) { g.setColor(Color.gray); } else { g.setColor(Color.white); } g.fill(r); g.setColor(Color.black); g.draw(r); } } } } } finally { g.dispose(); } }
protected void refreshScaleFactor(ShapeCreationPanel scp) { CubicPath[] paths = getCubicPaths(scp); for (CubicPath path : paths) { path.setScaleFactor(getScaleFactor(scp)); } }
@Override public void mouseDragged(MouseEvent e) { try { if (e.getClickCount() > 1) return; ShapeCreationPanel scp = (ShapeCreationPanel) e.getComponent(); boolean isCreating = ShapeCreationPanel.MODE_CREATE.equals(scp.getMode()); CubicPath[] paths = getCubicPaths(scp); int i = scp.getSelectionModel().getSelection().getShapeIndex(); CubicPath path = i == -1 ? null : paths[i]; Point2D p = new Point2D.Double(e.getX(), e.getY()); try { scp.getTransform().createInverse().transform(p, p); } catch (NoninvertibleTransformException e2) { throw new RuntimeException(e2); } float x = (float) p.getX(); float y = (float) p.getY(); boolean replacePath = true; if (isCreating) { int nodeIndex = path.getNodeCount() - 1; float dx = x - clickX; float dy = y - clickY; path.setPrevControlForNode(nodeIndex, clickX - dx, clickY - dy); } else { Selection s = scp.getSelectionModel().getSelection(); int nodeIndex = s.getNodeIndex(); if (nodeIndex != -1) { if (Handle.PREVIOUS_CONTROL.equals(s.getHandle())) { path.setPrevControlForNode(nodeIndex, new Point2D.Double(x, y)); if (Constraint.ANGLE_ONLY.equals(getConstraint(scp))) { path.setNextControlForNodeFromPrev(nodeIndex, false); } else if (Constraint.ANGLE_AND_DISTANCE.equals(getConstraint(scp))) { path.setNextControlForNodeFromPrev(nodeIndex, true); } } else if (Handle.PRIMARY.equals(s.getHandle())) { path.setNode(nodeIndex, new Point2D.Double(x, y), true); } else { // next control: path.setNextControlForNode(nodeIndex, new Point2D.Double(x, y)); if (Constraint.ANGLE_ONLY.equals(getConstraint(scp))) { path.setPrevControlForNodeFromNext(nodeIndex, false); } else if (Constraint.ANGLE_AND_DISTANCE.equals(getConstraint(scp))) { path.setPrevControlForNodeFromNext(nodeIndex, true); } } } else { float dx = e.getX() - lastUntransformedX; float dy = e.getY() - lastUntransformedY; nudge(scp, dx, dy); replacePath = false; } } if (i >= 0 && replacePath) { changingDataModel.add(Thread.currentThread()); try { scp.getDataModel().setShape(i, path); } finally { changingDataModel.remove(Thread.currentThread()); } } } finally { lastUntransformedX = e.getX(); lastUntransformedY = e.getY(); } }