org.eclipse.team.internal.ccvs.ui.mappings.ChangeSetActionProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.team.internal.ccvs.ui.mappings.ChangeSetActionProvider.java

Source

/*******************************************************************************
 * Copyright (c) 2006, 2010 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 * Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 94808 [Change Sets] "&" not showing up in dropdown menu
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.mappings;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.widgets.Control;
import org.eclipse.team.core.diff.*;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.internal.ccvs.core.mapping.ChangeSetModelProvider;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.core.subscribers.*;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.internal.ui.mapping.ResourceModelActionProvider;
import org.eclipse.team.internal.ui.mapping.ResourceModelTraversalCalculator;
import org.eclipse.team.internal.ui.synchronize.*;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.BaseSelectionListenerAction;
import org.eclipse.ui.navigator.INavigatorContentExtension;
import org.eclipse.ui.navigator.INavigatorContentService;

public class ChangeSetActionProvider extends ResourceModelActionProvider {

    /**
     * Menu group that can be added to the context menu
     */
    public final static String CHANGE_SET_GROUP = "changeSetActions"; //$NON-NLS-1$

    // Constants for persisting sorting options
    private static final String P_LAST_COMMENTSORT = TeamUIPlugin.ID + ".P_LAST_COMMENT_SORT"; //$NON-NLS-1$

    private MenuManager sortByComment;
    private MenuManager addToChangeSet;
    private CreateChangeSetAction createChangeSet;
    private EditChangeSetAction editChangeSet;
    private RemoveChangeSetAction removeChangeSet;
    private MakeDefaultChangeSetAction makeDefault;
    private OpenChangeSetAction openCommitSet;

    private class CreateChangeSetAction extends ModelParticipantAction {

        public CreateChangeSetAction(ISynchronizePageConfiguration configuration) {
            super(TeamUIMessages.ChangeLogModelProvider_0, configuration);
        }

        public void run() {
            final IDiff[] diffs = getLocalChanges(getStructuredSelection());
            syncExec(new Runnable() {
                public void run() {
                    createChangeSet(diffs);
                }
            });
        }

        /* package */void createChangeSet(IDiff[] diffs) {
            ActiveChangeSet set = getChangeSetCapability().createChangeSet(getConfiguration(), diffs);
            if (set != null) {
                getActiveChangeSetManager().add(set);
            }
        }

        protected boolean isEnabledForSelection(IStructuredSelection selection) {
            return isContentProviderEnabled() && containsOnlyLocalChanges(selection);
        }
    }

    /**
     * Escape a string so it can be used as an action text without '&'
     * being interpreted as a mnemonic. Specifically, turn each '&' into '&&'.
     */
    /* package */static String escapeActionText(String x) {
        // Loosely based on org.eclipse.jface.action.LegacyActionTools#removeMnemonics
        int ampersandIndex = x.indexOf('&');
        if (ampersandIndex == -1)
            return x;

        int len = x.length();
        StringBuffer sb = new StringBuffer(2 * len + 1);
        int doneIndex = 0;
        while (ampersandIndex != -1) {
            sb.append(x.substring(doneIndex, ampersandIndex));
            sb.append("&&"); //$NON-NLS-1$
            doneIndex = ampersandIndex + 1;
            ampersandIndex = x.indexOf('&', doneIndex);
        }
        if (doneIndex < len)
            sb.append(x.substring(doneIndex, len));
        return sb.toString();
    }

    private class AddToChangeSetAction extends ModelParticipantAction {

        private final ActiveChangeSet set;

        public AddToChangeSetAction(ISynchronizePageConfiguration configuration, ActiveChangeSet set,
                ISelection selection) {
            super(set == null ? TeamUIMessages.ChangeSetActionGroup_2 : escapeActionText(set.getTitle()),
                    configuration);
            this.set = set;
            selectionChanged(selection);
        }

        public void run() {
            IDiff[] diffArray = getLocalChanges(getStructuredSelection());
            if (set != null) {
                set.add(diffArray);
            } else {
                ChangeSet[] sets = getActiveChangeSetManager().getSets();
                IResource[] resources = getResources(diffArray);
                for (int i = 0; i < sets.length; i++) {
                    ActiveChangeSet activeSet = (ActiveChangeSet) sets[i];
                    activeSet.remove(resources);
                }
            }
        }

        protected boolean isEnabledForSelection(IStructuredSelection selection) {
            return isContentProviderEnabled() && containsOnlyLocalChanges(selection);
        }
    }

    private abstract class ChangeSetAction extends BaseSelectionListenerAction {

        public ChangeSetAction(String title, ISynchronizePageConfiguration configuration) {
            super(title);
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.actions.BaseSelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection)
        */
        protected boolean updateSelection(IStructuredSelection selection) {
            return getSelectedSet() != null;
        }

        protected ActiveChangeSet getSelectedSet() {
            IStructuredSelection selection = getStructuredSelection();
            if (selection.size() == 1) {
                Object first = selection.getFirstElement();
                if (first instanceof ActiveChangeSet) {
                    ActiveChangeSet activeChangeSet = (ActiveChangeSet) first;
                    if (activeChangeSet.isUserCreated())
                        return activeChangeSet;
                }
            }
            return null;
        }
    }

    private class EditChangeSetAction extends ChangeSetAction {

        public EditChangeSetAction(ISynchronizePageConfiguration configuration) {
            super(TeamUIMessages.ChangeLogModelProvider_6, configuration);
        }

        public void run() {
            ActiveChangeSet set = getSelectedSet();
            if (set == null)
                return;
            getChangeSetCapability().editChangeSet(internalGetSynchronizePageConfiguration(), set);
        }
    }

    private class RemoveChangeSetAction extends ModelParticipantAction {

        public RemoveChangeSetAction(ISynchronizePageConfiguration configuration) {
            super(TeamUIMessages.ChangeLogModelProvider_7, configuration);
        }

        public void run() {
            IDiff[] diffArray = getLocalChanges(getStructuredSelection());
            ChangeSet[] sets = getActiveChangeSetManager().getSets();
            IResource[] resources = getResources(diffArray);
            for (int i = 0; i < sets.length; i++) {
                ActiveChangeSet activeSet = (ActiveChangeSet) sets[i];
                activeSet.remove(resources);
            }
        }

        protected boolean isEnabledForSelection(IStructuredSelection selection) {
            return isContentProviderEnabled() && containsOnlyLocalChanges(selection);
        }
    }

    private class MakeDefaultChangeSetAction extends ChangeSetAction {
        public MakeDefaultChangeSetAction(ISynchronizePageConfiguration configuration) {
            super(TeamUIMessages.ChangeLogModelProvider_9, configuration);
        }

        protected boolean updateSelection(IStructuredSelection selection) {
            if (getSelectedSet() != null) {
                setText(TeamUIMessages.ChangeLogModelProvider_9);
                setChecked(getSelectedSet().equals(getActiveChangeSetManager().getDefaultSet()));
            } else {
                setText(TeamUIMessages.ChangeLogModelProvider_10);
                setChecked(false);
            }
            return true;
        }

        public void run() {
            getActiveChangeSetManager().makeDefault(isChecked() ? getSelectedSet() : null);
            if (getSelectedSet() == null) {
                setChecked(false); // keep unchecked
            }
        }
    }

    /* *****************************************************************************
     * Action that allows changing the model providers sort order.
     */
    private class ToggleSortOrderAction extends Action {
        private int criteria;

        protected ToggleSortOrderAction(String name, int criteria) {
            super(name, IAction.AS_RADIO_BUTTON);
            this.criteria = criteria;
            update();
        }

        public void run() {
            int sortCriteria = getSortCriteria(internalGetSynchronizePageConfiguration());
            if (isChecked() && sortCriteria != criteria) {
                setSortCriteria(internalGetSynchronizePageConfiguration(), criteria);
                update();
                ((SynchronizePageConfiguration) internalGetSynchronizePageConfiguration()).getPage().getViewer()
                        .refresh();
            }
        }

        public void update() {
            setChecked(criteria == getSortCriteria(internalGetSynchronizePageConfiguration()));
        }
    }

    public static int getSortCriteria(ISynchronizePageConfiguration configuration) {
        int sortCriteria = ChangeSetSorter.DATE;
        if (configuration != null) {
            Object o = configuration.getProperty(P_LAST_COMMENTSORT);
            if (o instanceof Integer) {
                Integer wrapper = (Integer) o;
                sortCriteria = wrapper.intValue();
            } else {
                try {
                    IDialogSettings pageSettings = configuration.getSite().getPageSettings();
                    if (pageSettings != null) {
                        sortCriteria = pageSettings.getInt(P_LAST_COMMENTSORT);
                    }
                } catch (NumberFormatException e) {
                    // ignore and use the defaults.
                }
            }
        }
        switch (sortCriteria) {
        case ChangeSetSorter.COMMENT:
        case ChangeSetSorter.DATE:
        case ChangeSetSorter.USER:
            break;
        default:
            sortCriteria = ChangeSetSorter.DATE;
            break;
        }
        return sortCriteria;
    }

    public static void setSortCriteria(ISynchronizePageConfiguration configuration, int criteria) {
        configuration.setProperty(P_LAST_COMMENTSORT, new Integer(criteria));
        IDialogSettings pageSettings = configuration.getSite().getPageSettings();
        if (pageSettings != null) {
            pageSettings.put(P_LAST_COMMENTSORT, criteria);
        }
    }

    public ChangeSetActionProvider() {
        super();
    }

    protected void initialize() {
        super.initialize();
        if (getChangeSetCapability().supportsCheckedInChangeSets()) {
            sortByComment = new MenuManager(TeamUIMessages.ChangeLogModelProvider_0a);
            sortByComment.add(
                    new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_1a, ChangeSetSorter.COMMENT));
            sortByComment
                    .add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_2a, ChangeSetSorter.DATE));
            sortByComment
                    .add(new ToggleSortOrderAction(TeamUIMessages.ChangeLogModelProvider_3a, ChangeSetSorter.USER));
            openCommitSet = new OpenChangeSetAction(getSynchronizePageConfiguration());
        }
        if (getChangeSetCapability().supportsActiveChangeSets()) {
            createChangeSet = new CreateChangeSetAction(getSynchronizePageConfiguration());
            editChangeSet = new EditChangeSetAction(getSynchronizePageConfiguration());
            makeDefault = new MakeDefaultChangeSetAction(getSynchronizePageConfiguration());
            removeChangeSet = new RemoveChangeSetAction(getSynchronizePageConfiguration());
        }
    }

    protected ActiveChangeSet getSelectedActiveChangeSet(IStructuredSelection selection) {
        if (selection.size() == 1) {
            Object first = selection.getFirstElement();
            if (first instanceof ActiveChangeSet) {
                ActiveChangeSet activeChangeSet = (ActiveChangeSet) first;
                if (activeChangeSet.isUserCreated())
                    return activeChangeSet;
            }
        }
        return null;
    }

    private IResource[] getResources(IDiff[] diffArray) {
        List result = new ArrayList();
        for (int i = 0; i < diffArray.length; i++) {
            IDiff diff = diffArray[i];
            IResource resource = ResourceDiffTree.getResourceFor(diff);
            if (resource != null) {
                result.add(resource);
            }
        }
        return (IResource[]) result.toArray(new IResource[result.size()]);
    }

    public void fillContextMenu(IMenuManager menu) {
        if (isContentProviderEnabled()) {
            super.fillContextMenu(menu);
            if (getChangeSetCapability().enableCheckedInChangeSetsFor(getSynchronizePageConfiguration())) {
                appendToGroup(menu, "file-bottom", //$NON-NLS-1$
                        openCommitSet);
                appendToGroup(menu, ISynchronizePageConfiguration.SORT_GROUP, sortByComment);
            }
            IStructuredSelection selection = (IStructuredSelection) getContext().getSelection();
            if (getChangeSetCapability().enableActiveChangeSetsFor(getSynchronizePageConfiguration())
                    && containsOnlyLocalChanges(selection)) {

                if (containsOnlyUnassignedChanges(selection)) {
                    // only local unassigned changes
                    addToChangeSet = new MenuManager(TeamUIMessages.ChangeLogModelProvider_13);
                    appendToGroup(menu, CHANGE_SET_GROUP, addToChangeSet);
                } else {
                    addToChangeSet = new MenuManager(TeamUIMessages.ChangeLogModelProvider_12);
                    appendToGroup(menu, CHANGE_SET_GROUP, addToChangeSet);
                    appendToGroup(menu, CHANGE_SET_GROUP, removeChangeSet);
                }

                addChangeSets(addToChangeSet);

                if (getSelectedActiveChangeSet(selection) != null) {
                    appendToGroup(menu, CHANGE_SET_GROUP, editChangeSet);
                }
                appendToGroup(menu, CHANGE_SET_GROUP, makeDefault);
            }
        }
    }

    protected void addChangeSets(IMenuManager manager) {
        ChangeSet[] sets = getActiveChangeSetManager().getSets();
        Arrays.sort(sets, new ChangeSetComparator());
        ISelection selection = getContext().getSelection();
        createChangeSet.selectionChanged(selection);
        manager.add(createChangeSet);
        manager.add(new Separator());
        for (int i = 0; i < sets.length; i++) {
            ActiveChangeSet set = (ActiveChangeSet) sets[i];
            AddToChangeSetAction action = new AddToChangeSetAction(getSynchronizePageConfiguration(), set,
                    selection);
            manager.add(action);
        }
        manager.add(new Separator());
    }

    public void dispose() {
        if (addToChangeSet != null) {
            addToChangeSet.dispose();
            addToChangeSet.removeAll();
        }
        if (sortByComment != null) {
            sortByComment.dispose();
            sortByComment.removeAll();
        }
        super.dispose();
    }

    private boolean appendToGroup(IContributionManager manager, String groupId, IContributionItem item) {
        if (manager == null || item == null)
            return false;
        IContributionItem group = manager.find(groupId);
        if (group != null) {
            manager.appendToGroup(group.getId(), item);
            return true;
        }
        return false;
    }

    private boolean appendToGroup(IContributionManager manager, String groupId, IAction action) {
        if (manager == null || action == null)
            return false;
        IContributionItem group = manager.find(groupId);
        if (group != null) {
            manager.appendToGroup(group.getId(), action);
            // registerActionWithWorkbench(action);
            return true;
        }
        return false;
    }

    public ChangeSetCapability getChangeSetCapability() {
        ISynchronizeParticipant participant = getSynchronizePageConfiguration().getParticipant();
        if (participant instanceof IChangeSetProvider) {
            IChangeSetProvider provider = (IChangeSetProvider) participant;
            return provider.getChangeSetCapability();
        }
        return null;
    }

    /* package */void syncExec(final Runnable runnable) {
        final Control ctrl = getSynchronizePageConfiguration().getPage().getViewer().getControl();
        Utils.syncExec(runnable, ctrl);
    }

    /* package */ActiveChangeSetManager getActiveChangeSetManager() {
        return CVSUIPlugin.getPlugin().getChangeSetManager();
    }

    public IDiff[] getLocalChanges(IStructuredSelection selection) {
        if (selection instanceof ITreeSelection) {
            ITreeSelection ts = (ITreeSelection) selection;
            TreePath[] paths = ts.getPaths();
            List result = new ArrayList();
            for (int i = 0; i < paths.length; i++) {
                TreePath path = paths[i];
                IDiff[] diffs = getLocalChanges(path);
                for (int j = 0; j < diffs.length; j++) {
                    IDiff diff = diffs[j];
                    result.add(diff);
                }
            }
            return (IDiff[]) result.toArray(new IDiff[result.size()]);
        }
        return new IDiff[0];
    }

    private IDiff[] getLocalChanges(TreePath path) {
        IResourceDiffTree tree = getDiffTree(path);
        if (path.getSegmentCount() == 1 && path.getLastSegment() instanceof IDiffTree) {
            return ((ResourceDiffTree) tree).getDiffs();
        }
        ResourceTraversal[] traversals = getTraversals(path.getLastSegment());
        return tree.getDiffs(traversals);
    }

    private IResourceDiffTree getDiffTree(TreePath path) {
        return getContentProvider().getDiffTree(path);
    }

    private boolean containsOnlyUnassignedChanges(IStructuredSelection selection) {
        IDiff[] diffArray = getLocalChanges(selection);
        ChangeSet[] activeChangeSets = getActiveChangeSetManager().getSets();
        IResource[] resources = getResources(diffArray);
        for (int i = 0; i < activeChangeSets.length; i++) {
            for (int j = 0; j < resources.length; j++) {
                if (activeChangeSets[i].contains(resources[j]))
                    return false;
            }
        }
        return true;
    }

    public boolean containsOnlyLocalChanges(IStructuredSelection selection) {
        if (selection instanceof ITreeSelection) {
            ITreeSelection ts = (ITreeSelection) selection;
            TreePath[] paths = ts.getPaths();
            for (int i = 0; i < paths.length; i++) {
                TreePath path = paths[i];
                if (!containsOnlyLocalChanges(path)) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean containsOnlyLocalChanges(TreePath path) {
        IResourceDiffTree tree = getDiffTree(path);
        ResourceTraversal[] traversals = getTraversals(path.getLastSegment());
        return !tree.hasMatchingDiffs(traversals, getNonLocalChangesFilter());
    }

    private ResourceTraversal[] getTraversals(Object element) {
        if (element instanceof ChangeSet) {
            ChangeSet set = (ChangeSet) element;
            return new ResourceTraversal[] {
                    new ResourceTraversal(set.getResources(), IResource.DEPTH_ZERO, IResource.NONE) };
        }
        if (element instanceof IProject) {
            IProject project = (IProject) element;
            return new ResourceTraversal[] {
                    new ResourceTraversal(new IResource[] { project }, IResource.DEPTH_INFINITE, IResource.NONE) };
        }
        if (element instanceof IFile) {
            IFile file = (IFile) element;
            return new ResourceTraversal[] {
                    new ResourceTraversal(new IResource[] { file }, IResource.DEPTH_ZERO, IResource.NONE) };
        }
        if (element instanceof IFolder) {
            IFolder folder = (IFolder) element;
            if (getLayout().equals(IPreferenceIds.COMPRESSED_LAYOUT)) {
                return new ResourceTraversal[] {
                        new ResourceTraversal(new IResource[] { folder }, IResource.DEPTH_ONE, IResource.NONE) };
            } else if (getLayout().equals(IPreferenceIds.TREE_LAYOUT)) {
                return new ResourceTraversal[] { new ResourceTraversal(new IResource[] { folder },
                        IResource.DEPTH_INFINITE, IResource.NONE) };
            } else if (getLayout().equals(IPreferenceIds.FLAT_LAYOUT)) {
                return new ResourceTraversal[] {
                        new ResourceTraversal(new IResource[] { folder }, IResource.DEPTH_ZERO, IResource.NONE) };
            }
        }
        return new ResourceTraversal[0];
    }

    private FastDiffFilter getNonLocalChangesFilter() {
        return new FastDiffFilter() {
            public boolean select(IDiff diff) {
                if (diff instanceof IThreeWayDiff && isVisible(diff)) {
                    IThreeWayDiff twd = (IThreeWayDiff) diff;
                    if (twd.getDirection() == IThreeWayDiff.OUTGOING
                            || twd.getDirection() == IThreeWayDiff.CONFLICTING) {
                        return false;
                    }
                }
                return true;
            }
        };
    }

    /* package */boolean isVisible(IDiff diff) {
        return ((SynchronizePageConfiguration) getSynchronizePageConfiguration()).isVisible(diff);
    }

    protected ResourceModelTraversalCalculator getTraversalCalculator() {
        return ResourceModelTraversalCalculator.getTraversalCalculator(getSynchronizePageConfiguration());
    }

    private ChangeSetContentProvider getContentProvider() {
        INavigatorContentExtension extension = getExtension();
        if (extension != null) {
            ITreeContentProvider provider = extension.getContentProvider();
            if (provider instanceof ChangeSetContentProvider) {
                return (ChangeSetContentProvider) provider;
            }
        }
        return null;
    }

    private INavigatorContentExtension getExtension() {
        INavigatorContentService service = getActionSite().getContentService();
        Set set = service.findContentExtensionsByTriggerPoint(getModelProvider());
        for (Iterator iter = set.iterator(); iter.hasNext();) {
            INavigatorContentExtension extension = (INavigatorContentExtension) iter.next();
            return extension;
        }
        return null;
    }

    private Object getModelProvider() {
        return ChangeSetModelProvider.getProvider();
    }

    private String getLayout() {
        return TeamUIPlugin.getPlugin().getPreferenceStore().getString(IPreferenceIds.SYNCVIEW_DEFAULT_LAYOUT);
    }

    public void setContext(ActionContext context) {
        super.setContext(context);
        if (context != null) {
            if (editChangeSet != null)
                editChangeSet.selectionChanged((IStructuredSelection) getContext().getSelection());
            if (removeChangeSet != null)
                removeChangeSet.selectionChanged((IStructuredSelection) getContext().getSelection());
            if (makeDefault != null)
                makeDefault.selectionChanged((IStructuredSelection) getContext().getSelection());
        }
    }

    protected boolean isContentProviderEnabled() {
        ChangeSetContentProvider provider = getContentProvider();
        if (provider != null) {
            return provider.isEnabled();
        }
        return false;
    }

    /* package */ISynchronizePageConfiguration internalGetSynchronizePageConfiguration() {
        return getSynchronizePageConfiguration();
    }
}