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

Quick Search    Search Deep

Source code: com/port80/graph/dot/impl/RouteFactory.java


1   //
2   // Copyright(c) 2002, Chris Leung
3   //
4   
5   package com.port80.graph.dot.impl;
6   
7   import java.awt.geom.GeneralPath;
8   import java.awt.geom.PathIterator;
9   
10  import com.port80.util.msg;
11  import com.port80.util.sprint;
12  import com.port80.util.attr.IAttrFactory;
13  import com.port80.util.struct.FloatList;
14  
15  /** Route (DotRoute) attribute factory.
16   *
17   */
18  public class RouteFactory implements IAttrFactory {
19  
20      ////////////////////////////////////////////////////////////////////////
21  
22      private static final String NAME = "RouteFactory";
23      private static final boolean DEBUG = false;
24  
25      private static RouteFactory instance = null;
26  
27      ////////////////////////////////////////////////////////////////////////
28  
29      private static boolean isDotMode = false;
30      private static double maxY = 0.0;
31  
32      ////////////////////////////////////////////////////////////////////////
33  
34      public static void dotModeOn(double maxy) {
35          maxY = maxy; isDotMode = true;
36      }
37  
38      public static void dotModeOff() {
39          isDotMode = false;
40      }
41  
42      // Instance fields /////////////////////////////////////////////////////
43      //
44  
45      ////////////////////////////////////////////////////////////////////////
46  
47      /** @return The singleton instance of the factory. */
48      public static RouteFactory getInstance() {
49          if (instance == null) instance = new RouteFactory();
50          return instance;
51      }
52  
53      /** @return An instance of the specified shape. */
54      public static DotRoute create(String stringvalue) {
55          if (instance == null) instance = new RouteFactory();
56          return (DotRoute)instance.createObject(stringvalue);
57      }
58  
59      private RouteFactory() {}
60  
61      // IAttrFactory interface //////////////////////////////////////////////
62      //
63  
64      /** Create an instance of route from the String spec.
65       *
66       *  Current accepted .dot file string format:
67       *
68       *  For beizer curves:
69       *     [x0,y0 (x11,y11 x12,y12 x13,y13)+]
70       *  p0-p1-...
71       *     [e|E,xe,ye x0,y0 (x11,y11 x12,y12 x13,y13)+]
72       *  p0-p1-...->pe
73       *      [s|S,xs,ys [e,xe,ye] x0,y0 (x11,y11 x12,y12 x13,y13)+]
74       *  ps<-p0-p1-...->pe
75       *  For polyline:
76       *      [p x0,y0 x1,y1 ...]
77       *      [p s|S,xs,ys x0,y0 x1,y1 ...]
78       *      [p e|E,xs,ys x0,y0 x1,y1 ...]
79       *
80       *  s=location of tail arrow head from start of spline.
81       *  S=location of head arrow head from start of spline.
82       *  e=location of head arrow head from end of spline.
83       *  E=location of tail arrow head from end of spline.
84       *
85       *  where xs,ys and xe,ye are the arrow end points away from the curve.
86       */
87      public Object createObject(String str) {
88  
89          if (str == null || str.length() == 0 || str.equals("null")) return null;
90          if (DEBUG) msg.println(NAME + ".createObject(): str=" + str);
91  
92          FloatList pts = new FloatList();
93  
94          int end = str.length();
95          int start = skipWhiteSpace(str, 0, end);
96          char type = str.charAt(start);
97          FloatList startpt = null;
98          FloatList endpt = null;
99          boolean iscurve = true;
100         boolean isReversed = false;
101         if (type == 'p') {
102             start += 2;
103             iscurve = false;
104         }
105         if (type == 's' || type == 'S') {
106             if (type == 'S') isReversed = true;
107             startpt = new FloatList();
108             start = parsePoint(str, start + 2, end, startpt);
109             if (start >= 0) type = str.charAt(start);
110         }
111         if (type == 'e' || type == 'E') {
112             if (type == 'E') isReversed = true;
113             endpt = new FloatList();
114             start = parsePoint(str, start + 2, end, endpt);
115         }
116         while (start >= 0 && start < end) start = parsePoint(str, start, end, pts);
117         if (start < 0) {
118             msg.err("RouteFactory.createObject(): invalid input string"
119                     + ": str=" + str
120                    );
121             return null;
122         }
123         if (iscurve) return createBezier(pts, startpt, endpt, isReversed);
124         else return createPolyline(pts, startpt, endpt, isReversed);
125     }
126 
127     public boolean isValid(Object a) {
128       return (a instanceof DotRoute);
129     }
130         
131     /** The String representation of an attribute value. */
132     public String toString(Object attrObject) {
133         DotRoute attr = (DotRoute)attrObject;
134         PathIterator it = attr.getPath().getPathIterator(null);
135         int type;
136         boolean iscurve = false;
137         StringBuffer ret = new StringBuffer();
138         for (float[] pts = new float[6]; !it.isDone(); it.next()) {
139             type = it.currentSegment(pts);
140             if (ret.length() > 0) ret.append(" ");
141             if (type == PathIterator.SEG_CUBICTO) {
142                 iscurve = true;
143                 for (int i = -1; i < 5;) {
144                     //if(i>=0) ret.append(" ");
145                     ret.append(sprint.f(" %.1f,%.1f")
146                                .a(pts[++i])
147                                .a(isDotMode ? (maxY - pts[++i]) : pts[++i])
148                                .end()
149                               );
150                 }
151             } else ret.append(sprint.f("%.1f,%.1f")
152                                   .a(pts[0])
153                                   .a(isDotMode ? (maxY - pts[1]) : pts[1])
154                                   .end()
155                                  );
156         }
157         DotPoint pt = attr.getEndPt();
158         if (pt != null) ret.insert(0, sprint.f((attr.isReversed() ? "E" : "e") + ",%.1f,%.1f ")
159                                        .a(pt.getX())
160                                        .a(isDotMode ? (maxY - pt.getY()) : pt.getY())
161                                        .end()
162                                       );
163         pt = attr.getStartPt();
164         if (pt != null) ret.insert(0, sprint.f((attr.isReversed() ? "S" : "s") + ",%.1f,%.1f ")
165                                        .a(pt.getX())
166                                        .a(isDotMode ? (maxY - pt.getY()) : pt.getY())
167                                        .end()
168                                       );
169         if (!iscurve) ret.insert(0, "p ");
170         //if(iscurve) ret.replace(0,2,"s,");
171         //else ret.replace(0,2,"e,");
172         return ret.toString();
173     }
174 
175     /** The String representation of attribute type itself. */
176     public String toString() {
177         return NAME;
178     }
179     /** Prompt user and present a user interface to obtain an
180      *  attribute value from user. */
181     public Object promptUser(String prompt) {
182         return null;
183     }
184 
185     ////////////////////////////////////////////////////////////////////////
186 
187     /** @return false if parse failed.*/
188     private int parsePoint(String str, int start, int max, FloatList pts) {
189         String xstr, ystr;
190         char c;
191         int end = str.indexOf(',', start);
192         if (end <= 0) return -1;
193         xstr = str.substring(start, end);
194         start = end + 1;
195         while (start < max
196                 && !((c = str.charAt(start)) == ' '
197                      || c == '\t'
198                      || c == '\n'
199                      || c == '\r'
200                      || c == '\f'
201                     )
202               ) ++start;
203         ystr = str.substring(end + 1, start);
204         float x = -1;
205         float y = -1;
206         try {
207             x = Float.parseFloat(xstr);
208             y = Float.parseFloat(ystr);
209             if (isDotMode) y = (float)maxY - y;
210         } catch (Exception e) {
211             msg.err("RouteFactory.createObject(): invalid float numbers"
212                     + ": x=" + xstr + ", y=" + ystr
213                    );
214             return -1;
215         }
216         if (DEBUG) msg.println(NAME + ".parserPoint(): x=" + x + ", y=" + y);
217         pts.add(x);
218         pts.add(y);
219         start = skipWhiteSpace(str, start, max);
220         return start;
221     }
222 
223     private int skipWhiteSpace(String str, int start, int max) {
224         char c;
225         while (start < max &&
226                 ( (c = str.charAt(start)) == ' '
227                   || c == '\t'
228                   || c == '\n'
229                   || c == '\r'
230                   || c == '\f'
231                 )
232               ) ++start;
233         return start;
234     }
235 
236     private DotRoute createPolyline(FloatList pts, FloatList startpt, FloatList endpt, boolean isReversed) {
237         GeneralPath ret = new GeneralPath();
238         int n = -1;
239         int max = pts.size();
240         ret.moveTo(pts.get(++n), pts.get(++n));
241         for (; n < max - 1;) {
242             ret.lineTo(pts.get(++n), pts.get(++n));
243         }
244         DotPoint s0 = new DotPoint(pts.get(0), pts.get(1));
245         DotPoint e0 = new DotPoint(pts.get(max - 2), pts.get(max - 1));
246         DotPoint s = (startpt == null ? null : new DotPoint(startpt.get(0), startpt.get(1)));
247         DotPoint e = (endpt == null) ? null : new DotPoint(endpt.get(0), endpt.get(1));
248         return new DotRoute(ret, s0, s, e0, e, isReversed);
249     }
250 
251     /** The Bezier points from the .dot file looks like a mess.  It
252      *  appears to be arranged like this:
253      *
254      *  'e' x0,y0 (xn3,yn3 xn2,yn2 xn1,yn1) ... (x13,y13 x12,y12 x11,y11) x_ y_
255      *  p_<-p0->p1->...->pn
256      *  's' x_,y_ (xn3,yn3 xn2,yn2 xn1,yn1) ... (x13,y13 x12,y12 x11,y11) x0 y0
257      *  p0->p1->...->pn->p_
258      *  where
259      *     p_ is the arrow head.
260      */
261     private DotRoute createBezier(FloatList pts, FloatList startpt, FloatList endpt, boolean isReversed) {
262         if (DEBUG) msg.println(NAME + ".createBezier()"
263                                    + ": size=" + pts.size()
264                                    + ", start=" + (startpt != null)
265                                    + ", end=" + (endpt != null)
266                                   );
267         int max = pts.size();
268         if (max % 6 != 2) msg.err(NAME + ".createBezier(): expected 3n+1 points: size=" + max);
269         if (DEBUG) {
270             StringBuffer buf = new StringBuffer(NAME + ".createBezier(): route=\n");
271             if (startpt != null) buf.append("start=" + startpt.get(0) + "," + startpt.get(1) + "\n");
272             for (int i = 0; i <= max - 2; i += 2) buf.append("  " + pts.get(i) + "," + pts.get(i + 1));
273             if (endpt != null) buf.append("end=" + endpt.get(0) + "," + endpt.get(1));
274             msg.println(buf.toString());
275         }
276         GeneralPath ret = new GeneralPath();
277         float x0, y0;
278         int n = -1;
279         x0 = pts.get(++n);
280         y0 = pts.get(++n);
281         ret.moveTo(x0, y0);
282         while (n < max - 6) {
283             ret.curveTo(pts.get(++n),
284                         pts.get(++n),
285                         pts.get(++n),
286                         pts.get(++n),
287                         pts.get(++n),
288                         pts.get(++n)
289                        );
290         }
291         // Start,end arrows.
292         //
293         //FIXME:
294         /*
295         if(endpt!=null) ret.lineTo(endpt.get(0),endpt.get(1));
296         if(startpt!=null) {
297             ret.moveTo(x0,y0);
298             ret.lineTo(startpt.get(0),startpt.get(1));
299         }
300         */
301         DotPoint s0 = new DotPoint(pts.get(0), pts.get(1));
302         DotPoint e0 = new DotPoint(pts.get(max - 2), pts.get(max - 1));
303         DotPoint s = (startpt == null ? null : new DotPoint(startpt.get(0), startpt.get(1)));
304         DotPoint e = (endpt == null) ? null : new DotPoint(endpt.get(0), endpt.get(1));
305         return new DotRoute(ret, s0, s, e0, e, isReversed);
306     }
307 
308     ////////////////////////////////////////////////////////////////////////
309 
310 }
311