View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
5    */
6   package net.kwfgrid.gwui.graphview;
7   
8   import de.fzi.wim.guibase.graphview.graph.Node;
9   import de.fzi.wim.guibase.graphview.view.JGraphPane;
10  import de.fzi.wim.guibase.graphview.view.Manipulator;
11  import de.fzi.wim.guibase.graphview.view.NodePainter;
12  import net.kwfgrid.gworkflowdl.structure.Place;
13  import net.kwfgrid.gworkflowdl.structure.Token;
14  import net.kwfgrid.gwui.ZoomGroup;
15  import org.glassbox.Theme;
16  import org.glassbox.graphview.*;
17  import org.glassbox.gui.Group;
18  import org.glassbox.gui.Member;
19  import org.jdom.Element;
20  
21  import java.awt.*;
22  
23  /***
24   * The painter for <code>PlaceNodes</code>.<br>
25   * This painter has the following properties which can be configured via the application's theme:
26   * <pre><ul>
27   * <li>kwfgrid.PlaceNodePainter.default.stroke</li>
28   * <li>kwfgrid.PlaceNodePainter.default.color</li>
29   * <li>kwfgrid.PlaceNodePainter.default.paint</li>
30   * <li>kwfgrid.PlaceNodePainter.default.size</li>
31   * <li>kwfgrid.PlaceNodePainter.default.token.paint</li>
32   * <li>kwfgrid.PlaceNodePainter.button.insets</li>
33   * </ul></pre>
34   */
35  public class PlaceNodePainter extends TextNodePainter2 implements Member {
36  
37      private static final String[] EMPTY_TEXT = new String[0];
38  
39      public static final String IDENTIFIER = "kwfgrid.PlaceNodePainter";
40  
41      protected static final String SIZE_KEY = "kwfgrid.PlaceNodePainter.size";
42      protected static final String FONT_KEY = "kwfgrid.PlaceNodePainter.font";
43      protected static final String INSETS_KEY = "kwfgrid.PlaceNodePainter.insets";
44      protected static final String BORDER_STROKE_KEY = "kwfgrid.PlaceNodePainter.border.stroke";
45      protected static final String BORDER_ARC_SIZE_KEY = "kwfgrid.PlaceNodePainter.border.arc.size";
46      protected static final String BUTTON_INSETS_KEY = "kwfgrid.PlaceNodePainter.button.insets";
47  
48      protected static final String BORDER_COLOR_KEY = "kwfgrid.PlaceNodePainter.default.border.color";
49      protected static final String BACKGROUND_COLOR_KEY = "kwfgrid.PlaceNodePainter.default.background.color";
50      protected static final String TOKEN_PAINT_KEY = "kwfgrid.PlaceNodePainter.default.token.paint";
51      protected static final String FAULTTOKEN_PAINT_KEY = "kwfgrid.PlaceNodePainter.default.faulttoken.paint";
52      protected static final String TEXT_COLOR_KEY = "kwfgrid.PlaceNodePainter.default.text.color";
53  
54      protected static final String LABEL_FONT_KEY = "kwfgrid.PlaceNodePainter.label.font";
55      protected static final Font LABEL_FONT = Theme.getFont(LABEL_FONT_KEY);
56      protected static final String LABEL_COLOR_KEY = "kwfgrid.PlaceNodePainter.label.color";
57      protected static final Color LABEL_COLOR = Theme.getColor(LABEL_COLOR_KEY);
58  
59  
60      protected static final String DEAD_BORDER_COLOR_KEY = "kwfgrid.PlaceNodePainter.dead.border.color";
61      protected static final String DEAD_BACKGROUND_COLOR_KEY = "kwfgrid.PlaceNodePainter.dead.border.color";
62      protected static final String DEAD_TOKEN_PAINT_KEY = "kwfgrid.PlaceNodePainter.dead.token.paint";
63      protected static final String DEAD_TEXT_COLOR_KEY = "kwfgrid.PlaceNodePainter.dead.text.color";
64  
65      protected static final Dimension SIZE = Theme.getSize(SIZE_KEY);
66      protected static final Font FONT = Theme.getFont(FONT_KEY);
67      protected static final FontMetrics FONT_METRICS = Toolkit.getDefaultToolkit().getFontMetrics(FONT);
68      protected static final Insets INSETS = Theme.getInsets(INSETS_KEY);
69      protected static final Stroke BORDER_STROKE = Theme.getStroke(BORDER_STROKE_KEY);
70      protected static final Dimension BORDER_ARC_SIZE = Theme.getSize(BORDER_ARC_SIZE_KEY);
71      protected static final Insets BUTTON_INSETS = Theme.getInsets(BUTTON_INSETS_KEY);
72  
73      protected static final Paint TOKEN_PAINT = Theme.getPaint(TOKEN_PAINT_KEY);
74      protected static final Paint FAULTTOKEN_PAINT = Theme.getPaint(FAULTTOKEN_PAINT_KEY);
75  
76      protected static final Color TEXT_COLOR = Theme.getColor(TEXT_COLOR_KEY);
77      protected static final Color BORDER_COLOR = Theme.getColor(BORDER_COLOR_KEY);
78      protected static final Color BACKGROUND_COLOR = Theme.getColor(BACKGROUND_COLOR_KEY);
79  
80      protected static final Paint DEAD_TOKEN_PAINT = Theme.getPaint(DEAD_TOKEN_PAINT_KEY);
81      protected static final Color DEAD_TEXT_COLOR = Theme.getColor(DEAD_TEXT_COLOR_KEY);
82      protected static final Color DEAD_BORDER_COLOR = Theme.getColor(DEAD_BORDER_COLOR_KEY);
83      protected static final Color DEAD_BACKGROUND_COLOR = Theme.getColor(DEAD_BACKGROUND_COLOR_KEY);
84  
85      /***
86         Inner class for painting the Token.
87       */
88      protected static class TokenPainter implements ZoomableNodePainter {
89          private int _w, _h;
90          private boolean _paintlabels;
91          private Rectangle _bounds;
92          private Color _textcolor;
93          private Paint _paint;
94  
95          protected TokenPainter(Paint paint, Color textcolor) {
96              _paint = paint;
97              _textcolor = textcolor;
98              _bounds = new Rectangle();
99              setZoomFactor(1d);
100         }
101 
102         public void setZoomFactor(double zf) {
103             _w = (int) ((double) (SIZE.width - INSETS.left - INSETS.right) * zf);
104             _h = (int) ((double) (SIZE.height - INSETS.top - INSETS.bottom) * zf);
105             _paintlabels = zf > 0.5d;
106         }
107 
108         public void paintNode(JGraphPane gpane, Graphics2D g, Node node) {
109             PlaceNode pn = (PlaceNode) node;
110             Place p = pn.getPlace();
111             int tokn = p.getTokenNumber();
112             getNodeScreenBounds(gpane, node, _bounds);
113 
114             if (tokn > 0) {
115                 g.setPaint(_paint);
116                 g.fillArc(_bounds.x,
117                         _bounds.y,
118                         _bounds.width - 1,
119                         _bounds.height - 1,
120                         0,
121                         360);
122 
123                 if (tokn > 1 && _paintlabels) {
124                     g.setColor(_textcolor);
125                     g.setFont(FONT);
126                     String s = "" + tokn;
127                     int w = FONT_METRICS.stringWidth(s);
128                     int h = FONT_METRICS.getHeight();
129                     g.drawString(s, _bounds.x + (_bounds.width - w) / 2, _bounds.y + (_bounds.height - h) / 2 + h - 2);
130                 }
131             }
132         }
133 
134         public boolean isInNode(JGraphPane gpane, Node node, Point point) {
135             getNodeScreenBounds(gpane, node, _bounds);
136             return _bounds.contains(point);
137         }
138 
139         public void getNodeScreenBounds(JGraphPane gpane, Node node, Rectangle bounds) {
140             Point p = gpane.getScreenPointForNode(node);
141             bounds.setBounds(p.x - _w / 2,
142                     p.y - _h / 2,
143                     _w,
144                     _h);
145         }
146 
147         public String getToolTipText(JGraphPane gpane, Node node, Point point) {
148             return null;
149         }
150     }
151 
152     /***
153        Inner class for painting the Place (without probably attached icons).
154      */
155     protected static class PlacePainter implements ZoomableNodePainter {
156         /***
157          * Default Painter.
158          */
159         protected NodeBorder DEFAULT = new NodeBorder(new TokenPainter(TOKEN_PAINT, TEXT_COLOR),
160                 INSETS,
161                 BORDER_COLOR,
162                 BACKGROUND_COLOR,
163                 BORDER_STROKE,
164                 BORDER_ARC_SIZE);
165 
166         /***
167          * Painter for dead places.
168          */
169         protected NodeBorder DEAD = new NodeBorder(new TokenPainter(DEAD_TOKEN_PAINT, DEAD_TEXT_COLOR),
170                 INSETS,
171                 DEAD_BORDER_COLOR,
172                 DEAD_BACKGROUND_COLOR,
173                 BORDER_STROKE,
174                 BORDER_ARC_SIZE);
175 
176         /***
177          * Painter for SOAP Faults.
178          */
179         protected NodeBorder FAULT = new NodeBorder(
180                 new TokenPainter(FAULTTOKEN_PAINT, TEXT_COLOR),
181                 INSETS,
182                 BORDER_COLOR,
183                 BACKGROUND_COLOR,
184                 BORDER_STROKE,
185                 BORDER_ARC_SIZE);
186 
187         protected NodePainter getState(PlaceNode node) {
188             if (!node.isQuasiLive()) {
189                 return DEAD;
190             } else if (node.hasFault()) {
191                 return FAULT;
192             } else {
193                 return DEFAULT;
194             }
195         }
196 
197         public void setZoomFactor(double zf) {
198             DEFAULT.setZoomFactor(zf);
199             DEAD.setZoomFactor(zf);
200             FAULT.setZoomFactor(zf);
201         }
202 
203         public void paintNode(JGraphPane pane, Graphics2D g, Node node) {
204             Stroke oldstroke = g.getStroke();
205             Color oldcolor = g.getColor();
206             PlaceNode pn = (PlaceNode) node;
207             getState(pn).paintNode(pane, g, pn);
208             g.setStroke(oldstroke);
209             g.setColor(oldcolor);
210         }
211 
212         public boolean isInNode(JGraphPane gpane, Node node, Point point) {
213             PlaceNode pn = (PlaceNode) node;
214             NodePainter state = getState(pn);
215             return state.isInNode(gpane, node, point);
216         }
217 
218         public void getNodeScreenBounds(JGraphPane gpane, Node node, Rectangle bounds) {
219             PlaceNode pn = (PlaceNode) node;
220             NodePainter state = getState(pn);
221             state.getNodeScreenBounds(gpane, node, bounds);
222         }
223 
224         public String getToolTipText(JGraphPane view, Node n, Point point) {
225             PlaceNode node = (PlaceNode) n;
226             StringBuffer t = new StringBuffer();
227             t.append("<html>");
228             String tokentype = node.getPlace().getTokenType();
229             if (tokentype != null && tokentype.length() > 0)
230                 t.append(tokentype).append(" Place<br>");
231             t.append("ID: <b>").append(node.getPlace().getID()).append("</b>");
232             int tnum = node.getPlace().getTokenNumber();
233             if (tnum > 0)
234                 t.append("<br>").append(tnum).append(" Token").append((tnum != 1 ? "s" : ""));
235             t.append("</html>");
236             return t.toString();
237         }
238     }
239 
240     private ZoomGroup _group;
241     private boolean _paintlabels;
242 
243     public PlaceNodePainter() {
244         super(new NodeButtonSet(IDENTIFIER,
245                 new PlacePainter(),
246                 BUTTON_INSETS,
247                 NodeIconSet.HORIZONTAL,
248                 NodeIconSet.RIGHT | NodeIconSet.OUTSIDE,
249                 NodeIconSet.CENTER | NodeIconSet.INSIDE,
250                 Cursor.getPredefinedCursor(Cursor.HAND_CURSOR),
251                 PlaceNode.class),
252             LABEL_FONT,
253             LABEL_COLOR,
254             TextNodePainter2.BOTTOM,
255             2);
256 
257         _group = null;
258         updateNodeSize();
259     }
260     
261     ///
262     /// Public API
263     /// ....................................................................................................
264 
265     public Manipulator getGraphManipulator() {
266         return (Manipulator) getDelegate();
267     }
268 
269     /***
270        Add a button or icon
271      */
272     public void addButton(NodeIconSet.Icon icon) {
273 	    NodePainter np = getDelegate();
274         if (np instanceof NodeButtonSet) {
275             ((NodeButtonSet)np).addButton(icon);
276         }
277     }
278 
279     ///
280     /// Private API
281     /// ....................................................................................................
282 
283     private void updateNodeSize() {
284         double zf = 1d;
285         if (_group != null) {
286             zf = ((Double) _group.getProperty(ZoomGroup.ZOOM_FACTOR_KEY)).doubleValue();
287         }
288         setZoomFactor(zf);
289         _paintlabels = zf > 0.4d;
290     }
291 
292     ///
293     /// Implementation of TextNodePainter
294     /// ....................................................................................................
295 
296     protected String[] getText(Node node) {
297 	PlaceNode pnode = (PlaceNode)node;
298     return _paintlabels?pnode.getText():EMPTY_TEXT;
299     }
300 
301     ///
302     /// Implementation of Member
303     /// ....................................................................................................
304 
305     public Group getGroup() {
306         return _group;
307     }
308 
309     public String getIdentifier() {
310         return IDENTIFIER;
311     }
312 
313     public void groupPropertyChanged(String name, Object oldvalue, Object newvalue) {
314         if (ZoomGroup.ZOOM_FACTOR_KEY.equals(name)) {
315             updateNodeSize();
316         }
317     }
318 
319     public void setGroup(Group group) throws IllegalArgumentException {
320         if (!(group == null || group instanceof ZoomGroup))
321             throw new IllegalArgumentException("PlaceNodePainter must be member of a ZoomGroup.");
322 
323         _group = (ZoomGroup) group;
324 
325         updateNodeSize();
326     }
327 }