Bug 350925
diff --git a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/.classpath b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/.classpath
index 64c5e31..f3b093b 100644
--- a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/.classpath
+++ b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/.classpath
@@ -3,5 +3,6 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="test"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/META-INF/MANIFEST.MF b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/META-INF/MANIFEST.MF
index 29e4091..c38de51 100644
--- a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/META-INF/MANIFEST.MF
+++ b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/META-INF/MANIFEST.MF
@@ -13,7 +13,9 @@
  org.eclipse.amp.axf.core,
  org.eclipse.amp.axf.views,
  org.eclipse.amp.agf.core,
- com.ibm.icu
+ com.ibm.icu,
+ org.junit;bundle-version="4.8.1",
+ org.junit4;bundle-version="4.8.1"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-ActivationPolicy: lazy
 Export-Package: 
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 62ed0f2..83b2500 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
@@ -15,11 +15,9 @@
  */
 package org.eclipse.amp.agf.chart;
 
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
 
+import org.eclipse.amp.agf.chart.ide.AGFChartPlugin;
 import org.eclipse.amp.axf.core.IModel;
 import org.eclipse.amp.axf.core.IObservationProvider;
 import org.eclipse.amp.axf.view.SWTAsyncModelListener;
@@ -30,7 +28,6 @@
 import org.eclipse.birt.chart.factory.GeneratedChartState;
 import org.eclipse.birt.chart.factory.Generator;
 import org.eclipse.birt.chart.factory.RunTimeContext;
-import org.eclipse.birt.chart.log.ILogger;
 import org.eclipse.birt.chart.model.Chart;
 import org.eclipse.birt.chart.model.attribute.Bounds;
 import org.eclipse.birt.chart.model.attribute.CallBackValue;
@@ -40,8 +37,6 @@
 import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
 import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
 import org.eclipse.birt.chart.model.attribute.impl.PaletteImpl;
-import org.eclipse.birt.chart.script.IChartScriptContext;
-import org.eclipse.birt.chart.script.IExternalContext;
 import org.eclipse.birt.core.framework.PlatformConfig;
 import org.eclipse.core.runtime.IAdapterManager;
 import org.eclipse.core.runtime.Platform;
@@ -56,535 +51,487 @@
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
 import org.eclipse.jface.viewers.IColorProvider;
-import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
 import org.eclipse.ui.statushandlers.StatusManager;
 
-import com.ibm.icu.util.ULocale;
-
-// TODO: Auto-generated Javadoc
-/**
- * The Class ChartEditPart.
- */
 public class ChartEditPart extends AbstractGraphicalEditPart implements ICallBackNotifier {
 
-    private static final long serialVersionUID = 1L;
+	private Chart chart;
 
-    private Chart chart;
+	private final ResourceManager resourceManager;
 
-    private IDeviceRenderer renderer;
+	private IDeviceRenderer renderer;
 
-    private GeneratedChartState chartState;
+	private GeneratedChartState chartState;
 
-    private IDataProvider dataProvider;
+	private IDataProvider dataProvider;
 
-    private IColorProvider seriesColorProvider;
+	private IColorProvider seriesColorProvider;
 
-    private Palette genericPalette;
+	private Palette genericPalette;
 
-    /**
-     * Sets the series color provider.
-     * 
-     * @param seriesColorProvider the new series color provider
-     */
-    public void setSeriesColorProvider(IColorProvider seriesColorProvider) {
-        this.seriesColorProvider = seriesColorProvider;
-    }
+	private Object dataSource;
 
-    private Object dataSource;
+	private ChartModelListener chartListener;
 
-    private GC imageGC;
+	private IDataSelectionListener dataListener;
 
-    private Image image;
+	private int nextOpenPaletteIndex;
 
-    private ChartModelListener chartListener;
+	private IChartDesignStrategy chartStrategy;
 
-    // private RunTimeContext rtc;
+	/**
+	 * Instantiates a new chart edit part.
+	 */
+	public ChartEditPart() {
+		resourceManager = new ResourceManager();
+		PlatformConfig config = new PlatformConfig();
+		try {
+			config.setProperty(IDeviceRenderer.UPDATE_NOTIFIER, this);
+			renderer = ChartEngine.instance(config).getRenderer("dv.SWT");
+		} catch (ChartException e) {
+			throw new RuntimeException(e);
+		}
+		genericPalette = PaletteImpl.create(0, true);
+		genericPalette.shift(0);
+	}
 
-    IFigure imageFigure;
+	/**
+	 * The listener interface for receiving chartModel events. The class that is interested in processing a chartModel
+	 * event implements this interface, and the object created with that class is registered with a component using the
+	 * component's <code>addChartModelListener<code> method. When
+	 * the chartModel event occurs, that object's appropriate
+	 * method is invoked.
+	 * 
+	 * @see ChartModelEvent
+	 */
+	class ChartModelListener extends SWTAsyncModelListener {
+		/**
+		 * Instantiates a new chart model listener.
+		 */
+		public ChartModelListener() {
+			super(null, "Chart Updated View", 10000);
+		}
 
-    Collection<NameColorPair> seriesCache = new HashSet<NameColorPair>();
+		@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());
+		}
 
