blob: e7e220e74f63f13288ce43c652397fcce08ef417 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2015 Obeo.
* 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
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.preferences;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.compare.conflict.IConflictDetector;
import org.eclipse.emf.compare.diff.IDiffEngine;
import org.eclipse.emf.compare.equi.IEquiEngine;
import org.eclipse.emf.compare.match.IMatchEngine;
import org.eclipse.emf.compare.match.IMatchEngine.Factory;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.internal.extension.IItemDescriptor;
import org.eclipse.emf.compare.rcp.internal.extension.IItemRegistry;
import org.eclipse.emf.compare.rcp.internal.extension.impl.ItemUtil;
import org.eclipse.emf.compare.rcp.internal.match.DefaultRCPMatchEngineFactory;
import org.eclipse.emf.compare.rcp.internal.preferences.EMFComparePreferences;
import org.eclipse.emf.compare.rcp.internal.tracer.TracingConstant;
import org.eclipse.emf.compare.rcp.ui.EMFCompareRCPUIPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.EMFCompareRCPUIMessages;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.ui.AbstractConfigurationUI;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.ui.IConfigurationUIFactory;
import org.eclipse.emf.compare.rcp.ui.internal.preferences.impl.InteractiveUIContent;
import org.eclipse.emf.compare.rcp.ui.internal.preferences.impl.InteractiveUIContent.InteractiveUIBuilder;
import org.eclipse.emf.compare.req.IReqEngine;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
/**
* Preference page for engines preferences
*
* @author <a href="mailto:arthur.daussy@obeo.fr">Arthur Daussy</a>
*/
public class EnginesPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
/** Pointer to all {@link InteractiveUIContent} of each tab */
private final Map<String, InteractiveUIContent> interactiveUis = new HashMap<String, InteractiveUIContent>();
/** Data regarding the Difference selected engine */
private final DataHolder<IDiffEngine> diffEngineData = new DataHolder<IDiffEngine>();
/** Data regarding the Equivalence selected engine */
private final DataHolder<IEquiEngine> equiEngineData = new DataHolder<IEquiEngine>();
/** Data regarding the Requirement selected engine */
private final DataHolder<IReqEngine> reqEngineData = new DataHolder<IReqEngine>();
/** Data regarding the Conflicts detector selected engine */
private final DataHolder<IConflictDetector> conflictsDetectorData = new DataHolder<IConflictDetector>();
/** Data regarding the selected match engine factories. */
private final DataHolder<IMatchEngine.Factory> matchEnginesData = new DataHolder<IMatchEngine.Factory>();
public EnginesPreferencePage() {
super();
}
public EnginesPreferencePage(String title) {
super(title);
}
public EnginesPreferencePage(String title, ImageDescriptor image) {
super(title, image);
}
public void init(IWorkbench workbench) {
ScopedPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE,
EMFCompareRCPPlugin.PLUGIN_ID);
store.setSearchContexts(new IScopeContext[] {InstanceScope.INSTANCE, ConfigurationScope.INSTANCE });
setPreferenceStore(store);
}
@Override
protected Control createContents(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
container.setLayout(new FillLayout(SWT.HORIZONTAL));
TabFolder tabFolder = new TabFolder(container, SWT.NONE);
// Create match engine tab
createMatchEngineTab(tabFolder);
// Create diff engine tab
createDiffEngineTab(tabFolder);
// Create equi engine tab
createEquiEngineTab(tabFolder);
// Create req engine tab
createReqEngineTab(tabFolder);
// Create conflicts detectors tab
createConflictDetectorTab(tabFolder);
return container;
}
/**
* Create an {@link InteractiveUIContent} object of a specific type of engine.
*
* @param registry
* Registry holding engines.
* @param enginePreferenceKey
* Preference key use to store preferences
* @param tabComposite
* Holding composite.
* @param dataHolder
* Data that will be synchronized with the UI.
* @param <T>
* type of engine.
* @return {@link InteractiveUIContent} for a specific type of engine.
*/
private <T> InteractiveUIContent createEngineUIBuilder(IItemRegistry<T> registry,
String enginePreferenceKey, Composite tabComposite, DataHolder<T> dataHolder) {
IItemDescriptor<T> defaultEngine = ItemUtil.getDefaultItemDescriptor(registry, enginePreferenceKey);
InteractiveUIBuilder<T> uiBuilder = new InteractiveUIBuilder<T>(tabComposite, registry);
uiBuilder.setSimple(true).setDefaultCheck(Collections.singleton(defaultEngine))
.setDefaultSelection(defaultEngine).setHoldingData(dataHolder);
return uiBuilder.build();
}
/**
* Create a tab to select one Conflict Detector.
*
* @param tabFolder
*/
private void createConflictDetectorTab(TabFolder tabFolder) {
IItemRegistry<IConflictDetector> conflictDetectorDescriptorRegistry = EMFCompareRCPPlugin.getDefault()
.getConflictDetectorDescriptorRegistry();
// Create tab structure
Composite tabComposite = createTabSkeleton(tabFolder,
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.conflictDetector.tab.label"), //$NON-NLS-1$
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.conflictDetectorIntro.text"));//$NON-NLS-1$
InteractiveUIContent interactiveContent = createEngineUIBuilder(conflictDetectorDescriptorRegistry,
EMFComparePreferences.CONFLICTS_DETECTOR, tabComposite, conflictsDetectorData);
// Save for reset default
interactiveUis.put(EMFComparePreferences.CONFLICTS_DETECTOR, interactiveContent);
}
/**
* Create a tab to select one Requirement Engine.
*
* @param tabFolder
*/
private void createReqEngineTab(TabFolder tabFolder) {
IItemRegistry<IReqEngine> reqEngineDescriptorRegistry = EMFCompareRCPPlugin.getDefault()
.getReqEngineDescriptorRegistry();
// Create tab structure
Composite tabComposite = createTabSkeleton(tabFolder,
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.requirementEngine.tab.label"), //$NON-NLS-1$
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.reqEngineIntro.text")); //$NON-NLS-1$
InteractiveUIContent interactiveContent = createEngineUIBuilder(reqEngineDescriptorRegistry,
EMFComparePreferences.REQ_ENGINES, tabComposite, reqEngineData);
// Save for reset default
interactiveUis.put(EMFComparePreferences.REQ_ENGINES, interactiveContent);
}
/**
* Create a tab to select one Equivalence Engine.
*
* @param tabFolder
*/
private void createEquiEngineTab(TabFolder tabFolder) {
IItemRegistry<IEquiEngine> equiEngineDescriptorRegistry = EMFCompareRCPPlugin.getDefault()
.getEquiEngineDescriptorRegistry();
// Create tab structure
Composite tabComposite = createTabSkeleton(tabFolder,
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.equivalenceEngine.tab.label"), //$NON-NLS-1$
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.equiEngineIntro.text")); //$NON-NLS-1$
InteractiveUIContent interactiveContent = createEngineUIBuilder(equiEngineDescriptorRegistry,
EMFComparePreferences.EQUI_ENGINES, tabComposite, equiEngineData);
// Save for reset default
interactiveUis.put(EMFComparePreferences.EQUI_ENGINES, interactiveContent);
}
/**
* Create a tab to select one Difference Engine.
*
* @param tabFolder
*/
private void createDiffEngineTab(TabFolder tabFolder) {
IItemRegistry<IDiffEngine> diffEngineDescriptorRegistry = EMFCompareRCPPlugin.getDefault()
.getDiffEngineDescriptorRegistry();
// Create tab structure
Composite tabComposite = createTabSkeleton(tabFolder,
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.differenceEngine.tab.label"), //$NON-NLS-1$
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.diffEngineIntro.text")); //$NON-NLS-1$
InteractiveUIContent interactiveContent = createEngineUIBuilder(diffEngineDescriptorRegistry,
EMFComparePreferences.DIFF_ENGINES, tabComposite, diffEngineData);
// Save for reset default
interactiveUis.put(EMFComparePreferences.DIFF_ENGINES, interactiveContent);
}
/**
* Create a tab to disable/enable Match Engines.
*
* @param tabFolder
*/
private void createMatchEngineTab(TabFolder tabFolder) {
IItemRegistry<Factory> matchEngineFactoryDescriptorRegistry = EMFCompareRCPPlugin.getDefault()
.getMatchEngineFactoryDescriptorRegistry();
IItemDescriptor<Factory> defaultMatchEngineDescriptor = matchEngineFactoryDescriptorRegistry
.getItemDescriptor(DefaultRCPMatchEngineFactory.class.getCanonicalName());
Composite tabComposite = createTabSkeleton(tabFolder,
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.matchEngine.tab.label"), //$NON-NLS-1$
EMFCompareRCPUIMessages.getString("EnginesPreferencePage.matchEngineIntro.text")); //$NON-NLS-1$
Map<String, IConfigurationUIFactory> configuratorUIRegistry = EMFCompareRCPUIPlugin.getDefault()
.getMatchEngineConfiguratorRegistry();
String matchEnginePreferenceKey = EMFComparePreferences.MATCH_ENGINE_DISABLE_ENGINES;
Set<IItemDescriptor<Factory>> activeItems = ItemUtil.getActiveItems(
matchEngineFactoryDescriptorRegistry, EMFCompareRCPPlugin.PLUGIN_ID,
matchEnginePreferenceKey);
InteractiveUIBuilder<IMatchEngine.Factory> builder = new InteractiveUIBuilder<IMatchEngine.Factory>(
tabComposite, matchEngineFactoryDescriptorRegistry);
builder.setConfiguratorUIRegistry(configuratorUIRegistry).setDefaultCheck(activeItems)
.setConfigurationNodeKey(matchEnginePreferenceKey)
.setDefaultSelection(defaultMatchEngineDescriptor).setHoldingData(matchEnginesData);
// Forbid unchecking all match engines
InteractiveUIContent uiContent = builder.build();
uiContent.getViewer().addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
Object element = event.getElement();
if (!event.getChecked()) {
// Prevent from nothing checked
if (((CheckboxTableViewer)event.getSource()).getCheckedElements().length == 0) {
((CheckboxTableViewer)event.getSource()).setCheckedElements(new Object[] {element });
MessageDialog.openWarning(getShell(),
EMFCompareRCPUIMessages
.getString("InteractiveUIContent.incorrectSelection.title"), //$NON-NLS-1$
EMFCompareRCPUIMessages
.getString("InteractiveUIContent.incorrectSelection.message")); //$NON-NLS-1$
}
}
}
});
// Save for reset default
interactiveUis.put(matchEnginePreferenceKey, uiContent);
}
/**
* Create skeleton of a tab.
*
* @param tabFolder
* @param tabLabel
* @param introText
* Text use as description a tab
* @return Main composite of the tab
*/
private Composite createTabSkeleton(TabFolder tabFolder, String tabLabel, String introText) {
TabItem tbtmMain = new TabItem(tabFolder, SWT.NONE);
tbtmMain.setText(tabLabel);
Composite tabComposite = new Composite(tabFolder, SWT.NONE);
tbtmMain.setControl(tabComposite);
tabComposite.setLayout(new GridLayout(1, true));
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
tabComposite.setLayoutData(layoutData);
// Description text
Label introductionText = new Label(tabComposite, SWT.WRAP);
introductionText.setText(introText);
return tabComposite;
}
@Override
public boolean performOk() {
setEnginesPreferences();
storeConfigurations();
return super.performOk();
}
/**
* Set all engines preferences.
*/
private void setEnginesPreferences() {
// Update preferences preferences
setEnginePreferences(EMFComparePreferences.DIFF_ENGINES, diffEngineData.getData(),
Collections.singleton(EMFCompareRCPPlugin.getDefault().getDiffEngineDescriptorRegistry()
.getHighestRankingDescriptor()));
setEnginePreferences(EMFComparePreferences.EQUI_ENGINES, equiEngineData.getData(),
Collections.singleton(EMFCompareRCPPlugin.getDefault().getEquiEngineDescriptorRegistry()
.getHighestRankingDescriptor()));
setEnginePreferences(EMFComparePreferences.REQ_ENGINES, reqEngineData.getData(),
Collections.singleton(EMFCompareRCPPlugin.getDefault().getReqEngineDescriptorRegistry()
.getHighestRankingDescriptor()));
setEnginePreferences(EMFComparePreferences.CONFLICTS_DETECTOR, conflictsDetectorData.getData(),
Collections.singleton(EMFCompareRCPPlugin.getDefault().getConflictDetectorDescriptorRegistry()
.getHighestRankingDescriptor()));
// Set match engine to disable
Set<IItemDescriptor<Factory>> matchEngineRegsitry = Sets.newHashSet(EMFCompareRCPPlugin.getDefault()
.getMatchEngineFactoryDescriptorRegistry().getItemDescriptors());
Set<IItemDescriptor<Factory>> matchingEngineToDisable = Sets.difference(matchEngineRegsitry,
matchEnginesData.getData());
setEnginePreferences(EMFComparePreferences.MATCH_ENGINE_DISABLE_ENGINES, matchingEngineToDisable,
Collections.<IItemDescriptor<Factory>> emptyList());
}
/**
* Store the value of the configuration of each engine into preferences.
*/
private void storeConfigurations() {
for (Entry<String, InteractiveUIContent> interactiveContentEntry : interactiveUis.entrySet()) {
for (Entry<String, AbstractConfigurationUI> configuratorEntry : interactiveContentEntry.getValue()
.getConfigurators().entrySet()) {
AbstractConfigurationUI configurator = configuratorEntry.getValue();
configurator.storeConfiguration();
}
}
if (TracingConstant.CONFIGURATION_TRACING_ACTIVATED) {
StringBuilder traceMessage = new StringBuilder("Engines preference serialization:\n"); //$NON-NLS-1$
String prefDelimiter = " :\n"; //$NON-NLS-1$
String newLine = "\n"; //$NON-NLS-1$
traceMessage.append(EMFComparePreferences.DIFF_ENGINES).append(prefDelimiter)
.append(getPreferenceStore().getString(EMFComparePreferences.DIFF_ENGINES))
.append(newLine);
traceMessage.append(EMFComparePreferences.EQUI_ENGINES).append(prefDelimiter)
.append(getPreferenceStore().getString(EMFComparePreferences.EQUI_ENGINES))
.append(newLine);
traceMessage.append(EMFComparePreferences.REQ_ENGINES).append(prefDelimiter)
.append(getPreferenceStore().getString(EMFComparePreferences.REQ_ENGINES))
.append(newLine);
traceMessage.append(EMFComparePreferences.CONFLICTS_DETECTOR).append(prefDelimiter)
.append(getPreferenceStore().getString(EMFComparePreferences.CONFLICTS_DETECTOR))
.append(newLine);
traceMessage.append(EMFComparePreferences.MATCH_ENGINE_DISABLE_ENGINES).append(prefDelimiter)
.append(getPreferenceStore()
.getString(EMFComparePreferences.MATCH_ENGINE_DISABLE_ENGINES))
.append(newLine);
EMFCompareRCPPlugin.getDefault().log(IStatus.INFO, traceMessage.toString());
}
}
@Override
protected void performDefaults() {
resetDefaultPreferencesToHighestRank(
EMFCompareRCPPlugin.getDefault().getDiffEngineDescriptorRegistry(),
EMFComparePreferences.DIFF_ENGINES, diffEngineData);
resetDefaultPreferencesToHighestRank(
EMFCompareRCPPlugin.getDefault().getReqEngineDescriptorRegistry(),
EMFComparePreferences.REQ_ENGINES, reqEngineData);
resetDefaultPreferencesToHighestRank(
EMFCompareRCPPlugin.getDefault().getEquiEngineDescriptorRegistry(),
EMFComparePreferences.EQUI_ENGINES, equiEngineData);
resetDefaultPreferencesToHighestRank(
EMFCompareRCPPlugin.getDefault().getConflictDetectorDescriptorRegistry(),
EMFComparePreferences.CONFLICTS_DETECTOR, conflictsDetectorData);
resetDefaultPreferencesToAll(
EMFCompareRCPPlugin.getDefault().getMatchEngineFactoryDescriptorRegistry(),
EMFComparePreferences.MATCH_ENGINE_DISABLE_ENGINES, matchEnginesData);
resetConfigurations();
super.performDefaults();
}
/**
* Reset all configuration of each engine to its default value.
*/
private void resetConfigurations() {
for (Entry<String, InteractiveUIContent> interactiveContentEntry : interactiveUis.entrySet()) {
for (AbstractConfigurationUI configurator : interactiveContentEntry.getValue().getConfigurators()
.values()) {
configurator.resetDefault();
}
}
}
/**
* Reset engine preference to default using highest rank strategy.
*
* @param registry
* @param preferenceKey
*/
private <T> void resetDefaultPreferencesToHighestRank(IItemRegistry<T> registry, String preferenceKey,
DataHolder<T> dataObject) {
InteractiveUIContent interactiveContent = interactiveUis.get(preferenceKey);
if (interactiveContent != null) {
IItemDescriptor<T> defaultEngine = registry.getHighestRankingDescriptor();
interactiveContent.select(defaultEngine);
interactiveContent.checkElement(defaultEngine);
dataObject.setData(Collections.singleton(defaultEngine));
}
}
/**
* Reset to default for a collection (using all is default).
*
* @param registry
* @param preferenceKey
* @param dataObject
*/
private <T> void resetDefaultPreferencesToAll(IItemRegistry<T> registry, String preferenceKey,
DataHolder<T> dataObject) {
InteractiveUIContent interactiveContent = interactiveUis.get(preferenceKey);
if (interactiveContent != null) {
IItemDescriptor<T> defaultEngine = registry.getHighestRankingDescriptor();
interactiveContent.select(defaultEngine);
List<IItemDescriptor<T>> itemDescriptors = registry.getItemDescriptors();
interactiveContent
.checkElements(itemDescriptors.toArray(new IItemDescriptor[itemDescriptors.size()]));
dataObject.setData(Sets.newHashSet(itemDescriptors));
}
}
/**
* Set an engine preferences into the preferences (for a collection).
*
* @param preferenceKey
* @param currentSelectedEngine
* @param defaultConf
*/
private <T> void setEnginePreferences(String preferenceKey, Set<IItemDescriptor<T>> currentSelectedEngine,
Collection<IItemDescriptor<T>> defaultConf) {
if (currentSelectedEngine != null && !currentSelectedEngine.containsAll(defaultConf)) {
StringBuilder descriptorsKey = new StringBuilder();
for (Iterator<IItemDescriptor<T>> iterator = currentSelectedEngine.iterator(); iterator
.hasNext();) {
IItemDescriptor<T> iItemDescriptor = iterator.next();
descriptorsKey.append(iItemDescriptor.getID());
if (iterator.hasNext()) {
descriptorsKey.append(ItemUtil.PREFERENCE_DELIMITER);
}
}
getPreferenceStore().setValue(preferenceKey, descriptorsKey.toString());
} else {
getPreferenceStore().setToDefault(preferenceKey);
}
}
}