/*
* Copyright (C) 2011 Andrea Schweer
*
* This file is part of the Digital Parrot.
*
* The Digital Parrot is free software; you can redistribute it and/or modify
* it under the terms of the Eclipse Public License as published by the Eclipse
* Foundation or its Agreement Steward, either version 1.0 of the License, or
* (at your option) any later version.
*
* The Digital Parrot 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 Eclipse Public License for
* more details.
*
* You should have received a copy of the Eclipse Public License along with the
* Digital Parrot. If not, see http://www.eclipse.org/legal/epl-v10.html.
*
*/
package net.schweerelos.parrot.ui;
import java.awt.Dimension;
import java.awt.geom.Point2D;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.schweerelos.parrot.model.NodeWrapper;
import org.apache.commons.collections15.Factory;
import org.apache.commons.collections15.map.LazyMap;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.visualization.layout.ObservableCachingLayout;
import edu.uci.ics.jung.visualization.layout.PersistentLayout;
import edu.uci.ics.jung.visualization.util.Caching;
import edu.uci.ics.jung.visualization.util.ChangeEventSupport;
/**
* Implementation of PersistentLayout for NodeWrappers -- which means it deals with the value of each vertex rather than the vertex itself.
* Defers to another layout until 'restore' is called,
* then it uses the saved vertex locations.
*
* @author Andrea Schweer <schweer@cs.waikato.ac.nz>
*
* @see edu.uci.ics.jung.visualization.layout.PersistentLayoutImpl<V, E>
*/
public class NodeWrapperPersistentLayoutImpl extends ObservableCachingLayout<NodeWrapper, NodeWrapper>
implements PersistentLayout<NodeWrapper, NodeWrapper>, ChangeEventSupport, Caching {
/** Maps NodeWrapper URIs to the location of their respective vertex. */
protected Map<String, Point> uriToNodeLocation;
/** Holds all vertices whose position has been locked. */
protected Set<NodeWrapper> lockedVertices;
/** Whether the graph is locked (stops the VisualizationViewer rendering thread). */
protected boolean locked;
public NodeWrapperPersistentLayoutImpl(
Layout<NodeWrapper, NodeWrapper> delegate) {
super(delegate);
uriToNodeLocation = LazyMap.decorate(new HashMap<String, Point>(), new RandomPointFactory(getSize()));
lockedVertices = new HashSet<NodeWrapper>();
locked = false;
}
@Override
public synchronized void persist(String fileName) throws IOException {
uriToNodeLocation.clear();
for(NodeWrapper vertex : getGraph().getVertices()) {
Point p = new Point(transform(vertex));
uriToNodeLocation.put(vertex.getOntResource().getURI(), p);
}
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
fileName));
oos.writeObject(uriToNodeLocation);
oos.close();
}
@SuppressWarnings("unchecked")
@Override
public synchronized void restore(String fileName) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
fileName));
uriToNodeLocation = (Map<String, Point>) ois.readObject();
ois.close();
initializeLocations();
locked = true;
fireStateChanged();
}
protected void initializeLocations() {
for(NodeWrapper vertex : getGraph().getVertices()) {
Point2D coord = delegate.transform(vertex);
if (!lockedVertices.contains(vertex))
initializeLocation(vertex, coord, getSize());
}
}
protected void initializeLocation(NodeWrapper vertex, Point2D coord,
Dimension size) {
String uri = vertex.getOntResource().getURI();
if (uri != null && !uri.isEmpty() && uriToNodeLocation.containsKey(uri)) {
Point point = uriToNodeLocation.get(uri);
coord.setLocation(point.x, point.y);
} else {
// TODO
}
}
@Override
public void lock(boolean locked) {
this.locked = locked;
}
/*
* (non-Javadoc)
*
* @see edu.uci.ics.jung.visualization.Layout#incrementsAreDone()
*/
@Override
public boolean done() {
return locked;
}
/*
* (non-Javadoc)
*
* @see edu.uci.ics.jung.visualization.Layout#lockVertex(edu.uci.ics.jung.graph.Vertex)
*/
@Override
public void lock(NodeWrapper vertex, boolean state) {
lockedVertices.add(vertex);
delegate.lock(vertex, state);
}
@SuppressWarnings("serial")
public static class RandomPointFactory implements Factory<Point>, Serializable {
Dimension d;
public RandomPointFactory(Dimension d) {
this.d = d;
}
public edu.uci.ics.jung.visualization.layout.PersistentLayout.Point create() {
double x = Math.random() * d.width;
double y = Math.random() * d.height;
return new Point(x,y);
}
}
}