Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Constant2018-08-22 13:04:44 +0000
committerOlivier Constant2018-08-28 12:10:54 +0000
commit96eba5f4be692b468c5363297c8f1297dfb00cb0 (patch)
tree696b379c908860a50a34e6f6f6a68b1ed2e815b8
parenta67ea921db5f983113b880d413128070a02cc397 (diff)
downloadorg.eclipse.emf.diffmerge.core-96eba5f4be692b468c5363297c8f1297dfb00cb0.tar.gz
org.eclipse.emf.diffmerge.core-96eba5f4be692b468c5363297c8f1297dfb00cb0.tar.xz
org.eclipse.emf.diffmerge.core-96eba5f4be692b468c5363297c8f1297dfb00cb0.zip
Bug 516234 - Improve text comparison by using an external text viewer
- Model modifications go through model scopes - Tool is unique and located in the Features viewer - Double click is also supported in the Features viewer - Sides and directions are aligned with the model comparison - The "switch left and right view" button is hidden - The overall aspect of the text merge dialog is slightly different - UI strings are externalized Change-Id: I5290e2618c49ebaa8d7be2ed614e29c06f71b43a Signed-off-by: Olivier Constant <olivier.constant@thalesgroup.com>
-rw-r--r--plugins/org.eclipse.emf.diffmerge.connector.core/src/org/eclipse/emf/diffmerge/connector/core/ext/TeamComparisonViewer.java12
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/icons/full/compare.gifbin0 -> 224 bytes
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/EMFDiffMergeUIPlugin.java4
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/Messages.java3
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/messages.properties3
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/util/UIUtil.java4
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/AbstractComparisonViewer.java21
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/ComparisonViewer.java510
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/EMFDiffNode.java42
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/HeaderViewer.java2
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/MergerContent.java126
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextCompareContent.java115
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerDialog.java474
-rw-r--r--plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerViewerDialog.java285
14 files changed, 922 insertions, 679 deletions
diff --git a/plugins/org.eclipse.emf.diffmerge.connector.core/src/org/eclipse/emf/diffmerge/connector/core/ext/TeamComparisonViewer.java b/plugins/org.eclipse.emf.diffmerge.connector.core/src/org/eclipse/emf/diffmerge/connector/core/ext/TeamComparisonViewer.java
index f16588b3..ccf32730 100644
--- a/plugins/org.eclipse.emf.diffmerge.connector.core/src/org/eclipse/emf/diffmerge/connector/core/ext/TeamComparisonViewer.java
+++ b/plugins/org.eclipse.emf.diffmerge.connector.core/src/org/eclipse/emf/diffmerge/connector/core/ext/TeamComparisonViewer.java
@@ -11,6 +11,8 @@
*/
package org.eclipse.emf.diffmerge.connector.core.ext;
+import static org.eclipse.emf.diffmerge.ui.util.UIUtil.CC_MIRRORED_PROPERTY;
+
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
@@ -62,10 +64,6 @@ import org.eclipse.ui.IWorkbenchWindow;
*/
public class TeamComparisonViewer extends Viewer implements IFlushable, IPropertyChangeNotifier {
- /** The CompareConfiguration "mirrored" property defined in Neon and later,
- * explicit here for compatibility with older versions of Eclipse */
- protected static final String MIRRORED = "MIRRORED"; //$NON-NLS-1$
-
/** The non-null control of the viewer */
protected final Composite _control;
@@ -138,11 +136,11 @@ public class TeamComparisonViewer extends Viewer implements IFlushable, IPropert
// Invert left and right
if (_configuration != null) {
// Ensure consistency with text comparison
- _configuration.setProperty(MIRRORED, Boolean.TRUE);
+ _configuration.setProperty(CC_MIRRORED_PROPERTY, Boolean.TRUE);
}
}
}
- Object mirroredProp = _configuration.getProperty(MIRRORED);
+ Object mirroredProp = _configuration.getProperty(CC_MIRRORED_PROPERTY);
if (mirroredProp instanceof Boolean && ((Boolean)mirroredProp).booleanValue()) {
setup_p.swapLeftRole();
}
@@ -270,7 +268,7 @@ public class TeamComparisonViewer extends Viewer implements IFlushable, IPropert
protected Role getLeftRole(ComparisonSetup setup_p) {
Role result = setup_p.getLeftRole();
if (_configuration != null) {
- Object mirrored = _configuration.getProperty(MIRRORED);
+ Object mirrored = _configuration.getProperty(CC_MIRRORED_PROPERTY);
if (mirrored instanceof Boolean && ((Boolean)mirrored).booleanValue())
result = result.opposite();
}
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/icons/full/compare.gif b/plugins/org.eclipse.emf.diffmerge.ui/icons/full/compare.gif
new file mode 100644
index 00000000..dc549bce
--- /dev/null
+++ b/plugins/org.eclipse.emf.diffmerge.ui/icons/full/compare.gif
Binary files differ
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/EMFDiffMergeUIPlugin.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/EMFDiffMergeUIPlugin.java
index 6f7f260c..d129dcae 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/EMFDiffMergeUIPlugin.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/EMFDiffMergeUIPlugin.java
@@ -55,8 +55,8 @@ public class EMFDiffMergeUIPlugin extends AbstractUIPlugin {
/** Identifiers for UI images */
@SuppressWarnings("javadoc")
public static enum ImageID {
- CHECKED, CHECKED_DISABLED, CHECKIN_ACTION, CHECKOUT_ACTION, COLLAPSEALL, CONFLICT_STAT, DELETE,
- DOWN, EMPTY, EXPANDALL, FILTER, INC_STAT, INC_ADD_STAT, INC_REM_STAT, LEFT, LOCK, LOCK_CLOSED,
+ CHECKED, CHECKED_DISABLED, CHECKIN_ACTION, CHECKOUT_ACTION, COLLAPSEALL, COMPARE, CONFLICT_STAT,
+ DELETE, DOWN, EMPTY, EXPANDALL, FILTER, INC_STAT, INC_ADD_STAT, INC_REM_STAT, LEFT, LOCK, LOCK_CLOSED,
LOCK_OPEN, MODIFIED_STAT, NEXT_CHANGE_NAV, NEXT_DIFF_NAV, OUT_STAT, OUT_ADD_STAT, OUT_REM_STAT,
PLUS, PREV_CHANGE_NAV, PREV_DIFF_NAV, REDO, RIGHT, SHOW, SORT, SWAP, SYNCED, TREE, UNCHECKED,
UNCHECKED_DISABLED, UNDO, UP, UPDATE, VIEW_MENU, WARNING }
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/Messages.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/Messages.java
index 8d3f6001..d8d6a65f 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/Messages.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/Messages.java
@@ -106,6 +106,7 @@ public class Messages extends NLS {
public static String ComparisonViewer_MergeRightTooltip;
public static String ComparisonViewer_NextTooltip;
public static String ComparisonViewer_NoDiffsToMerge;
+ public static String ComparisonViewer_OpenDedicated_ToolTip;
public static String ComparisonViewer_PreviousTooltip;
public static String ComparisonViewer_RestartInProgress;
public static String ComparisonViewer_Right;
@@ -234,6 +235,8 @@ public class Messages extends NLS {
public static String PropertyChangeCategory_Description;
public static String PropertyChangeCategory_Text;
public static String ResourceScopeDefinitionFactory_Label;
+ public static String TextMergerDialog_HeaderLabel;
+ public static String TextMergerDialog_ShellLabel;
public static String ThreeWayOriginCategory_DescriptionLeft;
public static String ThreeWayOriginCategory_DescriptionRight;
public static String ThreeWayOriginCategory_TextLeft;
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/messages.properties b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/messages.properties
index 94b6f9e5..134a7084 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/messages.properties
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/messages.properties
@@ -86,6 +86,7 @@ ComparisonViewer_MergeLeftTooltip=Copy to the left
ComparisonViewer_MergeRightTooltip=Copy to the right
ComparisonViewer_NextTooltip=Next model difference
ComparisonViewer_NoDiffsToMerge=No difference to merge.
+ComparisonViewer_OpenDedicated_ToolTip=Open in dedicated editor
ComparisonViewer_PreviousTooltip=Previous model difference
ComparisonViewer_RestartInProgress=Updating comparison
ComparisonViewer_Right=right
@@ -214,6 +215,8 @@ OrderDifferenceCategory_Text=Order differences
PropertyChangeCategory_Description=Differences in the values of properties (attributes or references) of model elements.
PropertyChangeCategory_Text=Property differences
ResourceScopeDefinitionFactory_Label=Fragmented contents
+TextMergerDialog_HeaderLabel=Text Compare
+TextMergerDialog_ShellLabel=Compare Contents
ThreeWayOriginCategory_DescriptionLeft=Differences that originate from the left-hand side.
ThreeWayOriginCategory_DescriptionRight=Differences that originate from the right-hand side.
ThreeWayOriginCategory_TextLeft=Differences on the left
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/util/UIUtil.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/util/UIUtil.java
index 9254d420..0e6964ae 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/util/UIUtil.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/util/UIUtil.java
@@ -68,6 +68,10 @@ public final class UIUtil {
//Forbid instantiation
}
+ /** The CompareConfiguration "mirrored" property defined in Neon and later,
+ * explicit here for compatibility with older versions of Eclipse */
+ public static final String CC_MIRRORED_PROPERTY = "MIRRORED"; //$NON-NLS-1$
+
/**
* Create and return a composite within the given one with default characteristics
* @param parent_p a non-null composite
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/AbstractComparisonViewer.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/AbstractComparisonViewer.java
index b07dda4b..ad4516d0 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/AbstractComparisonViewer.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/AbstractComparisonViewer.java
@@ -186,6 +186,22 @@ implements IFlushable, IPropertyChangeNotifier, ICompareInputChangeListener, IAd
}
/**
+ * Execute the given runnable that may solely modify the comparison
+ * and ignores transactional aspects
+ * @param runnable_p a non-null object
+ */
+ protected void executeOnComparison(final Runnable runnable_p) {
+ EMFDiffNode input = getInput();
+ final boolean recordChanges = input != null && input.isUndoRedoSupported();
+ final EditingDomain domain = getEditingDomain();
+ try {
+ MiscUtil.executeWithBusyCursor(domain, null, runnable_p, recordChanges, getDisplay());
+ } catch (Exception e) {
+ throw new OperationCanceledException(e.getLocalizedMessage()); // Trigger transaction rollback
+ }
+ }
+
+ /**
* Execute the given runnable that may modify the model on the given side
* and ignores transactional aspects
* @param runnable_p a non-null object
@@ -343,7 +359,10 @@ implements IFlushable, IPropertyChangeNotifier, ICompareInputChangeListener, IAd
if (comparison != null) {
IModelScope impactedScope = comparison.getScope(
input.getRoleForSide(onLeft_p));
- if (impactedScope instanceof IPersistentModelScope) {
+ if (impactedScope instanceof IEditingDomainProvider) {
+ result = ((IEditingDomainProvider)impactedScope).getEditingDomain();
+ }
+ if (result == null && impactedScope instanceof IPersistentModelScope) {
Resource resource = ((IPersistentModelScope)impactedScope).getHoldingResource();
if (resource != null)
result = TransactionUtil.getEditingDomain(resource);
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/ComparisonViewer.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/ComparisonViewer.java
index 19f01d1d..3c6aa407 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/ComparisonViewer.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/ComparisonViewer.java
@@ -55,7 +55,6 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.Logger;
import org.eclipse.emf.diffmerge.api.IComparison;
import org.eclipse.emf.diffmerge.api.IMatch;
@@ -64,8 +63,8 @@ import org.eclipse.emf.diffmerge.api.diff.IDifference;
import org.eclipse.emf.diffmerge.api.diff.IPresenceDifference;
import org.eclipse.emf.diffmerge.api.diff.IReferenceValuePresence;
import org.eclipse.emf.diffmerge.api.diff.IValuePresence;
+import org.eclipse.emf.diffmerge.api.scopes.IEditableModelScope;
import org.eclipse.emf.diffmerge.diffdata.EComparison;
-import org.eclipse.emf.diffmerge.diffdata.EElementRelativePresence;
import org.eclipse.emf.diffmerge.diffdata.EMatch;
import org.eclipse.emf.diffmerge.diffdata.EMergeableDifference;
import org.eclipse.emf.diffmerge.diffdata.EValuePresence;
@@ -93,12 +92,11 @@ import org.eclipse.emf.diffmerge.ui.util.SymmetricMatchComparer;
import org.eclipse.emf.diffmerge.ui.util.UIUtil;
import org.eclipse.emf.diffmerge.ui.viewers.FeaturesViewer.FeaturesInput;
import org.eclipse.emf.diffmerge.ui.viewers.MergeImpactViewer.ImpactInput;
-import org.eclipse.emf.diffmerge.ui.viewers.TextMergerViewerDialog.EMFDiffNodeWrapper;
+import org.eclipse.emf.diffmerge.ui.viewers.TextMergerDialog.TextDiffNode;
import org.eclipse.emf.diffmerge.ui.viewers.ValuesViewer.ValuesInput;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.GroupMarker;
@@ -156,7 +154,6 @@ import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.menus.IMenuService;
-import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.progress.IProgressService;
@@ -194,8 +191,8 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/** The name of the "ignore right activation" property */
public static final String PROPERTY_ACTIVATION_IGNORE_RIGHT = "PROPERTY_ACTIVATION_IGNORE_RIGHT"; //$NON-NLS-1$
- /** The name of the "open in external viewer activation" property */
- public static final String PROPERTY_ACTIVATION_OPEN_EXTERNAL = "PROPERTY_ACTIVATION_OPEN_EXTERNAL"; //$NON-NLS-1$
+ /** The name of the "open in dedicated viewer activation" property */
+ public static final String PROPERTY_ACTIVATION_OPEN_DEDICATED = "PROPERTY_ACTIVATION_OPEN_DEDICATED"; //$NON-NLS-1$
/** The synthesis model tree viewer */
protected EnhancedComparisonTreeViewer _viewerSynthesisMain;
@@ -629,7 +626,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "log events" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemLogEvents(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -758,9 +755,52 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
/**
+ * Create the "open in dedicated editor" item in the given context
+ * and return it
+ * @param toolbar_p a non-null object
+ * @return a potentially null item
+ */
+ protected Item createItemOpenDedicated(ToolBar toolbar_p) {
+ final ToolItem result = new ToolItem(toolbar_p, SWT.PUSH);
+ // Image
+ result.setImage(getImage(ImageID.COMPARE));
+ // Tool tip text
+ result.setToolTipText(Messages.ComparisonViewer_OpenDedicated_ToolTip);
+ result.setEnabled(false);
+ // Enabled/visible state
+ addPropertyChangeListener(new IPropertyChangeListener() {
+ /**
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (PROPERTY_ACTIVATION_OPEN_DEDICATED.equals(event.getProperty())) {
+ boolean newEnabled = ((Boolean)event.getNewValue()).booleanValue();
+ result.setEnabled(newEnabled);
+ }
+ }
+ });
+ // Selection
+ result.addSelectionListener(new SelectionAdapter() {
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(SelectionEvent event) {
+ EMFDiffNode input = getInput();
+ ComparisonSelection selection = getSelection();
+ if (isDedicatedViewerApplicable(input, selection)) {
+ openDedicatedViewer(getInput(), getSelection().asMatch(),
+ (EAttribute)selection.asFeature());
+ }
+ }
+ });
+ return result;
+ }
+
+ /**
* Create the "restart" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemRestart(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.PUSH);
@@ -796,7 +836,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show all values and properties" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowAllFeatures(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.RADIO);
@@ -819,7 +859,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show all values" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowAllValues(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.RADIO);
@@ -842,7 +882,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show difference numbers per match" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowDifferenceNumbers(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -881,7 +921,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show values on differences" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowDiffValues(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.RADIO);
@@ -905,7 +945,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show merge impact" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowImpact(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -945,7 +985,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show left/right contents" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowSides(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -985,7 +1025,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "show uncounted elements" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemShowUncounted(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -1009,7 +1049,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "support undo/redo" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemSupportUndoRedo(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -1147,7 +1187,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "use custom icons" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemUseCustomIcons(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -1193,7 +1233,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "use custom labels" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemUseCustomLabels(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -1237,7 +1277,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
/**
* Create the "Use technical representation" item in the given context and return it
* @param context_p a non-null object
- * @return result a potentially null item
+ * @return a potentially null item
*/
protected Item createItemUseTechnicalRepresentation(Menu context_p) {
final MenuItem result = new MenuItem(context_p, SWT.CHECK);
@@ -1412,8 +1452,9 @@ public class ComparisonViewer extends AbstractComparisonViewer {
// One match: new input
FeaturesInput newInput = new FeaturesInput(getInput(), match);
boolean changeInput = !newInput.equals(result.getInput());
- if (changeInput)
+ if (changeInput) {
result.setInput(newInput);
+ }
// New selection
MatchAndFeature maf = selection.asMatchAndFeature();
if (maf != null) {
@@ -1421,7 +1462,8 @@ public class ComparisonViewer extends AbstractComparisonViewer {
result.setSelection(newSelection, true);
} else if (changeInput) {
// New input and no feature selected: select first feature if any
- MatchAndFeature firstMAF = result.getInnerViewer().getFirstIn(newInput);
+ MatchAndFeature firstMAF =
+ getDefaultFeatureSelection(newInput, result.getInnerViewer());
if (firstMAF != null) {
result.setSelection(new StructuredSelection(firstMAF));
}
@@ -1437,6 +1479,21 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
}
});
+ // Double click: open dedicated viewer
+ result.getInnerViewer().addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ ISelection selection = event.getViewer().getSelection();
+ if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
+ Object first = ((IStructuredSelection)selection).getFirstElement();
+ if (first instanceof MatchAndFeature) {
+ MatchAndFeature maf = (MatchAndFeature)first;
+ if (TextMergerDialog.isApplicableTo(maf.getFeature())) {
+ openDedicatedViewer(getInput(), maf.getMatch(), (EAttribute)maf.getFeature());
+ }
+ }
+ }
+ }
+ });
return result;
}
@@ -1668,15 +1725,11 @@ public class ComparisonViewer extends AbstractComparisonViewer {
currentMatch = currentInput.getMatchAndFeature().getMatch();
if (newMatch != currentMatch) {
// New match is different from current match
- HeaderViewer<?> rawFeaturesViewer = getFeaturesViewer();
- if (rawFeaturesViewer instanceof EnhancedFeaturesViewer) {
- EnhancedFeaturesViewer featuresViewer = (EnhancedFeaturesViewer)rawFeaturesViewer;
- FeaturesInput featuresInput = new FeaturesInput(getInput(), newMatch);
- MatchAndFeature firstMAF = featuresViewer.getInnerViewer().getFirstIn(featuresInput);
- if (firstMAF != null) {
- // First feature must be selected
- newInput = new ValuesInput(getInput(), firstMAF);
- }
+ FeaturesInput featuresInput = new FeaturesInput(getInput(), newMatch);
+ MatchAndFeature firstMAF = getDefaultFeatureSelection(featuresInput);
+ if (firstMAF != null) {
+ // Feature selected by default
+ newInput = new ValuesInput(getInput(), firstMAF);
}
} else {
// Same match and no feature
@@ -1689,14 +1742,13 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
}
});
-
- // add double click listener
+ // Double click: open dedicated viewer
result.getInnerViewer().addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
ValuesInput input = (ValuesInput) event.getViewer().getInput();
- if (canOpenInExternalEditor(input.getMatchAndFeature().getFeature())) {
- openExternalViewer(getInput(), input.getMatchAndFeature().getMatch(),
- input.getMatchAndFeature().getFeature(), isLeftSide_p);
+ MatchAndFeature maf = input.getMatchAndFeature();
+ if (TextMergerDialog.isApplicableTo(maf.getFeature())) {
+ openDedicatedViewer(getInput(), maf.getMatch(), (EAttribute)maf.getFeature());
}
}
});
@@ -1751,6 +1803,37 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
/**
+ * Return the match and feature that must be selected by default in the Features Viewer
+ * when its input is the given one
+ * @param nodeAndMatch_p a non-null object
+ * @return a potentially null object
+ */
+ protected MatchAndFeature getDefaultFeatureSelection(FeaturesInput nodeAndMatch_p) {
+ MatchAndFeature result = null;
+ HeaderViewer<?> rawFeaturesViewer = getFeaturesViewer();
+ if (rawFeaturesViewer instanceof EnhancedFeaturesViewer) {
+ FeaturesViewer viewer = ((EnhancedFeaturesViewer)rawFeaturesViewer).getInnerViewer();
+ if (viewer != null) {
+ result = getDefaultFeatureSelection(nodeAndMatch_p, viewer);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return the match and feature that must be selected by default in the given
+ * Features Viewer when its input is the given one
+ * @param nodeAndMatch_p a non-null object
+ * @param viewer_p a non-null viewer
+ * @return a potentially null object
+ */
+ protected MatchAndFeature getDefaultFeatureSelection(FeaturesInput nodeAndMatch_p,
+ FeaturesViewer viewer_p) {
+ MatchAndFeature result = viewer_p.getFirstIn(nodeAndMatch_p);
+ return result;
+ }
+
+ /**
* Return the default respective weights of the rows (sashes) of the GUI
* @return an int array whose size is equal to the number of rows
*/
@@ -1983,6 +2066,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
final ComparisonSelection selection = getSelection();
if (selection == null) return; // Should not happen according to ignore tool activation
EMFDiffNode input = getInput();
+ if (input == null) return; // Should not happen according to ignore tool activation
List<EMatch> selectedMatches = getSelectedMatchesForInteractions(selection);
// Make choices
IgnoreChoiceData choices = new IgnoreChoiceData(
@@ -1990,37 +2074,35 @@ public class ComparisonViewer extends AbstractComparisonViewer {
makeIgnoreChoices(choices, input, selectedMatches);
if (!choices.isProceed()) return;
// Ignore operation is set to proceed and choices have been made
- final Collection<IDifference> toIgnore = !selectedMatches.isEmpty()? getDifferencesToMerge(
- selectedMatches, input.getRoleForSide(onLeft_p), choices.isCoverChildren(), choices.isSideExclusive()):
- getInput().getCategoryManager().getPendingDifferencesFiltered(selection.asDifferencesToMerge());
- if (!toIgnore.isEmpty()) {
- executeOnModel(new Runnable() {
+ Collection<IDifference> toIgnore;
+ if (!selectedMatches.isEmpty()) {
+ toIgnore = getDifferencesToMerge(
+ selectedMatches, input.getRoleForSide(onLeft_p),
+ choices.isCoverChildren(), choices.isSideExclusive());
+ } else {
+ toIgnore = getInput().getCategoryManager().getPendingDifferencesFiltered(
+ selection.asDifferencesToMerge());
+ }
+ ignore(toIgnore);
+ }
+
+ /**
+ * Ignore the given set of differences
+ * @param differences_p a non-null, potentially empty set of differences
+ */
+ protected void ignore(final Collection<IDifference> differences_p) {
+ final EMFDiffNode input = getInput();
+ final ComparisonSelection selection = getSelection();
+ if (input != null && !differences_p.isEmpty()) {
+ executeOnComparison(new Runnable() {
/**
* @see java.lang.Runnable#run()
*/
public void run() {
- for (IDifference diff : toIgnore) {
- if (diff instanceof EElementRelativePresence) {
- EElementRelativePresence presence = (EElementRelativePresence)diff;
- presence.setIgnored(true);
- // Also on symmetrical if any
- if (diff instanceof EValuePresence) {
- IValuePresence symmetrical = ((EValuePresence)diff).getSymmetrical();
- if (symmetrical instanceof EMergeableDifference)
- ((EMergeableDifference) symmetrical).setIgnored(true);
- // Also on symmetrical ownership if any
- if (diff instanceof IReferenceValuePresence) {
- IReferenceValuePresence symmetricalOwnership =
- ((IReferenceValuePresence)diff).getSymmetricalOwnership();
- if (symmetricalOwnership instanceof EMergeableDifference)
- ((EMergeableDifference)symmetricalOwnership).setIgnored(true);
- }
- }
- }
- }
+ input.ignore(differences_p);
getUIComparison().setLastActionSelection(selection);
}
- }, onLeft_p);
+ });
if (!input.isReactive()) {
firePropertyChangeEvent(CompareEditorInput.DIRTY_STATE, new Boolean(true));
input.updateDifferenceNumbers();
@@ -2134,6 +2216,31 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
/**
+ * Return whether the "open dedicated viewer" tool is applicable in the given context
+ * @param input_p a potentially null input
+ * @param selection_p a potentially null selection
+ */
+ protected boolean isDedicatedViewerApplicable(EMFDiffNode input_p,
+ ComparisonSelection selection_p) {
+ boolean result = false;
+ if (input_p != null && selection_p != null && !selection_p.isEmpty()) {
+ EStructuralFeature feature = selection_p.asFeature();
+ if (feature == null) {
+ EMatch selectedMatch = selection_p.asMatch();
+ if (selectedMatch != null) {
+ FeaturesInput nodeAndMatch = new FeaturesInput(input_p, selectedMatch);
+ MatchAndFeature defaultMAF = getDefaultFeatureSelection(nodeAndMatch);
+ if (defaultMAF != null) {
+ feature = defaultMAF.getFeature();
+ }
+ }
+ }
+ result = TextMergerDialog.isApplicableTo(feature);
+ }
+ return result;
+ }
+
+ /**
* Set the given specification of ignore choices according to the given
* input and set of selected matches
* @param choices_p the non-null specification of the ignore choices
@@ -2268,6 +2375,45 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
/**
+ * Apply the merge of a value defined through a dedicated viewer
+ * @param node_p the non-null diff node
+ * @param match_p the non-null match element concerned
+ * @param feature_p the non-null feature concerned
+ * @param textDiffNode_p the non-null output of the dedicated merge operation
+ */
+ protected void mergeFromDedicatedViewer(final EMFDiffNode node_p, final IMatch match_p,
+ final EAttribute feature_p, TextDiffNode textDiffNode_p) {
+ final ComparisonSelection selection = getSelection();
+ final List<EMergeableDifference> toIgnore = selection.asDifferencesToMerge();
+ TextCompareContent left = textDiffNode_p.getLeft();
+ TextCompareContent right = textDiffNode_p.getRight();
+ String leftMergedValue = left.getEditedContent();
+ String rightMergedValue = right.getEditedContent();
+ if (leftMergedValue != null || rightMergedValue != null) {
+ // They cannot be both non-null due to TextMergerDialog.isEditable(boolean)
+ final boolean onLeft = leftMergedValue != null;
+ final String newValue = onLeft? leftMergedValue: rightMergedValue;
+ final IEditableModelScope impactedScope = node_p.getScope(onLeft);
+ executeOnModel(new IRunnableWithProgress() {
+ /**
+ * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor_p)
+ throws InvocationTargetException, InterruptedException {
+ EObject holder = match_p.get(node_p.getRoleForSide(onLeft));
+ impactedScope.add(holder, feature_p, newValue);
+ node_p.setModified(true, onLeft);
+ node_p.ignore(toIgnore);
+ getUIComparison().setLastActionSelection(selection);
+ }
+ }, onLeft);
+ setSelection(null);
+ firePropertyChangeEvent(CompareEditorInput.DIRTY_STATE, Boolean.TRUE);
+ getInput().updateDifferenceNumbers();
+ }
+ }
+
+ /**
* Navigate to the next/previous difference according to the given flag
* @param next_p whether navigation must be forward or back
* @return whether the operation could not be completed due to the
@@ -2286,6 +2432,37 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
/**
+ * Open a dedicated comparison viewer in order to view or merge a value
+ * on a given match through a given attribute.
+ * Precondition: the match and attribute qualify for a dedicated viewer.
+ * @param node_p a non-null diff node
+ * @param match_p the non-null match concerned
+ * @param feature_p the potentially null feature concerned where null stands for default
+ */
+ protected void openDedicatedViewer(final EMFDiffNode node_p, EMatch match_p,
+ EAttribute feature_p) {
+ assert feature_p == null || TextMergerDialog.isApplicableTo(feature_p);
+ EAttribute attribute = feature_p;
+ if (attribute == null) {
+ FeaturesInput nodeAndMatch = new FeaturesInput(node_p, match_p);
+ MatchAndFeature defaultMAF = getDefaultFeatureSelection(nodeAndMatch);
+ if (defaultMAF != null &&
+ TextMergerDialog.isApplicableTo(defaultMAF.getFeature())) {
+ attribute = (EAttribute)defaultMAF.getFeature();
+ }
+ }
+ if (attribute != null) {
+ TextMergerDialog dialog = new TextMergerDialog(
+ getShell(), node_p, match_p, attribute);
+ if (dialog.open() == Window.OK) {
+ // Merge confirmed
+ mergeFromDedicatedViewer(
+ node_p, match_p, attribute, dialog.getViewerInput());
+ }
+ }
+ }
+
+ /**
* Define the diff/merge-specific content of the contextual menu for
* the given viewer and associated (possibly the same) selection provider
* @param menuManager_p a non-null menu manager
@@ -2376,38 +2553,21 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
}
if (input != null) {
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_MERGE_TO_RIGHT, new Boolean(input.isEditable(false) && onLeft));
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_DELETE_LEFT, new Boolean(input.isEditable(true) && onLeft && allowDeletion));
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_MERGE_TO_LEFT, new Boolean(input.isEditable(true) && onRight));
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_DELETE_RIGHT, new Boolean(input.isEditable(false) && onRight && allowDeletion));
- }
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_IGNORE_LEFT, new Boolean(onLeft && allowIgnoring));
- firePropertyChangeEvent(
- PROPERTY_ACTIVATION_IGNORE_RIGHT, new Boolean(onRight && allowIgnoring));
- // refresh open in external window state.
- // use current selection to trigger open in external window action for
- // strings differences.
- if (selection != null && !selection.isEmpty()) {
- Boolean canOpenExternal = Boolean.FALSE;
- if (selection.asFeature() != null) {
- canOpenExternal = Boolean
- .valueOf(canOpenInExternalEditor(selection.asFeature()));
- } else if (selection.asMatch() != null) {
- Collection<EAttribute> attributesWithDifferences = selection.asMatch()
- .getAttributesWithDifferences();
- if (!attributesWithDifferences.isEmpty()) {
- EAttribute attribute = attributesWithDifferences.iterator().next();
- canOpenExternal = Boolean.valueOf(canOpenInExternalEditor(attribute));
- }
- }
- firePropertyChangeEvent(PROPERTY_ACTIVATION_OPEN_EXTERNAL,
- canOpenExternal);
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_MERGE_TO_RIGHT,
+ Boolean.valueOf(input.isEditable(false) && onLeft));
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_DELETE_LEFT,
+ Boolean.valueOf(input.isEditable(true) && onLeft && allowDeletion));
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_MERGE_TO_LEFT,
+ Boolean.valueOf(input.isEditable(true) && onRight));
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_DELETE_RIGHT,
+ Boolean.valueOf(input.isEditable(false) && onRight && allowDeletion));
}
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_IGNORE_LEFT,
+ Boolean.valueOf(onLeft && allowIgnoring));
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_IGNORE_RIGHT,
+ Boolean.valueOf(onRight && allowIgnoring));
+ firePropertyChangeEvent(PROPERTY_ACTIVATION_OPEN_DEDICATED,
+ Boolean.valueOf(isDedicatedViewerApplicable(input, selection)));
super.refreshTools();
}
@@ -2692,7 +2852,7 @@ public class ComparisonViewer extends AbstractComparisonViewer {
* Set up the navigation tools in the given tool bar
*/
protected void setupToolsDetails(ToolBar toolbar_p) {
- // Nothing by default
+ createItemOpenDedicated(toolbar_p);
}
/**
@@ -2705,8 +2865,6 @@ public class ComparisonViewer extends AbstractComparisonViewer {
createItemMerge(toolbar_p, !onLeft_p);
createItemIgnore(toolbar_p, onLeft_p);
createItemDelete(toolbar_p, onLeft_p);
- // create open in external window action
- createToolOpenExternal(toolbar_p, onLeft_p);
}
/**
@@ -2864,166 +3022,4 @@ public class ComparisonViewer extends AbstractComparisonViewer {
}
}
- /**
- * Utility method to indicate if the text viewer can be opened with the content of the feature.
- * By default, any EString type feature can be opened in the text viewer.
- *
- * @param feature_p the feature containing the content to display in the text viewer.
- * @return true if the feature content can be opened in the text viewer.
- */
- protected boolean canOpenInExternalEditor(EStructuralFeature feature_p) {
- return feature_p.getEType() == EcorePackage.Literals.ESTRING;
- }
-
- /**
- * Opens the textviewer on a modal dialog via the toolbar.
- *
- * @param diffNode the diffnode element
- * @param match the match element
- * @param onLeft the side
- */
- protected void openExternalViewer(final EMFDiffNode diffNode, EMatch match,
- boolean onLeft) {
- Collection<EAttribute> attributesWithDifferences = match
- .getAttributesWithDifferences();
- if (!attributesWithDifferences.isEmpty()) {
- EStructuralFeature feature = attributesWithDifferences.iterator().next();
- if (feature != null) {
- openExternalViewer(diffNode, match, feature, onLeft);
- }
- }
- }
-
- /**
- * Opens the textviwer on a modal dialog.
- *
- * @param diffNode the diffnode element
- * @param match the match element
- * @param feature the feature containing the contents to show in the textviewer
- * @param onLeft the side
- */
- protected void openExternalViewer(final EMFDiffNode diffNode, EMatch match,
- EStructuralFeature feature, boolean onLeft) {
- TextMergerViewerDialog dialog = new TextMergerViewerDialog(getShell(),
- diffNode, match, feature);
- if (dialog.open() == Window.OK) {
- // merge has been done on the dialog. refresh the viewer
- mergeAndRefresh(diffNode, match, feature, dialog.getViewerInput(),
- onLeft);
- }
- }
-
- /**
- * Run the merge operation from the content of the textviewer, and refresh the editor.
- *
- * @param diffNode the diffnode element
- * @param match the match element
- * @param feature the feature containing the contents to show in the textviewer
- * @param diffNodeWrapper the contents to be merge on the model
- * @param toLeft_p the side
- */
- private void mergeAndRefresh(final EMFDiffNode diffNode, final EMatch match,
- final EStructuralFeature feature, EMFDiffNodeWrapper diffNodeWrapper,
- boolean toLeft_p) {
- final ComparisonSelection selection = getSelection();
- final EList<EMergeableDifference> toIgnore = selection
- .asDifferencesToMerge();
- MergerContent left = (MergerContent) diffNodeWrapper.getLeft();
- final String mergedLeft = left.getEditedContent();
-
- MergerContent right = (MergerContent) diffNodeWrapper.getRight();
- final String mergedRight = right.getEditedContent();
- final Object leftContent = match.get(Role.TARGET).eGet(feature);
- final Object rightContent = match.get(Role.REFERENCE).eGet(feature);
-
- executeOnModel(new IRunnableWithProgress() {
- /**
- * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
- */
- public void run(IProgressMonitor monitor_p)
- throws InvocationTargetException, InterruptedException {
- if (mergedLeft != null) {
- if (leftContent instanceof String) {
- match.get(Role.TARGET).eSet(feature, mergedLeft);
- }
- diffNode.setModified(true, true);
- }
- if (mergedRight != null) {
- if (rightContent instanceof String) {
- match.get(Role.REFERENCE).eSet(feature, mergedRight);
- }
- diffNode.setModified(true, false);
- }
- if (!toIgnore.isEmpty()) {
- for (IDifference diff : toIgnore) {
- if (diff instanceof EElementRelativePresence) {
- EElementRelativePresence presence = (EElementRelativePresence) diff;
- presence.setIgnored(true);
- // Also on symmetrical if any
- if (diff instanceof EValuePresence) {
- IValuePresence symmetrical = ((EValuePresence) diff)
- .getSymmetrical();
- if (symmetrical instanceof EMergeableDifference) {
- ((EMergeableDifference)symmetrical).setIgnored(true);
- }
- }
- }
- }
- }
- }
- }, toLeft_p);
- getUIComparison().setLastActionSelection(null);
- setSelection(null);
- firePropertyChangeEvent(CompareEditorInput.DIRTY_STATE, Boolean.TRUE);
- getInput().updateDifferenceNumbers();
- }
-
- /**
- * Create the open in external textviwer editor tool item.
- *
- * @param toolbar the toolbar element
- * @param onLeft the side
- * @return the tool item created
- */
- private ToolItem createToolOpenExternal(ToolBar toolbar,
- final boolean onLeft) {
- final ToolItem result = new ToolItem(toolbar, SWT.PUSH);
- EMFDiffMergeUIPlugin.getDefault();
- // Image
- result.setImage(AbstractUIPlugin
- .imageDescriptorFromPlugin("org.eclipse.compare", //$NON-NLS-1$
- "$nl$/icons/full/eview16/compare_view.gif") //$NON-NLS-1$
- .createImage());
- // Tool tip
- result.setToolTipText("Open in external editor"); //$NON-NLS-1$
- result.setEnabled(false);
- // Activation.
- addPropertyChangeListener(new IPropertyChangeListener() {
- /**
- * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
- */
- public void propertyChange(PropertyChangeEvent event) {
- if (PROPERTY_ACTIVATION_OPEN_EXTERNAL.equals(event.getProperty())) {
- result.setEnabled(((Boolean) event.getNewValue()).booleanValue());
- }
- }
- });
- // Selection
- result.addSelectionListener(new SelectionAdapter() {
- /**
- * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
- */
- @Override
- public void widgetSelected(SelectionEvent event) {
- if (getSelection().asFeature() != null) {
- openExternalViewer(getInput(), getSelection().asMatch(),
- getSelection().asFeature(), onLeft);
- } else if (getSelection().asMatch() != null) {
- openExternalViewer(getInput(), getSelection().asMatch(), onLeft);
- }
- }
- });
- return result;
- }
-
}
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/EMFDiffNode.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/EMFDiffNode.java
index e322a9eb..4c4e46e0 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/EMFDiffNode.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/EMFDiffNode.java
@@ -28,6 +28,10 @@ import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.OperationHistoryEvent;
import org.eclipse.emf.diffmerge.api.IComparison;
import org.eclipse.emf.diffmerge.api.Role;
+import org.eclipse.emf.diffmerge.api.diff.IDifference;
+import org.eclipse.emf.diffmerge.api.diff.IReferenceValuePresence;
+import org.eclipse.emf.diffmerge.api.diff.IValuePresence;
+import org.eclipse.emf.diffmerge.api.scopes.IEditableModelScope;
import org.eclipse.emf.diffmerge.api.scopes.IFeaturedModelScope;
import org.eclipse.emf.diffmerge.diffdata.EComparison;
import org.eclipse.emf.diffmerge.diffdata.EMatch;
@@ -339,6 +343,17 @@ IUserPropertyOwner {
}
/**
+ * Return the scope o the given side
+ * @param left_p whether the side is left or right
+ * @return a non-null scope, unless the UI comparison has been disposed
+ */
+ public IEditableModelScope getScope(boolean left_p) {
+ EComparison comparison = getActualComparison();
+ return comparison != null?
+ comparison.getScope(getRoleForSide(left_p)): null;
+ }
+
+ /**
* Return the UI comparison of this node
* @return a non-null UI comparison
*/
@@ -422,6 +437,33 @@ IUserPropertyOwner {
}
/**
+ * Silently mark the given set of differences as ignored
+ * @param differences_p a non-null, potentially empty collection
+ */
+ public void ignore(Collection<? extends IDifference> differences_p) {
+ for (IDifference difference : differences_p) {
+ if (difference instanceof IDifference.Editable) {
+ ((IDifference.Editable)difference).setIgnored(true);
+ // Also on symmetrical if any
+ if (difference instanceof IValuePresence) {
+ IValuePresence symmetrical = ((IValuePresence)difference).getSymmetrical();
+ if (symmetrical instanceof IDifference.Editable) {
+ ((IDifference.Editable)symmetrical).setIgnored(true);
+ }
+ // Also on symmetrical ownership if any
+ if (difference instanceof IReferenceValuePresence) {
+ IReferenceValuePresence symmetricalOwnership =
+ ((IReferenceValuePresence)difference).getSymmetricalOwnership();
+ if (symmetricalOwnership instanceof IDifference.Editable) {
+ ((IDifference.Editable)symmetricalOwnership).setIgnored(true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Return whether the given structural feature must be considered as a containment
* @param feature_p a potentially null feature
*/
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/HeaderViewer.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/HeaderViewer.java
index eddaf5f9..27101bf6 100644
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/HeaderViewer.java
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/HeaderViewer.java
@@ -181,7 +181,7 @@ public abstract class HeaderViewer<V extends Viewer> extends Viewer {
}
/**
- * Return the wrapped viewer
+ * Return the wrapped viewer, non-null after controls have been created
*/
public V getInnerViewer() {
return _innerViewer;
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/MergerContent.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/MergerContent.java
deleted file mode 100644
index 087cf362..00000000
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/MergerContent.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * <copyright>
- *
- * Copyright (c) 2017-2018 Intel Corporation.
- * 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:
- * Stephane Bouchet (Intel Corporation) - Bug # : initial API and implementation
- *
- * </copyright>
- */
-package org.eclipse.emf.diffmerge.ui.viewers;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-
-import org.eclipse.compare.IEditableContent;
-import org.eclipse.compare.IStreamContentAccessor;
-import org.eclipse.compare.ITypedElement;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * The merger content class is used to display textual elements in the textViewer.
- *
- * @author Stephane Bouchet (Intel Corporation)
- *
- */
-public class MergerContent implements ITypedElement, IEditableContent, IStreamContentAccessor {
-
- /** the content to display. */
- private final Object content;
-
- /** indicates if the content is editable. */
- private final boolean editable;
-
- /** the editedContent if the initial content is edited. */
- private String editedContent;
-
- /**
- * The constructor.
- *
- * @param content_p the inital content to display.
- * @param editable_p true if the content can be edited.
- */
- public MergerContent(Object content_p, boolean editable_p) {
- this.content=content_p;
- this.editable=editable_p;
- }
-
- /**
- * @see org.eclipse.compare.IEditableContent#isEditable()
- */
- public boolean isEditable() {
- return editable;
- }
-
- /**
- * @see org.eclipse.compare.IEditableContent#setContent(byte[])
- */
- public void setContent(byte[] newContent) {
- try {
- editedContent=new String(newContent, "UTF-8"); //$NON-NLS-1$
- }
- catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * @see org.eclipse.compare.IEditableContent#replace(org.eclipse.compare.ITypedElement, org.eclipse.compare.ITypedElement)
- */
- public ITypedElement replace(ITypedElement dest, ITypedElement src) {
- return null;
- }
-
- /**
- * @see org.eclipse.compare.ITypedElement#getName()
- */
- public String getName() {
- return null;
- }
-
- /**
- * @see org.eclipse.compare.ITypedElement#getImage()
- */
- public Image getImage() {
- return null;
- }
-
- /**
- * @see org.eclipse.compare.ITypedElement#getType()
- */
- public String getType() {
- return ITypedElement.TEXT_TYPE;
- }
-
- /**
- * @see org.eclipse.compare.IStreamContentAccessor#getContents()
- */
- public InputStream getContents() throws CoreException {
- try {
- if (content instanceof String) {
- return new ByteArrayInputStream(((String)content).getBytes("UTF8")); //$NON-NLS-1$
- }
- }
- catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- return null;
- }
- return null;
- }
-
- /**
- * Returns the edited content.
- * @return the edited content.
- */
- public String getEditedContent() {
- return editedContent;
- }
-
-} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextCompareContent.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextCompareContent.java
new file mode 100644
index 00000000..50b72009
--- /dev/null
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextCompareContent.java
@@ -0,0 +1,115 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2017-2018 Intel 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:
+ * Stephane Bouchet (Intel Corporation) - Bug #516234 : initial API and implementation
+ * Olivier Constant (Thales Global Services) - final integration
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.diffmerge.ui.viewers;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.eclipse.compare.IEditableContent;
+import org.eclipse.compare.IStreamContentAccessor;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.graphics.Image;
+
+
+/**
+ * This class is used to display textual elements in the TextMergeViewer.
+ * @see TextMergeViewer
+ *
+ * @author Stephane Bouchet (Intel Corporation)
+ */
+public class TextCompareContent implements ITypedElement, IEditableContent,
+IStreamContentAccessor {
+
+ /** The non-null content to display */
+ private final String _content;
+
+ /** Whether the content is editable */
+ private final boolean _editable;
+
+ /** The edited content if the initial content has been edited */
+ protected String _editedContent;
+
+
+ /**
+ * Constructor
+ * @param content_p the non-null initial content to display
+ * @param editable_p whether the content can be edited
+ */
+ public TextCompareContent(String content_p, boolean editable_p) {
+ _content = content_p;
+ _editable = editable_p;
+ }
+
+ /**
+ * @see org.eclipse.compare.IStreamContentAccessor#getContents()
+ */
+ public InputStream getContents() throws CoreException {
+ return new ByteArrayInputStream(_content.getBytes());
+ }
+
+ /**
+ * Return the edited content, if any
+ * @return a potentially null string
+ */
+ public String getEditedContent() {
+ return _editedContent;
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getImage()
+ */
+ public Image getImage() {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getName()
+ */
+ public String getName() {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getType()
+ */
+ public String getType() {
+ return ITypedElement.TEXT_TYPE;
+ }
+
+ /**
+ * @see org.eclipse.compare.IEditableContent#isEditable()
+ */
+ public boolean isEditable() {
+ return _editable;
+ }
+
+ /**
+ * @see org.eclipse.compare.IEditableContent#replace(org.eclipse.compare.ITypedElement, org.eclipse.compare.ITypedElement)
+ */
+ public ITypedElement replace(ITypedElement dest_p, ITypedElement src_p) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.compare.IEditableContent#setContent(byte[])
+ */
+ public void setContent(byte[] newContent_p) {
+ _editedContent = new String(newContent_p);
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerDialog.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerDialog.java
new file mode 100644
index 00000000..dcb66f1f
--- /dev/null
+++ b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerDialog.java
@@ -0,0 +1,474 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2017-2018 Intel 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:
+ * Stephane Bouchet (Intel Corporation) - Bug #516234 : initial API and implementation
+ * Olivier Constant (Thales Global Services) - final integration
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.diffmerge.ui.viewers;
+
+import static org.eclipse.emf.diffmerge.api.Role.ANCESTOR;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.ICompareInput;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.diffmerge.api.IMatch;
+import org.eclipse.emf.diffmerge.api.Role;
+import org.eclipse.emf.diffmerge.api.diff.IAttributeValuePresence;
+import org.eclipse.emf.diffmerge.api.scopes.IFeaturedModelScope;
+import org.eclipse.emf.diffmerge.ui.Messages;
+import org.eclipse.emf.diffmerge.ui.util.DiffMergeLabelProvider;
+import org.eclipse.emf.diffmerge.ui.util.UIUtil;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IContributionManagerOverrides;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+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.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * This dialog show the compared content of a String feature to be reviewed
+ * and optionally edited.
+ *
+ * @author Stephane Bouchet (Intel Corporation)
+ */
+public class TextMergerDialog extends MessageDialog {
+
+ /**
+ * A diff node with text content. It can be used as input of a Text Merge Viewer.
+ * @author Stephane Bouchet (Intel Corporation)
+ */
+ protected class TextDiffNode extends DiffNode {
+ /** The optional ancestor content */
+ private TextCompareContent _ancestorContent;
+ /** The non-null left content */
+ private TextCompareContent _leftContent;
+ /** The non-null right content */
+ private TextCompareContent _rightContent;
+ /**
+ * Constructor
+ * @param kind_p the kind of the node according to Differencer
+ */
+ public TextDiffNode(int kind_p) {
+ super(kind_p);
+ }
+ /**
+ * @see org.eclipse.compare.structuremergeviewer.DiffNode#getAncestor()
+ */
+ @Override
+ public TextCompareContent getAncestor() {
+ if (_diffNode.isThreeWay()) {
+ _ancestorContent = new TextCompareContent(getValue(Role.ANCESTOR), false);
+ }
+ return _ancestorContent;
+ }
+ /**
+ * @see org.eclipse.compare.structuremergeviewer.DiffNode#getLeft()
+ */
+ @Override
+ public TextCompareContent getLeft() {
+ if (_leftContent == null) {
+ _leftContent = new TextCompareContent(
+ getValue(_diffNode.getRoleForSide(true)),
+ isEditable(true));
+ }
+ return _leftContent;
+ }
+ /**
+ * @see org.eclipse.compare.structuremergeviewer.DiffNode#getRight()
+ */
+ @Override
+ public TextCompareContent getRight() {
+ if (_rightContent == null) {
+ _rightContent = new TextCompareContent(
+ getValue(_diffNode.getRoleForSide(false)),
+ isEditable(false));
+ }
+ return _rightContent;
+ }
+ }
+
+
+ /** The number of tool bar columns */
+ protected static final int TOOLBAR_COLUMNS = 4;
+
+ /** The default size of the window */
+ protected static final Point DEFAULT_SIZE = new Point(800, 600);
+
+ /** The (initially null) label of the "switch left and right view" action */
+ protected static String __switchSidesActionLabel = null;
+
+ /** The non-null diff node */
+ protected final EMFDiffNode _diffNode;
+
+ /** The non-null match concerned */
+ protected final IMatch _match;
+
+ /** The non-null feature concerned */
+ protected final EAttribute _feature;
+
+ /** The non-null label provider */
+ protected final ILabelProvider _labelProvider = DiffMergeLabelProvider.getInstance();
+
+ /** The (non-null after initialization) text merge viewer */
+ protected TextMergeViewer _textViewer;
+
+ /** The (initially null, non-null after first attempt of use) tool bar manager */
+ protected ToolBarManager _toolBarManager;
+
+ /** The (non-null if the confirmation button has been pressed) input of the text merge viewer */
+ protected TextDiffNode _viewerInput;
+
+
+ /**
+ * Constructor
+ * @param shell_p a non-null shell
+ * @param diffNode_p a non-null diff node for the global comparison
+ * @param match_p the non-null match concerned
+ * @param feature_p the non-null attribute concerned
+ */
+ public TextMergerDialog(Shell shell_p, EMFDiffNode diffNode_p,
+ IMatch match_p, EAttribute feature_p) {
+ super(shell_p, null, null, null, 0,
+ new String[] {
+ IDialogConstants.OK_LABEL,
+ IDialogConstants.CANCEL_LABEL }, 0);
+ assert isApplicableTo(feature_p);
+ _diffNode = diffNode_p;
+ _match = match_p;
+ _feature = feature_p;
+ _toolBarManager = null;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.MessageDialog#buttonPressed(int)
+ */
+ @Override
+ protected void buttonPressed(int buttonId) {
+ // Store the merged content before closing so that it can be used afterwards
+ if (buttonId == Window.OK) {
+ _textViewer.flush(new NullProgressMonitor());
+ _viewerInput = (TextDiffNode)_textViewer.getInput();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.MessageDialog#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ @Override
+ protected void configureShell(Shell shell) {
+ shell.setText(Messages.TextMergerDialog_ShellLabel);
+ shell.setSize(DEFAULT_SIZE);
+ super.configureShell(shell);
+ }
+
+ /**
+ * Create, configure and return a compare configuration for the Text Merge Viewer
+ * @return a non-null object
+ */
+ protected CompareConfiguration createCompareConfiguration() {
+ CompareConfiguration result = new CompareConfiguration();
+ result.setProperty(UIUtil.CC_MIRRORED_PROPERTY, Boolean.FALSE);
+ if (_diffNode.isThreeWay()) {
+ result.setAncestorLabel(_labelProvider.getText(getScope(ANCESTOR)));
+ }
+ result.setLeftLabel(_labelProvider.getText(getScope(true)));
+ result.setLeftEditable(_diffNode.isEditable(true));
+ result.setRightLabel(_labelProvider.getText(getScope(false)));
+ result.setRightEditable(_diffNode.isEditable(false));
+ return result;
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.MessageDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected Control createDialogArea(Composite parent_p) {
+ // Parent layout
+ GridLayout layout = new GridLayout();
+ parent_p.setLayout(layout);
+ // Tool bar
+ final Composite toolbar = new Composite(parent_p, SWT.NONE);
+ GridLayout toolbarLayout = new GridLayout(TOOLBAR_COLUMNS, false);
+ toolbarLayout.marginHeight = 0;
+ toolbarLayout.marginWidth = 0;
+ toolbar.setLayout(toolbarLayout);
+ toolbar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ // Tool bar contents: image
+ Label labelImage = new Label(toolbar, SWT.NONE);
+ labelImage.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(
+ ISharedImages.IMG_OBJ_FILE));
+ labelImage.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+ // Tool bar contents: text
+ Label labelText = new Label(toolbar, SWT.TOP);
+ labelText.setText(Messages.TextMergerDialog_HeaderLabel);
+ labelText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+ // Main composite
+ final Composite main = new Composite(parent_p, SWT.NONE);
+ GridLayout mainLayout = new GridLayout();
+ mainLayout.marginHeight = 2;
+ mainLayout.marginWidth = 0;
+ main.setLayout(mainLayout);
+ main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ // Compare configuration for Text Merge Viewer
+ CompareConfiguration cc = createCompareConfiguration();
+ // Text Merge Viewer in main composite
+ _textViewer = createTextMergeViewer(main, toolbar, cc);
+ _textViewer.setLabelProvider(_labelProvider);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ data.horizontalSpan = 2;
+ _textViewer.getControl().setLayoutData(data);
+ // Input
+ ICompareInput input = new TextDiffNode(getDifferencerKind());
+ _textViewer.setInput(input);
+ return main;
+ }
+
+ /**
+ * Create and return the Text Merge Viewer of this dialog
+ * @param parent_p a non-null composite for the main control
+ * @param toolbar_p a non-null composite for the tool bar
+ * @param cc_p a non-null compare configuration
+ * @return a non-null Text Merge Viewer
+ */
+ protected TextMergeViewer createTextMergeViewer(Composite parent_p,
+ final Composite toolbar_p, CompareConfiguration cc_p) {
+ TextMergeViewer result = new TextMergeViewer(parent_p, SWT.BORDER, cc_p) {
+ /**
+ * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getToolBarManager(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected IToolBarManager getToolBarManager(Composite localParent_p) {
+ if (_toolBarManager != null && _toolBarManager.getControl() == null)
+ return null;
+ if (_toolBarManager == null) {
+ _toolBarManager = createToolBarManager(toolbar_p);
+ }
+ return _toolBarManager;
+ }
+ };
+ return result;
+ }
+
+ /**
+ * Create and return the tool bar manager of the main viewer in the given context
+ * @param parent_p a non-null composite
+ * @return a non-null tool bar manager
+ */
+ protected ToolBarManager createToolBarManager(Composite parent_p) {
+ final ToolBar tb = new ToolBar(parent_p, SWT.FLAT);
+ tb.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
+ ToolBarManager result = new ToolBarManager(tb);
+ result.setOverrides(new IContributionManagerOverrides() {
+ /**
+ * @see org.eclipse.jface.action.IContributionManagerOverrides#getAccelerator(org.eclipse.jface.action.IContributionItem)
+ */
+ public Integer getAccelerator(IContributionItem item_p) {
+ return null;
+ }
+ /**
+ * @see org.eclipse.jface.action.IContributionManagerOverrides#getAcceleratorText(org.eclipse.jface.action.IContributionItem)
+ */
+ public String getAcceleratorText(IContributionItem item_p) {
+ return null;
+ }
+ /**
+ * @see org.eclipse.jface.action.IContributionManagerOverrides#getEnabled(org.eclipse.jface.action.IContributionItem)
+ */
+ public Boolean getEnabled(IContributionItem item_p) {
+ // Disable "switch left and right view" action
+ Boolean localResult = null;
+ if (isSwitchSidesAction(item_p)) {
+ localResult = Boolean.FALSE;
+ }
+ return localResult;
+ }
+ /**
+ * @see org.eclipse.jface.action.IContributionManagerOverrides#getText(org.eclipse.jface.action.IContributionItem)
+ */
+ public String getText(IContributionItem item_p) {
+ return null;
+ }
+ /**
+ * @see org.eclipse.jface.action.IContributionManagerOverrides#getVisible(org.eclipse.jface.action.IContributionItem)
+ */
+ public Boolean getVisible(IContributionItem item_p) {
+ // Hide "switch left and right view" action
+ Boolean localResult = null;
+ if (isSwitchSidesAction(item_p)) {
+ localResult = Boolean.FALSE;
+ }
+ return localResult;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Return the difference related to the current state
+ * @return an attribute value presence which may have a symmetrical, or null if none
+ */
+ protected IAttributeValuePresence getDifference() {
+ IAttributeValuePresence result = null;
+ Collection<IAttributeValuePresence> allDiffs = _match.getAttributeDifferences(_feature);
+ // Size is between 0 and 2 since the upper bound is 1 according to method isApplicableTo
+ if (!allDiffs.isEmpty()) {
+ result = allDiffs.iterator().next();
+ }
+ return result;
+ }
+
+ /**
+ * Return the kind of the overall difference according to Differencer
+ * @return a positive int
+ */
+ protected int getDifferencerKind() {
+ return _diffNode.isThreeWay()? Differencer.CONFLICTING: Differencer.CHANGE;
+ }
+
+ /**
+ * Return the model scope on the given side
+ * @param left_p whether the side is left or right
+ * @return a non-null model scope
+ */
+ protected IFeaturedModelScope getScope(boolean left_p) {
+ return getScope(_diffNode.getRoleForSide(left_p));
+ }
+
+ /**
+ * Return the model scope that plays the given role
+ * @param role_p a non-null role
+ * @return a model scope that is non-null except for the ancestor role on a two-way comparison
+ */
+ protected IFeaturedModelScope getScope(Role role_p) {
+ return _diffNode.getActualComparison().getScope(role_p);
+ }
+
+ /**
+ * Return the label of the "switch left and right view" action
+ * @return a potentially null string
+ */
+ protected String getSwitchSidesActionLabel() {
+ String result = __switchSidesActionLabel;
+ if (result == null) {
+ final String BUNDLE_NAME=
+ "org.eclipse.compare.contentmergeviewer.TextMergeViewerResources"; //$NON-NLS-1$
+ ResourceBundle bundle = null;
+ try {
+ bundle = ResourceBundle.getBundle(BUNDLE_NAME);
+ } catch (MissingResourceException e) {
+ // Proceed
+ }
+ if (bundle != null) {
+ final String KEY = "action.SwitchLeftAndRight.label"; //$NON-NLS-1$
+ result = bundle.getString(KEY);
+ }
+ __switchSidesActionLabel = (result != null)? result:
+ "FAILED_TO_COMPUTE_SWITCH_SIDES_ACTION_LABEL"; //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ /**
+ * Return the value for merge on the side of the given role
+ * @param role_p a non-null role
+ * @return a value which is non-null except for the ancestor role on a two-way comparison
+ */
+ protected String getValue(Role role_p) {
+ String result = null;
+ IFeaturedModelScope scope = getScope(role_p);
+ if (scope != null) {
+ result = ""; // Default //$NON-NLS-1$
+ EObject element = _match.get(role_p);
+ if (element != null) {
+ List<Object> rawValue = scope.get(element, _feature); // Current value in case of previous text merge
+ if (rawValue.size() == 1) { // Value is present
+ result = (String)rawValue.get(0);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return the viewer input
+ * @return an object which is non-null if and only if the confirmation button has been pressed
+ */
+ public TextDiffNode getViewerInput() {
+ return _viewerInput;
+ }
+
+ /**
+ * Return whether text merge is applicable to the given structural feature
+ * @param feature_p a potentially null feature
+ */
+ public static boolean isApplicableTo(EStructuralFeature feature_p) {
+ return feature_p instanceof EAttribute &&
+ feature_p.getUpperBound() == 1 &&
+ String.class.equals(feature_p.getEType().getInstanceClass());
+ }
+
+ /**
+ * Return whether the given side is editable
+ * @param left_p whether the side is left
+ */
+ protected boolean isEditable(boolean left_p) {
+ // Forbid double edition: editable only if this side is the only editable one
+ return !_match.isPartial() && _diffNode.isEditable(left_p) && !_diffNode.isEditable(!left_p);
+ }
+
+ /**
+ * Return whether the given contribution item refers to the "switch left and right view" action
+ * @param item_p a non-null contribution item
+ */
+ protected boolean isSwitchSidesAction(IContributionItem item_p) {
+ boolean result = false;
+ // The contribution item has no ID so we fall back to using the action label
+ // as a criterion
+ if (item_p instanceof ActionContributionItem) {
+ ActionContributionItem actionItem = (ActionContributionItem)item_p;
+ String itemLabel = actionItem.getAction().getText();
+ if (itemLabel != null) {
+ result = itemLabel.equals(getSwitchSidesActionLabel());
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerViewerDialog.java b/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerViewerDialog.java
deleted file mode 100644
index 64b5ee63..00000000
--- a/plugins/org.eclipse.emf.diffmerge.ui/src/org/eclipse/emf/diffmerge/ui/viewers/TextMergerViewerDialog.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/**
- * <copyright>
- *
- * Copyright (c) 2017-2018 Intel Corporation.
- * 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:
- * Stephane Bouchet (Intel Corporation) - Bug # : initial API and implementation
- *
- * </copyright>
- */
-package org.eclipse.emf.diffmerge.ui.viewers;
-
-import org.eclipse.compare.CompareConfiguration;
-import org.eclipse.compare.ITypedElement;
-import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
-import org.eclipse.compare.structuremergeviewer.DiffNode;
-import org.eclipse.compare.structuremergeviewer.Differencer;
-import org.eclipse.compare.structuremergeviewer.ICompareInput;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.emf.diffmerge.api.Role;
-import org.eclipse.emf.diffmerge.api.scopes.IEditableModelScope;
-import org.eclipse.emf.diffmerge.diffdata.EMatch;
-import org.eclipse.emf.diffmerge.ui.util.DiffMergeLabelProvider;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-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.Shell;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-/**
- * The textual dialog editor that displays the content of a feature to be
- * reviwed and optionnaly edited.
- *
- * @author Stephane Bouchet (Intel Corporation)
- *
- */
-public class TextMergerViewerDialog extends MessageDialog {
-
- /** the number of toolbar columns. */
- private static final int TOOLBAR_COLUMNS = 3;
-
- /** the default size of the window. */
- private static final Point DEFAULT_SIZE = new Point(800, 600);
-
- /** the diffNode element. */
- protected final EMFDiffNode diffNode;
-
- /** the match element. */
- protected final EMatch match;
-
- /** the feature containing the values to display on both sides. */
- protected final EStructuralFeature feature;
-
- /** the label provider. */
- private final ILabelProvider labelProvider = DiffMergeLabelProvider
- .getInstance();
-
- /** the compare configuration. */
- private final CompareConfiguration compareConfiguration = new CompareConfiguration();
-
- /** the ancestor model. */
- private final IEditableModelScope ancestor;
-
- /** the left model. */
- private final IEditableModelScope left;
-
- /** the right model. */
- private final IEditableModelScope right;
-
- /** the textViewer. */
- private TextMergeViewer textViewer;
-
- /** the diffNode wrapper. */
- private EMFDiffNodeWrapper viewerInput;
-
- /**
- * This Utility class wrapps a diffNode element to a texttual element that the
- * textviewer can handle.
- *
- * @author Stephane Bouchet (Intel Corporation)
- *
- */
- class EMFDiffNodeWrapper extends DiffNode {
-
- /** the ancestor mergerContent. */
- private MergerContent ancestorMergerContent;
-
- /** the left mergerContent. */
- private MergerContent leftMergerContent;
-
- /** the right mergerContent. */
- private MergerContent rightMergerContent;
-
- /**
- * The constructor.
- *
- * @param kind
- * the difference Kind
- */
- public EMFDiffNodeWrapper(int kind) {
- super(kind);
- }
-
- /**
- * @see org.eclipse.compare.structuremergeviewer.DiffNode#getAncestor()
- */
- @Override
- public ITypedElement getAncestor() {
- if (match.get(Role.ANCESTOR) != null) {
- ancestorMergerContent = new MergerContent(
- match.get(Role.ANCESTOR).eGet(feature), false);
- }
- return ancestorMergerContent;
- }
-
- /**
- * @see org.eclipse.compare.structuremergeviewer.DiffNode#getLeft()
- */
- @Override
- public ITypedElement getLeft() {
- if (leftMergerContent == null) {
- leftMergerContent = new MergerContent(
- match.get(Role.TARGET).eGet(feature), diffNode.isEditable(true));
- }
- return leftMergerContent;
- }
-
- /**
- * @see org.eclipse.compare.structuremergeviewer.DiffNode#getRight()
- */
- @Override
- public ITypedElement getRight() {
- if (rightMergerContent == null) {
- rightMergerContent = new MergerContent(
- match.get(Role.REFERENCE).eGet(feature),
- diffNode.isEditable(false));
- }
- return rightMergerContent;
- }
-
- }
-
- /**
- * The constructor.
- *
- * @param parentShell
- * the parent shell.
- * @param diffNode_p
- * the diffNode element
- * @param match_p
- * the match element
- * @param feature_p
- * the feature containing the values to display
- */
- public TextMergerViewerDialog(Shell parentShell, EMFDiffNode diffNode_p,
- EMatch match_p, EStructuralFeature feature_p) {
- super(parentShell, null, null, null, 0,
- new String[] { "Merge", IDialogConstants.CANCEL_LABEL }, 0); //$NON-NLS-1$
- diffNode = diffNode_p;
- this.match = match_p;
- this.feature = feature_p;
- setShellStyle(getShellStyle() | SWT.RESIZE);
- ancestor = diffNode.getActualComparison().getScope(Role.ANCESTOR);
- left = diffNode.getActualComparison().getScope(Role.TARGET);
- right = diffNode.getActualComparison().getScope(Role.REFERENCE);
- }
-
- /**
- * @see org.eclipse.jface.dialogs.MessageDialog#configureShell(org.eclipse.swt.widgets.Shell)
- */
- @Override
- protected void configureShell(Shell shell) {
- shell.setText("Compare Contents"); //$NON-NLS-1$
- shell.setSize(DEFAULT_SIZE);
- super.configureShell(shell);
- }
-
- /**
- * @see org.eclipse.jface.dialogs.MessageDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
- */
- @Override
- protected Control createDialogArea(Composite parent) {
- GridLayout layout = new GridLayout();
- layout.verticalSpacing = 0;
- parent.setLayout(layout);
- final Composite toolbar = new Composite(parent, SWT.NONE);
- GridLayout toolbarLayout = new GridLayout(TOOLBAR_COLUMNS, false);
- toolbarLayout.marginHeight = 0;
- toolbarLayout.marginWidth = 0;
- toolbar.setLayout(toolbarLayout);
- toolbar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
- Label labelImage = new Label(toolbar, SWT.NONE);
- labelImage.setImage(PlatformUI.getWorkbench().getSharedImages()
- .getImage(ISharedImages.IMG_OBJ_FILE));
- labelImage.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
- Label labelText = new Label(toolbar, SWT.TOP);
- labelText.setText("Text Compare"); //$NON-NLS-1$
- labelText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
- final Composite main = new Composite(parent, SWT.NONE);
- GridLayout mainLayout = new GridLayout();
- mainLayout.marginHeight = 2;
- mainLayout.marginWidth = 0;
- main.setLayout(mainLayout);
- main.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- if (ancestor != null) {
- compareConfiguration.setAncestorLabel(labelProvider.getText(ancestor));
- }
-
- compareConfiguration.setLeftLabel(labelProvider.getText(left));
- compareConfiguration.setLeftEditable(!left.isReadOnly());
-
- compareConfiguration.setRightLabel(labelProvider.getText(right));
- compareConfiguration.setRightEditable(!right.isReadOnly());
-
- textViewer = new TextMergeViewer(main, SWT.BORDER, compareConfiguration) {
- private ToolBarManager toolBarManager;
-
- @Override
- protected IToolBarManager getToolBarManager(Composite parentComposite) {
- if (toolBarManager != null && toolBarManager.getControl() == null)
- return null;
- if (toolBarManager == null) {
- final ToolBar tb = new ToolBar(toolbar, SWT.FLAT);
- tb.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
- toolBarManager = new ToolBarManager(tb);
- }
- return toolBarManager;
- }
-
- };
- textViewer.setLabelProvider(labelProvider);
-
- ICompareInput input = new EMFDiffNodeWrapper(
- ancestor != null ? Differencer.CONFLICTING : Differencer.CHANGE);
-
- textViewer.setInput(input);
-
- GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
- data.horizontalSpan = 2;
- textViewer.getControl().setLayoutData(data);
- return main;
- }
-
- /**
- * @see org.eclipse.jface.dialogs.MessageDialog#buttonPressed(int)
- */
- @Override
- protected void buttonPressed(int buttonId) {
- // save the mergedContent before closing, will be used afterward by
- // comparisonViewer
- if (buttonId == Window.OK) {
- textViewer.flush(new NullProgressMonitor());
- viewerInput = (EMFDiffNodeWrapper) textViewer.getInput();
- }
- super.buttonPressed(buttonId);
- }
-
- /**
- * Returns the viewer input.
- *
- * @return the viewer input
- */
- protected EMFDiffNodeWrapper getViewerInput() {
- return viewerInput;
- }
-
-}

Back to the top