/*
* Copyright (C) 2012 Jason Gedge <http://www.gedge.ca>
*
* This file is part of the OpGraph project.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/**
*
*/
package ca.gedge.opgraph.app.commands.publish;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.AbstractAction;
import ca.gedge.opgraph.ContextualItem;
import ca.gedge.opgraph.InputField;
import ca.gedge.opgraph.OpLink;
import ca.gedge.opgraph.OpGraph;
import ca.gedge.opgraph.OpNode;
import ca.gedge.opgraph.OutputField;
import ca.gedge.opgraph.app.GraphDocument;
import ca.gedge.opgraph.app.GraphEditorModel;
import ca.gedge.opgraph.app.edits.graph.RemoveLinkEdit;
import ca.gedge.opgraph.app.edits.node.PublishFieldEdit;
import ca.gedge.opgraph.extensions.Publishable;
/**
* A command to publish a field in a node.
*/
class PublishFieldCommand extends AbstractAction {
/** The publishable object */
private Publishable publishable;
/** The node with a field to be published */
private OpNode node;
/** The field to publish */
private ContextualItem field;
/**
* Constructs a command that publishes a field of a given node.
*
* @param publishable the publishing extension
* @param node the node with a field to publish
* @param field the field to publish
*/
public PublishFieldCommand(Publishable publishable, OpNode node, ContextualItem field) {
super(field.getKey());
this.publishable = publishable;
this.node = node;
this.field = field;
putValue(SHORT_DESCRIPTION, field.getDescription());
putValue(LONG_DESCRIPTION, field.getDescription());
}
/**
* If currently editing , publish the given field of the selected node.
*
* @param field the field to publish
*/
public void publishFieldOfSelected(ContextualItem field) {
if(publishable != null && field != null && node != null) {
final GraphDocument document = GraphEditorModel.getActiveDocument();
document.getUndoSupport().postEdit(new PublishFieldEdit(document.getGraph(), publishable, node, field.getKey(), field));
document.getCanvas().updateAnchorFillStates(node);
}
}
/**
* If currently editing a macro, unpublish the given field of the selected node.
*
* @param field the field to unpublish
*/
public void unpublishFieldOfSelected(ContextualItem field) {
if(publishable != null && field != null && node != null) {
final GraphDocument document = GraphEditorModel.getActiveDocument();
final OpGraph graphOfMacroParent = document.getBreadcrumb().peekState(1);
final OpNode publishNode = ((publishable instanceof OpNode) ? (OpNode)publishable : null);
// If there is a parent graph, then check to see which links will
// be removed if this field is unpublished
final Collection<OpLink> linksToRemove = new ArrayList<OpLink>();
if(graphOfMacroParent != null) {
// For input fields, check incoming links, otherwise outgoing
if(field instanceof InputField) {
final InputField publishedField = publishable.getPublishedInput(node, (InputField)field);
for(OpLink link : graphOfMacroParent.getIncomingEdges(publishNode)) {
if(link.getDestinationField().equals(publishedField))
linksToRemove.add(link);
}
} else if(field instanceof OutputField) {
final OutputField publishedField = publishable.getPublishedOutput(node, (OutputField)field);
for(OpLink link : graphOfMacroParent.getOutgoingEdges(publishNode)) {
if(link.getSourceField().equals(publishedField))
linksToRemove.add(link);
}
}
}
// Compound edit if there are links to remove
if(linksToRemove.size() == 0) {
document.getUndoSupport().postEdit(new PublishFieldEdit(document.getGraph(), publishable, node, null, field));
} else {
document.getUndoSupport().beginUpdate();
for(OpLink link : linksToRemove)
document.getUndoSupport().postEdit(new RemoveLinkEdit(graphOfMacroParent, link));
document.getUndoSupport().postEdit(new PublishFieldEdit(document.getGraph(), publishable, node, null, field));
document.getUndoSupport().endUpdate();
}
document.getCanvas().updateAnchorFillStates(node);
}
}
//
// Overrides
//
@Override
public void actionPerformed(ActionEvent e) {
boolean isPublishing = true;
if((field instanceof InputField) && publishable.getPublishedInput(node, (InputField)field) != null)
isPublishing = false;
else if((field instanceof OutputField) && publishable.getPublishedOutput(node, (OutputField)field) != null)
isPublishing = false;
if(isPublishing)
publishFieldOfSelected(field);
else
unpublishFieldOfSelected(field);
}
}