Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / simulator / interfaces / swing / SwingPresenter.java
package simulator.interfaces.swing;

import java.awt.Component;
import java.awt.Toolkit;
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 javax.swing.SwingUtilities;

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 {
	public final String screenUpdateChannelName = "ScreenUpdate";
	public final String setVisibleChannelName = "SetVisible";
	public final String setTextChannelName = "SetText";
	public final String mouseEventChannelName = "MouseEvent";
	public final String textEventChannelName = "TextEvent";
	
	protected JPanel mainPanel;
	protected Simulator simulator;
	protected Map<String, Component> components;
	protected DataTransferChannel screenUpdateChannel;
	protected DataTransferChannel setVisibleChannel;
	protected DataTransferChannel setTextChannel;
	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);
		setVisibleChannel = (DataTransferChannel) simulator.getModel().getChannel(setVisibleChannelName);
		setTextChannel = (DataTransferChannel) simulator.getModel().getChannel(setTextChannelName);
		mouseEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(mouseEventChannelName);
		textEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(textEventChannelName);
		simulator.addNativeReceiver(this, screenUpdateChannel);
	}

	@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 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\"");
									JButton button = new JButton(text.toString().replace("\"", ""));
									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, widgetsResource);
									
									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, widgetsResource);
								} else if (type.toString().equals("\"label\"")) {
									// Add a label component.
									Expression text = widget.get("\"text\"");
									JLabel label = new JLabel(text.toString().replace("\"", ""));
									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, widgetsResource);
									
									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, widgetsResource);
								} else if (type.toString().equals("\"textInput\"")) {
									// Add a text input component.
									JTextField textField = new JTextField(10);
									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, widgetsResource);
								}
							}
						}
						mainPanel.invalidate();
						mainPanel.validate();
						mainPanel.repaint();
					}
				}
			}
		}
	}

}