Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / application / editor / DataTransferModelingCellEditor.java
package application.editor;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.util.EventObject;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JComboBox;
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.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 models.algebra.Expression;
import models.dataFlowModel.DataTransferModel;
import models.dataFlowModel.DataTransferChannel;
import models.dataFlowModel.PushPullAttribute;
import models.dataFlowModel.PushPullValue;
import models.visualModel.FormulaChannel;
import parser.Parser;
import parser.Parser.TokenStream;
import parser.exceptions.ExpectedDoubleQuotation;
import parser.exceptions.ExpectedRightBracket;

public class DataTransferModelingCellEditor  implements mxICellEditor {
	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 Object editingCell;
	private EventObject trigger;
	private JComboBox<String> comboBox;
	private mxGraphComponent graphComponent;
	private Editor editor;

	public DataTransferModelingCellEditor(mxGraphComponent graphComponent, Editor editor) {
		this.graphComponent = graphComponent;
		this.editor = editor;
	}

	@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)) {
			DataTransferModel model = editor.getModel();
			DataTransferChannel ch = (DataTransferChannel) model.getChannel((String) ((mxCell) cell).getValue());
			if (ch == null) {
				ch = (DataTransferChannel) model.getIOChannel((String) ((mxCell) cell).getValue());
				if(ch == null) {
					//resource
					return;
				}
			}

			if(ch instanceof FormulaChannel) {

				JPanel panel = new JPanel();
				JLabel label1 = new JLabel("Formula: ");
				JLabel label2 = new JLabel("Source: ");
				GridBagLayout layout = new GridBagLayout();
				panel.setLayout(layout);
				GridBagConstraints gbc = new GridBagConstraints();

				gbc.gridx = 0;
				gbc.gridy = 0;
				layout.setConstraints(label1, gbc);
				panel.add(label1);

				gbc.gridx = 1;
				gbc.gridy = 0;
				JTextField formulaText = new JTextField(((FormulaChannel) ch).getFormula(),15);
				layout.setConstraints(formulaText, gbc);
				panel.add(formulaText);

				gbc.gridx = 0;
				gbc.gridy = 1;
				layout.setConstraints(label2, gbc);
				panel.add(label2);

				gbc.gridx = 1;
				gbc.gridy = 1;
				JTextArea textArea = new JTextArea(ch.getSourceText(),7,15);
				textArea.setEditable(false);
				layout.setConstraints(textArea, gbc);
				panel.add(textArea);

				int r = JOptionPane.showConfirmDialog(
						null,				// owner window
						panel,				// message
						"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) {
					TokenStream stream = new Parser.TokenStream();
					Parser parser = new Parser(stream);

					String formula = formulaText.getText();
					stream.addLine(formula.split(Parser.EQUALS)[1]);

					try {
						Expression exp = parser.parseTerm(stream, editor.getModel());
						((FormulaChannel) ch).setFormula(formula);
						((FormulaChannel) ch).setFormulaTerm(exp);
					} catch (ExpectedRightBracket | ExpectedDoubleQuotation e) {
						e.printStackTrace();
					}
				}
			}else {
				JPanel panel = new JPanel();
				JTextArea textArea = new JTextArea(ch.getSourceText(), 10, 20);
				panel.add(textArea);
				//			JEditorPane panel = new JEditorPane("text/plain", ch.toString());
				//			panel.setEditable(true);
				int ret = JOptionPane.showConfirmDialog(null, panel, "Channel Code", JOptionPane.OK_CANCEL_OPTION);
				if (ret == JOptionPane.OK_OPTION) {
					editor.setChannelCode(ch, textArea.getText());
				}
			}
			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();
			}
		}
	}

	@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;
	}

}