This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 113573
Collapse All | Expand All

(-)graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java (+2 lines)
Lines 102-107 Link Here
102
        "test.resize.ResizeTest",
102
        "test.resize.ResizeTest",
103
        "test.router.OSRCollisionsCollectorTest",
103
        "test.router.OSRCollisionsCollectorTest",
104
        "test.router.OSRComputeControlPointsTest",
104
        "test.router.OSRComputeControlPointsTest",
105
        "test.routing.ActionsWithRoutingPolicyTest",
106
        "test.routing.RoutingPolicyTest",
105
        "test.sceneresize.LimitedSceneTest",
107
        "test.sceneresize.LimitedSceneTest",
106
        "test.sceneresize.SceneResizeTest",
108
        "test.sceneresize.SceneResizeTest",
107
        "test.scroll.ScrollTest",
109
        "test.scroll.ScrollTest",
(-)graph/examples/src/test/routing/ActionsWithRoutingPolicyTest.java (+103 lines)
Added Link Here
1
/*
2
 * The contents of this file are subject to the terms of the Common Development
3
 * and Distribution License (the License). You may not use this file except in
4
 * compliance with the License.
5
 *
6
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7
 * or http://www.netbeans.org/cddl.txt.
8
 *
9
 * When distributing Covered Code, include this CDDL Header Notice in each file
10
 * and include the License file at http://www.netbeans.org/cddl.txt.
11
 * If applicable, add the following below the CDDL Header, with the fields
12
 * enclosed by brackets [] replaced by your own identifying information:
13
 * "Portions Copyrighted [year] [name of copyright owner]"
14
 *
15
 * The Original Software is NetBeans. The Initial Developer of the Original
16
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17
 * Microsystems, Inc. All Rights Reserved.
18
 */
19
20
package test.routing;
21
22
import org.netbeans.api.visual.action.ActionFactory;
23
import org.netbeans.api.visual.anchor.AnchorFactory;
24
import org.netbeans.api.visual.anchor.AnchorShape;
25
import org.netbeans.api.visual.anchor.PointShape;
26
import org.netbeans.api.visual.border.BorderFactory;
27
import org.netbeans.api.visual.router.RouterFactory;
28
import org.netbeans.api.visual.widget.*;
29
import test.SceneSupport;
30
31
import javax.swing.*;
32
import java.awt.*;
33
import java.awt.event.ActionEvent;
34
35
/**
36
 * @author David Kaspar
37
 */
38
public class ActionsWithRoutingPolicyTest extends Scene {
39
40
    private LayerWidget mainLayer;
41
    private ConnectionWidget connection;
42
43
    public ActionsWithRoutingPolicyTest () {
44
        mainLayer = new LayerWidget (this);
45
        addChild (mainLayer);
46
        LayerWidget connLayer = new LayerWidget (this);
47
        addChild (connLayer);
48
49
        Widget source = createLabel ("Source", 50, 200, Color.GREEN);
50
        Widget target = createLabel ("Target", 450, 200, Color.GREEN);
51
52
        connection = new ConnectionWidget (this);
53
        connection.setSourceAnchor (AnchorFactory.createDirectionalAnchor (source, AnchorFactory.DirectionalAnchorKind.HORIZONTAL));
54
        connection.setTargetAnchor (AnchorFactory.createDirectionalAnchor (target, AnchorFactory.DirectionalAnchorKind.HORIZONTAL));
55
        connection.setTargetAnchorShape (AnchorShape.TRIANGLE_FILLED);
56
        connection.setPaintControlPoints (true);
57
        connection.setControlPointShape (PointShape.SQUARE_FILLED_BIG);
58
        connection.setRouter (RouterFactory.createOrthogonalSearchRouter (mainLayer));
59
        connection.getActions ().addAction (ActionFactory.createAddRemoveControlPointAction (1.0, 5.0, ConnectionWidget.RoutingPolicy.UPDATE_END_POINTS_ONLY));
60
        connection.getActions ().addAction (ActionFactory.createMoveControlPointAction (ActionFactory.createFreeMoveControlPointProvider (), ConnectionWidget.RoutingPolicy.UPDATE_END_POINTS_ONLY));
61
        connLayer.addChild (connection);
62
    }
63
64
    private Widget createLabel (String text, int x, int y, Color color) {
65
        LabelWidget label = new LabelWidget (this, text);
66
        label.setOpaque (true);
67
        label.setBackground (color);
68
        label.setBorder (BorderFactory.createLineBorder (5));
69
        label.setPreferredLocation (new Point (x, y));
70
        label.getActions ().addAction (ActionFactory.createMoveAction ());
71
        mainLayer.addChild (label);
72
        return label;
73
    }
74
75
    private JComponent createPanel () {
76
        JPanel panel = new JPanel ();
77
        panel.setLayout (new BorderLayout ());
78
79
        JToolBar bar = new JToolBar ();
80
        bar.add (new AbstractAction("Force Rerouting") {
81
            public void actionPerformed (ActionEvent e) {
82
                connection.reroute ();
83
                validate ();
84
            }
85
        });
86
        bar.addSeparator ();
87
        bar.add (new AbstractAction("Reset routing policy to always-route") {
88
            public void actionPerformed (ActionEvent e) {
89
                connection.setRoutingPolicy (ConnectionWidget.RoutingPolicy.ALWAYS_ROUTE);
90
                validate ();
91
            }
92
        });
93
        panel.add (bar, BorderLayout.NORTH);
94
95
        panel.add (createView (), BorderLayout.CENTER);
96
        return panel;
97
    }
98
99
    public static void main (String[] args) {
100
        SceneSupport.show (new ActionsWithRoutingPolicyTest ().createPanel ());
101
    }
102
103
}
(-)graph/examples/src/test/routing/RoutingPolicyTest.java (+130 lines)
Added Link Here
1
/*
2
 * The contents of this file are subject to the terms of the Common Development
3
 * and Distribution License (the License). You may not use this file except in
4
 * compliance with the License.
5
 *
6
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7
 * or http://www.netbeans.org/cddl.txt.
8
 *
9
 * When distributing Covered Code, include this CDDL Header Notice in each file
10
 * and include the License file at http://www.netbeans.org/cddl.txt.
11
 * If applicable, add the following below the CDDL Header, with the fields
12
 * enclosed by brackets [] replaced by your own identifying information:
13
 * "Portions Copyrighted [year] [name of copyright owner]"
14
 *
15
 * The Original Software is NetBeans. The Initial Developer of the Original
16
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17
 * Microsystems, Inc. All Rights Reserved.
18
 */
