com.arc.cdt.debug.seecode.internal.ui.action.AbstractDebugActionDelegate.java Source code

Java tutorial

Introduction

Here is the source code for com.arc.cdt.debug.seecode.internal.ui.action.AbstractDebugActionDelegate.java

Source

/*******************************************************************************
 * Copyright (c) 2005-2012 Synopsys, Incorporated
 * 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
 *
 * Contributors:
 * Synopsys, Inc - Initial implementation 
 *******************************************************************************/
package com.arc.cdt.debug.seecode.internal.ui.action;

import java.util.Iterator;

import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IActionDelegate2;
import org.eclipse.ui.INullSelectionListener;
import org.eclipse.ui.IViewActionDelegate;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

/**
 * Copied from CDT internal class.
 * @author davidp
 * @currentOwner <a href="mailto:davidp@arc.com">davidp</a>
 * @version $Revision$
 * @lastModified $Date$
 * @lastModifiedBy $Author$
 * @reviewed 0 $Revision:1$
 */

public abstract class AbstractDebugActionDelegate
        implements IWorkbenchWindowActionDelegate, IViewActionDelegate, IActionDelegate2, INullSelectionListener {

    /**
     * The underlying action for this delegate
     */
    private IAction fAction;
    /**
     * This action's view part, or <code>null</code>
     * if not installed in a view.
     */
    private IViewPart fViewPart;

    /**
     * Cache of the most recent seletion
     */
    private IStructuredSelection fSelection = StructuredSelection.EMPTY;

    /**
     * Whether this delegate has been initialized
     */
    private boolean fInitialized = false;

    /**
     * The window associated with this action delegate
     * May be <code>null</code>
     */
    protected IWorkbenchWindow fWindow;

    /**
     * Background job for this action, or <code>null</code> if none.
     */
    private DebugRequestJob fBackgroundJob = null;

    class DebugRequestJob extends Job {

        private Object[] fElements = null;

        /** 
         * Constructs a new job to perform a debug request (for example, step)
         * in the background.
         * 
         * @param name job name
         */
        public DebugRequestJob(String name) {
            super(name);
            setPriority(Job.INTERACTIVE);
        }

        /* (non-Javadoc)
         * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
         */
        @Override
        protected IStatus run(IProgressMonitor monitor) {
            MultiStatus status = new MultiStatus(CDebugUIPlugin.getUniqueIdentifier(),
                    DebugException.REQUEST_FAILED, getStatusMessage(), null);
            for (int i = 0; i < fElements.length; i++) {
                Object element = fElements[i];
                try {
                    doAction(element);
                } catch (DebugException e) {
                    status.merge(e.getStatus());
                }
            }
            return status;
        }

        /**
         * Sets the selection to operate on.
         * 
         * @param elements
         */
        public void setTargets(Object[] elements) {
            fElements = elements;
        }

    }

    /**
     * It's crucial that delegate actions have a zero-arg constructor so that
     * they can be reflected into existence when referenced in an action set
     * in the plugin's plugin.xml file.
     */
    public AbstractDebugActionDelegate() {
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
     */
    @Override
    public void dispose() {
        if (getWindow() != null) {
            getWindow().getSelectionService().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
        }
        fBackgroundJob = null;
        fSelection = null;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
     */
    @Override
    public void init(IWorkbenchWindow window) {
        // listen to selection changes in the debug view
        setWindow(window);
        window.getSelectionService().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
     */
    @Override
    public void run(IAction action) {
        if (action.isEnabled()) {
            IStructuredSelection selection = getSelection();
            // disable the action so it cannot be run again until an event or selection change
            // updates the enablement
            action.setEnabled(false);
            if (isRunInBackground()) {
                runInBackground(action, selection);
            } else {
                runInForeground(selection);
            }
        }
    }

    /**
     * Runs this action in a background job.
     */
    private void runInBackground(IAction action, IStructuredSelection selection) {
        if (fBackgroundJob == null) {
            fBackgroundJob = new DebugRequestJob(action.getText());
        }
        fBackgroundJob.setTargets(selection.toArray());
        fBackgroundJob.schedule();
    }

    /**
     * Runs this action in the UI thread.
     */
    private void runInForeground(final IStructuredSelection selection) {
        final MultiStatus status = new MultiStatus(CDebugUIPlugin.getUniqueIdentifier(),
                DebugException.REQUEST_FAILED, getStatusMessage(), null);
        BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
            @SuppressWarnings("unchecked")
            @Override
            public void run() {
                Iterator<Object> selectionIter = selection.iterator();
                while (selectionIter.hasNext()) {
                    Object element = selectionIter.next();
                    try {
                        doAction(element);
                    } catch (DebugException e) {
                        status.merge(e.getStatus());
                    }
                }
            }
        });
        reportErrors(status);
    }

    private void reportErrors(final MultiStatus ms) {
        if (!ms.isOK()) {
            IWorkbenchWindow window = CDebugUIPlugin.getActiveWorkbenchWindow();
            if (window != null) {
                ErrorDialog.openError(window.getShell(), getErrorDialogTitle(), getErrorDialogMessage(), ms);
            } else {
                CDebugUIPlugin.log(ms);
            }
        }
    }

    /**
     * Returns whether or not this action should be run in the background.
     * Subclasses may override.
     * @return whether or not this action should be run in the background
     */
    protected boolean isRunInBackground() {
        return false;
    }

    /**
     * AbstractDebugActionDelegates come in 2 flavors: IViewActionDelegate, 
     * IWorkbenchWindowActionDelegate delegates.
     * </p>
     * <ul>
     * <li>IViewActionDelegate delegate: getView() != null</li>
     * <li>IWorkbenchWindowActionDelegate: getView == null</li>
     * </ul>
     * <p>
     * Only want to call update(action, selection) for IViewActionDelegates.
     * An initialize call to update(action, selection) is made for all flavors to set the initial
     * enabled state of the underlying action.
     * IWorkbenchWindowActionDelegate's listen to selection changes
     * in the debug view only.
     * </p>
     * 
     * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
     */
    @Override
    public void selectionChanged(IAction action, ISelection s) {
        boolean wasInitialized = initialize(action, s);
        if (!wasInitialized) {
            if (getView() != null) {
                update(action, s);
            }
        }
    }

    protected void update(IAction action, ISelection s) {
        if (s instanceof IStructuredSelection) {
            IStructuredSelection ss = (IStructuredSelection) s;
            action.setEnabled(getEnableStateForSelection(ss));
            setSelection(ss);
        } else {
            action.setEnabled(false);
            setSelection(StructuredSelection.EMPTY);
        }
    }

    /**
     * Performs the specific action on this element.
     */
    protected abstract void doAction(Object element) throws DebugException;

    /**
     * Returns the String to use as an error dialog title for
     * a failed action. Default is to return null.
     */
    protected String getErrorDialogTitle() {
        return null;
    }

    /**
     * Returns the String to use as an error dialog message for
     * a failed action. This message appears as the "Message:" in
     * the error dialog for this action.
     * Default is to return null.
     */
    protected String getErrorDialogMessage() {
        return null;
    }

    /**
     * Returns the String to use as a status message for
     * a failed action. This message appears as the "Reason:"
     * in the error dialog for this action.
     * Default is to return the empty String.
     */
    protected String getStatusMessage() {
        return ""; //$NON-NLS-1$
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
     */
    @Override
    public void init(IViewPart view) {
        fViewPart = view;
    }

    /**
     * Returns this action's view part, or <code>null</code>
     * if not installed in a view.
     * 
     * @return view part or <code>null</code>
     */
    protected IViewPart getView() {
        return fViewPart;
    }

    /**
     * Initialize this delegate, updating this delegate's
     * presentation.
     * As well, all of the flavors of AbstractDebugActionDelegates need to 
     * have the initial enabled state set with a call to update(IAction, ISelection).
     * 
     * @param action the presentation for this action
     * @return whether the action was initialized
     */
    protected boolean initialize(IAction action, ISelection selection) {
        if (!isInitialized()) {
            setAction(action);
            if (getView() == null) {
                //update on the selection in the debug view
                IWorkbenchWindow window = getWindow();
                if (window != null && window.getShell() != null && !window.getShell().isDisposed()) {
                    IWorkbenchPage page = window.getActivePage();
                    if (page != null) {
                        selection = page.getSelection(IDebugUIConstants.ID_DEBUG_VIEW);
                    }
                }
            }
            update(action, selection);
            setInitialized(true);
            return true;
        }
        return false;
    }

    /**
     * Returns the most recent selection
     * 
     * @return structured selection
     */
    protected IStructuredSelection getSelection() {
        return fSelection;
    }

    /**
     * Sets the most recent selection
     * 
     * @parm selection structured selection
     */
    private void setSelection(IStructuredSelection selection) {
        fSelection = selection;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
     */
    @Override
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        update(getAction(), selection);
    }

    protected void setAction(IAction action) {
        fAction = action;
    }

    protected IAction getAction() {
        return fAction;
    }

    protected void setView(IViewPart viewPart) {
        fViewPart = viewPart;
    }

    protected boolean isInitialized() {
        return fInitialized;
    }

    protected void setInitialized(boolean initialized) {
        fInitialized = initialized;
    }

    protected IWorkbenchWindow getWindow() {
        return fWindow;
    }

    protected void setWindow(IWorkbenchWindow window) {
        fWindow = window;
    }

    /**
     * Return whether the action should be enabled or not based on the given selection.
     */
    @SuppressWarnings("unchecked")
    protected boolean getEnableStateForSelection(IStructuredSelection selection) {
        if (selection.size() == 0) {
            return false;
        }
        Iterator<Object> itr = selection.iterator();
        while (itr.hasNext()) {
            Object element = itr.next();
            if (!isEnabledFor(element)) {
                return false;
            }
        }
        return true;
    }

    protected boolean isEnabledFor(Object element) {
        return true;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate2#runWithEvent(org.eclipse.jface.action.IAction, org.eclipse.swt.widgets.Event)
     */
    @Override
    public void runWithEvent(IAction action, Event event) {
        run(action);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IActionDelegate2#init(org.eclipse.jface.action.IAction)
     */
    @Override
    public void init(IAction action) {
    }
}