Java tutorial
/* * Copyright (c) 2012 Diamond Light Source Ltd. * * 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 */ package org.dawnsci.plotting.system; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import org.dawb.common.ui.util.GridUtils; import org.dawnsci.plotting.AbstractPlottingSystem; import org.dawnsci.plotting.Activator; import org.dawnsci.plotting.PlottingActionBarManager; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.dawnsci.analysis.api.RMIServerProvider; import org.eclipse.dawnsci.analysis.api.dataset.IDataset; import org.eclipse.dawnsci.analysis.api.dataset.IErrorDataset; import org.eclipse.dawnsci.analysis.dataset.impl.Dataset; import org.eclipse.dawnsci.analysis.dataset.impl.DatasetFactory; import org.eclipse.dawnsci.analysis.dataset.impl.IntegerDataset; import org.eclipse.dawnsci.macro.api.IMacroService; import org.eclipse.dawnsci.macro.api.MacroEventObject; import org.eclipse.dawnsci.plotting.api.IPlottingSystem; import org.eclipse.dawnsci.plotting.api.IPlottingSystemViewer; import org.eclipse.dawnsci.plotting.api.IPrintablePlotting; import org.eclipse.dawnsci.plotting.api.PlotType; import org.eclipse.dawnsci.plotting.api.PlottingFactory; import org.eclipse.dawnsci.plotting.api.annotation.IAnnotation; import org.eclipse.dawnsci.plotting.api.axis.IAxis; import org.eclipse.dawnsci.plotting.api.axis.IClickListener; import org.eclipse.dawnsci.plotting.api.axis.IPositionListener; import org.eclipse.dawnsci.plotting.api.histogram.IPaletteService; import org.eclipse.dawnsci.plotting.api.preferences.BasePlottingConstants; import org.eclipse.dawnsci.plotting.api.preferences.PlottingConstants; import org.eclipse.dawnsci.plotting.api.preferences.ToolbarConfigurationConstants; import org.eclipse.dawnsci.plotting.api.region.IRegion; import org.eclipse.dawnsci.plotting.api.region.IRegion.RegionType; import org.eclipse.dawnsci.plotting.api.region.IRegionListener; import org.eclipse.dawnsci.plotting.api.remote.RemotePlottingSystem; import org.eclipse.dawnsci.plotting.api.trace.ColorOption; import org.eclipse.dawnsci.plotting.api.trace.IImage3DTrace; import org.eclipse.dawnsci.plotting.api.trace.IImageStackTrace; import org.eclipse.dawnsci.plotting.api.trace.IImageTrace; import org.eclipse.dawnsci.plotting.api.trace.IIsosurfaceTrace; import org.eclipse.dawnsci.plotting.api.trace.ILineStackTrace; import org.eclipse.dawnsci.plotting.api.trace.ILineTrace; import org.eclipse.dawnsci.plotting.api.trace.IMulti2DTrace; import org.eclipse.dawnsci.plotting.api.trace.IScatter3DTrace; import org.eclipse.dawnsci.plotting.api.trace.ISurfaceTrace; import org.eclipse.dawnsci.plotting.api.trace.ITrace; import org.eclipse.dawnsci.plotting.api.trace.ITraceListener; import org.eclipse.dawnsci.plotting.api.trace.IVectorTrace; import org.eclipse.dawnsci.plotting.api.trace.TraceEvent; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.nebula.visualization.xygraph.figures.Trace; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.PageBook; import org.eclipse.ui.preferences.ScopedPreferenceStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An implementation of IPlottingSystem, not designed to be public. * * THIS CLASS SHOULD NOT BE USED OUTSIDE THIS PLUGIN! * * THIS CLASS IS plugin private, do not export org.dawb.workbench.plotting.system from this plugin. * * @author gerring * */ public class PlottingSystemImpl extends AbstractPlottingSystem { private Logger logger = LoggerFactory.getLogger(PlottingSystemImpl.class); private static IMacroService mservice; public void setMacroService(IMacroService s) { mservice = s; } private Composite parent; private StackLayout stackLayout; private PlotActionsManagerImpl actionBarManager; private List<IPlottingSystemViewer> viewers; private IPlottingSystemViewer activeViewer; /** * Boolean to set if the intensity value labels should be shown at high zoom. */ private boolean showValueLabels = true; public PlottingSystemImpl() { super(); PlottingSystemActivator.getPlottingPreferenceStore().setDefault("org.dawnsci.plotting.showValueLabels", true); showValueLabels = PlottingSystemActivator.getPlottingPreferenceStore() .getBoolean("org.dawnsci.plotting.showValueLabels"); this.actionBarManager = (PlotActionsManagerImpl) super.actionBarManager; viewers = createViewerList(); for (IPlottingSystemViewer v : viewers) { if (v instanceof LightWeightPlotViewer) { activeViewer = v; break; } } } public boolean isShowValueLabels() { return showValueLabels; } public void setShowValueLabels(boolean showValueLabels) { this.showValueLabels = showValueLabels; PlottingSystemActivator.getPlottingPreferenceStore().setValue("org.dawnsci.plotting.showValueLabels", showValueLabels); } private List<IPlottingSystemViewer> createViewerList() { IConfigurationElement[] es = Platform.getExtensionRegistry() .getConfigurationElementsFor("org.eclipse.dawnsci.plotting.api.plottingViewer"); if (es == null || es.length < 1) throw new RuntimeException("There are no plot viewers defined!"); List<IPlottingSystemViewer> viewers = new ArrayList<IPlottingSystemViewer>(es.length); for (IConfigurationElement ie : es) { try { viewers.add((IPlottingSystemViewer) ie.createExecutableExtension("class")); } catch (CoreException e) { throw new RuntimeException("Fatal Plotting Error! Cannot create " + ie.getAttribute("class")); } } return viewers; } private boolean containerOverride = false; private static Display getDisplay() { return Display.getDefault(); } @Override public void createPlotPart(final Composite container, final String plotName, final IActionBars bars, final PlotType hint, final IWorkbenchPart part) { super.createPlotPart(container, plotName, bars, hint, part); if (container.getLayout() instanceof GridLayout) { GridUtils.removeMargins(container); } this.plottingMode = hint; if (container.getLayout() instanceof PageBook.PageBookLayout) { if (hint.is3D()) throw new RuntimeException( "Cannot deal with " + PageBook.PageBookLayout.class.getName() + " and 3D at the moment!"); this.parent = container; logger.debug("Cannot deal with " + PageBook.PageBookLayout.class.getName() + " and 3D at the moment!"); } else { this.containerOverride = true; this.parent = new Composite(container, SWT.NONE); this.stackLayout = new StackLayout(); this.parent.setLayout(stackLayout); parent.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE)); } // We make the viewerless plotting system before the viewer so that // any macro listener can import numpy. try { RMIServerProvider.getInstance().exportAndRegisterObject(IPlottingSystem.RMI_PREFIX + plotName, new RemotePlottingSystem(this)); } catch (Exception e) { logger.error("Unable to register plotting system " + plotName, e); } if (mservice != null) { mservice.publish(new MacroEventObject(this)); } // We ignore hint, we create a light weight plot as default because // it looks nice. We swap this for a 3D one if required. IPlottingSystemViewer lightWeightViewer = createViewer(PlotType.XY); if (lightWeightViewer != null && parent.getLayout() instanceof StackLayout) { final StackLayout layout = (StackLayout) parent.getLayout(); layout.topControl = lightWeightViewer.getControl(); container.layout(); } getDisplay().asyncExec(new Runnable() { public void run() { PlottingFactory.notityPlottingSystemCreated(plotName, PlottingSystemImpl.this); } }); } @Override public Control setControl(Control alternative, boolean showPlotToolbar) { if (stackLayout == null) throw new IllegalArgumentException( "The plotting system is not in StackLayout mode and cannot show alternative controls!"); Control previous = stackLayout.topControl; stackLayout.topControl = alternative; Control toolBar = ((ToolBarManager) getActionBars().getToolBarManager()).getControl(); if (toolBar.getLayoutData() instanceof GridData) { // It is our toolbar Control toolbarControl = toolBar.getParent(); if (toolbarControl.getLayoutData() instanceof GridData) { GridUtils.setVisible(toolbarControl, showPlotToolbar); toolbarControl.getParent().layout(new Control[] { toolbarControl }); } } parent.layout(); return previous; } @Override protected PlottingActionBarManager createActionBarManager() { return new PlotActionsManagerImpl(this); } @Override public Composite getPlotComposite() { if (containerOverride) return parent; if (activeViewer != null) return (Composite) activeViewer.getControl(); return null; } /** * Does nothing if the viewer is already created. * @param type */ private IPlottingSystemViewer createViewer(PlotType type) { IPlottingSystemViewer viewer = getViewer(type); if (viewer == null) { logger.error("Cannot find a plot viewer for plot type " + type); return null; } if (viewer.getControl() != null) { return viewer; } viewer.init(this); viewer.createControl(parent); parent.layout(); return viewer; } private IPlottingSystemViewer getViewer(PlotType type) { for (IPlottingSystemViewer v : viewers) { if (v.isPlotTypeSupported(type)) return v; } return null; } private IPlottingSystemViewer getViewer(Class<? extends ITrace> type) { for (IPlottingSystemViewer v : viewers) { if (v.isTraceTypeSupported(type)) return v; } return null; } public void setFocus() { if (activeViewer != null) activeViewer.setFocus(); } public void addTraceListener(final ITraceListener l) { super.addTraceListener(l); if (activeViewer != null) activeViewer.addImageTraceListener(l); } public void removeTraceListener(final ITraceListener l) { super.removeTraceListener(l); if (activeViewer != null) activeViewer.removeImageTraceListener(l); } @Override public void setEnabled(final boolean enabled) { if (activeViewer == null) return; if (getDisplay().getThread() == Thread.currentThread()) { if (activeViewer != null) activeViewer.setEnabled(enabled); } else { getDisplay().syncExec(new Runnable() { public void run() { if (activeViewer != null) activeViewer.setEnabled(enabled); } }); } } @Override public boolean isEnabled() { if (activeViewer == null) return true; return activeViewer.isEnabled(); } public List<ITrace> updatePlot1D(IDataset x, final List<? extends IDataset> ys, final IProgressMonitor monitor) { return updatePlot1D(x, ys, null, null, monitor); } public List<ITrace> updatePlot1D(IDataset x, final List<? extends IDataset> ys, final List<String> dataNames, final IProgressMonitor monitor) { return updatePlot1D(x, ys, dataNames, null, monitor); } public List<ITrace> updatePlot1D(IDataset x, final List<? extends IDataset> ys, final String plotTitle, final IProgressMonitor monitor) { return updatePlot1D(x, ys, null, plotTitle, monitor); } private List<ITrace> updatePlot1D(IDataset x, final List<? extends IDataset> ys, final List<String> dataNames, final String plotTitle, final IProgressMonitor monitor) { final List<ITrace> updatedAndCreated = new ArrayList<ITrace>(3); final List<IDataset> unfoundYs = new ArrayList<IDataset>(ys.size()); final List<String> unfoundNames = new ArrayList<String>(ys.size()); for (int i = 0; i < ys.size(); i++) { final IDataset y = ys.get(i); final String dataName = dataNames != null ? dataNames.get(i) : null; final ITrace trace = getTrace(y.getName()); if (trace != null && trace instanceof ILineTrace) { if (x == null) x = IntegerDataset.createRange(y.getSize()); final IDataset finalX = x; final ILineTrace lineTrace = (ILineTrace) trace; updatedAndCreated.add(lineTrace); if (!((IErrorDataset) y).hasErrors()) { lineTrace.setErrorBarEnabled(false); } else if (((IErrorDataset) y).hasErrors()) { lineTrace.setErrorBarEnabled(true); } if (getDisplay().getThread() == Thread.currentThread()) { lineTrace.setData(finalX, y); } else { getDisplay().syncExec(new Runnable() { public void run() { lineTrace.setData(finalX, y); } }); } continue; } unfoundYs.add(y); unfoundNames.add(dataName); } if (!unfoundYs.isEmpty()) { if (x == null) x = IntegerDataset.createRange(unfoundYs.get(0).getSize()); final Collection<ITrace> news = createPlot1D(x, unfoundYs, unfoundNames, plotTitle, monitor); updatedAndCreated.addAll(news); } return updatedAndCreated; } @Override public List<ITrace> createPlot1D(final IDataset xIn, final List<? extends IDataset> ysIn, final IProgressMonitor monitor) { return createPlot1D(xIn, ysIn, null, monitor); } /** * Does not have to be called in UI thread. */ @Override public List<ITrace> createPlot1D(final IDataset xIn, final List<? extends IDataset> ysIn, final String title, final IProgressMonitor monitor) { return createPlot1D(xIn, ysIn, null, title, monitor); } @Override public List<ITrace> createPlot1D(final IDataset xIn, final List<? extends IDataset> ysIn, final List<String> dataNames, final String title, final IProgressMonitor monitor) { if (monitor != null) monitor.worked(1); // create index datasets if necessary final List<ITrace> traces = new ArrayList<ITrace>(7); final IDataset x; if (ysIn == null || ysIn.isEmpty()) { return traces; } if (xIn == null) { final int max = getMaxSize(ysIn); x = DatasetFactory.createRange(0, max, 1, Dataset.INT32); if (ysIn.size() == 1) x.setName("Index of " + ysIn.get(0).getName()); else x.setName("Indices"); } else { x = xIn; } if (getDisplay().getThread() == Thread.currentThread()) { List<ITrace> ts = createPlot1DInternal(x, ysIn, dataNames, title, monitor); if (ts != null) traces.addAll(ts); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { List<ITrace> ts = createPlot1DInternal(x, ysIn, dataNames, title, monitor); if (ts != null) traces.addAll(ts); } }); } if (monitor != null) monitor.worked(1); return traces; } @Override public void append(final String name, final Number xValue, final Number yValue, final IProgressMonitor monitor) throws Exception { if (!this.plottingMode.is1D()) throw new Exception("Can only add in 1D mode!"); if (name == null || "".equals(name)) throw new IllegalArgumentException("The dataset name must not be null or empty string!"); if (getDisplay().getThread() == Thread.currentThread()) { appendInternal(name, xValue, yValue, monitor); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { appendInternal(name, xValue, yValue, monitor); } }); } } /** * Do not call before createPlotPart(...) */ public void setPlotType(final PlotType mode) { if (getDisplay().getThread() == Thread.currentThread()) { switchPlottingType(mode); } else { getDisplay().syncExec(new Runnable() { public void run() { switchPlottingType(mode); } }); } } @Override public ITrace updatePlot2D(final IDataset data, final List<? extends IDataset> axes, final IProgressMonitor monitor) { return updatePlot2D(data, axes, null, monitor); } @Override public ITrace updatePlot2D(final IDataset data, final List<? extends IDataset> axes, final String dataName, final IProgressMonitor monitor) { if (plottingMode.is1D()) { if (getDisplay().getThread() == Thread.currentThread()) { switchPlottingType(PlotType.IMAGE); } else { getDisplay().syncExec(new Runnable() { public void run() { switchPlottingType(PlotType.IMAGE); } }); } } final Collection<ITrace> traces = plottingMode.is3D() ? getTraces(ISurfaceTrace.class) : getTraces(IImageTrace.class); if (monitor != null && monitor.isCanceled()) return null; if (traces != null && traces.size() > 0) { ITrace image = traces.iterator().next(); final int[] shape = image.getData() != null ? image.getData().getShape() : null; if (shape != null && Arrays.equals(shape, data.getShape())) { if (getDisplay().getThread() == Thread.currentThread()) { image = updatePlot2DInternal(image, data, axes, dataName, monitor); } else { final List<ITrace> images = Arrays.asList(image); getDisplay().syncExec(new Runnable() { public void run() { // This will keep the previous zoom level if there // was one // and will be faster than createPlot2D(...) which // autoscales. ITrace im = updatePlot2DInternal(images.get(0), data, axes, dataName, monitor); images.set(0, im); } }); image = images.get(0); } return image; } else { return createPlot2D(data, axes, dataName, monitor); } } else { return createPlot2D(data, axes, dataName, monitor); } } private ITrace updatePlot2DInternal(final ITrace image, final IDataset data, final List<? extends IDataset> axes, final String dataName, final IProgressMonitor monitor) { if (data.getName() != null) if (activeViewer != null) activeViewer.setTitle(data.getName()); if (monitor != null && monitor.isCanceled()) return null; try { if (image instanceof IImageTrace) { ((IImageTrace) image).setData(data, axes, false); } else if (image instanceof ISurfaceTrace) { ((ISurfaceTrace) image).setData(data, axes); } return image; } catch (Throwable ne) { // We create a new one then clear(); return createPlot2D(data, axes, monitor); } } /** * Must be called in UI thread. Creates and updates image. * NOTE removes previous traces if any plotted. * * @param data * @param axes, x first. * @param monitor */ @Override public ITrace createPlot2D(final IDataset data, final List<? extends IDataset> axes, final IProgressMonitor monitor) { return createPlot2D(data, axes, null, monitor); } @Override public ITrace createPlot2D(final IDataset data, final List<? extends IDataset> axes, final String dataName, final IProgressMonitor monitor) { final List<ITrace> traces = new ArrayList<ITrace>(7); if (getDisplay().getThread() == Thread.currentThread()) { ITrace ts = createPlot2DInternal(data, axes, dataName, monitor); if (ts != null) traces.add(ts); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { ITrace ts = createPlot2DInternal(data, axes, dataName, monitor); if (ts != null) traces.add(ts); } }); } return traces.size() > 0 ? traces.get(0) : null; } protected ITrace createPlot2DInternal(final IDataset data, List<? extends IDataset> axes, String dataName, final IProgressMonitor monitor) { try { if (plottingMode.is1D()) { switchPlottingType(PlotType.IMAGE); } clearPlotViewer(); // Only one image at a time! if (traceMap == null) traceMap = new LinkedHashMap<String, ITrace>(31); traceMap.clear(); String traceName = data.getName(); if (part != null && (traceName == null || "".equals(traceName))) { traceName = part.getTitle(); } if (monitor != null && monitor.isCanceled()) return null; ITrace trace = null; if (plottingMode.is3D()) { trace = createSurfaceTrace(traceName); trace.setDataName(dataName); ((ISurfaceTrace) trace).setData(data, axes); addTrace(trace); } else { final IPlottingSystemViewer viewer = getViewer(IImageTrace.class); IImageTrace imageTrace = createImageTrace(traceName); imageTrace.setData(data, axes, false); trace = imageTrace; viewer.clearTraces(); imageTrace.setDataName(dataName); addTrace(trace); if (data.getName() != null) viewer.setTitle(data.getName()); } if (mservice != null) { mservice.publish(new MacroEventObject(data)); if (axes != null && !axes.isEmpty()) mservice.publish(new MacroEventObject(axes)); } return trace; } catch (Throwable e) { logger.error("Cannot load file " + data.getName(), e); return null; } } @Override public IImageTrace createImageTrace(String traceName) { IImageTrace trace = (IImageTrace) getViewer(IImageTrace.class).createTrace(traceName, IImageTrace.class); fireTraceCreated(new TraceEvent(trace)); return trace; } @Override public IImageStackTrace createImageStackTrace(String traceName) { IImageStackTrace trace = (IImageStackTrace) getViewer(IImageStackTrace.class).createTrace(traceName, IImageStackTrace.class); fireTraceCreated(new TraceEvent(trace)); return trace; } /** * An IdentityHashMap used to map Dataset to color used to plot it. * records keys for both strings and sets so that different models for the * file being plotted work. Sometimes dataset name is unique but the set is * not, sometimes the dataset is unique but its name is not. */ private Map<Object, Color> colorMap; // Warning can be mem leak /** * A map for recording traces to be used in the update method. * * Uses a map of abstract data set name to Trace to retrieve Trace on the * update. */ private Map<String, ITrace> traceMap; // Warning can be mem leak private List<ITrace> createPlot1DInternal(final IDataset xIn, final List<? extends IDataset> ysIn, final List<String> dataNames, final String title, final IProgressMonitor monitor) { // Switch off error bars if very many plots. IPreferenceStore store = getPreferenceStore(); boolean errorBarEnabled = store.getBoolean(PlottingConstants.GLOBAL_SHOW_ERROR_BARS); Collection<ITrace> existing = getTraces(ILineTrace.class); int traceCount = ysIn.size() + (existing != null ? existing.size() : 0); if (errorBarEnabled && traceCount >= store.getInt(PlottingConstants.AUTO_HIDE_ERROR_SIZE)) errorBarEnabled = false; if (errorBarEnabled) { // No error dataset there then false again boolean foundErrors = false; for (IDataset ids : ysIn) { if (((Dataset) ids).hasErrors()) { foundErrors = true; break; } } if (!foundErrors) errorBarEnabled = false; } PlotType newType = null; if (plottingMode.is1Dor2D()) { newType = PlotType.XY; } else if (plottingMode.isStacked3D()) { newType = PlotType.XY_STACKED_3D; } else if (plottingMode.isScatter3D()) { newType = PlotType.XY_SCATTER_3D; } if (newType != null) switchPlottingType(newType); if (colorMap == null && getColorOption() != ColorOption.NONE) { if (getColorOption() == ColorOption.BY_NAME) { colorMap = new HashMap<Object, Color>(ysIn.size()); } else { colorMap = new IdentityHashMap<Object, Color>(ysIn.size()); } } if (traceMap == null) traceMap = new LinkedHashMap<String, ITrace>(31); final IPlottingSystemViewer viewer = getViewer(plottingMode); List<ITrace> traces = null; if (plottingMode.is1D()) { if (viewer.getControl() == null) return null; List<ILineTrace> lines = viewer.createLineTraces(title, xIn, ysIn, dataNames, traceMap, colorMap, monitor); traces = new ArrayList<ITrace>(lines.size()); traces.addAll(lines); } else if (plottingMode.isScatter3D()) { traceMap.clear(); IScatter3DTrace trace = (IScatter3DTrace) viewer.createTrace(title, IScatter3DTrace.class); final IDataset x = xIn; final Dataset y = (Dataset) ysIn.get(1); final Dataset z = (Dataset) ysIn.get(2); if (dataNames != null) trace.setDataName(dataNames.get(0)); trace.setData(x, Arrays.asList(x, y, z)); viewer.addTrace(trace); traceMap.put(trace.getName(), trace); traces = Arrays.asList((ITrace) trace); } else if (plottingMode.isStacked3D()) { traceMap.clear(); ILineStackTrace trace = (ILineStackTrace) viewer.createTrace(title, ILineStackTrace.class); final IDataset x = xIn; final Dataset y = DatasetFactory.createRange(getMaxSize(ysIn), Dataset.INT32); final Dataset z = DatasetFactory.createRange(ysIn.size(), Dataset.INT32); if (dataNames != null) trace.setDataName(dataNames.get(0)); trace.setData(Arrays.asList(x, y, z), ysIn.toArray(new Dataset[ysIn.size()])); viewer.addTrace(trace); traceMap.put(trace.getName(), trace); traces = Arrays.asList((ITrace) trace); } Collection<ITrace> lineTraces = getTraces(ILineTrace.class); if (lineTraces != null) for (ITrace iTrace : lineTraces) { ((ILineTrace) iTrace).setErrorBarEnabled(errorBarEnabled); } if (mservice != null) { mservice.publish(new MacroEventObject(ysIn)); mservice.publish(new MacroEventObject(xIn)); } fireTracesPlotted(new TraceEvent(traces)); return traces; } private IPreferenceStore store; private IPreferenceStore getPreferenceStore() { if (store != null) return store; store = new ScopedPreferenceStore(InstanceScope.INSTANCE, "org.dawnsci.plotting"); return store; } @SuppressWarnings("unused") private boolean isAllInts(List<Dataset> ysIn) { for (Dataset a : ysIn) { if (a.getDtype() != Dataset.INT16 && a.getDtype() != Dataset.INT32 && a.getDtype() != Dataset.INT64) { return false; } } return true; } public ILineTrace createLineTrace(String traceName) { ILineTrace trace = (ILineTrace) getViewer(ILineTrace.class).createTrace(traceName, ILineTrace.class); return trace; } public IVectorTrace createVectorTrace(String traceName) { IVectorTrace trace = (IVectorTrace) getViewer(IVectorTrace.class).createTrace(traceName, IVectorTrace.class); return trace; } @Override public ISurfaceTrace createSurfaceTrace(String traceName) { ISurfaceTrace trace = (ISurfaceTrace) getViewer(ISurfaceTrace.class).createTrace(traceName, ISurfaceTrace.class); return (ISurfaceTrace) setPaletteData(trace); } @Override public IIsosurfaceTrace createIsosurfaceTrace(String traceName) { IIsosurfaceTrace trace = (IIsosurfaceTrace) getViewer(IIsosurfaceTrace.class).createTrace(traceName, IIsosurfaceTrace.class); return (IIsosurfaceTrace) setPaletteData(trace); } @Override public IMulti2DTrace createMulti2DTrace(String traceName) { IMulti2DTrace trace = (IMulti2DTrace) getViewer(IMulti2DTrace.class).createTrace(traceName, IMulti2DTrace.class); return (IMulti2DTrace) setPaletteData(trace); } private IImage3DTrace setPaletteData(IImage3DTrace trace) { PaletteData palette = null; if (trace.getPaletteData() == null) { final String schemeName = PlottingSystemActivator.getPlottingPreferenceStore() .getString(PlottingConstants.COLOUR_SCHEME); final Collection<ITrace> col = getTraces(IImageTrace.class); if (col != null && col.size() > 0) { palette = ((IImageTrace) col.iterator().next()).getPaletteData(); } else { try { final IPaletteService pservice = (IPaletteService) PlatformUI.getWorkbench() .getService(IPaletteService.class); palette = pservice.getDirectPaletteData(schemeName); } catch (Exception e) { palette = null; } } trace.setPaletteData(palette); trace.setPaletteName(schemeName); } return trace; } @Override public ILineStackTrace createLineStackTrace(String traceName) { ILineStackTrace trace = (ILineStackTrace) getViewer(ILineStackTrace.class).createTrace(traceName, ILineStackTrace.class); return trace; } @Override public IScatter3DTrace createScatter3DTrace(String traceName) { IScatter3DTrace trace = (IScatter3DTrace) getViewer(IScatter3DTrace.class).createTrace(traceName, IScatter3DTrace.class); return trace; } protected void switchPlottingType(PlotType type) { PlotType previous = plottingMode; plottingMode = type; actionBarManager.switchActions(plottingMode); Control top = null; IPlottingSystemViewer viewer = createViewer(type); if (viewer == null) return; activeViewer = viewer; top = viewer.getControl(); viewer.updatePlottingRole(type); if (parent != null && !parent.isDisposed() && parent.getLayout() instanceof StackLayout) { final StackLayout layout = (StackLayout) parent.getLayout(); layout.topControl = top; parent.layout(); } if (isAutoHideRegions() && previous != plottingMode) { // We auto-hide regions that are different plot type. final Collection<IRegion> regions = getRegions(); if (regions != null) for (IRegion iRegion : regions) { if (iRegion.isUserRegion()) iRegion.setVisible(iRegion.getPlotType() == null || iRegion.getPlotType() == type); } } } /** * Adds trace, makes visible * @param traceName * @return */ public void addTrace(ITrace trace) { IPlottingSystemViewer viewer = getViewer(trace.getClass()); boolean ok = viewer.addTrace(trace); if (!ok) return; // it has not added. if (traceMap == null) this.traceMap = new HashMap<String, ITrace>(7); traceMap.put(trace.getName(), trace); fireTraceAdded(new TraceEvent(trace)); } /** * Removes a trace. * @param traceName * @return */ public void removeTrace(ITrace trace) { if (traceMap != null) traceMap.remove(trace.getName()); IPlottingSystemViewer viewer = getViewer(trace.getClass()); viewer.removeTrace(trace); fireTraceRemoved(new TraceEvent(trace)); } @Override public void renameTrace(final ITrace trace, String name) { if (name != null && name.equals(trace.getName())) return; trace.setName(name); if (traceMap == null) traceMap = new LinkedHashMap<String, ITrace>(3); traceMap.put(name, trace); } @Override public void moveTrace(final String oldName, String name) { if (name != null && name.equals(oldName)) return; if (traceMap != null) { ITrace trace = traceMap.remove(oldName); traceMap.put(name, trace); } } public Collection<ITrace> getTraces() { if (traceMap == null) return Collections.emptyList(); return new LinkedHashSet<ITrace>(traceMap.values()); } @Override public ITrace getTrace(String name) { if (traceMap == null) return null; return traceMap.get(name); } private void appendInternal(final String name, Number xValue, final Number yValue, final IProgressMonitor monitor) { final ITrace wrapper = traceMap.get(name); if (wrapper == null) return; final Trace trace = ((LineTraceImpl) wrapper).getTrace(); LightWeightDataProvider prov = (LightWeightDataProvider) trace.getDataProvider(); if (prov == null) return; prov.append(xValue, yValue); } /** * Override this method to provide an implementation of title setting. * @param title */ public void setTitle(final String title) { super.setTitle(title); activeViewer.setTitle(title); } /** * Call to set the plot title color. * @param title */ public void setTitleColor(final Color color) { activeViewer.setTitleColor(color); } @Override public void setBackgroundColor(final Color color) { activeViewer.setBackgroundColor(color); } public String getTitle() { return activeViewer.getTitle(); } @Override public void setShowLegend(boolean b) { String id = ToolbarConfigurationConstants.CONFIG.getId() + BasePlottingConstants.XY_SHOWLEGEND; IAction action = actionBarManager.findAction(getPlotName() + "/" + id); if (action != null) { action.setChecked(b); } if (activeViewer != null) { activeViewer.setShowLegend(b); } } @Override public boolean isShowIntensity() { if (activeViewer != null) return activeViewer.isShowIntensity(); return false; } @Override public void setShowIntensity(boolean b) { if (activeViewer != null) activeViewer.setShowIntensity(b); repaint(false); } public Color get1DPlotColor(Object object) { if (getColorOption() == ColorOption.NONE) return null; if (colorMap == null) return null; if (object == null) return null; if (colorOption == ColorOption.BY_DATA) { return colorMap.get(object); } else if (colorOption == ColorOption.BY_NAME) { return colorMap.get((String) object); } return null; } private int getMaxSize(List<? extends IDataset> sets) { int max = 1; // Cannot be less than one for (IDataset set : sets) { if (set != null) max = Math.max(max, set.getSize()); } return max; } @Override public void reset() { if (getDisplay().getThread() == Thread.currentThread()) { resetInternal(); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { resetInternal(); } }); } } private void resetInternal() { if (traceMap != null) traceMap.clear(); if (colorMap != null) colorMap.clear(); for (IPlottingSystemViewer v : viewers) { if (v.getControl() != null) v.reset(true); } fireTracesCleared(new TraceEvent(this)); } @Override public void clear() { if (getDisplay().getThread() == Thread.currentThread()) { clearInternal(); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { clearInternal(); } }); } } private void clearInternal() { if (activeViewer.getControl() != null) { try { clearPlotViewer(); if (colorMap != null) colorMap.clear(); } catch (Throwable e) { logger.error("Cannot remove traces!", e); } } } @Override public void dispose() { super.dispose(); store = null; if (colorMap != null) { colorMap.clear(); colorMap = null; } clearPlotViewer(); for (IPlottingSystemViewer v : viewers) { if (v.getControl() != null) v.dispose(); } try { RMIServerProvider.getInstance().unbind(IPlottingSystem.RMI_PREFIX + plotName); } catch (Exception e) { logger.error("Unable to deregister plotting system"); } } @Override public void clearTraces() { if (getDisplay().getThread() == Thread.currentThread()) { removeAllTraces(); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { removeAllTraces(); } }); } } private void removeAllTraces() { final Collection<ITrace> traces = getTraces(); for (ITrace iTrace : traces) { removeTrace(iTrace); } } /** * */ private void clearPlotViewer() { for (IPlottingSystemViewer v : viewers) { if (v.getControl() != null) v.clearTraces(); } if (traceMap != null) traceMap.clear(); fireTracesCleared(new TraceEvent(this)); } public void repaint() { repaint(isRescale()); } public void repaint(final boolean autoScale) { if (activeViewer != null) activeViewer.repaint(autoScale); } /** * Creates an image of the same size as the Rectangle passed in. * @param size, ignored for 3D plots, instead the size of the widget it used. * @return */ @Override public Image getImage(Rectangle size) { return activeViewer.getImage(size); } /** * Use this method to create axes other than the default y and x axes. * * @param title * @param isYAxis, normally it is. * @param side - either SWT.LEFT, SWT.RIGHT, SWT.TOP, SWT.BOTTOM * @return */ @Override public IAxis createAxis(final String title, final boolean isYAxis, int side) { return activeViewer.createAxis(title, isYAxis, side); } @Override public IAxis removeAxis(final IAxis axis) { return activeViewer.removeAxis(axis); } @Override public List<IAxis> getAxes() { return activeViewer.getAxes(); } @Override public IAxis getAxis(String name) { return activeViewer.getAxis(name); } @Override public IAxis getSelectedXAxis() { return activeViewer.getSelectedXAxis(); } @Override public void setSelectedXAxis(IAxis selectedXAxis) { activeViewer.setSelectedXAxis(selectedXAxis); } @Override public IAxis getSelectedYAxis() { return activeViewer.getSelectedYAxis(); } @Override public void setSelectedYAxis(IAxis selectedYAxis) { activeViewer.setSelectedYAxis(selectedYAxis); } public boolean addRegionListener(final IRegionListener l) { return activeViewer.addRegionListener(l); } public boolean removeRegionListener(final IRegionListener l) { return activeViewer.removeRegionListener(l); } /** * Throws exception if region exists already. * @throws Exception */ public IRegion createRegion(final String name, final RegionType regionType) throws Exception { return activeViewer.createRegion(name, regionType); } public void clearRegions() { activeViewer.clearRegions(); } @Override public void resetAxes() { if (getDisplay().getThread() == Thread.currentThread()) { activeViewer.resetAxes(); } else { getDisplay().syncExec(new Runnable() { @Override public void run() { activeViewer.resetAxes(); } }); } } public void clearRegionTool() { activeViewer.clearRegionTool(); } /** * Add a selection region to the graph. * @param region */ public void addRegion(final IRegion region) { activeViewer.addRegion(region); } /** * Remove a selection region to the graph. * @param region */ public void removeRegion(final IRegion region) { activeViewer.removeRegion(region); } @Override public void renameRegion(final IRegion region, String name) { activeViewer.renameRegion(region, name); } /** * Get a region by name. * @param name * @return */ public IRegion getRegion(final String name) { return activeViewer.getRegion(name); } /** * Get regions * @param name * @return */ public Collection<IRegion> getRegions() { return activeViewer.getRegions(); } @Override public Collection<IRegion> getRegions(final RegionType type) { return activeViewer.getRegions(type); } @Override public IAnnotation createAnnotation(final String name) throws Exception { return activeViewer.createAnnotation(name); } @Override public void addAnnotation(final IAnnotation annotation) { activeViewer.addAnnotation(annotation); } @Override public void removeAnnotation(final IAnnotation annotation) { activeViewer.removeAnnotation(annotation); } @Override public void renameAnnotation(final IAnnotation annotation, String name) { activeViewer.renameAnnotation(annotation, name); } @Override public void clearAnnotations() { activeViewer.clearAnnotations(); } @Override public IAnnotation getAnnotation(final String name) { return activeViewer.getAnnotation(name); } @Override public void autoscaleAxes() { activeViewer.autoscaleAxes(); } @Override public void printPlotting() { if (activeViewer instanceof IPrintablePlotting) { ((IPrintablePlotting) activeViewer).printPlotting(); } } /** * Print scaled plotting to printer */ public void printScaledPlotting() { if (activeViewer instanceof IPrintablePlotting) { ((IPrintablePlotting) activeViewer).printScaledPlotting(); } } @Override public void copyPlotting() { if (activeViewer instanceof IPrintablePlotting) { ((IPrintablePlotting) activeViewer).copyPlotting(); } } @Override public String savePlotting(String filename) throws Exception { if (activeViewer instanceof IPrintablePlotting) { ((IPrintablePlotting) activeViewer).savePlotting(filename); } return null; } @Override public void savePlotting(String filename, String filetype) throws Exception { if (activeViewer instanceof IPrintablePlotting) { ((IPrintablePlotting) activeViewer).savePlotting(filename, filetype); } } public void setXFirst(boolean xfirst) { super.setXFirst(xfirst); activeViewer.setXFirst(xfirst); } public void setRescale(boolean rescale) { super.setRescale(rescale); activeViewer.setRescale(rescale); } /** * NOTE This listener is *not* notified once for each configuration setting made on * the configuration but once whenever the form is applied by the user (and many things * are changed) * * You then have to read the property you require from the object (for instance the axis * format) in case it has changed. This is not ideal, later there may be more events fired and * it will be possible to check property name, for now it is always set to "Graph Configuration". * * @param listener */ @Override public void addPropertyChangeListener(IPropertyChangeListener listener) { super.addPropertyChangeListener(listener); activeViewer.addPropertyChangeListener(listener); } @Override public void removePropertyChangeListener(IPropertyChangeListener listener) { super.removePropertyChangeListener(listener); activeViewer.removePropertyChangeListener(listener); } public void setActionBars(IActionBars bars) { this.bars = bars; } @Override public void setDefaultCursor(int cursorType) { activeViewer.setDefaultCursor(cursorType); } @Override public void addPositionListener(IPositionListener l) { activeViewer.addPositionListener(l); } @Override public void removePositionListener(IPositionListener l) { activeViewer.removePositionListener(l); } @Override public void addClickListener(IClickListener l) { activeViewer.addClickListener(l); } @Override public void removeClickListener(IClickListener l) { activeViewer.removeClickListener(l); } public void setKeepAspect(boolean checked) { activeViewer.setKeepAspect(checked); } public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { if (adapter.isAssignableFrom(getClass())) return this; for (IPlottingSystemViewer v : viewers) { if (v.getClass() == adapter) return v; if (adapter.isAssignableFrom(v.getClass())) return v; if (v instanceof IAdaptable) { Object inst = ((IAdaptable) v).getAdapter(adapter); if (inst != null) return inst; } } return super.getAdapter(adapter); } }