1
2
3
4
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
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
339 setZoomFactor(zf);
340 _paintlabels = zf > 0.4d;
341 }
342
343
344
345
346
347 protected String[] getText(Node node) {
348 TransitionNode tnode = (TransitionNode) node;
349 return _paintlabels ? tnode.getText() : EMPTY_TEXT;
350 }
351
352
353
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
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 }