-    private IDataSelectionListener dataListener;
+		@Override
+		public void observeStart(IObservationProvider observed) {
+			updateChartSelection();
+			endPainting();
+		}
 
-    private int nextOpenPaletteIndex;
+		@Override
+		public void observeInitialize(IObservationProvider model) {
+			getResourceManager().setImage(null);
+		}
 
-    /**
-     * Instantiates a new chart edit part.
-     */
-    public ChartEditPart() {
-        PlatformConfig config = new PlatformConfig();
-        try {
-            config.setProperty(IDeviceRenderer.UPDATE_NOTIFIER, this);
-            renderer = ChartEngine.instance(config).getRenderer("dv.SWT");
-        } catch (ChartException e) {
-            throw new RuntimeException(e);
-        }
-        genericPalette = PaletteImpl.create(0, true);
-        genericPalette.shift(0);
-    }
+		@Override
+		public void update(final IModel model) {
+			beginPainting();
+			getChartStrategy().update();
+			refresh();
+		}
 
-    /**
-     * The listener interface for receiving chartModel events. The class that is interested in processing a chartModel
-     * event implements this interface, and the object created with that class is registered with a component using the
-     * component's <code>addChartModelListener<code> method. When
-     * the chartModel event occurs, that object's appropriate
-     * method is invoked.
-     * 
-     * @see ChartModelEvent
-     */
-    class ChartModelListener extends SWTAsyncModelListener {
-        private static final long serialVersionUID = -6061682325662130469L;
+		@Override
+		public void observationEnd(IObservationProvider model) {
+			getDataProvider().removeListener(getDataSource(), getDataListener());
+			model = null;
+		}
 
-        /**
-         * Instantiates a new chart model listener.
-         */
-        public ChartModelListener() {
-            super(null, "Chart Updated View", 10000);
-        }
+	}
 
-        /**
-         * @param observed
-         * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#observing(org.eclipse.amp.axf.core.IObservationProvider)
-         */
-        public void observing(IObservationProvider observed) {
-            // wait for data source to be available from model set..
-            while (dataProvider == null) {
-                try {
-                    Thread.sleep(25);
-                } catch (InterruptedException e) {
-                }
-            }
-            setChartStrategy(ChartType.TIME_SERIES.createStrategy());
-            chartUpated = true;
-        }
+	private void updateValueSetColor(Object valueSet) {
+		String seriesLabel = dataProvider.getText(valueSet);
+		Color swtColor = seriesColorProvider.getForeground(seriesLabel);
+		EList<Fill> entries = chartStrategy.getValueSetsDefinition().getSeriesPalette().getEntries();
+		ColorDefinition cd = null;
+		if (swtColor == null) {
+			// List<Fill> palette = ySeriesDefinition.getSeriesPalette().getEntries();
+			// if (nextOpenPaletteIndex >= palette.size()) {
+			// nextOpenPaletteIndex = 0;
+			// }
+			// cd = (ColorDefinition) palette.get(nextOpenPaletteIndex);
+			// Color lineColor = new Color(org.eclipse.swt.widgets.Display.getCurrent(), cd.getRed(), cd.getGreen(), cd
+			// .getBlue());
+			if (seriesColorProvider instanceof CachedColorProvider) {
+				cd = (ColorDefinition) genericPalette.getEntries().get(nextOpenPaletteIndex++);
+				if (nextOpenPaletteIndex > genericPalette.getEntries().size() - 1) {
+					nextOpenPaletteIndex = 0;
+				}
+				swtColor = new Color(org.eclipse.swt.widgets.Display.getCurrent(), cd.getRed(), cd.getGreen(), cd.getBlue());
+				((CachedColorProvider) seriesColorProvider).putForegroundColor(seriesLabel, swtColor);
+			}
+		} else {
+			cd = ColorDefinitionImpl.create(swtColor.getRed(), swtColor.getGreen(), swtColor.getBlue());
+			// if (chartType == ChartType.TIME_SERIES) {
+			// cd = ((LineSeries) lineSeries).getLineAttributes().getColor();
+			// } else if (chartType == ChartType.STACKED_AREA) {
+			// cd = ((AreaSeries) lineSeries).getLineAttributes().getColor();
+			// }
+			// cd.setRed(swtColor.getRed());
+			// cd.setGreen(swtColor.getGreen());
+			// cd.setBlue(swtColor.getBlue());
+		}
+		entries.add(cd);
+	}
 
