Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/graph/impl/DirectedGraphRenderer.java


1   //
2   // Copyright(c) 2002, Chris Leung
3   //
4   
5   package com.port80.graph.impl;
6   
7   import java.awt.BasicStroke;
8   import java.awt.Color;
9   import java.awt.Font;
10  import java.awt.FontMetrics;
11  import java.awt.Graphics2D;
12  import java.awt.Shape;
13  import java.awt.geom.AffineTransform;
14  import java.awt.geom.GeneralPath;
15  import java.awt.geom.Point2D;
16  import java.awt.geom.Rectangle2D;
17  import java.util.Collection;
18  import java.util.Iterator;
19  import java.util.TreeSet;
20  
21  import com.port80.graph.IArrow;
22  import com.port80.graph.IEdge;
23  import com.port80.graph.IGraph;
24  import com.port80.graph.IGraphRenderer;
25  import com.port80.graph.IGraphShape;
26  import com.port80.graph.IGraphStroke;
27  import com.port80.graph.IVertex;
28  import com.port80.graph.dot.impl.DotRoute;
29  import com.port80.util.msg;
30  import com.port80.util.sprint;
31  import com.port80.util.attr.FontFactory;
32  import com.port80.util.attr.IAttrTable;
33  
34  /** Render directed graph.
35   */
36  public class DirectedGraphRenderer implements IGraphRenderer {
37  
38    // Static fields ///////////////////////////////////////////////////////
39    //
40  
41    private static final String NAME = "DirectedGraphRenderer";
42    private static final boolean DEBUG = false;
43  
44    // Instance fields /////////////////////////////////////////////////////
45    //
46    private boolean fDirty = true;
47    private double fScale = 1.0;
48    private String fScaleStr = "";
49  
50    // Constructors ////////////////////////////////////////////////////////
51    //
52  
53    /** Constructor for GraphPanel. */
54    public DirectedGraphRenderer() {
55    }
56  
57    // IGraphRenderer interface ////////////////////////////////////////////
58    //
59  
60    /** Calculate the geometry of an IVertex and update its -shape attribute.
61     *
62     *  @return The updated shape.
63     */
64    public Shape updateShape(Graphics2D g2d, IVertex v) {
65      if (false)
66        msg.println("DirectedGraphRenderer.updateShape(IVertex): " + v.getName());
67      String label = v.getAttrString("label");
68      if (DEBUG)
69        if (label == null)
70          msg.err(NAME + ".updateShape(IVertex): label==null");
71      //
72      Font font = updateFont(v);
73      int minwidth = v.getAttrInt("minwidth");
74      int minheight = v.getAttrInt("minheight");
75      int exclude = v.getAttrInt("exclude", 0);
76      Point2D pos = (Point2D) v.getAttr("pos");
77      Color fontcolor = (Color) v.getAttr("fontcolor");
78      Color bordercolor = (Color) v.getAttr("color");
79      Color fillcolor = (Color) v.getAttr("fillcolor");
80      IGraphStroke stroke = updateStroke(v, "style",false);
81      if (pos == null)
82        pos = new Point2D.Double(0.0, 0.0);
83      IGraphShape gshape = (IGraphShape) v.getAttrCached("shape");
84      gshape.update(
85        g2d,
86        label,
87        pos,
88        minwidth,
89        minheight,
90        font,
91        stroke,
92        fontcolor,
93        bordercolor,
94        fillcolor,
95        exclude);
96      Rectangle2D bounds = gshape.getBounds2D();
97      v.setAttr("-bounds", bounds);
98      if (DEBUG)
99        msg.println(
100         NAME
101           + ".updateShape(IVertex): v="
102           + v.getName()
103           + ", bounds="
104           + bounds.toString());
105     //
106     // Update out edges label dimensions.
107     //
108     IEdge[] outs = v.outs();
109     for (int i = 0, max = outs.length; i < max; ++i)
110       updateLabelBounds(g2d, outs[i]);
111     return gshape;
112   }
113 
114   /** Calculate the geometry of all vertices in a graph. */
115   public void updateShape(Graphics2D g2d, IGraph graph) {
116     if (false)
117       msg.println(
118         "DirectedGraphRenderer.updateShape(IGraph): " + graph.getName());
119     Collection c = graph.allVertices();
120     IVertex v;
121     for (Iterator it = c.iterator(); it.hasNext();) {
122       v = (IVertex) it.next();
123       updateShape(g2d, v);
124     }
125   }
126 
127   ////////////////////////////////////////////////////////////////////////
128 
129   public void setScale(double d) {
130     fScale = d;
131     if (fScale != 1.0)
132       fScaleStr = sprint.f(",%.2f").a(1 / fScale).end();
133     else
134       fScaleStr = "";
135   }
136 
137   public void render(Graphics2D g2d, IVertex v) {
138     if (false)
139       msg.println("DirectedGraphRenderer.render(IVertex): " + v.getName());
140     IGraphShape gshape = (IGraphShape) v.getAttr("-shape");
141     if (DEBUG)
142       msg.println("\tShape=" + gshape);
143     gshape.render(g2d);
144   }
145 
146   public void renderBus(Graphics2D g2d, IVertex v) {
147     if (false)
148       msg.println("DirectedGraphRenderer.renderBus(IVertex): " + v.getName());
149     if (fDirty) {
150       updateShape(g2d, v);
151       // Update in edges just to make sure.
152       IEdge[] ins = v.ins();
153       for (int i = 0, max = ins.length; i < max; ++i) {
154         updateLabelBounds(g2d, ins[i]);
155       }
156     }
157     DotRoute tobus = (DotRoute) v.getAttrCached("tobus");
158     DotRoute frombus = (DotRoute) v.getAttrCached("frombus");
159     DotRoute inbus = (DotRoute) v.getAttrCached("inbus");
160     DotRoute outbus = (DotRoute) v.getAttrCached("outbus");
161     Color buscolor;
162     g2d.setStroke(StrokeFactory.create("bus").getStroke()); // + fScaleStr).getStroke());
163     buscolor = (Color) v.getAttr("ibuscolor");
164     g2d.setPaint(buscolor);
165     if (inbus != null)
166       g2d.draw(inbus.getPath());
167     if (frombus != null)
168       g2d.draw(frombus.getPath());
169     buscolor = (Color) v.getAttr("obuscolor");
170     g2d.setPaint(buscolor);
171     if (tobus != null)
172       g2d.draw(tobus.getPath());
173     if (outbus != null)
174       g2d.draw(outbus.getPath());
175   }
176 
177   public void render(Graphics2D g2d, IEdge e) {
178     DotRoute route = (DotRoute) e.getAttrCached("pos");
179     if (route == null)
180       return;
181     //
182     Color color = (Color) e.getAttr("color");
183     if (color == null)
184       color = Color.black;
185     g2d.setPaint(color);
186     GraphStroke graphstroke = (GraphStroke) e.getAttrCached("style");
187     g2d.setStroke(graphstroke.getStroke());
188     //g2d.setStroke(StrokeFactory.create("solid" + scaleStr).getStroke());
189     //new BasicStroke(1.0f*sc,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
190     //
191     GeneralPath p = route.getPath();
192     g2d.draw(p);
193     //
194     IArrow arrow;
195     arrow = (IArrow) e.getAttrCached("headarrow");
196     if (arrow != null)
197       arrow.render(g2d, route.getHeadTransform());
198     arrow = (IArrow) e.getAttrCached("tailarrow");
199     if (arrow != null)
200       arrow.render(g2d, route.getTailTransform());
201   }
202 
203   public void render(Graphics2D g2d, IGraph g) {
204     //
205     if (false)
206       msg.println(NAME + "render(Graphics2D,IGraph): " + g.getName());
207     updateShape(g2d, g);
208     //
209     Rectangle2D bounds = (Rectangle2D) g.getAttr("bb");
210     Color bg = (Color) g.getAttr("bgcolor");
211     if (DEBUG)
212       if (bg == null)
213         msg.err(NAME + ".paint(IGraph): bg==null");
214     g2d.setBackground(bg);
215     g2d.clearRect(
216       (int) bounds.getX(),
217       (int) bounds.getY(),
218       (int) bounds.getWidth() + 1,
219       (int) bounds.getHeight() + 1);
220     //
221     g2d.setStroke(new BasicStroke(0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
222     g2d.setPaint(Color.black);
223     g2d.draw(bounds);
224     //
225     Collection c;
226     AffineTransform tx = null;
227     if (fScale != 1.0) {
228       tx = g2d.getTransform();
229       g2d.scale(fScale, fScale);
230     }
231     c = g.allVertices();
232     for (Iterator it = c.iterator(); it.hasNext();) {
233       renderBus(g2d,(IVertex)it.next());
234       //FIXME: For clip checking, draw edge first
235       if (DEBUG) {
236         render(g2d, (IVertex) it.next());
237       }
238     }
239     c=new TreeSet(new DirectedEdgeFactory.EdgeRenderingComparator());
240     c.addAll(g.allEdges());
241     for (Iterator it = c.iterator(); it.hasNext();) {
242       render(g2d, (IEdge) it.next());
243     }
244     if (!DEBUG) {
245       c = g.allVertices();
246       for (Iterator it = c.iterator(); it.hasNext();) {
247         render(g2d, (IVertex) it.next());
248       }
249     }
250     if (tx != null)
251       g2d.setTransform(tx);
252   }
253 
254   ////////////////////////////////////////////////////////////////////////
255 
256   private Font updateFont(IAttrTable table) {
257     String fontspec = table.getAttrString("fontname") + "-";
258     String fontstyle = table.getAttrString("fontstyle");
259     if (fontstyle != null)
260       fontspec += fontstyle;
261     fontspec += "-" + (int) table.getAttrDouble("fontsize");
262     Font font = FontFactory.create(fontspec);
263     table.setAttr("-font", font);
264     return font;
265   }
266 
267   /**
268    *  @param table Attribute table.
269    *  @param attrname Attribute name that defined the stroke (eg. style).
270    *  @param bold True to double outline stroke width.
271    */
272   private IGraphStroke updateStroke(IAttrTable table, String attrname, boolean bold) {
273     IGraphStroke stroke = (IGraphStroke) table.getAttr("-" + attrname);
274     if (stroke == null) {
275       if (bold) { // || fScale!=1.0) {
276         String strokename = table.getAttrAsString(attrname);
277         double w=(bold? 3.0: 1.0); // /fScale;
278         int index = strokename.indexOf(',');
279         if (index >= 0) {
280           String wstr=strokename.substring(index+1);
281           strokename=strokename.substring(0,index);
282           w*=msg.parseFloat(wstr,1.0f);
283         }
284         strokename += sprint.f(",%.2f").a(w).end();
285         stroke = StrokeFactory.create(strokename);
286       } else {
287         stroke=StrokeFactory.create(table.getAttrString(attrname));
288       }
289       table.setAttr("-"+attrname,stroke);
290     }
291     return stroke;
292   }
293 
294   private Rectangle2D updateLabelBounds(Graphics2D g2d, IEdge e) {
295     String label = e.getAttrString("label");
296     if (label == null)
297       return null;
298     Font font = updateFont(e);
299     FontMetrics fm = g2d.getFontMetrics(font);
300     Rectangle2D bounds = fm.getStringBounds(label, g2d);
301     e.setAttr("-bounds", bounds);
302     if (DEBUG)
303       msg.println(
304         NAME + ".updateLabelBounds(IEdge): bounds=" + bounds.toString());
305     return bounds;
306   }
307 
308   ////////////////////////////////////////////////////////////////////////
309 
310 }