/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2012-2013, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.etl; import java.awt.Point; import java.awt.event.ActionEvent; import java.lang.reflect.InvocationTargetException; import javax.swing.AbstractAction; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; import org.apache.sis.util.ArgumentChecks; import org.geotoolkit.gui.swing.resource.MessageBundle; import org.geotoolkit.processing.chain.model.Constant; import org.geotoolkit.processing.chain.model.DataLink; import org.geotoolkit.processing.chain.model.Element; import org.geotoolkit.processing.chain.model.ElementCondition; import org.geotoolkit.processing.chain.model.ElementManual; import org.geotoolkit.processing.chain.model.ElementProcess; import org.geotoolkit.processing.chain.model.FlowLink; import org.geotoolkit.processing.chain.model.Parameter; import org.geotoolkit.processing.chain.model.Positionable; import org.geotoolkit.processing.chain.model.event.EventChain; import org.geotoolkit.util.collection.CollectionChangeEvent; import org.netbeans.api.visual.action.ActionFactory; import org.netbeans.api.visual.action.PopupMenuProvider; import org.netbeans.api.visual.widget.ConnectionWidget; import org.netbeans.api.visual.widget.Widget; import org.openide.util.Exceptions; /** * Advanced scene for a chain. * Display all. (ChainElements, parameters, constants, links) * * @author Johann Sorel (Geomatys) * @author Quentin Boileau (Geomatys) */ public class ChainSceneAdvanced extends ChainSceneIntermediate { public ChainSceneAdvanced(final EventChain chain, final boolean editable) { super(chain, editable); if (editable) { getActions().addAction(ActionFactory.createPopupMenuAction(new ProcessPopup())); } } @Override protected void setChain(final EventChain chain) { getMapping().clear(); if(this.chain != null){ this.chain.removeListener(this); } this.chain = chain; if(this.chain != null){ this.chain.addListener(this); } final WChainParametersFull inParameters = new WChainParametersFull(this, MessageBundle.format("inputs"),Integer.MIN_VALUE, editable); final WChainParametersFull outParameters = new WChainParametersFull(this, MessageBundle.format("outputs"), Integer.MAX_VALUE, editable); getMapping().put(IN, inParameters); getMapping().put(OUT, outParameters); getMapping().put(ElementProcess.BEGIN, inParameters.getExecutionWidget()); getMapping().put(ElementProcess.END, outParameters.getExecutionWidget()); addWigetToMainLayer(inParameters); addWigetToMainLayer(outParameters); for(final Parameter param : chain.getInputs()){ createInParameter(param); } for(final Parameter param : chain.getOutputs()){ createOutParameter(param); } for(final Element ele : chain.getElements()){ if(ele instanceof ElementProcess){ createElementProcess((ElementProcess)ele); }else if(ele instanceof ElementManual){ createElementManual((ElementManual)ele); }else if(ele instanceof ElementCondition){ createElementCondition((ElementCondition)ele); } } for(final Constant cst : chain.getConstants()){ createConstant(cst); } for(final DataLink link : chain.getDataLinks()){ createDataLink(link); } for(final FlowLink execlink : chain.getFlowLinks()){ createFlowLink(execlink); } if(SwingUtilities.isEventDispatchThread()){ replaceAll(); }else{ try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { replaceAll(); } }); } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (InvocationTargetException ex) { Exceptions.printStackTrace(ex); } } getScene().validate(); repaint(); } private void replaceAll(){ int minX=0; int maxX=0; for(Widget widget : getMapping().values()){ if(widget instanceof WPositionable){ final WPositionable element = (WPositionable) widget; final Positionable positionable = element.getObject(); widget.setPreferredLocation(new Point(positionable.getX(), positionable.getY())); if(positionable.getX()< minX) {minX = positionable.getX();} if(positionable.getX()> maxX) {maxX = positionable.getX();} } } final Widget win = getMapping().get(IN); final Widget wout = getMapping().get(OUT); win.setPreferredLocation(new Point(minX-150, 0)); wout.setPreferredLocation(new Point(maxX+150, 0)); //refresh validate(); } @Override public void dispose() { this.chain.removeListener(this); } @Override protected void createConstant(final Constant cst){ final WConstant widget = new WConstant(this, cst, editable); widget.setPreferredLocation(new Point(cst.getX(), cst.getY())); getMapping().put(cst, widget); addWigetToMainLayer(widget); validate(); } @Override protected void removeConstant(final Constant cst){ final Widget widget = getMapping().remove(cst); ArgumentChecks.ensureNonNull("constant widget", widget); getMainLayer().removeChild(widget); getScene().validate(); } @Override protected void createDataLink(final DataLink link) { final EventChain sequence = getChain(); final Object source = link.getSource(sequence); final Object target = link.getTarget(sequence); Widget w_source = getMapping().get(source); Widget w_target = getMapping().get(target); if (w_source instanceof WElementProcess) { final WElementProcess pw = (WElementProcess) w_source; w_source = pw.getOutputWidget(link.getSourceCode()); } else if (w_source instanceof WConstant) { final WConstant pw = (WConstant) w_source; w_source = pw.getOffering(); } if (w_target instanceof WElementProcess) { final WElementProcess pw = (WElementProcess) w_target; w_target = pw.getInputWidget(link.getTargetCode()); } else if (w_target instanceof WConstant) { final WConstant pw = (WConstant) w_target; w_target = pw.getOffering(); } else if (w_target instanceof WElementCondition) { final WElementCondition pw = (WElementCondition) w_target; w_target = pw.getInputWidget(link.getTargetCode()); } ArgumentChecks.ensureNonNull("link source", w_source); ArgumentChecks.ensureNonNull("link target", w_target); final ConnectionWidget connection = new WDataLink(this, link); connection.setSourceAnchor(new SideAnchor(w_source, false)); connection.setTargetAnchor(new SideAnchor(w_target, true)); getMapping().put(link, connection); getConnectionLayer().addChild(connection); getScene().validate(); } @Override protected void removeDataLink(final DataLink link) { final Widget widget = getMapping().remove(link); ArgumentChecks.ensureNonNull("link widget", widget); getConnectionLayer().removeChild(widget); getScene().validate(); } //////////////////////////////////////////////////////////////////////////// // chain events ///////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @Override public void constantChange(CollectionChangeEvent event) { if(event.getType() == CollectionChangeEvent.ITEM_ADDED){ for(Object obj : event.getItems()){ createConstant((Constant)obj); } }else if(event.getType() == CollectionChangeEvent.ITEM_REMOVED){ for(Object obj : event.getItems()){ removeConstant((Constant)obj); } } } private class ProcessPopup implements PopupMenuProvider{ @Override public JPopupMenu getPopupMenu(final Widget widget, final Point point) { final JPopupMenu menu = new JPopupMenu(); menu.add(new JMenuItem( new AbstractAction("New Constant") { @Override public void actionPerformed(ActionEvent e) { final Constant cst = new Constant(getChain().getNextId(), Integer.class, "", point.x, point.y); getChain().getConstants().add(cst); } } )); return menu; } } }