org.csstudio.opibuilder.visualparts.ScriptsInputDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.csstudio.opibuilder.visualparts.ScriptsInputDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * 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.csstudio.opibuilder.visualparts;

import java.util.ArrayList;
import java.util.List;

import org.csstudio.opibuilder.OPIBuilderPlugin;
import org.csstudio.opibuilder.model.AbstractWidgetModel;
import org.csstudio.opibuilder.script.PVTuple;
import org.csstudio.opibuilder.script.ScriptData;
import org.csstudio.opibuilder.script.ScriptService;
import org.csstudio.opibuilder.script.ScriptService.ScriptType;
import org.csstudio.opibuilder.script.ScriptsInput;
import org.csstudio.opibuilder.scriptUtil.FileUtil;
import org.csstudio.opibuilder.util.ResourceUtil;
import org.csstudio.ui.util.CustomMediaFactory;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;

/**The dialog for scripts input editing.
 * @author Xihui Chen
 *
 */
public class ScriptsInputDialog extends HelpTrayDialog {

    private Action addAction;
    private Action editAction;
    private Action removeAction;
    private Action moveUpAction;
    private Action moveDownAction;
    private Action convertToEmbedAction;

    private TableViewer scriptsViewer;
    private PVTupleTableEditor pvsEditor;
    private Button skipFirstExecutionButton;
    private Button checkConnectivityButton;
    private Button stopExecuteOnErrorButton;

    private List<ScriptData> scriptDataList;
    private String title;

    private IPath startPath;

    private AbstractWidgetModel widgetModel;

    public ScriptsInputDialog(Shell parentShell, ScriptsInput scriptsInput, String dialogTitle,
            AbstractWidgetModel widgetModel) {
        super(parentShell);
        setShellStyle(getShellStyle() | SWT.RESIZE);
        this.scriptDataList = scriptsInput.getCopy().getScriptList();
        title = dialogTitle;
        this.widgetModel = widgetModel;
        this.startPath = widgetModel.getRootDisplayModel().getOpiFilePath().removeLastSegments(1);
    }

    @Override
    protected void okPressed() {
        pvsEditor.forceFocus();
        for (ScriptData scriptData : scriptDataList) {
            boolean hasTrigger = false;
            for (PVTuple pvTuple : scriptData.getPVList()) {
                hasTrigger |= pvTuple.trigger;
            }
            if (!hasTrigger) {
                MessageDialog.openWarning(getShell(), "Warning",
                        NLS.bind("At least one trigger PV must be selected for the script:\n{0}",
                                scriptData.getPath().toString()));
                return;
            }
        }
        super.okPressed();
    }

    @Override
    protected String getHelpResourcePath() {
        return "/" + OPIBuilderPlugin.PLUGIN_ID + "/html/Script.html"; //$NON-NLS-1$; //$NON-NLS-2$
    }