-        /**
-         * @param observed
-         * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#observeStart(org.eclipse.amp.axf.core.IObservationProvider)
-         */
-        public void observeStart(IObservationProvider observed) {
-            updateChartSelection();
-            endPainting();
-        }
+	@Override
+	protected IFigure createFigure() {
+		chartListener.setWidget(getViewer().getControl());
 
-        /**
-         * 
-         * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#observeInitialize(org.eclipse.amp.axf.core.IObservationProvider)
-         */
-        @Override
-        public void observeInitialize(IObservationProvider model) {
-            image = null;
-        }
+		final Figure newFigure = new Figure() {
+			@Override
+			public void paintFigure(Graphics graphics) {
+				if (getResourceManager().getImage() != null) {
+					graphics.drawImage(getResourceManager().getImage(), 0, 0);
+					if (getChartListener() != null) {
+						getChartListener().endPainting();
+					}
+				}
+			}
+		};
+		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);
+			}
 
-        /**
-         * 
-         * @see org.eclipse.amp.axf.view.SWTThreadModelListener#update(org.eclipse.amp.axf.core.IModel)
-         */
-        @Override
-        public void update(final IModel model) {
-            beginPainting();
-            chartStrategy.update();
-            refresh();
-        }
+			@Override
+			protected Dimension calculatePreferredSize(IFigure container, int hintWidth, int hintHeight) {
+				return new Dimension(hintWidth < 1 ? 100 : hintWidth, hintHeight < 1 ? 100 : hintHeight);
+			}
 
-        /**
-         * 
-         * @see org.eclipse.amp.axf.core.AbstractLifecycleListener#observationEnd(org.eclipse.amp.axf.core.IObservationProvider)
-         */
-        public void observationEnd(IObservationProvider model) {
-            dataProvider.removeListener(dataSource, dataListener);
-            model = null;
-        }
+			public void layout(IFigure container) {
+				newFigure.setLocation(new Point(0, 0));
+			}
+		});
+		newFigure.addFigureListener(new FigureListener() {
+			public void figureMoved(IFigure source) {
+				regenerateChart();
+			}
+		});
+		
+		return newFigure;
+	}
 
-        // /**
-        // * @return
-        // * @see org.eclipse.amp.axf.view.SWTThreadModelListener#getWidget()
-        // */
-        // public Control getWidget() {
-        // if (getViewer() != null) {
-        // return getViewer().getControl();
-        // }
-        // return null;
-        // }
-    };
+	@Override
+	protected void createEditPolicies() {
+		//
+	}
 
-    IChartScriptContext csc = new IChartScriptContext() {
+	@Override
+	public void refresh() {
+		new Thread() {
+			@Override
+			public void run() {
+				regenerateChart(true);
+			}
+		}.run();
+	}
 
-        public void setProperty(Object key, Object value) {
-        }
+	@Override
+	public void setModel(Object model) {
+		super.setModel(model);
+		chartListener = new ChartModelListener();
+		((IModel) model).addModelListener(chartListener);
+		IAdapterManager adapterManager = Platform.getAdapterManager();
+		// We seem to need to force loading of the data provider, at least in the exemplar case
+		Object provider = adapterManager.loadAdapter(this.getModel(), "org.eclipse.amp.agf.chart.IDataProvider");
 
-        public ULocale getULocale() {
-            return null;
-        }
+		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());
+		}
 
