diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index c255db9..115c5fb 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -7,45 +7,27 @@ import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; import com.mxgraph.layout.mxCircleLayout; import com.mxgraph.layout.mxCompactTreeLayout; 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.view.mxCellState; -import com.mxgraph.util.mxRectangle; import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; -import algorithms.DataTransferModelAnalyzer; -import algorithms.Validation; import application.editor.stages.ControlFlowDelegationStage; -import application.editor.stages.DataFlowCellEditor; import application.editor.stages.DataFlowModelingStage; import application.editor.stages.PushPullSelectionStage; import application.layouts.*; import code.ast.CompilationUnit; -import models.Edge; import models.EdgeAttribute; -import models.Node; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannelGenerator; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; import models.visualModel.FormulaChannelGenerator; import parser.Parser; import parser.exceptions.ExpectedAssignment; @@ -87,7 +69,7 @@ public Editor(mxGraphComponent graphComponent) { this.graphComponent = graphComponent; this.graph = graphComponent.getGraph(); - + STAGE_DATA_FLOW_MODELING = new DataFlowModelingStage(graph); STAGE_PUSH_PULL_SELECTION = new PushPullSelectionStage(graph); STAGE_CONTROL_FLOW_DELEGATION = new ControlFlowDelegationStage(graph); @@ -334,9 +316,33 @@ fileString += "geometry {\n"; - Object root = graph.getDefaultParent(); - for (int i = 0; i < graph.getModel().getChildCount(root); i++) { - Object cell = graph.getModel().getChildAt(root, i); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(Stage.NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); + for (int i = 0; i < graph.getModel().getChildCount(nodeLayer); i++) { + Object cell = graph.getModel().getChildAt(nodeLayer, i); + if (graph.getModel().isVertex(cell)) { + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + int x = (int) state.getX(); + int y = (int) state.getY(); + int w = (int) state.getWidth(); + int h = (int) state.getHeight(); + + for (IdentifierTemplate res: model.getIdentifierTemplates()){ + if(res instanceof IdentifierTemplate && state.getLabel().equals(res.getResourceName())) + fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; + } + + for (ChannelGenerator ioC: model.getIOChannelGenerators()) { + if(ioC instanceof ChannelGenerator && state.getLabel().equals(ioC.getChannelName())) { + fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; + } + } + } + } + for (int i = 0; i < graph.getModel().getChildCount(dataFlowLayer); i++) { + Object cell = graph.getModel().getChildAt(dataFlowLayer, i); if (graph.getModel().isVertex(cell)) { mxGraphView view = graph.getView(); mxCellState state = view.getState(cell); @@ -352,55 +358,47 @@ fileString +="\tnode c " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; } } - - for (IdentifierTemplate res: model.getIdentifierTemplates()){ - if(res instanceof IdentifierTemplate && state.getLabel().equals(res.getResourceName())) - fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } - - for (ChannelGenerator ioC: model.getIOChannelGenerators()) { - if(ioC instanceof ChannelGenerator && state.getLabel().equals(ioC.getChannelName())) { - fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } - } } - } + } fileString += "}\n"; return fileString; } public void setDAGLayout() { - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { DAGLayout ctl = new DAGLayout(graph); - ctl.execute(parent); + ctl.execute(dataFlowLayer); } finally { graph.getModel().endUpdate(); } } public void setTreeLayout() { - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); ctl.setLevelDistance(100); // ctl.setHorizontal(false); ctl.setEdgeRouting(false); - ctl.execute(parent); + ctl.execute(dataFlowLayer); } finally { graph.getModel().endUpdate(); } } public void setCircleLayout() { - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { mxCircleLayout ctl = new mxCircleLayout(graph); - ctl.execute(parent); + ctl.execute(dataFlowLayer); } finally { graph.getModel().endUpdate(); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java index 642c492..591927d 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -9,6 +9,10 @@ abstract public class Stage { protected DataTransferModel model = null; protected mxGraph graph = null; + public static final int NODE_LAYER = 0; + public static final int DATA_FLOW_LAYER = 0; + public static final int PUSH_FLOW_LAYER = 1; + public static final int PULL_FLOW_LAYER = 2; public Stage(mxGraph graph) { this.graph = graph; diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java index 9b400d8..30f7156 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java @@ -37,18 +37,7 @@ /************************************************************* * */ -public class DataFlowCellEditor extends FlowCellEditor { - 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 EventObject trigger; - private JComboBox comboBox; - +public class DataFlowCellEditor extends FlowCellEditor { /************************************************************* * [ *constructor ] /************************************************************* @@ -81,7 +70,7 @@ } } - if(ch instanceof FormulaChannelGenerator) { + if (ch instanceof FormulaChannelGenerator) { JPanel panel = new JPanel(); JLabel label1 = new JLabel("Formula: "); @@ -119,7 +108,7 @@ "Edit Formula Channel", // window's title JOptionPane.OK_CANCEL_OPTION, // option (button types) JOptionPane.QUESTION_MESSAGE); // message type (icon types) - if(r == JOptionPane.OK_OPTION) { + if (r == JOptionPane.OK_OPTION) { TokenStream stream = new Parser.TokenStream(); Parser parser = new Parser(stream); @@ -134,7 +123,7 @@ e.printStackTrace(); } } - }else { + } else { JPanel panel = new JPanel(); JTextArea textArea = new JTextArea(ch.getSourceText(), 10, 20); panel.add(textArea); @@ -147,25 +136,6 @@ } return; } - - mxCellState state = graphComponent.getGraph().getView().getState(cellObj); - if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { - editingCell = cellObj; - trigger = eventObj; - - double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); - Object value = graphComponent.getGraph().getModel().getValue(cellObj); - 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(); - } - } } /************************************************************* @@ -174,86 +144,5 @@ */ @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 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; - } - } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java index 4392d14..f94754f 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -58,7 +58,19 @@ public void clear() { model = null; - ((mxGraphModel) graph.getModel()).clear(); + ((mxGraphModel) graph.getModel()).clear(); + + // Construct layers. + mxCell root = (mxCell) graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + root.insert(new mxCell()); // NODE_LAYER, DATA_FLOW_LAYER + root.insert(new mxCell()); // PUSH_FLOW_LAYER + root.insert(new mxCell()); // PULL_FLOW_LAYER + } finally { + graph.getModel().endUpdate(); + } + graph.refresh(); } public DataTransferModel getModel() { @@ -69,7 +81,10 @@ } public void setModel(DataTransferModel model) { + clear(); + // Set the model. this.model = model; + // Update the mxGraph. graph = constructGraph(graph, model); } @@ -87,8 +102,9 @@ * @return constructed mxGraph */ public mxGraph constructGraph(mxGraph graph, DataTransferModel model) { - ((mxGraphModel) graph.getModel()).clear(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); @@ -107,12 +123,11 @@ for (ChannelGenerator c: model.getChannelGenerators()) { DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) c; if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + Object channel = graph.insertVertex(dataFlowLayer, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel + graph.addCell(port_in, channel); // insert the input port of a channel mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); graph.addCell(port_out, channel); // insert the output port of a channel channelsIn.put(channelGen, port_in); @@ -122,7 +137,7 @@ // create resource vertices for (IdentifierTemplate res: model.getIdentifierTemplates()) { - Object resource = graph.insertVertex(parent, null, + Object resource = graph.insertVertex(dataFlowLayer, null, res.getResourceName(), 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex resources.put(res, resource); @@ -133,27 +148,27 @@ DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) ch; // input edge for (IdentifierTemplate srcRes: channelGen.getInputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false;strokeColor=#FF0000"); + graph.insertEdge(dataFlowLayer, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false;strokeColor=#FF0000"); } // output edge for (IdentifierTemplate dstRes: channelGen.getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false;strokeColor=#FF0000"); + graph.insertEdge(dataFlowLayer, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false;strokeColor=#FF0000"); } // reference edges for (IdentifierTemplate refRes: channelGen.getReferenceIdentifierTemplates()) { - graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false;strokeColor=#FF0000"); + graph.insertEdge(dataFlowLayer, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false;strokeColor=#FF0000"); } } for (ChannelGenerator ioChannelGen: model.getIOChannelGenerators()) { if (channelsOut.get(ioChannelGen) == null) { - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + Object channel = graph.insertVertex(nodeLayer, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); port_out.setVertex(true); graph.addCell(port_out, channel); // insert the output port of a channel channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false;strokeColor=#FF0000"); + graph.insertEdge(dataFlowLayer, null, null, port_out, resources.get(outRes), "movable=false;strokeColor=#FF0000"); } } } @@ -167,9 +182,10 @@ public void addIdentifierTemplate(IdentifierTemplate res) { getModel().addIdentifierTemplate(res); graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(NODE_LAYER); try { - graph.insertVertex(parent, null, res.getResourceName(), 20, 20, 80, 30, + graph.insertVertex(layer, null, res.getResourceName(), 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex } finally { graph.getModel().endUpdate(); @@ -179,7 +195,8 @@ public void addChannelGenerator(DataTransferChannelGenerator channelGen) { getModel().addChannelGenerator(channelGen); graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); @@ -189,7 +206,7 @@ geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + Object channel = graph.insertVertex(layer, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); graph.addCell(port_in, channel); // insert the input port of a channel @@ -204,13 +221,14 @@ public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { getModel().addIOChannelGenerator(ioChannelGen); graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(NODE_LAYER); try { mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + Object channel = graph.insertVertex(layer, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); port_out.setVertex(true); graph.addCell(port_out, channel); // insert the output port of a channel @@ -222,7 +240,8 @@ public void addFormulaChannelGenerator(FormulaChannelGenerator formulaChannelGen) { getModel().addChannelGenerator(formulaChannelGen); graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); @@ -232,7 +251,7 @@ geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + Object channel = graph.insertVertex(layer, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); graph.addCell(port_in, channel); // insert the input port of a channel diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java index c25855b..f4f27da 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java @@ -1,13 +1,36 @@ package application.editor.stages; +import java.awt.Rectangle; import java.util.EventObject; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; + +import com.mxgraph.model.mxIGraphModel; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import com.mxgraph.view.mxCellState; + import application.editor.FlowCellEditor; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; /************************************************************* * */ public class PushPullSelectionCellEditor extends FlowCellEditor { + 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 EventObject trigger; + private JComboBox comboBox; /************************************************************* * [ *constructor ] @@ -26,6 +49,30 @@ */ @Override public void startEditing(Object cellObj, EventObject eventObj) { + if (editingCell != null) { + stopEditing(true); + } + + if (graphComponent.getGraph().getModel().isEdge(cellObj)) { + mxCellState state = graphComponent.getGraph().getView().getState(cellObj); + if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { + editingCell = cellObj; + trigger = eventObj; + + double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); + Object value = graphComponent.getGraph().getModel().getValue(cellObj); + 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(); + } + } + } } /************************************************************* @@ -34,6 +81,86 @@ */ @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 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; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java index 35e1a97..7c8c8c2 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -61,7 +61,8 @@ } private void updateEdgeAttiributes(mxGraph graph, DataFlowGraph dataFlowGraph) { - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell layer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { // update attributes of input and output edges @@ -71,7 +72,7 @@ DataTransferChannelGenerator channelGen = dataFlow.getChannelGenerator(); ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); ResourceNode dstRes = (ResourceNode) dataFlow.getDestination(); - for (Object edge: graph.getChildEdges(parent)) { + for (Object edge: graph.getChildEdges(layer)) { mxCell edgeCell = (mxCell) edge; if (edgeCell.getValue() instanceof SrcDstAttribute) { SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); diff --git a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java index 830bd5f..54d0bf1 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java @@ -10,6 +10,7 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; +import application.editor.Stage; import models.dataFlowModel.DataTransferModel; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; @@ -148,11 +149,28 @@ String h = stream.next(); int hC = Integer.parseInt(h); - Object root = graph.getDefaultParent(); mxIGraphModel graphModel = graph.getModel(); - for (int i = 0; i < graph.getModel().getChildCount(root); i++) { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(Stage.NODE_LAYER); + mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); + for (int i = 0; i < graph.getModel().getChildCount(nodeLayer); i++) { - Object cell = graph.getModel().getChildAt(root, i); + Object cell = graph.getModel().getChildAt(nodeLayer, i); + if (!graph.getModel().isVertex(cell)) continue; + + mxGeometry geom = (mxGeometry) ((mxCell) cell).getGeometry().clone(); + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + + if (!name.equals(state.getLabel())) continue; + + geom.setX(xC); + geom.setY(yC); + graphModel.setGeometry(cell, geom); + } + for (int i = 0; i < graph.getModel().getChildCount(dataFlowLayer); i++) { + + Object cell = graph.getModel().getChildAt(dataFlowLayer, i); if (!graph.getModel().isVertex(cell)) continue; mxGeometry geom = (mxGeometry) ((mxCell) cell).getGeometry().clone();