Source Code Cross Referenced for ConnectionWidget.java in  » IDE-Netbeans » api » org » netbeans » api » visual » widget » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » api » org.netbeans.api.visual.widget 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.netbeans.api.visual.widget;
0042:
0043:        import org.netbeans.api.visual.anchor.Anchor;
0044:        import org.netbeans.api.visual.anchor.AnchorShape;
0045:        import org.netbeans.api.visual.anchor.PointShape;
0046:        import org.netbeans.api.visual.layout.LayoutFactory;
0047:        import org.netbeans.api.visual.model.ObjectState;
0048:        import org.netbeans.api.visual.router.Router;
0049:        import org.netbeans.api.visual.router.RouterFactory;
0050:        import org.netbeans.modules.visual.layout.ConnectionWidgetLayout;
0051:
0052:        import java.awt.*;
0053:        import java.awt.geom.AffineTransform;
0054:        import java.awt.geom.GeneralPath;
0055:        import java.awt.geom.Line2D;
0056:        import java.awt.geom.Point2D;
0057:        import java.util.ArrayList;
0058:        import java.util.Collection;
0059:        import java.util.Collections;
0060:        import java.util.List;
0061:
0062:        /**
0063:         * This class represents a connection between two location. The locations are resolved by Anchors.
0064:         * The path of the connection is specified by control points which are resolved by Routers (DirectRouter is used by default).
0065:         * <p>
0066:         * The connection is rendered using the foreground color and a specified stroke. It also renders control points,
0067:         * end points (first and last control points) and anchors. The shape of points are defined by assigned AnchorShape and PointShape.
0068:         * <p>
0069:         * For speed optimalization, the connection widget are usually placed in the a separate layer widget that is rendered after
0070:         * the main layer with widgets (that used anchors depends on) is rendered.
0071:         * <p>
0072:         * Line color is defined by foregroundColor property. Note: If you are changing a state of the ConnectionWidget
0073:         * (e.g. using it as a representation of an object in ObjectScene, GraphScene or GraphPinScene classes,
0074:         * then the ConnectionWidget.notifyStateChanged method is automatically called.
0075:         * The built-in implementation of this method overrides foregroundColor based on a new state of the widget
0076:         * (the particular color is resolved by the LookFeel of the scene).
0077:         *
0078:         * @author David Kaspar
0079:         */
0080:        // TODO - control points can be modified by accessing: getControlPoints ().get (0).x or y
0081:        public class ConnectionWidget extends Widget {
0082:
0083:            private static final double HIT_DISTANCE_SQUARE = 16.0;
0084:            private static final Stroke STROKE_DEFAULT = new BasicStroke(1.0f);
0085:
0086:            /**
0087:             * This enum represents a policy which is used for re-routing control points of a ConnectionWidget.
0088:             * @since 2.9
0089:             */
0090:            public enum RoutingPolicy {
0091:
0092:                /**
0093:                 * All control points are rerouted when it is necessary. This is the default policy.
0094:                 * @since 2.9
0095:                 */
0096:                ALWAYS_ROUTE,
0097:
0098:                /**
0099:                 * All control points (except end points) are kept at the same location.
0100:                 * End points are updated to locations resolved by source and target anchors.
0101:                 * Note: This is used when an user customizes/adds/removes control points
0102:                 * and the change has to be kept until it is reset by the user (setting policy to ALWAYS_ROUTE.
0103:                 * @since 2.9
0104:                 */
0105:                UPDATE_END_POINTS_ONLY,
0106:
0107:                /**
0108:                 * Temporarily disables routing until any end point changes its location. Locations are the first
0109:                 * and the last point of control points. When an end point location is changed,
0110:                 * then the policy is automatically changed to <code>ALWAYS_ROUTE</code>.
0111:                 * Note: This is used by GraphLayouts which routes the path (control points)
0112:                 * by themselves and would like to keep the path until user moves with source or target widget/anchor.
0113:                 * @since 2.9
0114:                 */
0115:                DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED,
0116:
0117:                /**
0118:                 * Disable routing completely, so control points are kept at their previous location.
0119:                 * Note: This is not often used unless you have to freeze a ConnectionWidget
0120:                 * @since 2.9
0121:                 */
0122:                DISABLE_ROUTING
0123:
0124:            }
0125:
0126:            private Anchor sourceAnchor;
0127:            private Anchor targetAnchor;
0128:            private AnchorShape sourceAnchorShape;
0129:            private AnchorShape targetAnchorShape;
0130:            private PointShape controlPointShape;
0131:            private PointShape endPointShape;
0132:            private Router router;
0133:            private boolean routingRequired;
0134:            private List<Point> controlPoints = Collections.emptyList();
0135:            private List<Point> controlPointsUm = Collections
0136:                    .unmodifiableList(controlPoints);
0137:            private ConnectionWidgetLayout connectionWidgetLayout;
0138:            private Stroke stroke;
0139:            private boolean paintControlPoints;
0140:            private Color lineColor;
0141:            private Cursor controlPointsCursor;
0142:            private int controlPointCutDistance;
0143:
0144:            private Anchor.Entry sourceEntry;
0145:            private Anchor.Entry targetEntry;
0146:
0147:            private RoutingPolicy routingPolicy;
0148:
0149:            /**
0150:             * Creates a connection widget.
0151:             * @param scene the scene
0152:             */
0153:            public ConnectionWidget(Scene scene) {
0154:                super (scene);
0155:                sourceAnchorShape = AnchorShape.NONE;
0156:                targetAnchorShape = AnchorShape.NONE;
0157:                controlPointShape = PointShape.NONE;
0158:                endPointShape = PointShape.NONE;
0159:                router = RouterFactory.createDirectRouter();
0160:                routingRequired = true;
0161:                connectionWidgetLayout = new ConnectionWidgetLayout(this );
0162:                setLayout(connectionWidgetLayout);
0163:                stroke = STROKE_DEFAULT;
0164:                paintControlPoints = false;
0165:                controlPointCutDistance = 0;
0166:                sourceEntry = new ConnectionEntry(true);
0167:                targetEntry = new ConnectionEntry(false);
0168:
0169:                routingPolicy = RoutingPolicy.ALWAYS_ROUTE;
0170:            }
0171:
0172:            /**
0173:             * Implements the widget-state specific look of the widget.
0174:             * @param previousState the previous state
0175:             * @param state the new state
0176:             */
0177:            public void notifyStateChanged(ObjectState previousState,
0178:                    ObjectState state) {
0179:                setForeground(lineColor != null ? lineColor : getScene()
0180:                        .getLookFeel().getLineColor(state));
0181:                setPaintControlPoints(state.isSelected());
0182:            }
0183:
0184:            /**
0185:             * Returns a stroke of the connection widget.
0186:             * @return the stroke
0187:             */
0188:            public final Stroke getStroke() {
0189:                return stroke;
0190:            }
0191:
0192:            /**
0193:             * Sets a stroke.
0194:             * @param stroke the stroke
0195:             */
0196:            public final void setStroke(Stroke stroke) {
0197:                assert stroke != null;
0198:                this .stroke = stroke;
0199:                repaint(); // TODO - check when to revalidate and when to repaint only
0200:            }
0201:
0202:            /**
0203:             * Returns line color of the widget.
0204:             * @return the line color; null if no line color is specified
0205:             */
0206:            public final Color getLineColor() {
0207:                return lineColor;
0208:            }
0209:
0210:            /**
0211:             * Sets a line color of the widget.
0212:             * @param lineColor the line color; if null, then the line color will be resolved from LookFeel of the scene.
0213:             */
0214:            public final void setLineColor(Color lineColor) {
0215:                this .lineColor = lineColor;
0216:                ObjectState state = getState();
0217:                notifyStateChanged(state, state);
0218:            }
0219:
0220:            /**
0221:             * Returns whether the control (and end) points are painted
0222:             * @return true, if the control points (and end points) are painted
0223:             */
0224:            public final boolean isPaintControlPoints() {
0225:                return paintControlPoints;
0226:            }
0227:
0228:            /**
0229:             * Sets whether the control (and end) points are painted
0230:             * @param paintControlPoints if true, then control points are painted
0231:             */
0232:            public final void setPaintControlPoints(boolean paintControlPoints) {
0233:                this .paintControlPoints = paintControlPoints;
0234:                repaint();
0235:            }
0236:
0237:            /**
0238:             * Returns the cursor for control point.
0239:             * @return the cursor
0240:             * @since 2.3
0241:             */
0242:            public final Cursor getControlPointsCursor() {
0243:                return controlPointsCursor;
0244:            }
0245:
0246:            /**
0247:             * Sets a control points cursor. The cursor is used only when mouse is over a visible control point
0248:             * @param controlPointsCursor the control points cursor
0249:             * @since 2.3
0250:             */
0251:            public final void setControlPointsCursor(Cursor controlPointsCursor) {
0252:                this .controlPointsCursor = controlPointsCursor;
0253:            }
0254:
0255:            /**
0256:             * Returns the cut distance at control points.
0257:             * @return the cut distance
0258:             * @since 2.5
0259:             */
0260:            public int getControlPointCutDistance() {
0261:                return controlPointCutDistance;
0262:            }
0263:
0264:            /**
0265:             * Sets the cut distance at control points.
0266:             * @param controlPointCutDistance if positive number, then the path is cut to render smooth corners;
0267:             *     otherwise the path is rendered using control points only
0268:             * @since 2.5
0269:             */
0270:            public void setControlPointCutDistance(int controlPointCutDistance) {
0271:                this .controlPointCutDistance = controlPointCutDistance;
0272:                repaint();
0273:            }
0274:
0275:            /**
0276:             * Returns a source anchor of the connection widget.
0277:             * @return the source anchor
0278:             */
0279:            public final Anchor getSourceAnchor() {
0280:                return sourceAnchor;
0281:            }
0282:
0283:            /**
0284:             * Sets a source anchor of the connection widget.
0285:             * @param sourceAnchor the source anchor
0286:             */
0287:            public final void setSourceAnchor(Anchor sourceAnchor) {
0288:                if (this .sourceAnchor != null)
0289:                    this .sourceAnchor.removeEntry(sourceEntry);
0290:                this .sourceAnchor = sourceAnchor;
0291:                if (this .sourceAnchor != null)
0292:                    sourceAnchor.addEntry(sourceEntry);
0293:                reroute();
0294:            }
0295:
0296:            /**
0297:             * Returns a target anchor of the connection widget.
0298:             * @return the target anchor
0299:             */
0300:            public final Anchor getTargetAnchor() {
0301:                return targetAnchor;
0302:            }
0303:
0304:            /**
0305:             * Sets a target anchor of the connection widget.
0306:             * @param targetAnchor the target anchor
0307:             */
0308:            public final void setTargetAnchor(Anchor targetAnchor) {
0309:                if (this .targetAnchor != null)
0310:                    this .targetAnchor.removeEntry(targetEntry);
0311:                this .targetAnchor = targetAnchor;
0312:                if (targetAnchor != null)
0313:                    targetAnchor.addEntry(targetEntry);
0314:                reroute();
0315:            }
0316:
0317:            /**
0318:             * Returns an anchor entry representing the source of the connection widget.
0319:             * @return the anchor entry representing the source of the connection widget
0320:             */
0321:            public Anchor.Entry getSourceAnchorEntry() {
0322:                return sourceEntry;
0323:            }
0324:
0325:            /**
0326:             * Returns an anchor entry representing the target of the connection widget.
0327:             * @return the anchor entry representing the target of the connection widget
0328:             */
0329:            public Anchor.Entry getTargetAnchorEntry() {
0330:                return targetEntry;
0331:            }
0332:
0333:            /**
0334:             * Returns an anchor shape of the source of the connection widget.
0335:             * @return the source anchor shape
0336:             */
0337:            public AnchorShape getSourceAnchorShape() {
0338:                return sourceAnchorShape;
0339:            }
0340:
0341:            /**
0342:             * Sets the anchor shape of the source of the connection widget.
0343:             * @param sourceAnchorShape the source anchor shape
0344:             */
0345:            public void setSourceAnchorShape(AnchorShape sourceAnchorShape) {
0346:                assert sourceAnchorShape != null;
0347:                boolean repaintOnly = this .sourceAnchorShape.getRadius() == sourceAnchorShape
0348:                        .getRadius();
0349:                this .sourceAnchorShape = sourceAnchorShape;
0350:                revalidate(repaintOnly);
0351:            }
0352:
0353:            /**
0354:             * Returns an anchor shape of the target of the connection widget.
0355:             * @return the target anchor shape
0356:             */
0357:            public AnchorShape getTargetAnchorShape() {
0358:                return targetAnchorShape;
0359:            }
0360:
0361:            /**
0362:             * Sets the anchor shape of the target of the connection widget.
0363:             * @param targetAnchorShape the target anchor shape
0364:             */
0365:            public void setTargetAnchorShape(AnchorShape targetAnchorShape) {
0366:                assert targetAnchorShape != null;
0367:                boolean repaintOnly = this .targetAnchorShape.getRadius() == targetAnchorShape
0368:                        .getRadius();
0369:                this .targetAnchorShape = targetAnchorShape;
0370:                revalidate(repaintOnly);
0371:            }
0372:
0373:            /**
0374:             * Returns a point shape of control points of the connection widget.
0375:             * @return the control points shape
0376:             */
0377:            public PointShape getControlPointShape() {
0378:                return controlPointShape;
0379:            }
0380:
0381:            /**
0382:             * Sets a point shape of control points of the connection widget.
0383:             * @param controlPointShape the control points shape
0384:             */
0385:            public void setControlPointShape(PointShape controlPointShape) {
0386:                assert controlPointShape != null;
0387:                boolean repaintOnly = this .controlPointShape.getRadius() == controlPointShape
0388:                        .getRadius();
0389:                this .controlPointShape = controlPointShape;
0390:                revalidate(repaintOnly);
0391:            }
0392:
0393:            /**
0394:             * Returns a point shape of end points of the connection widget.
0395:             * @return the end points shape
0396:             */
0397:            public PointShape getEndPointShape() {
0398:                return endPointShape;
0399:            }
0400:
0401:            /**
0402:             * Sets a point shape of end points of the connection widget.
0403:             * @param endPointShape the end points shape
0404:             */
0405:            public void setEndPointShape(PointShape endPointShape) {
0406:                assert endPointShape != null;
0407:                boolean repaintOnly = this .endPointShape.getRadius() == endPointShape
0408:                        .getRadius();
0409:                this .endPointShape = endPointShape;
0410:                revalidate(repaintOnly);
0411:            }
0412:
0413:            /**
0414:             * Returns a routing policy.
0415:             * @return the routing policy
0416:             * @since 2.9
0417:             */
0418:            public final RoutingPolicy getRoutingPolicy() {
0419:                return routingPolicy;
0420:            }
0421:
0422:            /**
0423:             * Sets a routing policy. It invokes re-routing in case of routing policy change unless its is changed to DISABLE_ROUTING.
0424:             * @param routingPolicy the new routing policy
0425:             * @since 2.9
0426:             */
0427:            public final void setRoutingPolicy(RoutingPolicy routingPolicy) {
0428:                assert routingPolicy != null;
0429:                if (this .routingPolicy == routingPolicy)
0430:                    return;
0431:                boolean changed = routingPolicy != RoutingPolicy.DISABLE_ROUTING;
0432:                this .routingPolicy = routingPolicy;
0433:                if (changed)
0434:                    reroute();
0435:            }
0436:
0437:            /**
0438:             * Returns the control-points-based path router of the connection widget.
0439:             * @return the path router
0440:             */
0441:            public final Router getRouter() {
0442:                return router;
0443:            }
0444:
0445:            /**
0446:             * Sets a control-points-based path router of the connection widget.
0447:             * @param router the path router
0448:             */
0449:            public final void setRouter(Router router) {
0450:                assert router != null;
0451:                this .router = router;
0452:                reroute();
0453:            }
0454:
0455:            /**
0456:             * Returns a list of control points.
0457:             * @return the list of control points
0458:             */
0459:            public List<Point> getControlPoints() {
0460:                return controlPointsUm;
0461:            }
0462:
0463:            /**
0464:             * Returns a location of control point at the specified index in the list of control points.
0465:             *
0466:             * @param index index of the control point to return
0467:             * @return the point; null if the control point does not exist
0468:             */
0469:            public Point getControlPoint(int index) {
0470:                if (index < 0 || index >= controlPoints.size())
0471:                    return null;
0472:                return new Point(controlPoints.get(index));
0473:            }
0474:
0475:            /**
0476:             * Sets control points.
0477:             * @param controlPoints the list of control points
0478:             * @param sceneLocations if true, then controlPoints argyment is taken as a list of scene locations;
0479:             *            if false, then controlPoints argument is taken as a list of local locations
0480:             */
0481:            public void setControlPoints(Collection<Point> controlPoints,
0482:                    boolean sceneLocations) {
0483:                if (sceneLocations) {
0484:                    Point translation = this .convertLocalToScene(new Point());
0485:                    ArrayList<Point> list = new ArrayList<Point>();
0486:                    for (Point point : controlPoints)
0487:                        list.add(new Point(point.x - translation.x, point.y
0488:                                - translation.y));
0489:                    this .controlPoints = list;
0490:                } else
0491:                    this .controlPoints = new ArrayList<Point>(controlPoints);
0492:                this .controlPointsUm = Collections
0493:                        .unmodifiableList(this .controlPoints);
0494:                routingRequired = false;
0495:                revalidate();
0496:            }
0497:
0498:            /**
0499:             * Sets a constraint for a child widget when ConnectionWidgetLayout (by default) is used.
0500:             * @param childWidget the child widget for which the constraint is set
0501:             * @param alignment the alignment specified relatively to the origin point
0502:             * @param placementInPercentage the placement on a path in percentage of the path length
0503:             */
0504:            public void setConstraint(Widget childWidget,
0505:                    LayoutFactory.ConnectionWidgetLayoutAlignment alignment,
0506:                    float placementInPercentage) {
0507:                connectionWidgetLayout.setConstraint(childWidget, alignment,
0508:                        placementInPercentage);
0509:            }
0510:
0511:            /**
0512:             * Sets a constraint for a child widget when ConnectionWidgetLayout (by default) is used.
0513:             * @param childWidget the child widget for which the constraint is set
0514:             * @param alignment the alignment specified relatively to the origin point
0515:             * @param placementAtDistance the placement on a path in pixels as a distance from the source anchor
0516:             */
0517:            public void setConstraint(Widget childWidget,
0518:                    LayoutFactory.ConnectionWidgetLayoutAlignment alignment,
0519:                    int placementAtDistance) {
0520:                connectionWidgetLayout.setConstraint(childWidget, alignment,
0521:                        placementAtDistance);
0522:            }
0523:
0524:            /**
0525:             * Removes a constraint for a child widget.
0526:             * @param childWidget the child widget
0527:             */
0528:            public void removeConstraint(Widget childWidget) {
0529:                connectionWidgetLayout.removeConstraint(childWidget);
0530:            }
0531:
0532:            /**
0533:             * Forces path routing.
0534:             */
0535:            public final void calculateRouting() {
0536:                if (routingRequired) {
0537:                    switch (routingPolicy) {
0538:                    case ALWAYS_ROUTE:
0539:                        setControlPoints(router.routeConnection(this ), true);
0540:                        break;
0541:                    case UPDATE_END_POINTS_ONLY: {
0542:                        Point sourcePoint = sourceAnchor != null ? sourceAnchor
0543:                                .compute(sourceEntry).getAnchorSceneLocation()
0544:                                : null;
0545:                        Point targetPoint = targetAnchor != null ? targetAnchor
0546:                                .compute(targetEntry).getAnchorSceneLocation()
0547:                                : null;
0548:                        if (sourcePoint == null || targetPoint == null) {
0549:                            controlPoints.clear();
0550:                            break;
0551:                        }
0552:                        sourcePoint = convertSceneToLocal(sourcePoint);
0553:                        targetPoint = convertSceneToLocal(targetPoint);
0554:                        if (controlPoints.size() < 1)
0555:                            controlPoints.add(sourcePoint);
0556:                        else
0557:                            controlPoints.set(0, sourcePoint);
0558:                        if (controlPoints.size() < 2)
0559:                            controlPoints.add(targetPoint);
0560:                        else
0561:                            controlPoints.set(controlPoints.size() - 1,
0562:                                    targetPoint);
0563:                    }
0564:                        break;
0565:                    case DISABLE_ROUTING_UNTIL_END_POINT_IS_MOVED: {
0566:                        Point sourcePoint = sourceAnchor != null ? sourceAnchor
0567:                                .compute(sourceEntry).getAnchorSceneLocation()
0568:                                : null;
0569:                        Point firstPoint = getFirstControlPoint();
0570:                        if (firstPoint != null)
0571:                            firstPoint = convertLocalToScene(firstPoint);
0572:                        if (sourcePoint == null ? firstPoint == null
0573:                                : sourcePoint.equals(firstPoint)) {
0574:                            Point targetPoint = targetAnchor != null ? targetAnchor
0575:                                    .compute(targetEntry)
0576:                                    .getAnchorSceneLocation()
0577:                                    : null;
0578:                            Point lastPoint = getLastControlPoint();
0579:                            if (lastPoint != null)
0580:                                lastPoint = convertLocalToScene(lastPoint);
0581:                            if (targetPoint == null ? lastPoint == null
0582:                                    : targetPoint.equals(lastPoint))
0583:                                break;
0584:                        }
0585:                        routingPolicy = RoutingPolicy.ALWAYS_ROUTE;
0586:                        setControlPoints(router.routeConnection(this ), true);
0587:                    }
0588:                        break;
0589:                    case DISABLE_ROUTING:
0590:                        break;
0591:                    default:
0592:                        throw new IllegalStateException(
0593:                                "Unexpected routing policy: " + routingPolicy); // NOI18N
0594:                    }
0595:                }
0596:            }
0597:
0598:            /**
0599:             * Calculates a client area of the connection widget.
0600:             * @return the calculated client area
0601:             */
0602:            protected Rectangle calculateClientArea() {
0603:                calculateRouting();
0604:                int controlPointShapeRadius = controlPointShape.getRadius();
0605:                int controlPointShapeRadius2 = controlPointShapeRadius
0606:                        + controlPointShapeRadius;
0607:                int endPointShapeRadius = endPointShape.getRadius();
0608:
0609:                Rectangle rect = null;
0610:                for (Point point : controlPoints) {
0611:                    Rectangle addRect = new Rectangle(point.x
0612:                            - controlPointShapeRadius, point.y
0613:                            - controlPointShapeRadius,
0614:                            controlPointShapeRadius2, controlPointShapeRadius2);
0615:                    if (rect == null)
0616:                        rect = addRect;
0617:                    else
0618:                        rect.add(addRect);
0619:                }
0620:
0621:                Point firstPoint = getFirstControlPoint();
0622:                if (firstPoint != null) {
0623:                    int radius = Math.max(sourceAnchorShape.getRadius(),
0624:                            endPointShapeRadius);
0625:                    int radius2 = radius + radius;
0626:                    if (rect == null)
0627:                        rect = new Rectangle(firstPoint.x - radius,
0628:                                firstPoint.y - radius, radius2, radius2);
0629:                    else
0630:                        rect.add(new Rectangle(firstPoint.x - radius,
0631:                                firstPoint.y - radius, radius2, radius2));
0632:                }
0633:
0634:                Point lastPoint = getLastControlPoint();
0635:                if (lastPoint != null) {
0636:                    int radius = Math.max(targetAnchorShape.getRadius(),
0637:                            endPointShapeRadius);
0638:                    int radius2 = radius + radius;
0639:                    if (rect == null)
0640:                        rect = new Rectangle(lastPoint.x - radius, lastPoint.y
0641:                                - radius, radius2, radius2);
0642:                    else
0643:                        rect.add(new Rectangle(lastPoint.x - radius,
0644:                                lastPoint.y - radius, radius2, radius2));
0645:                }
0646:
0647:                if (rect != null)
0648:                    rect.grow(2, 2); // TODO - improve line width calculation
0649:
0650:                return rect != null ? rect : new Rectangle();
0651:            }
0652:
0653:            /**
0654:             * Returns whether the connection widget is validated and routed.
0655:             * @return true, if the connection widget is validated and routed
0656:             */
0657:            public boolean isValidated() {
0658:                return super .isValidated() && isRouted();
0659:            }
0660:
0661:            /**
0662:             * Returns whether the connection widget is routed.
0663:             * @return true if the connection widget is routed
0664:             */
0665:            public final boolean isRouted() {
0666:                return !routingRequired;
0667:            }
0668:
0669:            /**
0670:             * Schedules the connection widget for re-routing its path.
0671:             */
0672:            public final void reroute() {
0673:                routingRequired = true;
0674:                revalidate();
0675:            }
0676:
0677:            /**
0678:             * Returns the first control point.
0679:             * @return the first control point; null, if list of control points is empty
0680:             */
0681:            public final Point getFirstControlPoint() {
0682:                if (controlPoints.size() <= 0)
0683:                    return null;
0684:                return new Point(controlPoints.get(0));
0685:            }
0686:
0687:            /**
0688:             * Returns the last control point.
0689:             * @return the last control point; null, if list of control points is empty
0690:             */
0691:            public final Point getLastControlPoint() {
0692:                int size = controlPoints.size();
0693:                if (size <= 0)
0694:                    return null;
0695:                return new Point(controlPoints.get(size - 1));
0696:            }
0697:
0698:            /**
0699:             * Returns the rotation of the source anchor shape.
0700:             * @return the source anchor shape rotation
0701:             */
0702:            private double getSourceAnchorShapeRotation() {
0703:                if (controlPoints.size() <= 1)
0704:                    return 0.0;
0705:                Point point1 = controlPoints.get(0);
0706:                Point point2 = controlPoints.get(1);
0707:                return Math.atan2(point2.y - point1.y, point2.x - point1.x);
0708:            }
0709:
0710:            /**
0711:             * Returns the rotation of the target anchor shape.
0712:             * @return the target anchor shape rotation
0713:             */
0714:            public double getTargetAnchorShapeRotation() {
0715:                int size = controlPoints.size();
0716:                if (size <= 1)
0717:                    return 0.0;
0718:                Point point1 = controlPoints.get(size - 1);
0719:                Point point2 = controlPoints.get(size - 2);
0720:                return Math.atan2(point2.y - point1.y, point2.x - point1.x);
0721:            }
0722:
0723:            /**
0724:             * Returns whether a specified local location is a part of the connection widget. It checks whether the location is
0725:             * close to the control-points-based path (up to 4px from the line),
0726:             * close to the anchors (defined by AnchorShape) or
0727:             * close to the control points (PointShape).
0728:             * @param localLocation the local locaytion
0729:             * @return true, if the location is a part of the connection widget
0730:             */
0731:            public boolean isHitAt(Point localLocation) {
0732:                if (!super .isHitAt(localLocation))
0733:                    return false;
0734:
0735:                List<Point> controlPoints = getControlPoints();
0736:                for (int i = 0; i < controlPoints.size() - 1; i++) {
0737:                    Point point1 = controlPoints.get(i);
0738:                    Point point2 = controlPoints.get(i + 1);
0739:                    double dist = Line2D.ptSegDistSq(point1.x, point1.y,
0740:                            point2.x, point2.y, localLocation.x,
0741:                            localLocation.y);
0742:                    if (dist < HIT_DISTANCE_SQUARE)
0743:                        return true;
0744:                }
0745:
0746:                return getControlPointHitAt(localLocation) >= 0;
0747:            }
0748:
0749:            /**
0750:             * Returns whether the local location hits the first control point (also meant to be the source anchor).
0751:             * @param localLocation the local location
0752:             * @return true if it hits the first control point
0753:             */
0754:            public final boolean isFirstControlPointHitAt(Point localLocation) {
0755:                int endRadius = endPointShape.getRadius();
0756:                endRadius *= endRadius;
0757:                Point firstPoint = getFirstControlPoint();
0758:                if (firstPoint != null)
0759:                    if (Point2D.distanceSq(firstPoint.x, firstPoint.y,
0760:                            localLocation.x, localLocation.y) <= endRadius)
0761:                        return true;
0762:                return false;
0763:            }
0764:
0765:            /**
0766:             * Returns whether the local location hits the last control point (also meant to be the target anchor).
0767:             * @param localLocation the local location
0768:             * @return true if it hits the last control point
0769:             */
0770:            public final boolean isLastControlPointHitAt(Point localLocation) {
0771:                int endRadius = endPointShape.getRadius();
0772:                endRadius *= endRadius;
0773:                Point lastPoint = getLastControlPoint();
0774:                if (lastPoint != null)
0775:                    if (Point2D.distanceSq(lastPoint.x, lastPoint.y,
0776:                            localLocation.x, localLocation.y) <= endRadius)
0777:                        return true;
0778:                return false;
0779:            }
0780:
0781:            /**
0782:             * Returns an index of a control point that is hit by the local location
0783:             * @param localLocation the local location
0784:             * @return the index; -1 if no control point was hit
0785:             */
0786:            public final int getControlPointHitAt(Point localLocation) {
0787:                int controlRadius = controlPointShape.getRadius();
0788:                controlRadius *= controlRadius;
0789:
0790:                if (isFirstControlPointHitAt(localLocation))
0791:                    return 0;
0792:
0793:                if (isLastControlPointHitAt(localLocation))
0794:                    return controlPoints.size() - 1;
0795:
0796:                for (int i = 0; i < controlPoints.size(); i++) {
0797:                    Point point = controlPoints.get(i);
0798:                    if (Point2D.distanceSq(point.x, point.y, localLocation.x,
0799:                            localLocation.y) <= controlRadius)
0800:                        return i;
0801:                }
0802:
0803:                return -1;
0804:            }
0805:
0806:            /**
0807:             * Returns a cursor for a specified local location in the widget.
0808:             * If paintControlPoints is true and controlPointsCursor is non-null and local location is over a control point, then it return controlPointsCursor.
0809:             * Otherwise it return value from super.getCursorAt method.
0810:             * @param localLocation the local location
0811:             * @return the cursor
0812:             * @since 2.3
0813:             */
0814:            protected Cursor getCursorAt(Point localLocation) {
0815:                if (paintControlPoints) {
0816:                    Cursor pointsCursor = getControlPointsCursor();
0817:                    if (pointsCursor != null
0818:                            && getControlPointHitAt(localLocation) >= 0)
0819:                        return pointsCursor;
0820:                }
0821:                return super .getCursorAt(localLocation);
0822:            }
0823:
0824:            /**
0825:             * Paints the connection widget (the path, the anchor shapes, the control points, the end points).
0826:             */
0827:            protected void paintWidget() {
0828:                Graphics2D gr = getGraphics();
0829:                gr.setColor(getForeground());
0830:                GeneralPath path = null;
0831:
0832:                Point firstControlPoint = getFirstControlPoint();
0833:                Point lastControlPoint = getLastControlPoint();
0834:                boolean isSourceCutDistance = Math.abs(sourceAnchorShape
0835:                        .getCutDistance()) != 0.0;
0836:                boolean isTargetCutDistance = Math.abs(targetAnchorShape
0837:                        .getCutDistance()) != 0.0;
0838:                double firstControlPointRotation = firstControlPoint != null
0839:                        && (sourceAnchorShape.isLineOriented() || isSourceCutDistance) ? getSourceAnchorShapeRotation()
0840:                        : 0.0;
0841:                double lastControlPointRotation = lastControlPoint != null
0842:                        && (targetAnchorShape.isLineOriented() || isTargetCutDistance) ? getTargetAnchorShapeRotation()
0843:                        : 0.0;
0844:
0845:                List<Point> points;
0846:                if ((isSourceCutDistance || isTargetCutDistance)
0847:                        && controlPoints.size() >= 2) {
0848:                    points = new ArrayList<Point>(controlPoints);
0849:                    points
0850:                            .set(
0851:                                    0,
0852:                                    new Point(
0853:                                            firstControlPoint.x
0854:                                                    + (int) (sourceAnchorShape
0855:                                                            .getCutDistance() * Math
0856:                                                            .cos(firstControlPointRotation)),
0857:                                            firstControlPoint.y
0858:                                                    + (int) (sourceAnchorShape
0859:                                                            .getCutDistance() * Math
0860:                                                            .sin(firstControlPointRotation))));
0861:                    points
0862:                            .set(
0863:                                    controlPoints.size() - 1,
0864:                                    new Point(
0865:                                            lastControlPoint.x
0866:                                                    + (int) (targetAnchorShape
0867:                                                            .getCutDistance() * Math
0868:                                                            .cos(lastControlPointRotation)),
0869:                                            lastControlPoint.y
0870:                                                    + (int) (targetAnchorShape
0871:                                                            .getCutDistance() * Math
0872:                                                            .sin(lastControlPointRotation))));
0873:                } else {
0874:                    points = controlPoints;
0875:                }
0876:
0877:                if (controlPointCutDistance > 0) {
0878:                    for (int a = 0; a < points.size() - 1; a++) {
0879:                        Point p1 = points.get(a);
0880:                        Point p2 = points.get(a + 1);
0881:                        double len = p1.distance(p2);
0882:
0883:                        if (a > 0) {
0884:                            Point p0 = points.get(a - 1);
0885:                            double ll = p0.distance(p1);
0886:                            if (len < ll)
0887:                                ll = len;
0888:                            ll /= 2;
0889:                            double cll = controlPointCutDistance;
0890:                            if (cll > ll)
0891:                                cll = ll;
0892:                            double direction = Math.atan2(p2.y - p1.y, p2.x
0893:                                    - p1.x);
0894:                            if (!Double.isNaN(direction)) {
0895:                                path = addToPath(path, p1.x
0896:                                        + (int) (cll * Math.cos(direction)),
0897:                                        p1.y
0898:                                                + (int) (cll * Math
0899:                                                        .sin(direction)));
0900:                            }
0901:                        } else {
0902:                            path = addToPath(path, p1.x, p1.y);
0903:                        }
0904:
0905:                        if (a < points.size() - 2) {
0906:                            Point p3 = points.get(a + 2);
0907:                            double ll = p2.distance(p3);
0908:                            if (len < ll)
0909:                                ll = len;
0910:                            ll /= 2;
0911:                            double cll = controlPointCutDistance;
0912:                            if (cll > ll)
0913:                                cll = ll;
0914:                            double direction = Math.atan2(p2.y - p1.y, p2.x
0915:                                    - p1.x);
0916:                            if (!Double.isNaN(direction)) {
0917:                                path = addToPath(path, p2.x
0918:                                        - (int) (cll * Math.cos(direction)),
0919:                                        p2.y
0920:                                                - (int) (cll * Math
0921:                                                        .sin(direction)));
0922:                            }
0923:                        } else {
0924:                            path = addToPath(path, p2.x, p2.y);
0925:                        }
0926:                    }
0927:                } else {
0928:                    for (Point point : points)
0929:                        path = addToPath(path, point.x, point.y);
0930:                }
0931:                if (path != null) {
0932:                    Stroke previousStroke = gr.getStroke();
0933:                    gr.setPaint(getForeground());
0934:                    gr.setStroke(getStroke());
0935:                    gr.draw(path);
0936:                    gr.setStroke(previousStroke);
0937:                }
0938:
0939:                AffineTransform previousTransform;
0940:
0941:                if (firstControlPoint != null) {
0942:                    previousTransform = gr.getTransform();
0943:                    gr.translate(firstControlPoint.x, firstControlPoint.y);
0944:                    if (sourceAnchorShape.isLineOriented())
0945:                        gr.rotate(firstControlPointRotation);
0946:                    sourceAnchorShape.paint(gr, true);
0947:                    gr.setTransform(previousTransform);
0948:                }
0949:
0950:                if (lastControlPoint != null) {
0951:                    previousTransform = gr.getTransform();
0952:                    gr.translate(lastControlPoint.x, lastControlPoint.y);
0953:                    if (targetAnchorShape.isLineOriented())
0954:                        gr.rotate(lastControlPointRotation);
0955:                    targetAnchorShape.paint(gr, false);
0956:                    gr.setTransform(previousTransform);
0957:                }
0958:
0959:                if (paintControlPoints) {
0960:                    int last = controlPoints.size() - 1;
0961:                    for (int index = 0; index <= last; index++) {
0962:                        Point point = controlPoints.get(index);
0963:                        previousTransform = gr.getTransform();
0964:                        gr.translate(point.x, point.y);
0965:                        if (index == 0 || index == last)
0966:                            endPointShape.paint(gr);
0967:                        else
0968:                            controlPointShape.paint(gr);
0969:                        gr.setTransform(previousTransform);
0970:                    }
0971:                }
0972:            }
0973:
0974:            private GeneralPath addToPath(GeneralPath path, int x, int y) {
0975:                if (path == null) {
0976:                    path = new GeneralPath();
0977:                    path.moveTo(x, y);
0978:                } else {
0979:                    path.lineTo(x, y);
0980:                }
0981:                return path;
0982:            }
0983:
0984:            private class ConnectionEntry implements  Anchor.Entry {
0985:
0986:                private boolean source;
0987:
0988:                public ConnectionEntry(boolean source) {
0989:                    this .source = source;
0990:                }
0991:
0992:                public void revalidateEntry() {
0993:                    ConnectionWidget.this .reroute();
0994:                }
0995:
0996:                public ConnectionWidget getAttachedConnectionWidget() {
0997:                    return ConnectionWidget.this ;
0998:                }
0999:
1000:                public boolean isAttachedToConnectionSource() {
1001:                    return source;
1002:                }
1003:
1004:                public Anchor getAttachedAnchor() {
1005:                    return source ? ConnectionWidget.this .getSourceAnchor()
1006:                            : ConnectionWidget.this .getTargetAnchor();
1007:                }
1008:
1009:                public Anchor getOppositeAnchor() {
1010:                    return source ? ConnectionWidget.this.getTargetAnchor()
1011:                            : ConnectionWidget.this.getSourceAnchor();
1012:                }
1013:
1014:            }
1015:
1016:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.