-        public Object getProperty(Object key) {
-            return null;
-        }
+		setDataProvider((IDataProvider) provider);
 
-        public ILogger getLogger() {
-            return null;
-        }
+		// createChart();
+	}
 
-        public Locale getLocale() {
-            return null;
-        }
+	/**
+	 * 
+	 * @see org.eclipse.birt.chart.device.IUpdateNotifier#regenerateChart()
+	 */
+	public void regenerateChart() {
+		regenerateChart(true);
+	}
 
-        public IExternalContext getExternalContext() {
-            return null;
-        }
+	/**
+	 * Regenerate chart.
+	 * 
+	 * @param forceNewImage
+	 *          the force new image
+	 */
+	public synchronized void regenerateChart(boolean forceNewImage) {
+		if (forceNewImage) {
+			getResourceManager().setImage(null);
+		}
+		try {
+			if (chart != null && chartStrategy.isInitialized() && getFigure() != null && !getFigure().getSize().isEmpty()) {
+				createImage();
+				Dimension area = getFigure().getSize();
+				Bounds chartBounds = BoundsImpl.create(0, 0, area.width, area.height);
+				chartBounds.scale(72d / renderer.getDisplayServer().getDpiResolution());
+				Generator gr = Generator.instance();
+				RunTimeContext rtc = new RunTimeContext();
+				rtc.setScriptingEnabled(false);
 
-        public Chart getChartInstance() {
-            return chart;
-        }
-    };
+				// rtc.setScriptContext(csc);
+				// csc.setChartInstance(chart);
+				chartState = gr.build(renderer.getDisplayServer(), chart, chartBounds, rtc);
+				gr.render(renderer, chartState);
+				getFigure().repaint();
+			} else {
+				chartListener.endPainting();
+			}
+		} catch (ChartException ce) {
+			StatusManager.getManager().handle(new Status(Status.WARNING, AGFChartPlugin.PLUGIN_ID, "Couldn't generate chart.", ce));
+			chartListener.endPainting();
+		}
+	}
 
-    private IChartDesignStrategy chartStrategy;
+	/**
+	 * Creates the image.
+	 */
+	public void createImage() {
+		Dimension area = getFigure().getSize();
+		Rectangle swtBounds = new Rectangle(0, 0, Math.max(area.width, 10), Math.max(area.height, 10));
+		if (resourceManager.getImage() == null || !resourceManager.getImage().getBounds().equals(swtBounds)) {
+			resourceManager.setImage(new Image(getViewer().getControl().getDisplay(), swtBounds));
+			resourceManager.setGc(new GC(resourceManager.getImage()));
+			renderer.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, resourceManager.getGc());
+		}
+	}
 
