org.dawb.tango.extensions.editors.MultiScanEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.dawb.tango.extensions.editors.MultiScanEditor.java

Source

/*
 * 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 org.dawb.tango.extensions.editors;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.dawb.common.ui.util.EclipseUtils;
import org.dawb.common.ui.util.GridUtils;
import org.dawb.common.ui.views.PlotDataView;
import org.dawb.common.ui.views.monitor.actions.TangoPreferencesAction;
import org.dawb.common.ui.widgets.ActionBarWrapper;
import org.dawnsci.io.spec.MultiScanDataParser;
import org.dawb.tango.extensions.Activator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dawnsci.plotting.api.IPlottingSystem;
import org.eclipse.dawnsci.plotting.api.PlotType;
import org.eclipse.dawnsci.plotting.api.PlottingFactory;
import org.eclipse.dawnsci.plotting.api.trace.ColorOption;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.jface.action.Action;
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.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IActionBars2;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.IPage;
import org.eclipse.ui.part.PageBookView;
import org.eclipse.ui.progress.IProgressService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An editor which combines a plot with a graph of data sets.
 * 
 * Currently this is for 1D analyses only so if the data does not contain 1D, this
 * editor will not show.
 * 
 */
public class MultiScanEditor extends EditorPart implements IReusableEditor {

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

    // This view is a composite of two other views.
    private IPlottingSystem<Composite> plottingSystem;
    private MultiScanDataParser data;
    private boolean isDefaultConnectedSpec;
    private Composite plot;

    private MenuManager menuMan;

    public MultiScanEditor(final boolean isConnectedSpec) {

        this.isDefaultConnectedSpec = isConnectedSpec;
        try {
            this.plottingSystem = PlottingFactory.createPlottingSystem();
            plottingSystem.setColorOption(ColorOption.BY_DATA);
        } catch (Exception e) {
            logger.error("Cannot locate any plotting systems!", e);
        }
    }

