Bug 508257 - The "Swap sides" preference negatively affects Refactoring
Preview dialog

This change introduces API to disable swapping of the left and the right
panes in the Compare dialog.

Change-Id: I825085d5b27f3706eabafffbed509c5686e9a9be
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareConfiguration.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareConfiguration.java
index 0214515..6e18fbc 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareConfiguration.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareConfiguration.java
@@ -116,6 +116,7 @@
 	private IPreferenceStore fPreferenceStore;
 	private ListenerList<IPropertyChangeListener> fListeners= new ListenerList<>();
 	private HashMap<String, Object> fProperties= new HashMap<>();
+	private boolean fMirroringEnabled = true;
 	private boolean fLeftEditable= true;
 	private boolean fRightEditable= true;
 	private String fAncestorLabel;
@@ -366,16 +367,55 @@
 	}
 
 	/**
+	 * Returns true if the compare viewer is mirrored, i.e. the left and the right panes are swapped.
+	 * Mirroring is enabled by default.
+	 * <p>
 	 * <b>Only the views are mirrored. All model values for left and right are not changed!</b>
 	 *
-	 * @return true if the left and right side of the viewer are mirrored. Default is false.
+	 * @return true if the compare viewer is mirrored. By default the Compare viewer is not mirrored.
 	 * @since 3.7
 	 */
 	public boolean isMirrored() {
+		if (!fMirroringEnabled)
+			return false;
 		Object property = getProperty(MIRRORED);
 		return property instanceof Boolean && (Boolean) property;
 	}
 
+	/**
+	 * Returns true if mirroring of the compare viewer is enabled. Mirroring is enabled by default.
+	 *
+	 * @return true if mirroring is enabled
+	 * @see #isMirrored()
+	 * @see #setMirroringEnabled(boolean)
+	 * @since 3.7
+	 */
+	public final boolean isMirroringEnabled() {
+		return fMirroringEnabled;
+	}
+
+	/**
+	 * Enables or disables mirroring of the compare viewer, i.e. swapping of the left and the right panes.
+	 * The mirroring is enabled by default.
+	 * <p>
+	 * Code that always puts the after state on the right should disable mirroring. Code that may put the after state
+	 * on the left should not disable mirroring.
+	 * <p>
+	 * The "after" state is the state of the file after applying some particular change and is determined by user
+	 * actions rather than the file timestamps. For example, when previewing result of a revert operation, the "after"
+	 * state is the state of the file that existed at some point in the past.
+	 * <p>
+	 * When previewing a hypothetical change, the "after" state is the proposed future change and the "before" state
+	 * is the current state of the file. When comparing two existing file states, the "before" and "after" states
+	 * can be determined by chronology or by order in which the users selected the file states.
+	 *
+	 * @param value if true, the mirroring is enabled, otherwise disabled
+	 * @since 3.7
+	 */
+	public final void setMirroringEnabled(boolean value) {
+		fMirroringEnabled = value;
+	}
+
 	private ImageDescriptor getImageDescriptor(int kind) {
 		return fgImages[(kind & 15) + (isMirrored() ? 16 : 0)];
 	}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/ContentMergeViewer.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/ContentMergeViewer.java
index 4f04b3f..b0f67a2 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/ContentMergeViewer.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/ContentMergeViewer.java
@@ -918,22 +918,24 @@
 			tbm.appendToGroup("merge", copyRightToLeftItem); //$NON-NLS-1$
 			fHandlerService.registerAction(copyRightToLeftItem.getAction(), "org.eclipse.compare.copyAllRightToLeft"); //$NON-NLS-1$
 
-			fSwitchLeftAndRight = new Action() {
-				@Override
-				public void run() {
-					IPreferenceStore preferences = getCompareConfiguration().getPreferenceStore();
-					preferences.setValue(ComparePreferencePage.SWAPPED, !getCompareConfiguration().isMirrored());
-					if (preferences instanceof IPersistentPreferenceStore) {
-						try {
-							((IPersistentPreferenceStore) preferences).save();
-						} catch (IOException e) {
-							CompareUIPlugin.log(e);
+			if (getCompareConfiguration().isMirroringEnabled()) {
+				fSwitchLeftAndRight = new Action() {
+					@Override
+					public void run() {
+						IPreferenceStore preferences = getCompareConfiguration().getPreferenceStore();
+						preferences.setValue(ComparePreferencePage.SWAPPED, !getCompareConfiguration().isMirrored());
+						if (preferences instanceof IPersistentPreferenceStore) {
+							try {
+								((IPersistentPreferenceStore) preferences).save();
+							} catch (IOException e) {
+								CompareUIPlugin.log(e);
+							}
 						}
 					}
-				}
-			};
-			Utilities.initAction(fSwitchLeftAndRight, getResourceBundle(), "action.SwitchLeftAndRight."); //$NON-NLS-1$
-			tbm.appendToGroup("modes", fSwitchLeftAndRight); //$NON-NLS-1$
+				};
+				Utilities.initAction(fSwitchLeftAndRight, getResourceBundle(), "action.SwitchLeftAndRight."); //$NON-NLS-1$
+				tbm.appendToGroup("modes", fSwitchLeftAndRight); //$NON-NLS-1$
+			}
 
 			final ChangePropertyAction a= new ChangePropertyAction(fBundle, getCompareConfiguration(), "action.EnableAncestor.", ICompareUIConstants.PROP_ANCESTOR_VISIBLE); //$NON-NLS-1$
 			a.setChecked(fAncestorVisible);