-    private void updateValueSetColor(Object valueSet, int index) {
-        String seriesLabel = dataProvider.getText(valueSet);
-        Color swtColor = seriesColorProvider.getForeground(seriesLabel);
-        EList<Fill> entries = chartStrategy.getValueSetsDefinition().getSeriesPalette().getEntries();
-        ColorDefinition cd = null;
-        if (swtColor == null) {
-            // List<Fill> palette = ySeriesDefinition.getSeriesPalette().getEntries();
-            // if (nextOpenPaletteIndex >= palette.size()) {
-            // nextOpenPaletteIndex = 0;
-            // }
-            // cd = (ColorDefinition) palette.get(nextOpenPaletteIndex);
-            // Color lineColor = new Color(org.eclipse.swt.widgets.Display.getCurrent(), cd.getRed(), cd.getGreen(), cd
-            // .getBlue());
-            if (seriesColorProvider instanceof CachedColorProvider) {
-                cd = (ColorDefinition) genericPalette.getEntries().get(nextOpenPaletteIndex++);
-                if (nextOpenPaletteIndex > genericPalette.getEntries().size() - 1) {
-                    nextOpenPaletteIndex = 0;
-                }
-                swtColor = new Color(org.eclipse.swt.widgets.Display.getCurrent(), cd.getRed(), cd.getGreen(), cd
-                                     .getBlue());
-                ((CachedColorProvider) seriesColorProvider).putForegroundColor(seriesLabel, swtColor);
-            }
-        } else {
-            cd = ColorDefinitionImpl.create(swtColor.getRed(), swtColor.getGreen(), swtColor.getBlue());
-            // if (chartType == ChartType.TIME_SERIES) {
-            // cd = ((LineSeries) lineSeries).getLineAttributes().getColor();
-            // } else if (chartType == ChartType.STACKED_AREA) {
-            // cd = ((AreaSeries) lineSeries).getLineAttributes().getColor();
-            // }
-            // cd.setRed(swtColor.getRed());
-            // cd.setGreen(swtColor.getGreen());
-            // cd.setBlue(swtColor.getBlue());
-        }
-        entries.add(cd);
-    }
+	/**
+	 * Creates the chart.
+	 */
+	public synchronized void createChart() {
+		chart = chartStrategy.createChart(dataProvider, dataSource);
+		chart.getTitle().getLabel().setVisible(false);
+	}
 
-    /**
-     * 
-     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
-     */
-    protected IFigure createFigure() {
-        chartListener.setWidget(getViewer().getControl());
+	/**
+	 * Update chart series.
+	 */
+	public synchronized void updateChartSelection() {
+		chartStrategy.updateSelection();
+		@SuppressWarnings("rawtypes")
+		List valueSets = dataProvider.getValueSets(dataSource);
+		chartStrategy.getValueSetsDefinition().getSeriesPalette().getEntries().clear();
+		for (Object valueSet : valueSets) {
+			updateValueSetColor(valueSet);
+		}
+	}
 
-        imageFigure = new Figure() {
-            public void paintFigure(Graphics graphics) {
-                if (image != null) {
-                    graphics.drawImage(image, 0, 0);
-                    if (chartListener != null) {
-                        chartListener.endPainting();
-                    }
-                }
-            }
-        };
-
-        imageFigure.setLayoutManager(new AbstractLayout() {
-            public Dimension getMinimumSize(IFigure container, int hintWidth, int hintHeight) {
-
-                return new Dimension(hintWidth < 1 ? 1 : hintWidth, hintHeight < 1 ? 1 : hintHeight);
-            }
-
-            protected Dimension calculatePreferredSize(IFigure container, int hintWidth, int hintHeight) {
-
-                return new Dimension(hintWidth < 1 ? 100 : hintWidth, hintHeight < 1 ? 100 : hintHeight);
-            }
-
-            public void layout(IFigure container) {
-                imageFigure.setLocation(new Point(0, 0));
-            }
-        });
-        imageFigure.addFigureListener(new FigureListener() {
-            public void figureMoved(IFigure source) {
-                regenerateChart();
-            }
-        });
-        return imageFigure;
-    }
-
-    /**
-     * 
-     * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
-     */
-    protected void createEditPolicies() {
-    }
-
-    /**
-     * 
-     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#refresh()
-     */
-    public void refresh() {
-        new Thread() {
-            public void run() {
-                regenerateChart(true);
-            };
-        }.run();
-    }
-
-    /**
-     * 
-     * @see org.eclipse.gef.editparts.AbstractEditPart#setModel(java.lang.Object)
-     */
-    public void setModel(Object model) {
-        super.setModel(model);
-        chartListener = new ChartModelListener();
-        ((IModel) model).addModelListener(chartListener);
-        IAdapterManager adapterManager = Platform.getAdapterManager();
-        // We seem to need to force loading of the data provider, at least in the exemplar case
-        Object provider = adapterManager.loadAdapter(this.getModel(), "org.eclipse.amp.agf.chart.IDataProvider");
-
-        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());
-        }
+	/**
+	 * 
+	 * @see org.eclipse.birt.chart.device.IUpdateNotifier#getDesignTimeModel()
+	 */
+	public Chart getDesignTimeModel() {
+		return chart;
+	}
 