19
20
package test.routing;
21
22
import org.netbeans.api.visual.action.ActionFactory;
23
import org.netbeans.api.visual.anchor.AnchorFactory;
24
import org.netbeans.api.visual.anchor.AnchorShape;
25
import org.netbeans.api.visual.anchor.PointShape;
26
import org.netbeans.api.visual.border.BorderFactory;
27
import org.netbeans.api.visual.router.RouterFactory;
28
import org.netbeans.api.visual.widget.*;
29
import test.SceneSupport;
30
31
import javax.swing.*;
32
import java.awt.*;
33
import java.awt.event.ActionEvent;
34
35
/**
36
 * @author David Kaspar
37
 */
38
public class RoutingPolicyTest extends Scene {
39
40
    private LayerWidget mainLayer;
41
    private ConnectionWidget connection;
42
43
    public RoutingPolicyTest () {
44
        mainLayer = new LayerWidget (this);
45
        addChild (mainLayer);
46
        LayerWidget connLayer = new LayerWidget (this);
47
        addChild (connLayer);
48
49
        createLabel ("Buttons in toolbar", 200, 100, Color.YELLOW);
50
        createLabel ("allows you to switch", 200, 130, Color.YELLOW);
51
        createLabel ("routing policy of the connection widget.", 200, 160, Color.YELLOW);
52
53
        createLabel ("Try double-clicking on the connection widget.", 200, 250, Color.CYAN);
54
        createLabel ("Try dragging control points of the connection widget.", 200, 280, Color.CYAN);
55
        createLabel ("Try force re-routing of the connection widget.", 200, 310, Color.CYAN);
56
57
        Widget source = createLabel ("Source", 50, 200, Color.GREEN);
58
        Widget target = createLabel ("Target", 450, 200, Color.GREEN);
59
60
        connection = new ConnectionWidget (this);
61
        connection.setSourceAnchor (AnchorFactory.createDirectionalAnchor (source, AnchorFactory.DirectionalAnchorKind.HORIZONTAL));
62
        connection.setTargetAnchor (AnchorFactory.createDirectionalAnchor (target, AnchorFactory.DirectionalAnchorKind.HORIZONTAL));
63
        connection.setTargetAnchorShape (AnchorShape.TRIANGLE_FILLED);
64
        connection.setPaintControlPoints (true);
65
        connection.setControlPointShape (PointShape.SQUARE_FILLED_BIG);
66
        connection.setRouter (RouterFactory.createOrthogonalSearchRouter (mainLayer));
67
        connection.getActions ().addAction (ActionFactory.createAddRemoveControlPointAction ());
68
        connection.getActions ().addAction (ActionFactory.createFreeMoveControlPointAction ());
69
        connLayer.addChild (connection);
70
    }
71
72
    private Widget createLabel (String text, int x, int y, Color color) {
73
        LabelWidget label = new LabelWidget (this, text);
74
        label.setOpaque (true);
75
        label.setBackground (color);
76
        label.setBorder (BorderFactory.createLineBorder (5));
77
        label.setPreferredLocation (new Point (x, y));
78
        label.getActions ().addAction (ActionFactory.createMoveAction ());
79
        mainLayer.addChild (label);
80
        return label;
81
    }
82
83
    private JComponent createPanel () {
84
        JPanel panel = new JPanel ();
85
        panel.setLayout (new BorderLayout ());
86
87
        JToolBar bar = new JToolBar ();
88
        bar.add (new AbstractAction("Force Rerouting") {
89
            public void actionPerformed (ActionEvent e) {
90
                connection.reroute ();
91
                validate ();
92
            }
93
        });
94
        bar.addSeparator ();
95
        bar.add (new JLabel ("Switch routing policy:"));
96
        bar.add (new AbstractAction("Always Route") {
97
            public void actionPerformed (ActionEvent e) {
98
                connection.setRoutingPolicy (ConnectionWidget.RoutingPolicy.ALWAYS_ROUTE);
99
                validate ();
100
            }
101
        });
102
        bar.add (new AbstractAction("Update End Points Only") {
103
            public void actionPerformed (ActionEvent e) {
104
                connection.setRoutingPolicy (ConnectionWidget.RoutingPolicy.UPDATE_END_POINTS_ONLY);
105
                validate ();
106
            }
107
        });
108
        bar.add (new AbstractAction("Disable Routing Until End Point is Moved") {
109
            public void actionPerformed (ActionEvent e) {
110
                connection.setRoutingPolicy (ConnectionWidget.RoutingPolicy.DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED);
111
                validate ();
112
            }
113
        });
114
        bar.add (new AbstractAction("Disable Routing") {
115
            public void actionPerformed (ActionEvent e) {
116
                connection.setRoutingPolicy (ConnectionWidget.RoutingPolicy.DISABLE_ROUTING);
117
                validate ();
118
            }
119
        });
120
        panel.add (bar, BorderLayout.NORTH);
121
122
        panel.add (createView (), BorderLayout.CENTER);
123
        return panel;
124
    }
125
126
    public static void main (String[] args) {
127
        SceneSupport.show (new RoutingPolicyTest ().createPanel ());
128
    }
129
130
}
(-)graph/lib/apichanges.xml (+16 lines)
Lines 534-539 Link Here
534
            <class package="org.netbeans.api.visual.anchor" name="Anchor" link="yes"/>
