/* * The University of Wales, Cardiff Triana Project Software License (Based * on the Apache Software License Version 1.1) * * Copyright (c) 2007 University of Wales, Cardiff. All rights reserved. * * Redistribution and use of the software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, * must include the following acknowledgment: "This product includes * software developed by the University of Wales, Cardiff for the Triana * Project (http://www.trianacode.org)." Alternately, this * acknowledgment may appear in the software itself, if and wherever * such third-party acknowledgments normally appear. * * 4. The names "Triana" and "University of Wales, Cardiff" must not be * used to endorse or promote products derived from this software * without prior written permission. For written permission, please * contact triana@trianacode.org. * * 5. Products derived from this software may not be called "Triana," nor * may Triana appear in their name, without prior written permission of * the University of Wales, Cardiff. * * 6. This software may not be sold, used or incorporated into any product * for sale to third parties. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * ------------------------------------------------------------------------ * * This software consists of voluntary contributions made by many * individuals on behalf of the Triana Project. For more information on the * Triana Project, please see. http://www.trianacode.org. * * This license is based on the BSD license as adopted by the Apache * Foundation and is governed by the laws of England and Wales. * */ package org.trianacode.gui.panels; import org.trianacode.gui.action.FormatKeyStroke; import org.trianacode.gui.action.tools.DecInNodeAction; import org.trianacode.gui.action.tools.DecOutNodeAction; import org.trianacode.gui.action.tools.IncInNodeAction; import org.trianacode.gui.action.tools.IncOutNodeAction; import org.trianacode.gui.util.Env; import org.trianacode.gui.windows.ParameterWindow; import org.trianacode.gui.windows.WindowButtonConstants; import org.trianacode.taskgraph.ParameterNode; import org.trianacode.taskgraph.Task; import org.trianacode.taskgraph.TaskGraphException; import org.trianacode.taskgraph.TaskGraphUtils; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.util.Enumeration; /** * NodeEditor is the panel which pops up when units are double clicked which allows the input/output nodes to be edited * by the user at run-time. * * @author Ian Taylor * @version $Revision: 4048 $ */ public class NodeEditor extends ParameterPanel implements java.awt.event.ActionListener { public static int DEFAULT_NODE_LIMIT = 100; public static String EMPTY_LIST_STRING = "<-- None -->"; private javax.swing.JComboBox outNodes; private javax.swing.JComboBox inNodes; private javax.swing.JButton addInp; private javax.swing.JButton removeInp; private javax.swing.JButton addOut; private javax.swing.JButton removeOut; private JTabbedPane all; private JList inList = new JList(new DefaultListModel()); private JList outList = new JList(new DefaultListModel()); private JPanel inputParPanel = new JPanel(); private JPanel outputParPanel = new JPanel(); private JPanel nodes = new JPanel(); /** * Creates a NodeEditor. */ public NodeEditor() { super(); } /** * Hide auto-commit */ public boolean isAutoCommitVisible() { return false; } public void init() { setName(Env.getString("NodeEditorTitle") + " " + getTask().getToolName()); setLayout(new BorderLayout()); initOutputParameterPanel(); initInputParameterPanel(); initNodesPanel(); all = new JTabbedPane(); all.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); all.setName("Input / Output Node Settings"); all.setAutoscrolls(true); all.addTab(Env.getString("nodes"), null, nodes, "Select Number of Input/Output Nodes"); all.addTab(Env.getString("inParams"), null, inputParPanel, "Select Input Nodes for Parameter Input"); all.addTab(Env.getString("outParams"), null, outputParPanel, "Select Output Nodes for Parameter Output"); add(all, BorderLayout.CENTER); all.getSelectedComponent().setVisible(true); } /** * Initialises the input parameter panel */ public void initInputParameterPanel() { inputParPanel.setLayout(new BorderLayout(3, 3)); JPanel buttonpanel = new JPanel(new GridLayout(2, 1, 0, 3)); JPanel buttoncont = new JPanel(new BorderLayout()); addInp = new JButton(Env.getString("add")); addInp.addActionListener(this); buttonpanel.add(addInp); removeInp = new JButton(Env.getString("remove")); removeInp.addActionListener(this); buttonpanel.add(removeInp); buttoncont.add(buttonpanel, BorderLayout.SOUTH); inputParPanel.add(buttoncont, BorderLayout.EAST); if (getTask().getParameterInputNodeCount() == 0) { ((DefaultListModel) inList.getModel()).addElement(EMPTY_LIST_STRING); } else { ParameterNode[] inparams = getTask().getParameterInputNodes(); for (int count = 0; count < inparams.length; ++count) { ((DefaultListModel) inList.getModel()).addElement(new ParameterListElement(inparams[count])); } } inList.setPrototypeCellValue("123456789012345"); JScrollPane scroll = new JScrollPane(inList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); inputParPanel.add(new JLabel("Input Parameters"), BorderLayout.NORTH); inputParPanel.add(scroll, BorderLayout.CENTER); inputParPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); } /** * Initialises the output parameter panel */ public void initOutputParameterPanel() { outputParPanel.setLayout(new BorderLayout(3, 3)); JPanel buttonpanel = new JPanel(new GridLayout(2, 1, 0, 3)); JPanel buttoncont = new JPanel(new BorderLayout()); addOut = new JButton(Env.getString("add")); addOut.addActionListener(this); buttonpanel.add(addOut); removeOut = new JButton(Env.getString("remove")); removeOut.addActionListener(this); buttonpanel.add(removeOut); buttoncont.add(buttonpanel, BorderLayout.SOUTH); outputParPanel.add(buttoncont, BorderLayout.EAST); if (getTask().getParameterOutputNodeCount() == 0) { ((DefaultListModel) outList.getModel()).addElement(EMPTY_LIST_STRING); } else { ParameterNode[] outparams = getTask().getParameterOutputNodes(); for (int count = 0; count < outparams.length; ++count) { ((DefaultListModel) outList.getModel()).addElement(new ParameterListElement(outparams[count])); } } outList.setPrototypeCellValue("12345678901234567890"); outList.setVisibleRowCount(8); JScrollPane scroll = new JScrollPane(outList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); outputParPanel.add(new JLabel("Output Parameters"), BorderLayout.NORTH); outputParPanel.add(scroll, BorderLayout.CENTER); outputParPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); } /** * Changes the NodeCable Editor user interface to show 'out' output nodes selected */ public void outSelect(int out) { outNodes.setSelectedItem(String.valueOf(out)); } public void initNodesPanel() { Task task = getTask(); nodes.removeAll(); nodes.setLayout(new BorderLayout()); inNodes = new JComboBox(); outNodes = new JComboBox(); for (int i = task.getMinDataInputNodes(); i <= Math.min(task.getMaxDataInputNodes(), DEFAULT_NODE_LIMIT); ++i) { inNodes.addItem(String.valueOf(i)); } inNodes.setSelectedItem(String.valueOf(task.getDataInputNodeCount())); if (task.getMinDataInputNodes() == task.getMaxDataInputNodes()) { inNodes.setEnabled(false); } for (int i = task.getMinDataOutputNodes(); i <= Math.min(task.getMaxDataOutputNodes(), DEFAULT_NODE_LIMIT); ++i) { outNodes.addItem(String.valueOf(i)); } outNodes.setSelectedItem(String.valueOf(task.getDataOutputNodeCount())); if (task.getMinDataOutputNodes() == task.getMaxDataOutputNodes()) { outNodes.setEnabled(false); } JPanel choiceBoxes = new JPanel(new FlowLayout()); JLabel input = new JLabel(Env.getString("InputNodes"), JLabel.CENTER); JLabel output = new JLabel(Env.getString("OutputNodes"), JLabel.CENTER); choiceBoxes.add(input); choiceBoxes.add(inNodes); choiceBoxes.add(outNodes); choiceBoxes.add(output); nodes.add(choiceBoxes, BorderLayout.NORTH); //nodes.add(getAcceleratorPanel(), BorderLayout.CENTER); nodes.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); } /** * @return a label panel with the shortcut keys on it */ private JPanel getAcceleratorPanel() { JPanel accPanel = new JPanel(new GridLayout(3, 3, 5, 5)); accPanel.add(new JLabel("")); String label = Env.getString("InputNodes"); accPanel.add(new JLabel(label)); label = Env.getString("OutputNodes"); ; accPanel.add(new JLabel(label)); label = Env.getString("increment"); accPanel.add(new JLabel(label)); label = FormatKeyStroke .keyStroke2String((KeyStroke) (new IncInNodeAction(null)).getValue(AbstractAction.ACCELERATOR_KEY)); accPanel.add(new JLabel(label)); label = FormatKeyStroke .keyStroke2String((KeyStroke) (new IncOutNodeAction(null)).getValue(AbstractAction.ACCELERATOR_KEY)); accPanel.add(new JLabel(label)); label = Env.getString("decrement"); accPanel.add(new JLabel(label)); label = FormatKeyStroke .keyStroke2String((KeyStroke) (new DecInNodeAction(null)).getValue(AbstractAction.ACCELERATOR_KEY)); accPanel.add(new JLabel(label)); label = FormatKeyStroke .keyStroke2String((KeyStroke) (new DecOutNodeAction(null)).getValue(AbstractAction.ACCELERATOR_KEY)); accPanel.add(new JLabel(label)); JPanel outer = new JPanel(new BorderLayout()); outer.add(new JLabel(Env.getString("shortcuts"), JLabel.CENTER), BorderLayout.NORTH); JPanel inner = new JPanel(new BorderLayout()); inner.add(accPanel, BorderLayout.NORTH); outer.add(inner, BorderLayout.CENTER); return outer; } public void reset() { } /** * Called when the OK button on the unit panel is clicked. Applies node changes to the task. */ public void okClicked() { super.okClicked(); applyNodeChanges(); } /** * Called when the Apply button on the unit panel is clicked. Applies node changes to the task. */ public void applyClicked() { super.applyClicked(); applyNodeChanges(); } /** * This method adds and removes input/output nodes and parameter nodes. */ private void applyNodeChanges() { try { TaskGraphUtils.disconnectControlTask(getTask().getParent()); if (getTask().getMaxDataInputNodes() != getTask().getMinDataOutputNodes()) { int nodecount = Integer.parseInt((String) inNodes.getSelectedItem()); while (getTask().getDataInputNodeCount() < nodecount) { getTask().addDataInputNode(); } while (getTask().getDataInputNodeCount() > nodecount) { getTask().removeDataInputNode(getTask().getDataInputNode(getTask().getDataInputNodeCount() - 1)); } } // Add or remove output nodes as required if (getTask().getMaxDataOutputNodes() != getTask().getMinDataOutputNodes()) { int nodecount = Integer.parseInt((String) outNodes.getSelectedItem()); while (getTask().getDataOutputNodeCount() < nodecount) { getTask().addDataOutputNode(); } while (getTask().getDataOutputNodeCount() > nodecount) { getTask().removeDataOutputNode(getTask().getDataOutputNode(getTask().getDataOutputNodeCount() - 1)); } } // Set input parameter names, adding or removing nodes as required DefaultListModel model = ((DefaultListModel) inList.getModel()); ParameterListElement elem; for (int count = 0; count < model.getSize(); count++) { if (!model.elementAt(count).equals(EMPTY_LIST_STRING)) { elem = (ParameterListElement) model.elementAt(count); if (count < getTask().getParameterInputNodeCount()) { getTask().getParameterInputNode(count).setParameterName(elem.getParameterName()); } else { getTask().addParameterInputNode(elem.getParameterName()); } if (elem.isTrigger()) { getTask().getParameterInputNode(count).setTriggerNode(true); } } } while (getTask().getParameterInputNodeCount() > model.getSize()) { getTask().removeParameterInputNode( getTask().getParameterInputNode(getTask().getParameterInputNodeCount() - 1)); } if (model.contains(EMPTY_LIST_STRING) && (getTask().getParameterInputNodeCount() == 1)) { getTask().removeParameterInputNode(getTask().getParameterInputNode(0)); } // Set output parameter names, adding or removing nodes as required model = ((DefaultListModel) outList.getModel()); for (int count = 0; count < model.getSize(); count++) { if (!model.elementAt(count).equals(EMPTY_LIST_STRING)) { elem = (ParameterListElement) model.elementAt(count); if (count < getTask().getParameterOutputNodeCount()) { getTask().getParameterOutputNode(count).setParameterName(elem.getParameterName()); } else { getTask().addParameterOutputNode(elem.getParameterName()); } } } while (getTask().getParameterOutputNodeCount() > model.getSize()) { getTask().removeParameterOutputNode( getTask().getParameterOutputNode(getTask().getParameterOutputNodeCount() - 1)); } if (model.contains(EMPTY_LIST_STRING) && (getTask().getParameterOutputNodeCount() == 1)) { getTask().removeParameterOutputNode(getTask().getParameterOutputNode(0)); } TaskGraphUtils.connectControlTask(getTask().getParent()); } catch (TaskGraphException except) { except.printStackTrace(); getTask().getParent().removeControlTask(); } String incount = String.valueOf(getTask().getDataInputNodeCount()); if (((DefaultComboBoxModel) inNodes.getModel()).getIndexOf(incount) == -1) { ((DefaultComboBoxModel) inNodes.getModel()).addElement(incount); } inNodes.setSelectedItem(incount); String outcount = String.valueOf(getTask().getDataOutputNodeCount()); if (((DefaultComboBoxModel) outNodes.getModel()).getIndexOf(outcount) == -1) { ((DefaultComboBoxModel) outNodes.getModel()).addElement(outcount); } outNodes.setSelectedItem(outcount); } public void actionPerformed(ActionEvent e) { if (e.getSource() == addInp) { addParameter(inList, true); } else if (e.getSource() == removeInp) { if (inList.getSelectedIndex() > -1) { Object[] selected = inList.getSelectedValues(); for (int count = 0; count < selected.length; count++) { ((DefaultListModel) inList.getModel()).removeElement(selected[count]); } } if (inList.getModel().getSize() == 0) { ((DefaultListModel) inList.getModel()).addElement(EMPTY_LIST_STRING); } } else if (e.getSource() == addOut) { addParameter(outList, false); } else if (e.getSource() == removeOut) { if (outList.getSelectedIndex() > -1) { Object[] selected = outList.getSelectedValues(); for (int count = 0; count < selected.length; count++) { ((DefaultListModel) outList.getModel()).removeElement(selected[count]); } } if (outList.getModel().getSize() == 0) { ((DefaultListModel) outList.getModel()).addElement(EMPTY_LIST_STRING); } } } /** * Displays a list of available parameters, and adds the selected parameter. */ private void addParameter(JList list, boolean input) { AddParameterNodePanel panel; if (input) { String[] existlist = new String[0]; if (!((DefaultListModel) list.getModel()).contains(EMPTY_LIST_STRING)) { existlist = new String[((DefaultListModel) list.getModel()).size()]; Enumeration enumeration = ((DefaultListModel) list.getModel()).elements(); for (int count = 0; count < existlist.length; count++) { existlist[count] = ((ParameterListElement) enumeration.nextElement()).getParameterName(); } } panel = new AddParameterNodePanel(existlist); } else { panel = new AddParameterNodePanel(false); } panel.setTask(getTask()); panel.init(); ParameterWindow window = new ParameterWindow(this, WindowButtonConstants.OK_CANCEL_BUTTONS, true); window.setLocation(getLocationOnScreen().x + 150, getLocationOnScreen().y + 40); window.setParameterPanel(panel); window.setTitle(Env.getString("addParameterNode")); window.setVisible(true); if (window.isAccepted()) { if (((DefaultListModel) list.getModel()).contains(EMPTY_LIST_STRING)) { ((DefaultListModel) list.getModel()).removeElement(EMPTY_LIST_STRING); } if (panel.isParameterNode()) { String[] selected = panel.getParameterNames(); for (int count = 0; count < selected.length; count++) { ((DefaultListModel) list.getModel()) .addElement(new ParameterListElement(selected[count], panel.isTriggerNode())); } } else { ((DefaultListModel) list.getModel()) .addElement(new ParameterListElement(ParameterNode.TRIGGER_PARAM, panel.isTriggerNode())); } if (((DefaultListModel) list.getModel()).size() == 0) { ((DefaultListModel) list.getModel()).addElement(EMPTY_LIST_STRING); } } } /** * Called when the panel is finished with. */ public void dispose() { } public class ParameterListElement { private String paramname; private boolean trigger; public ParameterListElement(ParameterNode node) { paramname = node.getParameterName(); trigger = node.isTriggerNode(); } public ParameterListElement(String paramname, boolean trigger) { this.paramname = paramname; this.trigger = trigger; } public String getParameterName() { return paramname; } public boolean isTrigger() { return trigger; } public String toString() { if (isTrigger() && paramname.equals(ParameterNode.TRIGGER_PARAM)) { return "[TRIGGER]"; } else if (isTrigger()) { return paramname + " [TRIGGER]"; } else { return paramname; } } } }