uk.ac.diamond.scisoft.analysis.rcp.editors.DataEditor.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.diamond.scisoft.analysis.rcp.editors.DataEditor.java

Source

/*
 * Copyright 2012 Diamond Light Source Ltd.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package uk.ac.diamond.scisoft.analysis.rcp.editors;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.dawb.common.ui.util.EclipseUtils;
import org.dawb.common.ui.util.GridUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dawnsci.analysis.api.dataset.IDataset;
import org.eclipse.dawnsci.analysis.dataset.impl.Dataset;
import org.eclipse.dawnsci.analysis.dataset.impl.DatasetUtils;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ContributionManager;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.PageChangedEvent;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.part.EditorPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import uk.ac.diamond.scisoft.analysis.axis.AxisValues;
import uk.ac.diamond.scisoft.analysis.deprecated.rcp.Activator;
import uk.ac.diamond.scisoft.analysis.rcp.AnalysisRCPActivator;
import uk.ac.diamond.scisoft.analysis.rcp.plotting.AbstractPlotWindow;
import uk.ac.diamond.scisoft.analysis.rcp.plotting.DataSetPlotter;
import uk.ac.diamond.scisoft.analysis.rcp.preference.DeprecatedPreferenceConstants;
import uk.ac.diamond.scisoft.analysis.rcp.util.CSVUtils;

/**
 * An editor which shows the current data sets plotted in a table.
 * 
 * This may be needed if the scientist has manipulated the data and would like to view it or export it.
 */
public class DataEditor extends EditorPart implements IReusableEditor, IPageChangedListener {

    private static Logger logger = LoggerFactory.getLogger(DataEditor.class);

    // This view is a composite of two other views.
    private TableViewer tableViewer;
    private CLabel errorLabel;
    private Composite main;
    private AbstractPlotWindow plotWindow;

    public DataEditor() {

    }

    /**
     * You must call this method with the plotWindow which you would like to 
     * interrogate and show the window of.
     * @param plotWindow
     */
    public void setPlotter(AbstractPlotWindow plotWindow) {
        this.plotWindow = plotWindow;
    }

