diff options
Diffstat (limited to 'plugins')
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 Binary files differnew file mode 100644 index 00000000..dc549bce --- /dev/null +++ b/plugins/org.eclipse.emf.diffmerge.ui/icons/full/compare.gif 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; - } - -} |