/*
* Copyright (c) 2012 European Synchrotron Radiation Facility,
* 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 fable.framework.ui.views;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JApplet;
import jep.JepException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import fable.framework.imageprint.JLChartActions;
import fable.framework.ui.object.ColumnFileController;
import fable.framework.ui.rcp.Activator;
import fable.python.ColumnFile;
import fr.esrf.tangoatk.widget.util.chart.IJLChartActionListener;
import fr.esrf.tangoatk.widget.util.chart.IJLChartListener;
import fr.esrf.tangoatk.widget.util.chart.JLAxis;
import fr.esrf.tangoatk.widget.util.chart.JLChart;
import fr.esrf.tangoatk.widget.util.chart.JLChartActionEvent;
import fr.esrf.tangoatk.widget.util.chart.JLChartEvent;
import fr.esrf.tangoatk.widget.util.chart.JLDataView;
/*******************************************************************************
* @description This class can be used to create an XY plot of a series of
* ColumnFiles with JLChart.<br>
* The plot currently displays plots only one ColumnFiles at a time
* because files can have different columns. ColumnFiles can be
* removed or added or edited. <br>
* ColumnFiles can be added by clicking on the Open Column File
* action button.
* <p>
* Usage :
* <p>
* ColFileXYPlot plot= new ColFileXYPlot( parent, "myName", "y",
* "x");
* <p>
* Use plot.populateChart() to fill the chart
*
* @author Andy Gotz + Gaelle Suchet
*
* @todo add support for plotting multiple files on same plot on y1 or y2
*
* @since 19-05-2005 : keep or remove selected dots
*
*/
public class ColFileXYPlot implements IJLChartListener {
private static final long serialVersionUID = 1L;
/**
* A vector is kept of each column file currently loaded with its associated
* data view and a vector of additional data views (to be plotted on the y2
* axis)
*/
private Vector<ColumnFile> columnFileVector = new Vector<ColumnFile>();
private Vector<JLDataView> dataViewVector = new Vector<JLDataView>();
private java.awt.Frame chartFrame;
private JApplet chartContainer;
private JLChart chart;
/**
* Extra actions for the chart.
*/
private JLChartActions actions;
/**
* The parent Composite from the constructor.
*/
Composite parent;
/**
* The SashForm that holds the plot and the options.
*/
SashForm sashForm;
/**
* The Composite that holds the plot.
*/
private Composite plotSwtAwtComposite;
/**
* The Composite that holds the options.
*/
private ScrolledComposite optionsComposite;
/**
* Indicates when the plot options are visible.
*/
private boolean optionsShowing = true;
/**
* Listener for items added to the plot context menu.
*/
private IJLChartActionListener chartActionListener;
/**
* Paint listener for the parent composite.
*/
private PaintListener paintListener;
private String chartName, syAxisLabel, sxAxisLabel;
static int iDataColor = 0;
Combo colFileCombo, xKeysCombo, yKeysCombo;
public Button updateButton;
private Button removeButton;
private Button resetButton;
private Button switchXYButton;
private Group editGroup;
private int currentXIndex = 0;
private int currentYIndex = 1;
double[] currentXData;
double[] currentYData;
private JLDataView currentDataView = null;
ColumnFile currentColumnFile = null;
private Text txtY1Min, txtY1Max, txtXMax, txtXMin;
private Button removeDataButton, keepDataButton;
ImageDescriptor widget_close = Activator.imageDescriptorFromPlugin(
Activator.PLUGIN_ID, "images/widget_close.gif");
ImageDescriptor widget_open = Activator.imageDescriptorFromPlugin(
Activator.PLUGIN_ID, "images/widget_open.gif");
private ImageDescriptor imgdescChartOpt = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID,
"images/graphView.gif");
private ImageDescriptor imgdescRefreshplot = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID,
"images/refresh.gif");
private ImageDescriptor imgdescdelete = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "images/delete.gif");
private ImageDescriptor imgdescswitch = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "images/switch.gif");
private ImageDescriptor imgdescSub = Activator.imageDescriptorFromPlugin(
Activator.PLUGIN_ID, "images/subtract.gif");
private java.awt.Color dataColors[] = { new java.awt.Color(51, 51, 255),
new java.awt.Color(255, 51, 0), new java.awt.Color(51, 255, 255),
new java.awt.Color(255, 204, 51), new java.awt.Color(153, 0, 153),
new java.awt.Color(0, 255, 60) };
private ImageDescriptor keep_descriptor = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "images/check.gif");
private ImageDescriptor remove_descriptor = Activator
.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "images/delete.gif");
private Image img_delete, img_keep;
// Gaelle add for manage Transformer and this columnFile plot as we can
// add ColumnFile here
private ColumnFileController colController;
/** This dataview is used to display selected spot in table. */
private JLDataView markedDataView;
private int[] selectedRowsId;
/**
* ColFileXYPlot constructor
*
* @param parent
* - composite
* @param name
* -chart name
* @param yLabel
* - y label name
* @param xLabel
* - x label name
*/
public ColFileXYPlot(Composite parent, String name, String xLabel,
String yLabel) {
this.parent = parent;
chartName = name;
syAxisLabel = yLabel;
sxAxisLabel = xLabel;
img_keep = keep_descriptor.createImage();
int width = img_keep.getBounds().width;
int height = img_keep.getBounds().height;
Image tmp = remove_descriptor.createImage();
img_delete = new Image(Display.getDefault(), tmp.getImageData()
.scaledTo(width, height));
if (widget_open != null) {
// openEdit = widget_open.createImage();
}
if (widget_close != null) {
// hideEdit = widget_close.createImage();
}
tmp.dispose();
parent.setLayout(new GridLayout(1, true));
GridDataFactory.fillDefaults().grab(true, true).applyTo(parent);
// Make a paint listener that paints the chart
// KE: May not be necessary
parent.addPaintListener(new PaintListener() {
// @Override
public void paintControl(PaintEvent arg0) {
repaint();
}
});
// Create a SashForm so the plot can be sized independently of the view
sashForm = new SashForm(parent, SWT.HORIZONTAL);
GridDataFactory.fillDefaults().grab(true, true).applyTo(sashForm);
createChartFrame(sashForm);
createChart();
createOptionsGroup(sashForm);
// Needs to be done after contents are defined
sashForm.setWeights(new int[] { 2, 1 });
/*
* do not listen to the default labels from the preference store, labels
* differ from one column file to the next one
*/
/*
* Activator.getDefault().getPreferenceStore().addPropertyChangeListener(
* new IPropertyChangeListener() { public void
* propertyChange(PropertyChangeEvent event) { if ((String)
* event.getProperty() != null) { if (((String) event.getProperty())
* .equals(ColumnFilePlotPreferences.X_LABEL)) { setSxAxisLabel((String)
* event.getNewValue()); } else if (((String) event.getProperty())
* .equals(ColumnFilePlotPreferences.Y_LABEL)) { setSyAxisLabel((String)
* event.getNewValue()); } } } });
*/
colController = ColumnFileController.getColumnFileController();
colController.setcolumnFileVector(columnFileVector);
}
/**
* Set y axis label
*
* @param syAxisLabel
*/
public void setSyAxisLabel(String syAxisLabel) {
if (syAxisLabel != null) {
this.syAxisLabel = syAxisLabel;
selectLabelinYCombo(syAxisLabel);
}
}
/**
* Set x axis label
*
* @param sxAxisLabel
*/
public void setSxAxisLabel(String sxAxisLabel) {
if (sxAxisLabel != null) {
this.sxAxisLabel = sxAxisLabel;
selectLabelinXCombo(sxAxisLabel);
}
}
/** *********************************************************************** */
// LIST KEYS
/** *********************************************************************** */
/**
* Initialise x and y keys combo box with values to plot
*
* @since added job when columnFile is loaded, to avoid invalid thread acces
* fill combo in display thread.
* @param colandValues
*/
public void populateListsKeys(final ColumnFile col) {
// HashMap<String, double[]> values = col.getColumnstoPlot();
Display.getDefault().syncExec(new Runnable() {
// @Override
public void run() {
String[] colandValues = col.getTitles();
xKeysCombo.removeAll();
yKeysCombo.removeAll();
for (int i = 0; colandValues != null && i < colandValues.length; i++) {
String key = colandValues[i];
/* do not store data as part of keys combo */
/*
* xKeysCombo.setData(key, (double[]) values.get(key));
* yKeysCombo.setData(key, (double[]) values.get(key));
*/
yKeysCombo.setData("help" + key, key);
xKeysCombo.setData("help" + key, key);
xKeysCombo.add(key);
yKeysCombo.add(key);
}
yKeysCombo.setEnabled(yKeysCombo.getItemCount() > 0);
xKeysCombo.setEnabled(yKeysCombo.getItemCount() > 0);
if (currentXIndex > xKeysCombo.getItemCount()) {
resetPreferredCurrentXIndex();
}
if (currentYIndex > yKeysCombo.getItemCount()) {
resetPreferredCurrentY1Index();
}
xKeysCombo.select(currentXIndex);
yKeysCombo.select(currentYIndex);
}
});
}
/**
* Create the x keys combo box
*
* @param parent
*/
private void createListsKeys_X(Composite parent) {
new Label(parent, SWT.NONE).setText("X");
xKeysCombo = new Combo(parent, SWT.BORDER | SWT.V_SCROLL);
GridData gdlist = new GridData(SWT.LEFT, GridData.CENTER, true, false);
xKeysCombo.setLayoutData(gdlist);
xKeysCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
plotSelectedXAxis();
}
});
}
/**
* @author SUCHET
* @date Jul, 8 2008 Called when user select x key to plot, or when system
* force data to plot for example after computation in transformer,
* force y to display eta values
*/
private void plotSelectedXAxis() {
String[] sel = xKeysCombo.getItems();
currentXIndex = xKeysCombo.getSelectionIndex();
if (currentXIndex < 0) {
resetPreferredCurrentXIndex();
}
sxAxisLabel = sel[currentXIndex];
chart.getXAxis().setName(sxAxisLabel);
updateChart();
}
/**
* Create the y keys combo box
*
* @param parent
*/
private void createListsKeys_Y(Composite parent) {
new Label(parent, SWT.NONE).setText("Y");
yKeysCombo = new Combo(parent, SWT.BORDER | SWT.V_SCROLL);
GridData gdlist = new GridData(SWT.LEFT, GridData.CENTER, true, false);
yKeysCombo.setLayoutData(gdlist);
yKeysCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
plotSelectedY1Axis();
}
});
}
/**
* @author SUCHET
* @date Jul, 8 2008 Called when user select y key to plot, or when system
* force data to plot for example after computation in transformer,
* force y to display eta values
*/
private void plotSelectedY1Axis() {
String[] sel = yKeysCombo.getItems();
currentYIndex = yKeysCombo.getSelectionIndex();
if (currentYIndex < 0) {
resetPreferredCurrentY1Index();
}
syAxisLabel = sel[currentYIndex];
chart.getY1Axis().setName(syAxisLabel);
updateChart();
}
/**
* Create the Group of options for JLChart. These consist of a combo with a
* list of dataview. allowing user to remove or add column files top plot.
* There is also a clear all button and an option to enable the editor
*
* @param parent
*/
private void createOptionsGroup(Composite parent) {
optionsComposite = new ScrolledComposite(parent, SWT.V_SCROLL
| SWT.H_SCROLL);
optionsComposite.setLayout(new GridLayout(1, false));
Composite mainComposite = new Composite(optionsComposite, SWT.None);
mainComposite.setLayout(new GridLayout(1, false));
mainComposite.setLayoutData(new GridData());
mainComposite.pack();
optionsComposite.setContent(mainComposite);
Group groupChartOptions = new Group(mainComposite, SWT.NONE);
groupChartOptions.setLayout(new GridLayout());
((GridLayout) (groupChartOptions.getLayout())).numColumns = 2;
GridData gridChartOpt = new GridData(SWT.CENTER | SWT.FILL, SWT.FILL,
true, false);
gridChartOpt.verticalSpan = 1;
gridChartOpt.horizontalSpan = 1;
groupChartOptions.setLayoutData(gridChartOpt);
groupChartOptions.setText("Plot Options");
/** **************************Column to plot************************* */
createListsKeys_X(groupChartOptions);
createListsKeys_Y(groupChartOptions);
/** ***************************************************************** */
new Label(groupChartOptions, SWT.None).setText("Data");
colFileCombo = new Combo(groupChartOptions, SWT.READ_ONLY);
colFileCombo.setEnabled(dataViewVector.size() > 0);
colFileCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false));
((GridData) colFileCombo.getLayoutData()).horizontalSpan = 1;
colFileCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
super.widgetSelected(e);
Combo cbo = ((Combo) e.widget);
int index = cbo.getSelectionIndex();
if (index >= 0) {
/* cannot get two different data from the same object ?! */
/*
* currentDataView = (JLDataView) cbo.getData(cbo
* .getItem(index));
*/
/*
* currentColumnFile = (ColumnFile) cbo.getData(cbo
* .getItem(index));
*/
currentColumnFile = columnFileVector.get(index);
colController.setCurrentColumnFile(currentColumnFile);
populateListsKeys(currentColumnFile);
if (currentDataView != null)
chart.removeDataView(currentDataView);
currentDataView = dataViewVector.get(index);
chart.getY1Axis().addDataView(currentDataView);
}
updateChart();
repaint();
}
});
createOptionsButtons(groupChartOptions);
/* GROUP KEEP OR REMOVE DOTS */
createEditPlotOptions(mainComposite);
// parent.layout();
optionsComposite.setMinHeight(Display.getDefault().getPrimaryMonitor()
.getBounds().height);
optionsComposite.setMinWidth(Display.getDefault().getPrimaryMonitor()
.getBounds().width);
optionsComposite.setExpandVertical(true);
optionsComposite.setExpandHorizontal(true);
optionsComposite.setMinSize(mainComposite.computeSize(SWT.DEFAULT,
SWT.DEFAULT));
}
/**
* This method instantiates buttons "Update", "Clear plot", and "Options"
*
* @param groupChartOptions
*/
private void createOptionsButtons(Group groupChartOptions) {
createRemoveButton(groupChartOptions);
createShowDataOptionsButton(groupChartOptions);
createSwitchXYButton(groupChartOptions);
createUpdateButton(groupChartOptions);
createClearAllButton(groupChartOptions);
}
/**
* This method instantiates the switch x y button and adds it to the group
* options.
*
* @param groupChartOptions
*/
private void createSwitchXYButton(Group groupChartOptions) {
switchXYButton = new Button(groupChartOptions, SWT.PUSH);
switchXYButton.setText("Switch X Y");
final Image removeimage = imgdescswitch.createImage();
switchXYButton.setImage(removeimage);
switchXYButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (removeimage != null && !removeimage.isDisposed()) {
removeimage.dispose();
}
}
});
switchXYButton.setToolTipText("Switch the x and y axes");
switchXYButton.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | SWT.RESIZE));
switchXYButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (currentXIndex < 0 || currentYIndex < 0) {
return;
}
int temp = currentYIndex;
currentYIndex = currentXIndex;
currentXIndex = temp;
String tempString = syAxisLabel;
syAxisLabel = sxAxisLabel;
sxAxisLabel = tempString;
xKeysCombo.select(currentXIndex);
yKeysCombo.select(currentYIndex);
chart.getXAxis().setName(sxAxisLabel);
chart.getY1Axis().setName(syAxisLabel);
updateChart();
}
});
}
/**
* This method instantiates the reset button and adds it to the group
* options.
*
* @param groupChartOptions
*/
private void createClearAllButton(Group groupChartOptions) {
resetButton = new Button(groupChartOptions, SWT.PUSH);
resetButton.setText("Clear");
final Image removeimage = imgdescdelete.createImage();
resetButton.setImage(removeimage);
resetButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (removeimage != null && !removeimage.isDisposed()) {
removeimage.dispose();
}
}
});
resetButton.setToolTipText("Clear plot and remove all column files");
resetButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| SWT.RESIZE));
resetButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clearAllPlots();
}
});
}
/**
* This method instantiates the update button and adds it to the group
* options.
*
* @param groupChartOptions
*/
private void createUpdateButton(Group groupChartOptions) {
updateButton = new Button(groupChartOptions, SWT.PUSH);
updateButton.setText("Update");
final Image imageRefresh = imgdescRefreshplot.createImage();
updateButton.setImage(imageRefresh);
updateButton.setToolTipText("Update chart frame and plot");
updateButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (imageRefresh != null && !imageRefresh.isDisposed()) {
imageRefresh.dispose();
}
}
});
updateButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| SWT.RESIZE));
updateButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
/** **************X***************************** */
/* get data from column file rather than from combo */
/*
* double[] listX = ((double[])
* xKeysCombo.getData(sxAxisLabel));
*/
double[] listX = ((double[]) currentColumnFile
.getColumnstoPlot().get(sxAxisLabel));
int len = listX != null ? listX.length : 0;
if (len > 0) {
currentXData = new double[len];
/*
* currentXData = (double[])
* (xKeysCombo.getData(sxAxisLabel));
*/
currentXData = (double[]) currentColumnFile
.getColumnstoPlot().get(sxAxisLabel);
}
/** ***************Y**************************** */
/* get data from column file rather than from combo */
/*
* double[] listY = ((double[])
* yKeysCombo.getData(syAxisLabel));
*/
double[] listY = ((double[]) currentColumnFile
.getColumnstoPlot().get(syAxisLabel));
len = listY != null ? listY.length : 0;
if (len > 0) {
currentYData = new double[len];
/*
* currentYData = (double[])
* yKeysCombo.getData(syAxisLabel);
*/
currentYData = (double[]) currentColumnFile
.getColumnstoPlot().get(syAxisLabel);
}
/** ****************UPDATE **************************** */
updateChart(currentXData, currentYData);
}
});
}
/**
* This method instantiates the show data options button and adds it to the
* group options.
*
* @param groupChartOptions
*/
private void createShowDataOptionsButton(Group groupChartOptions) {
Button button = new Button(groupChartOptions, SWT.PUSH);
button.setText("Data");
button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| SWT.RESIZE));
final Image image_chartOptions = imgdescChartOpt.createImage();
button.setImage(image_chartOptions);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (currentDataView != null) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
chart.showDataOptionDialog(currentDataView);
}
});
} else {
MessageDialog.openInformation(Display.getCurrent()
.getActiveShell(), "Column file plot",
"No current dataview is available "
+ "to display options.");
}
}
});
button.setToolTipText("Display current data options box.");
button.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (image_chartOptions != null
&& !image_chartOptions.isDisposed()) {
image_chartOptions.dispose();
}
}
});
}
/**
* This methods instantiates the remove button and adds it to the group
* options.
*
* @param groupChartOptions
*/
private void createRemoveButton(Group groupChartOptions) {
removeButton = new Button(groupChartOptions, SWT.PUSH);
final Image subtractimage = imgdescSub.createImage();
removeButton.setImage(subtractimage);
removeButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (subtractimage != null && !subtractimage.isDisposed()) {
subtractimage.dispose();
}
}
});
removeButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| SWT.RESIZE));
removeButton.setText("Remove Data");
removeButton
.setToolTipText("Remove selected ColumnFile of the list from the plot");
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int index = colFileCombo.getSelectionIndex();
/** make removal simpler by using the index */
/*
* JLDataView dt = (JLDataView)
* (dataViewCombo.getData(dataViewCombo .getItem(index)));
* removeDataView(dt); columnFileVector.remove((ColumnFile)
* dataViewCombo .getData(dataViewCombo.getItem(index)));
*/
columnFileVector.remove(index);
// GS 18/07/08 : if this is the last dataview,
// remove it from the chart
JLDataView dataview = dataViewVector.elementAt(index);
chart.removeDataView(dataview);
xKeysCombo.removeAll();
yKeysCombo.removeAll();
//
dataViewVector.remove(index);
colFileCombo.remove(index);
if (index > colFileCombo.getItemCount() - 1) {
index = colFileCombo.getItemCount() - 1;
}
colFileCombo.select(index);
/* use Gaelle's trick to redraw */
colFileCombo.notifyListeners(SWT.Selection, new Event());
}
});
}
/**
* This method creates options group to keep or remove dots.
*
* @param mainComposite
*/
private void createEditPlotOptions(Composite mainComposite) {
editGroup = new Group(mainComposite, SWT.NONE);
editGroup.setText("Plot Editor");
editGroup.setLayout(new GridLayout());
((GridLayout) (editGroup.getLayout())).numColumns = 2;
GridData gdColumnDots = new GridData(SWT.CENTER | SWT.FILL, SWT.FILL,
true, false);
gdColumnDots.verticalSpan = 1;
gdColumnDots.horizontalSpan = 1;
editGroup.setLayoutData(gdColumnDots);
// ------------------------X AXIS-------------------------------------/
new Label(editGroup, SWT.None).setText("X Min");
txtXMin = new Text(editGroup, SWT.BORDER);
txtXMin.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
new Label(editGroup, SWT.None).setText("X Max");
txtXMax = new Text(editGroup, SWT.BORDER);
txtXMax.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// ------------------------Y AXIS-------------------------------------/
new Label(editGroup, SWT.None).setText("Y Min");
txtY1Min = new Text(editGroup, SWT.BORDER);
txtY1Min.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
new Label(editGroup, SWT.None).setText("Y Max");
txtY1Max = new Text(editGroup, SWT.BORDER);
txtY1Max.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// ------------------------BUTTONS-------------------------------------/
keepDataButton = new Button(editGroup, SWT.PUSH);
keepDataButton.setText("Keep");
keepDataButton
.setToolTipText("Keep all dots between min X, Y and max X, Y "
+ "and remove others");
keepDataButton.setImage(img_keep);
keepDataButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (img_keep != null && !img_keep.isDisposed()) {
img_keep.dispose();
}
}
});
keepDataButton.setEnabled(columnFileVector.size() > 0);
keepDataButton.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL, GridData.CENTER, true, false,
1, 1));
keepDataButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
double minX = 0;
double minY = 0;
double maxX = 0;
double maxY = 0;
if (!txtXMin.getText().trim().equals("")) {
minX = Double.valueOf(txtXMin.getText());
}
if (!txtXMin.getText().trim().equals("")) {
minY = Double.valueOf(txtY1Min.getText());
}
if (!txtXMin.getText().trim().equals("")) {
maxX = Double.valueOf(txtXMax.getText());
}
if (!txtXMin.getText().trim().equals("")) {
maxY = Double.valueOf(txtY1Max.getText());
}
keepDots(minX, maxX, minY, maxY);
updateChart();
repaint();
}
});
removeDataButton = new Button(editGroup, SWT.PUSH);
removeDataButton.setText("Remove");
removeDataButton
.setToolTipText("Remove all dots between min X, Y and max X, Y and keep others");
removeDataButton.setImage(img_delete);
removeDataButton.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (img_delete != null && !img_delete.isDisposed()) {
img_delete.dispose();
}
}
});
removeDataButton.setEnabled(columnFileVector.size() > 0);
removeDataButton.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL, GridData.CENTER, true, false,
1, 1));
removeDataButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
double minX = 0;
double minY = 0;
double maxX = 0;
double maxY = 0;
if (!txtXMin.getText().trim().equals("")) {
minX = Double.valueOf(txtXMin.getText());
}
if (!txtXMin.getText().trim().equals("")) {
minY = Double.valueOf(txtY1Min.getText());
}
if (!txtXMin.getText().trim().equals("")) {
maxX = Double.valueOf(txtXMax.getText());
}
if (!txtXMin.getText().trim().equals("")) {
maxY = Double.valueOf(txtY1Max.getText());
}
removeDots(minX, maxX, minY, maxY);
updateChart();
repaint();
}
});
}
/**
* remove all dots selected in the border of the plots in column file
*
* @param xmin
* - min selected X axes in the plot
* @param xmax
* - max selected X axes in the plot
* @param ymin
* - min selected Y axes in the plot
* @param ymax
* - max selected Y axes in the plot
*/
private void removeDots(double xmin, double xmax, double ymin, double ymax) {
try {
currentColumnFile.removeDots(sxAxisLabel, xmin, xmax, syAxisLabel,
ymin, ymax);
} catch (JepException e) {
System.out.println(e.getMessage());
}
}
/**
* keep all dots selected in the zone and remove others
*
* @param xmin
* - min selected X axes in the plot
* @param xmax
* - max selected X axes in the plot
* @param ymin
* - min selected Y axes in the plot
* @param ymax
* - max selected Y axes in the plot
*/
private void keepDots(double xmin, double xmax, double ymin, double ymax) {
try {
currentColumnFile.keepDots(sxAxisLabel, xmin, xmax, syAxisLabel,
ymin, ymax);
} catch (JepException e) {
System.out.println(e.getMessage());
}
}
/*
* create an SWT_AWT frame to hold the JLChart
*
* @param parent
*/
private void createChartFrame(Composite parent) {
plotSwtAwtComposite = new Composite(parent, SWT.EMBEDDED
| SWT.NO_BACKGROUND);
GridData gdlist = new GridData(SWT.FILL, SWT.FILL, true, true);
gdlist.verticalSpan = 2;
gdlist.horizontalSpan = 2;
plotSwtAwtComposite.setLayout(new GridLayout());
plotSwtAwtComposite.setLayoutData(gdlist);
chartFrame = SWT_AWT.new_Frame(plotSwtAwtComposite);
chartContainer = new JApplet();
chartFrame.add(chartContainer);
}
/**
* Clear all plots
*/
public void clearAllPlots() {
for (Iterator<JLDataView> it = dataViewVector.iterator(); it.hasNext();) {
chart.removeDataView(it.next());
}
columnFileVector.removeAllElements();
dataViewVector.removeAllElements();
colFileCombo.removeAll();
xKeysCombo.removeAll();
yKeysCombo.removeAll();
repaint();
iDataColor = 0;
}
/**
* Create the JLChart and initialize it with default settings e.g.
* autoscale.
*/
public void createChart() {
chart = new JLChart();
chart.setToolTipText("Zoom: Ctrl + select zone with mouse ");
chart.setHeader(chartName);
chart.setHeaderFont(new Font("Dialog", Font.BOLD, 18));
chart.getY1Axis().setName(syAxisLabel);
chart.getY1Axis().setAutoScale(true);
chart.getY1Axis().setGridVisible(true);
chart.getY1Axis().setSubGridVisible(true);
chart.getXAxis().setName(sxAxisLabel);
chart.getXAxis().setGridVisible(true);
chart.getXAxis().setSubGridVisible(true);
chart.getXAxis().setAnnotation(JLAxis.VALUE_ANNO);
chart.getXAxis().setAutoScale(true);
chartContainer.add(chart);
Dimension chartSize = chartContainer.getSize();
if (chartSize.height < chartSize.width) {
chart.setSize(chartSize.height, chartSize.height);
} else {
chart.setSize(chartSize.width, chartSize.width);
}
// Create the actions
actions = new JLChartActions(parent.getDisplay(), chart);
// Remove the Swing print item and replace it with ours then add our
// actions
chart.removeMenuItem(JLChart.MENU_PRINT);
chart.addUserAction("Print Setup");
chart.addUserAction("Print Preview");
chart.addUserAction("Print");
chart.addUserAction("Copy");
chart.addUserAction("Toggle Plot Options");
chartActionListener = new IJLChartActionListener() {
private static final long serialVersionUID = 1L;
public void actionPerformed(final JLChartActionEvent evt) {
// Run in the SWT thread
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (evt.getName().equals("Print Setup")) {
actions.printSetupAction.run();
} else if (evt.getName().equals("Print Preview")) {
actions.printPreviewAction.run();
} else if (evt.getName().equals("Print")) {
actions.printAction.run();
} else if (evt.getName().equals("Copy")) {
actions.copyAction.run();
} else if (evt.getName().equals("Toggle Plot Options")) {
setOptionsShowing(!optionsShowing);
}
}
});
}
public boolean getActionState(JLChartActionEvent evt) {
return false;
}
};
chart.addJLChartActionListener(chartActionListener);
// Since 15/07/2008 : to customize popup info : display label name
chart.setJLChartListener(this);
chart.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
double minX = chart.getXAxis().getMin();
double minY = chart.getY1Axis().getMin();
double maxX = chart.getXAxis().getMax();
double maxY = chart.getY1Axis().getMax();
if (chart.getY1Axis().getScale() == JLAxis.LOG_SCALE) {
minY = Math.pow(10, minY);
maxY = Math.pow(10, maxY);
}
if (chart.getXAxis().getScale() == JLAxis.LOG_SCALE) {
minX = Math.pow(10, minX);
maxX = Math.pow(10, maxX);
}
txtY1Min.setText(String.valueOf(minY));
txtY1Max.setText(String.valueOf(maxY));
txtXMax.setText(String.valueOf(maxX));
txtXMin.setText(String.valueOf(minX));
}
});
}
});
}
/**
* This function customize the value popup (request July 2008) Seen in
* JLchart snippet
*/
public String[] clickOnChart(JLChartEvent e) {
String[] ret = new String[2];
ret[0] = sxAxisLabel + "=" + e.getXValue();
ret[1] = syAxisLabel + "=" + e.getYValue();
return ret;
}
/** ********************************************************************* */
// Populate/
/** ********************************************************************* */
/**
* This method returns indices of the spot identified by its id and adds a
* new JLDatView to display theses spots in a different color
*
* @param a
* list of spot id
* @param name
* the name of the id
* @return a list of index with all ids
*/
public int[] markSelectedRows(double[] id, String name) {
selectedRowsId = new int[id.length];
if (markedDataView == null) {
markedDataView = new JLDataView();
setDataViewOptions(markedDataView, JLDataView.MARKER_CROSS, null,
7, 0);
} else {
markedDataView.reset();
}
double[] allid = currentColumnFile.getColumnstoPlot().get(name);
for (int j = 0; j < id.length; j++) {
for (int i = 0; i < allid.length; i++) {
if (allid[i] == id[j]) {
selectedRowsId[j] = i;
if (currentDataView != null) {
double x = currentDataView.getXValueByIndex(i);
double y = currentDataView.getYValueByIndex(i);
markedDataView.add(x, y);
}
break;
}
}
}
if (markedDataView.getDataLength() > 0) {
markedDataView.setLabelVisible(true);
markedDataView.setName("# " + id.length
+ " selected dots in table : ");
setDataViewOptions(markedDataView, markedDataView.getMarker(),
markedDataView.getMarkerColor(), markedDataView
.getMarkerSize(), markedDataView.getLineWidth());
chart.getY1Axis().addDataView(markedDataView);
this.repaint();
}
return selectedRowsId;
}
/**
* Update the plot with the data from the currently selected ColumnFile and
* the currently selected indices.
*/
public void updateChart() {
if (currentDataView != null) {
currentDataView.reset();
}
currentXData = currentYData = null;
if (xKeysCombo.getItemCount() > currentXIndex && currentXIndex > -1) {
sxAxisLabel = xKeysCombo.getItem(currentXIndex);
chart.getXAxis().setName(sxAxisLabel);
}
/* double[] listX = ((double[]) xKeysCombo.getData(sxAxisLabel)); */
int len = 0;
if (sxAxisLabel != null && currentColumnFile != null) {
double[] listX = currentColumnFile.getColumnstoPlot().get(
sxAxisLabel);
len = listX != null ? listX.length : 0;
}
if (len > 0) {
currentXData = new double[len];
currentXData = currentColumnFile.getColumnstoPlot()
.get(sxAxisLabel);
}
/** ***************Y**************************** */
if (yKeysCombo.getItemCount() > currentYIndex && currentYIndex > -1) {
syAxisLabel = yKeysCombo.getItem(currentYIndex);
chart.getY1Axis().setName(syAxisLabel);
}
/* double[] listY = ((double[]) yKeysCombo.getData(syAxisLabel)); */
if (syAxisLabel != null && currentColumnFile != null) {
double[] listY = currentColumnFile.getColumnstoPlot().get(
syAxisLabel);
len = listY != null ? listY.length : 0;
}
if (len > 0) {
currentYData = new double[len];
currentYData = currentColumnFile.getColumnstoPlot()
.get(syAxisLabel);
}
if (currentXData != null && currentYData != null) {
if (!syAxisLabel.equals("") && !sxAxisLabel.equals("")) {
if (currentDataView == null) {
currentDataView = new JLDataView();
}
currentDataView.setXDataSorted(false);
currentDataView.setData(currentXData, currentYData);
}
chart.setHeader(currentColumnFile.getFileName());
} else {
chart.setNoValueString("No value to display");
}
/**/
updateRowsMarked();
/**/
repaint();
}
/**
* new since we use Editor. To update selected spot in a tableviewer, when
* user plot other data.
*/
private void updateRowsMarked() {
if (selectedRowsId != null && selectedRowsId.length > 0) {
markedDataView.reset();
double[] allid = currentColumnFile.getColumnstoPlot().get(
currentColumnFile.getColumnfileId());
for (int j = 0; j < selectedRowsId.length; j++) {
for (int i = 0; i < allid.length; i++) {
if (allid[i] == selectedRowsId[j]) {
if (currentDataView != null) {
double x = currentDataView.getXValueByIndex(i);
double y = currentDataView.getYValueByIndex(i);
markedDataView.add(x, y);
}
break;
}
}
}
if (markedDataView != null) {
chart.getY1Axis().addDataView(markedDataView);
}
}
}
/**
* Add a new data set with x and y values
*/
public JLDataView updateChart(final double x[], final double y[]) {
if (!Display.getCurrent().isDisposed()) {
if (x != null && y != null) {
if (!syAxisLabel.equals("") && !sxAxisLabel.equals("")) {
if (currentDataView == null) {
currentDataView = new JLDataView();
}
currentDataView.setXDataSorted(false);
currentDataView.setData(x, y);
}
} else {
chart.setNoValueString("No value to display");
}
}
repaint();
return currentDataView = null;
}
public void updateColumnFile(ColumnFile col) {
populateListsKeys(col);
}
/**
* Add a new columnFile object in the plot if it doesn't exist. Otherwise,
* update plot.
*
* @param col
*/
public void addColumnFile(ColumnFile col) {
currentColumnFile = col;
colController.setCurrentColumnFile(currentColumnFile);
if (columnFileVector.lastIndexOf(col) < 0) {
columnFileVector.add(col);
JLDataView data = null;
data = new JLDataView();
data.setXDataSorted(false);
data.setName(col.getFullFileName());
addDataView(data);
populateListsKeys(col);
if (xKeysCombo.getItemCount() > 0)
setSxAxisLabel(xKeysCombo.getItems()[currentXIndex]);
if (yKeysCombo.getItemCount() > 0)
setSyAxisLabel(yKeysCombo.getItems()[currentYIndex]);
/*
* ignore preferences for now - does not make much sense because the
* column file can have totally different labels to the ones in the
* preferences rather force the plot to start with the current
* indices (cf. above)
*/
/*
* setSxAxisLabel(Activator.getDefault().getPreferenceStore()
* .getString(ColumnFilePlotPreferences.X_LABEL));
* setSyAxisLabel(Activator.getDefault().getPreferenceStore()
* .getString(ColumnFilePlotPreferences.Y_LABEL));
*/
updateChart();
} else {
populateListsKeys(col);
repaint();
}
Display.getDefault().syncExec(new Runnable() {
// @Override
public void run() {
removeDataButton.setEnabled(columnFileVector.size() > 0);
keepDataButton.setEnabled(columnFileVector.size() > 0);
}
});
}
public void addDataView(JLDataView dtV) {
if (!Display.getCurrent().isDisposed()) {
if (dtV != null) {
chart.getY1Axis().setName(syAxisLabel);
chart.getXAxis().setName(sxAxisLabel);
// Add a new dataview to vector if dataview doesn't
// exist in the vector. otherwise, update plot
if (dataViewVector.indexOf(dtV) < 0) {
dataViewVector.add(dtV);
colFileCombo.add(dtV.getName());
/* cannot setData() twice on the same object ?! */
// dataViewCombo.setData(dtV.getName(), dtV);
colFileCombo.setData(dtV.getName(), columnFileVector
.lastElement());
}
/* display only one plot at a time - remove the current one */
if (currentDataView != null)
chart.removeDataView(currentDataView);
currentDataView = dtV;
currentColumnFile = columnFileVector.lastElement();
colController.setCurrentColumnFile(currentColumnFile);
colFileCombo.select(colFileCombo.getItemCount() - 1);
colFileCombo.setEnabled(dataViewVector.size() > 0);
setDataViewOptions(dtV, JLDataView.MARKER_DOT, null, 7, 0);
chart.getY1Axis().addDataView(dtV);
} else {
chart.setNoValueString("No value to display");
}
repaint();
}
}
/**
* This methods set dots options for this JLDataview
*
* @param dtV
* a JLDataView
* @param marker
* @param markerSize
* @param lineWidth
*/
private void setDataViewOptions(JLDataView dtV, int marker, Color color,
int markerSize, int lineWidth) {
dtV.setMarker(marker);
dtV.setMarkerSize(markerSize);
dtV.setLineWidth(lineWidth);
if (color == null) {
dtV.setMarkerColor(dataColors[iDataColor]);
if (iDataColor < dataColors.length - 1) {
iDataColor += 1;
} else {
iDataColor = 0;
}
}
}
public void removeDataView(JLDataView dv) {
chart.removeDataView(dv);
dataViewVector.remove(dv);
if (colFileCombo.getItemCount() > 0) {
colFileCombo.remove(dv.getName());
colFileCombo.select(colFileCombo.getItemCount() - 1);
} else {
colFileCombo.setEnabled(false);
}
repaint();
}
public void repaint() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
// squareChartContainer();
chartContainer.repaint();
}
});
}
/**
* To make a square if scale is the same.
*
*/
/*
* private void squareChartContainer() {
*
* if (chart.getY1Axis().getMax() == chart.getXAxis().getMax()) { Dimension
* chartSize = chartContainer.getSize(); if (chartSize.height >
* chartSize.width) { chartSize.height = chartSize.width; } else {
* chartSize.width = chartSize.height; } chart.setSize(chartSize); } }
*/
/**
* Force x axis with this label. Label should exist in combo
*/
private void selectLabelinXCombo(String label) {
boolean found = false;
int i = 0;
for (i = 0; xKeysCombo != null && !found
&& i < xKeysCombo.getItemCount(); i++) {
if (xKeysCombo.getItems()[i].equals(label)) {
found = true;
xKeysCombo.select(i);
currentXIndex = i;
}
}
}
/**
* Force x axis with this label. Label should exist in combo
*/
private void selectLabelinYCombo(String label) {
boolean found = false;
int i = 0;
for (i = 0; yKeysCombo != null && !found
&& i < yKeysCombo.getItemCount(); i++) {
if (yKeysCombo.getItems()[i].equals(label)) {
found = true;
yKeysCombo.select(i);
currentYIndex = i;
}
}
}
/**
*
* @return this chart
*/
public JLChart getChart() {
return chart;
}
public JApplet getChartContainer() {
return chartContainer;
}
public Vector<JLDataView> getVectordataview() {
return dataViewVector;
}
public JLDataView getCurrentDataView() {
return currentDataView;
}
/**
* *************************************************************************
* **********
*/
class comboDataView_ContentProvider implements IContentProvider {
public Object[] getElements(Vector<JLDataView> inputElement) {
return inputElement.toArray();
}
public void dispose() {
// TODO Auto-generated method stub
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// TODO Auto-generated method stub
}
}
class comboDataView_LabelProvider implements IBaseLabelProvider {
public Image getImage(Object element) {
return null;
}
public String getText(Object element) {
return ((JLDataView) element).getName();
}
public void addListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
}
public void dispose() {
// TODO Auto-generated method stub
}
public boolean isLabelProperty(Object element, String property) {
// TODO Auto-generated method stub
return false;
}
public void removeListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
}
}
/**
* @date Jul, 8 2008 For transformer to display the latest computation (for
* example, plot tth vs eta)
* @param xyLabel
*/
public void plotData(String[] xyLabel) {
boolean bfound = false;
String xlabel = "";
String ylabel = "";
if (xyLabel.length == 2) {
xlabel = xyLabel[0];
ylabel = xyLabel[1];
}
for (int i = 0; !bfound && i < xKeysCombo.getItemCount(); i++) {
if (xKeysCombo.getItem(i).equals(xlabel)) {
bfound = true;
xKeysCombo.select(i);
}
}
bfound = false;
for (int i = 0; !bfound && i < yKeysCombo.getItemCount(); i++) {
if (yKeysCombo.getItem(i).equals(ylabel)) {
bfound = true;
yKeysCombo.select(i);
}
}
plotSelectedXAxis();
plotSelectedY1Axis();
}
/**
* Dispose method, even though this is not a SWT Control. Should be called
* by users of this class when they are finished with it. May not be
* implemented completely properly, but removes listeners.
*/
public void dispose() {
if (chart != null && chartActionListener != null) {
chart.removeJLChartActionListener(chartActionListener);
chartActionListener = null;
}
if (parent != null && !parent.isDisposed() && paintListener != null) {
parent.removePaintListener(paintListener);
paintListener = null;
}
chart = null;
}
/**
* @return Whether plot options are showing or not.
*/
public boolean getOptionsShowing() {
return optionsShowing;
}
/**
* Set whether plot options are showing or not.
*
* @param optionsShowing
* Whether to show plot options.
*/
public void setOptionsShowing(boolean optionsShowing) {
this.optionsShowing = optionsShowing;
if (sashForm == null)
return;
if (optionsShowing) {
sashForm.setMaximizedControl(null);
} else {
sashForm.setMaximizedControl(plotSwtAwtComposite);
}
}
private void resetPreferredCurrentXIndex() {
currentXIndex = 0;
}
private void resetPreferredCurrentY1Index() {
currentYIndex = 1;
}
}