/**
* Copyright (C) 2008-2010 Daniel Senff
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package de.danielsenff.imageflow.models.unit;
import java.awt.Point;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import visualap.Node;
import de.danielsenff.imageflow.ImageFlow;
import de.danielsenff.imageflow.ImageFlowView;
import de.danielsenff.imageflow.controller.ExecuteWorkflowListener;
import de.danielsenff.imageflow.controller.GraphController;
import de.danielsenff.imageflow.gui.GraphPanel;
import de.danielsenff.imageflow.models.Displayable;
import de.danielsenff.imageflow.models.NodeListener;
import de.danielsenff.imageflow.models.connection.Input;
import de.danielsenff.imageflow.models.connection.Output;
import de.danielsenff.imageflow.models.datatype.DataType;
import de.danielsenff.imageflow.models.datatype.ImageDataType;
import de.danielsenff.imageflow.models.delegates.NodeDescription;
import de.danielsenff.imageflow.models.delegates.UnitDescription;
import de.danielsenff.imageflow.models.delegates.UnitDescription.Para;
import de.danielsenff.imageflow.models.parameter.Parameter;
import de.danielsenff.imageflow.models.parameter.ParameterFactory;
/**
* Factory for creating {@link UnitElement}s.
* @author danielsenff
*
*/
public class UnitFactory {
/**
* Creates a {@link UnitElement} based on the given Descriptions.
* @param unitDescription
* @param origin
* @return
*/
public static UnitElement createProcessingUnit(
final NodeDescription unitDescription,
final Point origin) {
return createProcessingUnit(unitDescription, origin, null);
}
/**
* Creates a {@link UnitElement} based on the given Descriptions.
* @param nodeDescription
* @param unitDescription
* @param origin
* @param args
* @return
*/
public static UnitElement createProcessingUnit(
final NodeDescription nodeDescription,
final Point origin,
String[] args) {
UnitElement unitElement = null;
if(nodeDescription instanceof UnitDescription) {
UnitDescription unitDescription = (UnitDescription)nodeDescription;
unitElement = manufactureUnitElement(origin, args, unitDescription);
}
return unitElement;
}
private static UnitElement manufactureUnitElement(final Point origin,
String[] args, UnitDescription unitDescription) {
UnitElement unitElement;
String unitName = unitDescription.getUnitName();
String imageJSyntax = unitDescription.imageJSyntax;
// usual case, we deal with a UnitElement
// if we have a SourceUnit, we have to take the according class
if(unitName.equals("Import from Window")) {
unitElement = new ImportUnitElement(new Point(origin), unitName, imageJSyntax);
} else if(unitName.equals("Image Source")) {
unitElement = new SourceUnitElement(new Point(origin), unitName, imageJSyntax);
} else if(unitName.equals("Background")) {
unitElement = new BackgroundUnitElement(new Point(origin), unitName, imageJSyntax);
} else
unitElement = new UnitElement(new Point(origin), unitName, imageJSyntax);
unitElement.setHelpString(unitDescription.helpString);
unitElement.setColor(unitDescription.getColor());
// add an icon if there is one mentioned and found
File iconFile = new File(unitDescription.pathToIcon);
if(iconFile.exists()) {
try {
unitElement.setIcon(ImageIO.read(iconFile));
} catch (IOException e) {
e.printStackTrace();
}
}
if(unitDescription.icon != null) {
unitElement.setIcon(unitDescription.icon);
unitElement.setIconURL(unitDescription.iconURL);
}
if(unitDescription.componentSize != null)
unitElement.setCompontentSize(unitDescription.componentSize);
// setup of the Parameters
if(unitDescription.hasParameters())
addParameters(unitDescription, unitElement);
// setup of the inputs
if(unitDescription.hasInputs())
addInputs(unitDescription, unitElement);
// setup of the output(s)
if(unitDescription.hasOutputs())
addOutputs(unitDescription,unitElement);
unitElement.setDisplay(unitDescription.isDisplayUnit);
// setup the PinTolerance
setPinTolerance(unitElement);
//special cases
if(unitElement instanceof BackgroundUnitElement) {
String imageType = (String) unitElement.getParameter(2).getValue();
((BackgroundUnitElement)unitElement).setOutputImageType(imageType);
} else if(unitElement instanceof SourceUnitElement) {
SourceUnitElement sourceUnit = (SourceUnitElement)unitElement;
if(args != null && args[0] != null) {
((SourceUnitElement)unitElement).setFilePath(args[0]);
}
if(!sourceUnit.hasFilePath()) {
sourceUnit.showOpenFileChooser();
}
sourceUnit.updateImageType();
}
return unitElement;
}
/**
* sets pinTolerance accordings to number of inputs and outputs
* @param unitElement current {@link UnitElement}, which contains the number of inputs and outputs
*/
private static void setPinTolerance(UnitElement unitElement) {
// get maxiumum of pins and adjust PIN_TOLERANCE to number of pins
int maxPins = Math.max(unitElement.inputs.size(), unitElement.outputs.size());
if (maxPins > 2) {
int pinTolerance = (100 / (2*maxPins)) - 2;
unitElement.setPinTolerance(pinTolerance);
}
}
private static void addParameters(final UnitDescription unitDescription,
UnitElement unitElement) {
int numParas = unitDescription.numParas;
for (int i = 1; i <= numParas; i++) {
Para para = unitDescription.para[i];
Parameter parameter = ParameterFactory.createParameter(para.name,
para.dataTypeString,
para.value,
para.helpString,
para.trueString,
para.options);
parameter.setHidden(para.hidden);
parameter.setReadOnly(para.readOnly);
unitElement.addParameter(parameter);
}
}
private static void addOutputs(final UnitDescription unitDescription,
UnitElement unitElement) {
int numOutputs = unitDescription.numOutputs;
for (int i = 1; i <= numOutputs; i++) {
UnitDescription.Output outputDescription = unitDescription.output[i];
Output output = createOutput(outputDescription, unitElement, i);
unitElement.addOutput(output);
if(unitElement instanceof Displayable) {
boolean doDisplay = outputDescription.doDisplay;
unitElement.setDisplay(doDisplay);
}
}
}
/**
* Create a {@link IOutput} for the given {@link UnitElement}.
* @param outputDescription
* @param unitElement
* @param i
* @return
*/
public static Output createOutput(UnitDescription.Output outputDescription,
UnitElement unitElement, int i) {
String name = outputDescription.name;
String shortName = outputDescription.shortName;
DataType dataType = outputDescription.dataType;
if(unitElement instanceof ImageSourceUnit
&& dataType instanceof ImageDataType) {
int imageType = ((ImageSourceUnit)unitElement).getImageType();
((ImageDataType)dataType).setImageBitDepth(imageType);
}
// imagetype -1 means output will be the same type as the input
Output output = new Output(dataType, unitElement, i);
output.setupOutput(name, shortName);
return output;
}
private static void addInputs(final UnitDescription unitDescription,
UnitElement unitElement) {
int numInputs = unitDescription.numInputs;
for (int i = 1; i <= numInputs; i++) {
Input input = createInput(unitDescription.input[i], unitElement, i);
unitElement.addInput(input);
}
}
/**
* Create a {@link Input} for the given {@link UnitElement}.
* @param inputDescription
* @param unitElement
* @param i
* @return
*/
public static Input createInput(final UnitDescription.Input inputDescription,
final UnitElement unitElement, final int i) {
String name = inputDescription.name;
String shortName = inputDescription.shortName;
boolean needToCopyInput = inputDescription.needToCopyInput;
boolean required = inputDescription.required;
DataType dataType = inputDescription.dataType;
if(dataType instanceof ImageDataType) {
((ImageDataType)dataType).setImageBitDepth(inputDescription.imageType);
}
Input input = new Input(dataType, unitElement, i, required);
input.setupInput(name, shortName, needToCopyInput);
return input;
}
/**
* Creates a new {@link CommentNode}.
* @param string
* @param point
* @return
*/
public static CommentNode createComment(final String string, final Point point) {
CommentNode commentNode = new CommentNode(point, string);
return commentNode;
}
/**
* Node is registered to the GraphPanel
* @param node
*/
public static void registerModelListener(Node node) {
// if we ever go multi-document, this will have to be addressed here
final ImageFlowView ifView = ((ImageFlowView)ImageFlow.getApplication().getMainView());
final GraphPanel graphPanel = ifView.getGraphPanel();
final GraphController graphController = ifView.getGraphController();
if(node instanceof CommentNode) {
((CommentNode)node).addModelListener(new NodeListener(graphPanel, ifView));
} else if (node instanceof UnitElement) {
UnitElement unit = (UnitElement)node;
unit.addModelListener(new NodeListener(graphPanel, ifView));
}
}
}