/**
* 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.util.ArrayList;
import java.util.Vector;
import javax.swing.JOptionPane;
import de.danielsenff.imageflow.ImageFlow;
import de.danielsenff.imageflow.models.Model;
import de.danielsenff.imageflow.models.ModelListener;
import de.danielsenff.imageflow.models.unit.UnitElement;
/**
* List that holds all {@link Connection}s.
* @author Daniel Senff
*
*/
public class ConnectionList extends Vector<Connection> implements Model, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
private final ArrayList<ModelListener> listeners;
/**
* Constructs a ConnectionList
*/
public ConnectionList() {
this.listeners = new ArrayList<ModelListener>();
}
/**
* Sees, if a connection between the given Pins exists.
* @param from
* @param to
* @return
*/
public boolean containsConnection(final Pin from, final Pin to) {
for (final Connection connection : this) {
if (connection.getInput().equals(from)
&& connection.getOutput().equals(to))
return true;
else if (connection.getInput().equals(to)
&& connection.getOutput().equals(from))
return true;
}
return false;
}
/*
* add
*/
/**
* Creates a new Connection and adds it to the ConnectionList
* @param from
* @param fromOutput
* @param to
* @param toInput
* @return
*/
public boolean add(final UnitElement from,
final int fromOutput,
final UnitElement to,
final int toInput) {
return this.add(new Connection(from, fromOutput, to, toInput));
}
/**
* Creates a new Connection between two pins and adds it to the list.
* @param from
* @param to
* @return
*/
public boolean add(final Pin from, final Pin to) {
// check if both pins are on the same node
if(from.getParent().equals(to.getParent())) return false;
// check if connection is between input and output, not 2 outputs or two inputs
if((from instanceof Input && to instanceof Input)
|| (from instanceof Output && to instanceof Output)) {
return false;
}
return this.add(new Connection(from, to));
}
/**
* adds the connection, if the pins are already connected, the old connection is deleted
* if inputs are locked, the connection will not be added.
* @param connection
* @return
*/
@Override
public boolean add(final Connection connection) {
final Input input = connection.getInput();
final Output output = connection.getOutput();
if(input.isLocked() || output.isLocked()) {
return false;
}
// check if connection produces loop
if(input.isConnectedInOutputBranch(output.getParent())) {
System.out.println("Connection disallowed: Loop detected");
JOptionPane.showMessageDialog(ImageFlow.getApplication().getMainFrame(),
"The connection you tried to establish is not allowed " + '\n' +
"and will be dismissed because it would cause loops.",
"Connection refused",
JOptionPane.WARNING_MESSAGE);
return false;
}
// check the bit depth
if(!connection.isCompatible()) {
final String dataTypeI = connection.getInput().getDataType().toString();
final String dataTypeO = connection.getOutput().getDataType().toString();
System.out.println("Connection disallowed: " +
"Incompatible dataTypes " + dataTypeO + " to " + dataTypeI);
// return false;
}
//check if input already got a connection, if yes, delete that one
for (int i = 0; i < this.size(); i++) {
final Connection conn = (Connection) this.get(i);
// edges is connected with this input?
if(conn.isConnected(input)) {
remove(conn);
}
}
if(!output.isConnectedWith(input))
connection.connect();
final boolean add = super.add(connection);
notifyModelListeners();
return add;
}
/**
* Adds the connection to the list without any security checking.
* @param connection
* @return
*/
public boolean addUnchecked(final Connection connection) {
connection.connect();
final boolean add = super.add(connection);
notifyModelListeners();
return add;
}
/*
* Remove
*/
@Override
public Connection remove(final int index) {
final Connection connection = (Connection) super.remove(index);
((Input)connection.to).disconnectAll();
((Output)connection.from).disconnectAll();
notifyModelListeners();
return connection;
}
@Override
public boolean remove(final Object o) {
final Connection connection = (Connection) o;
((Input)connection.to).disconnectAll();
((Output)connection.from).disconnectFrom(connection.to);
notifyModelListeners();
return super.remove(o);
}
/*
* ModelListener
*/
/*
* (non-Javadoc)
* @see de.danielsenff.imageflow.models.Model#addModelListener(de.danielsenff.imageflow.models.ModelListener)
*/
public void addModelListener(final ModelListener listener) {
if (! this.listeners.contains(listener)) {
this.listeners.add(listener);
notifyModelListener(listener);
}
}
public void notifyModelListener(final ModelListener listener) {
listener.modelChanged(this);
}
public void notifyModelListeners() {
for (final ModelListener listener : this.listeners) {
notifyModelListener(listener);
}
}
public void removeModelListener(final ModelListener listener) {
this.listeners.remove(listener);
}
@Override
public ConnectionList clone() {
final ConnectionList cloneList = new ConnectionList();
for (final Connection connection : this) {
final Connection clonConn = new Connection(connection.getOutput(), connection.getInput());
cloneList.add(clonConn);
}
return cloneList;
}
/**
* Finds a connection based on the given id
* @param id
* @return
*/
public Connection getConnectionByID(final int id) {
for (final Connection connection : this) {
if(connection.id == id)
return connection;
}
return null;
}
}