-        setDataProvider((IDataProvider) provider);
+	/**
+	 * 
+	 * @see org.eclipse.birt.chart.device.IUpdateNotifier#getRunTimeModel()
+	 */
+	public Chart getRunTimeModel() {
+		return chartState.getChartModel();
+	}
 
-        // createChart();
-    }
+	ChartModelListener getChartListener() {
+		return chartListener;
+	}
 
-    /**
-     * 
-     * @see org.eclipse.birt.chart.device.IUpdateNotifier#regenerateChart()
-     */
-    public void regenerateChart() {
-        regenerateChart(true);
-    }
+	IChartDesignStrategy getChartStrategy() {
+		return chartStrategy;
+	}
 
-    /**
-     * Regenerate chart.
-     * 
-     * @param forceNewImage the force new image
-     */
-    public synchronized void regenerateChart(boolean forceNewImage) {
-        if (forceNewImage) {
-            image = null;
-        }
-        try {
-            if (chart != null && chartStrategy.isInitialized() && getFigure() != null
-                    && !getFigure().getSize().isEmpty()) {
-                createImage();
-                Dimension area = getFigure().getSize();
-                Bounds chartBounds = BoundsImpl.create(0, 0, area.width, area.height);
-                chartBounds.scale(72d / renderer.getDisplayServer().getDpiResolution());
-                Generator gr = Generator.instance();
-                RunTimeContext rtc = new RunTimeContext();
-                rtc.setScriptingEnabled(false);
+	Object getDataSource() {
+		return dataSource;
+	}
 
-                // rtc.setScriptContext(csc);
-                // csc.setChartInstance(chart);
-                chartState = gr.build(renderer.getDisplayServer(), chart, chartBounds, rtc);
-                gr.render(renderer, chartState);
-                imageFigure.repaint();
-            } else {
-                chartListener.endPainting();
-            }
-        } catch (ChartException ce) {
-            StatusManager.getManager().handle(
-                                              new Status(Status.WARNING, "org.eclipse.amp.agf.chart",
-                                                         "Couldn't generate chart.", ce));
-            chartListener.endPainting();
-        }
-    }
+	IDataSelectionListener getDataListener() {
+		return dataListener;
+	}
 
-    /**
-     * Creates the image.
-     */
-    public void createImage() {
-        Dimension area = getFigure().getSize();
-        org.eclipse.swt.graphics.Rectangle swtBounds = new org.eclipse.swt.graphics.Rectangle(0, 0, Math
-                                                                                              .max(area.width, 10), Math.max(area.height, 10));
-        if (image == null || !image.getBounds().equals(swtBounds)) {
-            if (image != null) {
-                image.dispose();
-                imageGC.dispose();
-            }
-            image = new Image(getViewer().getControl().getDisplay(), swtBounds);
-            imageGC = new GC(image);
-            renderer.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, imageGC);
-        }
-    }
+	/**
+	 * 
+	 * @see org.eclipse.birt.chart.device.IUpdateNotifier#peerInstance()
+	 */
+	public Object peerInstance() {
+		return this;
+	}
 