534
            <class package="org.netbeans.api.visual.anchor" name="Anchor" link="yes"/>
535
            <issue number="111987"/>
535
            <issue number="111987"/>
536
        </change>
536
        </change>
537
538
        <change>
539
            <api name="general"/>
540
            <summary>Routing policy support for ConnectionWidget</summary>
541
            <version major="2" minor="9"/>
542
            <date day="23" month="8" year="2007"/>
543
            <author login="dkaspar"/>
544
            <compatibility addition="yes"/>
545
            <description>
546
                ConnectionWidget allows to specify routing policy. The policy defines behaviour of path routing in ConnectionWidget.
547
                There are 4 values: Always-route, Update-end-points-only, Disable-routing-until-end-point-is-moved, Disable-routing.
548
                AddRemoveControlPointAction and MoveControlPointAction has new factory methods for automatic assignment of routing policy.
549
            </description>
550
            <class package="org.netbeans.api.visual.widget" name="ConnectionWidget" link="yes"/>
551
            <issue number="113573"/>
552
        </change>
537
    </changes>
553
    </changes>
538
554
539
    <htmlcontents>
555
    <htmlcontents>
(-)graph/lib/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.api.visual
2
OpenIDE-Module: org.netbeans.api.visual
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/visual/resources/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/visual/resources/Bundle.properties
4
OpenIDE-Module-Specification-Version: 2.8
4
OpenIDE-Module-Specification-Version: 2.9
5
AutoUpdate-Essential-Module: true
5
AutoUpdate-Essential-Module: true
6
6
(-)graph/lib/src/org/netbeans/api/visual/action/ActionFactory.java (-3 / +28 lines)
Lines 178-190 Link Here
178
    }
178
    }
179
179
180
    /**
180
    /**
181
     * Creates a add-remove control point action with a specified sensitivity. The action is assigned to a FreeConnectionWidget.
181
     * Creates a add-remove control point action with a specified sensitivity.
182
     * @param createSensitivity the create sensitivity
182
     * @param createSensitivity the create sensitivity
183
     * @param deleteSensitivity the delete sensitivity
183
     * @param deleteSensitivity the delete sensitivity
184
     * @return the add-remove control point action
184
     * @return the add-remove control point action
185
     */
185
     */
186
    public static WidgetAction createAddRemoveControlPointAction (double createSensitivity, double deleteSensitivity) {
186
    public static WidgetAction createAddRemoveControlPointAction (double createSensitivity, double deleteSensitivity) {
187
        return new AddRemoveControlPointAction (createSensitivity, deleteSensitivity);
187
        return createAddRemoveControlPointAction (createSensitivity, deleteSensitivity, null);
188
    }
189
190
    /**
191
     * Creates a add-remove control point action with a specified sensitivity.
192
     * @param createSensitivity the create sensitivity
193
     * @param deleteSensitivity the delete sensitivity
194
     * @param routingPolicy the routing policy that is automatically set to a connection widget with control points modified by this action;
195
     *     if null, then routing policy is not set
196
     * @return the add-remove control point action
197
     * @since 2.9
198
     */
199
    public static WidgetAction createAddRemoveControlPointAction (double createSensitivity, double deleteSensitivity, ConnectionWidget.RoutingPolicy routingPolicy) {
200
        return new AddRemoveControlPointAction (createSensitivity, deleteSensitivity, routingPolicy);
188
    }
201
    }
189
202
190
    /**
203
    /**
Lines 452-459 Link Here
452
     * @return the move control point action
465
     * @return the move control point action
453
     */
466
     */
454
    public static WidgetAction createMoveControlPointAction (MoveControlPointProvider provider) {
467
    public static WidgetAction createMoveControlPointAction (MoveControlPointProvider provider) {
468
        return createMoveControlPointAction (provider, null);
469
    }
470
471
    /**
472
     * Creates a move control point (of a connection widget) action with a specified provider.
473
     * @param provider the move control point provider
474
     * @param routingPolicy the routing policy that is automatically set to a connection widget with control points modified by this action;
475
     *     if null, then routing policy is not set
476
     * @return the move control point action
477
     * @since 2.9
478
     */
479
    public static WidgetAction createMoveControlPointAction (MoveControlPointProvider provider, ConnectionWidget.RoutingPolicy routingPolicy) {
455
        assert provider != null;
480
        assert provider != null;
456
        return new MoveControlPointAction (provider);
481
        return new MoveControlPointAction (provider, routingPolicy);
457
    }
482
    }