    @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(final Composite parent) {

        final Composite main = new Composite(parent, SWT.NONE);
        final GridLayout gridLayout = new GridLayout(1, false);
        main.setLayout(gridLayout);
        GridUtils.removeMargins(main);

        final Composite tools = new Composite(main, SWT.RIGHT);
        tools.setLayout(new GridLayout(2, false));
        GridUtils.removeMargins(tools);
        tools.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));

        // 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.
        ToolBarManager toolMan = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
        final ToolBar toolBar = toolMan.createControl(tools);
        toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));

        ToolBarManager extraMan = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
        final ToolBar extraBar = extraMan.createControl(tools);
        extraBar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));

        this.menuMan = new MenuManager();
        final IActionBars bars = this.getEditorSite().getActionBars();
        ActionBarWrapper wrapper = new ActionBarWrapper(toolMan, null, null, (IActionBars2) bars);

        createCustomMenuBarActionsRight(menuMan);
        createCustomToolbarActionsRight(extraMan);
        Action menuAction = new Action("", Activator.imageDescriptorFromPlugin("icons/DropDown.png")) {
            @Override
            public void run() {
                final Menu mbar = menuMan.createContextMenu(extraBar);
                mbar.setVisible(true);
            }
        };
        extraMan.add(menuAction);

        this.plot = new Composite(main, SWT.BORDER);
        plot.setLayout(new FillLayout());
        plot.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        // NOTE use name of input. This means that although two files of the same
        // name could be opened, the editor name is clearly visible in the GUI and
        // is usually short.
        final String plotName = this.getEditorInput().getName();

        plottingSystem.createPlotPart(plot, plotName, wrapper, PlotType.XY, this);

        // Finally
        if (toolMan != null)
            toolMan.update(true);
        if (extraMan != null)
            extraMan.update(true);

    }

    private void createCustomMenuBarActionsRight(final MenuManager menuMan) {

        menuMan.add(new Action("Unselect and collapse all") {
            public void run() {
                plottingSystem.reset();

                final MultiScanComponent comp = getMultiScanComponent(false);
                if (comp == null)
                    return;

                comp.clear();

            }
        });
        final Action tableColumns = new Action("Preferences...", IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                PreferenceDialog pref = PreferencesUtil.createPreferenceDialogOn(
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                        "org.edna.workbench.editors.preferencePage", null, null);
                if (pref != null)
                    pref.open();
            }
        };
        tableColumns.setImageDescriptor(Activator.imageDescriptorFromPlugin("icons/application_view_columns.png"));
        menuMan.add(tableColumns);
    }

    /**
     * Override to provide extra content.
     * @param toolMan
     */
    protected void createCustomToolbarActionsRight(final ToolBarManager toolMan) {

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

        final Action connectSpec = new Action("Disconnect from spec.", IAction.AS_CHECK_BOX) {
            @Override
            public void run() {
                final IEditorPart part = EclipseUtils.getActiveEditor();
                if (part instanceof MultiScanMultiEditor) {
                    final boolean isConnected = ((MultiScanMultiEditor) part).toggleConnect();
                    setChecked(isConnected);
                    if (isConnected) {
                        setText("Disconnect from spec.");
                    } else {
                        setText("Connect to spec.");
                        final String errorMessage = ((MultiScanMultiEditor) part).getSpecError();
                        if (errorMessage != null) {
                            boolean yes = MessageDialog.openQuestion(getSite().getShell(), "Cannot Connect",
                                    errorMessage
                                            + "\n\nWould you like to open the Tango Preferences and configure the connection?");
                            if (yes)
                                try {
                                    (new TangoPreferencesAction()).execute(null);
                                } catch (Exception ne) {
                                    logger.error("Cannot open Tango Preferences!", ne);
                                }
                        }
                    }
                }
            }
        };
        connectSpec.setChecked(isDefaultConnectedSpec);
        if (isDefaultConnectedSpec) {
            connectSpec.setText("Disconnect from spec.");
        } else {
            connectSpec.setText("Connect to spec.");
        }
        connectSpec.setImageDescriptor(Activator.imageDescriptorFromPlugin("icons/connect_spec.png"));

        toolMan.add(connectSpec);

    }

    private boolean doingUpdate = false;

    /**
     * 
     * @param selections - takes copy and possibly modifies it
     */
    protected void updatePlot(final List<Dataset> sel) {

        if (doingUpdate)
            return;

        try {
            doingUpdate = true;
            if (sel == null || sel.size() < 1) {
                plottingSystem.reset();
                return;
            }

            final List<IDataset> selections = new ArrayList<IDataset>(sel);

            IProgressService service = getEditorSite() != null
                    ? (IProgressService) getSite().getService(IProgressService.class)
                    : (IProgressService) PlatformUI.getWorkbench().getService(IProgressService.class);
            try {
                service.run(true, true, new IRunnableWithProgress() {
                    @Override
                    public void run(final IProgressMonitor monitor)
                            throws InvocationTargetException, InterruptedException {

                        monitor.beginTask("Updating selected DataSets", 100);

                        final IDataset x = selections.remove(0);
                        plottingSystem.clear();
                        plottingSystem.createPlot1D(x, selections, monitor);

                        monitor.done();
                    }
                });
            } catch (Exception e) {
                logger.error("Cannot create plot required.", e);
            }
        } finally {
            doingUpdate = false;
        }
    }

    @Override
    public void setInput(final IEditorInput input) {
        super.setInput(input);
        setPartName(input.getName());
        try {
            data = new MultiScanDataParser(EclipseUtils.getInputStream(input));
        } catch (Exception e) {
            logger.error("Cannot read " + input.getName(), e);
        }
    }

    @Override
    public void setFocus() {
        plot.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 (plottingSystem != null)
            plottingSystem.dispose();
        super.dispose();
    }

    /**
     * Thread safe update method.
     * @param line
     */
    public void addLine(final String line) {

        if (line == null || "".equals(line))
            return;

        final MultiScanComponent multiScanComponent = getMultiScanComponent(false);
        if (multiScanComponent == null)
            return;

        final String scanName = this.data.processLine(line);

        if (scanName != null) {
            this.data.update(false);
            getSite().getShell().getDisplay().asyncExec(new Runnable() {
                @Override
                public void run() {
                    multiScanComponent.refresh(scanName);
                }
            });
        }
    }

    public void setPlot(String scanName, String... plotNames) {
        MultiScanComponent multiScanComponent = getMultiScanComponent(true);
        if (multiScanComponent == null)
            return;
        multiScanComponent.setPlot(scanName, plotNames);
    }

    private MultiScanComponent getMultiScanComponent(boolean showView) {

        final IWorkbenchPage wb = EclipseUtils.getActivePage();
        if (wb == null)
            return null;

        PageBookView view = (PageBookView) wb.findView(PlotDataView.ID);
        if (view == null && showView)
            try {
                view = (PageBookView) wb.showView(PlotDataView.ID);
            } catch (PartInitException e) {
                return null;
            }
        if (view == null)
            return null;

        IPage page = view.getCurrentPage();
        if (!(page instanceof MultiScanPage))
            return null;
        return ((MultiScanPage) page).getMultiScanComponent();
    }

    public IPlottingSystem<Composite> getPlottingSystem() {
        return this.plottingSystem;
    }

    public MultiScanDataParser getData() {
        return data;
    }

    public MenuManager getMenuManager() {
        return this.menuMan;
    }
}