    @Override
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        setSite(site);
        setInput(input);
        setPartName(input.getName());

    }

    @Override
    public boolean isDirty() {
        return false;
    }

    @Override
    public void createPartControl(Composite parent) {

        this.main = new Composite(parent, SWT.NONE);
        final GridLayout gridLayout = new GridLayout(1, false);
        gridLayout.verticalSpacing = 0;
        gridLayout.marginWidth = 0;
        gridLayout.marginHeight = 0;
        gridLayout.horizontalSpacing = 0;
        main.setLayout(gridLayout);

        // We use a local toolbar to make it clear to the user the tools
        // that they can use, also because the toolbar actions are 
        // hard coded.
        final ToolBarManager toolMan = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
        final ToolBar toolBar = toolMan.createControl(main);
        toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
        createActions(toolMan);

        errorLabel = new CLabel(main, SWT.NONE);
        errorLabel.setImage(AnalysisRCPActivator.getImage("icons/error.png"));
        errorLabel.setText(
                "This editor shows the data plotted. Please plot at least one data set and view the data here.");
        errorLabel.setForeground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_RED));
        errorLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));

        toolMan.update(false);
        main.layout();

        Activator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent event) {
                if (event.getProperty().equals(DeprecatedPreferenceConstants.DATA_FORMAT)) {
                    if (tableViewer != null)
                        tableViewer.refresh();
                }
            }
        });
    }

    private void createActions(final ContributionManager toolMan) {

        final Action exportCsv = new Action("Export current plotted data to csv file", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                CSVUtils.createCSV(EclipseUtils.getIFile(getEditorInput()), data, "_plot");
            }
        };
        exportCsv.setImageDescriptor(AnalysisRCPActivator.getImageDescriptor("icons/page_white_excel.png"));
        toolMan.add(exportCsv);

        toolMan.add(new Separator(getClass().getName() + "Sep1"));

        final Action format = new Action("Preferences...", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                        "uk.ac.diamond.scisoft.analysis.rcp.preferencePage", null, null);
                if (pref != null)
                    pref.open();
            }
        };
        format.setImageDescriptor(Activator.getImageDescriptor("icons/application_view_list.png"));
        toolMan.add(format);
    }

    private Map<String, Dataset> data;

    /**
     * This method to creates the table columns required to hold the
     * 1D data currently in the plotter passed in.
     * @param plotter
     */
    private void update(final DataSetPlotter plotter) {

        if (tableViewer != null) {
            GridUtils.setVisible(tableViewer.getTable(), false);
            tableViewer.getTable().dispose();
        }

        final List<IDataset> sets = plotter.getCurrentDataSets();
        if (sets == null || sets.isEmpty()) {
            GridUtils.setVisible(errorLabel, true);
            main.layout();
            return;
        }

        // We put the x values as the first set
        final List<AxisValues> axes = plotter.getXAxisValues();
        final Dataset x = axes.get(0).toDataset();
        x.setName(plotter.getXAxisLabel());
        sets.add(0, x);

        final Table table = new Table(main, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        this.tableViewer = new TableViewer(table);
        table.setLayoutData(new GridData(GridData.FILL_BOTH));
        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        ColumnViewerToolTipSupport.enableFor(tableViewer, ToolTip.NO_RECREATE);
        GridUtils.setVisible(errorLabel, false);
        main.layout();

        if (data == null)
            data = new LinkedHashMap<String, Dataset>();
        data.clear();

        final String[] names = new String[sets.size()];
        for (int i = 0; i < sets.size(); i++) {

            final Dataset set = DatasetUtils.convertToDataset(sets.get(i));

            final TableViewerColumn col = new TableViewerColumn(tableViewer, SWT.RIGHT, i);
            names[i] = set.getName() != null ? set.getName() : "";
            data.put(names[i], set);
            col.getColumn().setText(names[i]);
            col.getColumn().setWidth(150);
            col.setLabelProvider(new ValueColumnProvider(i));
        }
        tableViewer.setUseHashlookup(true);
        tableViewer.setColumnProperties(names);
        final MenuManager menuManager = new MenuManager();
        tableViewer.getControl().setMenu(menuManager.createContextMenu(tableViewer.getControl()));
        createActions(menuManager);

        final Object[] data = getRowData(sets);
        tableViewer.setContentProvider(new IStructuredContentProvider() {
            @Override
            public void dispose() {
            }

            @Override
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            }

            @Override
            public Object[] getElements(Object inputElement) {
                return data;
            }
        });
        tableViewer.setInput(data);
        main.layout();
    }

    /**
     * The data sets are the columns, we need an array of the rows to work
     * best with TableViewer.
     * @param sets
     * @return an array of RowObjects
     */
    protected Object[] getRowData(final List<IDataset> sets) {

        // Find max
        int max = Integer.MIN_VALUE;
        for (IDataset set : sets)
            max = Math.max(max, set.getSize());

        final List<RowObject> rows = new ArrayList<RowObject>(max);
        for (int row = 0; row < max; row++) {
            final RowObject rowOb = new RowObject(row);
            rows.add(rowOb);
            for (IDataset set : sets) {
                try {
                    rowOb.add(set.getDouble(row));
                } catch (Exception ne) {
                    rowOb.add(Double.NaN);
                }
            }
        }

        return rows.toArray(new Object[max]);
    }

    private class RowObject {
        private List<Double> rowValues = new ArrayList<Double>(31);
        private int row;

        RowObject(int row) {
            this.row = row;
        }

        public void add(Double value) {
            rowValues.add(value);
        }

        public Double get(int col) {
            return rowValues.get(col);
        }

        @SuppressWarnings("unused")
        public int getRow() {
            return row;
        }
    }

    private class ValueColumnProvider extends ColumnLabelProvider {
        private int columnIndex;

        ValueColumnProvider(int columnIndex) {
            this.columnIndex = columnIndex;
        }

        @Override
        public String getText(Object element) {
            final RowObject row = (RowObject) element;
            final double val = row.get(columnIndex);
            if (Double.isNaN(val))
                return "";

            return formatValue(val);
        }

        private String formatValue(final double val) {
            final String formatString = Activator.getDefault().getPreferenceStore()
                    .getString(DeprecatedPreferenceConstants.DATA_FORMAT);
            try {
                DecimalFormat format = new DecimalFormat(formatString);
                return format.format(val);
            } catch (Exception ne) {
                logger.debug("Format does not work: " + formatString, ne);
                return String.valueOf(val);
            }
        }

    }

    @Override
    public void setInput(final IEditorInput input) {
        super.setInput(input);
        setPartName(input.getName());
    }

    @Override
    public void setFocus() {
        if (tableViewer != null)
            tableViewer.getControl().setFocus();
    }

    @Override
    public void doSave(IProgressMonitor monitor) {
        // TODO Auto-generated method stub

    }

    @Override
    public void doSaveAs() {
        // TODO Auto-generated method stub

    }

    @Override
    public boolean isSaveAsAllowed() {
        return false;
    }

    @Override
    public void dispose() {
        if (tableViewer != null)
            tableViewer.getControl().dispose();
        if (main != null)
            main.dispose();
        if (data != null)
            data.clear();
        if (plotWindow != null)
            plotWindow = null;
        super.dispose();
    }

    @Override
    public void pageChanged(PageChangedEvent event) {
        if (event.getSelectedPage() == this) { // Just selected this page
            logger.error("PlotWindow does not support DataSetPlotter anymore");
            //         update(plotWindow.getMainPlotter());
        }
    }

}