458
483
459
    /**
484
    /**
(-)graph/lib/src/org/netbeans/api/visual/widget/ConnectionWidget.java (-2 / +113 lines)
Lines 61-66 Link Here
61
    private static final double HIT_DISTANCE_SQUARE = 16.0;
61
    private static final double HIT_DISTANCE_SQUARE = 16.0;
62
    private static final Stroke STROKE_DEFAULT = new BasicStroke (1.0f);
62
    private static final Stroke STROKE_DEFAULT = new BasicStroke (1.0f);
63
63
64
    /**
65
     * This enum represents a policy which is used for re-routing control points of a ConnectionWidget.
66
     * @since 2.9
67
     */
68
    public enum RoutingPolicy {
69
70
        /**
71
         * All control points are rerouted when it is necessary. This is the default policy.
72
         * @since 2.9
73
         */
74
        ALWAYS_ROUTE,
75
76
        /**
77
         * All control points (except end points) are kept at the same location.
78
         * End points are updated to locations resolved by source and target anchors.
79
         * Note: This is used when an user customizes/adds/removes control points
80
         * and the change has to be kept until it is reset by the user (setting policy to ALWAYS_ROUTE.
81
         * @since 2.9
82
         */
83
        UPDATE_END_POINTS_ONLY,
84
85
        /**
86
         * Temporarily disables routing until any end point changes its location. Locations are the first
87
         * and the last point of control points. When an end point location is changed,
88
         * then the policy is automatically changed to <code>ALWAYS_ROUTE</code>.
89
         * Note: This is used by GraphLayouts which routes the path (control points)
90
         * by themselves and would like to keep the path until user moves with source or target widget/anchor.
91
         * @since 2.9
92
         */
93
        DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED,
94
95
        /**
96
         * Disable routing completely, so control points are kept at their previous location.
97
         * Note: This is not often used unless you have to freeze a ConnectionWidget
98
         * @since 2.9
99
         */
100
        DISABLE_ROUTING
101
102
    }
103
64
    private Anchor sourceAnchor;
104
    private Anchor sourceAnchor;
65
    private Anchor targetAnchor;
105
    private Anchor targetAnchor;
66
    private AnchorShape sourceAnchorShape;
106
    private AnchorShape sourceAnchorShape;
Lines 81-86 Link Here
81
    private Anchor.Entry sourceEntry;
121
    private Anchor.Entry sourceEntry;
82
    private Anchor.Entry targetEntry;
122
    private Anchor.Entry targetEntry;
83
123
124
    private RoutingPolicy routingPolicy;
125
84
    /**
126
    /**
85
     * Creates a connection widget.
127
     * Creates a connection widget.
86
     * @param scene the scene
128
     * @param scene the scene
Lines 100-105 Link Here
100
        controlPointCutDistance = 0;
142
        controlPointCutDistance = 0;
101
        sourceEntry = new ConnectionEntry (true);
143
        sourceEntry = new ConnectionEntry (true);
102
        targetEntry = new ConnectionEntry (false);
144
        targetEntry = new ConnectionEntry (false);
145
146
        routingPolicy = RoutingPolicy.ALWAYS_ROUTE;
103
    }
147
    }
104
148
105
    /**
149
    /**
Lines 338-343 Link Here
338
    }
382
    }
339
383
340
    /**
384
    /**
385
     * Returns a routing policy.
386
     * @return the routing policy
387
     * @since 2.9
388
     */
389
    public final RoutingPolicy getRoutingPolicy () {
390
        return routingPolicy;
391
    }
392
393
    /**
394
     * Sets a routing policy. It invokes re-routing in case of routing policy change unless its is changed to DISABLE_ROUTING.
395
     * @param routingPolicy the new routing policy
396
     * @since 2.9
397
     */
398
    public final void setRoutingPolicy (RoutingPolicy routingPolicy) {
399
        assert routingPolicy != null;
400
        if (this.routingPolicy == routingPolicy)
401
            return;
402
        boolean changed = routingPolicy != RoutingPolicy.DISABLE_ROUTING;
403
        this.routingPolicy = routingPolicy;
404
        if (changed)
405
            reroute ();
406
    }
407
408
    /**
341
     * Returns the control-points-based path router of the connection widget.
409
     * Returns the control-points-based path router of the connection widget.
342
     * @return the path router
410
     * @return the path router
343
     */
411
     */
Lines 427-434 Link Here
427
     * Forces path routing.
495
     * Forces path routing.
428
     */
496
     */
