/* * 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.hci; import org.trianacode.gui.main.TaskComponent; import org.trianacode.gui.main.TaskGraphPanel; import org.trianacode.gui.util.Env; import org.trianacode.gui.windows.ErrorDialog; import org.trianacode.taskgraph.*; import org.trianacode.taskgraph.imp.RenderingHintImp; import org.trianacode.taskgraph.proxy.IncompatibleProxyException; import org.trianacode.taskgraph.proxy.Proxy; import org.trianacode.taskgraph.tool.Tool; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.logging.Logger; /** * A gui class with static methods for handling taskgraph operations, such as create task and connect nodes. * * @author Ian Wang * @version $Revision: 4048 $ */ public class TaskGraphHandler { static Logger logger = Logger.getLogger("org.trianacode.gui.hci.TaskGraphHandler"); /** * Creates a unit from a ToolImp object and places it on this MainTriana at the position indicated and sets it to be * the only selected ToolImp. A reference to the toolbox which the tool came from and the position within that * toolbox is also given. */ public static void createTask(final Tool tool, final TaskGraphPanel panel, final int x, final int y) { Thread taskThread = new Thread(new Runnable() { public void run() { TrianaProgressBar progressBar = null; try { Tool newtool; if (tool instanceof TaskGraph) { newtool = ((TaskGraph) tool); } else { RenderingHint hint = getTaskGraphFactoryHint(tool, panel); if (hint == null) { return; } newtool = TaskGraphUtils.cloneTool(tool); ((Tool) newtool).addRenderingHint(hint); } boolean pause = (!(newtool instanceof TaskGraph)) || (TaskGraphUtils.getAllTasksCount((TaskGraph) newtool, true) <= 10); progressBar = new TrianaProgressBar("Loading: " + newtool.getToolName(), pause); TaskComponent[] comps = panel.getTaskComponents(); for (int count = 0; count < comps.length; count++) { comps[count].setSelected(false); } if (newtool instanceof Tool) { TaskLayoutUtils.setPosition((Tool) newtool, new TPoint(x, y), panel.getLayoutDetails()); } Task task = panel.getTaskGraph().createTask(newtool, false); if (GUIEnv.isAutoConnect()) { boolean connect = (panel.getTaskGraph().getControlTask() != task); if (connect) { TPoint pos = TaskLayoutUtils.getPosition(task, panel.getLayoutDetails()); new AutoConnect() .autoConnect(task, (int) pos.getX(), (int) pos.getY(), panel.getTaskGraph()); } } panel.getContainer().requestFocus(); } catch (TaskException except) { new ErrorDialog(Env.getString("taskError") + ": " + tool.getToolName(), except.getMessage()); } finally { if (progressBar != null) { progressBar.disposeProgressBar(); } } } }); taskThread.setName("TrianaTaskCreation"); taskThread.setPriority(Thread.NORM_PRIORITY); taskThread.start(); } /** * Gets the taskgraph factory rendering hint for the specified tool. This method should not be used with taskgraphs * (a RuntimeException will be thrown!). * * @return the taskgraph factory rendering hint, or null if cancelled */ private static RenderingHint getTaskGraphFactoryHint(Tool newtool, TaskGraphPanel panel) throws TaskException { TaskGraphFactory factory = TaskGraphManager.getTaskGraphFactory(panel.getTaskGraph()); Proxy proxy = newtool.getProxy(); if (newtool instanceof TaskGraphFactory) { throw (new RuntimeException("getTaskGraphFactoryHint should not be called with TaskGraph instances")); } if (proxy == null) { throw (new TaskException("No Proxy set in " + newtool.getToolName())); } TaskFactory[] factories = factory.getRegisteredTaskGraphFactories(proxy.getType()); String factoryname; if (factories.length == 0) { throw (new TaskException("No TaskFactory set in for Proxy type: " + proxy.getType())); } if (factories.length == 1) { factoryname = factories[0].getFactoryName(); } else { factoryname = showSelectTaskFactoryDialog(newtool.getToolName(), proxy.getType(), factories); } if (factoryname == null) { return null; } RenderingHintImp hint = new RenderingHintImp(TaskGraphFactory.TASKGRAPH_FACTORY_RENDENRING_HINT, true); hint.setRenderingDetail(TaskGraphFactory.FACTORY_NAME, factoryname); return hint; } /** * Connects two nodes, type checking if required */ public static void connect(TaskGraphPanel panel, Node outnode, Node innode) { try { logger.fine( outnode.getTask().getToolName() + " attempting to connect to " + innode.getTask().getToolName()); panel.getTaskGraph().connect(outnode, innode); } catch (IncompatibleTypeException except) { new ErrorDialog( Env.getString("cableError") + ": " + outnode.getTask().getToolName() + "->" + innode.getTask() .getToolName(), "Error connecting " + outnode.getTask().getToolName() + " to " + innode.getTask().getToolName() + ": Incompatible Types"); } catch (IncompatibleProxyException except) { new ErrorDialog( Env.getString("cableError") + ": " + outnode.getTask().getToolName() + "->" + innode.getTask() .getToolName(), "Error connecting " + outnode.getTask().getToolName() + " to " + innode.getTask().getToolName() + ": Incompatible Proxies (" + outnode.getTopLevelTask().getProxy().getType() + "->" + innode.getTopLevelTask().getProxy().getType() + ")"); } catch (CableException except) { new ErrorDialog( Env.getString("cableError") + ": " + outnode.getTask().getToolName() + "->" + innode.getTask() .getToolName(), except.getMessage()); } } /** * @return the selected factory name or null if cancelled */ private static String showSelectTaskFactoryDialog(String toolname, String proxyname, TaskFactory[] factories) { SelectTaskFactoryDialog dialog = new SelectTaskFactoryDialog(toolname, proxyname, factories); dialog.show(); if (dialog.isAccepted()) { return dialog.getFactoryName(); } else { return null; } } private static class SelectTaskFactoryDialog extends JDialog implements ActionListener, ListSelectionListener { private JList list = new JList(new DefaultListModel()); private JTextArea description = new JTextArea(10, 20); private JButton ok = new JButton(Env.getString("OK")); private JButton cancel = new JButton(Env.getString("Cancel")); private boolean okclicked = false; public SelectTaskFactoryDialog(String toolname, String proxyname, TaskFactory[] factories) { super(GUIEnv.getApplicationFrame(), "Create Task: " + toolname, true); initLayout(proxyname); populateList(factories); } /** * @return true if the dialog was accepted */ public boolean isAccepted() { return okclicked; } /** * @return the name of the taskgraph factory */ public String getFactoryName() { if (list.getSelectedValue() != null) { return ((TaskFactoryItem) list.getSelectedValue()).getTaskFactory().getFactoryName(); } else { return null; } } private void initLayout(String proxyname) { JScrollPane scroll = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); list.setPrototypeCellValue("01234567890123456789012345"); list.setVisibleRowCount(10); list.addListSelectionListener(this); JPanel listpanel = new JPanel(new BorderLayout(3, 0)); listpanel.add(scroll, BorderLayout.CENTER); listpanel.add(description, BorderLayout.EAST); description.setEditable(false); description.setLineWrap(true); description.setWrapStyleWord(true); description.setBackground(getBackground()); JPanel listcont = new JPanel(new BorderLayout(0, 3)); listcont.add(new JLabel(proxyname + " Type:"), BorderLayout.NORTH); listcont.add(listpanel, BorderLayout.CENTER); JPanel buttonpanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); buttonpanel.add(ok); buttonpanel.add(cancel); ok.addActionListener(this); cancel.addActionListener(this); JPanel mainpanel = new JPanel(new BorderLayout(0, 5)); mainpanel.add(listcont, BorderLayout.CENTER); mainpanel.add(buttonpanel, BorderLayout.SOUTH); mainpanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); getContentPane().add(mainpanel); getRootPane().setDefaultButton(ok); setLocationRelativeTo(GUIEnv.getApplicationFrame()); pack(); } private void populateList(TaskFactory[] factories) { DefaultListModel model = (DefaultListModel) list.getModel(); for (int count = 0; count < factories.length; count++) { addSorted(new TaskFactoryItem(factories[count]), model); } if (model.size() > 0) { list.setSelectedIndex(0); } ok.setEnabled(model.size() > 0); } private void addSorted(TaskFactoryItem item, DefaultListModel model) { for (int count = 0; count < model.size(); count++) { if (item.toString().compareTo(model.getElementAt(count).toString()) < 0) { model.add(count, item); return; } } model.addElement(item); } /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent event) { if (event.getSource() == ok) { okclicked = true; setVisible(false); dispose(); } else { setVisible(false); dispose(); } } /** * Called whenever the value of the selection changes. */ public void valueChanged(ListSelectionEvent event) { if (event.getSource() == list) { if (list.getSelectedIndex() != -1) { TaskFactory factory = ((TaskFactoryItem) list.getSelectedValue()).getTaskFactory(); description.setText(factory.getFactoryDescription()); ok.setEnabled(true); } else { description.setText(null); ok.setEnabled(false); } } } } public static class TaskFactoryItem { private TaskFactory factory; public TaskFactoryItem(TaskFactory factory) { this.factory = factory; } public TaskFactory getTaskFactory() { return factory; } public String toString() { return factory.getFactoryName(); } } }