blob: f1451ceba9283218f4ae77e4117261d97fa71247 [file] [log] [blame]
package org.eclipse.stem.ui.grapheditor;
import java.awt.Polygon;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.stem.adapters.file.File;
import org.eclipse.stem.core.Utility;
import org.eclipse.stem.core.common.Identifiable;
import org.eclipse.stem.core.graph.Edge;
import org.eclipse.stem.core.graph.EdgeLabel;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.definitions.adapters.spatial.SpatialProviderAdapter;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.SegmentBuilder;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLongProvider;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLongProviderAdapterFactory;
import org.eclipse.stem.definitions.adapters.spatial.geo.PlatformLatLongDataProvider;
import org.eclipse.stem.definitions.edges.MigrationEdgeLabel;
import org.eclipse.stem.definitions.labels.AreaLabel;
import org.eclipse.stem.definitions.labels.CommonBorderRelationshipLabel;
import org.eclipse.stem.definitions.labels.LabelsFactory;
import org.eclipse.stem.definitions.labels.PopulationLabel;
import org.eclipse.stem.definitions.labels.RelativePhysicalRelationshipLabel;
import org.eclipse.stem.definitions.labels.impl.AreaLabelImpl;
import org.eclipse.stem.definitions.labels.impl.PopulationLabelImpl;
import org.eclipse.stem.ui.Activator;
import org.eclipse.stem.ui.grapheditor.handlers.SaveInProjectDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphConnection;
import org.eclipse.zest.core.widgets.GraphItem;
import org.eclipse.zest.core.widgets.GraphNode;
public class GraphCanvas {
//set some global variables that are necessary to be accessed from several methods
org.eclipse.stem.core.graph.Graph stemGraph;
DecimalFormat df = new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.US));
//TODO when java 1.6 is set
//df.setRoundingMode(RoundingMode.HALF_UP);
double zoomFactor = 1.0;
double ZOOMING_FACTOR = 1.1;
double UNZOOMING_FACTOR = 1 / ZOOMING_FACTOR;
double offsetX=0;
double offsetY=0;
double scaleFactor=0;
int lastOffsetX=0;
int lastOffsetY=0;
final int MARGIN = 5;
boolean cancel=false;
boolean leftMouseButtonPressed=false;
double xTranslation = 0.0, yTranslation = 0.0;
final static int UNDEFINED = GraphDefs.UNDEFINED ,
MIGRATION_EDGE = GraphDefs.MIGRATION_EDGE,
CONTAINMENT_EDGE = GraphDefs.CONTAINMENT_EDGE,
COMMON_BORDER_EDGE = GraphDefs.COMMON_BORDER_EDGE,
AREA_LABEL = GraphDefs.AREA_LABEL,
POPULATION_LABEL = GraphDefs.POPULATION_LABEL,
NODE_TITLE= GraphDefs.NODE_TITLE,
NODE_URI= GraphDefs.NODE_URI,
NODE_LABEL= GraphDefs.NODE_LABEL,
EDGE_TITLE= GraphDefs.EDGE_TITLE,
EDGE_AURI= GraphDefs.EDGE_AURI,
EDGE_BURI= GraphDefs.EDGE_BURI,
EDGE_LABEL_VALUE= GraphDefs.EDGE_LABEL_VALUE;
//TODO : handle coordinates * R > integer range
//Rescale for Data
static double RFD = GraphDefs.R;
double maxLT=Double.NEGATIVE_INFINITY,
maxLG=Double.NEGATIVE_INFINITY,
minLT=Double.MAX_VALUE,
minLG=Double.MAX_VALUE;
Rectangle zestGraphBounds = null;
Rectangle graphBounds = null;
List<DisplayPolygon> polygonsToDraw = new ArrayList<DisplayPolygon>();
Map<String,GraphNode> GraphNodes = new HashMap<String, GraphNode>();
Map<String,GraphConnection> GraphConnections = new HashMap<String, GraphConnection>();
List<double[]> centers = new ArrayList<double[]>();
Map<String,Set<DisplayPolygon>> nodeID2Poly = new HashMap<String, Set<DisplayPolygon>>();
Map<URI,List<org.eclipse.stem.core.graph.NodeLabel>> nodeURI2Label = new HashMap<URI,List<org.eclipse.stem.core.graph.NodeLabel>>();
List<org.eclipse.stem.core.graph.Graph> graphList;
public void display(List<org.eclipse.stem.core.graph.Graph> graphList, File file, IProject project)
{
display(graphList, file, project, null );
}
public void display(List<org.eclipse.stem.core.graph.Graph> graphList, File file, IProject project, Model model)
{
this.graphList = graphList;
//reload?
/*final ResourceSet resourceSet = new ResourceSetImpl();
Resource resource;
for (org.eclipse.stem.core.graph.Graph graph : graphList)
{
resource = resourceSet.createResource(graph.getURI());
resource.setModified(true);
Identifiable id = Utility.getIdentifiable(resource.getURI());
if (id instanceof Graph) graph = (org.eclipse.stem.core.graph.Graph) id;
}*/
org.eclipse.stem.core.graph.Graph canonicalGraph = null;
for (org.eclipse.stem.core.graph.Graph graph : graphList)
{
if (canonicalGraph == null)
{
canonicalGraph = (org.eclipse.stem.core.graph.Graph) EcoreUtil.copy(graph);
}
else
{
canonicalGraph.addGraph((org.eclipse.stem.core.graph.Graph) EcoreUtil.copy(graph), null);
}
}
this.stemGraph = canonicalGraph;
final Display display = Activator.getDefault().getWorkbench().getDisplay();
final Shell shell = new Shell(display);
shell.setText("STEM Graph Editor");
String topCompositeText = "";
if (graphList.size() > 1)
{
topCompositeText = "Canonical Graph of ";
if (project != null) topCompositeText += "\"" + project.getName() + "\"";
if (model != null) topCompositeText += "\"" + model.getDublinCore().getTitle()+"\"";
if (topCompositeText.equals("")) topCompositeText = stemGraph.getURI().lastSegment();
}
else topCompositeText = stemGraph.getURI().lastSegment();
final Composite topComposite = createTopComposite(shell, topCompositeText);
final Graph zestGraph = new Graph(shell, SWT.NONE);
final Composite dataComposite = createDataComposite(shell, zestGraph);
final Composite bottomComposite = createBottomComposite(shell, zestGraph, file, project);
final FormLayout layout = new FormLayout();
layout.marginHeight = MARGIN;
layout.marginWidth = MARGIN;
shell.setLayout(layout);
final FormData topCompositeFormData = new FormData();
topComposite.setLayoutData(topCompositeFormData);
topCompositeFormData.top = new FormAttachment(0, 0);
topCompositeFormData.left = new FormAttachment(0, 0);
topCompositeFormData.right = new FormAttachment(100, 0);
//graph composite
final FormData graphRendererFormData = new FormData(1000,600);
zestGraph.setLayoutData(graphRendererFormData);
graphRendererFormData.top = new FormAttachment(topComposite, 0);
graphRendererFormData.bottom = new FormAttachment(dataComposite, 0);
graphRendererFormData.left = new FormAttachment(0, 0);
graphRendererFormData.right = new FormAttachment(100, 0);
final FormData dataCompositeFormData = new FormData();
dataComposite.setLayoutData(dataCompositeFormData);
dataCompositeFormData.bottom = new FormAttachment(bottomComposite, 0);
dataCompositeFormData.left = new FormAttachment(0, 0);
dataCompositeFormData.right = new FormAttachment(100, 0);
// Bottom Composite
final FormData bottomCompositeFormData = new FormData();
bottomComposite.setLayoutData(bottomCompositeFormData);
bottomCompositeFormData.bottom = new FormAttachment(100, 0);
bottomCompositeFormData.left = new FormAttachment(0, 0);
bottomCompositeFormData.right = new FormAttachment(100, 0);
shell.pack();
//assign map: URI -> labels that have this URI as target
EMap<URI,org.eclipse.stem.core.graph.NodeLabel> graphNodeLabelList = stemGraph.getNodeLabels();
for(Map.Entry<URI,org.eclipse.stem.core.graph.NodeLabel> nodeLabel : graphNodeLabelList.entrySet())
{
URI labelURI = nodeLabel.getKey();
org.eclipse.stem.core.graph.NodeLabel tmpLabel = nodeLabel.getValue();
if (tmpLabel != null)
{
if(nodeURI2Label.get(tmpLabel.getURIOfIdentifiableToBeLabeled()) == null)
{
List<org.eclipse.stem.core.graph.NodeLabel> labels = new ArrayList<org.eclipse.stem.core.graph.NodeLabel>();
labels.add(tmpLabel);
nodeURI2Label.put(tmpLabel.getURIOfIdentifiableToBeLabeled(), labels);
}
else
{
nodeURI2Label.get(tmpLabel.getURIOfIdentifiableToBeLabeled()).add(tmpLabel);
}
}
}
//assign nodes to index in list of graphs that were given to this graphCanvas Instance
int numnodes = stemGraph.getNodes().size();
final Map<URI, GraphNode> URI2Graphnodes = new HashMap<URI, GraphNode>();
int[] assign = new int[numnodes];
if (graphList != null)
{
if (graphList.size() > 0) {
for (int i=0; i<numnodes; i++)
{
URI URI_i = stemGraph.getNodes().get(i).getKey();
for (int j=0; j<graphList.size(); j++)
{
if (graphList.get(j).getNodes().get(URI_i) != null)
{
assign[i] = j;
}
}
}
}
}
// Fill GraphDisplay with nodes
// The spatial information in translated into polygons. Each polygon has a zest node
// in its center. Via the lists "nodeID2Poly" and "GraphNodes" STEM nodes and polygons/zest nodes
// are mapped
for (int i=0; i<numnodes; i++)
{
Node n = stemGraph.getNodes().get(i).getValue();
//adaptNew is necessary, otherwise opening two times results in erratic segment reading
//LatLongProviderAdapterFactory.INSTANCE.adaptAllNew(n);
LatLongProvider latLongProvider = (LatLongProvider) LatLongProviderAdapterFactory.INSTANCE
.adaptNew(n, LatLongProvider.class);
//if node has no labels, add them from canonical graph info if available
//if (n.getLabels().size() == 0)
//NO! otherwise several labels from different sources wont be shown
{
URI nURI = n.getURI();
if (nodeURI2Label.get(nURI) != null)
{ List<org.eclipse.stem.core.graph.NodeLabel> labelList = nodeURI2Label.get(nURI);
for (org.eclipse.stem.core.graph.NodeLabel label: labelList)
{
if (!n.getLabels().contains(label))
n.getLabels().add(label);
}
}
}
List<Segment> segments = latLongProvider.getLatLong().getSegments();
Segment segment = null;
if (segments != null)
{
Set<DisplayPolygon> displayPolys = new HashSet<DisplayPolygon>();
//spatial information can contain several disjunct areas, select largest area to
//calculate center
if (segments.size() >= 1)
{ double largestArea = -1.0;
for (Segment segment_tmp: segments)
{
DisplayPolygon dPolygon = new DisplayPolygon(n.getURI().lastSegment(), segment_tmp);
polygonsToDraw.add(dPolygon);
displayPolys.add(dPolygon);
double area = Math.abs(dPolygon.getArea());
if(area >= largestArea) {
largestArea = area;
segment = segment_tmp;
}
for (int z=0; z < segment_tmp.size(); z++)
{
minLT = (segment_tmp.latitude(z)*RFD < minLT)? segment_tmp.latitude(z)*RFD : minLT ;
maxLT = (segment_tmp.latitude(z)*RFD > maxLT)? segment_tmp.latitude(z)*RFD : maxLT ;
minLG = (segment_tmp.longitude(z)*RFD < minLG) ? segment_tmp.longitude(z)*RFD :minLG ;
maxLG = (segment_tmp.longitude(z)*RFD > maxLG) ? segment_tmp.longitude(z)*RFD :maxLG ;
}
}
nodeID2Poly.put(n.getDublinCore().getIdentifier(), displayPolys);
}
if ((segment != null) && (segment.size() > 0))
{
double[] c = latLongProvider.getCenter();
centers.add(new double[]{c[1]*RFD, -c[0]*RFD});
}
} // if segments != null
for (double[] center : centers)
{
GraphNode graphCenterNode = new GraphNode(zestGraph, SWT.NONE, "");
graphCenterNode.setData(new NodeData(n,
center[0],
center[1]
));
graphCenterNode.setBackgroundColor(display.getSystemColor((assign[i] % 14)+2));
GraphNodes.put(n.getDublinCore().getIdentifier(), graphCenterNode);
URI2Graphnodes.put(n.getURI(), graphCenterNode );
}
centers.clear();
n.eAdapters().remove(latLongProvider);
latLongProvider = null;
} // end putting nodes into graph, untranslated
// Fill GraphDisplay with Edges
int numedges = stemGraph.getEdges().size();
for (int i=0; i<numedges; i++)
{
Edge e = stemGraph.getEdges().get(i).getValue();
URI nodeAURI = e.getNodeAURI();
URI nodeBURI = e.getNodeBURI();
URI edgeURI = e.getURI();
EdgeLabel edgeLabel = e.getLabel();
String edgeIdentifier = e.getDublinCore().getIdentifier();
String edgeTitle;
if (e.getDublinCore().getTitle() != null) edgeTitle = e.getDublinCore().getTitle();
else edgeTitle = "";
if ((URI2Graphnodes.get(nodeAURI) != null) &&
(URI2Graphnodes.get(nodeBURI) != null))
{
GraphConnection gc = new GraphConnection(zestGraph, SWT.NONE,
URI2Graphnodes.get(nodeAURI), URI2Graphnodes.get(nodeBURI));
gc.setData(new ConnectionData(nodeAURI, nodeBURI, edgeURI, edgeLabel, edgeTitle, edgeIdentifier));
GraphConnections.put(edgeIdentifier, gc);
}
}
//DisplayBounds
zestGraphBounds = zestGraph.getBounds();
//Bounds of accumulated polygons
//old- transposed: graphBounds = new Rectangle((int)(minLT), (int)(minLG) , (int)(maxLT-minLT), (int)(maxLG-minLG));
graphBounds = new Rectangle((int)(minLG), -(int)(minLT+maxLT-minLT) , (int)(maxLG-minLG), (int)(maxLT-minLT));
// compute the offset and scale so that stem graph fits well into display
computeTransform();
// draw Polygons
final PaintListener polygonPainter = new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.setClipping(zestGraph.getBounds());
e.gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
e.gc.setForeground(ColorConstants.lightGray);
for (final DisplayPolygon displayPolygon : polygonsToDraw)
e.gc.drawPolygon(polyAdapter(displayPolygon.transformedPolygon));
}
};
zestGraph.addPaintListener(polygonPainter);
redraw();
//remove automatic scroll bars when nodes leave display, remove mouse wheel scrolling
zestGraph.setVerticalScrollBarVisibility(0);
zestGraph.setHorizontalScrollBarVisibility(0);
zestGraph.getViewport().setIgnoreScroll(true);
Listener[] listeners = zestGraph.getVerticalBar().getListeners(SWT.Selection);
for (int i=0; i<listeners.length; i++)
{
zestGraph.getVerticalBar().removeListener(SWT.Selection, listeners[0]);
zestGraph.getVerticalBar().removeListener(SWT.Selection, listeners[1]);
}
listeners = zestGraph.getHorizontalBar().getListeners(SWT.Selection);
for (int i=0; i<listeners.length; i++)
{
zestGraph.getHorizontalBar().removeListener(SWT.Selection, listeners[0]);
zestGraph.getHorizontalBar().removeListener(SWT.Selection, listeners[1]);
}
shell.open();
while (!shell.isDisposed()) {
while (!display.readAndDispatch()) {
display.sleep();
}
}
//shell.close();
} // display
/************************************************************************
* Graphic functions
************************************************************************/
private double[] D2N(double x, double y)
{
double x_back = ((x/zoomFactor) - xTranslation - offsetX) / scaleFactor;
double y_back = ((y/zoomFactor) - yTranslation - offsetY) / scaleFactor;
return new double[]{x_back,y_back};
}
private void zoomOut() {
zoomFactor *= UNZOOMING_FACTOR;
redraw();
}
private void zoomIn() {
zoomFactor *= ZOOMING_FACTOR;
redraw();
}
private void addTranslation (final double xTranslationAddition, final double yTranslationAddition)
{
this.xTranslation += (xTranslationAddition) /zoomFactor;
this.yTranslation += (yTranslationAddition) / zoomFactor;
redraw();
} // addTranslation
private void addTranslationToPoly(DisplayPolygon polygon, final double xTranslationAddition, final double yTranslationAddition)
{
for (int i=0; i<polygon.npoints; i++)
{
polygon.transformedPolygon.xpoints[i] += (int) xTranslationAddition ;
polygon.transformedPolygon.ypoints[i] += (int) yTranslationAddition ;
polygon.originalPolygon.xpoints[i] += (int) xTranslationAddition*RFD/scaleFactor /zoomFactor;
polygon.originalPolygon.ypoints[i] += (int) yTranslationAddition*RFD/scaleFactor /zoomFactor;
}
}
private void addTranslationToNode(GraphNode node, final double xTranslation, final double yTranslation)
{
NodeData nodeData = (NodeData) node.getData();
nodeData.origX += xTranslation*RFD/scaleFactor /zoomFactor;
nodeData.origY += yTranslation*RFD/scaleFactor /zoomFactor;
}
private void redraw()
{
double origX, origY, displayX, displayY;
for (DisplayPolygon displayPolygon : polygonsToDraw) {
for (int i=0; i<displayPolygon.npoints; i++)
{
displayPolygon.transformedPolygon.xpoints[i] =
(int) ((displayPolygon.originalPolygon.xpoints[i]/RFD * scaleFactor + offsetX + xTranslation) * zoomFactor);
displayPolygon.transformedPolygon.ypoints[i] =
(int) ((displayPolygon.originalPolygon.ypoints[i]/RFD * scaleFactor + offsetY + yTranslation) * zoomFactor);
}
}
for (Map.Entry<String, GraphNode> entry : GraphNodes.entrySet())
{
GraphNode gn = entry.getValue();
NodeData nodeData = (NodeData) gn.getData();
origX = nodeData.getOrigX();
origY = nodeData.getOrigY();
displayX = (origX/RFD * scaleFactor + offsetX + xTranslation) * zoomFactor;
displayY = (origY/RFD * scaleFactor + offsetY + yTranslation) * zoomFactor;
//TODO scaling of node size with zoom factor
int size = 10;
gn.setSize(size, size);
gn.setLocation( displayX - size/2, displayY- size/2);
}
}
//computes offsets and scaling
private void computeTransform() {
Rectangle polygonsBoundsRect = graphBounds;
if (polygonsBoundsRect == null) {
return;
}
final Rectangle canvasBounds = zestGraphBounds;
final int effectiveCanvasWidth = canvasBounds.width - MARGIN;
final int effectiveCanvasHeight = canvasBounds.height - MARGIN;
final double width = polygonsBoundsRect.width/RFD;
final double height = polygonsBoundsRect.height/RFD;
final double WIDTH_RATIO = effectiveCanvasWidth / width;
final double HEIGHT_RATIO = effectiveCanvasHeight / height;
scaleFactor = Math.min(WIDTH_RATIO, HEIGHT_RATIO) * zoomFactor * 0.9;
// Figure out the extra translation needed to center the image either
// vertically or horizontally in the canvas
int xCenteringTranslation = 0;
int yCenteringTranslation = 0;
// Anything to center?
if (width > 0 && height > 0) {
// Yes
xCenteringTranslation = (int)(effectiveCanvasWidth - (width * scaleFactor)) / 2 - canvasBounds.x/2;
yCenteringTranslation = (int)(effectiveCanvasHeight - (height * scaleFactor)) / 2 - canvasBounds.y/2;
} // if anything to center
offsetX = -polygonsBoundsRect.x * scaleFactor/RFD + xCenteringTranslation;
offsetY = -polygonsBoundsRect.y * scaleFactor/RFD + yCenteringTranslation;
} // computeTransform
// ------------------------------ SAVING -----------------------------
private void saveGraph(List<org.eclipse.stem.core.graph.Graph> graphList, boolean saveAs, IProject project)
{
boolean canonical = graphList.size() > 1;
URI newURI = null;
if (saveAs == true)
{
//final SaveAsDialog saveAsDialog = new SaveAsDialog(Activator.getDefault().getWorkbench().getDisplay().getActiveShell());
final SaveInProjectDialog saveAsDialog = new SaveInProjectDialog(Activator.getDefault().getWorkbench().getDisplay().getActiveShell());
saveAsDialog.open();
final IPath path = saveAsDialog.getResult();
// Did we get a path?
if (path != null) {
// Yes
final IFile saveAsFile = ResourcesPlugin.getWorkspace().getRoot()
.getFile(path);
// Did we get a valid file?
project = saveAsFile.getProject();
if (saveAsFile != null) {
newURI = URI.createPlatformResourceURI(saveAsFile.getFullPath().toString());
}
}
}
Map<URI,URI> orig2newGraphURI = new HashMap<URI,URI>();
Map<URI,URI> orig2newModelURI = new HashMap<URI,URI>();
if (!canonical) //either single graph or canonical graph (with save as)
{
org.eclipse.stem.core.graph.Graph graph = graphList.get(0);
URI origURI = graph.getURI();
if (newURI ==null)
{
//transform filepaths to platform resource URI
newURI = URI.createPlatformResourceURI(project.getName() + "/graphs/" +
graph.getURI().lastSegment());
}
saving(graph, project, newURI);
//later set new reference in models when saved (not save as), save info in list
orig2newGraphURI.put(origURI, newURI);
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) { Activator.logError(ex.getMessage(), ex); }
}
else //if (canonical): it is a collection of graphs to be saved: save all graphs in their specific files
{
for (org.eclipse.stem.core.graph.Graph graph : graphList)
{
URI origURI = graph.getURI();
if (!saveAs) //every graph gets its own file URI, when save as,
{
//transform filepaths to platform resource URI
newURI = URI.createPlatformResourceURI(project.getName() + "/graphs/" +
graph.getURI().lastSegment());
}
saving(graph, project, newURI);
//set new reference in models when saved (not save as)
orig2newGraphURI.put(origURI, newURI);
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) {
Activator.logError(ex.getMessage(), ex);
}
}
}
if (!saveAs)
{
/* old
Map<String, Model> projectModels = new HashMap<String, Model>();
projectModels = addProjectModels(projectModels, project);
projectModels = getModels(projectModels);
for (Map.Entry<String, Model> entry : projectModels.entrySet()) {
Model model = entry.getValue();
saveModel(model, project, orig2newModelURI);
}
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) { Activator.logError(ex.getMessage(), ex); }
projectModels = new HashMap<String, Model>();
projectModels = addProjectModels(projectModels, project);
projectModels = getModels(projectModels);
for (Map.Entry<String, Model> entry : projectModels.entrySet()) {
Model model = entry.getValue();
output(model);
updateModelReferenceAndSave(model, project, orig2newGraphURI, orig2newModelURI );
}
*/
List<Model> projectModels = new ArrayList<Model>();
projectModels = addProjectModels(projectModels, project);
projectModels = getModels(projectModels);
for (Model model : projectModels) {
saveModel(model, project, orig2newModelURI);
}
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) {}
projectModels = new ArrayList<Model>();
projectModels = addProjectModels(projectModels, project);
projectModels = getModels(projectModels);
for (Model model : projectModels) {
updateModelReferenceAndSave(model, project, orig2newGraphURI, orig2newModelURI );
}
try {
project.touch(null);
project.refreshLocal(IResource.DEPTH_INFINITE, null);
//project.close(null);
//project.open(null);
}
catch (Exception ex) { Activator.logError(ex.getMessage(), ex); }
PlatformLatLongDataProvider plldp = new PlatformLatLongDataProvider();
plldp.flush();
}
}
private void saving(org.eclipse.stem.core.graph.Graph graph, IProject project, URI newURI)
{
String projectName = project.getName();
//make a deep copy of the graph where all changes are made
ArrayList<Identifiable> newlist = new ArrayList<Identifiable>();
//not working, keep for testing
/*Identifiable id = (Identifiable) EcoreUtil.copy(graph);
id.setURI(newURI);
org.eclipse.stem.core.graph.Graph graphcopy = (org.eclipse.stem.core.graph.Graph) id;
*/
//this seems to work
org.eclipse.stem.core.graph.Graph graphcopy = graph;
graphcopy.setURI(newURI);
String fileBaseName = graphcopy.getURI().lastSegment().
substring(0, graphcopy.getURI().lastSegment().lastIndexOf("."));
String tail = projectName + "/.gml/" + fileBaseName + "_MAP.xml";
if(!project.getFolder(".gml").exists())
{
IProgressMonitor monitor = new NullProgressMonitor();
try {
project.getFolder(".gml").create(false, true, monitor);
} catch (CoreException e)
{
Activator.logError(e.getMessage(), e);
} finally {
monitor.done();
}
}
//LABELS
EMap<URI, NodeLabel> stemLabels = graphcopy.getNodeLabels();
EMap<URI, NodeLabel> stemLabels_stemGraph = stemGraph.getNodeLabels();
for (Map.Entry<URI,NodeLabel> entry : stemLabels_stemGraph.entrySet())
{
URI uri = entry.getKey();
NodeLabel nodeLabel = entry.getValue();
if(stemLabels.containsKey(uri))
{
NodeLabel copyGraphNodeLabel = stemLabels.get(uri);
if ((nodeLabel != null) && (copyGraphNodeLabel != null))
if (!copyGraphNodeLabel.toString().equals(nodeLabel.toString()))
//TODO if (copyGraphNodeLabel != nodeLabel)
{
//System.err.println("Change Label with URI " + uri + " from "
// + copyGraphNodeLabel.toString() + " to " + nodeLabel.toString());
if (stemLabels.get(uri) instanceof PopulationLabel)
{
((PopulationLabel)stemLabels.get(uri)).
setPopulationIdentifier(((PopulationLabel)nodeLabel).getPopulationIdentifier());
((PopulationLabel)stemLabels.get(uri)).
setName(((PopulationLabel)nodeLabel).getName());
}
if (stemLabels.get(uri) instanceof AreaLabel)
((AreaLabel)stemLabels.get(uri))
//.setCurrentValue(((AreaLabel)nodeLabel).getCurrentAreaValue());
.getCurrentAreaValue().setArea(((AreaLabel)nodeLabel).getCurrentAreaValue().getArea());
}
}
}
//EDGES
EMap<URI, Edge> stemEdges = graphcopy.getEdges();
for (Map.Entry<URI,Edge> entry : stemEdges.entrySet())
{
URI uri = entry.getKey();
Edge e = entry.getValue();
String edgeID = e.getDublinCore().getIdentifier();
GraphConnection gc = GraphConnections.get(edgeID);
if (gc != null)
{
ConnectionData edgeData = (ConnectionData) gc.getData();
//Title
e.getDublinCore().setTitle(edgeData.getEdgeTitle());
if (e.getLabel() instanceof MigrationEdgeLabel)
{
EdgeLabel edgeLabel = edgeData.getEdgeLabel();
double migRate = ((MigrationEdgeLabel)edgeLabel).getCurrentValue().getMigrationRate();
((MigrationEdgeLabel)e.getLabel())
.getCurrentValue().setMigrationRate(migRate);
}
}
}
Map<Node, NodeLabel> add2GraphMap = new HashMap<Node,NodeLabel>();
//NODES
EMap<URI, Node> stemNodes = graphcopy.getNodes();
Map<String,Set<GmlPolygon>> polygonMap = new HashMap<String,Set<GmlPolygon>>();
SpatialGmlExporter sgmle = new SpatialGmlExporter();
for (Map.Entry<URI,Node> entry : stemNodes.entrySet())
{
Node n = entry.getValue();
String nodeID = n.getDublinCore().getIdentifier();
GraphNode gn = GraphNodes.get(nodeID);
if (gn != null)
{
NodeData nodeData = (NodeData) gn.getData();
//Title
n.getDublinCore().setTitle(nodeData.getNodeTitle());
//graph.getNode(n.getURI()).getDublinCore().setTitle(nodeData.getNodeTitle());
if (nodeURI2Label.containsKey(nodeData.getNodeURI()))
{
//in the list nodeURI2Label the labels of the canonical graph
//have been assigned to their target nodes. If meanwhile
//new labels have been added in the editor, the list lengths should
//differ
if (nodeURI2Label.get(nodeData.getNodeURI()).size() != nodeData.getNodeLabels().size())
{
List<NodeLabel> originalLabelList = nodeURI2Label.get(nodeData.getNodeURI());
for (NodeLabel nodeLabel : nodeData.getNodeLabels())
{
if (!originalLabelList.contains(nodeLabel))
{
graphcopy.getNodeLabels().put(nodeLabel.getURI(), nodeLabel);
add2GraphMap.put(graph.getNode(nodeLabel.getURIOfIdentifiableToBeLabeled()), nodeLabel);
}
}
}
}
else // there were no assignments of labels to this node in advance
{
if (nodeData.getNodeLabels() != null)
{
for (NodeLabel nodeLabel : nodeData.getNodeLabels())
{
graphcopy.getNodeLabels().put(nodeLabel.getURI(), nodeLabel);
}
}
}
}
for (Map.Entry<Node,NodeLabel> URINodeEntry : add2GraphMap.entrySet())
{
NodeLabel nl = URINodeEntry.getValue();
Node node = URINodeEntry.getKey();
graph.getNode(node.getURI()).getLabels().add(nl);
}
//Spatial
Set<DisplayPolygon> displayPolygons = nodeID2Poly.get(n.getDublinCore().getIdentifier());
if (displayPolygons != null)
{
if (n.getDublinCore().getSpatial().indexOf(SpatialProviderAdapter.STEM_SPATIAL_SCHEME_PREFIX+"inline") >= 0)
{
String spatialURIString = polygon2LatLong(displayPolygons);
n.getDublinCore().setSpatial(spatialURIString);
}
if (n.getDublinCore().getSpatial().indexOf(SpatialProviderAdapter.STEM_SPATIAL_SCHEME_PREFIX+"platform") >= 0)
{
Set<GmlPolygon> gmlPolygons = new HashSet<GmlPolygon>();
for (DisplayPolygon dPolygon : displayPolygons)
{
gmlPolygons.add(dPolygon.getUnscaledGmlPolygon());
}
polygonMap.put(n.getURI().lastSegment(), gmlPolygons);
String nodeSpatialString = SpatialProviderAdapter.STEM_SPATIAL_SCHEME_PREFIX+"platform:/resource/" +
tail + "#" + n.getURI().lastSegment();
n.getDublinCore().setSpatial(nodeSpatialString);
}
}
}//node loop
if (polygonMap.size() > 0)
{
sgmle.writeSpatialData( polygonMap,
ResourcesPlugin.getWorkspace().getRoot().getLocation().toString().concat("/" + tail ),
graphcopy.getURI().lastSegment(),
-1);
String spatialString = SpatialProviderAdapter.STEM_SPATIAL_SCHEME_PREFIX+"platform:/resource/" + tail;
graphcopy.getDublinCore().setSpatial(spatialString);
}
// saving Graph
try {
graphcopy.getDublinCore().setTitle("");
//make another copy here, or problems with save as...
Identifiable graphCopyCopy = (Identifiable) EcoreUtil.copy(graphcopy);
graphCopyCopy.setURI(newURI);
newlist.add(graphCopyCopy);
Utility.serializeIdentifiables(newlist, newURI);
newlist = null;
} catch(Exception e) {
Activator.logError(e.getMessage(), e);
}
}
private String polygon2LatLong(Set<DisplayPolygon> displayPolygons)
{
//LatLong latLong = new LatLong();
List<Segment> segments = new ArrayList<Segment>();
for (DisplayPolygon displayPolygon : displayPolygons)
{
SegmentBuilder sb = new SegmentBuilder();
for (int i=0; i<displayPolygon.npoints; i++)
{ //transform to old coordinate System
sb.add( -displayPolygon.originalPolygon.ypoints[i] / RFD,
displayPolygon.originalPolygon.xpoints[i] / RFD);
}
segments.add(sb.toSegment());
//sometimes, values of segment show something different
//System.err.println("S2S: " + sb.toString());
}
//manually create inline spatial string, because toSTring of segment gives wrong values sometimes
final StringBuilder sb = new StringBuilder(SpatialProviderAdapter.STEM_SPATIAL_SCHEME_PREFIX);
sb.append("inline");
sb.append("://");
for (final Segment segment : segments) {
sb.append("/");
for (int s=0; s<segment.size(); s++)
{
sb.append(segment.latitude(s));
sb.append(",");
sb.append(segment.longitude(s));
// Any more values?
if (s < segment.size() - 1) {
// Yes
sb.append(",");
}
}
} // for each segment
return sb.toString();
//this sometimes gives wrong values!
//latLong.add(segments);
//String spatialString = InlineLatLongDataProvider.createSpatialInlineURIString(latLong);
//return spatialString;
}
/***************************************************************************
* Composites
*
***************************************************************************/
private Composite createBottomComposite(final Composite parent, final Graph zestGraph, final File file, final IProject project) {
GridData toolbarGridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER, GridData.HORIZONTAL_ALIGN_BEGINNING, false, false);
ToolBar toolBar = new ToolBar(parent, SWT.HORIZONTAL);
toolBar.setLayoutData(toolbarGridData);
toolBar.setLayout(new FillLayout(SWT.HORIZONTAL));
if (graphList.size() >= 1) //== // if file == null it is a canonical graph
{
ToolItem saveButton = new ToolItem(toolBar, SWT.PUSH);
saveButton.setText("Save Graph and Quit");
saveButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
saveGraph(graphList, false, project);
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) { Activator.logError(ex.getMessage(), ex); }
//display(graphList, null, project, null); //TODO check to give model
Activator.getDefault().getWorkbench().getDisplay().getActiveShell().dispose();
//clean(graphList, project);
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
}
ToolItem separator = new ToolItem(toolBar, SWT.SEPARATOR);
ToolItem saveAsButton = new ToolItem(toolBar, SWT.PUSH);
saveAsButton.setText("Save Graph As ...");
saveAsButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
List<org.eclipse.stem.core.graph.Graph> saveGraphList =
new ArrayList<org.eclipse.stem.core.graph.Graph>();
saveGraphList.add(stemGraph);
saveGraph(saveGraphList, true, project);
try { project.refreshLocal(IResource.DEPTH_INFINITE, null); }
catch (Exception ex) { Activator.logError(ex.getMessage(), ex); }
//Activator.getDefault().getWorkbench().getDisplay().getActiveShell().dispose();
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
/* TODO Reset Button
ToolItem resetButton = new ToolItem(toolBar, SWT.PUSH);
resetButton.setText("Reset");
resetButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
xTranslation = 0;
yTranslation = 0;
zoomFactor = 0;
redraw();
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
*/
ToolItem separator2 = new ToolItem(toolBar, SWT.SEPARATOR);
ToolItem quitButton = new ToolItem(toolBar, SWT.PUSH);
quitButton.setText("Quit");
quitButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
Activator.getDefault().getWorkbench().getDisplay().getActiveShell().dispose();
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
return toolBar;
} // createBottomComposite
private Composite createDataComposite(final Composite parent, final Graph zestGraph) {
final Composite dataComposite = new Composite(parent, SWT.CENTER);
final Composite propertiesComposite_nodes = new Composite(dataComposite, SWT.CENTER);
final Composite propertiesComposite_edges = new Composite(dataComposite, SWT.CENTER);
final Composite infoComposite = new Composite(dataComposite, SWT.CENTER);
final RowLayout dataCompositeLayout = new RowLayout(SWT.VERTICAL);
dataComposite.setLayout(dataCompositeLayout);
final RowLayout propertiesCompositeNodesLayout = new RowLayout(SWT.HORIZONTAL);
propertiesComposite_nodes.setLayout(propertiesCompositeNodesLayout);
final RowLayout propertiesCompositeEdgesLayout = new RowLayout(SWT.HORIZONTAL);
propertiesComposite_edges.setLayout(propertiesCompositeEdgesLayout);
final RowLayout infoCompositeLayout = new RowLayout(SWT.HORIZONTAL);
infoComposite.setLayout(infoCompositeLayout);
final Label nodeTitle;
final Text nodeTitle_edit;
final Label nodeURI;
final Label nodeURI_edit;
final Label nodeLabelType;
final Combo nodeLabelType_edit;
final Label nodeLabelValue;
final Combo nodeLabelValue_edit;
final Label nodeXY;
final Label nodeXY_edit;
final Label nodeAURI;
final Label nodeAURI_edit;
final Label nodeBURI;
final Label nodeBURI_edit;
//final Label edgeURI;
//final Label edgeURI_edit;
final Label edgeTitle;
final Text edgeTitle_edit;
final Label edgeLabelType;
final Label edgeLabelType_edit;
final Label edgeLabelValue;
final Text edgeLabelValue_edit;
nodeTitle = new Label(propertiesComposite_nodes, SWT.NONE);
nodeTitle.setLayoutData(new RowData(30, SWT.DEFAULT));
nodeTitle.setText("Title: ");
nodeTitle_edit = new Text(propertiesComposite_nodes, SWT.NONE);
nodeTitle_edit.setLayoutData(new RowData(250, SWT.DEFAULT));
nodeTitle_edit.addModifyListener(new TextModifyListener(zestGraph, NODE_TITLE));
nodeURI = new Label(propertiesComposite_nodes, SWT.NONE);
nodeURI.setLayoutData(new RowData(30, SWT.DEFAULT));
nodeURI.setText("URI: ");
nodeURI_edit = new Label(propertiesComposite_nodes, SWT.NONE);
nodeURI_edit.setLayoutData(new RowData(200, SWT.DEFAULT));
nodeLabelType = new Label(propertiesComposite_nodes, SWT.NONE);
nodeLabelType.setLayoutData(new RowData(50, SWT.DEFAULT));
nodeLabelType.setText("LabelType: ");
nodeLabelType_edit = new Combo(propertiesComposite_nodes, SWT.READ_ONLY);
nodeLabelType_edit.setLayoutData(new RowData(95, SWT.DEFAULT));
nodeLabelValue = new Label(propertiesComposite_nodes, SWT.NONE);
nodeLabelValue.setLayoutData(new RowData(130, SWT.DEFAULT));
nodeLabelValue.setText("Value: ");
nodeLabelValue_edit = new Combo(propertiesComposite_nodes, SWT.NONE);
nodeLabelValue_edit.setLayoutData(new RowData(80, SWT.DEFAULT));
nodeLabelType_edit.addSelectionListener(new ComboListenerType(zestGraph, nodeLabelValue_edit, nodeLabelValue));
nodeLabelValue_edit.addKeyListener(new ComboListenerValue(zestGraph, nodeLabelType_edit));
nodeLabelValue_edit.addSelectionListener(new ComboSelectionListenerValue(zestGraph, nodeLabelType_edit, nodeLabelValue));
nodeXY = new Label(propertiesComposite_nodes, SWT.NONE);
nodeXY.setText("XY: ");
nodeXY.setLayoutData(new RowData(20, SWT.DEFAULT));
nodeXY_edit = new Label(propertiesComposite_nodes, SWT.NONE);
nodeXY_edit.setLayoutData(new RowData(70, SWT.DEFAULT));
edgeTitle = new Label(propertiesComposite_edges, SWT.NONE);
edgeTitle.setLayoutData(new RowData(30, SWT.DEFAULT));
edgeTitle.setText("Title: ");
edgeTitle_edit = new Text(propertiesComposite_edges, SWT.NONE);
edgeTitle_edit.setLayoutData(new RowData(400, SWT.DEFAULT));
edgeTitle_edit.addModifyListener(new TextModifyListener(zestGraph, EDGE_TITLE));
edgeLabelType = new Label(propertiesComposite_edges, SWT.NONE);
edgeLabelType.setLayoutData(new RowData(60, SWT.DEFAULT));
edgeLabelType.setText("EdgeType: ");
edgeLabelType_edit = new Label(propertiesComposite_edges, SWT.NONE);
edgeLabelType_edit.setLayoutData(new RowData(120, SWT.DEFAULT));
edgeLabelValue = new Label(propertiesComposite_edges, SWT.NONE);
edgeLabelValue.setLayoutData(new RowData(30, SWT.DEFAULT));
edgeLabelValue.setText("Value: ");
edgeLabelValue_edit = new Text(propertiesComposite_edges, SWT.NONE);
edgeLabelValue_edit.setLayoutData(new RowData(30, SWT.DEFAULT));
edgeLabelValue_edit.addModifyListener(new TextModifyListener(zestGraph, EDGE_LABEL_VALUE));
nodeAURI = new Label(propertiesComposite_edges, SWT.NONE);
nodeAURI.setLayoutData(new RowData(40, SWT.DEFAULT));
nodeAURI.setText("NodeA: ");
nodeAURI_edit = new Label(propertiesComposite_edges, SWT.NONE);
nodeAURI_edit.setLayoutData(new RowData(150, SWT.DEFAULT));
nodeBURI = new Label(propertiesComposite_edges, SWT.NONE);
nodeBURI.setLayoutData(new RowData(40, SWT.DEFAULT));
nodeBURI.setText("NodeB: ");
nodeBURI_edit = new Label(propertiesComposite_edges, SWT.NONE);
nodeBURI_edit.setLayoutData(new RowData(150, SWT.DEFAULT));
nodeAURI_edit.setVisible(false);
nodeBURI_edit.setVisible(false);
edgeLabelType_edit.setVisible(false);
edgeLabelValue_edit.setVisible(false);
edgeTitle_edit.setVisible(false);
nodeURI_edit.setVisible(false);
nodeTitle_edit.setVisible(false);
nodeLabelType_edit.setVisible(false);
nodeLabelValue_edit.setVisible(false);
nodeXY_edit.setVisible(false);
final Label coordinate_trans = new Label(infoComposite, SWT.NONE);
coordinate_trans.setLayoutData(new RowData(200, SWT.DEFAULT));
coordinate_trans.setText("XY: ");
final Label zoom = new Label(infoComposite, SWT.NONE);
zoom.setLayoutData(new RowData(100, SWT.DEFAULT));
zoom.setText("Zoom: " + zoomFactor);
// MouseClick Listener
zestGraph.addMouseListener( new MouseListener() {
public void mouseDown(final MouseEvent e) {
int x = Display.getCurrent().getCursorLocation().x;
int y = Display.getCurrent().getCursorLocation().y;
// Is the left mouse button?
if ((e.button == 1) && (zestGraph.getSelection().size() == 0))
{
lastOffsetX = x;
lastOffsetY = y;
leftMouseButtonPressed = true;
} // if
if ((e.button == 1) && (zestGraph.getSelection().size() > 0))
{
leftMouseButtonPressed = true;
lastOffsetX = x;
lastOffsetY = y;
}
zestGraph.redraw();
} // mouseDown
public void mouseUp(final MouseEvent e) {
// Is it the left mouse button?
if ((e.button == 1) && (zestGraph.getSelection().size() == 0))
{
int x = Display.getCurrent().getCursorLocation().x;
int y = Display.getCurrent().getCursorLocation().y;
// Yes
// new x and y are defined by current mouse location subtracted
// by previously processed mouse location
int newX = x - lastOffsetX;
int newY = y - lastOffsetY;
// Did we move from the spot where the mouse went down?
if (newX != 0 || newY != 0) {
// Yes
addTranslation(newX, newY);
} // if moved
leftMouseButtonPressed = false;
}
if ((e.button == 1) && (zestGraph.getSelection().size() > 0))
{
int x = Display.getCurrent().getCursorLocation().x;
int y = Display.getCurrent().getCursorLocation().y;
for (int i=0; i<zestGraph.getSelection().size(); i++)
{
GraphItem selectedItem = (GraphItem) zestGraph.getSelection().get(0);
if (selectedItem instanceof GraphNode)
{
final int newX = x - lastOffsetX;
final int newY = y - lastOffsetY;
lastOffsetX = x;
lastOffsetY = y;
if (newX != 0 || newY != 0) {
zestGraph.redraw();
}
}
}
leftMouseButtonPressed = false;
}
zestGraph.redraw();
redraw();
}
public void mouseDoubleClick(final MouseEvent e) {}
});
//MouseMove Listener
zestGraph.addMouseMoveListener(new MouseMoveListener() {
public void mouseMove(MouseEvent e) {
int x = Display.getCurrent().getCursorLocation().x;
int y = Display.getCurrent().getCursorLocation().y;
Point xy = zestGraph.toControl(Display.getCurrent().getCursorLocation());
double[] xy_trans = D2N(xy.x,xy.y);
coordinate_trans.setText("Coordinates: " + df.format(-xy_trans[1]) + " " + df.format(xy_trans[0]) );
//other coord systems
//coordinate2.setText("xy2: " + e.x + " " + e.y);
//coordinate2.setText("xy2: " + xy.toString() );
if ((leftMouseButtonPressed) && (zestGraph.getSelection().size() == 0)) {
// Yes
// new x and y are defined by current mouse location subtracted
// by previously processed mouse location
final int newX = x - lastOffsetX;
final int newY = y - lastOffsetY;
lastOffsetX = x;
lastOffsetY = y;
// Did we move from the spot where the mouse went down?
if (newX != 0 || newY != 0) {
// Yes
// This is a translation of the map then
// update the canvas translation
addTranslation(newX, newY);
} // if moved
zestGraph.redraw();
redraw();
}
if ((leftMouseButtonPressed) && (zestGraph.getSelection().size() > 0)) {
for (int i=0; i<zestGraph.getSelection().size(); i++)
{
GraphItem selectedItem = (GraphItem) zestGraph.getSelection().get(0);
if (selectedItem instanceof GraphNode)
{
GraphNode selectedNode = (GraphNode) selectedItem;
NodeData nodeData = (NodeData) selectedNode.getData();
String nodeID = nodeData.getNodeIdentifier();
Set<DisplayPolygon> DisplayPolygons = nodeID2Poly.get(nodeID);
final int newX = x - lastOffsetX;
final int newY = y - lastOffsetY;
lastOffsetX = x;
lastOffsetY = y;
if (newX != 0 || newY != 0) {
for (DisplayPolygon displayPolygon : DisplayPolygons)
{ addTranslationToPoly(displayPolygon, newX, newY); }
addTranslationToNode(selectedNode, newX, newY);
double[] nodexy_trans = new double[]{((NodeData)selectedNode.getData()).getOrigX()/RFD, ((NodeData)selectedNode.getData()).getOrigY()/RFD};
nodeXY_edit.setText( df.format(-nodexy_trans[1]) + " " + df.format(nodexy_trans[0]));
zestGraph.redraw();
}
}
}
//update();
} // if mouse pressed and selection
} //end MouseMove
});
//Selection of Nodes / Edges
zestGraph.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
List<GraphItem> selectedItems = zestGraph.getSelection();
if (selectedItems.size() == 1)
{
nodeAURI_edit.setVisible(true);
nodeBURI_edit.setVisible(true);
edgeLabelType_edit.setVisible(true);
edgeLabelValue_edit.setVisible(true);
edgeTitle_edit.setVisible(true);
nodeURI_edit.setVisible(true);
nodeTitle_edit.setVisible(true);
nodeLabelType_edit.setVisible(true);
nodeLabelValue_edit.setVisible(true);
nodeXY_edit.setVisible(true);
GraphItem selectedItem = selectedItems.get(0);
if (selectedItem instanceof GraphNode)
{
nodeAURI_edit.setVisible(false);
nodeBURI_edit.setVisible(false);
edgeLabelType_edit.setVisible(false);
edgeLabelValue_edit.setVisible(false);
edgeTitle_edit.setVisible(false);
GraphNode selectedNode = (GraphNode) selectedItem;
NodeData nodeData = (NodeData) selectedNode.getData();
if (selectedNode.getData() != null)
{
nodeURI_edit.setText(((NodeData)selectedNode.getData()).getNodeURI().lastSegment().toString());
nodeTitle_edit.setText(((NodeData)selectedNode.getData()).getNodeTitle().toString());
List<org.eclipse.stem.core.graph.NodeLabel> nodeLabels = nodeData.getNodeLabels();
List<Integer> nodeLabelTypes = nodeData.getNodeLabelTypes();
nodeLabelType_edit.removeAll();
nodeLabelValue_edit.removeAll();
for(int i=0; i<nodeLabelTypes.size(); i++)
{
switch(nodeLabelTypes.get(i))
{
case AREA_LABEL: nodeLabelType_edit.add("Area Label",i);
break;
case POPULATION_LABEL: nodeLabelType_edit.add("Population Label",i);
break;
}
}
// initialize label values for first label when node is selected
if (nodeLabelType_edit.getItemCount() >0)
{
nodeLabelType_edit.select(0);
NodeLabel nodeLabel = nodeLabels.get(0);
switch(nodeLabelTypes.get(0))
{
case AREA_LABEL: AreaLabel areaLabel = (AreaLabel) nodeLabel;
nodeLabelValue_edit.add(String.valueOf(areaLabel.getCurrentAreaValue().getArea()));
nodeLabelValue.setText("Value (Area km^2): ");
break;
case POPULATION_LABEL: PopulationLabel populationLabel = (PopulationLabel) nodeLabel;
nodeLabelValue_edit.add(populationLabel.getName());
nodeLabelValue_edit.add(String.valueOf(populationLabel.getCurrentPopulationValue().getCount()));
nodeLabelValue_edit.add(String.valueOf(populationLabel.getPopulatedArea()));
nodeLabelValue.setText("Value (Population name): ");
break;
}
nodeLabelValue_edit.select(0);
}
}
double[] xy_trans = new double[]{((NodeData)selectedNode.getData()).getOrigX()/RFD, ((NodeData)selectedNode.getData()).getOrigY()/RFD};
nodeXY_edit.setText( df.format(-xy_trans[1]) + " " + df.format(xy_trans[0]));
}
else if (selectedItem instanceof GraphConnection)
{
nodeURI_edit.setVisible(false);
nodeTitle_edit.setVisible(false);
nodeLabelType_edit.setVisible(false);
nodeLabelValue_edit.setVisible(false);
nodeXY_edit.setVisible(false);
GraphConnection selectedEdge = (GraphConnection) selectedItem;
if (selectedEdge.getData() != null)
{
edgeTitle_edit.setText(((ConnectionData)selectedEdge.getData()).getEdgeTitle());
nodeAURI_edit.setText(((ConnectionData)selectedEdge.getData()).getNodeAURI().lastSegment().toString());
nodeBURI_edit.setText(((ConnectionData)selectedEdge.getData()).getNodeBURI().lastSegment().toString());
switch ( ((ConnectionData)selectedEdge.getData()).getEdgeLabelType() )
{
case MIGRATION_EDGE: MigrationEdgeLabel migrationEdgeLabel = (MigrationEdgeLabel)((ConnectionData)selectedEdge.getData()).getEdgeLabel();
edgeLabelType_edit.setText("Migration Edge");
edgeLabelValue_edit.setText(migrationEdgeLabel.getCurrentValue().getMigrationRate()+"");
break;
case CONTAINMENT_EDGE: RelativePhysicalRelationshipLabel rprl = (RelativePhysicalRelationshipLabel) ((ConnectionData)selectedEdge.getData()).getEdgeLabel();
edgeLabelType_edit.setText("Containment Edge");
//edgeLabelValue_edit.setText(rprl.getCurrentValue().toString());
edgeLabelValue_edit.setVisible(false);
break;
case COMMON_BORDER_EDGE:CommonBorderRelationshipLabel cbrl = (CommonBorderRelationshipLabel) ((ConnectionData)selectedEdge.getData()).getEdgeLabel();
edgeLabelType_edit.setText("Common Border Edge");
edgeLabelValue_edit.setVisible(false);
break;
case UNDEFINED: edgeLabelType_edit.setText("");
edgeLabelValue_edit.setText("");
}
}
}
} // Selection size of zest Graph == 1
else // selection size = 0 or > 1
{
nodeAURI_edit.setVisible(false);
nodeBURI_edit.setVisible(false);
edgeLabelType_edit.setVisible(false);
edgeLabelValue_edit.setVisible(false);
edgeTitle_edit.setVisible(false);
nodeURI_edit.setVisible(false);
nodeTitle_edit.setVisible(false);
nodeLabelType_edit.setVisible(false);
nodeLabelValue.setText("Value: ");
nodeLabelValue_edit.setVisible(false);
nodeXY_edit.setVisible(false);
}
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
//Zoom with mouse wheel
zestGraph.addMouseWheelListener(
new MouseWheelListener(){
public void mouseScrolled(final MouseEvent e) {
// Zoom Out?
if (e.count >= 0)
{
zoomIn();
zestGraph.redraw();
double zoomFactor_display = ((int)(zoomFactor*100))/100.0;
zoom.setText("Zoom: " + zoomFactor_display);
}
else {
zoomOut();
zestGraph.redraw();
double zoomFactor_display = ((int)(zoomFactor*100))/100.0;
zoom.setText("Zoom: " + zoomFactor_display);
}
}
});
// Create context menu
Menu menu = new Menu(zestGraph.getShell(),SWT.POP_UP );
final MenuItem addLabel = new MenuItem(menu, SWT.CASCADE);
final Menu labelMenu = new Menu(zestGraph.getShell(), SWT.DROP_DOWN);
final MenuItem addAreaLabel = new MenuItem(labelMenu, SWT.PUSH);
final MenuItem addPopulationLabel = new MenuItem(labelMenu, SWT.PUSH);
addLabel.setMenu(labelMenu);
addLabel.setText("Add Label");
addAreaLabel.setText("Add Area Label");
addPopulationLabel.setText("Add Population Label");
/*
//TODO add edges to graph
MenuItem addEdge = new MenuItem(menu, SWT.CASCADE);
Menu edgeMenu = new Menu(zestGraph.getShell(), SWT.DROP_DOWN);
MenuItem addMigrationEdge = new MenuItem(edgeMenu, SWT.CASCADE);
MenuItem addContainmentEdge = new MenuItem(edgeMenu, SWT.CASCADE);
addEdge.setText("Add Edge");
addEdge.setMenu(edgeMenu);
addMigrationEdge.setText("Add Migration Edge");
addContainmentEdge.setText("Add Containment Edge");
*/
menu.addMenuListener(new MenuListener() {
public void menuHidden(org.eclipse.swt.events.MenuEvent e) {
}
public void menuShown(org.eclipse.swt.events.MenuEvent e) {
List<GraphItem> selectedItems = zestGraph.getSelection();
if (selectedItems.size() == 1)
{
if (selectedItems.get(0) instanceof GraphNode)
{
//addAreaLabel.setEnabled(true);
addLabel.setEnabled(true);
}
else
{
addLabel.setEnabled(false);
//addAreaLabel.setEnabled(false);
}
}
else
{
addLabel.setEnabled(false);
//addAreaLabel.setEnabled(false);
}
}
});
addAreaLabel.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
List<GraphItem> selectedItems = zestGraph.getSelection();
if (selectedItems.size() == 1)
{
if (selectedItems.get(0) instanceof GraphItem)
{
GraphItem selectedNode = (GraphItem) selectedItems.get(0);
NodeData nodeData = (NodeData) selectedNode.getData();
final AreaLabel areaLabel = LabelsFactory.eINSTANCE.createAreaLabel();
areaLabel.getCurrentAreaValue().setArea(0.0);
areaLabel.setURIOfIdentifiableToBeLabeled(nodeData.getNodeURI());
areaLabel.setNode(nodeData.getNode());
URI newURI = createAreaLabelURI(nodeData.getNode());
//prevents multiple labels, important for population already
//areaLabel.setURI(newURI);
//stemGraph.getNodeLabels().put(newURI, areaLabel);
stemGraph.getNodeLabels().put(areaLabel.getURI(), areaLabel);
nodeData.getNodeLabels().add(areaLabel);
nodeData.getNodeLabelTypes().add(AREA_LABEL);
nodeLabelType_edit.add("Area Label");
nodeLabelType_edit.select(nodeLabelType_edit.getItemCount()-1);
nodeLabelValue_edit.setItems(new String[]{"0.0"});
nodeLabelValue_edit.select(0);
}
}
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
addPopulationLabel.addSelectionListener(new SelectionListener() {
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
List<GraphItem> selectedItems = zestGraph.getSelection();
if (selectedItems.size() == 1)
{
if (selectedItems.get(0) instanceof GraphItem)
{
String initPop = "population name";
GraphItem selectedNode = (GraphItem) selectedItems.get(0);
NodeData nodeData = (NodeData) selectedNode.getData();
PopulationLabel populationLabel = LabelsFactory.eINSTANCE.createPopulationLabel();
populationLabel.setPopulationIdentifier(initPop);
populationLabel.setPopulatedArea(0.0);
populationLabel.getCurrentPopulationValue().setCount(0);
populationLabel.setName(initPop);
populationLabel.setURIOfIdentifiableToBeLabeled(nodeData.getNodeURI());
populationLabel.setNode(nodeData.getNode());
URI newURI = createPopulationLabelURI(nodeData.getNode(), initPop);
//this would prevent multiple labels, important for population already
//populationLabel.setURI(newURI);
//stemGraph.getNodeLabels().put(newURI, populationLabel);
stemGraph.getNodeLabels().put(populationLabel.getURI(), populationLabel);
nodeData.getNodeLabels().add(populationLabel);
nodeData.getNodeLabelTypes().add(POPULATION_LABEL);
nodeLabelType_edit.add("Population Label");
nodeLabelType_edit.select(nodeLabelType_edit.getItemCount()-1);
nodeLabelValue_edit.setItems(new String[]{initPop, "0", "0.0"});
nodeLabelValue_edit.select(0);
}
}
}
public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {
}
});
zestGraph.setMenu(menu);
return dataComposite;
} // createTopComposite
private Composite createTopComposite(final Composite parent, String text) {
final Composite topComposite = new Composite(parent, SWT.CENTER);
final FillLayout topCompositeLayout = new FillLayout(SWT.VERTICAL);
topComposite.setLayout(topCompositeLayout);
Label title = new Label(topComposite, SWT.CENTER);
title.setText(text);
return topComposite;
} // createTopComposite
/*
Polygon functions and class
*/
private int[] polyAdapter(Polygon polygon)
{
if (polygon == null) return new int[]{0,0};
int[] points = new int[polygon.npoints*2];
for (int i=0; i< polygon.npoints; i++ )
{
points[i*2] = polygon.xpoints[i];//jfw
points[(i*2)+1] = polygon.ypoints[i];
}
return points;
}
private URI createAreaLabelURI(Node n) {
String code = n.getURI().lastSegment();
int adminLevel = Utility.keyLevel(n.getURI().lastSegment());
String countryCode = getCountryCode(n);
return AreaLabelImpl.createAreaLabelURI(adminLevel, countryCode, code);
}
private URI createPopulationLabelURI(Node n, String population) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
String code = n.getURI().lastSegment();
int adminLevel = Utility.keyLevel(n.getURI().lastSegment());
String countryCode = getCountryCode(n);
return PopulationLabelImpl.createPopulationLabelURI(adminLevel, countryCode, population, year+"", code);
}
private String getCountryCode(Node n) {
if(Utility.keyLevel(n.getURI().lastSegment()) == 0) return n.getURI().lastSegment();
else for(Edge e:n.getEdges())
if(Utility.keyLevel(e.getA().getURI().lastSegment()) < Utility.keyLevel(n.getURI().lastSegment()))
return getCountryCode(e.getA());
return "ZZZ"; // Not found, but ZZZ is the parent of everything
}
private List<Model> addProjectModels(List<Model> projectModels, IProject project)
{
IFolder modelFolder = project.getFolder("models");
IResource[] models = null;
try {
models = modelFolder.members();
} catch(Exception e) {
e.printStackTrace();
}
if (models != null) {
for(IResource r:models) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
if(id instanceof Model)
{
projectModels.add((Model)id);
}
}
catch(Exception ex) { }
}
}
return projectModels;
}
private List<Model> getModels (List<Model> parentModel)
{
List<Model> modelsCollector = new ArrayList<Model>();
for (Model model : parentModel)
{
List<Model> models = getModels(model.getModels());
modelsCollector.addAll(models);
}
parentModel.addAll(modelsCollector);
return parentModel;
}
private void saveModel (Model model, IProject project, Map<URI,URI> orig2newModelURI)
{
URI modelURI = model.getURI();
URI newModelURI = URI.createPlatformResourceURI
(project.getName() + "/models/" + modelURI.lastSegment());
orig2newModelURI.put(modelURI, newModelURI);
if (!newModelURI.equals(modelURI) )
{ ArrayList<Identifiable> newlist = new ArrayList<Identifiable>();
Identifiable modelCopy = (Model) EcoreUtil.copy(model);
modelCopy.setURI(newModelURI);
newlist.add(modelCopy);
try {
Utility.serializeIdentifiables(newlist, newModelURI);
}
catch (Exception ex) { Activator.logError(ex.getMessage(), ex);
}
}
}
private void updateModelReferenceAndSave(Model model, IProject project, Map<URI,URI> orig2newGraphURI, Map<URI,URI> orig2newModelURI)
{
try {
URI modelURI = model.getURI();
for (org.eclipse.stem.core.graph.Graph graph : model.getGraphs())
{
URI graphURI = graph.getURI();
if (orig2newGraphURI.containsKey(graphURI))
{
if(!graphURI.equals(orig2newGraphURI.get(graphURI)))
{
graph.setURI(orig2newGraphURI.get(graphURI));
}
}
}
for (Model childModel : model.getModels())
{
URI childModelURI = childModel.getURI();
if (orig2newModelURI.containsKey(childModelURI))
{
if(!childModelURI.equals(orig2newModelURI.get(childModelURI)))
{
childModel.setURI(orig2newModelURI.get(childModelURI));
}
}
}
URI newModelURI = URI.createPlatformResourceURI
(project.getName() + "/models/" + modelURI.lastSegment());
//TODO virgin test?
{ ArrayList<Identifiable> newlist = new ArrayList<Identifiable>();
Identifiable modelCopy = (Identifiable) EcoreUtil.copy(model);
modelCopy.setURI(newModelURI);
newlist.add(modelCopy);
Utility.serializeIdentifiables(newlist, newModelURI);
}
} catch(Exception e) { Activator.logError(e.getMessage(), e); }
}
private void clean(List<org.eclipse.stem.core.graph.Graph> graphList, IProject project)
{
/*
zoomFactor = 1.0;
ZOOMING_FACTOR = 1.1;
UNZOOMING_FACTOR = 1 / ZOOMING_FACTOR;
offsetX=0;
offsetY=0;
scaleFactor=0;
lastOffsetX=0;
lastOffsetY=0;
leftMouseButtonPressed=false;
xTranslation = 0.0;
yTranslation = 0.0;
maxLT=Double.NEGATIVE_INFINITY;
maxLG=Double.NEGATIVE_INFINITY;
minLT=Double.MAX_VALUE;
minLG=Double.MAX_VALUE;
zestGraphBounds = null;
graphBounds = null;
polygonsToDraw = new ArrayList<DisplayPolygon>();
GraphNodes = new HashMap<String, GraphNode>();
GraphConnections = new HashMap<String, GraphConnection>();
centers = new ArrayList<double[]>();
nodeID2Poly = new HashMap<String, Set<DisplayPolygon>>();
nodeURI2Label = new HashMap<URI,List<org.eclipse.stem.core.graph.NodeLabel>>();
*/
/*
for (org.eclipse.stem.core.graph.Graph graph : graphList)
{
EMap<URI,Node> nodeList = graph.getNodes();
for (Map.Entry<URI,Node> entry : nodeList.entrySet())
{
URI uri = entry.getKey();
Node node = entry.getValue();
EList<Adapter> adapterList = node.eAdapters();
node.eAdapters().removeAll(node.eAdapters());
String a = "";
}
}
List<URI> graphURIs = new ArrayList<URI>();
for (org.eclipse.stem.core.graph.Graph graph : graphList)
{
graphURIs.add(graph.getURI());
}
graphList = new ArrayList<org.eclipse.stem.core.graph.Graph>();
*/
IContainer graphsFolder = project.getFolder("graphs");
IResource[] graphs = null;
try {
graphs = graphsFolder.members();
} catch(Exception e) {
e.printStackTrace();
}
if (graphs != null) {
for(IResource r:graphs) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
if (id instanceof org.eclipse.stem.core.graph.Graph)
{
/*if (graphURIs.contains( ((org.eclipse.stem.core.graph.Graph)id).getURI()))
{
graphList.add((org.eclipse.stem.core.graph.Graph)id);
System.err.println("Add graph " + ((org.eclipse.stem.core.graph.Graph)id).getURI());
}*/
org.eclipse.stem.core.graph.Graph graph = (org.eclipse.stem.core.graph.Graph) id;
for (Map.Entry<URI,Node> entry : graph.getNodes().entrySet())
{
URI nodeURI = entry.getKey();
Node node = entry.getValue();
if (node.eContainer().eIsProxy())
{
EcoreUtil.resolve(node, (EObject) node);
}
for (NodeLabel label : node.getLabels())
{
if (label.eContainer().eIsProxy())
{
EcoreUtil.resolve(label, (EObject) label);
}
}
}
}
} catch(Exception e) {
// Skip bad file
}
}
}
/*
IContainer modelsFolder = project.getFolder("models");
IResource[] models = null;
try {
models = modelsFolder.members();
} catch(Exception e) {
e.printStackTrace();
}
if (models != null) {
for(IResource r:models) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
if (id instanceof Model)
{
for (org.eclipse.stem.core.graph.Graph graph : ((Model)id).getGraphs())
if (graphURIs.contains( graph.getURI()))
{
if (!graphList.contains(graph.getURI()))
{
graphList.add((org.eclipse.stem.core.graph.Graph)id);
System.err.println("Add graph " + ((org.eclipse.stem.core.graph.Graph)id).getURI());
}
}
}
} catch(Exception e) {
// Skip bad file
}
}
}
*/
}
/* maybe useful one day
private Map<String, Model> addProjectModels(Map<String, Model> projectModels, IProject project)
{
IFolder modelFolder = project.getFolder("models");
IResource[] models = null;
try {
models = modelFolder.members();
} catch(Exception e) {
Activator.logError(e.getMessage(), e);
}
if (models != null) {
for(IResource r:models) {
// ignore system files
if(r.getName().startsWith(".")) continue;
try {
URI uri = URI.createURI(r.getLocationURI().toString());
Identifiable id = Utility.getIdentifiable(uri);
if(id instanceof Model)
{ Model model = (Model)id;
projectModels.put(model.getURI().lastSegment(), model);
}
}
catch(Exception ex) {
Activator.logError(ex.getMessage(), ex);
}
}
}
return projectModels;
}
private Map<String, Model> getModels (Map<String, Model> parentModels)
{
Map<String, Model> modelsCollector = new HashMap<String, Model>();
for (Map.Entry<String, Model> parentEntry : parentModels.entrySet())
{
Model parentModel = parentEntry.getValue();
Map<String, Model> childModelsListMap = new HashMap<String, Model>();
List<Model> childModelsList = parentModel.getModels();
//transform to map
for (Model childModel : childModelsList)
{
childModelsListMap.put(childModel.getURI().lastSegment(), childModel);
}
Map<String, Model> childModelsListMap2 = getModels(childModelsListMap);
for (Map.Entry<String, Model> entry : childModelsListMap2.entrySet())
{
Model model = entry.getValue();
modelsCollector.put(model.getURI().lastSegment(), model);
}
}
for (Map.Entry<String, Model> entry : modelsCollector.entrySet())
{
Model model = entry.getValue();
String key = entry.getKey();
parentModels.put(key, model);
}
return parentModels;
}
public void output(Model model)
{
System.err.println(model.getURI());
for (org.eclipse.stem.core.graph.Graph graph : model.getGraphs())
{
System.err.println("---->" + graph.getURI());
}
}
*/
} //end of graph canvas