429
    public final void calculateRouting () {
497
    public final void calculateRouting () {
430
        if (routingRequired)
498
        if (routingRequired) {
431
            setControlPoints (router.routeConnection (this), true);
499
            switch (routingPolicy) {
500
                case ALWAYS_ROUTE:
501
                    setControlPoints (router.routeConnection (this), true);
502
                    break;
503
                case UPDATE_END_POINTS_ONLY: {
504
                    Point sourcePoint = sourceAnchor != null ? sourceAnchor.compute (sourceEntry).getAnchorSceneLocation () : null;
505
                    Point targetPoint = targetAnchor != null ? targetAnchor.compute (targetEntry).getAnchorSceneLocation () : null;
506
                    if (sourcePoint == null  ||  targetPoint == null) {
507
                        controlPoints.clear ();
508
                        break;
509
                    }
510
                    sourcePoint = convertSceneToLocal (sourcePoint);
511
                    targetPoint = convertSceneToLocal (targetPoint);
512
                    if (controlPoints.size () < 1)
513
                        controlPoints.add (sourcePoint);
514
                    else
515
                        controlPoints.set (0, sourcePoint);
516
                    if (controlPoints.size () < 2)
517
                        controlPoints.add (targetPoint);
518
                    else
519
                        controlPoints.set (controlPoints.size () - 1, targetPoint);
520
                    } break;
521
                case DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED: {
522
                    Point sourcePoint = sourceAnchor != null ? sourceAnchor.compute (sourceEntry).getAnchorSceneLocation () : null;
523
                    Point firstPoint = getFirstControlPoint ();
524
                    if (firstPoint != null)
525
                        firstPoint = convertLocalToScene (firstPoint);
526
                    if (sourcePoint == null ? firstPoint == null : sourcePoint.equals (firstPoint)) {
527
                        Point targetPoint = targetAnchor != null ? targetAnchor.compute (targetEntry).getAnchorSceneLocation () : null;
528
                        Point lastPoint = getLastControlPoint ();
529
                        if (lastPoint != null)
530
                            lastPoint = convertLocalToScene (lastPoint);
531
                        if (targetPoint == null  ? lastPoint == null : targetPoint.equals (lastPoint))
532
                            break;
533
                    }
534
                    routingPolicy = RoutingPolicy.ALWAYS_ROUTE;
535
                    setControlPoints (router.routeConnection (this), true);
536
                    } break;
537
                case DISABLE_ROUTING:
538
                    break;
539
                default:
540
                    throw new IllegalStateException ("Unexpected routing policy: " + routingPolicy); // NOI18N
541
            }
542
        }
432
    }
543
    }
