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.dawb.workbench.ui.editors; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.dawb.common.ui.util.CSVUtils; import org.dawb.common.ui.util.EclipseUtils; import org.dawb.common.ui.util.GridUtils; import org.dawb.workbench.ui.Activator; import org.dawb.workbench.ui.editors.preference.EditorConstants; 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.slicing.api.editor.ISelectedPlotting; import org.eclipse.dawnsci.slicing.api.editor.ISlicablePlottingPart; 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; /** * 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 CSVDataEditor extends EditorPart implements IReusableEditor, IPageChangedListener { private static Logger logger = LoggerFactory.getLogger(CSVDataEditor.class); // This view is a composite of two other views. private TableViewer tableViewer; private CLabel errorLabel; private Composite main; private Map<String, IDataset> data; private ISlicablePlottingPart dataProvider; private IPropertyChangeListener propListener; public CSVDataEditor() { } public void setDataProvider(final ISlicablePlottingPart dataHolder) { this.dataProvider = dataHolder; } @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(Activator.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(); this.propListener = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(EditorConstants.DATA_FORMAT)) { if (tableViewer != null) tableViewer.refresh(); } } }; Activator.getDefault().getPreferenceStore().addPropertyChangeListener(propListener); } private void createActions(final ContributionManager toolMan) { final Action refresh = new Action("Refresh", IAction.AS_PUSH_BUTTON) { @Override public void run() { update(); } }; refresh.setImageDescriptor(Activator.getImageDescriptor("icons/reset.gif")); toolMan.add(refresh); toolMan.add(new Separator(getClass().getName() + "Sep1")); 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(Activator.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); } /** * This method to creates the table columns required to hold the * 1D data currently in the plotter passed in. * * The first data set is should usually be the x value. * * @param plotter */ private void update() { if (tableViewer != null) { if (!tableViewer.getControl().isDisposed()) { GridUtils.setVisible(tableViewer.getTable(), false); tableViewer.getTable().dispose(); } } this.data = dataProvider instanceof ISelectedPlotting ? ((ISelectedPlotting) dataProvider).getSelected() : null; if (data == null || data.isEmpty()) { GridUtils.setVisible(errorLabel, true); main.layout(); return; } //check if data is not 3d if (data.values().size() == 1 && data.values().iterator().next().getShape().length == 3) { errorLabel.setText("The Data tab cannot display 3D dataset."); GridUtils.setVisible(errorLabel, true); main.layout(); return; } 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(); final boolean is2D = data.size() == 1 && data.values().iterator().next().getShape().length == 2; int i = 0; for (String name : data.keySet()) { final Dataset set = (Dataset) data.get(name); final TableViewerColumn col = new TableViewerColumn(tableViewer, SWT.RIGHT, i); final String colName = set.getName() != null ? set.getName() : ""; col.getColumn().setText(colName); if (is2D) { col.setLabelProvider(new BufferColumnProvider()); col.getColumn().setWidth(3000); } else { col.setLabelProvider(new ValueColumnProvider(i)); col.getColumn().setWidth(150); } ++i; } tableViewer.setUseHashlookup(true); tableViewer.setColumnProperties(data.keySet().toArray(new String[data.size()])); final MenuManager menuManager = new MenuManager(); tableViewer.getControl().setMenu(menuManager.createContextMenu(tableViewer.getControl())); createActions(menuManager); final RowObject[] rowData = getRowData(data.values()); 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 rowData; } }); tableViewer.setInput(rowData); 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 RowObject[] getRowData(final Collection<IDataset> sets) { if (sets.size() == 1 && sets.iterator().next().getShape().length == 2) { final Dataset set = (Dataset) sets.iterator().next(); final int[] shape = set.getShape(); final List<RowObject> rows = new ArrayList<RowObject>(shape[0]); for (int row = 0; row < shape[0]; row++) { final RowObject rowOb = new RowObject(row); rows.add(rowOb); for (int col = 0; col < shape[1]; col++) { rowOb.add(set.getDouble(row, col)); } } return rows.toArray(new RowObject[rows.size()]); } else { // 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 RowObject[rows.size()]); } } private class RowObject { private List<Float> rowValues = new ArrayList<Float>(31); private int row; RowObject(int row) { this.row = row; } public void add(float value) { rowValues.add(value); } public void add(double value) { rowValues.add((float) value); } public Float get(int col) { return rowValues.get(col); } public int getRow() { return row; } public String toString() { return rowValues.toString(); } } 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(EditorConstants.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); } } } private class BufferColumnProvider extends ColumnLabelProvider { @Override public String getText(Object element) { final RowObject row = (RowObject) element; return row.toString(); } } @Override public void setInput(final IEditorInput input) { super.setInput(input); setPartName(input.getName()); } @Override public void setFocus() { try { if (tableViewer == null) return; if (tableViewer.getControl().isDisposed()) return; if (tableViewer != null) tableViewer.getControl().setFocus(); } catch (Throwable ne) { return; // Intentionally ignored. } } @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() { Activator.getDefault().getPreferenceStore().removePropertyChangeListener(propListener); if (tableViewer != null) tableViewer.getControl().dispose(); if (main != null) main.dispose(); if (data != null) data.clear(); dataProvider = null; super.dispose(); } @Override public void pageChanged(PageChangedEvent event) { if (event.getSelectedPage() == this) { // Just selected this page update(); } } }