/**
* 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.connection;
import java.awt.Point;
import visualap.Node;
import de.danielsenff.imageflow.models.Lockable;
import de.danielsenff.imageflow.models.datatype.DataType;
import de.danielsenff.imageflow.models.datatype.DataTypeFactory;
import de.danielsenff.imageflow.models.datatype.ImageDataType;
import de.danielsenff.imageflow.models.unit.AbstractUnit;
import de.danielsenff.imageflow.models.unit.UnitElement;
/**
* Input Pins
* @author danielsenff
*
*/
public class Input extends Pin implements Lockable {
/**
* the id of the image connected to this input
*/
protected String inputID;
/**
* the title of the image connected this input
*/
protected String inputTitle;
/**
* flag indicating if the image at this input needs to be duplicated
*/
protected boolean needToCopyInput;
/**
* flag to set inputs not required. Default is required.
*/
protected boolean requiredInput = true;
/**
* write protection
*/
protected boolean locked = false;
/**
* Connection
*/
protected Connection connection;
/**
* @param displayName
* @param shortDisplayName
* @param dataType
* @param parentNode
* @param fromUnit
* @param inputNumber
* @param required
* @param needToCopyInput
*/
public Input(
final String displayName,
final String shortDisplayName,
final DataType dataType,
final UnitElement parentNode,
int inputNumber,
boolean required,
boolean needToCopyInput) {
this(dataType, parentNode, inputNumber, required);
this.setupInput(displayName, shortDisplayName, needToCopyInput);
}
/**
* @param dataType
* @param parentNode
* @param inputNumber
*/
public Input(final DataType dataType,
final UnitElement parentNode,
int inputNumber) {
this(dataType, parentNode, inputNumber, true);
}
/**
* @param dataType
* @param nodeParent
* @param inputNumber
* @param requiredInput
*/
public Input(DataType dataType,
final UnitElement nodeParent,
int inputNumber,
boolean requiredInput) {
super(dataType, inputNumber, nodeParent);
setRequiredInput(requiredInput);
if(getDataType() instanceof ImageDataType) {
((ImageDataType)getDataType()).setParentUnitElement((UnitElement) getParent());
((ImageDataType)getDataType()).setParentPin(this);
}
}
/**
* Sets the connection between this input and an output.
* @param fromUnitNumber
* @param fromOutputNumber
*/
private void generateID(final int fromUnitNumber, final int fromOutputNumber) {
this.inputTitle = "Unit_" + fromUnitNumber + "_Output_" + fromOutputNumber;
this.inputID = "ID_Unit_" + fromUnitNumber + "_Output_" + fromOutputNumber;
}
/**
* Set a new {@link Connection} for this Input.
* The input may not be locked to be successful.
* @param connection
*/
public void setConnection(final Connection connection) {
if(!isLocked()) {
this.connection = connection;
generateID(connection.getOutput().getParent().getNodeID(),
connection.getOutput().getIndex());
}
}
/**
* Setup the basic data.
* @param displayName Name of the Pin
* @param shortDisplayName Abbreviation of the Pin
* @param inputImageBitDepth Flag which defines, what image-formats can be taken.
* @param needToCopyInput
*/
public void setupInput(final String displayName,
final String shortDisplayName,
final int inputImageBitDepth,
final boolean needToCopyInput) {
this.displayName = displayName;
this.shortDisplayName = shortDisplayName;
this.dataType = DataTypeFactory.createImage(inputImageBitDepth);
this.setNeedToCopyInput(needToCopyInput);
}
/**
* @param displayName
* @param shortDisplayName
* @param needToCopyInput
*/
public void setupInput(final String displayName,
final String shortDisplayName,
final boolean needToCopyInput) {
this.displayName = displayName;
this.shortDisplayName = shortDisplayName;
this.setNeedToCopyInput(needToCopyInput);
}
/**
* Get the ImageTitle.
* This is the title of the image later used in the Macro
* @return
*/
public String getImageTitle() {
return inputTitle;
}
/**
* @param needToCopyInput
*/
public void setNeedToCopyInput(final boolean needToCopyInput) {
this.needToCopyInput = needToCopyInput;
}
/**
* Returns true, if this Input requires it's input to be copied.
* @return
*/
public boolean isNeedToCopyInput() {
return needToCopyInput;
}
/**
* @return the imageID
*/
public String getImageID() {
return this.inputID;
}
/**
* Returns whether or not this Input is required for running the attached {@link UnitElement}
* or if it is optional.
* @return the requiredInput
*/
public boolean isRequired() {
return this.requiredInput;
}
/**
* Set if this Input is required for this {@link UnitElement}.
* @param requiredInput the requiredInput to set
*/
public void setRequiredInput(final boolean requiredInput) {
this.requiredInput = requiredInput;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString()+" DataType: " + getDataType();
}
/* (non-Javadoc)
* @see graph.Pin#getLocation()
*/
@Override
public Point getOrigin() {
int height = parent.getDimension().height;
int nump = ((UnitElement) parent).getInputsCount();
int y = (index*height / nump ) - (height/(2*nump)) + parent.getOrigin().y;
return new Point(parent.getOrigin().x, y);
}
/* (non-Javadoc)
* @see graph.Pin#getParent()
*/
@Override
public UnitElement getParent() {
return (UnitElement)super.getParent();
}
/**
* Return the unit from which this Input is connected.
* @return the fromUnit
*/
public UnitElement getFromUnit() {
return (UnitElement) this.connection.getFromUnit();
}
/**
* @return
*/
public int getFromUnitNumber() {
return ((AbstractUnit) this.connection.getFromUnit()).getNodeID();
}
/**
* Returns the current {@link Connection} or null, if this pin is not connected.
* @return
*/
public Connection getConnection() {
return this.connection;
}
/**
* Returns whether or not this Input is connected.
* @return
*/
public boolean isConnected() {
return connection != null;
}
/**
* Checks if this Input is connected with the given {@link Output}
* @param output
* @return
*/
public boolean isConnectedWith(Pin output) {
if(output instanceof Output && isConnected()) {
return this.connection.getOutput().equals(output);
}
return false;
}
/**
* Resets the this Input, so that it is unconnected.
*/
public void disconnectAll() {
if(!isLocked()) {
generateID(0, 0); // reset connection
this.connection = null;
}
}
/**
* The {@link Output} which is connected with this Input.
* @return
*/
public Output getFromOutput() {
// return from;
return connection.getOutput();
}
/**
* Returns true if the graph branch connected to this inputs parent's output contains the unit.
* @param goal
* @return
*/
public boolean isConnectedInOutputBranch(Node goal) {
// self reference
if(goal.equals(parent))
// can only check inputs, which are connected
// return traverseInput(this, goal);
return false;
else
return traverseOutput((UnitElement) this.parent, goal);
}
/**
* Returns true if the graph branch connected to this input contains the unit.
* @param goal
* @return
*/
public boolean isConnectedInInputBranch(Node goal) {
// self reference
if(goal.equals(parent))
// can only check inputs, which are connected
// return traverseInput(this, goal);
return false;
else
return traverseInput(this, goal);
// return traverseOutput2(getConnection().getFromUnit(), goal);
}
/**
*
* @param start
* @param goal
* @return
*/
public static boolean traverseInput(final Input start, final Node goal) {
if(start.getParent().equals(goal)) {
return true;
} else if(start.isConnected()) {
for (Input input : start.getFromUnit().getInputs()) {
return traverseInput(input, goal);
}
}
return false;
}
private static boolean traverseOutput(UnitElement parent, Node goal) {
if(parent.equals(goal)) {
return true;
} else if (parent.hasInputsConnected()) {
for (Output output : parent.getOutputs()) {
if(output.isConnected()) {
for (Connection connection : output.getConnections()) {
if(traverseOutput((UnitElement)connection.getToUnit(), goal))
return true;
}
}
}
}
return false;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean isLocked) {
this.locked = isLocked;
}
}