433
544
434
    /**
545
    /**
(-)graph/lib/src/org/netbeans/api/visual/widget/doc-files/documentation.html (-2 / +23 lines)
Lines 132-137 Link Here
132
<ul>
132
<ul>
133
<li><a href="#Router">Router</a>
133
<li><a href="#Router">Router</a>
134
<li><a href="#ConnectionWidgetLayout">ConnectionWidgetLayout</a>
134
<li><a href="#ConnectionWidgetLayout">ConnectionWidgetLayout</a>
135
<li><a href="#RoutingPolicy">Routing Policy</a>
135
<li><a href="#ConnectionWidgetMethods">ConnectionWidget Methods</a>
136
<li><a href="#ConnectionWidgetMethods">ConnectionWidget Methods</a>
136
</ul>
137
</ul>
137
<li><a href="#Anchor">Anchor</a>
138
<li><a href="#Anchor">Anchor</a>
Lines 857-863 Link Here
857
Created by: <code>ActionFactory.createAddRemoveControlPointAction</code>
858
Created by: <code>ActionFactory.createAddRemoveControlPointAction</code>
858
859
859
<p>
860
<p>
860
The action could be attached to <code>FreeConnectionWidget</code> only and allow user to add a control point by double-clicking on path or remove control point by double-clicking on it. The action requires <code>FreeRouter</code> to be set to the <code>FreeConnectionWidget</code> where the action is attached - otherwise the control points are rerouted and therefore you loose the change. For fixing moving-anchor problem use <code>FreeRectangularAnchor</code>.
861
The action allows user to add a control point by double-clicking on path or remove control point by double-clicking on it. The action has <code>routingPolicy</code> which is automatically set to <code>ConnectionWidget</code> to prevent discarding of user changes by router assigned to the connection widget. For fixing moving-anchor problem use <code>FreeRectangularAnchor</code>.
861
862
862
<h3><a name="AlignWithMoveAction">AlignWithMoveAction</a></h3>
863
<h3><a name="AlignWithMoveAction">AlignWithMoveAction</a></h3>
863
864
Lines 1175-1181 Link Here
1175
<li><code>RouterFactory.createDirectRouter</code> creates a straight line between the source and the target anchor.
1176
<li><code>RouterFactory.createDirectRouter</code> creates a straight line between the source and the target anchor.
1176
<li><code>RouterFactory.createOrthogonalSeachRouter (CollisionsCollector)</code> creates an orthogonal path that tries to avoid overlapping areas specified by the <code>CollisionsCollector</code>. There is a built-in implementation <code>RouterFactory.createWidgetsCollisionCollector (LayerWidget...)</code> which collects all validated children widgets of the specified layer widgets and for each it gets the widget boundary and claims it as a vertical and horizontal collision. In case of ConnectionWidget, it takes the path (defined by its control points) and claims all horizontal and vertical segments as appropriate collisions.
1177
<li><code>RouterFactory.createOrthogonalSeachRouter (CollisionsCollector)</code> creates an orthogonal path that tries to avoid overlapping areas specified by the <code>CollisionsCollector</code>. There is a built-in implementation <code>RouterFactory.createWidgetsCollisionCollector (LayerWidget...)</code> which collects all validated children widgets of the specified layer widgets and for each it gets the widget boundary and claims it as a vertical and horizontal collision. In case of ConnectionWidget, it takes the path (defined by its control points) and claims all horizontal and vertical segments as appropriate collisions.
1177
<li><code>RouterFactory.createOrthogonalSeachRouter (ConnectionWidgetCollisionsCollector)</code> creates an orthogonal path similarly as the previous case but the <code>ConnectionWidgetCollisionsCollector</code> gets a context of currently routed connection widget.
1178
<li><code>RouterFactory.createOrthogonalSeachRouter (ConnectionWidgetCollisionsCollector)</code> creates an orthogonal path similarly as the previous case but the <code>ConnectionWidgetCollisionsCollector</code> gets a context of currently routed connection widget.
1178
<li><code>RouterFactory.createFreeRouter</code> is similar to <code>DirectRouter</code> but it modifies only the first and last point of the route. The "middle" control points stay the same. This effect is used by <code>AddRemoveControlPointAction</code> to maintain the control points created by user.
1179
<li><code>RouterFactory.createFreeRouter</code> is similar to <code>DirectRouter</code> but it modifies only the first and last point of the route. The "middle" control points stay the same. This effect is used by <code>AddRemoveControlPointAction</code> to maintain the control points created by user. From now this router is no longer useful, since it can be replaced by more flexible way: use any router that you like and set "Update-end-points-only" routing policy to the ConnectionWidget.
1179
</ul>
1180
</ul>
1180
1181
1181
<h3><a name="ConnectionWidgetLayout">ConnectionWidgetLayout</a></h3>
1182
<h3><a name="ConnectionWidgetLayout">ConnectionWidgetLayout</a></h3>
Lines 1186-1191 Link Here
1186
<p>
1187
<p>
1187
See <code>test.connectionlabels.ConnectionLabelsTest</code> for details.
1188
See <code>test.connectionlabels.ConnectionLabelsTest</code> for details.
1188
1189
1190
<h3><a name="RoutingPolicy">Routing Policy</a></h3>
1191
1192
Since version 2.9, the ConnectionWidget class has additional <code>routingPolicy</code> property. It ease management of control points changed by users. There are 4 values:
1193
<ol>
1194
<li><code>ALWAYS_ROUTE</code> - This is default value. The router is always invoked when a ConnectionWidget is changed and needs to be re-routed.
1195
<li><code>UPDATE_END_POINTS_ONLY</code> - The router is not invoked. Instead location of the first and the last control points are changed/updated to location computed by source and target anchors.
1196
<li><code>DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED</code> - The router is not invoked until the first or the last control points is moved (means it has different location from one computed by source or target anchor).
1197
<li><code>DISABLE_ROUTING</code> - The router is not invoked. The control points are freezed at the same locations.
1198
</ol>
1199
1200
These routing policy are very useful when you are using modifying control points:
1201
<ul>
1202
<li>You can specify <code>routingPolicy</code> value to factory method of <code>AddRemoveControlPointAction</code> and <code>MoveControlPointAction</code>. If not null, then the value is automatically set to a ConnectionWidget which control points are modified by the action. Usually <code>UPDATE_END_POINT_ONLY</code> is used.
1203
<li>Some graph-oriented layout algorithms are resolving not only location of nodes on a scene but also routes path of edges. Then you can use <code>UPDATE_END_POINT_ONLY</code> or <code>DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED</code> to prevent discard of paths routed by the graph-oriented layout.
1204
1205
For usages, see <code>test.routing.ActionsWithRoutingPolicyTest</code> and <code>test.routing.RoutingPolicyTest</code> examples.
1206
1189
<h3><a name="ConnectionWidgetMethods">ConnectionWidget Methods</a></h3>
1207
<h3><a name="ConnectionWidgetMethods">ConnectionWidget Methods</a></h3>
1190
1208
1191
<p>
1209
<p>
Lines 1225-1230 Link Here
1225
<tr>
1243
<tr>
1226
<td>getRouter<br>setRouter
1244
<td>getRouter<br>setRouter
1227
<td>Controls a router assigned to the connection widget. The routers is calculating a path and sets a new one using <code>setControlPoints</code> method.
1245
<td>Controls a router assigned to the connection widget. The routers is calculating a path and sets a new one using <code>setControlPoints</code> method.
1246
<tr>
1247
<td>getRoutingPolicy<br>setRoutingPolicy
1248
<td>Controls a routing policy assigned to the connection widget. It controls whether and how control points are re-routed. For details, see <a href="#RoutingPolicy">Routing Policy</a> section.
1228
<tr>
1249
<tr>
1229
<td>getControlPoints()<br>setControlPoints(List&lt;Point>controlPoints,boolean sceneLocations)<br>getControlPoint(int index)
1250
<td>getControlPoints()<br>setControlPoints(List&lt;Point>controlPoints,boolean sceneLocations)<br>getControlPoint(int index)
1230
<td>Manipulates with control points. If the <code>sceneLocations</code> is <code>true</code> then the <code>controlPoints</code> are recalculated relatively to the connection widget location otherwise controlPoints are taken as they are (and therefore they are taken as local locations). This method is usually called by the assigned router.
1251
<td>Manipulates with control points. If the <code>sceneLocations</code> is <code>true</code> then the <code>controlPoints</code> are recalculated relatively to the connection widget location otherwise controlPoints are taken as they are (and therefore they are taken as local locations). This method is usually called by the assigned router.
(-)graph/lib/src/org/netbeans/modules/visual/action/AddRemoveControlPointAction.java (-53 / +31 lines)
Lines 18-112 Link Here
18
 */
