Source Code Cross Referenced for EdgeRenderer.java in  » Graphic-Library » jgraph » org » jgraph » graph » 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 » Graphic Library » jgraph » org.jgraph.graph 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)EdgeRenderer.java	1.0 03-JUL-04
0003:         * 
0004:         * Copyright (c) 2001-2005 Gaudenz Alder
0005:         *  
0006:         * See LICENSE file in distribution for licensing details of this source file
0007:         */
0008:        package org.jgraph.graph;
0009:
0010:        import java.awt.BasicStroke;
0011:        import java.awt.Color;
0012:        import java.awt.Component;
0013:        import java.awt.Dimension;
0014:        import java.awt.Font;
0015:        import java.awt.FontMetrics;
0016:        import java.awt.GradientPaint;
0017:        import java.awt.Graphics;
0018:        import java.awt.Graphics2D;
0019:        import java.awt.Polygon;
0020:        import java.awt.Rectangle;
0021:        import java.awt.RenderingHints;
0022:        import java.awt.Shape;
0023:        import java.awt.geom.Ellipse2D;
0024:        import java.awt.geom.GeneralPath;
0025:        import java.awt.geom.Point2D;
0026:        import java.awt.geom.Rectangle2D;
0027:        import java.awt.image.BufferedImage;
0028:        import java.io.Serializable;
0029:        import java.lang.ref.WeakReference;
0030:        import java.util.Map;
0031:
0032:        import javax.swing.JComponent;
0033:        import javax.swing.UIManager;
0034:
0035:        import org.jgraph.JGraph;
0036:        import org.jgraph.util.Bezier;
0037:        import org.jgraph.util.Spline2D;
0038:
0039:        /**
0040:         * This renderer displays entries that implement the CellView interface.
0041:         * 
0042:         * @version 1.0 1/1/02
0043:         * @author Gaudenz Alder
0044:         */
0045:
0046:        public class EdgeRenderer extends JComponent implements 
0047:                CellViewRenderer, Serializable {
0048:
0049:            /** Static Graphics used for Font Metrics */
0050:            protected static transient Graphics fontGraphics;
0051:
0052:            // Headless environment does not allow graphics
0053:            static {
0054:                try {
0055:                    fontGraphics = new BufferedImage(1, 1,
0056:                            BufferedImage.TYPE_INT_RGB).getGraphics();
0057:                } catch (Error e) {
0058:                    // No font graphics
0059:                    fontGraphics = null;
0060:                }
0061:            }
0062:
0063:            /** A switch for painting the extra labels */
0064:            public boolean simpleExtraLabels = true;
0065:
0066:            /** Override this if you want the extra labels to appear in a special fontJ */
0067:            public Font extraLabelFont = null;
0068:
0069:            /** Reference to the font metrics of the above */
0070:            protected transient FontMetrics metrics;
0071:
0072:            /** Cache the current graph for drawing */
0073:            protected transient WeakReference graph;
0074:
0075:            /** Cache the current edgeview for drawing */
0076:            protected transient EdgeView view;
0077:
0078:            /** Painting attributes of the current edgeview */
0079:            protected transient int beginDeco, endDeco, beginSize, endSize,
0080:                    lineStyle;
0081:
0082:            /** Width of the current edge view */
0083:            protected transient float lineWidth;
0084:
0085:            /**
0086:             * Boolean attributes of the current edgeview. Fill flags are checked for
0087:             * valid decorations.
0088:             */
0089:            protected transient boolean labelBorder, beginFill, endFill, focus,
0090:                    selected, preview, opaque, childrenSelected,
0091:                    labelTransformEnabled, isMoveBelowZero;
0092:
0093:            /**
0094:             * Color attributes of the current edgeview. This components foreground is
0095:             * set to the edgecolor, the fontColor is in an extra variable. If the
0096:             * fontColor is null, the current foreground is used. The default background
0097:             * instead is used for text and is not visible if the label is not visible
0098:             * or if opaque is true.
0099:             */
0100:            protected transient Color borderColor, defaultForeground,
0101:                    defaultBackground, fontColor;
0102:
0103:            /** Contains the current dash pattern. Null means no pattern. */
0104:            protected transient float[] lineDash;
0105:
0106:            /** Contains the current dash offset. Null means no offset. */
0107:            protected transient float dashOffset = 0.0f;
0108:
0109:            /** The gradient color of the edge */
0110:            protected transient Color gradientColor = null;
0111:
0112:            /** The color of the graph grid */
0113:            protected transient Color gridColor = null;
0114:
0115:            /** The color of the second available handle */
0116:            protected transient Color lockedHandleColor = null;
0117:
0118:            /** The color of highlighted cells */
0119:            protected transient Color highlightColor = null;
0120:
0121:            /* THIS CODE WAS ADDED BY MARTIN KRUEGER 10/20/2003 */
0122:
0123:            protected Bezier bezier;
0124:
0125:            protected Spline2D spline;
0126:
0127:            /* END */
0128:
0129:            /**
0130:             * Constructs a renderer that may be used to render edges.
0131:             */
0132:            public EdgeRenderer() {
0133:                defaultForeground = UIManager.getColor("Tree.textForeground");
0134:                defaultBackground = UIManager.getColor("Tree.textBackground");
0135:            }
0136:
0137:            /**
0138:             * Sets view to work with, caching necessary values until the next call of
0139:             * this method or until some other methods with explicitly specified
0140:             * different view
0141:             */
0142:            void setView(CellView value) {
0143:                if (value instanceof  EdgeView) {
0144:                    view = (EdgeView) value;
0145:                    installAttributes(view);
0146:                } else {
0147:                    view = null;
0148:                }
0149:            }
0150:
0151:            /**
0152:             * Configure and return the renderer based on the passed in components. The
0153:             * value is typically set from messaging the graph with
0154:             * <code>convertValueToString</code>.
0155:             * 
0156:             * @param graph
0157:             *            the graph that that defines the rendering context.
0158:             * @param view
0159:             *            the cell view that should be rendered.
0160:             * @param sel
0161:             *            whether the object is selected.
0162:             * @param focus
0163:             *            whether the object has the focus.
0164:             * @param preview
0165:             *            whether we are drawing a preview.
0166:             * @return the component used to render the value.
0167:             */
0168:            public Component getRendererComponent(JGraph graph, CellView view,
0169:                    boolean sel, boolean focus, boolean preview) {
0170:                if (view instanceof  EdgeView && graph != null) {
0171:                    this .gridColor = graph.getGridColor();
0172:                    this .lockedHandleColor = graph.getLockedHandleColor();
0173:                    this .highlightColor = graph.getHighlightColor();
0174:                    this .isMoveBelowZero = graph.isMoveBelowZero();
0175:                    this .graph = new WeakReference(graph);
0176:                    this .focus = focus;
0177:                    this .selected = sel;
0178:                    this .preview = preview;
0179:                    this .childrenSelected = graph.getSelectionModel()
0180:                            .isChildrenSelected(view.getCell());
0181:                    setView(view);
0182:                    return this ;
0183:                }
0184:                return null;
0185:            }
0186:
0187:            /**
0188:             * Returns true if the edge shape intersects the given rectangle.
0189:             */
0190:            public boolean intersects(JGraph graph, CellView value,
0191:                    Rectangle rect) {
0192:                if (value instanceof  EdgeView && graph != null && value != null) {
0193:                    setView(value);
0194:
0195:                    // If we have two control points, we can get rid of hit
0196:                    // detection on do an intersection test on the two diagonals
0197:                    // of rect and the line between the two points
0198:                    EdgeView edgeView = (EdgeView) value;
0199:                    if (edgeView.getPointCount() == 2) {
0200:                        Point2D p0 = edgeView.getPoint(0);
0201:                        Point2D p1 = edgeView.getPoint(1);
0202:                        if (rect.intersectsLine(p0.getX(), p0.getY(),
0203:                                p1.getX(), p1.getY()))
0204:                            return true;
0205:                    } else {
0206:                        Graphics2D g2 = (Graphics2D) graph.getGraphics();
0207:                        if (g2.hit(rect, view.getShape(), true))
0208:                            return true;
0209:                    }
0210:                    Rectangle2D r = getLabelBounds(graph, view);
0211:                    if (r != null && r.intersects(rect))
0212:                        return true;
0213:                    Object[] labels = GraphConstants.getExtraLabels(view
0214:                            .getAllAttributes());
0215:                    if (labels != null) {
0216:                        for (int i = 0; i < labels.length; i++) {
0217:                            r = getExtraLabelBounds(graph, view, i);
0218:                            if (r != null && r.intersects(rect))
0219:                                return true;
0220:                        }
0221:                    }
0222:                }
0223:                return false;
0224:            }
0225:
0226:            /**
0227:             * Returns the bounds of the edge shape.
0228:             */
0229:            public Rectangle2D getBounds(CellView value) {
0230:                if (value instanceof  EdgeView && value != null) {
0231:                    // No need to call setView as getPaintBounds will
0232:                    view = (EdgeView) value;
0233:                    Rectangle2D r = getPaintBounds(view);
0234:                    JGraph graph = null;
0235:                    if (this .graph != null) {
0236:                        graph = (JGraph) this .graph.get();
0237:                    }
0238:                    Rectangle2D rect = getLabelBounds(graph, view);
0239:                    if (rect != null)
0240:                        Rectangle2D.union(r, rect, r);
0241:                    Object[] labels = GraphConstants.getExtraLabels(view
0242:                            .getAllAttributes());
0243:                    if (labels != null) {
0244:                        for (int i = 0; i < labels.length; i++) {
0245:                            rect = getExtraLabelBounds(graph, view, i);
0246:                            if (rect != null)
0247:                                Rectangle2D.union(r, rect, r);
0248:                        }
0249:                    }
0250:                    int b = (int) Math.ceil(lineWidth);
0251:                    r.setFrame(r.getX() - b, r.getY() - b,
0252:                            r.getWidth() + 2 * b, r.getHeight() + 2 * b);
0253:                    return r;
0254:                }
0255:                return null;
0256:            }
0257:
0258:            private boolean isLabelTransformEnabled() {
0259:                return labelTransformEnabled;
0260:            }
0261:
0262:            /**
0263:             * Estimates whether the transform for label should be applied. With the
0264:             * transform, the label will be painted along the edge. To apply transform,
0265:             * rotate graphics by the angle returned from {@link #getLabelAngle}
0266:             * 
0267:             * @return true, if transform can be applied, false otherwise
0268:             */
0269:            private boolean isLabelTransform(String label) {
0270:                if (!isLabelTransformEnabled()) {
0271:                    return false;
0272:                }
0273:                Point2D p = getLabelPosition(view);
0274:                if (p != null && label != null && label.length() > 0) {
0275:                    int sw = metrics.stringWidth(label);
0276:                    Point2D p1 = view.getPoint(0);
0277:                    Point2D p2 = view.getPoint(view.getPointCount() - 1);
0278:                    double length = Math.sqrt((p2.getX() - p1.getX())
0279:                            * (p2.getX() - p1.getX()) + (p2.getY() - p1.getY())
0280:                            * (p2.getY() - p1.getY()));
0281:                    if (!(length <= Double.NaN || length < sw)) {
0282:                        return true;
0283:                    }
0284:                }
0285:                return false;
0286:            }
0287:
0288:            /**
0289:             * Calculates the angle at which graphics should be rotated to paint label
0290:             * along the edge. Before calling this method always check that transform
0291:             * should be applied using {@linkisLabelTransform}
0292:             * 
0293:             * @return the value of the angle, 0 if the angle is zero or can't be
0294:             *         calculated
0295:             */
0296:            private double getLabelAngle(String label) {
0297:                Point2D p = getLabelPosition(view);
0298:                double angle = 0;
0299:                if (p != null && label != null && label.length() > 0) {
0300:                    int sw = metrics.stringWidth(label);
0301:                    // Note: For control points you may want to choose other
0302:                    // points depending on the segment the label is in.
0303:                    Point2D p1 = view.getPoint(0);
0304:                    Point2D p2 = view.getPoint(view.getPointCount() - 1);
0305:                    // Length of the edge
0306:                    double length = Math.sqrt((p2.getX() - p1.getX())
0307:                            * (p2.getX() - p1.getX()) + (p2.getY() - p1.getY())
0308:                            * (p2.getY() - p1.getY()));
0309:                    if (!(length <= Double.NaN || length < sw)) { // Label fits into
0310:                        // edge's length
0311:
0312:                        // To calculate projections of edge
0313:                        double cos = (p2.getX() - p1.getX()) / length;
0314:                        double sin = (p2.getY() - p1.getY()) / length;
0315:
0316:                        // Determine angle
0317:                        angle = Math.acos(cos);
0318:                        if (sin < 0) { // Second half
0319:                            angle = 2 * Math.PI - angle;
0320:                        }
0321:                    }
0322:                    if (angle > Math.PI / 2 && angle <= Math.PI * 3 / 2) {
0323:                        angle -= Math.PI;
0324:                    }
0325:                }
0326:                return angle;
0327:            }
0328:
0329:            /**
0330:             * Returns the label bounds of the specified view in the given graph.
0331:             */
0332:            public Rectangle2D getLabelBounds(JGraph paintingContext,
0333:                    EdgeView view) {
0334:                if (paintingContext == null && graph != null) {
0335:                    JGraph graph = (JGraph) this .graph.get();
0336:                    paintingContext = graph;
0337:                }
0338:                // No need to call setView as getLabelPosition will
0339:                String label = (paintingContext != null) ? paintingContext
0340:                        .convertValueToString(view) : String.valueOf(view
0341:                        .getCell());
0342:                if (label != null) {
0343:                    Point2D p = getLabelPosition(view);
0344:                    Dimension d = getLabelSize(view, label);
0345:                    return getLabelBounds(p, d, label);
0346:                } else {
0347:                    return null;
0348:                }
0349:            }
0350:
0351:            /**
0352:             * Returns the label bounds of the specified view in the given graph. Note:
0353:             * The index is the position of the String object for the label in the extra
0354:             * labels array of the view.
0355:             */
0356:            public Rectangle2D getExtraLabelBounds(JGraph paintingContext,
0357:                    EdgeView view, int index) {
0358:                if (paintingContext == null && graph != null) {
0359:                    JGraph graph = (JGraph) this .graph.get();
0360:                    paintingContext = graph;
0361:                }
0362:                setView(view);
0363:                Object[] labels = GraphConstants.getExtraLabels(view
0364:                        .getAllAttributes());
0365:                if (labels != null && index < labels.length) {
0366:                    Point2D p = getExtraLabelPosition(this .view, index);
0367:                    Dimension d = getExtraLabelSize(paintingContext, this .view,
0368:                            index);
0369:                    String label = (paintingContext != null) ? paintingContext
0370:                            .convertValueToString(labels[index]) : String
0371:                            .valueOf(labels[index]);
0372:                    return getLabelBounds(p, d, label);
0373:                }
0374:                return new Rectangle2D.Double(getX(), getY(), 0, 0);
0375:            }
0376:
0377:            /**
0378:             * Returns the label bounds of the specified view in the given graph.
0379:             */
0380:            public Rectangle2D getLabelBounds(Point2D p, Dimension d,
0381:                    String label) {
0382:                if (label != null && isLabelTransform(label)) {
0383:                    // With transform label is rotated, so we should
0384:                    // rotate the rectangle (sw, sh) and return the
0385:                    // bounding rectangle
0386:                    double angle = getLabelAngle(label);
0387:                    if (angle < 0)
0388:                        angle = -angle;
0389:                    if (angle > Math.PI / 2)
0390:                        angle %= Math.PI / 2;
0391:                    double yside = Math.abs(Math.cos(angle) * d.height
0392:                            + Math.sin(angle) * d.width);
0393:                    double xside = Math.abs(d.width * Math.cos(angle)
0394:                            + d.height * Math.sin(angle));
0395:                    // Getting maximum is not good, but I don't want to be
0396:                    // drown in calculations
0397:                    if (xside > yside)
0398:                        yside = xside;
0399:                    if (yside > xside)
0400:                        xside = yside;
0401:                    angle = getLabelAngle(label);
0402:
0403:                    // Increasing by height is safe, but I think the precise
0404:                    // value is font.descent layed on edge vector and
0405:                    // projected on each axis
0406:                    d.width = (int) xside + d.height;
0407:                    d.height = (int) yside + d.height;
0408:                }
0409:                if (p != null && d != null) {
0410:                    double x = Math.max(0, p.getX() - (d.width / 2));
0411:                    double y = Math.max(0, p.getY() - (d.height / 2));
0412:                    return new Rectangle2D.Double(x, y, d.width + 1,
0413:                            d.height + 1);
0414:                }
0415:                return null;
0416:            }
0417:
0418:            /**
0419:             * Returns the label position of the specified view in the given graph.
0420:             */
0421:            public Point2D getLabelPosition(EdgeView view) {
0422:                setView(view);
0423:                return getLabelPosition(view.getLabelPosition());
0424:            }
0425:
0426:            /**
0427:             * Returns the label position of the specified view in the given graph.
0428:             */
0429:            public Point2D getExtraLabelPosition(EdgeView view, int index) {
0430:                setView(view);
0431:                Point2D[] pts = GraphConstants.getExtraLabelPositions(view
0432:                        .getAllAttributes());
0433:                if (pts != null && index < pts.length)
0434:                    return getLabelPosition(pts[index]);
0435:                return null;
0436:            }
0437:
0438:            /**
0439:             * Returns the label position of the specified view in the given graph.
0440:             */
0441:            protected Point2D getLabelPosition(Point2D pos) {
0442:                Rectangle2D tmp = getPaintBounds(view);
0443:                int unit = GraphConstants.PERMILLE;
0444:                Point2D p0 = view.getPoint(0);
0445:                if (pos != null && tmp != null) {
0446:                    if (!isLabelTransformEnabled()) {
0447:                        return getRelativeLabelPosition(view, pos);
0448:                    } else {
0449:                        Point2D vector = view.getLabelVector();
0450:                        double dx = vector.getX();
0451:                        double dy = vector.getY();
0452:                        double len = Math.sqrt(dx * dx + dy * dy);
0453:                        if (len > 0) {
0454:                            double x = p0.getX() + (dx * pos.getX() / unit);
0455:                            double y = p0.getY() + (dy * pos.getX() / unit);
0456:                            x += (-dy * pos.getY() / len);
0457:                            y += (dx * pos.getY() / len);
0458:                            return new Point2D.Double(x, y);
0459:                        } else {
0460:                            return new Point2D.Double(p0.getX() + pos.getX(),
0461:                                    p0.getY() + pos.getY());
0462:                        }
0463:                    }
0464:                }
0465:                return null;
0466:            }
0467:
0468:            protected Point2D getRelativeLabelPosition(EdgeView edge,
0469:                    Point2D geometry) {
0470:                int pointCount = edge.getPointCount();
0471:
0472:                double length = 0;
0473:                double[] segments = new double[pointCount];
0474:                Point2D pt = edge.getPoint(0);
0475:
0476:                if (pt != null) {
0477:                    for (int i = 1; i < pointCount; i++) {
0478:                        Point2D tmp = edge.getPoint(i);
0479:
0480:                        if (tmp != null) {
0481:                            double dx = pt.getX() - tmp.getX();
0482:                            double dy = pt.getY() - tmp.getY();
0483:
0484:                            double segment = Math.sqrt(dx * dx + dy * dy);
0485:
0486:                            segments[i - 1] = segment;
0487:                            length += segment;
0488:                            pt = tmp;
0489:                        }
0490:                    }
0491:
0492:                    double x = geometry.getX() / GraphConstants.PERMILLE;
0493:                    double y = geometry.getY();
0494:
0495:                    double dist = x * length;
0496:                    length = 0;
0497:
0498:                    int index = 1;
0499:                    double segment = segments[0];
0500:
0501:                    while (dist > length + segment && index < pointCount - 1) {
0502:                        length += segment;
0503:                        segment = segments[index++];
0504:                    }
0505:
0506:                    double factor = (dist - length) / segment;
0507:
0508:                    Point2D p0 = edge.getPoint(index - 1);
0509:                    Point2D pe = edge.getPoint(index);
0510:
0511:                    if (p0 != null && pe != null) {
0512:                        double dx = pe.getX() - p0.getX();
0513:                        double dy = pe.getY() - p0.getY();
0514:
0515:                        double nx = dy / segment;
0516:                        double ny = dx / segment;
0517:
0518:                        double offsetX = 0;
0519:                        double offsetY = 0;
0520:
0521:                        Point2D offset = GraphConstants.getOffset(edge
0522:                                .getAllAttributes());
0523:
0524:                        if (offset != null) {
0525:                            offsetX = offset.getX();
0526:                            offsetY = offset.getY();
0527:                        }
0528:
0529:                        x = p0.getX() + dx * factor + nx * y + offsetX;
0530:                        y = p0.getY() + dy * factor + ny * y + offsetY;
0531:
0532:                        return new Point2D.Double(x, y);
0533:                    }
0534:                }
0535:
0536:                return null;
0537:            }
0538:
0539:            /**
0540:             * Returns the label size of the specified view in the given graph.
0541:             */
0542:            public Dimension getExtraLabelSize(JGraph paintingContext,
0543:                    EdgeView view, int index) {
0544:                Object[] labels = GraphConstants.getExtraLabels(view
0545:                        .getAllAttributes());
0546:                if (labels != null && index < labels.length) {
0547:                    String label = (paintingContext != null) ? paintingContext
0548:                            .convertValueToString(labels[index]) : String
0549:                            .valueOf(labels[index]);
0550:                    return getLabelSize(view, label);
0551:                }
0552:                return null;
0553:            }
0554:
0555:            /**
0556:             * Returns the label size of the specified view in the given graph.
0557:             */
0558:            public Dimension getLabelSize(EdgeView view, String label) {
0559:                if (label != null && fontGraphics != null) {
0560:                    fontGraphics.setFont(GraphConstants.getFont(view
0561:                            .getAllAttributes()));
0562:                    metrics = fontGraphics.getFontMetrics();
0563:                    int sw = metrics.stringWidth(label);
0564:                    int sh = metrics.getHeight();
0565:                    return new Dimension(sw, sh);
0566:                }
0567:                return null;
0568:            }
0569:
0570:            /**
0571:             * Installs the attributes of specified cell in this renderer instance. This
0572:             * means, retrieve every published key from the cells hashtable and set
0573:             * global variables or superclass properties accordingly.
0574:             * 
0575:             * @param view
0576:             *            the cell view to retrieve the attribute values from.
0577:             */
0578:            protected void installAttributes(CellView view) {
0579:                Map map = view.getAllAttributes();
0580:                beginDeco = GraphConstants.getLineBegin(map);
0581:                beginSize = GraphConstants.getBeginSize(map);
0582:                beginFill = GraphConstants.isBeginFill(map)
0583:                        && isFillable(beginDeco);
0584:                endDeco = GraphConstants.getLineEnd(map);
0585:                endSize = GraphConstants.getEndSize(map);
0586:                endFill = GraphConstants.isEndFill(map) && isFillable(endDeco);
0587:                lineWidth = GraphConstants.getLineWidth(map);
0588:                Edge.Routing routing = GraphConstants.getRouting(map);
0589:                lineStyle = (routing != null && view instanceof  EdgeView) ? routing
0590:                        .getPreferredLineStyle((EdgeView) view)
0591:                        : Edge.Routing.NO_PREFERENCE;
0592:                if (lineStyle == Edge.Routing.NO_PREFERENCE)
0593:                    lineStyle = GraphConstants.getLineStyle(map);
0594:                lineDash = GraphConstants.getDashPattern(map);
0595:                dashOffset = GraphConstants.getDashOffset(map);
0596:                borderColor = GraphConstants.getBorderColor(map);
0597:                Color foreground = GraphConstants.getLineColor(map);
0598:                setForeground((foreground != null) ? foreground
0599:                        : defaultForeground);
0600:                Color background = GraphConstants.getBackground(map);
0601:                setBackground((background != null) ? background
0602:                        : defaultBackground);
0603:                Color gradientColor = GraphConstants.getGradientColor(map);
0604:                setGradientColor(gradientColor);
0605:                setOpaque(GraphConstants.isOpaque(map));
0606:                setFont(GraphConstants.getFont(map));
0607:                Color tmp = GraphConstants.getForeground(map);
0608:                fontColor = (tmp != null) ? tmp : getForeground();
0609:                labelTransformEnabled = GraphConstants.isLabelAlongEdge(map);
0610:            }
0611:
0612:            protected boolean isFillable(int decoration) {
0613:                return !(decoration == GraphConstants.ARROW_SIMPLE
0614:                        || decoration == GraphConstants.ARROW_LINE || decoration == GraphConstants.ARROW_DOUBLELINE);
0615:            }
0616:
0617:            /**
0618:             * Returns the bounds of the edge shape without label
0619:             */
0620:            public Rectangle2D getPaintBounds(EdgeView view) {
0621:                Rectangle2D rec = null;
0622:                setView(view);
0623:                if (view.getShape() != null)
0624:                    rec = view.getShape().getBounds();
0625:                else
0626:                    rec = new Rectangle2D.Double(0, 0, 0, 0);
0627:                return rec;
0628:            }
0629:
0630:            /**
0631:             * Paint the renderer.
0632:             */
0633:            public void paint(Graphics g) {
0634:                if (view.isLeaf()) {
0635:                    Shape edgeShape = view.getShape();
0636:                    // Sideeffect: beginShape, lineShape, endShape
0637:                    if (edgeShape != null) {
0638:                        Graphics2D g2 = (Graphics2D) g;
0639:                        g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
0640:                                RenderingHints.VALUE_STROKE_PURE);
0641:                        int c = BasicStroke.CAP_BUTT;
0642:                        int j = BasicStroke.JOIN_MITER;
0643:                        setOpaque(false);
0644:                        super .paint(g);
0645:                        translateGraphics(g);
0646:                        g.setColor(getForeground());
0647:                        if (lineWidth > 0) {
0648:                            g2.setStroke(new BasicStroke(lineWidth, c, j));
0649:                            if (gradientColor != null && !preview) {
0650:                                g2.setPaint(new GradientPaint(0, 0,
0651:                                        getBackground(), getWidth(),
0652:                                        getHeight(), gradientColor, true));
0653:                            }
0654:                            if (view.beginShape != null) {
0655:                                if (beginFill)
0656:                                    g2.fill(view.beginShape);
0657:                                g2.draw(view.beginShape);
0658:                            }
0659:                            if (view.endShape != null) {
0660:                                if (endFill)
0661:                                    g2.fill(view.endShape);
0662:                                g2.draw(view.endShape);
0663:                            }
0664:                            if (lineDash != null) // Dash For Line Only
0665:                                g2.setStroke(new BasicStroke(lineWidth, c, j,
0666:                                        10.0f, lineDash, dashOffset));
0667:                            if (view.lineShape != null)
0668:                                g2.draw(view.lineShape);
0669:                        }
0670:
0671:                        if (selected) { // Paint Selected
0672:                            g2.setStroke(GraphConstants.SELECTION_STROKE);
0673:                            g2.setColor(highlightColor);
0674:                            if (view.beginShape != null)
0675:                                g2.draw(view.beginShape);
0676:                            if (view.lineShape != null)
0677:                                g2.draw(view.lineShape);
0678:                            if (view.endShape != null)
0679:                                g2.draw(view.endShape);
0680:                        }
0681:                        g2.setStroke(new BasicStroke(1));
0682:                        g.setFont((extraLabelFont != null) ? extraLabelFont
0683:                                : getFont());
0684:                        Object[] labels = GraphConstants.getExtraLabels(view
0685:                                .getAllAttributes());
0686:                        JGraph graph = (JGraph) this .graph.get();
0687:                        if (labels != null) {
0688:                            for (int i = 0; i < labels.length; i++)
0689:                                paintLabel(g, graph
0690:                                        .convertValueToString(labels[i]),
0691:                                        getExtraLabelPosition(view, i),
0692:                                        false || !simpleExtraLabels);
0693:                        }
0694:                        if (graph.getEditingCell() != view.getCell()) {
0695:                            g.setFont(getFont());
0696:                            Object label = graph.convertValueToString(view);
0697:                            if (label != null) {
0698:                                paintLabel(g, label.toString(),
0699:                                        getLabelPosition(view), true);
0700:                            }
0701:                        }
0702:                    }
0703:                } else {
0704:                    paintSelectionBorder(g);
0705:                }
0706:            }
0707:
0708:            /**
0709:             * Provided for subclassers to paint a selection border.
0710:             */
0711:            protected void paintSelectionBorder(Graphics g) {
0712:                ((Graphics2D) g).setStroke(GraphConstants.SELECTION_STROKE);
0713:                if (childrenSelected)
0714:                    g.setColor(gridColor);
0715:                else if (focus && selected)
0716:                    g.setColor(lockedHandleColor);
0717:                else if (selected)
0718:                    g.setColor(highlightColor);
0719:                if (childrenSelected || selected) {
0720:                    Dimension d = getSize();
0721:                    g.drawRect(0, 0, d.width - 1, d.height - 1);
0722:                }
0723:            }
0724:
0725:            // This if for subclassers that to not want the graphics
0726:            // to be relative to the top, left corner of this component.
0727:            // Note: Override this method with an empty implementation
0728:            // if you want absolute positions for your edges
0729:            protected void translateGraphics(Graphics g) {
0730:                g.translate(-getX(), -getY());
0731:            }
0732:
0733:            /**
0734:             * Paint the specified label for the current edgeview.
0735:             */
0736:            protected void paintLabel(Graphics g, String label, Point2D p,
0737:                    boolean mainLabel) {
0738:                if (p != null && label != null && label.length() > 0
0739:                        && metrics != null) {
0740:                    int sw = metrics.stringWidth(label);
0741:                    int sh = metrics.getHeight();
0742:                    Graphics2D g2 = (Graphics2D) g;
0743:                    boolean applyTransform = isLabelTransform(label);
0744:                    double angle = 0;
0745:                    int dx = -sw / 2;
0746:                    int offset = isMoveBelowZero || applyTransform ? 0 : Math
0747:                            .min(0, (int) (dx + p.getX()));
0748:
0749:                    g2.translate(p.getX() - offset, p.getY());
0750:                    if (applyTransform) {
0751:                        angle = getLabelAngle(label);
0752:                        g2.rotate(angle);
0753:                    }
0754:                    if (isOpaque() && mainLabel) {
0755:                        g.setColor(getBackground());
0756:                        g.fillRect(-sw / 2 - 1, -sh / 2 - 1, sw + 2, sh + 2);
0757:                    }
0758:                    if (borderColor != null && mainLabel) {
0759:                        g.setColor(borderColor);
0760:                        g.drawRect(-sw / 2 - 1, -sh / 2 - 1, sw + 2, sh + 2);
0761:                    }
0762:
0763:                    int dy = +sh / 4;
0764:                    g.setColor(fontColor);
0765:                    if (applyTransform && borderColor == null && !isOpaque()) {
0766:                        // Shift label perpendicularly by the descent so it
0767:                        // doesn't cross the line.
0768:                        dy = -metrics.getDescent();
0769:                    }
0770:                    g.drawString(label, dx, dy);
0771:                    if (applyTransform) {
0772:                        // Undo the transform
0773:                        g2.rotate(-angle);
0774:                    }
0775:                    g2.translate(-p.getX() + offset, -p.getY());
0776:                }
0777:            }
0778:
0779:            /**
0780:             * Returns the shape that represents the current edge in the context of the
0781:             * current graph. This method sets the global beginShape, lineShape and
0782:             * endShape variables as a side-effect.
0783:             */
0784:            protected Shape createShape() {
0785:                int n = view.getPointCount();
0786:                if (n > 1) {
0787:                    // Following block may modify static vars as side effect (Flyweight
0788:                    // Design)
0789:                    EdgeView tmp = view;
0790:                    Point2D[] p = null;
0791:                    p = new Point2D[n];
0792:                    for (int i = 0; i < n; i++) {
0793:                        Point2D pt = tmp.getPoint(i);
0794:                        if (pt == null)
0795:                            return null; // exit
0796:                        p[i] = new Point2D.Double(pt.getX(), pt.getY());
0797:                    }
0798:
0799:                    // End of Side-Effect Block
0800:                    // Undo Possible MT-Side Effects
0801:                    if (view != tmp) {
0802:                        view = tmp;
0803:                        installAttributes(view);
0804:                    }
0805:                    // End of Undo
0806:                    if (view.sharedPath == null) {
0807:                        view.sharedPath = new GeneralPath(
0808:                                GeneralPath.WIND_NON_ZERO, n);
0809:                    } else {
0810:                        view.sharedPath.reset();
0811:                    }
0812:                    view.beginShape = view.lineShape = view.endShape = null;
0813:                    Point2D p0 = p[0];
0814:                    Point2D pe = p[n - 1];
0815:                    Point2D p1 = p[1];
0816:                    Point2D p2 = p[n - 2];
0817:
0818:                    if (lineStyle == GraphConstants.STYLE_BEZIER && n > 2) {
0819:                        bezier = new Bezier(p);
0820:                        p2 = bezier.getPoint(bezier.getPointCount() - 1);
0821:                    } else if (lineStyle == GraphConstants.STYLE_SPLINE
0822:                            && n > 2) {
0823:                        spline = new Spline2D(p);
0824:                        double[] point = spline.getPoint(0.9875);
0825:                        // Extrapolate p2 away from the end point, pe, to avoid integer
0826:                        // rounding errors becoming too large when creating the line end
0827:                        double scaledX = pe.getX()
0828:                                - ((pe.getX() - point[0]) * 128);
0829:                        double scaledY = pe.getY()
0830:                                - ((pe.getY() - point[1]) * 128);
0831:                        p2.setLocation(scaledX, scaledY);
0832:                    }
0833:
0834:                    if (beginDeco != GraphConstants.ARROW_NONE) {
0835:                        view.beginShape = createLineEnd(beginSize, beginDeco,
0836:                                p1, p0);
0837:                    }
0838:                    if (endDeco != GraphConstants.ARROW_NONE) {
0839:                        view.endShape = createLineEnd(endSize, endDeco, p2, pe);
0840:                    }
0841:                    view.sharedPath
0842:                            .moveTo((float) p0.getX(), (float) p0.getY());
0843:                    /* THIS CODE WAS ADDED BY MARTIN KRUEGER 10/20/2003 */
0844:                    if (lineStyle == GraphConstants.STYLE_BEZIER && n > 2) {
0845:                        Point2D[] b = bezier.getPoints();
0846:                        view.sharedPath.quadTo((float) b[0].getX(),
0847:                                (float) b[0].getY(), (float) p1.getX(),
0848:                                (float) p1.getY());
0849:                        for (int i = 2; i < n - 1; i++) {
0850:                            Point2D b0 = b[2 * i - 3];
0851:                            Point2D b1 = b[2 * i - 2];
0852:                            view.sharedPath.curveTo((float) b0.getX(),
0853:                                    (float) b0.getY(), (float) b1.getX(),
0854:                                    (float) b1.getY(), (float) p[i].getX(),
0855:                                    (float) p[i].getY());
0856:                        }
0857:                        view.sharedPath.quadTo((float) b[b.length - 1].getX(),
0858:                                (float) b[b.length - 1].getY(),
0859:                                (float) p[n - 1].getX(), (float) p[n - 1]
0860:                                        .getY());
0861:                    } else if (lineStyle == GraphConstants.STYLE_SPLINE
0862:                            && n > 2) {
0863:                        for (double t = 0; t <= 1; t += 0.0125) {
0864:                            double[] xy = spline.getPoint(t);
0865:                            view.sharedPath
0866:                                    .lineTo((float) xy[0], (float) xy[1]);
0867:                        }
0868:                    }
0869:                    /* END */
0870:                    else {
0871:                        for (int i = 1; i < n - 1; i++)
0872:                            view.sharedPath.lineTo((float) p[i].getX(),
0873:                                    (float) p[i].getY());
0874:                        view.sharedPath.lineTo((float) pe.getX(), (float) pe
0875:                                .getY());
0876:                    }
0877:                    view.sharedPath
0878:                            .moveTo((float) pe.getX(), (float) pe.getY());
0879:                    if (view.endShape == null && view.beginShape == null) {
0880:                        // With no end decorations the line shape is the same as the
0881:                        // shared path and memory
0882:                        view.lineShape = view.sharedPath;
0883:                    } else {
0884:                        view.lineShape = (GeneralPath) view.sharedPath.clone();
0885:                        if (view.endShape != null)
0886:                            view.sharedPath.append(view.endShape, true);
0887:                        if (view.beginShape != null)
0888:                            view.sharedPath.append(view.beginShape, true);
0889:                    }
0890:                    return view.sharedPath;
0891:                }
0892:                return null;
0893:            }
0894:
0895:            /**
0896:             * Paint the current view's direction. Sets tmpPoint as a side-effect such
0897:             * that the invoking method can use it to determine the connection point to
0898:             * this decoration.
0899:             */
0900:            protected Shape createLineEnd(int size, int style, Point2D src,
0901:                    Point2D dst) {
0902:                if (src == null || dst == null)
0903:                    return null;
0904:                int d = (int) Math.max(1, dst.distance(src));
0905:                int ax = (int) -(size * (dst.getX() - src.getX()) / d);
0906:                int ay = (int) -(size * (dst.getY() - src.getY()) / d);
0907:                if (style == GraphConstants.ARROW_DIAMOND) {
0908:                    Polygon poly = new Polygon();
0909:                    poly.addPoint((int) dst.getX(), (int) dst.getY());
0910:                    poly.addPoint((int) (dst.getX() + ax / 2 + ay / 3),
0911:                            (int) (dst.getY() + ay / 2 - ax / 3));
0912:                    Point2D last = (Point2D) dst.clone();
0913:                    dst.setLocation(dst.getX() + ax, dst.getY() + ay);
0914:                    poly.addPoint((int) dst.getX(), (int) dst.getY());
0915:                    poly.addPoint((int) (last.getX() + ax / 2 - ay / 3),
0916:                            (int) (last.getY() + ay / 2 + ax / 3));
0917:                    return poly;
0918:
0919:                } else if (style == GraphConstants.ARROW_TECHNICAL
0920:                        || style == GraphConstants.ARROW_CLASSIC) {
0921:                    Polygon poly = new Polygon();
0922:                    poly.addPoint((int) dst.getX(), (int) dst.getY());
0923:                    poly.addPoint((int) (dst.getX() + ax + ay / 2), (int) (dst
0924:                            .getY()
0925:                            + ay - ax / 2));
0926:                    Point2D last = (Point2D) dst.clone();
0927:                    if (style == GraphConstants.ARROW_CLASSIC) {
0928:                        dst.setLocation((int) (dst.getX() + ax * 2 / 3),
0929:                                (int) (dst.getY() + ay * 2 / 3));
0930:                        poly.addPoint((int) dst.getX(), (int) dst.getY());
0931:                    } else if (style == GraphConstants.ARROW_DIAMOND) {
0932:                        dst.setLocation(dst.getX() + 2 * ax, dst.getY() + 2
0933:                                * ay);
0934:                        poly.addPoint((int) dst.getX(), (int) dst.getY());
0935:                    } else
0936:                        dst.setLocation((int) (dst.getX() + ax), (int) (dst
0937:                                .getY() + ay));
0938:                    poly.addPoint((int) (last.getX() + ax - ay / 2),
0939:                            (int) (last.getY() + ay + ax / 2));
0940:                    return poly;
0941:
0942:                } else if (style == GraphConstants.ARROW_SIMPLE) {
0943:                    GeneralPath path = new GeneralPath(
0944:                            GeneralPath.WIND_NON_ZERO, 4);
0945:                    path.moveTo((float) (dst.getX() + ax + ay / 2),
0946:                            (float) (dst.getY() + ay - ax / 2));
0947:                    path.lineTo((float) dst.getX(), (float) dst.getY());
0948:                    path.lineTo((float) (dst.getX() + ax - ay / 2),
0949:                            (float) (dst.getY() + ay + ax / 2));
0950:                    return path;
0951:
0952:                } else if (style == GraphConstants.ARROW_CIRCLE) {
0953:                    Ellipse2D ellipse = new Ellipse2D.Float((float) (dst.getX()
0954:                            + ax / 2 - size / 2),
0955:                            (float) (dst.getY() + ay / 2 - size / 2), size,
0956:                            size);
0957:                    dst.setLocation(dst.getX() + ax, dst.getY() + ay);
0958:                    return ellipse;
0959:
0960:                } else if (style == GraphConstants.ARROW_LINE
0961:                        || style == GraphConstants.ARROW_DOUBLELINE) {
0962:                    GeneralPath path = new GeneralPath(
0963:                            GeneralPath.WIND_NON_ZERO, 4);
0964:                    path.moveTo((float) (dst.getX() + ax / 2 + ay / 2),
0965:                            (float) (dst.getY() + ay / 2 - ax / 2));
0966:                    path.lineTo((float) (dst.getX() + ax / 2 - ay / 2),
0967:                            (float) (dst.getY() + ay / 2 + ax / 2));
0968:                    if (style == GraphConstants.ARROW_DOUBLELINE) {
0969:                        path.moveTo((float) (dst.getX() + ax / 3 + ay / 2),
0970:                                (float) (dst.getY() + ay / 3 - ax / 2));
0971:                        path.lineTo((float) (dst.getX() + ax / 3 - ay / 2),
0972:                                (float) (dst.getY() + ay / 3 + ax / 2));
0973:                    }
0974:                    return path;
0975:                }
0976:                return null;
0977:            }
0978:
0979:            /**
0980:             * @return Returns the gradientColor.
0981:             */
0982:            public Color getGradientColor() {
0983:                return gradientColor;
0984:            }
0985:
0986:            /**
0987:             * @param gradientColor
0988:             *            The gradientColor to set.
0989:             */
0990:            public void setGradientColor(Color gradientColor) {
0991:                this .gradientColor = gradientColor;
0992:            }
0993:
0994:            /**
0995:             * Overridden for performance reasons. See the <a
0996:             * href="#override">Implementation Note </a> for more information.
0997:             */
0998:            public void validate() {
0999:            }
1000:
1001:            /**
1002:             * Overridden for performance reasons. See the <a
1003:             * href="#override">Implementation Note </a> for more information.
1004:             */
1005:            public void revalidate() {
1006:            }
1007:
1008:            /**
1009:             * Overridden for performance reasons. See the <a
1010:             * href="#override">Implementation Note </a> for more information.
1011:             */
1012:            public void repaint(long tm, int x, int y, int width, int height) {
1013:            }
1014:
1015:            /**
1016:             * Overridden for performance reasons. See the <a
1017:             * href="#override">Implementation Note </a> for more information.
1018:             */
1019:            public void repaint(Rectangle r) {
1020:            }
1021:
1022:            /**
1023:             * Overridden for performance reasons. See the <a
1024:             * href="#override">Implementation Note </a> for more information.
1025:             */
1026:            protected void firePropertyChange(String propertyName,
1027:                    Object oldValue, Object newValue) {
1028:                // Strings get interned...
1029:                if (propertyName == "text")
1030:                    super .firePropertyChange(propertyName, oldValue, newValue);
1031:            }
1032:
1033:            /**
1034:             * Overridden for performance reasons. See the <a
1035:             * href="#override">Implementation Note </a> for more information.
1036:             */
1037:            public void firePropertyChange(String propertyName, byte oldValue,
1038:                    byte newValue) {
1039:            }
1040:
1041:            /**
1042:             * Overridden for performance reasons. See the <a
1043:             * href="#override">Implementation Note </a> for more information.
1044:             */
1045:            public void firePropertyChange(String propertyName, char oldValue,
1046:                    char newValue) {
1047:            }
1048:
1049:            /**
1050:             * Overridden for performance reasons. See the <a
1051:             * href="#override">Implementation Note </a> for more information.
1052:             */
1053:            public void firePropertyChange(String propertyName, short oldValue,
1054:                    short newValue) {
1055:            }
1056:
1057:            /**
1058:             * Overridden for performance reasons. See the <a
1059:             * href="#override">Implementation Note </a> for more information.
1060:             */
1061:            public void firePropertyChange(String propertyName, int oldValue,
1062:                    int newValue) {
1063:            }
1064:
1065:            /**
1066:             * Overridden for performance reasons. See the <a
1067:             * href="#override">Implementation Note </a> for more information.
1068:             */
1069:            public void firePropertyChange(String propertyName, long oldValue,
1070:                    long newValue) {
1071:            }
1072:
1073:            /**
1074:             * Overridden for performance reasons. See the <a
1075:             * href="#override">Implementation Note </a> for more information.
1076:             */
1077:            public void firePropertyChange(String propertyName, float oldValue,
1078:                    float newValue) {
1079:            }
1080:
1081:            /**
1082:             * Overridden for performance reasons. See the <a
1083:             * href="#override">Implementation Note </a> for more information.
1084:             */
1085:            public void firePropertyChange(String propertyName,
1086:                    double oldValue, double newValue) {
1087:            }
1088:
1089:            /**
1090:             * Overridden for performance reasons. See the <a
1091:             * href="#override">Implementation Note </a> for more information.
1092:             */
1093:            public void firePropertyChange(String propertyName,
1094:                    boolean oldValue, boolean newValue) {
1095:            }
1096:
1097:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.