package simulator.interfaces.swing;
import java.awt.Component;
import java.awt.FlowLayout;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import models.algebra.Constant;
import models.algebra.Expression;
import models.algebra.Term;
import models.dataConstraintModel.JsonTerm;
import models.dataConstraintModel.MapTerm;
import models.dataConstraintModel.ResourcePath;
import models.dataFlowModel.DataTransferChannel;
import simulator.Event;
import simulator.Resource;
import simulator.Simulator;
import simulator.SystemState;
import simulator.interfaces.INativeReceiver;
public class SwingPresenter implements INativeReceiver {
// Native channel names.
public final String screenUpdateChannelName = "ScreenUpdate";
public final String setLayoutChannelName = "SetLayout";
public final String setVisibleChannelName = "SetVisible";
public final String setTextChannelName = "SetText";
public final String setXChannelName = "SetX";
public final String setYChannelName = "SetY";
public final String setWidthChannelName = "SetWidth";
public final String setHeightChannelName = "SetHeight";
public final String mouseEventChannelName = "MouseEvent";
public final String textEventChannelName = "TextEvent";
protected JPanel mainPanel;
protected Simulator simulator;
protected Map<String, Component> components;
// Native channels.
protected DataTransferChannel screenUpdateChannel;
protected DataTransferChannel setLayoutChannel;
protected DataTransferChannel setVisibleChannel;
protected DataTransferChannel setTextChannel;
protected DataTransferChannel setXChannel;
protected DataTransferChannel setYChannel;
protected DataTransferChannel setWidthChannel;
protected DataTransferChannel setHeightChannel;
protected DataTransferChannel mouseEventChannel;
protected DataTransferChannel textEventChannel;
protected Map<DataTransferChannel, Map<String, Resource>> channelAndResourcesForReceiving = new HashMap<>();
public SwingPresenter(JPanel mainPanel, Simulator simulator) {
this.mainPanel = mainPanel;
this.simulator = simulator;
components = new HashMap<>();
screenUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(screenUpdateChannelName);
setLayoutChannel = (DataTransferChannel) simulator.getModel().getChannel(setLayoutChannelName);
setVisibleChannel = (DataTransferChannel) simulator.getModel().getChannel(setVisibleChannelName);
setTextChannel = (DataTransferChannel) simulator.getModel().getChannel(setTextChannelName);
setXChannel = (DataTransferChannel) simulator.getModel().getChannel(setXChannelName);
setYChannel = (DataTransferChannel) simulator.getModel().getChannel(setYChannelName);
setWidthChannel = (DataTransferChannel) simulator.getModel().getChannel(setWidthChannelName);
setHeightChannel = (DataTransferChannel) simulator.getModel().getChannel(setHeightChannelName);
mouseEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(mouseEventChannelName);
textEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(textEventChannelName);
simulator.addNativeReceiver(this, screenUpdateChannel);
simulator.addNativeReceiver(new SwingLayout(), setLayoutChannel);
}
@Override
public void onReceiveFromModel(Event event, SystemState nextSystemState) {
Expression message = event.getMessage();
if (message instanceof Term && ((Term) message).getChildren().size() >= 2) {
Expression curScExp = ((Term) message).getChild(0);
Expression nextScExp = ((Term) message).getChild(1);
if (curScExp instanceof JsonTerm && nextScExp instanceof JsonTerm) {
JsonTerm curSc = (JsonTerm) curScExp;
JsonTerm nextSc = (JsonTerm) nextScExp;
Expression newLayout = nextSc.get("layout");
if (newLayout != null) {
if (newLayout.toString().equals("true")) {
mainPanel.setLayout(new FlowLayout());
} else if (newLayout.toString().equals("false")) {
mainPanel.setLayout(null);
}
}
Expression oldWidgets = curSc.get("widgets");
Expression newWidgets = nextSc.get("widgets");
if (oldWidgets instanceof MapTerm && newWidgets instanceof MapTerm) {
Set<String> oldWidSet = new HashSet<>(((MapTerm) oldWidgets).keySet());
Set<String> newWidSet = new HashSet<>(((MapTerm) newWidgets).keySet());
oldWidSet.removeAll(((MapTerm) newWidgets).keySet());
newWidSet.removeAll(((MapTerm) oldWidgets).keySet());
if (!oldWidSet.isEmpty() || !newWidSet.isEmpty()) {
// If the set of screen components is changed.
// Remove old components and their native receivers.
for (String oldWid: oldWidSet) {
mainPanel.remove(components.get(oldWid));
}
for (DataTransferChannel channel: channelAndResourcesForReceiving.keySet()) {
Map<String, Resource> widToResource = channelAndResourcesForReceiving.get(channel);
for (String oldWid: oldWidSet) {
Resource resource = widToResource.remove(oldWid);
if (resource != null) {
simulator.removeNativeReceiver(channel, resource);
}
}
}
// Add new swing components.
Resource screenResource = nextSystemState.getResource(event.getInputResource().getResourceIdentifier());
Resource widgetsResource = screenResource.getChildrenMap().get("widgets");
for (String newWid: newWidSet) {
Expression value = ((MapTerm) newWidgets).get(newWid);
if (value instanceof JsonTerm) {
JsonTerm widget = (JsonTerm) value;
Resource widgetResource = widgetsResource.getChildrenMap().get(newWid);
Expression type = widget.get("\"type\"");
if (type.toString().equals("\"button\"")) {
// Add a button 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\"");
JButton button = new JButton(text.toString().replace("\"", ""));
if (x != null && y != null) {
button.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString()));
}
if (width != null && height != null) {
button.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString()));
}
mainPanel.add(button);
components.put(newWid, button);
// Connect swing component and model.
ResourcePath resPath = mouseEventChannel.getOutputResources().iterator().next();
button.addMouseListener(new ComponentMouseSender(simulator, mouseEventChannel, resPath, widgetResource)); // button => widgetResource
ComponentVisibilityReceiver nativeVisibilityReceiver = new ComponentVisibilityReceiver(button); // widgetResource => button
simulator.addNativeReceiver(nativeVisibilityReceiver, setVisibleChannel, widgetResource);
Map<String, Resource> resources = channelAndResourcesForReceiving.get(setVisibleChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setVisibleChannel, resources);
}
resources.put(newWid, widgetResource);
ComponentTextReceiver nativeTextReceiver = new ComponentTextReceiver(button); // widgetResource => button
simulator.addNativeReceiver(nativeTextReceiver, setTextChannel, widgetResource);
resources = channelAndResourcesForReceiving.get(setTextChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setTextChannel, resources);
}
resources.put(newWid, widgetResource);
Resource widgetXResource = widgetResource.getChildrenMap().get("\"x\"");
if (widgetXResource != null) {
ComponentXReceiver nativeXReceiver = new ComponentXReceiver(button); // widgetResource => button
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(button); // widgetResource => button
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(button); // widgetResource => button
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(button); // widgetResource => button
simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource);
resources = channelAndResourcesForReceiving.get(setHeightChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setHeightChannel, resources);
}
resources.put(newWid, widgetHeightResource);
}
} else if (type.toString().equals("\"label\"")) {
// 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\"");
JLabel label = new JLabel(text.toString().replace("\"", ""));
if (x != null && y != null) {
label.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString()));
}
if (width != null && height != null) {
label.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString()));
}
mainPanel.add(label);
components.put(newWid, label);
// Connect swing component and model.
ComponentVisibilityReceiver nativeVisibilityReceiver = new ComponentVisibilityReceiver(label); // widgetResource => label
simulator.addNativeReceiver(nativeVisibilityReceiver, setVisibleChannel, widgetResource);
Map<String, Resource> resources = channelAndResourcesForReceiving.get(setVisibleChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setVisibleChannel, resources);
}
resources.put(newWid, widgetResource);
ComponentTextReceiver nativeTextReceiver = new ComponentTextReceiver(label); // widgetResource => label
simulator.addNativeReceiver(nativeTextReceiver, setTextChannel, widgetResource);
resources = channelAndResourcesForReceiving.get(setTextChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setTextChannel, resources);
}
resources.put(newWid, widgetResource);
Resource widgetXResource = widgetResource.getChildrenMap().get("x");
if (widgetXResource != null) {
ComponentXReceiver nativeXReceiver = new ComponentXReceiver(label); // 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(label); // 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(label); // 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(label); // 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);
}
} else if (type.toString().equals("\"textInput\"")) {
// Add a text input component.
Expression x = widget.get("\"x\"");
Expression y = widget.get("\"y\"");
Expression width = widget.get("\"width\"");
Expression height = widget.get("\"height\"");
JTextField textField = new JTextField(10);
if (x != null && y != null) {
textField.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString()));
}
if (width != null && height != null) {
textField.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString()));
}
mainPanel.add(textField);
components.put(newWid, textField);
// Connect swing component and model.
ResourcePath resPath = textEventChannel.getOutputResources().iterator().next();
textField.getDocument().addDocumentListener(new ComponentTextSender(simulator, textEventChannel, resPath, widgetResource)); // textField => widgetResource
ComponentVisibilityReceiver nativeReceiver = new ComponentVisibilityReceiver(textField); // widgetResource => textField
simulator.addNativeReceiver(nativeReceiver, setVisibleChannel, widgetResource);
Map<String, Resource> 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(textField); // widgetResource => textField
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(textField); // widgetResource => textField
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(textField); // widgetResource => textField
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(textField); // widgetResource => textField
simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource);
resources = channelAndResourcesForReceiving.get(setHeightChannel);
if (resources == null) {
resources = new HashMap<>();
channelAndResourcesForReceiving.put(setHeightChannel, resources);
}
resources.put(newWid, widgetHeightResource);
}
}
}
}
mainPanel.invalidate();
mainPanel.validate();
mainPanel.repaint();
}
}
}
}
}
public class SwingLayout implements INativeReceiver {
@Override
public void onReceiveFromModel(Event event, SystemState nextSystemState) {
Expression message = event.getMessage();
if (message instanceof Term && ((Term) message).getChildren().size() >= 1) {
Expression newLayout = ((Term) message).getChild(0);
if (newLayout instanceof Constant) {
if (newLayout.toString().equals("true")) {
mainPanel.setLayout(new FlowLayout());
} else if (newLayout.toString().equals("false")) {
mainPanel.setLayout(null);
}
}
}
}
}
}