/***************************************************************************** | |
* Copyright (c) 2016 CEA LIST. | |
* | |
* | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* David LOPEZ BETANCUR (CEA LIST) | |
* Sebastien REVOL (CEA LIST) | |
* | |
*****************************************************************************/ | |
package org.eclipse.papyrus.moka.xygraph.mapping.common; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.eclipse.emf.common.notify.Notification; | |
import org.eclipse.nebula.visualization.xygraph.figures.Axis; | |
import org.eclipse.nebula.visualization.xygraph.figures.IXYGraph; | |
import org.eclipse.nebula.visualization.xygraph.figures.Trace; | |
import org.eclipse.nebula.visualization.xygraph.figures.XYGraph; | |
import org.eclipse.nebula.visualization.xygraph.linearscale.Range; | |
import org.eclipse.papyrus.moka.xygraph.mapping.util.BaseAxisListener; | |
import org.eclipse.papyrus.moka.xygraph.mapping.util.TraceDataBounds; | |
import org.eclipse.papyrus.moka.xygraph.mapping.writing.ModelWritingStrategyFactory; | |
import org.eclipse.papyrus.moka.xygraph.model.xygraph.AxisDescriptor; | |
import org.eclipse.papyrus.moka.xygraph.model.xygraph.TraceDescriptor; | |
import org.eclipse.papyrus.moka.xygraph.model.xygraph.XYGraphDescriptor; | |
import org.eclipse.papyrus.moka.xygraph.model.xygraph.XYGraphPackage; | |
public class XYGraphCoordinator{ | |
protected XYGraphBinder graphMap; | |
protected ModelWritingStrategyFactory factory; | |
private List<XYGraphListener> listeners = new ArrayList<XYGraphListener>(); | |
public XYGraphCoordinator(XYGraphBinder binder, ModelWritingStrategyFactory factory){ | |
this.graphMap = binder; | |
this.factory = factory; | |
} | |
public void updateDescriptors(XYGraph xy){ | |
factory.getXYGraphUpdateStrategy().updateXYGraph(xy, graphMap); | |
for( Axis axis : graphMap.getAxes()) | |
factory.getAxisUpdateStrategy().updateAxisDescriptor(axis, graphMap); | |
for( Trace trace: graphMap.getTraces() ) | |
factory.getTraceUpdateStrategy().updateTraceDescriptor(trace, graphMap); | |
onXYGraphUpdated(); | |
} | |
protected void onXYGraphUpdated() { | |
fireXYGraphUpdated(graphMap.getXYGraphDescriptor()); | |
} | |
public IXYGraph buildXYGraph(){ | |
//1. Axes first (Primary axes are required for the xyGraph) | |
factory.getAxisBuildStrategy().rebuildAxes(graphMap); | |
//2. Build the xyGraph | |
IXYGraph xy = factory.getXYGraphBuildStrategy().buildGraph(graphMap); | |
XYGraphDescriptor gDesc = graphMap.getXYGraphDescriptor(); | |
//2.1. The axes need the graph before the traces. | |
for( AxisDescriptor aDesc : gDesc.getAxisDescriptors() ){ | |
Axis axis = graphMap.getAxisFor(aDesc); | |
//Listen range changes | |
axis.addListener(new BaseAxisListener(){ | |
@Override | |
public void axisRangeChanged(Axis axis, Range old_range, Range new_range) { | |
onAxisRangeChanged( axis, old_range, new_range ); | |
} | |
}); | |
if( graphMap.isPrimary(aDesc) ) | |
continue; | |
xy.addAxis(axis); | |
} | |
//3. Build and add the traces | |
factory.getTraceBuildStrategy().rebuildTraces(graphMap); | |
for( TraceDescriptor tDesc : gDesc.getTraceDescriptors() ) | |
xy.addTrace(graphMap.getTraceFor(tDesc)); | |
onXYGraphBuilt(); | |
return xy; | |
} | |
protected void onXYGraphBuilt(){ | |
fireXYGraphBuilt(graphMap.getXYGraphDescriptor()); | |
} | |
public XYGraphDescriptor getXYGraphDescriptor(){ | |
return graphMap.getXYGraphDescriptor(); | |
} | |
public void addXYGraphListener( XYGraphListener listener ){ | |
listeners.add(listener); | |
} | |
protected void fireXYGraphUpdated(XYGraphDescriptor xyGraph){ | |
for( XYGraphListener listener : listeners ) | |
listener.onXYGraphUpdated(this, xyGraph); | |
} | |
protected void fireXYGraphBuilt(XYGraphDescriptor xyGraph) { | |
for( XYGraphListener listener : listeners ) | |
listener.onXYGraphBuilt(this, xyGraph); | |
} | |
public void synchronizeTracesVisibility(){ | |
XYGraphDescriptor xyDesc = graphMap.getXYGraphDescriptor(); | |
List<TraceDescriptor> visibles = xyDesc.getVisibleTraces(); | |
//Make the newly added traces visible? | |
factory.getTraceBuildStrategy().rebuildTraces(graphMap); | |
for( TraceDescriptor tDesc : graphMap.getTraceDescriptors() ){ | |
if( visibles.contains(tDesc) ) | |
showTrace(graphMap.getXYGraph(), graphMap.getTraceFor(tDesc)); | |
else | |
hideTrace(graphMap.getXYGraph(), graphMap.getTraceFor(tDesc)); | |
} | |
} | |
protected void addNewTrace( TraceDescriptor tDesc, boolean visible ){ | |
XYGraphDescriptor xy = graphMap.getXYGraphDescriptor(); | |
//Add the trace descriptor. | |
xy.getTraceDescriptors().add(tDesc); | |
//Rebuild the traces | |
factory.getTraceBuildStrategy().rebuildTraces(graphMap); | |
if( visible ){ | |
xy.getVisibleTraces().add( tDesc ); | |
showTrace(graphMap.getXYGraph(), graphMap.getTraceFor(tDesc)); | |
} | |
} | |
protected void removeTrace( TraceDescriptor tDesc ){ | |
//Remove it from the visibles | |
XYGraphDescriptor xy = graphMap.getXYGraphDescriptor(); | |
xy.getVisibleTraces().remove(tDesc); | |
//Unbind it | |
Trace trace = graphMap.unbindTrace(tDesc); | |
//Hide it | |
hideTrace(graphMap.getXYGraph(), trace); | |
} | |
private void hideTrace(XYGraph graph, Trace trace){ | |
//Only remove it if contained | |
if( graph.getPlotArea().getChildren().contains(trace) ){ | |
graph.removeTrace(trace); | |
} | |
} | |
private void showTrace(XYGraph graph, Trace trace){ | |
//Only add it if not contained | |
if( !graph.getPlotArea().getChildren().contains(trace) ){ | |
graph.addTrace(trace); | |
} | |
} | |
public void onModelUpdate(Notification notification) { | |
//System.out.println(notification.getFeature()); | |
if( XYGraphPackage.eINSTANCE.getXYGraphDescriptor_VisibleTraces().equals(notification.getFeature()) ){ | |
synchronizeTracesVisibility(); | |
} | |
//Apply the changes to the XYGraph (Figure) | |
//Currently manual, we might want to change everything later? | |
if( XYGraphPackage.eINSTANCE.getXYGraphDescriptor_Title().equals(notification.getFeature()) ){ | |
graphMap.getXYGraph().setTitle(notification.getNewStringValue()); | |
} | |
} | |
protected void onAxisRangeChanged(Axis axis, Range old_range, Range new_range) { | |
AxisDescriptor aDesc = graphMap.getDescriptorFor(axis); | |
//aDesc.setRangeLower(new_range.getLower()); | |
//aDesc.setRangeUpper(new_range.getUpper()); | |
//Update the range in the axis? | |
factory.getAxisUpdateStrategy().updateAxisDescriptor(axis, graphMap); | |
System.out.println("Updated axis Range: " + aDesc.getRangeLower() + ", " + aDesc.getRangeUpper()); | |
} | |
public void dispose() { | |
graphMap.dispose(); | |
} | |
public void rescaleAxesIfNeeded(){ | |
AxisDescriptor xPrimary = graphMap.getDescriptorFor(graphMap.getXAxisPrimary()); | |
AxisDescriptor yPrimary = graphMap.getDescriptorFor(graphMap.getYAxisPrimary()); | |
if( xPrimary.getRangeLower() < xPrimary.getRangeUpper() && yPrimary.getRangeLower() < yPrimary.getRangeUpper() ) | |
return; //not needed. | |
forceAxesRescale(); | |
} | |
public void forceAxesRescale(){ | |
//System.out.println("Forcing re-scale"); | |
TraceDataBounds dataBounds = new TraceDataBounds(); | |
for( TraceDescriptor tDesc : graphMap.getTraceDescriptors() ) | |
dataBounds.union( graphMap.getTraceDataBounds(tDesc) ); | |
graphMap.getXAxisPrimary().setRange(dataBounds.getxMin(), dataBounds.getxMax()); | |
graphMap.getYAxisPrimary().setRange(dataBounds.getyMin(), dataBounds.getyMax()); | |
factory.getAxisUpdateStrategy().updateAxisDescriptor(graphMap.getXAxisPrimary(), graphMap); | |
factory.getAxisUpdateStrategy().updateAxisDescriptor(graphMap.getYAxisPrimary(), graphMap); | |
} | |
} |