package tests; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.EventObject; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.CellRendererPane; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.border.BevelBorder; import com.mxgraph.canvas.mxICanvas; import com.mxgraph.canvas.mxImageCanvas; import com.mxgraph.model.mxCell; import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxIGraphModel; import com.mxgraph.shape.mxITextShape; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.swing.handler.mxRubberband; import com.mxgraph.swing.view.mxCellEditor; import com.mxgraph.swing.view.mxICellEditor; import com.mxgraph.swing.view.mxInteractiveCanvas; import com.mxgraph.util.mxConstants; import com.mxgraph.util.mxPoint; import com.mxgraph.util.mxUtils; import com.mxgraph.view.mxCellState; import com.mxgraph.view.mxGraph; public class GraphicalViewer extends JFrame { /** * */ private static final long serialVersionUID = -844106998814982739L; final int PORT_DIAMETER = 8; final int PORT_RADIUS = PORT_DIAMETER / 2; public GraphicalViewer() { super("Graphical Viewer"); // Demonstrates the use of a Swing component for rendering vertices. // Note: Use the heavyweight feature to allow for event handling in // the Swing component that is used for rendering the vertex. mxGraph graph = new mxGraph() { public boolean isPort(Object cell) { mxGeometry geo = getCellGeometry(cell); return (geo != null) ? geo.isRelative() : false; } public boolean isCellFoldable(Object cell, boolean collapse) { return false; } }; Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo1.setRelative(true); mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); Object c1 = graph.insertVertex(parent, null, "c1", 150, 20, 30, 30); mxCell c1_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); c1_in.setVertex(true); graph.addCell(c1_in, c1); mxCell c1_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); c1_out.setVertex(true); graph.addCell(c1_out, c1); Object c2 = graph.insertVertex(parent, null, "c2", 150, 100, 30, 30); mxCell c2_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); c2_in.setVertex(true); graph.addCell(c2_in, c2); mxCell c2_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); c2_out.setVertex(true); graph.addCell(c2_out, c2); Object payment = graph.insertVertex(parent, null, "payment", 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); Object points = graph.insertVertex(parent, null, "points", 240, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); Object history = graph.insertVertex(parent, null, "history", 240, 150, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); graph.insertEdge(parent, null, "PUSH/PULL", payment, c1_in); graph.insertEdge(parent, null, "", c1_out, points); graph.insertEdge(parent, null, "PUSH/PULL", payment, c2_in); graph.insertEdge(parent, null, "", c2_out, history); } finally { graph.getModel().endUpdate(); } mxGraphComponent graphComponent = new mxGraphComponent(graph) { protected mxICellEditor createCellEditor() { final mxGraphComponent graphComponent = this; return new mxICellEditor() { /** * */ public int DEFAULT_MIN_WIDTH = 70; public int DEFAULT_MIN_HEIGHT = 30; public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; protected int minimumWidth = DEFAULT_MIN_WIDTH; protected int minimumHeight = DEFAULT_MIN_HEIGHT; private Object editingCell; private EventObject trigger; private JComboBox<String> comboBox; @Override public Object getEditingCell() { return editingCell; } @Override public void startEditing(Object cell, EventObject evt) { if (editingCell != null) { stopEditing(true); } mxCellState state = graphComponent.getGraph().getView().getState(cell); if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { editingCell = cell; trigger = evt; double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); if (comboBox == null) { comboBox = new JComboBox<>(new String[]{"PUSH", "PULL"}); comboBox.setBorder(BorderFactory.createEmptyBorder()); comboBox.setOpaque(false); } comboBox.setBounds(getEditorBounds(state, scale)); comboBox.setVisible(true); graphComponent.getGraphControl().add(comboBox, 0); comboBox.updateUI(); } } @Override public void stopEditing(boolean cancel) { if (editingCell != null) { comboBox.transferFocusUpCycle(); Object cell = editingCell; editingCell = null; if (!cancel) { EventObject trig = trigger; trigger = null; graphComponent.labelChanged(cell, getCurrentValue(), trig); } else { mxCellState state = graphComponent.getGraph().getView().getState(cell); graphComponent.redraw(state); } if (comboBox.getParent() != null) { comboBox.setVisible(false); comboBox.getParent().remove(comboBox); } graphComponent.requestFocusInWindow(); } } public String getCurrentValue() { return (String) comboBox.getSelectedItem(); } /** * Returns the bounds to be used for the editor. */ public Rectangle getEditorBounds(mxCellState state, double scale) { mxIGraphModel model = state.getView().getGraph().getModel(); Rectangle bounds = null; bounds = state.getLabelBounds().getRectangle(); bounds.height += 10; // Applies the horizontal and vertical label positions if (model.isVertex(state.getCell())) { String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); if (horizontal.equals(mxConstants.ALIGN_LEFT)) { bounds.x -= state.getWidth(); } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { bounds.x += state.getWidth(); } String vertical = mxUtils.getString(state.getStyle(), mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE); if (vertical.equals(mxConstants.ALIGN_TOP)) { bounds.y -= state.getHeight(); } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { bounds.y += state.getHeight(); } } bounds.setSize( (int) Math.max(bounds.getWidth(), Math.round(minimumWidth * scale)), (int) Math.max(bounds.getHeight(), Math.round(minimumHeight * scale))); return bounds; } }; } // // public Component[] createComponents(mxCellState state) { // if (getGraph().getModel().isEdge(state.getCell())) // { // return new Component[] { new JComboBox(new String[]{"PUSH", "PULL"}) }; // } // // return null; // } }; graphComponent.getGraphControl().addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { Object cell = graphComponent.getCellAt(e.getX(), e.getY()); if (cell != null) { System.out.println("cell="+graph.getLabel(cell)); } } }); getContentPane().add(graphComponent); } public static void main(String[] args) { GraphicalViewer frame = new GraphicalViewer(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 320); frame.setVisible(true); } }