package application.editor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Rectangle; import java.util.EventObject; import java.util.HashMap; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; import com.mxgraph.model.mxCell; import com.mxgraph.model.mxGraphModel; import com.mxgraph.model.mxIGraphModel; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.swing.view.mxICellEditor; import com.mxgraph.util.mxConstants; import com.mxgraph.util.mxUtils; import com.mxgraph.view.mxCellState; import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; import application.SimulatorWindow; import application.layouts.DAGLayout; import models.algebra.Expression; import models.algebra.InvalidMessage; import models.algebra.ParameterizedIdentifierIsFutureWork; import models.algebra.Term; import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; import models.algebra.Variable; import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; import models.visualModel.FormulaChannel; import parser.Parser; import parser.Parser.TokenStream; import parser.exceptions.ExpectedColon; import parser.exceptions.ExpectedRightBracket; import parser.exceptions.WrongJsonExpression; import simulator.ChannelState; import simulator.Resource; import simulator.ResourceIdentifier; import simulator.Simulator; import simulator.Event; import simulator.SystemState; public class InputEventCellEditor implements mxICellEditor { public int DEFAULT_MIN_WIDTH = 70; public int DEFAULT_MIN_HEIGHT = 30; public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; private double x = 20; private double y = 20; 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; private mxGraphComponent graphComponent; private Simulator simulator; private JComboBox<String> pulldownMenu; private Editor editor; private boolean bReflectingArchitectureModel = false; private mxGraph graph; public InputEventCellEditor(mxGraphComponent graphComponent, Simulator simulator, Editor editor, mxGraph graph) { this.graphComponent = graphComponent; this.simulator = simulator; this.editor = editor; this.graph = graph; } @Override public Object getEditingCell() { return editingCell; } @Override public void startEditing(Object cell, EventObject evt) { if (editingCell != null) { stopEditing(true); } if (!graphComponent.getGraph().getModel().isEdge(cell)) { Resource res = simulator.getCurState().getResource((String) ((mxCell) cell).getValue()); ResourceIdentifier resId = res.getResourceIdentifier();//resource ArrayList<DataTransferChannel> eventChs = new ArrayList<>();//iOchannelList ArrayList<String> messages = new ArrayList<>();//ADLmessage ArrayList<Expression> eventMessages = new ArrayList<>();//messageList ResourcePath eventResPath = null; for(Channel ch : simulator.getModel().getIOChannels()) {//all channel if(((DataTransferChannel)ch).getInputResources().size()== 0) {//ioch Or normalch for(ChannelMember out: ((DataTransferChannel)ch).getOutputChannelMembers()) { ResourcePath resPath = out.getResource(); if(resId.isInstanceOf(resPath)) {//account.uid == acounts.123 eventResPath = resPath; eventChs.add(((DataTransferChannel)ch)); String message = null; Expression mesExp = out.getStateTransition().getMessageExpression();//sync(a,b) eventMessages.add(mesExp); if(mesExp instanceof Term) { message = ((Term) mesExp).getSymbol().toString();//sync }else if(mesExp instanceof Variable) { message = ((Variable) mesExp).getName();//x,y,z.. } messages.add(message);//pulldown } } } } String[] eventList = messages.toArray(new String[messages.size()]); JComboBox<String> event = new JComboBox<String>(eventList); JPanel eventChoice = new JPanel(); eventChoice.add(event);//FirstEventChoice int ret = JOptionPane.showConfirmDialog(null, eventChoice, "Event Choice", JOptionPane.OK_CANCEL_OPTION); if (ret == JOptionPane.OK_OPTION) { JPanel inputEvent = new JPanel(); JTextArea textArea = new JTextArea(eventMessages.get(0).toString(), 10, 30);//EventInput inputEvent.add(textArea); int approve = JOptionPane.showConfirmDialog(null, inputEvent, "Event Code", JOptionPane.OK_CANCEL_OPTION); if (approve == JOptionPane.OK_OPTION) { try { TokenStream stream = new Parser.TokenStream(); Parser parser = new Parser(stream); stream.addLine(textArea.getText()); Expression eventMessage = parser.parseTerm(stream,simulator.getModel()); Event newEvent = new Event(eventChs.get(0), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); simulator.transition(newEvent); constructNextSimulateGraph(simulator.getCurState().getRootResources(), simulator.getModel(),simulator.getModel().getDataFlowGraph(), graph); graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined | ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { e.printStackTrace(); } } } //resource return; } 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()); Object value = graphComponent.getGraph().getModel().getValue(cell); if (value != null && value instanceof PushPullAttribute) { PushPullAttribute attr = (PushPullAttribute) value; comboBox = new JComboBox<>(attr.getOptionStrings()); comboBox.setBorder(BorderFactory.createEmptyBorder()); comboBox.setOpaque(false); comboBox.setBounds(getEditorBounds(state, scale)); comboBox.setVisible(true); graphComponent.getGraphControl().add(comboBox, 0); comboBox.updateUI(); } } } private mxGraph constructNextSimulateGraph(Set<Resource> simulateRes, DataTransferModel model,DataFlowGraph dataFlowGraph, mxGraph nextGraph) { bReflectingArchitectureModel = true; ((mxGraphModel) nextGraph.getModel()).clear(); Object parent = nextGraph.getDefaultParent(); nextGraph.getModel().beginUpdate(); try { Map<Resource, Object> resources = new HashMap<>(); // create resource vertices for (Resource resNode: simulateRes) { int w = 400; int h = 150; ResourcePath res = resNode.getResourceIdentifier(); Object resource = nextGraph.insertVertex(parent, null, res.getLeafResourceName(), x, y, w, h, "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex resources.put(resNode, resource); createNextChildSimulateResourceVerticies(resource, resNode, resources, w, h); x+=400; } } finally { nextGraph.getModel().endUpdate(); } bReflectingArchitectureModel = false; return nextGraph; } private void createNextChildSimulateResourceVerticies(Object resource, Resource resNode, Map<Resource, Object> resources, int w, int h) { //sample if(resNode.getChildren() != null) { for (Resource childNode: resNode.getChildren()) { int i = 1; ResourcePath childRes = childNode.getResourceIdentifier(); Object childResource = graph.insertVertex(resource, null, childRes.getName(), x/i, y, w/(i+1), h/(i+2), "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex resources.put(childNode, childResource); i++; createNextChildSimulateResourceVerticies(childResource, childNode, resources, w, h); } } } @Override public void stopEditing(boolean cancel) { if (editingCell != null) { comboBox.transferFocusUpCycle(); Object cell = editingCell; editingCell = null; if (!cancel) { EventObject trig = trigger; trigger = null; Object value = graphComponent.getGraph().getModel().getValue(cell); if (value != null && value instanceof PushPullAttribute) { PushPullAttribute attr = (PushPullAttribute) value; List<PushPullValue> options = attr.getOptions(); PushPullValue selected = null; for (PushPullValue option: options) { if (option.toString().equals(getCurrentValue())) { selected = option; break; } } if (selected != null) { options.remove(selected); options.add(0, selected); } graphComponent.labelChanged(cell, attr, 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; } }