18
 */
19
package org.netbeans.modules.visual.action;
19
package org.netbeans.modules.visual.action;
20
20
21
import java.awt.Point;
22
import java.awt.geom.Line2D;
23
import java.util.ArrayList;
24
import org.netbeans.api.visual.action.WidgetAction;
21
import org.netbeans.api.visual.action.WidgetAction;
25
import org.netbeans.api.visual.widget.ConnectionWidget;
22
import org.netbeans.api.visual.widget.ConnectionWidget;
26
import org.netbeans.api.visual.widget.Widget;
23
import org.netbeans.api.visual.widget.Widget;
27
24
25
import java.awt.*;
28
import java.awt.event.MouseEvent;
26
import java.awt.event.MouseEvent;
29
import java.util.List;
27
import java.awt.geom.Line2D;
30
import org.netbeans.api.visual.action.WidgetAction.State;
28
import java.util.ArrayList;
31
29
32
/**
30
/**
33
 * @author Alex
31
 * @author Alex
34
 */
32
 */
35
public class AddRemoveControlPointAction extends WidgetAction.Adapter {
33
public class AddRemoveControlPointAction extends WidgetAction.Adapter {
36
34
37
    private double createSensitivity=1.00, deleteSensitivity=5.00;
35
    private double createSensitivity;
38
    private ConnectionWidget cWidget;
36
    private double deleteSensitivity;
39
    
37
    private ConnectionWidget.RoutingPolicy routingPolicy;
40
    public AddRemoveControlPointAction(){
38
41
        
39
    public AddRemoveControlPointAction (double createSensitivity, double deleteSensitivity, ConnectionWidget.RoutingPolicy routingPolicy) {
42
    }
43
    
44
    public AddRemoveControlPointAction(double createSensitivity, double deleteSensitivity) {
45
        this.createSensitivity = createSensitivity;
40
        this.createSensitivity = createSensitivity;
46
        this.deleteSensitivity = deleteSensitivity;
41
        this.deleteSensitivity = deleteSensitivity;
42
        this.routingPolicy = routingPolicy;
47
    }
43
    }
48
44
49
    public State mouseClicked(Widget widget, WidgetMouseEvent event) {
45
    public State mouseClicked(Widget widget, WidgetMouseEvent event) {
50
        if(event.getButton()==MouseEvent.BUTTON1 && event.getClickCount()==2  &&  widget instanceof ConnectionWidget) {
46
        if(event.getButton()==MouseEvent.BUTTON1 && event.getClickCount()==2  &&  widget instanceof ConnectionWidget) {
51
            cWidget=(ConnectionWidget)widget;
47
            addRemoveControlPoint ((ConnectionWidget) widget, event.getPoint ());
52
            Point point=event.getPoint();
48
            return State.CONSUMED;
53
            addRemoveControlPoint (point);
54
        }
49
        }
55
        return State.REJECTED;
50
        return State.REJECTED;
56
    }
51
    }
57
    
52
    
58
    /**
53
    /**
59
     * Adds or removes a control point on a specified location
54
     * Adds or removes a control point on a specified location
55
     * @param widget the connection widget
60
     * @param localLocation the local location
56
     * @param localLocation the local location
61
     */
57
     */
62
    private void addRemoveControlPoint (Point localLocation) {
58
    private void addRemoveControlPoint (ConnectionWidget widget, Point localLocation) {
63
        ArrayList<Point> list = new ArrayList<Point> (cWidget.getControlPoints());
59
        ArrayList<Point> list = new ArrayList<Point> (widget.getControlPoints ());
64
            if(!removeControlPoint(localLocation,list,deleteSensitivity)){
60
        if (!removeControlPoint (localLocation, list, deleteSensitivity)) {
65
                Point exPoint=null;int index=0;
61
            Point exPoint = null;
66
                for (Point elem : list) {
62
            int index = 0;
67
                    if(exPoint!=null){
63
            for (Point elem : list) {
68
                        Line2D l2d=new Line2D.Double(exPoint,elem);
64
                if (exPoint != null) {
69
                        if(l2d.ptLineDist(localLocation)<createSensitivity){
65
                    Line2D l2d = new Line2D.Double (exPoint, elem);
70
                            list.add(index,localLocation);
66
                    if (l2d.ptLineDist (localLocation) < createSensitivity) {
71
                            break;
67
                        list.add (index, localLocation);
72
                        }
68
                        break;
73
                    }
69
                    }
74
                    exPoint=elem;index++;
75
                }
70
                }
71
                exPoint = elem;
72
                index++;
76
            }
73
            }
77
            cWidget.setControlPoints(list,false);
74
        }
75
        if (routingPolicy != null)
76
            widget.setRoutingPolicy (routingPolicy);
77
        widget.setControlPoints (list, false);
78
    }
78
    }
79
    
79
    
80
    private boolean removeControlPoint(Point point, ArrayList<Point> list, double deleteSensitivity){
80
    private boolean removeControlPoint(Point point, ArrayList<Point> list, double deleteSensitivity){
81
        for (Point elem : list) {
81
        for (Point elem : list) {
82
            if(elem.distance(point)<deleteSensitivity){
82
            if (elem.distance (point) < deleteSensitivity) {
83
                list.remove(elem);
83
                list.remove (elem);
84
                return true;
84
                return true;
85
            }
85
            }
86
        }
86
        }
87
        return false;
87
        return false;
88
    }
88
    }
89
89
90
    /**
91
     * Returns a control point at a specific index.
92
     * @param index the index in the list of control points
93
     * @return the control point at specified index; null, if the connection widget does not have control points
94
     * @throws ArrayIndexOutOfBoundsException when index is out of bounds
95
     */
96
    private Point getControlPoint (int index) {
97
        List<Point> controlPoints=cWidget.getControlPoints();
98
        if (controlPoints.size () <= 0) return null;
99
        return new Point (controlPoints.get (index));
100
    }
101
102
    /**
103
     * Sets a sensitivity.
104
     * @param createSensitivity the sensitivity for adding a control point
105
     * @param deleteSensitivity the sensitivity for removing a control point
106
     */
107
    public void setSensitivity(double createSensitivity, double deleteSensitivity){
108
        this.createSensitivity=createSensitivity; 
109
        this.deleteSensitivity=deleteSensitivity;
110
    } 
111
    
112
}
90
}
(-)graph/lib/src/org/netbeans/modules/visual/action/MoveControlPointAction.java (-1 / +5 lines)
Lines 32-45 Link Here
32
public final class MoveControlPointAction extends WidgetAction.LockedAdapter {
32
public final class MoveControlPointAction extends WidgetAction.LockedAdapter {
33
33
34
    private MoveControlPointProvider provider;
34
    private MoveControlPointProvider provider;
35
    private ConnectionWidget.RoutingPolicy routingPolicy;
35
36
36
    private ConnectionWidget movingWidget = null;
37
    private ConnectionWidget movingWidget = null;
37
    private Point controlPointLocation;
38
    private Point controlPointLocation;
38
    private int controlPointIndex;
39
    private int controlPointIndex;
39
    private Point lastLocation = null;
40
    private Point lastLocation = null;
40
41
41
    public MoveControlPointAction (MoveControlPointProvider provider) {
42
    public MoveControlPointAction (MoveControlPointProvider provider, ConnectionWidget.RoutingPolicy routingPolicy) {
42
        this.provider = provider;
43
        this.provider = provider;
44
        this.routingPolicy = routingPolicy;
43
    }
45
    }
44
46
45
    protected boolean isLocked () {
47
    protected boolean isLocked () {
Lines 90-95 Link Here
90
        if (controlPoints == null)
92
        if (controlPoints == null)
91
            return State.REJECTED;
93
            return State.REJECTED;
92
94
95
        if (routingPolicy != null)
96
            movingWidget.setRoutingPolicy (routingPolicy);
93
        movingWidget.setControlPoints (controlPoints, false);
97
        movingWidget.setControlPoints (controlPoints, false);
94
        return State.createLocked (widget, this);
98
        return State.createLocked (widget, this);
95
    }
99
    }
(-)graph/www/documentation.html (+2 lines)
Lines 173-178 Link Here
173
<li><strong>test.resize.ResizeTest</strong> - how to use <code>ResizeAction</code>
173
<li><strong>test.resize.ResizeTest</strong> - how to use <code>ResizeAction</code>
174
<li><strong>test.router.OSRCollisionsCollectorTest</strong> - test of bugfix #96462 - Incorrectly routed path by OrthogonalSearchRouter when a target in collision region
174
<li><strong>test.router.OSRCollisionsCollectorTest</strong> - test of bugfix #96462 - Incorrectly routed path by OrthogonalSearchRouter when a target in collision region
175
<li><strong>test.router.OSRComputeControlPointsTest</strong> - test of bugfix #96460 - Wrong control points computation in OrthogonalSearchRouter
175
<li><strong>test.router.OSRComputeControlPointsTest</strong> - test of bugfix #96460 - Wrong control points computation in OrthogonalSearchRouter
176
<li><strong>test.routing.ActionsWithRoutingPolicyTest</strong> - how to use routing policy with <code>AddRemoveControlPointAction</code> and <code>MoveControlPointAction</code>
177
<li><strong>test.routing.RoutingPolicyTest</strong> - how to use routing policy of <code>ConnectionWidget</code>
176
<li><strong>test.sceneresize.LimitedSceneTest</strong> - test of cooperation of <code>OrthogonalSearchRouter</code> with <code>Scene.maximumBounds</code> property
178
<li><strong>test.sceneresize.LimitedSceneTest</strong> - test of cooperation of <code>OrthogonalSearchRouter</code> with <code>Scene.maximumBounds</code> property
177
<li><strong>test.sceneresize.SceneResizeTest</strong> - test of bugfix #84604 - scene resize based on Scene view component
179
<li><strong>test.sceneresize.SceneResizeTest</strong> - test of bugfix #84604 - scene resize based on Scene view component
178
<li><strong>test.scroll.ScrollTest</strong> - how to use <code>ScrollWidget</code> for scrollable view
180
<li><strong>test.scroll.ScrollTest</strong> - how to use <code>ScrollWidget</code> for scrollable view

Return to bug 113573