com.microsoft.tfs.client.common.ui.framework.action.SelectionProviderAction.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.tfs.client.common.ui.framework.action.SelectionProviderAction.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the repository root.

package com.microsoft.tfs.client.common.ui.framework.action;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;

import com.microsoft.tfs.client.common.ui.framework.helper.SelectionUtils;
import com.microsoft.tfs.client.common.ui.framework.telemetry.ClientTelemetryHelper;

/**
 * <p>
 * {@link SelectionProviderAction} is an base {@link Action} implementation. It
 * is intended for use by non-declarative actions that need to track the
 * selection provided by an {@link ISelectionProvider}.
 * </p>
 */
public abstract class SelectionProviderAction extends Action {
    /**
     * An {@link ISelectionChangedListener} that we attach and detach from our
     * {@link ISelectionProvider}.
     */
    private final ISelectionChangedListener selectionChangedListener;

    /**
     * The {@link ISelectionProvider} we're currently tracking or
     * <code>null</code>.
     */
    private ISelectionProvider selectionProvider;

    /**
     * The last {@link ISelection} from the {@link ISelectionProvider}.
     */
    private ISelection selection;

    /**
     * Creates a new {@link SelectionProviderAction}, supplying an initial
     * {@link ISelectionProvider} to track. This {@link SelectionProviderAction}
     * is initially disabled. If subclasses wish to perform immediate
     * enablement, they must manually call {@link #selectionChanged(ISelection)}
     * in the subclass constructor.
     *
     * @param selectionProvider
     *        initial {@link ISelectionProvider} or <code>null</code>
     */
    protected SelectionProviderAction(final ISelectionProvider selectionProvider) {
        /*
         * create a selection changed listener
         */
        selectionChangedListener = new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent event) {
                SelectionProviderAction.this.selectionChanged(event);
            }
        };

        /*
         * start tracking the specified provider
         */
        setSelectionProvider(selectionProvider);
    }

    /**
     * Provides a new {@link ISelectionProvider} for this
     * {@link SelectionProviderAction} to track. If there is an existing
     * {@link ISelectionProvider}, it will be disassociated from this
     * {@link SelectionProviderAction}. This method will trigger a call to
     * {@link #selectionChanged(ISelection)}.
     *
     * @param selectionProvider
     *        a new {@link ISelectionProvider} to track or <code>null</code>
     */
    public void setSelectionProvider(final ISelectionProvider selectionProvider) {
        dispose();
        this.selectionProvider = selectionProvider;
        if (selectionProvider != null) {
            selectionProvider.addSelectionChangedListener(selectionChangedListener);
            selectionChanged(selectionProvider.getSelection());
        } else {
            selectionChanged(StructuredSelection.EMPTY);
        }
    }

    /**
     * Should be called when this action is no longer needed. If this
     * {@link SelectionProviderAction} is tracking an {@link ISelectionProvider}
     * , this method removes the {@link ISelectionChangedListener} from the
     * provider and stops tracking the provider.
     */
    public void dispose() {
        if (selectionProvider != null) {
            selectionProvider.removeSelectionChangedListener(selectionChangedListener);
            selectionProvider = null;
        }
    }

    /**
     * Called by this {@link SelectionProviderAction} whenever the
     * {@link ISelectionProvider} being tracked publishes a
     * {@link SelectionChangedEvent}. Subclasses may overrride. The base class
     * calls the {@link #selectionChanged(ISelection)} method with the event's
     * {@link ISelection}.
     *
     * @param event
     *        a {@link SelectionChangedEvent} (must not be <code>null</code>)
     */
    protected void selectionChanged(final SelectionChangedEvent event) {
        selectionChanged(event.getSelection());
    }

    /**
     * Called by this {@link SelectionProviderAction} whenever the selection has
     * changed - either because a new {@link ISelectionProvider} has been set or
     * because a {@link SelectionChangedEvent} has been received. Subclasses may
     * override. The base class caches the selection, calls one of the
     * <code>computeEnablement</code> overrides, and sets enablement on this
     * action.
     *
     * @param selection
     *        the new {@link ISelection} (must not be <code>null</code>)
     */
    protected void selectionChanged(final ISelection selection) {
        this.selection = selection;
        if (selection instanceof IStructuredSelection) {
            setEnabled(computeEnablement((IStructuredSelection) selection));
        } else {
            setEnabled(computeEnablement(selection));
        }
    }

    /**
     * Called by this {@link SelectionProviderAction} whenever the selection has
     * changed and the new {@link ISelection} is not an
     * {@link IStructuredSelection}. The return value is used to set a new
     * enablement for this action. Subclasses may override. The base class just
     * returns <code>false</code>.
     *
     * @param selection
     *        the new {@link ISelection} (must not be <code>null</code>)
     * @return action enablement based on the new selection
     */
    protected boolean computeEnablement(final ISelection selection) {
        return false;
    }

    /**
     * Called by this {@link SelectionProviderAction} whenever the selection has
     * changed and the new {@link ISelection} is an {@link IStructuredSelection}
     * . The return value is used to set a new enablement for this action.
     * Subclasses may override. The base class just returns <code>false</code>.
     *
     * @param selection
     *        the new {@link IStructuredSelection} (must not be
     *        <code>null</code>)
     * @return action enablement based on the new selection
     */
    protected boolean computeEnablement(final IStructuredSelection selection) {
        return false;
    }

    /**
     * Obtains the current selection size. If there is no current selection,
     * returns <code>0</code>. If the current selection is not an
     * {@link IStructuredSelection}, throws an exception.
     *
     * @return the current selection size
     */
    protected final int getSelectionSize() {
        return SelectionUtils.getSelectionSize(selection);
    }

    protected final Object[] selectionToArray() {
        return SelectionUtils.selectionToArray(selection);
    }

    protected final Object[] selectionToArray(final Class targetType) {
        return SelectionUtils.selectionToArray(selection, targetType);
    }

    protected final Object[] adaptSelectionToArray(final Class targetType) {
        return SelectionUtils.adaptSelectionToArray(selection, targetType);
    }

    protected final Object[] selectionToArray(final Class targetType, final boolean adapt) {
        return SelectionUtils.selectionToArray(selection, targetType, adapt);
    }

    protected final Object getSelectionFirstElement() {
        return SelectionUtils.getSelectionFirstElement(selection);
    }

    protected final Object adaptSelectionFirstElement(final Class targetType) {
        return SelectionUtils.adaptSelectionFirstElement(selection, targetType);
    }

    /**
     * Obtains the current {@link IStructuredSelection}. If there is no current
     * selection, returns <code>null</code>. If the current selection is not an
     * {@link IStructuredSelection}, throws an exception.
     *
     * @return the current {@link IStructuredSelection} or <code>null</code> if
     *         there is no current selection
     */
    protected final IStructuredSelection getStructuredSelection() {
        return SelectionUtils.getStructuredSelection(selection);
    }

    /**
     * Obtains the current {@link ISelection}. If there is no current selection,
     * returns <code>null</code>.
     *
     * @return the current {@link ISelection} or <code>null</code> if there is
     *         no current selection
     */
    protected final ISelection getSelection() {
        return selection;
    }

    /**
     * Obtains the {@link ISelectionProvider} currently being tracked by this
     * {@link SelectionProviderAction}. If there is no current
     * {@link ISelectionProvider}, returns <code>null</code>.
     *
     * @return the current {@link ISelectionProvider} or <code>null</code> if
     *         there is no current {@link ISelectionProvider}
     */
    protected final ISelectionProvider getSelectionProvider() {
        return selectionProvider;
    }

    @Override
    public final void run() {
        ClientTelemetryHelper.sendRunActionEvent(this);
        doRun();
    }

    public abstract void doRun();
}