package com.vci.client.workflow.editor; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Properties; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import com.mxgraph.canvas.mxGraphics2DCanvas; import com.mxgraph.layout.mxCircleLayout; import com.mxgraph.layout.mxCompactTreeLayout; import com.mxgraph.layout.mxEdgeLabelLayout; import com.mxgraph.layout.mxIGraphLayout; import com.mxgraph.layout.mxOrganicLayout; import com.mxgraph.layout.mxParallelEdgeLayout; import com.mxgraph.layout.mxPartitionLayout; import com.mxgraph.layout.mxStackLayout; import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.swing.mxGraphOutline; import com.mxgraph.swing.handler.mxKeyboardHandler; import com.mxgraph.swing.handler.mxRubberband; import com.mxgraph.swing.util.mxMorphing; import com.mxgraph.util.mxEvent; import com.mxgraph.util.mxEventObject; import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.util.mxRectangle; import com.mxgraph.util.mxResources; import com.mxgraph.util.mxUndoManager; import com.mxgraph.util.mxUndoableEdit; import com.mxgraph.util.mxUndoableEdit.mxUndoableChange; import com.mxgraph.view.mxGraph; import com.vci.client.workflow.editor.shape.mxTaskShape; import com.vci.client.workflow.editor.ui.FlowEditor; import com.vci.client.workflow.editor.ui.TaskNewPanel; import com.vci.client.workflow.template.object.ProcessCategoryObject; import com.vci.client.workflow.template.object.ProcessDefinitionObject; public abstract class BasicGraphEditor extends JPanel { private static final long serialVersionUID = -2957233040496509650L; /** * */ protected mxGraphComponent graphComponent; protected EditorPalette palette; /** * */ protected mxUndoManager undoManager; /** * */ protected JLabel statusBar; /** * Flag indicating whether the current graph has been modified */ protected boolean modified = false; /** * */ protected mxRubberband rubberband; /** * */ protected mxKeyboardHandler keyboardHandler; private FlowEditor editor; private Object deployPanel; private String deployPanelFlag; /** * */ protected mxIEventListener undoHandler = new mxIEventListener() { public void invoke(Object source, mxEventObject evt) { undoManager.undoableEditHappened((mxUndoableEdit) evt .getProperty("edit")); } }; /** * */ protected mxIEventListener changeTracker = new mxIEventListener() { public void invoke(Object source, mxEventObject evt) { setModified(true); } }; /** * */ public BasicGraphEditor(mxGraphComponent component) { mxGraphics2DCanvas.putShape("task", new mxTaskShape()); // Stores a reference to the graph and creates the command history graphComponent = component; final mxGraph graph = graphComponent.getGraph(); undoManager = createUndoManager(); // Do not change the scale and translation after files have been loaded graph.setResetViewOnRootChange(false); // Updates the modified flag if the graph model changes graph.getModel().addListener(mxEvent.CHANGE, changeTracker); // Adds the command history to the model and view graph.getModel().addListener(mxEvent.UNDO, undoHandler); graph.getView().addListener(mxEvent.UNDO, undoHandler); // Keeps the selection in sync with the command history mxIEventListener undoHandler = new mxIEventListener() { public void invoke(Object source, mxEventObject evt) { List changes = ((mxUndoableEdit) evt .getProperty("edit")).getChanges(); graph.setSelectionCells(graph .getSelectionCellsForChanges(changes)); } }; undoManager.addListener(mxEvent.UNDO, undoHandler); undoManager.addListener(mxEvent.REDO, undoHandler); // Creates the outer split pane that contains the inner split pane and // the graph component on the right side of the window palette = getEditorPalette(); palette.setGraph(graphComponent.getGraph()); palette.setPreferredWidth(60); final JScrollPane scrollPane = new JScrollPane(palette); editor = new FlowEditor(this); JSplitPane outer = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane, editor); outer.setOneTouchExpandable(true); outer.setDividerLocation(150);//原来是200 outer.setDividerSize(7); // Creates the status bar statusBar = createStatusBar(); // Display some useful information about repaint events installRepaintListener(); // Puts everything together setLayout(new BorderLayout()); add(outer, BorderLayout.CENTER); add(statusBar, BorderLayout.SOUTH); Properties properties = new Properties(); try { ClassLoader cl = TaskNewPanel.class.getClassLoader(); InputStream in = cl.getResourceAsStream("flow-custom.properties"); properties.load(in); deployPanelFlag = (String) properties.get("workflow.template"); if ("1".equals(deployPanelFlag)) { //获取流程模板上的所有信息(修改流程模板) deployPanel = new FlowDeployPanel(this); } else if ("2".equals(deployPanelFlag)) { //获取流程模板上的所有信息(修改流程模板) deployPanel = new FlowDeployNewPanel(this); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } if ("1".equals(deployPanelFlag)) { add((FlowDeployPanel)deployPanel, BorderLayout.NORTH); } else if ("2".equals(deployPanelFlag)) { add((FlowDeployNewPanel)deployPanel, BorderLayout.NORTH); } // Installs rubberband selection and handling for some special // keystrokes such as F2, Control-C, -V, X, A etc. installHandlers(); installListeners(); } protected mxUndoManager createUndoManager() { return new mxUndoManager(); } /** * */ protected void installHandlers() { rubberband = new mxRubberband(graphComponent); keyboardHandler = new EditorKeyboardHandler(graphComponent); } /** * */ protected JLabel createStatusBar() { JLabel statusBar = new JLabel(mxResources.get("ready")); statusBar.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); return statusBar; } /** * */ protected void installRepaintListener() { graphComponent.getGraph().addListener(mxEvent.REPAINT, new mxIEventListener() { public void invoke(Object source, mxEventObject evt) { String buffer = (graphComponent.getTripleBuffer() != null) ? "" : " (unbuffered)"; mxRectangle dirty = (mxRectangle) evt .getProperty("region"); if (dirty == null) { status("Repaint all" + buffer); } else { status("Repaint: x=" + (int) (dirty.getX()) + " y=" + (int) (dirty.getY()) + " w=" + (int) (dirty.getWidth()) + " h=" + (int) (dirty.getHeight()) + buffer); } } }); } public abstract EditorPalette getEditorPalette(); /** * */ protected void mouseWheelMoved(MouseWheelEvent e) { if (e.getWheelRotation() < 0) { graphComponent.zoomIn(); } else { graphComponent.zoomOut(); } status(mxResources.get("scale") + ": " + (int) (100 * graphComponent.getGraph().getView().getScale()) + "%"); } protected void mouseLocationChanged(MouseEvent e) { status(e.getX() + ", " + e.getY()); } /** * */ protected void installListeners() { // Installs mouse wheel listener for zooming MouseWheelListener wheelTracker = new MouseWheelListener() { public void mouseWheelMoved(MouseWheelEvent e) { if (e.getSource() instanceof mxGraphOutline || e.isControlDown()) { BasicGraphEditor.this.mouseWheelMoved(e); } } }; // Handles mouse wheel events in the outline and graph component graphComponent.addMouseWheelListener(wheelTracker); // Installs a mouse motion listener to display the mouse location graphComponent.getGraphControl().addMouseMotionListener( new MouseMotionListener() { /* * (non-Javadoc) * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent) */ public void mouseDragged(MouseEvent e) { mouseLocationChanged(e); } /* * (non-Javadoc) * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent) */ public void mouseMoved(MouseEvent e) { mouseDragged(e); } }); } /** * * @param modified */ public void setModified(boolean modified) { boolean oldValue = this.modified; this.modified = modified; firePropertyChange("modified", oldValue, modified); } /** * * @return whether or not the current graph has been modified */ public boolean isModified() { return modified; } /** * */ public mxGraphComponent getGraphComponent() { return graphComponent; } /** * */ public mxUndoManager getUndoManager() { return undoManager; } /** * * @param name * @param action * @return a new Action bound to the specified string name */ public Action bind(String name, final Action action) { return bind(name, action, null); } /** * * @param name * @param action * @return a new Action bound to the specified string name and icon */ @SuppressWarnings("serial") public Action bind(String name, final Action action, String iconUrl) { ImageIcon imageIcon = null; if(iconUrl != null) { imageIcon = new ImageIcon( BasicGraphEditor.class.getResource(iconUrl)); } AbstractAction abstractAction = new AbstractAction(name, imageIcon) { public void actionPerformed(ActionEvent e) { action.actionPerformed(new ActionEvent(getGraphComponent(), e .getID(), e.getActionCommand())); } }; return abstractAction; } /** * * @param msg */ public void status(String msg) { statusBar.setText(msg); } /** * */ public void exit() { JFrame frame = (JFrame) SwingUtilities.windowForComponent(this); if (frame != null) { frame.dispose(); } } /** * */ public void setLookAndFeel(String clazz) { JFrame frame = (JFrame) SwingUtilities.windowForComponent(this); if (frame != null) { try { UIManager.setLookAndFeel(clazz); SwingUtilities.updateComponentTreeUI(frame); // Needs to assign the key bindings again keyboardHandler = new EditorKeyboardHandler(graphComponent); } catch (Exception e1) { e1.printStackTrace(); } } } /** * Creates an action that executes the specified layout. * * @param key Key to be used for getting the label from mxResources and also * to create the layout instance for the commercial graph editor example. * @return an action that executes the specified layout */ @SuppressWarnings("serial") public Action graphLayout(final String key, boolean animate) { final mxIGraphLayout layout = createLayout(key, animate); if (layout != null) { return new AbstractAction(mxResources.get(key)) { public void actionPerformed(ActionEvent e) { final mxGraph graph = graphComponent.getGraph(); Object cell = graph.getSelectionCell(); if (cell == null || graph.getModel().getChildCount(cell) == 0) { cell = graph.getDefaultParent(); } graph.getModel().beginUpdate(); try { long t0 = System.currentTimeMillis(); layout.execute(cell); status("Layout: " + (System.currentTimeMillis() - t0) + " ms"); } finally { mxMorphing morph = new mxMorphing(graphComponent, 20, 1.2, 20); morph.addListener(mxEvent.DONE, new mxIEventListener() { public void invoke(Object sender, mxEventObject evt) { graph.getModel().endUpdate(); } }); morph.startAnimation(); } } }; } else { return new AbstractAction(mxResources.get(key)) { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(graphComponent, mxResources.get("noLayout")); } }; } } /** * Creates a layout instance for the given identifier. */ protected mxIGraphLayout createLayout(String ident, boolean animate) { mxIGraphLayout layout = null; if (ident != null) { mxGraph graph = graphComponent.getGraph(); if (ident.equals("verticalHierarchical")) { layout = new mxHierarchicalLayout(graph); } else if (ident.equals("horizontalHierarchical")) { layout = new mxHierarchicalLayout(graph, JLabel.WEST); } else if (ident.equals("verticalTree")) { layout = new mxCompactTreeLayout(graph, false); } else if (ident.equals("horizontalTree")) { layout = new mxCompactTreeLayout(graph, true); } else if (ident.equals("parallelEdges")) { layout = new mxParallelEdgeLayout(graph); } else if (ident.equals("placeEdgeLabels")) { layout = new mxEdgeLabelLayout(graph); } else if (ident.equals("organicLayout")) { layout = new mxOrganicLayout(graph); } if (ident.equals("verticalPartition")) { layout = new mxPartitionLayout(graph, false) { /** * Overrides the empty implementation to return the size of the * graph control. */ public mxRectangle getContainerSize() { return graphComponent.getLayoutAreaSize(); } }; } else if (ident.equals("horizontalPartition")) { layout = new mxPartitionLayout(graph, true) { /** * Overrides the empty implementation to return the size of the * graph control. */ public mxRectangle getContainerSize() { return graphComponent.getLayoutAreaSize(); } }; } else if (ident.equals("verticalStack")) { layout = new mxStackLayout(graph, false) { /** * Overrides the empty implementation to return the size of the * graph control. */ public mxRectangle getContainerSize() { return graphComponent.getLayoutAreaSize(); } }; } else if (ident.equals("horizontalStack")) { layout = new mxStackLayout(graph, true) { /** * Overrides the empty implementation to return the size of the * graph control. */ public mxRectangle getContainerSize() { return graphComponent.getLayoutAreaSize(); } }; } else if (ident.equals("circleLayout")) { layout = new mxCircleLayout(graph); } } return layout; } public FlowEditor getEditor() { return editor; } public Object getDeployPanel() { return deployPanel; } public String getDeployPanelFlag() { return deployPanelFlag; } public void setFlowCategory(ProcessCategoryObject flowCategory) { if ("1".equals(deployPanelFlag)) { ((FlowDeployPanel)deployPanel).setFlowCategory(flowCategory); } else if ("2".equals(deployPanelFlag)) { ((FlowDeployNewPanel)deployPanel).setFlowCategory(flowCategory); } } public void setProcessDefinition(ProcessDefinitionObject selectedObj) throws Exception { if ("1".equals(deployPanelFlag)) { ((FlowDeployPanel)deployPanel).setProcessDefinition(selectedObj); } else if ("2".equals(deployPanelFlag)) { ((FlowDeployNewPanel)deployPanel).setProcessDefinition(selectedObj); } } /** * 模板导入时调用 * @param graphXml * @param processXml * @throws Exception */ public void setProcessDefinition(byte[] graphXml, byte[] processXml,ProcessDefinitionObject pd,byte[] objectXml ) throws Exception { if ("1".equals(deployPanelFlag)) { ((FlowDeployPanel)deployPanel).setProcessDefinition(graphXml,processXml,pd,objectXml); } else if ("2".equals(deployPanelFlag)) { ((FlowDeployNewPanel)deployPanel).setProcessDefinition(graphXml,processXml,pd,objectXml); } } }