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.Operation;
13  import net.kwfgrid.gworkflowdl.structure.Transition;
14  import net.kwfgrid.gwui.ZoomGroup;
15  import net.kwfgrid.gwui.workflow.XMLUtilities;
16  import org.apache.log4j.Logger;
17  import org.glassbox.Theme;
18  import org.glassbox.graphview.*;
19  import org.glassbox.gui.Group;
20  import org.glassbox.gui.Member;
21  
22  import javax.swing.*;
23  import java.awt.*;
24  import java.net.URL;
25  import java.util.HashMap;
26  
27  /***
28   * The painter for <code>TransitionNodes</code>.<br>
29   * This painter has the following properties which can be configured via the application's theme:
30   * <ul>
31   * <li>kwfgrid.TransitionNodePainter.default.font</li>
32   * <li>kwfgrid.TransitionNodePainter.bold.font</li>
33   * <li>kwfgrid.TransitionNodePainter.text.color</li>
34   * <li>kwfgrid.TransitionNodePainter.size</li>
35   * <li>kwfgrid.TransitionNodePainter.border.stroke</li>
36   * <li>kwfgrid.TransitionNodePainter.black.border.color</li>
37   * <li>kwfgrid.TransitionNodePainter.black.paint</li>
38   * <li>kwfgrid.TransitionNodePainter.blue.border.color</li>
39   * <li>kwfgrid.TransitionNodePainter.blue.paint</li>
40   * <li>kwfgrid.TransitionNodePainter.red.border.color</li>
41   * <li>kwfgrid.TransitionNodePainter.red.paint</li>
42   * <li>kwfgrid.TransitionNodePainter.yellow.border.color</li>
43   * <li>kwfgrid.TransitionNodePainter.yellow.paint</li>
44   * <li>kwfgrid.TransitionNodePainter.green.border.color</li>
45   * <li>kwfgrid.TransitionNodePainter.green.paint</li>
46   * <li>kwfgrid.STATUS.initiated.color</li>
47   * <li>kwfgrid.STATUS.running.color</li>
48   * <li>kwfgrid.STATUS.suspended.color</li>
49   * <li>kwfgrid.STATUS.terminated.color</li>
50   * <li>kwfgrid.STATUS.completed.color</li>
51   * <li>kwfgrid.STATUS.active.color</li>
52   * </ul>
53   */
54  public class TransitionNodePainter2 extends TextNodePainter2 implements Member {
55      public static final String IDENTIFIER = "kwfgrid.TransitionNodePainter2";
56  
57      private static final Logger logger = Logger.getLogger(TransitionNodePainter2.class);
58  
59      private static final String[] EMPTY_TEXT = new String[0];
60  
61      protected static final Insets INSETS = new Insets(0, 0, 0, 0);
62      protected static final String IMAGE_SIZE_KEY = "kwfgrid.TransitionNodePainter.image.size";
63      protected static final Dimension IMAGE_SIZE = Theme.getSize(IMAGE_SIZE_KEY);
64      protected static final String IMAGE_INSETS_KEY = "kwfgrid.TransitionNodePainter.image.insets";
65      protected static final Insets IMAGE_INSETS = Theme.getInsets(IMAGE_INSETS_KEY);
66      protected static final String DEFAULT_FONT_KEY = "kwfgrid.TransitionNodePainter.default.font";
67      protected static final Font DEFAULT_FONT = Theme.getFont(DEFAULT_FONT_KEY);
68      protected static final String BOLD_FONT_KEY = "kwfgrid.TransitionNodePainter.bold.font";
69      protected static final Font BOLD_FONT = Theme.getFont(BOLD_FONT_KEY);
70      protected static final String BORDER_STROKE_KEY = "kwfgrid.TransitionNodePainter.border.stroke";
71      protected static final Stroke BORDER_STROKE = Theme.getStroke(BORDER_STROKE_KEY);
72      protected static final String SIZE_KEY = "kwfgrid.TransitionNodePainter.size";
73      protected static final Dimension SIZE = Theme.getSize(SIZE_KEY);
74      protected static final String TEXT_COLOR_KEY = "kwfgrid.TransitionNodePainter.text.color";
75      protected static final Color TEXT_COLOR = Theme.getColor(TEXT_COLOR_KEY);
76      protected static final String BUTTON_INSETS_KEY = "kwfgrid.TransitionNodePainter.button.insets";
77      protected static final Insets BUTTON_INSETS = Theme.getInsets(BUTTON_INSETS_KEY);
78  
79      protected static final String DEAD_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.dead.border.color";
80      protected static final String DEAD_PAINT_KEY = "kwfgrid.TransitionNodePainter.dead.paint";
81      protected static final Color DEAD_BORDER_COLOR = Theme.getColor(DEAD_BORDER_COLOR_KEY);
82      protected static final Paint DEAD_PAINT = Theme.getPaint(DEAD_PAINT_KEY);
83  
84      protected static final String BLACK_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.black.border.color";
85      protected static final String BLACK_PAINT_KEY = "kwfgrid.TransitionNodePainter.black.paint";
86      protected static final Color BLACK_BORDER_COLOR = Theme.getColor(BLACK_BORDER_COLOR_KEY);
87      protected static final Paint BLACK_PAINT = Theme.getPaint(BLACK_PAINT_KEY);
88  
89      protected static final String RED_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.red.border.color";
90      protected static final String RED_PAINT_KEY = "kwfgrid.TransitionNodePainter.red.paint";
91      protected static final Color RED_BORDER_COLOR = Theme.getColor(RED_BORDER_COLOR_KEY);
92      protected static final Paint RED_PAINT = Theme.getPaint(RED_PAINT_KEY);
93  
94      protected static final String YELLOW_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.yellow.border.color";
95      protected static final String YELLOW_PAINT_KEY = "kwfgrid.TransitionNodePainter.yellow.paint";
96      protected static final Color YELLOW_BORDER_COLOR = Theme.getColor(YELLOW_BORDER_COLOR_KEY);
97      protected static final Paint YELLOW_PAINT = Theme.getPaint(YELLOW_PAINT_KEY);
98  
99      protected static final String GREEN_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.green.border.color";
100     protected static final String GREEN_PAINT_KEY = "kwfgrid.TransitionNodePainter.green.paint";
101     protected static final Color GREEN_BORDER_COLOR = Theme.getColor(GREEN_BORDER_COLOR_KEY);
102     protected static final Paint GREEN_PAINT = Theme.getPaint(GREEN_PAINT_KEY);
103 
104     protected static final String BLUE_BORDER_COLOR_KEY = "kwfgrid.TransitionNodePainter.blue.border.color";
105     protected static final String BLUE_PAINT_KEY = "kwfgrid.TransitionNodePainter.blue.paint";
106     protected static final Color BLUE_BORDER_COLOR = Theme.getColor(BLUE_BORDER_COLOR_KEY);
107     protected static final Paint BLUE_PAINT = Theme.getPaint(BLUE_PAINT_KEY);
108 
109     private static Color[] BACKGROUND_COLOR = new Color[]{Theme.getColor("kwfgrid.STATUS.undefined.color"),
110             Theme.getColor("kwfgrid.STATUS.initiated.color"),
111             Theme.getColor("kwfgrid.STATUS.running.color"),
112             Theme.getColor("kwfgrid.STATUS.suspended.color"),
113             Theme.getColor("kwfgrid.STATUS.active.color"),
114             Theme.getColor("kwfgrid.STATUS.terminated.color"),
115             Theme.getColor("kwfgrid.STATUS.completed.color")};
116 
117     private static String[] STATUS = new String[]{XMLUtilities.WORKFLOW_STATUS_UNDEFINED,
118             XMLUtilities.WORKFLOW_STATUS_INITIATED,
119             XMLUtilities.WORKFLOW_STATUS_RUNNING,
120             XMLUtilities.WORKFLOW_STATUS_SUSPENDED,
121             XMLUtilities.WORKFLOW_STATUS_ACTIVE,
122             XMLUtilities.WORKFLOW_STATUS_TERMINATED,
123             XMLUtilities.WORKFLOW_STATUS_COMPLETED};
124 
125 
126     /***
127      * Painter for the icons of the nodes.
128      * Uses transition's property <code>icon.url</code> to find the images.
129      */
130     protected static class TransitionImageNodePainter extends AbstractImageNodePainter {
131         private HashMap _images;
132 
133         public TransitionImageNodePainter(Dimension imagesize, Insets border, double zoomthreshold) {
134             super(imagesize, border, zoomthreshold);
135 
136             _images = new HashMap();
137         }
138 
139         protected ImageIcon getImageForNode(Node node) {
140             ImageIcon image = null;
141 
142             TransitionNode tn = (TransitionNode) node;
143             Transition t = tn.getTransition();
144 
145             String imageurl = t.getProperties().get("icon.url");
146 
147             if (imageurl == null || "".equals(imageurl.trim())) return null;
148 
149             image = (ImageIcon) _images.get(imageurl);
150 
151             try {
152                 if (image == null) {
153                     image = new ImageIcon(new URL(imageurl));
154                     _images.put(imageurl, image);
155                 }
156             } catch (Exception x) {
157                 logger.warn("Could not load image for transition.", x);
158             }
159 
160             return image;
161         }
162     }
163 
164     /***
165      * Painter for inner part of the nodes.
166      */
167     protected static class TransitionPainter implements ZoomableNodePainter {
168         protected ZoomableNodePainter PN = new NullNodePainter(SIZE);
169         protected ZoomableNodePainter PI = new TransitionImageNodePainter(IMAGE_SIZE, IMAGE_INSETS, 0.0d);
170 
171         protected NodeBorder DEAD = new NodeBorder(PN,
172                 INSETS,
173                 DEAD_BORDER_COLOR,
174                 DEAD_PAINT,
175                 BORDER_STROKE,
176                 new Dimension(0, 0));
177         /***
178          * Painter for abstraction level BLACK.
179          */
180         protected NodeBorder BLACK = new NodeBorder(PI,
181                 INSETS,
182                 BLACK_BORDER_COLOR,
183                 BLACK_PAINT,
184                 BORDER_STROKE,
185                 new Dimension(0, 0));
186 
187         /***
188          * Painter for abstraction level RED.
189          */
190         protected NodeBorder RED = new NodeBorder(PI,
191                 INSETS,
192                 RED_BORDER_COLOR,
193                 RED_PAINT,
194                 BORDER_STROKE,
195                 new Dimension(0, 0));
196 
197         /***
198          * Painter for abstraction level YELLOW.
199          */
200         protected NodeBorder YELLOW = new NodeBorder(PI,
201                 INSETS,
202                 YELLOW_BORDER_COLOR,
203                 YELLOW_PAINT,
204                 BORDER_STROKE,
205                 new Dimension(0, 0));
206 
207         /***
208          * Painter for abstraction level BLUE.
209          */
210         protected NodeBorder BLUE = new NodeBorder(PI,
211                 INSETS,
212                 BLUE_BORDER_COLOR,
213                 BLUE_PAINT,
214                 BORDER_STROKE,
215                 new Dimension(0, 0));
216 
217         /***
218          * Painter for abstraction level GREEN.
219          */
220         protected NodeBorder GREEN = new NodeBorder(PI,
221                 INSETS,
222                 GREEN_BORDER_COLOR,
223                 GREEN_PAINT,
224                 BORDER_STROKE,
225                 new Dimension(0, 0));
226 
227         public void setZoomFactor(double zf) {
228             PN.setZoomFactor(zf);
229             PI.setZoomFactor(zf);
230         }
231 
232         public void paintNode(JGraphPane gpane, Graphics2D g, Node node) {
233             Stroke oldstroke = g.getStroke();
234             Color oldcolor = g.getColor();
235             TransitionNode tn = (TransitionNode) node;
236             NodePainter state = getState(tn);
237             state.paintNode(gpane, g, node);
238             g.setStroke(oldstroke);
239             g.setColor(oldcolor);
240         }
241 
242         public boolean isInNode(JGraphPane gpane, Node node, Point point) {
243             TransitionNode tn = (TransitionNode) node;
244             NodePainter state = getState(tn);
245             return state.isInNode(gpane, node, point);
246         }
247 
248         public void getNodeScreenBounds(JGraphPane gpane, Node node, Rectangle bounds) {
249             TransitionNode tn = (TransitionNode) node;
250             NodePainter state = getState(tn);
251             state.getNodeScreenBounds(gpane, node, bounds);
252         }
253 
254         public String getToolTipText(JGraphPane gpane, Node node, Point point) {
255             TransitionNode tnode = (TransitionNode) node;
256             StringBuffer t = new StringBuffer();
257             String level = XMLUtilities.getAbstractionLevelDescription(tnode.getTransition());
258             t.append("<html>").append(level).append("<br>ID: <b>").append(tnode.getTransition().getID()).append("</b>");
259             String description = (String) tnode.getTransition().getDescription();
260             if (description != null && description.length() > 0) {
261                 t.append("<br><i>").append(description).append("</i>");
262             }
263             String lastResource = tnode.getTransition().getProperties().get("last.resource.name");
264             if (lastResource != null && lastResource.length() >0)
265                 t.append("<br><br>last used resource: <b>").append(lastResource).append("</b>");
266             t.append(tnode.getOperationToolTipText());
267             t.append("</html>");
268             return t.toString();
269         }
270 
271         protected NodePainter getState(TransitionNode node) {
272             if (!node.isQuasiLive()) {
273                 return DEAD;
274             }
275 
276             int level = node.getTransition().getAbstractionLevel();
277             NodeBorder painter = null;
278 
279             if (Operation.RED == level) {
280                 painter = RED;
281             } else if (Operation.BLUE == level) {
282                 painter = BLUE;
283             } else if (Operation.GREEN == level) {
284                 painter = GREEN;
285             } else if (Operation.YELLOW == level) {
286                 painter = YELLOW;
287             } else {
288                 painter = BLACK;
289             }
290 
291             String status = node.getTransition().getProperties().get(XMLUtilities.STATUS);
292             painter.setPaint(BACKGROUND_COLOR[0]);
293 
294             if (status != null) {
295                 for (int i = 0; i < STATUS.length; i++) {
296                     if (STATUS[i].equalsIgnoreCase(status)) {
297                         painter.setPaint(BACKGROUND_COLOR[i]);
298                         break;
299                     }
300                 }
301             }
302 
303             return painter;
304         }
305     }
306 
307     private ZoomGroup _group;
308     private boolean _paintlabels;
309 
310     public TransitionNodePainter2() {
311         super(new NodeButtonSet("kwfgrid.TransitionNodeButtons",
312                 new TransitionPainter(),
313                 BUTTON_INSETS,
314                 NodeIconSet.HORIZONTAL,
315                 NodeIconSet.RIGHT | NodeIconSet.OUTSIDE,
316                 NodeIconSet.TOP | NodeIconSet.INSIDE,
317                 Cursor.getPredefinedCursor(Cursor.HAND_CURSOR),
318                 TransitionNode.class),
319                 DEFAULT_FONT,
320                 TEXT_COLOR,
321                 TextNodePainter2.BOTTOM,
322                 2);
323 
324         _group = null;
325         updateNodeSize();
326         logger.debug("TransitionNodePainter2 instantiated.");
327     }
328 
329     ///
330     /// Private API
331     /// ....................................................................................................
332 
333     private void updateNodeSize() {
334         double zf = 1d;
335         if (_group != null) {
336             zf = ((Double) _group.getProperty(ZoomGroup.ZOOM_FACTOR_KEY)).doubleValue();
337         }
338         //((TransitionPainter)((NodeButtonSet)getDelegate()).getDelegate()).setZoomFactor(zf);
339         setZoomFactor(zf);
340         _paintlabels = zf > 0.4d;
341     }
342 
343     ///
344     /// Implementation of TextNodePainter
345     /// ....................................................................................................
346 
347     protected String[] getText(Node node) {
348         TransitionNode tnode = (TransitionNode) node;
349         return _paintlabels ? tnode.getText() : EMPTY_TEXT;
350     }
351 
352     ///
353     /// Implementation of Member
354     /// ....................................................................................................
355 
356     public Group getGroup() {
357         return _group;
358     }
359 
360     public String getIdentifier() {
361         return IDENTIFIER;
362     }
363 
364     public void groupPropertyChanged(String name, Object oldvalue, Object newvalue) {
365         if (ZoomGroup.ZOOM_FACTOR_KEY.equals(name)) {
366             updateNodeSize();
367         }
368     }
369 
370     public void setGroup(Group group) throws IllegalArgumentException {
371         if (!(group == null || group instanceof ZoomGroup))
372             throw new IllegalArgumentException("TransitionNodePainter2 must be member of a ZoomGroup.");
373 
374         _group = (ZoomGroup) group;
375 
376         updateNodeSize();
377     }
378 
379     ///
380     /// Public API
381     /// ....................................................................................................
382 
383     public Manipulator getGraphManipulator() {
384         return (Manipulator) getDelegate();
385     }
386 
387     public void addButton(NodeIconSet.Icon icon) {
388         ((NodeButtonSet) getDelegate()).addButton(icon);
389     }
390 }