-    /**
-     * Creates the chart.
-     */
-    public synchronized void createChart() {
-        chart = chartStrategy.createChart(dataProvider, dataSource);
+	/**
+	 * 
+	 * @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) {
+		//
+	}
 
-        chart.getTitle().getLabel().setVisible(false);
-    }
+	/**
+	 * Gets the chart.
+	 * 
+	 * @return the chart
+	 */
+	public Chart getChart() {
+		return chart;
+	}
 
-    boolean chartUpated = false;
+	/**
+	 * Sets the series color provider.
+	 * 
+	 * @param seriesColorProvider
+	 *          the new series color provider
+	 */
+	public void setSeriesColorProvider(IColorProvider seriesColorProvider) {
+		this.seriesColorProvider = seriesColorProvider;
+	}
 
-    /**
-     * Update chart series.
-     */
-    public synchronized void updateChartSelection() {
-        chartStrategy.updateSelection();
-        List valueSets = dataProvider.getValueSets(dataSource);
-        chartStrategy.getValueSetsDefinition().getSeriesPalette().getEntries().clear();
-        int index = 0;
-        for (Object valueSet : valueSets) {
-            updateValueSetColor(valueSet, index);
-            index++;
-        }
-    }
+	/**
+	 * 
+	 * @see org.eclipse.birt.chart.device.IUpdateNotifier#repaintChart()
+	 */
+	public void repaintChart() {
+		refresh();
+	}
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse .swt.events.SelectionEvent)
-     */
-    /**
-     * Widget default selected.
-     * 
-     * @param e the e
-     */
-    public void widgetDefaultSelected(SelectionEvent e) {
-        // TODO Auto-generated method stub
-    }
+	@Override
+	public void deactivate() {
+		super.deactivate();
+		dataProvider.removeListener(dataSource, dataListener);
+	}
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.birt.chart.device.swing.IUpdateNotifier#getDesignTimeModel()
-     */
-    /**
-     * 
-     * @see org.eclipse.birt.chart.device.IUpdateNotifier#getDesignTimeModel()
-     */
-    public Chart getDesignTimeModel() {
-        return chart;
-    }
+	/**
+	 * Gets the data provider.
+	 * 
+	 * @return the data provider
+	 */
+	public IDataProvider getDataProvider() {
+		return dataProvider;
+	}
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.eclipse.birt.chart.device.swing.IUpdateNotifier#getRunTimeModel()
-     */
-    /**
-     * 
-     * @see org.eclipse.birt.chart.device.IUpdateNotifier#getRunTimeModel()
-     */
-    public Chart getRunTimeModel() {
-        return chartState.getChartModel();
-    }
+	/**
+	 * Sets the data provider.
+	 * 
+	 * @param dataProvider
+	 *          the new data provider
+	 */
+	public synchronized void setDataProvider(IDataProvider dataProvider) {
+		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);
+						}
+					});
+				}
+			}
+		};
+		dataProvider.addListener(dataSource, dataListener);
+	}
 
-    /**
-     * 
-     * @see org.eclipse.birt.chart.device.IUpdateNotifier#peerInstance()
-     */
-    public Object peerInstance() {
-        return this;
-    }
+	public void setChartStrategy(IChartDesignStrategy chartStrategy) {
+		this.chartStrategy = chartStrategy;
+		createChart();
+		updateChartSelection();
+		if (getViewer().getControl().getDisplay() != null) {
+			getViewer().getControl().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					repaintChart();
+				}
+			});
+		}
+	}
 
-    /**
-     * 
-     * @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) {
-    }
+	/**
+	 * Gets the series color provider.
+	 * 
+	 * @return the series color provider
+	 */
+	public IColorProvider getSeriesColorProvider() {
+		return seriesColorProvider;
+	}
 
