blob: 33f67458ccf082cef1de346bfb4977fa5d5fa58c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2018 Obeo 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:
* Obeo - initial API and implementation
* Conor O'Mahony - bug 507465
* Martin Fleck - bug 483798
* Martin Fleck - bug 514415
* Tobias Ortmayr - bug 516248
* Philip Langer - bug 514079
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.configuration;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.ICompareInputLabelProvider;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.EMFCompare;
import org.eclipse.emf.compare.domain.ICompareEditingDomain;
import org.eclipse.emf.compare.ide.ui.internal.EMFCompareIDEUIPlugin;
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.merge.DiffRelationshipComputer;
import org.eclipse.emf.compare.merge.IDiffRelationshipComputer;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.EMFCompareRCPUIPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.AdapterFactoryChange;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.CompareEditingDomainChange;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.ComparisonAndScopeChange;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.DiffRelationshipComputerChange;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.EMFComparatorChange;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.impl.MergePreviewModeChange;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.StructureMergeViewerFilter;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.StructureMergeViewerGrouper;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.DefaultGroupProvider;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDeactivableDiffFilter;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider.Descriptor;
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.graphics.Image;
/**
* @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
*/
public class EMFCompareConfiguration extends ForwardingCompareConfiguration implements IEMFCompareConfiguration {
private static final String COMPARE_RESULT = EMFCompareIDEUIPlugin.PLUGIN_ID + ".COMPARE_RESULT"; //$NON-NLS-1$
private static final String COMPARATOR = EMFCompareIDEUIPlugin.PLUGIN_ID + ".COMPARATOR"; //$NON-NLS-1$
private static final String EDITING_DOMAIN = EMFCompareIDEUIPlugin.PLUGIN_ID + ".EDITING_DOMAIN"; //$NON-NLS-1$
private static final String ADAPTER_FACTORY = EMFCompareIDEUIPlugin.PLUGIN_ID + ".ADAPTER_FACTORY"; //$NON-NLS-1$
private static final String DIFF_RELATIONSHIP_COMPUTER = EMFCompareIDEUIPlugin.PLUGIN_ID
+ ".DIFF_RELATIONSHIP_COMPUTER"; //$NON-NLS-1$
private static final String PREVIEW_MERGE_MODE = EMFCompareIDEUIPlugin.PLUGIN_ID + ".PREVIEW_MERGE_MODE"; //$NON-NLS-1$
private static final String COMPARISON_SCOPE = EMFCompareIDEUIPlugin.PLUGIN_ID + ".COMPARISON_SCOPE"; //$NON-NLS-1$ ;
private static final String SMV_FILTERS = EMFCompareIDEUIPlugin.PLUGIN_ID + ".SMV_FILTERS"; //$NON-NLS-1$ ;
private static final String EVENT_BUS = EMFCompareIDEUIPlugin.PLUGIN_ID + ".EVENT_BUS"; //$NON-NLS-1$ ;
private static final String SMV_GROUP_PROVIDERS = EMFCompareIDEUIPlugin.PLUGIN_ID
+ ".SMV_GROUP_PROVIDERS"; //$NON-NLS-1$ ;
public static final String DISPLAY_GROUP_PROVIDERS = EMFCompareIDEUIPlugin.PLUGIN_ID
+ ".DISPLAY_GROUP_PROVIDERS"; //$NON-NLS-1$
public static final String DISPLAY_FILTERS = EMFCompareIDEUIPlugin.PLUGIN_ID + ".DISPLAY_FILTERS"; //$NON-NLS-1$
public static final String DISPLAY_SAVE_ACTION = EMFCompareIDEUIPlugin.PLUGIN_ID + ".DISPLAY_SAVE_ACTION"; //$NON-NLS-1$
public static final String DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS = EMFCompareIDEUIPlugin.PLUGIN_ID
+ ".DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS";//$NON-NLS-1$
/**
* This property name is equivalent to {@link CompareConfiguration#MIRRORED} however we redefine it for
* backwards compatibility.
*/
@SuppressWarnings("hiding")
public static final String MIRRORED = "MIRRORED"; //$NON-NLS-1$
private final PropertyChangeListener propertyChangeListener;
private final CompareConfiguration compareConfiguration;
private final Map<Class<? extends ICompareInput>, ICompareInputLabelProvider> labelProviders = new HashMap<Class<? extends ICompareInput>, ICompareInputLabelProvider>();
public EMFCompareConfiguration(CompareConfiguration compareConfiguration) {
this.compareConfiguration = compareConfiguration;
setDefaultValues();
propertyChangeListener = new PropertyChangeListener();
compareConfiguration.addPropertyChangeListener(propertyChangeListener);
}
private void setDefaultValues() {
EventBus eventBus = new EventBus();
if (getProperty(SMV_FILTERS) == null) {
setProperty(SMV_FILTERS, new StructureMergeViewerFilter(eventBus));
}
if (getProperty(SMV_GROUP_PROVIDERS) == null) {
setProperty(SMV_GROUP_PROVIDERS, new StructureMergeViewerGrouper(eventBus));
}
if (getProperty(EVENT_BUS) == null) {
setProperty(EVENT_BUS, eventBus);
}
if (getProperty(DISPLAY_GROUP_PROVIDERS) == null) {
setProperty(DISPLAY_GROUP_PROVIDERS, Boolean.TRUE);
}
if (getProperty(DISPLAY_FILTERS) == null) {
setProperty(DISPLAY_FILTERS, Boolean.TRUE);
}
if (getProperty(DISPLAY_SAVE_ACTION) == null) {
setProperty(DISPLAY_SAVE_ACTION, Boolean.TRUE);
}
if (getProperty(DIFF_RELATIONSHIP_COMPUTER) == null) {
setProperty(DIFF_RELATIONSHIP_COMPUTER,
new DiffRelationshipComputer(EMFCompareRCPPlugin.getDefault().getMergerRegistry()));
}
if (getProperty(DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS) == null) {
setProperty(DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS, Boolean.TRUE);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#getEventBus()
*/
public EventBus getEventBus() {
return (EventBus)getProperty(EVENT_BUS);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.ide.ui.internal.configuration.ForwardingCompareConfiguration#delegate()
*/
@Override
protected CompareConfiguration delegate() {
return compareConfiguration;
}
/**
* {@inheritDoc}.
* <p>
* The lifecycle of the EMFCompareConfiguration (ECC) does not follow the lifecycle of its delegate
* CompareConfiguration (CC). CC are created once per comparison editor instance. The comparison editor
* lives from the moment the user starts a comparison to the moment the user closes the editor.
* In-between, the user will be able to switch from one content merge viewer (CMV) to another by changing
* his selection in the structure merge viewer (SMW). For example, selecting an EObject in the SMV will
* show tree representations of these EObject in the CMV, whilst selecting a text attribute in the SMW
* will switch the CMV representation to textual viewers. When switching CMV, the ECC needs a partial
* dispose in order to change its installed listeners (this will also happen when mirroring the
* comparison). Furthermore, the user will be able to switch the whole comparison from one file to another
* if he has selected multiple files for comparison (for example, by comparing in a compare dialog). When
* switching from one file to another, the whole EMF Compare comparison needs to change, and thus we need
* to dispose of the ECC, but the CC cannot be disposed at that time since its own lifecycle hasn't come
* to an end.
* </p>
* <p>
* Because of this, there are three separate 'dispose' methods on an ECC. First is the inherited
* {@link #dispose()} which will dispose of this whole ECC after disposing its delegate CC. Second is
* {@link #disposeListeners()} which will only undertake a partial clean up of this ECC : listeners of the
* ECC are disposed, but not the Comparison itself, nor the delegate CC. Finally,
* {@link #disposeComparison()} will discard both the listeners and Comparison, but not the delegate CC.
* </p>
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#dispose()
*/
@Override
public void dispose() {
super.dispose();
disposeListeners();
// CompareConfiguration does not clear its properties list...
// Lets clean our own mess ourselves
// EVENT_BUS must not be set to null
Comparison comparison = getComparison();
disposeComparison();
if (comparison != null) {
comparison.eAdapters().clear();
}
}
/**
* {@link #dispose()} is only called when the comparison editor is closed, whereas EMFCompareConfiguration
* are created and discarded on each change of the ContentMergeViewer input. This will be called to
* dispose of the specific setup that was made by the EMFCompareConfiguration wrapper to its underlying
* CompareConfiguration. See documentation of {@link #dispose()}.
*
* @see #dispose()
*/
public void disposeListeners() {
compareConfiguration.removePropertyChangeListener(propertyChangeListener);
}
/**
* {@link #dispose()} is only called when the comparison editor is closed, whereas EMFCompareConfiguration
* follows its own separate lifecycle. See documentation of {@link #dispose()}.
*
* @see #dispose()
*/
public void disposeComparison() {
disposeListeners();
compareConfiguration.setProperty(COMPARISON_SCOPE, null);
compareConfiguration.setProperty(COMPARE_RESULT, null);
compareConfiguration.setProperty(SMV_FILTERS, null);
compareConfiguration.setProperty(EDITING_DOMAIN, null);
compareConfiguration.setProperty(ADAPTER_FACTORY, null);
compareConfiguration.setProperty(DIFF_RELATIONSHIP_COMPUTER, null);
compareConfiguration.setProperty(SMV_GROUP_PROVIDERS, null);
compareConfiguration.setProperty(PREVIEW_MERGE_MODE, null);
compareConfiguration.setProperty(DISPLAY_GROUP_PROVIDERS, null);
compareConfiguration.setProperty(DISPLAY_FILTERS, null);
compareConfiguration.setProperty(DISPLAY_SAVE_ACTION, null);
compareConfiguration.setProperty(DISPLAY_SELECT_UNRESOLVED_DIFF_ACTIONS, null);
}
public boolean getBooleanProperty(String key, boolean dflt) {
final boolean ret;
Object value = getProperty(key);
if (value instanceof Boolean) {
ret = ((Boolean)value).booleanValue();
} else {
ret = dflt;
}
return ret;
}
public Comparison getComparison() {
return (Comparison)getProperty(COMPARE_RESULT);
}
public EMFCompare getEMFComparator() {
return (EMFCompare)getProperty(COMPARATOR);
}
public ICompareEditingDomain getEditingDomain() {
return (ICompareEditingDomain)getProperty(EDITING_DOMAIN);
}
public MergeMode getMergePreviewMode() {
return (MergeMode)getProperty(PREVIEW_MERGE_MODE);
}
public AdapterFactory getAdapterFactory() {
return (AdapterFactory)getProperty(ADAPTER_FACTORY);
}
public IDiffRelationshipComputer getDiffRelationshipComputer() {
return (IDiffRelationshipComputer)getProperty(DIFF_RELATIONSHIP_COMPUTER);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#getComparisonScope()
*/
public IComparisonScope getComparisonScope() {
return (IComparisonScope)getProperty(COMPARISON_SCOPE);
}
public void setEMFComparator(EMFCompare newComparator) {
EMFCompare oldComparator = getEMFComparator();
setProperty(COMPARATOR, newComparator);
getEventBus().post(new EMFComparatorChange(oldComparator, newComparator));
}
public void setEditingDomain(ICompareEditingDomain newValue) {
ICompareEditingDomain oldValue = getEditingDomain();
setProperty(EDITING_DOMAIN, newValue);
getEventBus().post(new CompareEditingDomainChange(oldValue, newValue));
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#setComparisonAndScope(org.eclipse.emf.compare.scope.IComparisonScope,
* org.eclipse.emf.compare.Comparison)
*/
public void setComparisonAndScope(Comparison newComparison, IComparisonScope newComparisonScope) {
Comparison oldComparison = getComparison();
IComparisonScope oldComparisonScope = getComparisonScope();
setProperty(COMPARE_RESULT, newComparison);
setProperty(COMPARISON_SCOPE, newComparisonScope);
if (oldComparison == null && oldComparisonScope == null) {
initStructureMergeViewerGroupProvider(newComparison, newComparisonScope);
initStructureMergeViewerFilter(newComparison, newComparisonScope);
}
getEventBus().post(new ComparisonAndScopeChange(oldComparison, newComparison, oldComparisonScope,
newComparisonScope));
}
protected void initStructureMergeViewerGroupProvider(Comparison comparison,
IComparisonScope comparisonScope) {
EMFCompareRCPUIPlugin plugin = EMFCompareRCPUIPlugin.getDefault();
IDifferenceGroupProvider.Descriptor.Registry groupProviderRegistry = plugin
.getDifferenceGroupProviderRegistry();
Descriptor defaultGroupProvider = groupProviderRegistry.getDefaultGroupProvider(comparisonScope,
comparison);
IDifferenceGroupProvider defaultGroup = null;
if (defaultGroupProvider != null) {
defaultGroup = defaultGroupProvider.createGroupProvider();
}
if (defaultGroup == null) {
defaultGroup = new DefaultGroupProvider();
}
getStructureMergeViewerGrouper().setProvider(defaultGroup);
}
protected void initStructureMergeViewerFilter(Comparison comparison, IComparisonScope comparisonScope) {
EMFCompareRCPUIPlugin plugin = EMFCompareRCPUIPlugin.getDefault();
IDifferenceFilter.Registry filterRegistry = plugin.getDifferenceFilterRegistry();
Collection<IDifferenceFilter> filters = filterRegistry.getFilters(comparisonScope, comparison);
Collection<IDifferenceFilter> selectedFilters = Lists.newArrayList();
Collection<IDifferenceFilter> unselectedFilters = Lists.newArrayList();
Collection<IDifferenceFilter> activeFilters = Lists.newArrayList();
for (IDifferenceFilter filter : filters) {
if (!(filter instanceof IDeactivableDiffFilter) || ((IDeactivableDiffFilter)filter).isActive()) {
if (filter.defaultSelected()) {
selectedFilters.add(filter);
} else {
unselectedFilters.add(filter);
}
activeFilters.add(filter);
}
}
getStructureMergeViewerFilter().init(selectedFilters, unselectedFilters, activeFilters);
}
public void setMergePreviewMode(MergeMode previewMergeMode) {
MergeMode oldValue = getMergePreviewMode();
setProperty(PREVIEW_MERGE_MODE, previewMergeMode);
getEventBus().post(new MergePreviewModeChange(oldValue, previewMergeMode));
}
public void setAdapterFactory(AdapterFactory adapterFactory) {
AdapterFactory oldValue = getAdapterFactory();
setProperty(ADAPTER_FACTORY, adapterFactory);
getEventBus().post(new AdapterFactoryChange(oldValue, adapterFactory));
}
public void setDiffRelationshipComputer(IDiffRelationshipComputer diffRelationshipComputer) {
IDiffRelationshipComputer oldValue = getDiffRelationshipComputer();
setProperty(DIFF_RELATIONSHIP_COMPUTER, diffRelationshipComputer);
getEventBus().post(new DiffRelationshipComputerChange(oldValue, diffRelationshipComputer));
}
private class PropertyChangeListener implements IPropertyChangeListener {
public void propertyChange(PropertyChangeEvent event) {
fireChange(event.getProperty(), event.getOldValue(), event.getNewValue());
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#getStructureMergeViewerGrouper()
*/
public StructureMergeViewerGrouper getStructureMergeViewerGrouper() {
return (StructureMergeViewerGrouper)getProperty(SMV_GROUP_PROVIDERS);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration#getStructureMergeViewerFilter()
*/
public StructureMergeViewerFilter getStructureMergeViewerFilter() {
return (StructureMergeViewerFilter)getProperty(SMV_FILTERS);
}
public void setLabelProvider(Class<? extends ICompareInput> inputType,
ICompareInputLabelProvider labelProvider) {
labelProviders.put(inputType, labelProvider);
}
@Override
public String getLeftLabel(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final String leftLabel = labelProvider.getLeftLabel(element);
if (leftLabel != null) {
return leftLabel;
}
}
return super.getLeftLabel(element);
}
@Override
public Image getLeftImage(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final Image leftImage = labelProvider.getLeftImage(element);
if (leftImage != null) {
return leftImage;
}
}
return super.getLeftImage(element);
}
@Override
public String getRightLabel(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final String rightLabel = labelProvider.getRightLabel(element);
if (rightLabel != null) {
return rightLabel;
}
}
return super.getRightLabel(element);
}
@Override
public Image getRightImage(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final Image rightImage = labelProvider.getRightImage(element);
if (rightImage != null) {
return rightImage;
}
}
return super.getRightImage(element);
}
@Override
public String getAncestorLabel(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final String ancestorLabel = labelProvider.getAncestorLabel(element);
if (ancestorLabel != null) {
return ancestorLabel;
}
}
return super.getAncestorLabel(element);
}
@Override
public Image getAncestorImage(Object element) {
final ICompareInputLabelProvider labelProvider = getLabelProviderForType(element);
if (labelProvider != null) {
final Image ancestorImage = labelProvider.getAncestorImage(element);
if (ancestorImage != null) {
return ancestorImage;
}
}
return super.getLeftImage(element);
}
private ICompareInputLabelProvider getLabelProviderForType(Object element) {
if (element instanceof ICompareInput) {
return labelProviders.get(((ICompareInput)element).getClass());
}
return null;
}
}