001: package com.opensymphony.workflow.designer;
002:
003: import java.awt.*;
004: import java.awt.geom.Rectangle2D;
005: import java.awt.datatransfer.DataFlavor;
006: import java.awt.datatransfer.Transferable;
007: import java.awt.dnd.*;
008: import java.util.List;
009: import java.util.Properties;
010: import javax.swing.*;
011:
012: import com.opensymphony.workflow.designer.actions.*;
013: import com.opensymphony.workflow.designer.dnd.DragData;
014: import com.opensymphony.workflow.designer.layout.LayoutAlgorithm;
015: import com.opensymphony.workflow.designer.layout.SugiyamaLayoutAlgorithm;
016: import com.opensymphony.workflow.loader.*;
017: import org.jgraph.JGraph;
018: import org.jgraph.graph.*;
019:
020: public class WorkflowGraph extends JGraph implements DropTargetListener {
021: private Layout layout = new Layout();
022: private Point menuLocation = new Point();
023:
024: private WorkflowDescriptor descriptor;
025: private JPopupMenu genericMenu;
026: private JPopupMenu edgeMenu;
027: private JPopupMenu cellMenu;
028:
029: private UndoManager undoManager = new UndoManager();
030: private static final Color GRID_COLOR = new Color(240, 240, 240);
031:
032: public WorkflowGraph(GraphModel model,
033: WorkflowDescriptor descriptor, Layout layout,
034: boolean doAutoLayout) {
035: super (model);
036: getGraphLayoutCache().setFactory(new WorkflowCellViewFactory());
037: getGraphLayoutCache().setSelectsAllInsertedCells(false);
038: ToolTipManager.sharedInstance().registerComponent(this );
039: this .layout = layout;
040: setDescriptor(descriptor);
041: if (doAutoLayout) {
042: autoLayout();
043: }
044:
045: setGridEnabled(true);
046: setSizeable(true);
047: setGridColor(GRID_COLOR);
048: setGridSize(12);
049: //setTolerance(2);
050: setGridVisible(true);
051: setGridMode(JGraph.LINE_GRID_MODE);
052:
053: setBendable(true);
054: setMarqueeHandler(new WorkflowMarqueeHandler(this ));
055: setCloneable(false);
056: setPortsVisible(true);
057:
058: // one set of menu <==> one graph <==> one workflow descriptor
059: genericMenu = new JPopupMenu();
060: JMenu n = new JMenu(ResourceManager.getString("create.new"));
061: genericMenu.add(n);
062: n.add(new CreateStep(descriptor, getWorkflowGraphModel(),
063: menuLocation));
064: // n.add(new CreateInitialAction(descriptor, getWorkflowGraphModel(), menuLocation));
065: n.add(new CreateJoin(descriptor, getWorkflowGraphModel(),
066: menuLocation));
067: n.add(new CreateSplit(descriptor, getWorkflowGraphModel(),
068: menuLocation));
069: JMenu g = new JMenu(ResourceManager.getString("grid.size"));
070: genericMenu.add(g);
071: g.add(new SetGridSize(this , menuLocation, 1));
072: g.add(new SetGridSize(this , menuLocation, 2));
073: g.add(new SetGridSize(this , menuLocation, 4));
074: g.add(new SetGridSize(this , menuLocation, 8));
075: g.add(new SetGridSize(this , menuLocation, 12));
076: g.add(new SetGridSize(this , menuLocation, 16));
077:
078: cellMenu = new JPopupMenu();
079: cellMenu.add(new Delete(descriptor, this , menuLocation));
080:
081: edgeMenu = new JPopupMenu();
082: n = new JMenu(ResourceManager.getString("edge.color"));
083: edgeMenu.add(n);
084: n.add(new ResultEdgeColor(this , menuLocation, Color.black,
085: ResourceManager.getString("edge.color.black")));
086: n.add(new ResultEdgeColor(this , menuLocation, Color.LIGHT_GRAY,
087: ResourceManager.getString("edge.color.gray")));
088: n.add(new ResultEdgeColor(this , menuLocation, Color.red,
089: ResourceManager.getString("edge.color.red")));
090: n.add(new ResultEdgeColor(this , menuLocation, Color.ORANGE,
091: ResourceManager.getString("edge.color.orange")));
092: n.add(new ResultEdgeColor(this , menuLocation, new Color(0, 200,
093: 0), ResourceManager.getString("edge.color.green")));
094: n.add(new ResultEdgeColor(this , menuLocation, Color.MAGENTA,
095: ResourceManager.getString("edge.color.magenta")));
096: n.add(new ResultEdgeColor(this , menuLocation, Color.blue,
097: ResourceManager.getString("edge.color.blue")));
098: n = new JMenu(ResourceManager.getString("edge.width"));
099: edgeMenu.add(n);
100: for (int i = 1; i <= 5; i++) {
101: n.add(new ResultEdgeLineWidth(this , menuLocation, i));
102: }
103: edgeMenu.add(new Delete(descriptor, this , menuLocation));
104: model.addUndoableEditListener(undoManager);
105: new DropTarget(this , this );
106: }
107:
108: public String convertValueToString(Object value) {
109: if (value == null)
110: return null;
111: if (value instanceof EdgeView) {
112: return ((EdgeView) value).getCell().toString();
113: } else {
114: return value.toString();
115: }
116: }
117:
118: public WorkflowDescriptor getDescriptor() {
119: return descriptor;
120: }
121:
122: public void setDescriptor(WorkflowDescriptor descriptor) {
123: if (descriptor != null) {
124: this .descriptor = descriptor;
125: List initialActionList = descriptor.getInitialActions();
126: addInitialActions(initialActionList);
127: List stepsList = descriptor.getSteps();
128: for (int i = 0; i < stepsList.size(); i++) {
129: StepDescriptor step = (StepDescriptor) stepsList.get(i);
130: addStepDescriptor(step);
131: }
132: List splitsList = descriptor.getSplits();
133: for (int i = 0; i < splitsList.size(); i++)
134:
135: {
136: SplitDescriptor split = (SplitDescriptor) splitsList
137: .get(i);
138: addSplitDescriptor(split);
139: }
140: List joinsList = descriptor.getJoins();
141: for (int i = 0; i < joinsList.size(); i++) {
142: JoinDescriptor join = (JoinDescriptor) joinsList.get(i);
143: addJoinDescriptor(join);
144: }
145: getWorkflowGraphModel().insertResultConnections();
146: }
147: }
148:
149: public Layout getGraphLayout() {
150: return layout;
151: }
152:
153: public void autoLayout() {
154: if (descriptor.getSteps().size() > 0) {
155: LayoutAlgorithm algo = new SugiyamaLayoutAlgorithm();
156: Properties p = new Properties();
157: p
158: .put(
159: SugiyamaLayoutAlgorithm.KEY_HORIZONTAL_SPACING,
160: "110");
161: p.put(SugiyamaLayoutAlgorithm.KEY_VERTICAL_SPACING, "70");
162: algo.perform(this , true, p);
163: }
164: }
165:
166: public void addInitialActions(List initialActionList) {
167: InitialActionCell initialActionCell = new InitialActionCell(
168: ResourceManager.getString("action.initial.step"));
169: // Create Vertex Attributes
170: if (layout != null) {
171: double[] bounds = layout.getBounds(initialActionCell
172: .getId(), "InitialActionCell");
173: if (bounds != null) {
174: Rectangle2D rect = new Rectangle();
175: rect
176: .setRect(bounds[0], bounds[1], bounds[2],
177: bounds[3]);
178: initialActionCell.getAttributes().put(
179: GraphConstants.BOUNDS, rect);
180: }
181: if (initialActionCell.getChildCount() == 0) {
182: WorkflowPort port = new WorkflowPort();
183: initialActionCell.add(port);
184: }
185: } else {
186: WorkflowPort port = new WorkflowPort();
187: initialActionCell.add(port);
188:
189: }
190: getWorkflowGraphModel().insertInitialActions(initialActionList,
191: initialActionCell, null, null, null);
192: }
193:
194: public void addJoinDescriptor(JoinDescriptor descriptor) {
195: JoinCell join = new JoinCell(descriptor);
196: // Create Vertex Attributes
197: if (layout != null) {
198: double[] bounds = layout
199: .getBounds(join.getId(), "JoinCell");
200: if (bounds != null) {
201: Rectangle2D rect = new Rectangle();
202: rect
203: .setRect(bounds[0], bounds[1], bounds[2],
204: bounds[3]);
205: join.getAttributes().put(GraphConstants.BOUNDS, rect);
206: }
207: if (join.getChildCount() == 0) {
208: WorkflowPort port = new WorkflowPort();
209: join.add(port);
210: }
211:
212: } else {
213: WorkflowPort port = new WorkflowPort();
214: join.add(port);
215:
216: }
217: getWorkflowGraphModel().insertJoinCell(join, null, null, null);
218: }
219:
220: public void addSplitDescriptor(SplitDescriptor descriptor) {
221: SplitCell split = new SplitCell(descriptor);
222: if (layout != null) {
223: double[] bounds = layout.getBounds(split.getId(),
224: "SplitCell");
225: if (bounds != null) {
226: Rectangle2D rect = new Rectangle();
227: rect
228: .setRect(bounds[0], bounds[1], bounds[2],
229: bounds[3]);
230: split.getAttributes().put(GraphConstants.BOUNDS, rect);
231: }
232: if (split.getChildCount() == 0) {
233: WorkflowPort port = new WorkflowPort();
234: split.add(port);
235: }
236: } else {
237: WorkflowPort port = new WorkflowPort();
238: split.add(port);
239:
240: }
241: getWorkflowGraphModel()
242: .insertSplitCell(split, null, null, null);
243: }
244:
245: public void addStepDescriptor(StepDescriptor descriptor) {
246: StepCell step = CellFactory.createStep(
247: (WorkflowDescriptor) descriptor.getParent(),
248: descriptor, getWorkflowGraphModel(), null);
249: if (layout != null) {
250: double[] bounds = layout
251: .getBounds(step.getId(), "StepCell");
252: if (bounds != null) {
253: Rectangle2D rect = new Rectangle();
254: rect
255: .setRect(bounds[0], bounds[1], bounds[2],
256: bounds[3]);
257: step.getAttributes().put(GraphConstants.BOUNDS, rect);
258: }
259: }
260: // Insert into Model
261: // getWorkflowGraphModel().insertStepCell(step, null, null, null);
262: }
263:
264: public WorkflowGraphModel getWorkflowGraphModel() {
265: return (WorkflowGraphModel) getModel();
266: }
267:
268: public void showMenu(int x, int y) {
269: menuLocation.x = x;
270: menuLocation.y = y;
271: genericMenu.show(this , x, y);
272: }
273:
274: public void showDelete(int x, int y) {
275: menuLocation.x = x;
276: menuLocation.y = y;
277: cellMenu.show(this , x, y);
278: }
279:
280: public void showEdgeMenu(int x, int y) {
281: menuLocation.x = x;
282: menuLocation.y = y;
283: edgeMenu.show(this , x, y);
284: }
285:
286: public boolean removeEdge(ResultEdge edge) {
287: return getWorkflowGraphModel().removeEdge(edge);
288: }
289:
290: public boolean removeStep(StepCell step) {
291: getWorkflowGraphModel().removeStep(step);
292: return true;
293: }
294:
295: public boolean removeJoin(JoinCell join) {
296: return getWorkflowGraphModel().removeJoin(join);
297: }
298:
299: public boolean removeSplit(SplitCell split) {
300: return getWorkflowGraphModel().removeSplit(split);
301: }
302:
303: public void dragEnter(DropTargetDragEvent dtde) {
304: }
305:
306: public void dragOver(DropTargetDragEvent dtde) {
307: }
308:
309: public void dropActionChanged(DropTargetDragEvent dtde) {
310:
311: }
312:
313: public void drop(DropTargetDropEvent dtde) {
314: try {
315: //Ok, get the dropped object and try to figure out what it is.
316: Transferable tr = dtde.getTransferable();
317: DataFlavor[] flavors = tr.getTransferDataFlavors();
318: for (int i = 0; i < flavors.length; i++) {
319: if (flavors[i].isFlavorSerializedObjectType()) {
320: if (flavors[i].equals(DragData.WORKFLOW_FLAVOR)) {
321: dtde
322: .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
323: DragData o = (DragData) tr
324: .getTransferData(flavors[i]);
325: dtde.dropComplete(true);
326: CellFactory.createCell(this .descriptor, this
327: .getWorkflowGraphModel(), dtde
328: .getLocation(), o);
329: return;
330: }
331: }
332: }
333: dtde.rejectDrop();
334: } catch (Exception e) {
335: e.printStackTrace();
336: dtde.rejectDrop();
337: }
338: }
339:
340: public void dragExit(DropTargetEvent dte) {
341:
342: }
343:
344: public UndoManager getUndoManager() {
345: return undoManager;
346: }
347: }
|