-    /**
-     * Gets the chart.
-     * 
-     * @return the chart
-     */
-    public Chart getChart() {
-        return chart;
-    }
+	ResourceManager getResourceManager() {
+		return resourceManager;
+	}
+	/**
+	 * Encapsulate the dispose of gc and image
+	 * @author fei
+	 *
+	 */
+	class ResourceManager implements DisposeListener{
+		private GC gc;
 
-    /**
-     * 
-     * @see org.eclipse.birt.chart.device.IUpdateNotifier#repaintChart()
-     */
-    public void repaintChart() {
-        refresh();
-    }
+		private Image image;
+		
+		private Control attachedToDispose;
 
-    /**
-     * 
-     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
-     */
-    public void deactivate() {
-        super.deactivate();
-        dataProvider.removeListener(dataSource, dataListener);
-    }
+		public ResourceManager() {
+			// 
+		}
 
-    /**
-     * Gets the data provider.
-     * 
-     * @return the data provider
-     */
-    public IDataProvider getDataProvider() {
-        return dataProvider;
-    }
+		void setGc(GC gc) {
+			if (this.gc != null && !this.gc.isDisposed()) {
+				this.gc.dispose();
+			}
+			this.gc = gc;
+			addDisposeListener();
+		}
+		
+		GC getGc() {
+			return gc;
+		}
 
-    /**
-     * Sets the data provider.
-     * 
-     * @param dataProvider the new data provider
-     */
-    public synchronized void setDataProvider(IDataProvider dataProvider) {
-        this.dataProvider = dataProvider;
-        dataSource = dataProvider.getDataSource(getModel());
-        dataListener = new IDataSelectionListener() {
-            public void selectionChanged(Object dataSet) {
-                if (getParent() != null && getRoot() != null && getViewer() != null && chart != null) {
-                    updateChartSelection();
-                    getViewer().getControl().getDisplay().asyncExec(new Runnable() {
-                        public void run() {
-                            regenerateChart(true);
-                        }
-                    });
-                }
-            }
-        };
-        dataProvider.addListener(dataSource, dataListener);
-    }
+		private void addDisposeListener(){
+			assert attachedToDispose == null || attachedToDispose.equals(getViewer().getControl());
+			if(attachedToDispose == null && getViewer() != null){
+				attachedToDispose = getViewer().getControl();
+				attachedToDispose.addDisposeListener(this);
+			}
+		}
+		
+		Image getImage() {
+			return image;
+		}
 
-    /**
-     * @param chartType the chartType to set
-     */
-    public void setChartStrategy(IChartDesignStrategy chartStrategy) {
-        this.chartStrategy = chartStrategy;
-        createChart();
-        updateChartSelection();
-        if (getViewer().getControl().getDisplay() != null) {
-            getViewer().getControl().getDisplay().asyncExec(new Runnable() {
-                public void run() {
-                    repaintChart();
-                }
-            });
-        }
-    }
+		void setImage(Image image) {
+			if (this.image != null && !this.image.isDisposed()) {
+				this.image.dispose();
+			}
+			this.image = image;
+			addDisposeListener();
+		}
 
-    /**
-     * Gets the series color provider.
-     * 
-     * @return the series color provider
-     */
-    public IColorProvider getSeriesColorProvider() {
-        return seriesColorProvider;
-    }
+		public void widgetDisposed(DisposeEvent arg0) {
+			setImage(null);
+			setGc(null);
+		}
+	}
 }
diff --git a/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/test/org/eclipse/amp/agf/chart/ResourceManagerTest.java b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/test/org/eclipse/amp/agf/chart/ResourceManagerTest.java
new file mode 100644
index 0000000..20e4298
--- /dev/null
+++ b/org.eclipse.amp.agf/plugins/org.eclipse.amp.agf.chart/test/org/eclipse/amp/agf/chart/ResourceManagerTest.java
@@ -0,0 +1,75 @@
+package org.eclipse.amp.agf.chart;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.eclipse.amp.agf.chart.ChartEditPart.ResourceManager;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResourceManagerTest {
+	
+	private ResourceManager classToTest;
+	@Before
+	public void setUp() throws Exception {
+		classToTest = new ChartEditPart().getResourceManager();
+	}
+	/**
+	 * Would old gc be desposed?
+	 * Can we set null to dispose the gc
+	 */
+	@Test
+	public void testSetGc(){
+		Shell shell = new Shell();
+		GC gc = new GC(shell);
+		assertFalse(gc.isDisposed());
+		
+		classToTest.setGc(gc);
+		assertFalse(gc.isDisposed());
+		
+		GC gc2 = new GC(shell);
+		classToTest.setGc(gc2);
+		assertTrue(gc.isDisposed());
+		assertFalse(gc2.isDisposed());
+		
+		try{
+			classToTest.setGc(null);
+			assertTrue(gc2.isDisposed());
+		}catch(Exception e){
+			fail(e.getMessage());
+		}
+		shell.dispose();
+	}
+	/**
+	 * Would old image be desposed?
+	 * Can we set null to dispose the image
+	 */
+	@Test
+	public void testSetImage(){
+		Shell shell = new Shell();
+		Image image = new Image(Display.getCurrent(), 10, 10);
+		assertFalse(image.isDisposed());
+		
+		classToTest.setImage(image);
+		assertFalse(image.isDisposed());
+		
+		Image image2 = new Image(Display.getCurrent(), 10, 10);
+		classToTest.setImage(image2);
+		assertTrue(image.isDisposed());
+		assertFalse(image2.isDisposed());
+		
+		try{
+			classToTest.setImage(null);
+			assertTrue(image2.isDisposed());
+		}catch(Exception e){
+			fail(e.getMessage());
+		}
+		shell.dispose();
+	}
+}