    /**
     * @return the scriptDataList
     */
    public final List<ScriptData> getScriptDataList() {
        return scriptDataList;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void configureShell(final Shell shell) {
        super.configureShell(shell);
        if (title != null) {
            shell.setText(title);
        }
    }

    /**
     * Creates 'wrapping' label with the given text.
     *
     * @param parent
     *            The parent for the label
     * @param text
     *            The text for the label
     */
    private void createLabel(final Composite parent, final String text) {
        Label label = new Label(parent, SWT.WRAP);
        label.setText(text);
        label.setLayoutData(new GridData(SWT.FILL, 0, false, false));
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        final Composite parent_Composite = (Composite) super.createDialogArea(parent);

        // Parent composite has GridLayout with 1 columns.
        // Create embedded composite w/ 2 columns
        final Composite mainComposite = new Composite(parent_Composite, SWT.None);
        mainComposite.setLayout(new GridLayout(2, false));
        GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        gridData.heightHint = 250;
        mainComposite.setLayoutData(gridData);

        // Left Panel: List of scripts
        final Composite leftComposite = new Composite(mainComposite, SWT.NONE);
        leftComposite.setLayout(new GridLayout(1, false));
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd.widthHint = 350;
        leftComposite.setLayoutData(gd);
        createLabel(leftComposite, "Scripts");

        Composite toolBarComposite = new Composite(leftComposite, SWT.BORDER);
        GridLayout gridLayout = new GridLayout(1, false);
        gridLayout.marginLeft = 0;
        gridLayout.marginRight = 0;
        gridLayout.marginBottom = 0;
        gridLayout.marginTop = 0;
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        toolBarComposite.setLayout(gridLayout);
        gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        toolBarComposite.setLayoutData(gd);

        ToolBarManager toolbarManager = new ToolBarManager(SWT.FLAT);
        ToolBar toolBar = toolbarManager.createControl(toolBarComposite);
        GridData grid = new GridData();
        grid.horizontalAlignment = GridData.FILL;
        grid.verticalAlignment = GridData.BEGINNING;
        toolBar.setLayoutData(grid);
        createActions();
        toolbarManager.add(addAction);
        toolbarManager.add(editAction);
        toolbarManager.add(removeAction);
        toolbarManager.add(moveUpAction);
        toolbarManager.add(moveDownAction);
        toolbarManager.add(convertToEmbedAction);

        toolbarManager.update(true);

        scriptsViewer = createScriptsTableViewer(toolBarComposite);
        scriptsViewer.setInput(scriptDataList);

        // Right panel: Input PVs for selected script
        final Composite rightComposite = new Composite(mainComposite, SWT.NONE);
        gridLayout = new GridLayout(1, false);
        rightComposite.setLayout(gridLayout);
        gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd.minimumWidth = 250; // Account for the StringTableEditor's minimum size
        rightComposite.setLayoutData(gd);
        this.createLabel(rightComposite, "");

        TabFolder tabFolder = new TabFolder(rightComposite, SWT.None);
        tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        TabItem pvTab = new TabItem(tabFolder, SWT.NONE);
        pvTab.setText("Input PVs");
        TabItem optionTab = new TabItem(tabFolder, SWT.NONE);
        optionTab.setText("Options");

        pvsEditor = new PVTupleTableEditor(tabFolder, new ArrayList<PVTuple>(), SWT.NONE);
        pvsEditor.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        pvsEditor.setEnabled(false);

        pvTab.setControl(pvsEditor);

        final Composite optionTabComposite = new Composite(tabFolder, SWT.None);
        optionTabComposite.setLayout(new GridLayout(1, false));
        optionTab.setControl(optionTabComposite);
        skipFirstExecutionButton = new Button(optionTabComposite, SWT.CHECK | SWT.WRAP);
        skipFirstExecutionButton.setText("Skip executions triggered by PVs' first value.");
        skipFirstExecutionButton.setToolTipText(
                "Skip the script executions triggered by PVs' first connections during OPI startup.\n"
                        + "This is useful if you want to trigger a script from user inputs only.");
        skipFirstExecutionButton.setSelection(false);
        skipFirstExecutionButton.setEnabled(false);
        skipFirstExecutionButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty()) {
                    ((ScriptData) selection.getFirstElement())
                            .setSkipPVsFirstConnection(skipFirstExecutionButton.getSelection());
                }
            }
        });
        gd = new GridData(SWT.FILL, SWT.FILL, true, false);
        Point preferredSize = skipFirstExecutionButton.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        gd.widthHint = preferredSize.x;
        gd.minimumHeight = preferredSize.y;
        skipFirstExecutionButton.setLayoutData(gd);

        checkConnectivityButton = new Button(optionTabComposite, SWT.CHECK | SWT.WRAP);
        checkConnectivityButton.setSelection(false);
        checkConnectivityButton.setText("Execute anyway even if some PVs are disconnected.");
        checkConnectivityButton.setToolTipText(
                "This is only useful if you want to handle PVs' disconnection in script.\nOtherwise, please keep it unchecked.");
        checkConnectivityButton.setEnabled(false);
        checkConnectivityButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty()) {
                    ((ScriptData) selection.getFirstElement())
                            .setCheckConnectivity(!checkConnectivityButton.getSelection());
                }
                if (checkConnectivityButton.getSelection()) {
                    MessageDialog.openWarning(getShell(), "Warning", "If this option is checked, "
                            + "the script itself is responsible for checking PV's connectivity before using that PV in the script.\n"
                            + "Otherwise, you will probably get an error message with java.lang.NullPointerException. \n"
                            + "PV's connectivity can be checked via this method: pvArray[#].isConnected()");
                }
            }
        });
        gd = new GridData(SWT.FILL, SWT.FILL, true, false);
        preferredSize = checkConnectivityButton.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        gd.widthHint = preferredSize.x;
        gd.minimumHeight = preferredSize.y;
        checkConnectivityButton.setLayoutData(gd);

        stopExecuteOnErrorButton = new Button(optionTabComposite, SWT.CHECK | SWT.WRAP);
        stopExecuteOnErrorButton.setSelection(false);
        stopExecuteOnErrorButton.setText("Do not execute the script if error was detected.");
        stopExecuteOnErrorButton.setToolTipText("If this option is selected, the script will not be executed \n"
                + "on next trigger if error was detected in the script.");
        stopExecuteOnErrorButton.setEnabled(false);
        stopExecuteOnErrorButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty()) {
                    ((ScriptData) selection.getFirstElement())
                            .setStopExecuteOnError(stopExecuteOnErrorButton.getSelection());
                }
            }
        });
        gd = new GridData(SWT.FILL, SWT.FILL, true, false);
        preferredSize = stopExecuteOnErrorButton.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        gd.widthHint = preferredSize.x;
        gd.minimumHeight = preferredSize.y;
        stopExecuteOnErrorButton.setLayoutData(gd);

        if (scriptDataList.size() > 0) {
            setScriptsViewerSelection(scriptDataList.get(0));
            checkConnectivityButton.setSelection(!scriptDataList.get(0).isCheckConnectivity());
            skipFirstExecutionButton.setSelection(scriptDataList.get(0).isSkipPVsFirstConnection());
            stopExecuteOnErrorButton.setSelection(scriptDataList.get(0).isStopExecuteOnError());

        }
        return parent_Composite;
    }

    /**
     * Refreshes the enabled-state of the actions.
     */
    private void refreshGUIOnSelection() {

        IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
        if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
            removeAction.setEnabled(true);
            moveUpAction.setEnabled(true);
            moveDownAction.setEnabled(true);
            convertToEmbedAction.setEnabled(!((ScriptData) selection.getFirstElement()).isEmbedded());

            editAction.setEnabled(true);
            pvsEditor.updateInput(((ScriptData) selection.getFirstElement()).getPVList());
            pvsEditor.setEnabled(true);
            checkConnectivityButton.setSelection(!((ScriptData) selection.getFirstElement()).isCheckConnectivity());
            checkConnectivityButton.setEnabled(true);
            skipFirstExecutionButton
                    .setSelection(((ScriptData) selection.getFirstElement()).isSkipPVsFirstConnection());
            skipFirstExecutionButton.setEnabled(true);
            stopExecuteOnErrorButton
                    .setSelection(((ScriptData) selection.getFirstElement()).isStopExecuteOnError());
            stopExecuteOnErrorButton.setEnabled(true);

        } else {
            removeAction.setEnabled(false);
            moveUpAction.setEnabled(false);
            moveDownAction.setEnabled(false);
            convertToEmbedAction.setEnabled(false);
            pvsEditor.setEnabled(false);
            editAction.setEnabled(false);
            checkConnectivityButton.setEnabled(false);
            skipFirstExecutionButton.setEnabled(false);
            stopExecuteOnErrorButton.setEnabled(false);
        }
    }

    private void setScriptsViewerSelection(ScriptData scriptData) {
        scriptsViewer.refresh();
        if (scriptData == null)
            scriptsViewer.setSelection(StructuredSelection.EMPTY);
        else {
            scriptsViewer.setSelection(new StructuredSelection(scriptData));
        }
    }

    /**
     * Creates and configures a {@link TableViewer}.
     *
     * @param parent
     *            The parent for the table
     * @return The {@link TableViewer}
     */
    private TableViewer createScriptsTableViewer(final Composite parent) {
        TableViewer viewer = new TableViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.SINGLE);
        viewer.setContentProvider(new BaseWorkbenchContentProvider() {
            @SuppressWarnings("unchecked")
            @Override
            public Object[] getElements(final Object element) {
                return (((List<ScriptData>) element).toArray());
            }
        });
        viewer.setLabelProvider(new WorkbenchLabelProvider());
        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                refreshGUIOnSelection();
            }
        });
        viewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        return viewer;
    }

    /**
     * Creates the actions.
     */
    private void createActions() {
        addAction = new Action("Add") {
            @Override
            public void run() {
                ScriptChoiceDialog scriptChoiceDialog = new ScriptChoiceDialog(getShell());
                if (scriptChoiceDialog.open() == Window.CANCEL)
                    return;
                ScriptData scriptData = null;
                if (scriptChoiceDialog.isEmbedded()) {
                    EmbeddedScriptEditDialog scriptEditDialog = new EmbeddedScriptEditDialog(getShell(), null);
                    if (scriptEditDialog.open() == Window.OK)
                        scriptData = scriptEditDialog.getResult();
                } else {
                    IPath path;
                    RelativePathSelectionDialog rsd = new RelativePathSelectionDialog(
                            Display.getCurrent().getActiveShell(), startPath, "Select a script file",
                            new String[] { ScriptService.JS, ScriptService.PY });
                    rsd.setSelectedResource(new Path("./")); //$NON-NLS-1$
                    if (rsd.open() == Window.OK) {
                        if (rsd.getSelectedResource() != null) {
                            path = rsd.getSelectedResource();
                            scriptData = new ScriptData(path);
                        }
                    }
                }
                if (scriptData != null) {
                    scriptDataList.add(scriptData);
                    setScriptsViewerSelection(scriptData);
                }
            }
        };
        addAction.setToolTipText("Add a script");
        addAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/add.gif")); //$NON-NLS-1$

        editAction = new Action("Edit") {
            @Override
            public void run() {
                IPath path;
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
                    ScriptData sd = (ScriptData) selection.getFirstElement();
                    if (sd.isEmbedded()) {
                        EmbeddedScriptEditDialog scriptEditDialog = new EmbeddedScriptEditDialog(getShell(), sd);
                        if (scriptEditDialog.open() == Window.OK) {
                            ScriptData newSd = scriptEditDialog.getResult();
                            sd.setScriptName(newSd.getScriptName());
                            sd.setScriptType(newSd.getScriptType());
                            sd.setScriptText(newSd.getScriptText());
                            setScriptsViewerSelection(sd);
                        }
                    } else {
                        RelativePathSelectionDialog rsd = new RelativePathSelectionDialog(getShell(), startPath,
                                "Select a script file", new String[] { ScriptService.JS, ScriptService.PY });
                        rsd.setSelectedResource(((ScriptData) selection.getFirstElement()).getPath());
                        if (rsd.open() == Window.OK) {
                            if (rsd.getSelectedResource() != null) {
                                path = rsd.getSelectedResource();
                                sd.setPath(path);
                                setScriptsViewerSelection(sd);
                            }
                        }
                    }

                }

            }
        };
        editAction.setToolTipText("Edit/Change script path");
        editAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/edit.gif")); //$NON-NLS-1$
        editAction.setEnabled(false);
        removeAction = new Action() {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
                    scriptDataList.remove((ScriptData) selection.getFirstElement());
                    setScriptsViewerSelection(null);
                    this.setEnabled(false);
                }
            }
        };
        removeAction.setText("Remove Script");
        removeAction.setToolTipText("Remove the selected script from the list");
        removeAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/delete.gif")); //$NON-NLS-1$
        removeAction.setEnabled(false);

        moveUpAction = new Action() {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
                    ScriptData scriptData = (ScriptData) selection.getFirstElement();
                    int i = scriptDataList.indexOf(scriptData);
                    if (i > 0) {
                        scriptDataList.remove(scriptData);
                        scriptDataList.add(i - 1, scriptData);
                        setScriptsViewerSelection(scriptData);
                    }
                }
            }
        };
        moveUpAction.setText("Move Script Up");
        moveUpAction.setToolTipText("Move selected script up");
        moveUpAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/search_prev.gif")); //$NON-NLS-1$
        moveUpAction.setEnabled(false);

        moveDownAction = new Action() {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
                    ScriptData scriptData = (ScriptData) selection.getFirstElement();
                    int i = scriptDataList.indexOf(scriptData);
                    if (i < scriptDataList.size() - 1) {
                        scriptDataList.remove(scriptData);
                        scriptDataList.add(i + 1, scriptData);
                        setScriptsViewerSelection(scriptData);
                    }
                }
            }
        };
        moveDownAction.setText("Move Script Down");
        moveDownAction.setToolTipText("Move selected script down");
        moveDownAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/search_next.gif")); //$NON-NLS-1$
        moveDownAction.setEnabled(false);

        convertToEmbedAction = new Action() {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) scriptsViewer.getSelection();
                if (!selection.isEmpty() && selection.getFirstElement() instanceof ScriptData) {
                    ScriptData sd = (ScriptData) selection.getFirstElement();
                    if (!sd.isEmbedded()) {
                        IPath absoluteScriptPath = sd.getPath();
                        if (!absoluteScriptPath.isAbsolute()) {
                            absoluteScriptPath = ResourceUtil.buildAbsolutePath(widgetModel, absoluteScriptPath);
                            if (!ResourceUtil.isExsitingFile(absoluteScriptPath, true)) {
                                //search from OPI search path
                                absoluteScriptPath = ResourceUtil.getFileOnSearchPath(sd.getPath(), true);
                            }
                        }

                        try {
                            String text = FileUtil.readTextFile(absoluteScriptPath.toString());
                            String ext = absoluteScriptPath.getFileExtension().trim().toLowerCase();
                            if (ext.equals(ScriptService.JS))
                                sd.setScriptType(ScriptType.JAVASCRIPT);
                            else if (ext.equals(ScriptService.PY))
                                sd.setScriptType(ScriptType.PYTHON);
                            else {
                                MessageDialog.openError(getShell(), "Failed", "The script type is not recognized.");
                                return;
                            }
                            sd.setEmbedded(true);
                            sd.setScriptText(text);
                            sd.setScriptName(absoluteScriptPath.removeFileExtension().lastSegment());
                            setScriptsViewerSelection(sd);
                        } catch (Exception e) {
                            MessageDialog.openError(getShell(), "Failed", "Failed to read script file");
                        }

                    }

                }
            }
        };
        convertToEmbedAction.setText("Convert to Embedded Script");
        convertToEmbedAction.setToolTipText("Convert to Embedded Script");
        convertToEmbedAction.setImageDescriptor(CustomMediaFactory.getInstance()
                .getImageDescriptorFromPlugin(OPIBuilderPlugin.PLUGIN_ID, "icons/convertToEmbedded.png")); //$NON-NLS-1$
        convertToEmbedAction.setEnabled(false);
    }

}