diff --git a/AlgebraicDataflowArchitectureModel/models/TableUI.model b/AlgebraicDataflowArchitectureModel/models/TableUI.model new file mode 100644 index 0000000..defb520 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/TableUI.model @@ -0,0 +1,114 @@ +init { + screenTemplates := { + "000": { + "widgets": { + "001": {"type": "textInput", "text": "", "state": 0, "visible": true}, + "002": {"type": "table", "text": "testTeble", "state": 0, "visible": true, + "data": {"_": {"name": "_", "age": 0}}, + "rowHeight": 40, + "colWidth": 100, + "columns": append(append(nil, "name"), "age"), + "primaryKeyName": "id", + } + }, + "layout": true + } + } + screen1 := "000" + w002 := "002" +} + +native channel ScreenUpdate { + in screen(curSc: Json, update(curSc, nextSc)) = nextSc +} + +native channel SetLayout { + in screen.layout(curLayout: Bool, setLayout(nextLayout)) = nextLayout +} + +native channel SetVisible(wid: Str) { + in screen.widgets.{wid}.visible(curVisible: Bool, setVisible(nextVisible)) = nextVisible +} + +native channel SetText(wid: Str) { + in screen.widgets.{wid}.text(curText: Str, setText(nextText)) = nextText +} + +native channel SetX(wid: Str) { + in screen.widgets.{wid}.x(curX: Int, setX(nextX)) = nextX +} + +native channel SetY(wid: Str) { + in screen.widgets.{wid}.y(curY: Int, setY(nextY)) = nextY +} + +native channel SetWidth(wid: Str) { + in screen.widgets.{wid}.width(curWidth: Int, setWidth(nextWidth)) = nextWidth +} + +native channel SetHeight(wid: Str) { + in screen.widgets.{wid}.height(curHeight: Int, setHeight(nextHeight)) = nextHeight +} + +native channel MouseEvent(wid: Str) { + out screen.widgets.{wid}.state(curState: Int, mouseEvent(nextState)) = nextState +} + +native channel OnTableChanged(wid: Str) { + in screen.widgets.{wid}.data(curData: Map, tableChanged(nextData)) = nextData +} + +native channel TextEvent(wid: Str) { + out screen.widgets.{wid}.text(curText: Str, textEvent(nextText)) = nextText +} + +channel ChangeCurScreen { + out curScreen(curScId: Str, changeCurScreen(nextScId)) = nextScId +} + +channel ScreenTransition { + in curScreen(curScId: Str, transScreen(nextScId, screen)) = nextScId + ref screenTemplates.{nextScId}(screen, transScreen(nextScId, screen)) + out screen(curS, transScreen(nextScId, screen)) = screen +} + +channel EventDispatch(wid: Str) { + in screen.widgets.{wid}.state(curState: Int, dispatchEvent(curScId, wid, nextState)) = nextState + ref curScreen(curScId: Str, dispatchEvent(curScId, wid, nextState)) + out screenTemplates.{curScId}.widgets.{wid}.state(curState: Int, dispatchEvent(curScId, wid, nextState)) = nextState +} + + +channel EventHandler1(scId: Str, wid: Str) { + in screenTemplates.{scId="000"}.widgets.{wid="002"}.state(curState: Int, handleEvent1(nextState)) = nextState + out curScreen(curScId: Str, handleEvent1(nextState)) = if(nextState == 0, "001", curScId) +} + +channel EventHandler2(scId: Str, wid: Str) { + in screenTemplates.{scId="001"}.widgets.{wid="004"}.state(curState: Int, handleEvent2(nextState)) = nextState + out curScreen(curScId: Str, handleEvent2(nextState)) = if(nextState == 0, "000", curScId) +} + +channel EventHandler3(curScId: Str, wid: Str) { + in screenTemplates.{curScId="000"}.widgets.{wid="002"}.data(curData: Map, handleEvent3(nextData, wid)) = nextData + out screen.widgets.{wid="002"}.data(curData: Map, handleEvent3(nextData, wid)) = nextData +} + +channel addAccount { + out accounts(accounts: Map, addAccount(id: Str, name: Str, age: Int)) = insert(accounts, id, {"name": name, "age": age}) +} + +channel changeNameOfAccount(id: Str) { + out accounts.{id}.name(curName: Str, changeName(nextName: Str)) = nextName +} + +channel changeNameOfAccount(id: Str) { + out accounts.{id}.age(curAge: Int, changeAge(nextAge: Int)) = nextAge +} + +channel sendAccountToTable { + in accounts(cur: Map, sendAccount(next: Map, scId:Str, wid:Str)) = next + ref screen1(scId:Str, sendAccount(next, scId, wid)) + ref w002(wid: Str, sendAccount(next, scId, wid)) + out screenTemplates.{scId}.widgets.{wid}.data(cur: Map, sendAccount(next, scId, wid)) = next +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java index ba514e9..bdd76dd 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java @@ -6,7 +6,10 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; import javax.swing.JTextField; +import javax.swing.table.DefaultTableModel; import java.util.HashMap; import java.util.HashSet; @@ -17,6 +20,7 @@ import models.algebra.Expression; import models.algebra.Term; import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.ListTerm; import models.dataConstraintModel.MapTerm; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferChannel; @@ -38,6 +42,7 @@ public final String setHeightChannelName = "SetHeight"; public final String mouseEventChannelName = "MouseEvent"; public final String textEventChannelName = "TextEvent"; + public final String OnTableChangedChannelName = "OnTableChanged"; protected JPanel mainPanel; protected Simulator simulator; @@ -54,6 +59,7 @@ protected DataTransferChannel setHeightChannel; protected DataTransferChannel mouseEventChannel; protected DataTransferChannel textEventChannel; + protected DataTransferChannel onTableChangedChannel; protected Map> channelAndResourcesForReceiving = new HashMap<>(); @@ -71,6 +77,7 @@ setHeightChannel = (DataTransferChannel) simulator.getModel().getChannel(setHeightChannelName); mouseEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(mouseEventChannelName); textEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(textEventChannelName); + onTableChangedChannel = (DataTransferChannel)simulator.getModel().getChannel(OnTableChangedChannelName); simulator.addNativeReceiver(this, screenUpdateChannel); simulator.addNativeReceiver(new SwingLayout(), setLayoutChannel); } @@ -294,6 +301,147 @@ } resources.put(newWid, widgetHeightResource); } + } else if (type instanceof Constant && ((String)((Constant) type).getValue()).equals("table")) { + // Add a label component. + Expression text = widget.get("text"); + Expression x = widget.get("x"); + Expression y = widget.get("y"); + Expression width = widget.get("width"); + Expression height = widget.get("height"); + MapTerm data = (MapTerm)widget.get("data"); + ListTerm columnsList = (ListTerm)widget.get("columns"); + Constant rowNumExp = (Constant)widget.get("rowNum"); + Constant rowHeightExp = (Constant)widget.get("rowHeight"); + Constant primaryKeyNameExp = (Constant) widget.get("primaryKeyName"); + boolean primaryKeyVisible = !primaryKeyNameExp.getValue().equals(""); + +// JLabel label = new JLabel(((String) ((Constant) text).getValue())); + int colNum = columnsList.size() + (primaryKeyVisible ? 1 : 0); + String[] columns = new String[colNum]; + String[][] tableDatas = new String[data.keySet().size()][colNum]; + if(primaryKeyVisible) { + columns[0] = (String)primaryKeyNameExp.getValue(); + for(int i = 1; i < colNum; i++) { + columns[i] = (String)((Constant)columnsList.get(i - 1)).getValue(); + } + } else { + for(int i = 0; i < colNum; i++) { + columns[i] = (String)((Constant)columnsList.get(i)).getValue(); + } + } + int dataCount = 0; + for(String dataKey : data.keySet()) { + JsonTerm rowData = (JsonTerm) data.get(dataKey); + if(primaryKeyVisible) { + tableDatas[dataCount][0] = dataKey; + for(int j = 1; j < columns.length; j++) { + Constant cellValue = (Constant) rowData.get(columns[j]); + if(cellValue == null) { + tableDatas[dataCount][j] = "error"; + } else { + tableDatas[dataCount][j] = (String)((Constant) rowData.get(columns[j])).getValue(); + } + } + } else { + for(int j = 0; j < columns.length; j++) { + Constant cellValue = (Constant) rowData.get(columns[j]); + if(cellValue == null) { + tableDatas[dataCount][j] = "error"; + } else { + tableDatas[dataCount][j] = (String)((Constant) rowData.get(columns[j])).getValue(); + } + } + } + dataCount++; + } + DefaultTableModel tableModel = new DefaultTableModel(tableDatas, columns); + JTable table = new JTable(tableModel) { + @Override + public boolean isCellEditable(int row, int col) { + return false; + } + }; + JScrollPane scroll = new JScrollPane(table); + + if (x != null && y != null) { + scroll.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString())); + } + if (width != null && height != null) { + scroll.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString())); + } + mainPanel.add(scroll); + components.put(newWid, scroll); + + // Connect swing component and model. + ComponentVisibilityReceiver nativeVisibilityReceiver = new ComponentVisibilityReceiver(scroll); // widgetResource => label + simulator.addNativeReceiver(nativeVisibilityReceiver, setVisibleChannel, widgetResource.getChildrenMap().get("visible")); + Map resources = channelAndResourcesForReceiving.get(setVisibleChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setVisibleChannel, resources); + } + resources.put(newWid, widgetResource); + + Resource widgetXResource = widgetResource.getChildrenMap().get("x"); + if (widgetXResource != null) { + ComponentXReceiver nativeXReceiver = new ComponentXReceiver(scroll); // widgetResource => label + simulator.addNativeReceiver(nativeXReceiver, setXChannel, widgetXResource); + resources = channelAndResourcesForReceiving.get(setXChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setXChannel, resources); + } + resources.put(newWid, widgetXResource); + } + + Resource widgetYResource = widgetResource.getChildrenMap().get("y"); + if (widgetYResource != null) { + ComponentYReceiver nativeYReceiver = new ComponentYReceiver(scroll); // widgetResource => label + simulator.addNativeReceiver(nativeYReceiver, setYChannel, widgetYResource); + resources = channelAndResourcesForReceiving.get(setYChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setYChannel, resources); + } + resources.put(newWid, widgetYResource); + } + + Resource widgetWidthResource = widgetResource.getChildrenMap().get("width"); + if (widgetWidthResource != null) { + ComponentWidthReceiver nativeWidthReceiver = new ComponentWidthReceiver(scroll); // widgetResource => label + simulator.addNativeReceiver(nativeWidthReceiver, setWidthChannel, widgetWidthResource); + resources = channelAndResourcesForReceiving.get(setWidthChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setWidthChannel, resources); + } + resources.put(newWid, widgetWidthResource); + } + + Resource widgetHeightResource = widgetResource.getChildrenMap().get("height"); + if (widgetHeightResource != null) { + ComponentHeightReceiver nativeHeightReceiver = new ComponentHeightReceiver(scroll); // widgetResource => label + simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource); + resources = channelAndResourcesForReceiving.get(setHeightChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setHeightChannel, resources); + } + resources.put(newWid, widgetHeightResource); + } + + Resource widgetDataResource = widgetResource.getChildrenMap().get("data"); + if(widgetDataResource != null ) { + TableDataReceiver tableDataReceiver = new TableDataReceiver(tableModel, columns, (String)((Constant) primaryKeyNameExp).getValue()); + simulator.addNativeReceiver(tableDataReceiver, onTableChangedChannel, widgetDataResource); + resources = channelAndResourcesForReceiving.get(onTableChangedChannel); + if(resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(onTableChangedChannel, resources); + } + resources.put(newWid, widgetDataResource); + } + } else if (type instanceof Constant && ((String)((Constant) type).getValue()).equals("textInput")) { // Add a text input component. Expression x = widget.get("x"); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/TableDataReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/TableDataReceiver.java new file mode 100644 index 0000000..f2ad1c0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/TableDataReceiver.java @@ -0,0 +1,54 @@ +package simulator.interfaces.swing; +import javax.swing.table.DefaultTableModel; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.MapTerm; +import simulator.Event; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class TableDataReceiver implements INativeReceiver{ + + protected DefaultTableModel tableModel; + protected String[] columns; + protected String primaryKeyName; + protected boolean primaryKeyVisible; + + public TableDataReceiver(DefaultTableModel table, String[] columns, String primaryKeyName) { + this.tableModel = table; + this.columns = columns; + this.primaryKeyName = primaryKeyName; + this.primaryKeyVisible = !primaryKeyName.equals(""); + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + System.out.println(message); + if(message instanceof Term) { + MapTerm data = (MapTerm)((Term) message).getChild(0); + int colNum = columns.length + (primaryKeyVisible ? 1 : 0); + String[][] tableDatas = new String[data.keySet().size()][colNum]; + int dataCount = 0; + for(String dataKey : data.keySet()) { + JsonTerm rowData = (JsonTerm) data.get(dataKey); + if(primaryKeyVisible) { + tableDatas[dataCount][0] = dataKey; + for(int j = 1; j < columns.length; j++) { + tableDatas[dataCount][j] = (String)((Constant) rowData.get(columns[j])).getValue(); + } + } else { + for(int j = 0; j < columns.length; j++) { + tableDatas[dataCount][j] = (String)((Constant) rowData.get(columns[j])).getValue(); + } + } + dataCount++; + } + tableModel.setDataVector(tableDatas, columns); + } + } + +}