Bug 354549 timing problems in ChartView
diff --git a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/src/org/eclipse/amp/agf/chart/ChartEditPart.java b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/src/org/eclipse/amp/agf/chart/ChartEditPart.java
index d706c3a..c207c9c 100644
--- a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/src/org/eclipse/amp/agf/chart/ChartEditPart.java
+++ b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/src/org/eclipse/amp/agf/chart/ChartEditPart.java
@@ -49,6 +49,7 @@
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.common.util.EList;
+import org.eclipse.gef.EditPart;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.swt.events.DisposeEvent;
@@ -90,6 +91,7 @@
* Instantiates a new chart edit part.
*/
public ChartEditPart() {
+ chartStrategy = getInitStrategie();
resourceManager = new ResourceManager();
PlatformConfig config = new PlatformConfig();
try {
@@ -102,6 +104,10 @@
genericPalette.shift(0);
}
+ IChartDesignStrategy getInitStrategie() {
+ return ChartType.TIME_SERIES.createStrategy();
+ }
+
/**
* The listener interface for receiving chartModel events. The class that is
* interested in processing a chartModel event implements this interface, and
@@ -113,6 +119,7 @@
* @see ChartModelEvent
*/
class ChartModelListener extends SWTAsyncModelListener {
+
/**
* Instantiates a new chart model listener.
*/
@@ -122,15 +129,7 @@
@Override
public void observing(IObservationProvider observed) {
- // wait for data source to be available from model set..
- while (getDataProvider() == null) {
- try {
- Thread.sleep(25);
- } catch (InterruptedException e) {
- //
- }
- }
- setChartStrategy(ChartType.TIME_SERIES.createStrategy());
+ setChartStrategy(getInitStrategie());
}
@Override
@@ -201,6 +200,7 @@
chartListener.setWidget(getViewer().getControl());
final Figure newFigure = new Figure() {
+
@Override
public void paintFigure(Graphics graphics) {
if (getResourceManager().getImage() != null) {
@@ -212,6 +212,7 @@
}
};
newFigure.setLayoutManager(new AbstractLayout() {
+
@Override
public Dimension getMinimumSize(IFigure container, int hintWidth, int hintHeight) {
return new Dimension(hintWidth < 1 ? 1 : hintWidth, hintHeight < 1 ? 1 : hintHeight);
@@ -227,6 +228,7 @@
}
});
newFigure.addFigureListener(new FigureListener() {
+
public void figureMoved(IFigure source) {
regenerateChart();
}
@@ -242,12 +244,7 @@
@Override
public void refresh() {
- new Thread() {
- @Override
- public void run() {
- regenerateChart(true);
- }
- }.run();
+ regenerateChart(true);
}
@Override
@@ -261,7 +258,9 @@
Object provider = adapterManager.loadAdapter(this.getModel(), IDataProvider.ID);
if (!(provider instanceof IDataProvider)) {
- throw new RuntimeException("Couldn't find data provider for chart model. Please ensure that a data provider adapter has been defined for the class: " + this.getModel().getClass());
+ throw new RuntimeException(
+ "Couldn't find data provider for chart model. Please ensure that a data provider adapter has been defined for the class: "
+ + this.getModel().getClass());
}
setDataProvider((IDataProvider) provider);
@@ -306,7 +305,8 @@
chartListener.endPainting();
}
} catch (ChartException ce) {
- StatusManager.getManager().handle(new Status(Status.WARNING, AGFChartPlugin.PLUGIN_ID, "Couldn't generate chart.", ce));
+ StatusManager.getManager().handle(
+ new Status(Status.WARNING, AGFChartPlugin.PLUGIN_ID, "Couldn't generate chart.", ce));
chartListener.endPainting();
}
}
@@ -325,14 +325,6 @@
}
/**
- * Creates the chart.
- */
- public synchronized void createChart() {
- chart = chartStrategy.createChart(dataProvider, dataSource);
- chart.getTitle().getLabel().setVisible(false);
- }
-
- /**
* Update chart series.
*/
public synchronized void updateChartSelection() {
@@ -387,8 +379,7 @@
/**
*
- * @see org.eclipse.birt.chart.device.ICallBackNotifier#callback(java.lang.Object,
- * java.lang.Object,
+ * @see org.eclipse.birt.chart.device.ICallBackNotifier#callback(java.lang.Object, java.lang.Object,
* org.eclipse.birt.chart.model.attribute.CallBackValue)
*/
public void callback(Object arg0, Object arg1, CallBackValue arg2) {
@@ -447,10 +438,12 @@
this.dataProvider = dataProvider;
dataSource = dataProvider.getDataSource(getModel());
dataListener = new IDataSelectionListener() {
+
public void selectionChanged(Object dataSet) {
if (getParent() != null && getRoot() != null && getViewer() != null && getChart() != null) {
updateChartSelection();
getViewer().getControl().getDisplay().asyncExec(new Runnable() {
+
public void run() {
regenerateChart(true);
}
@@ -459,14 +452,24 @@
}
};
dataProvider.addListener(dataSource, dataListener);
+ createAndInitChart();
}
public void setChartStrategy(IChartDesignStrategy chartStrategy) {
this.chartStrategy = chartStrategy;
- createChart();
+ createAndInitChart();
+ }
+
+ private void createAndInitChart() {
+ if(dataProvider == null){
+ return;
+ }
+ chart = chartStrategy.createChart(dataProvider, dataSource);
+ chart.getTitle().getLabel().setVisible(false);
updateChartSelection();
- if (getViewer().getControl().getDisplay() != null) {
+ if (getViewer() != null && getViewer().getControl() != null && !getViewer().getControl().isDisposed()) {
getViewer().getControl().getDisplay().asyncExec(new Runnable() {
+
public void run() {
repaintChart();
}
@@ -493,6 +496,7 @@
* @author fei
*/
public class ResourceManager implements DisposeListener {
+
private GC gc;
private Image image;
@@ -530,7 +534,8 @@
private void addDisposeListener() {
removeDisposeListener();
- if (disposeEventProvider == null && getViewer() != null && getViewer().getControl() != null && !getViewer().getControl().isDisposed()) {
+ if (disposeEventProvider == null && getViewer() != null && getViewer().getControl() != null
+ && !getViewer().getControl().isDisposed()) {
disposeEventProvider = getViewer().getControl();
disposeEventProvider.addDisposeListener(this);
}
diff --git a/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.ide/src/org/eclipse/amp/axf/ide/view/ScaleGranularityControl.java b/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.ide/src/org/eclipse/amp/axf/ide/view/ScaleGranularityControl.java
index a4cbeb8..28ed94c 100644
--- a/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.ide/src/org/eclipse/amp/axf/ide/view/ScaleGranularityControl.java
+++ b/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.ide/src/org/eclipse/amp/axf/ide/view/ScaleGranularityControl.java
@@ -64,7 +64,12 @@
}
});
- ModelViewManager.getInstance().getManagerListeners().addModelManagerListener(ScaleGranularityControl.this);
+ IModel activeModel = ModelViewManager.getInstance().getActiveModel();
+ if (activeModel != null) {
+ engine = activeModel.getEngine();
+ }
+
+ ModelViewManager.getInstance().getManagerListeners().addModelManagerListener(this);
return scale;
}
diff --git a/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.views/src/org/eclipse/amp/axf/view/SWTAsyncModelListener.java b/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.views/src/org/eclipse/amp/axf/view/SWTAsyncModelListener.java
index cb57ee0..ab6c150 100644
--- a/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.views/src/org/eclipse/amp/axf/view/SWTAsyncModelListener.java
+++ b/org.eclipse.amp.axf/plugins/org.eclipse.amp.axf.views/src/org/eclipse/amp/axf/view/SWTAsyncModelListener.java
@@ -15,6 +15,9 @@
*/
package org.eclipse.amp.axf.view;
+import java.util.ArrayList;
+import java.util.List;
+
import org.eclipse.amp.axf.core.IModel;
import org.eclipse.amp.axf.core.LifeCycleState;
import org.eclipse.amp.axf.time.TimeGranularity;
@@ -33,155 +36,161 @@
*/
public abstract class SWTAsyncModelListener extends SWTThreadModelListener {
- private final class ReportingRunner implements Runnable {
- private final LifeCycleState key;
- private final IModel model;
- Exception t;
+ private List<ReportingRunner> reportingRunners;
- public ReportingRunner(LifeCycleState key, IModel model) {
- this.key = key;
- this.model = model;
- }
+ private boolean waitForPaint = true;
- public void run() {
- try {
- doUpdate(key, model);
- } catch (Exception e) {
- t = e;
- } finally {
- updating = false;
- if (t != null) {
- painting = false;
- t.printStackTrace();
- throw new RuntimeException("Problem in view updating for " + getName(), t);
- }
- }
- }
- }
+ private long minTimeBetweenUpdates = 10000;
- private boolean waitForPaint = true;
+ protected boolean updating = false;
- private long minTimeBetweenUpdates = 10000;
+ private boolean painting = false;
- protected boolean updating = false;
+ private long lastUpdate;
- private boolean painting = false;
+ /**
+ * Instantiates a new sWT async model listener.
+ *
+ * @param widget the widget
+ * @param name the name
+ */
+ public SWTAsyncModelListener(Control widget, String name) {
+ super(widget, name);
+ reportingRunners = new ArrayList<SWTAsyncModelListener.ReportingRunner>();
+ }
- private long lastUpdate;
+ /**
+ * Instantiates a new sWT async model listener.
+ *
+ * @param widget the widget
+ * @param name the name
+ * @param updatePeriod the update period
+ */
+ public SWTAsyncModelListener(Control widget, String name, long updatePeriod) {
+ this(widget, name);
+ this.minTimeBetweenUpdates = updatePeriod;
+ }
- /**
- * Instantiates a new sWT async model listener.
- *
- * @param widget the widget
- * @param name the name
- */
- public SWTAsyncModelListener(Control widget, String name) {
- super(widget, name);
- }
+ List<ReportingRunner> getReportingRunners() {
+ return reportingRunners;
+ }
- /**
- * Instantiates a new sWT async model listener.
- *
- * @param widget the widget
- * @param name the name
- * @param updatePeriod the update period
- */
- public SWTAsyncModelListener(Control widget, String name, long updatePeriod) {
- super(widget, name);
- this.minTimeBetweenUpdates = updatePeriod;
- }
+ /**
+ * @param key
+ * @param observed
+ * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#stateChange(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public void stateChange(Object key, Object observed) {
+ IModel model = (IModel) observed;
+ if (model.getEngine().isRunning()
+ && (System.currentTimeMillis() > lastUpdate + minTimeBetweenUpdates || model.getPeriod()
+ % ((TimeGranularity) model.getEngine().getUpdateGranularity()).getUpdateFrequency() == 0)) {
+ lastUpdate = System.currentTimeMillis();
+ updating = true;
+ if (AXFViewPlugin.getDefault() != null) {
+ Display display = AXFViewPlugin.getDefault().getWorkbench().getDisplay();
+ if (!display.isDisposed()) {
+ ReportingRunner runnable = new ReportingRunner((LifeCycleState) key, model);
+ reportingRunners.add(runnable);
+ display.asyncExec(runnable);
- /**
- * @param key
- * @param observed
- * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#stateChange(java.lang.Object, java.lang.Object)
- */
- @Override
- public void stateChange(Object key, Object observed) {
- IModel model = (IModel) observed;
- if (model.getEngine().isRunning()
- && (System.currentTimeMillis() > lastUpdate + minTimeBetweenUpdates || model.getPeriod()
- % ((TimeGranularity) model.getEngine().getUpdateGranularity()).getUpdateFrequency() == 0)) {
- lastUpdate = System.currentTimeMillis();
- updating = true;
- ReportingRunner runnable = new ReportingRunner((LifeCycleState) key, model);
- if (AXFViewPlugin.getDefault() != null) {
- Display display = AXFViewPlugin.getDefault().getWorkbench().getDisplay();
- if (!display.isDisposed()) {
- display.asyncExec(runnable);
- while ((updating || painting) && isWaitForUpdate()
- && (getWidget() == null || !getWidget().isDisposed())) {
- try {
- // Assume best case of 60fps + allow compute
- Thread.sleep(5);
- } catch (InterruptedException e) {
- }
- }
- }
- }
- if (runnable.t != null) {
- runnable.t.printStackTrace();
- }
- } else if (key == LifeCycleState.OBSERVED || key == LifeCycleState.END) {
- SWTAsyncModelListener.super.stateChange(key, model);
- }
- // Even though model is not null on method entrance (state change), it could become null during execution of
- // reporting runner
- if (model != null) {
- forceModelNotify(model);
- }
- }
+ }
+ }
+ } else if (key == LifeCycleState.OBSERVED || key == LifeCycleState.END) {
+ SWTAsyncModelListener.super.stateChange(key, model);
+ }
+ // Even though model is not null on method entrance (state change), it could become null during execution of
+ // reporting runner
+ if (model != null) {
+ forceModelNotify(model);
+ }
+ }
- private void doUpdate(Object key, final IModel model) {
- // Have to check visibility within UI thread
- if (getWidget() == null || !getWidget().isDisposed() && getWidget().isVisible()) {
- update(model);
- getListener().stateChange(key, model);
- }
- // If the update method hasn't explicitly indicated beginPainting, we are not waiting for the
- // actual update or it has already occurred.
- if (!painting) {
- }
- }
+ private void doUpdate(Object key, final IModel model) {
+ // Have to check visibility within UI thread
+ if (getWidget() == null || !getWidget().isDisposed() && getWidget().isVisible()) {
+ update(model);
+ getListener().stateChange(key, model);
+ }
+ // If the update method hasn't explicitly indicated beginPainting, we are not waiting for the
+ // actual update or it has already occurred.
+ if (!painting) {
+ }
+ }
- /**
- * Force model notify.
- *
- * @param model the model
- */
- public void forceModelNotify(IModel model) {
- model.getEngine().observationComplete(this);
- }
+ /**
+ * Force model notify.
+ *
+ * @param model the model
+ */
+ public void forceModelNotify(IModel model) {
+ model.getEngine().observationComplete(this);
+ }
- /**
- * Begin painting.
- */
- public void beginPainting() {
- this.painting = true;
- }
+ /**
+ * Begin painting.
+ */
+ public void beginPainting() {
+ this.painting = true;
+ }
- /**
- * End painting.
- */
- public void endPainting() {
- this.painting = false;
- }
+ /**
+ * End painting.
+ */
+ public void endPainting() {
+ this.painting = false;
+ }
- /**
- * Sets the wait for paint.
- *
- * @param waitForPaint the new wait for paint
- */
- public void setWaitForUpdate(boolean waitForPaint) {
- this.waitForPaint = waitForPaint;
- }
+ /**
+ * Sets the wait for paint.
+ *
+ * @param waitForPaint the new wait for paint
+ */
+ public void setWaitForUpdate(boolean waitForPaint) {
+ this.waitForPaint = waitForPaint;
+ }
- /**
- * Checks if is wait for paint.
- *
- * @return true, if is wait for paint
- */
- public boolean isWaitForUpdate() {
- return waitForPaint;
- }
+ /**
+ * Checks if is wait for paint.
+ *
+ * @return true, if is wait for paint
+ */
+ public boolean isWaitForUpdate() {
+ return waitForPaint;
+ }
+
+ private final class ReportingRunner implements Runnable {
+
+ private final LifeCycleState key;
+
+ private final IModel model;
+
+ Exception t;
+
+ public ReportingRunner(LifeCycleState key, IModel model) {
+ this.key = key;
+ this.model = model;
+ }
+
+ public void run() {
+ try {
+ if (reportingRunners.size() > 1) {
+ return;
+ }
+ doUpdate(key, model);
+ } catch (Exception e) {
+ t = e;
+ } finally {
+ reportingRunners.remove(this);
+ updating = false;
+ if (t != null) {
+ painting = false;
+ t.printStackTrace();
+ throw new RuntimeException("Problem in view updating for " + getName(), t);
+ }
+ }
+ }
+ }
+
}
diff --git a/org.eclipse.amp.escape/plugins/org.eclipse.amp.escape.ascape/src/org/eclipse/amp/escape/ascape/wrap/ScapeWrapperModel.java b/org.eclipse.amp.escape/plugins/org.eclipse.amp.escape.ascape/src/org/eclipse/amp/escape/ascape/wrap/ScapeWrapperModel.java
index 022d4af..e8c2d09 100644
--- a/org.eclipse.amp.escape/plugins/org.eclipse.amp.escape.ascape/src/org/eclipse/amp/escape/ascape/wrap/ScapeWrapperModel.java
+++ b/org.eclipse.amp.escape/plugins/org.eclipse.amp.escape.ascape/src/org/eclipse/amp/escape/ascape/wrap/ScapeWrapperModel.java
@@ -71,17 +71,12 @@
}
public void addModelListener(final ILifeCycleListener listener) {
- new Thread() {
- @Override
- public void run() {
- listeners.add(listener);
- if (!(listener instanceof ScapeWrapperModelListener)) {
- ModelWrapperScapeListener wrapper = new ModelWrapperScapeListener(ScapeWrapperModel.this, getScape(), listener);
- getScape().addView(wrapper);
- wrapperForListener.put(listener, wrapper);
- }
- }
- }.start();
+ listeners.add(listener);
+ if (!(listener instanceof ScapeWrapperModelListener)) {
+ ModelWrapperScapeListener wrapper = new ModelWrapperScapeListener(ScapeWrapperModel.this, getScape(), listener);
+ getScape().addView(wrapper);
+ wrapperForListener.put(listener, wrapper);
+ }
}
public Collection<ILifeCycleListener> getModelListeners() {
@@ -89,16 +84,11 @@
}
public void removeModelListener(final ILifeCycleListener listener) {
- new Thread() {
- @Override
- public void run() {
- listeners.remove(listener);
- if (listener instanceof ScapeWrapperModelListener) {
- getScape().removeScapeListener(((ScapeWrapperModelListener) listener).getWrapped());
- }
- listener.observationEnd(ScapeWrapperModel.this);
- }
- }.start();
+ listeners.remove(listener);
+ if (listener instanceof ScapeWrapperModelListener) {
+ getScape().removeScapeListener(((ScapeWrapperModelListener) listener).getWrapped());
+ }
+ listener.observationEnd(ScapeWrapperModel.this);
}
public boolean isInitialized() {
diff --git a/org.eclipse.amp.escape/tests/org.eclipse.amp.escape.ide.test/src/org/eclipse/amp/escape/ide/ProjectLoaderTest.java b/org.eclipse.amp.escape/tests/org.eclipse.amp.escape.ide.test/src/org/eclipse/amp/escape/ide/ProjectLoaderTest.java
index 9c3ac80..e4e07e1 100644
--- a/org.eclipse.amp.escape/tests/org.eclipse.amp.escape.ide.test/src/org/eclipse/amp/escape/ide/ProjectLoaderTest.java
+++ b/org.eclipse.amp.escape/tests/org.eclipse.amp.escape.ide.test/src/org/eclipse/amp/escape/ide/ProjectLoaderTest.java
@@ -6,8 +6,12 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
import java.util.List;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.junit.Test;
import org.osgi.framework.Bundle;
@@ -31,7 +35,7 @@
*/
@Test
public void testReadDependencies() throws IllegalStateException, FileNotFoundException, BundleException, IOException {
- List<Bundle> dependencies = ProjectLoader.readDependencies(new FileInputStream("testFiles/defaultManifest.MF"));
+ List<Bundle> dependencies = ProjectLoader.readDependencies(getInputStream("defaultManifest.MF"));
assertEquals(8, dependencies.size());
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.resources")));
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.runtime")));
@@ -53,7 +57,7 @@
*/
@Test
public void testReadDependencies_optionalBundles() throws IllegalStateException, FileNotFoundException, BundleException, IOException {
- List<Bundle> dependencies = ProjectLoader.readDependencies(new FileInputStream("testFiles/optionalBundles.MF"));
+ List<Bundle> dependencies = ProjectLoader.readDependencies(getInputStream("optionalBundles.MF"));
assertEquals(8, dependencies.size());
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.resources")));
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.runtime")));
@@ -77,7 +81,7 @@
*/
@Test
public void testReadDependencies_bundleUnavalilableButOptional() throws IllegalStateException, FileNotFoundException, BundleException, IOException {
- List<Bundle> dependencies = ProjectLoader.readDependencies(new FileInputStream("testFiles/bundleUnavalilableButOptional.MF"));
+ List<Bundle> dependencies = ProjectLoader.readDependencies(getInputStream("bundleUnavalilableButOptional.MF"));
assertEquals(8, dependencies.size());
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.resources")));
assertTrue(dependencies.contains(Platform.getBundle("org.eclipse.core.runtime")));
@@ -101,7 +105,12 @@
*/
@Test(expected = IllegalStateException.class)
public void testReadDependencies_bundleUnavailableButNecessary() throws IllegalStateException, FileNotFoundException, BundleException, IOException {
- ProjectLoader.readDependencies(new FileInputStream("testFiles/bundleUnavailableButNecessary.MF"));
+ ProjectLoader.readDependencies(getInputStream("bundleUnavailableButNecessary.MF"));
}
+ private InputStream getInputStream(String fileName) throws IOException{
+ URL[] url = FileLocator.findEntries(EscapeIDEPlugin.getDefault().getBundle(), new Path("testFiles/"+fileName));
+ assert url.length == 1 : "Es wurde nicht genau einen Pfad gefunden. Erwartet wurde der Pfad für das:testFiles/" + fileName;
+ return url[0].openStream();
+ }
}