blob: 74d4440052b8d80ab95fb4ac354aa458b6b7a1cc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.ui.synchronize;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.team.core.mapping.IMergeContext;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.internal.ui.mapping.CommonMenuManager;
import org.eclipse.team.internal.ui.mapping.MergeAction;
import org.eclipse.team.internal.ui.mapping.MergeIncomingChangesAction;
import org.eclipse.team.internal.ui.mapping.ModelSelectionDropDownAction;
import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration;
import org.eclipse.team.internal.ui.synchronize.actions.OpenInCompareAction;
import org.eclipse.team.internal.ui.synchronize.actions.SyncViewerShowPreferencesAction;
import org.eclipse.team.ui.mapping.SynchronizationActionProvider;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchSite;
/**
* Action group that contributes the merge actions to the model
* synchronize participant. The groups adds the following:
* <ul>
* <li>A toolbar action for attempting an auto-merge
* <li>Context menu merge actions that delegate to the
* model's merge action handlers.
* <li>TODO a merge all and overwrite all menu item?
* </ul>
* <p>
* Subclasses can configure the label and icons used for the merge actions
* by overriding {@link #configureMergeAction(String, Action)} and can
* configure where in the context menu the actions appear by overriding
* {@link #addToContextMenu(String, Action, IMenuManager)}.
*
* @since 3.2
**/
public class ModelSynchronizeParticipantActionGroup extends SynchronizePageActionGroup {
/**
* The id of the merge action group that determines where the merge
* actions (e.g. merge and overwrite) appear in the context menu or toolbar.
*/
public static final String MERGE_ACTION_GROUP = "merge"; //$NON-NLS-1$
/**
* The id of the action group that determines where the other
* actions (e.g. mark-as-merged) appear in the context menu.
*/
public static final String OTHER_ACTION_GROUP = "other"; //$NON-NLS-1$
/**
* The id used to identify the Merge All action.
*/
protected static final String MERGE_ALL_ACTION_ID = "org.eclipse.team.ui.mergeAll"; //$NON-NLS-1$
/**
* Create a merge action group.
*/
public ModelSynchronizeParticipantActionGroup() {
}
private MergeIncomingChangesAction updateToolbarAction;
private ModelSelectionDropDownAction modelPicker;
private SyncViewerShowPreferencesAction showPreferences;
private OpenInCompareAction openInCompareAction;
private MergeAction merge;
private MergeAction overwrite;
private MergeAction markAsMerged;
/* (non-Javadoc)
* @see org.eclipse.team.ui.synchronize.SynchronizePageActionGroup#initialize(org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration)
*/
@Override
public void initialize(ISynchronizePageConfiguration configuration) {
super.initialize(configuration);
ModelSynchronizeParticipant participant = ((ModelSynchronizeParticipant)configuration.getParticipant());
if (participant.isMergingEnabled()) {
updateToolbarAction = new MergeIncomingChangesAction(configuration);
configureMergeAction(MERGE_ALL_ACTION_ID, updateToolbarAction);
appendToGroup(
ISynchronizePageConfiguration.P_TOOLBAR_MENU,
MERGE_ACTION_GROUP,
updateToolbarAction);
// TODO: Should add a merge all to the context menu as well?
}
modelPicker = new ModelSelectionDropDownAction(configuration);
appendToGroup(
ISynchronizePageConfiguration.P_TOOLBAR_MENU,
ISynchronizePageConfiguration.NAVIGATE_GROUP,
modelPicker);
ISynchronizePageSite site = configuration.getSite();
IWorkbenchSite ws = site.getWorkbenchSite();
if (ws instanceof IViewSite) {
showPreferences = new SyncViewerShowPreferencesAction(configuration);
openInCompareAction = new OpenInCompareAction(configuration);
configuration.setProperty(SynchronizePageConfiguration.P_OPEN_ACTION, new Action() {
@Override
public void run() {
openInCompareAction.run();
}
});
}
}
@Override
public void fillActionBars(IActionBars actionBars) {
super.fillActionBars(actionBars);
if (actionBars != null && showPreferences != null) {
IMenuManager menu = actionBars.getMenuManager();
appendToGroup(menu, ISynchronizePageConfiguration.PREFERENCES_GROUP, showPreferences);
}
}
/* (non-Javadoc)
* @see org.eclipse.team.ui.synchronize.SynchronizePageActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager)
*/
@Override
public void fillContextMenu(IMenuManager menu) {
super.fillContextMenu(menu);
if (menu instanceof CommonMenuManager) {
CommonMenuManager cmm = (CommonMenuManager) menu;
addMergeActions(cmm);
}
Object[] elements = ((IStructuredSelection)getContext().getSelection()).toArray();
if (elements.length > 0 && openInCompareAction != null) {
IContributionItem fileGroup = findGroup(menu, ISynchronizePageConfiguration.FILE_GROUP);
if (fileGroup != null) {
ModelSynchronizeParticipant msp = ((ModelSynchronizeParticipant)getConfiguration().getParticipant());
boolean allElementsHaveCompareInput = true;
for (int i = 0; i < elements.length; i++) {
if (!msp.hasCompareInputFor(elements[i])) {
allElementsHaveCompareInput = false;
break;
}
}
if (allElementsHaveCompareInput) {
menu.appendToGroup(fileGroup.getId(), openInCompareAction);
}
}
}
}
/*
* Method to add the merge actions to the context menu. This method
* is called by the internal synchronization framework and should not
* to be invoked by other clients. Subclasses can configure the
* merge actions by overriding {@link #configureMergeAction(String, Action)}
* and can control where in the context menu the action appears by
* overriding {@link #addToContextMenu(String, Action, IMenuManager)}.
* @param cmm the menu manager
*/
private void addMergeActions(CommonMenuManager cmm) {
ModelSynchronizeParticipant participant = ((ModelSynchronizeParticipant)getConfiguration().getParticipant());
if (participant.isMergingEnabled()) {
if (!isTwoWayMerge()) {
if (merge == null) {
merge = new MergeAction(SynchronizationActionProvider.MERGE_ACTION_ID, cmm, getConfiguration());
configureMergeAction(SynchronizationActionProvider.MERGE_ACTION_ID, merge);
registerActionWithWorkbench(merge);
}
merge.update();
addToContextMenu(SynchronizationActionProvider.MERGE_ACTION_ID, merge, cmm);
}
if (overwrite == null) {
overwrite = new MergeAction(SynchronizationActionProvider.OVERWRITE_ACTION_ID, cmm, getConfiguration());
configureMergeAction(SynchronizationActionProvider.OVERWRITE_ACTION_ID, overwrite);
registerActionWithWorkbench(overwrite);
}
overwrite.update();
addToContextMenu(SynchronizationActionProvider.OVERWRITE_ACTION_ID, overwrite, cmm);
if (!isTwoWayMerge()) {
if (markAsMerged == null) {
markAsMerged = new MergeAction(SynchronizationActionProvider.MARK_AS_MERGE_ACTION_ID, cmm, getConfiguration());
configureMergeAction(SynchronizationActionProvider.MARK_AS_MERGE_ACTION_ID, markAsMerged);
}
markAsMerged.update();
addToContextMenu(SynchronizationActionProvider.MARK_AS_MERGE_ACTION_ID, markAsMerged, cmm);
registerActionWithWorkbench(markAsMerged);
}
}
}
/**
* Register this action with the workbench so that it can participate in keybindings and
* retargetable actions.
*
* @param action the action to register
*/
private void registerActionWithWorkbench(IAction action) {
ISynchronizePageSite site = getConfiguration().getSite();
String id = action.getId();
if (id != null) {
site.getActionBars().setGlobalActionHandler(id, action);
IKeyBindingService keyBindingService = site.getKeyBindingService();
if(keyBindingService != null)
keyBindingService.registerAction(action);
}
}
/**
* Configure the merge action to have appropriate label, image, etc.
* Subclasses may override but should invoke the overridden
* method for unrecognized ids in order to support future additions.
* @param mergeActionId the id of the merge action (one of
* {@link SynchronizationActionProvider#MERGE_ACTION_ID},
* {@link SynchronizationActionProvider#OVERWRITE_ACTION_ID} or
* {@link SynchronizationActionProvider#MARK_AS_MERGE_ACTION_ID})
* @param action the action for the given id
*/
protected void configureMergeAction(String mergeActionId, Action action) {
if (mergeActionId == SynchronizationActionProvider.MERGE_ACTION_ID) {
Utils.initAction(action, "action.merge."); //$NON-NLS-1$
} else if (mergeActionId == SynchronizationActionProvider.OVERWRITE_ACTION_ID) {
if (isTwoWayMerge()) {
Utils.initAction(action, "action.replace."); //$NON-NLS-1$
} else {
Utils.initAction(action, "action.overwrite."); //$NON-NLS-1$
}
} else if (mergeActionId == SynchronizationActionProvider.MARK_AS_MERGE_ACTION_ID) {
Utils.initAction(action, "action.markAsMerged."); //$NON-NLS-1$
} else if (mergeActionId == MERGE_ALL_ACTION_ID) {
if (isTwoWayMerge()) {
Utils.initAction(action, "action.replaceAll."); //$NON-NLS-1$
} else {
Utils.initAction(action, "action.mergeAll."); //$NON-NLS-1$
}
}
}
private boolean isTwoWayMerge() {
ModelSynchronizeParticipant participant = ((ModelSynchronizeParticipant)getConfiguration().getParticipant());
ISynchronizationContext context = participant.getContext();
if (context instanceof IMergeContext) {
IMergeContext mc = (IMergeContext) context;
return (mc.getMergeType() == ISynchronizationContext.TWO_WAY);
}
return false;
}
/**
* Add the merge action to the context menu manager.
* Subclasses may override but should invoke the overridden
* method for unrecognized ids in order to support future additions.
* @param mergeActionId the id of the merge action (one of
* {@link SynchronizationActionProvider#MERGE_ACTION_ID},
* {@link SynchronizationActionProvider#OVERWRITE_ACTION_ID} or
* {@link SynchronizationActionProvider#MARK_AS_MERGE_ACTION_ID})
* @param action the action for the given id
* @param manager the context menu manager
*/
protected void addToContextMenu(String mergeActionId, Action action, IMenuManager manager) {
IContributionItem group = null;;
if (mergeActionId == SynchronizationActionProvider.MERGE_ACTION_ID) {
group = manager.find(MERGE_ACTION_GROUP);
} else if (mergeActionId == SynchronizationActionProvider.OVERWRITE_ACTION_ID) {
group = manager.find(MERGE_ACTION_GROUP);
} else if (mergeActionId == SynchronizationActionProvider.MARK_AS_MERGE_ACTION_ID) {
group = manager.find(OTHER_ACTION_GROUP);
}
if (group != null) {
manager.appendToGroup(group.getId(), action);
} else {
manager.add(action);
}
}
/* (non-Javadoc)
* @see org.eclipse.team.ui.synchronize.SynchronizePageActionGroup#dispose()
*/
@Override
public void dispose() {
if (modelPicker != null)
modelPicker.dispose();
if (merge != null)
merge.dispose();
if (overwrite != null)
overwrite.dispose();
if (markAsMerged != null)
markAsMerged.dispose();
if (updateToolbarAction != null)
updateToolbarAction.dispose();
super.dispose();
}
}