Index: graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java =================================================================== RCS file: /cvs/graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java,v retrieving revision 1.71 diff -u -r1.71 RunDialog.java --- graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java 8 Jun 2007 08:44:57 -0000 1.71 +++ graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java 13 Jun 2007 13:35:44 -0000 @@ -108,6 +108,7 @@ "test.vmd.VMDCollisionTest", "test.vmd.VMDTest", "test.widget.AnimatedImageTest", + "test.widget.ConnectionWidgetCutDistanceTest", "test.zoom.FitToViewTest", }; Index: graph/examples/src/test/widget/ConnectionWidgetCutDistanceTest.java =================================================================== RCS file: graph/examples/src/test/widget/ConnectionWidgetCutDistanceTest.java diff -N graph/examples/src/test/widget/ConnectionWidgetCutDistanceTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ graph/examples/src/test/widget/ConnectionWidgetCutDistanceTest.java 13 Jun 2007 13:35:44 -0000 @@ -0,0 +1,67 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package test.widget; + +import org.netbeans.api.visual.anchor.AnchorFactory; +import org.netbeans.api.visual.router.RouterFactory; +import org.netbeans.api.visual.widget.ConnectionWidget; +import org.netbeans.api.visual.widget.Scene; +import org.netbeans.api.visual.widget.LabelWidget; +import org.netbeans.api.visual.layout.LayoutFactory; +import test.SceneSupport; + +import java.awt.*; + +/** + * @author David Kaspar + */ +public class ConnectionWidgetCutDistanceTest { + + public static void main (String[] args) { + Scene scene = new Scene (); + + ConnectionWidget conn1 = new ConnectionWidget (scene); + conn1.setControlPointCutDistance (8); + conn1.setRouter (RouterFactory.createOrthogonalSearchRouter ()); + conn1.setSourceAnchor (AnchorFactory.createFixedAnchor (new Point (50, 50))); + conn1.setTargetAnchor (AnchorFactory.createFixedAnchor (new Point (450, 150))); + conn1.getActions ().addAction (scene.createWidgetHoverAction ()); + scene.addChild (conn1); + + LabelWidget label1 = new LabelWidget (scene, "Control Point Cut Distance = 8"); + conn1.addChild (label1); + conn1.setConstraint (label1, LayoutFactory.ConnectionWidgetLayoutAlignment.BOTTOM_RIGHT, 0); + + ConnectionWidget conn2 = new ConnectionWidget (scene); + conn2.setControlPointCutDistance (0); + conn2.setRouter (RouterFactory.createOrthogonalSearchRouter ()); + conn2.setSourceAnchor (AnchorFactory.createFixedAnchor (new Point (50, 250))); + conn2.setTargetAnchor (AnchorFactory.createFixedAnchor (new Point (450, 350))); + conn2.getActions ().addAction (scene.createWidgetHoverAction ()); + scene.addChild (conn2); + + LabelWidget label2 = new LabelWidget (scene, "Control Point Cut Distance = 0"); + conn2.addChild (label2); + conn2.setConstraint (label2, LayoutFactory.ConnectionWidgetLayoutAlignment.BOTTOM_RIGHT, 0); + + SceneSupport.show (scene); + } + +} Index: graph/lib/apichanges.xml =================================================================== RCS file: /cvs/graph/lib/apichanges.xml,v retrieving revision 1.21 diff -u -r1.21 apichanges.xml --- graph/lib/apichanges.xml 8 Jun 2007 08:45:00 -0000 1.21 +++ graph/lib/apichanges.xml 13 Jun 2007 13:35:44 -0000 @@ -299,6 +299,22 @@ + + + + ConnectionWidget.controlPointCutDistance property introduced to render smoother corners of the path + + + + + + ConnectionWidget.controlPointCutDistance property allows you to specify a distance where the path should be cut + at each control point. + See test.widget.ConnectionWidgetCutDistanceTest for example. + + + + Index: graph/lib/src/org/netbeans/api/visual/widget/ConnectionWidget.java =================================================================== RCS file: /cvs/graph/lib/src/org/netbeans/api/visual/widget/ConnectionWidget.java,v retrieving revision 1.38 diff -u -r1.38 ConnectionWidget.java --- graph/lib/src/org/netbeans/api/visual/widget/ConnectionWidget.java 5 Jun 2007 08:41:01 -0000 1.38 +++ graph/lib/src/org/netbeans/api/visual/widget/ConnectionWidget.java 13 Jun 2007 13:35:44 -0000 @@ -76,6 +76,7 @@ private boolean paintControlPoints; private Color lineColor; private Cursor controlPointsCursor; + private int controlPointCutDistance; private Anchor.Entry sourceEntry; private Anchor.Entry targetEntry; @@ -96,6 +97,7 @@ setLayout (connectionWidgetLayout); stroke = STROKE_DEFAULT; paintControlPoints = false; + controlPointCutDistance = 0; sourceEntry = new ConnectionEntry (true); targetEntry = new ConnectionEntry (false); } @@ -182,6 +184,26 @@ } /** + * Returns the cut distance at control points. + * @return the cut distance + * @since 2.5 + */ + public int getControlPointCutDistance () { + return controlPointCutDistance; + } + + /** + * Sets the cut distance at control points. + * @param controlPointCutDistance if positive number, then the path is cut to render smooth corners; + * otherwise the path is rendered using control points only + * @since 2.5 + */ + public void setControlPointCutDistance (int controlPointCutDistance) { + this.controlPointCutDistance = controlPointCutDistance; + repaint (); + } + + /** * Returns a source anchor of the connection widget. * @return the source anchor */ @@ -648,14 +670,55 @@ points = controlPoints; } - - for (Point point : points) { - if (path == null) { - path = new GeneralPath (); - path.moveTo (point.x, point.y); - } else { - path.lineTo (point.x, point.y); + if (controlPointCutDistance > 0) { + for (int a = 0; a < points.size () - 1; a ++) { + Point p1 = points.get (a); + Point p2 = points.get (a + 1); + double len = p1.distance (p2); + + if (a > 0) { + Point p0 = points.get (a - 1); + double ll = p0.distance (p1); + if (len < ll) + ll = len; + ll /= 2; + double cll = controlPointCutDistance; + if (cll > ll) + cll = ll; + double direction = Math.atan2 (p2.y - p1.y, p2.x - p1.x); + if (!Double.isNaN (direction)) { + path = addToPath (path, + p1.x + (int) (cll * Math.cos (direction)), + p1.y + (int) (cll * Math.sin (direction)) + ); + } + } else { + path = addToPath (path, p1.x, p1.y); + } + + if (a < points.size () - 2) { + Point p3 = points.get (a + 2); + double ll = p2.distance (p3); + if (len < ll) + ll = len; + ll /= 2; + double cll = controlPointCutDistance; + if (cll > ll) + cll = ll; + double direction = Math.atan2 (p2.y - p1.y, p2.x - p1.x); + if (!Double.isNaN (direction)) { + path = addToPath (path, + p2.x - (int) (cll * Math.cos (direction)), + p2.y - (int) (cll * Math.sin (direction)) + ); + } + } else { + path = addToPath (path, p2.x, p2.y); + } } + } else { + for (Point point : points) + path = addToPath (path, point.x, point.y); } if (path != null) { Stroke previousStroke = gr.getStroke (); @@ -699,6 +762,16 @@ gr.setTransform (previousTransform); } } + } + + private GeneralPath addToPath (GeneralPath path, int x, int y) { + if (path == null) { + path = new GeneralPath (); + path.moveTo (x, y); + } else { + path.lineTo (x, y); + } + return path; } private class ConnectionEntry implements Anchor.Entry { Index: graph/lib/src/org/netbeans/api/visual/widget/doc-files/documentation.html =================================================================== RCS file: /cvs/graph/lib/src/org/netbeans/api/visual/widget/doc-files/documentation.html,v retrieving revision 1.17 diff -u -r1.17 documentation.html --- graph/lib/src/org/netbeans/api/visual/widget/doc-files/documentation.html 8 Jun 2007 08:45:02 -0000 1.17 +++ graph/lib/src/org/netbeans/api/visual/widget/doc-files/documentation.html 13 Jun 2007 13:35:45 -0000 @@ -1145,6 +1145,9 @@

There is a controlPointsCursor property which defines a mouse cursor when the mouse is over a visible control point. +

+There is a controlPointCutDistance property. If set to positive number (by default 0), then the connection path is cut at each control point to make smoother corners. The smooth corners are not used during calculation whether a mouse-cursor hits the path. +

Router

@@ -1198,6 +1201,9 @@ getEndPointShape
setEndPointShape Controls a shape of end points (source and target). Shape is defined by PointShape interface. The end points are painted only if isPaintControlPoints returns true. + +getControlPointCutDistance
setControlPointCutDistance +Controls a cut distance where the line cut with half-angle line at every control point. See test.widget.ConnectionWidgetCutDistanceTest example. getRouter
setRouter Controls a router assigned to the connection widget. The routers is calculating a path and sets a new one using setControlPoints method. Index: graph/www/documentation.html =================================================================== RCS file: /cvs/graph/www/documentation.html,v retrieving revision 1.91 diff -u -r1.91 documentation.html --- graph/www/documentation.html 8 Jun 2007 08:45:03 -0000 1.91 +++ graph/www/documentation.html 13 Jun 2007 13:35:45 -0000 @@ -179,6 +179,7 @@

  • test.vmd.VMDCollisionTest - test of WidgetCollisionCollector
  • test.vmd.VMDTest - how to use VMD plug-in
  • test.widget.AnimatedImageTest - test of animated image in ImageWidget +
  • test.widget.ConnectionWidgetCutDistanceTest - how to use control point cut distance in ConnectionWidget
  • test.zoom.CenteredZoomTest - how to use CenteredZoomAction
  • test.zoom.FitToViewTest - how to implement fit-to-view feature
  • test.zoom.MouseCenteredZoomTest - how to use MouseCenteredZoomAction