Apply Patch Wizard Changes
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
index 94f1050..3c6d65c 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
@@ -14,6 +14,7 @@
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.internal.DocumentManager;
+import org.eclipse.compare.internal.ICompareUIConstants;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.content.IContentType;
@@ -57,33 +58,33 @@
* Image descriptor for the disabled icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_DTOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.DTOOL_NEXT);
+ public static final ImageDescriptor DESC_DTOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.DTOOL_NEXT);
/**
* Image descriptor for the normal icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_CTOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.CTOOL_NEXT);
+ public static final ImageDescriptor DESC_CTOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.CTOOL_NEXT);
/**
* Image descriptor for the roll-over icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_ETOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.ETOOL_NEXT);
+ public static final ImageDescriptor DESC_ETOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.ETOOL_NEXT);
/**
* Image descriptor for the disabled icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_DTOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.DTOOL_PREV);
+ public static final ImageDescriptor DESC_DTOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.DTOOL_PREV);
/**
* Image descriptor for the normal icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_CTOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.CTOOL_PREV);
+ public static final ImageDescriptor DESC_CTOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.CTOOL_PREV);
/**
* Image descriptor for the roll-over icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_ETOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.ETOOL_PREV);
+ public static final ImageDescriptor DESC_ETOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.ETOOL_PREV);
/**
* Name of the title property of a compare viewer.
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
index 3cdfe35..34a04bf 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -134,14 +134,6 @@
}
}
- public static final String DTOOL_NEXT= "dlcl16/next_nav.gif"; //$NON-NLS-1$
- public static final String ETOOL_NEXT= "elcl16/next_nav.gif"; //$NON-NLS-1$
- public static final String CTOOL_NEXT= ETOOL_NEXT;
-
- public static final String DTOOL_PREV= "dlcl16/prev_nav.gif"; //$NON-NLS-1$
- public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
- public static final String CTOOL_PREV= ETOOL_PREV;
-
/** Status code describing an internal error */
public static final int INTERNAL_ERROR= 1;
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java
new file mode 100644
index 0000000..3e17776
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java
@@ -0,0 +1,21 @@
+package org.eclipse.compare.internal;
+
+
+public interface ICompareUIConstants {
+ public final String PREFIX = CompareUIPlugin.getPluginId() + "."; //$NON-NLS-1$
+
+ public static final String DTOOL_NEXT= "dlcl16/next_nav.gif"; //$NON-NLS-1$
+ public static final String ETOOL_NEXT= "elcl16/next_nav.gif"; //$NON-NLS-1$
+ public static final String CTOOL_NEXT= ETOOL_NEXT;
+
+ public static final String DTOOL_PREV= "dlcl16/prev_nav.gif"; //$NON-NLS-1$
+ public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
+ public static final String CTOOL_PREV= ETOOL_PREV;
+
+ public static final String RETARGET_PROJECT= "eview16/compare_view.gif"; //$NON-NLS-1$
+
+ public static final String IGNORE_WHITESPACE_ENABLED= "etool16/ignorews_edit.gif"; //$NON-NLS-1$
+ public static final String IGNORE_WHITESPACE_DISABLED= "dtool16/ignorews_edit.gif"; //$NON-NLS-1$
+
+ public static final String REVERSE_PATCH_ENABLED = "etool16/reverse_enabled.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java
new file mode 100644
index 0000000..6d91532
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java
@@ -0,0 +1,297 @@
+package org.eclipse.compare.internal.patch;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.internal.INavigatable;
+import org.eclipse.compare.internal.IOpenable;
+import org.eclipse.compare.internal.Utilities;
+import org.eclipse.compare.structuremergeviewer.IDiffContainer;
+import org.eclipse.compare.structuremergeviewer.IDiffElement;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.OpenEvent;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
+
+public class CheckboxDiffTreeViewer extends ContainerCheckedTreeViewer {
+
+ class CheckboxDiffViewerContentProvider implements ITreeContentProvider {
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // empty implementation
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ public void dispose() {
+ inputChanged(CheckboxDiffTreeViewer.this, getInput(), null);
+ }
+
+ public Object getParent(Object element) {
+ if (element instanceof IDiffElement)
+ return ((IDiffElement)element).getParent();
+ return null;
+ }
+
+ public final boolean hasChildren(Object element) {
+ if (element instanceof IDiffContainer)
+ return ((IDiffContainer)element).hasChildren();
+ return false;
+ }
+
+ public final Object[] getChildren(Object element) {
+ if (element instanceof IDiffContainer)
+ return ((IDiffContainer)element).getChildren();
+ return new Object[0];
+ }
+
+ public Object[] getElements(Object element) {
+ return getChildren(element);
+ }
+ }
+
+ /*
+ * Takes care of swapping left and right if fLeftIsLocal
+ * is true.
+ */
+ class CheckboxDiffViewerLabelProvider extends LabelProvider {
+
+ public String getText(Object element) {
+
+ if (element instanceof IDiffElement)
+ return ((IDiffElement)element).getName();
+
+
+ return Utilities.getString(fBundle, "defaultLabel"); //$NON-NLS-1$
+ }
+
+ public Image getImage(Object element) {
+ if (element instanceof IDiffElement) {
+ IDiffElement input= (IDiffElement) element;
+ return input.getImage();
+ }
+ return null;
+ }
+ }
+
+ CompareConfiguration fCompareConfiguration;
+ private ResourceBundle fBundle;
+
+ public CheckboxDiffTreeViewer(Composite parent, CompareConfiguration compareConfiguration) {
+ super(parent);
+ initialize(compareConfiguration);
+ }
+
+ private void initialize(CompareConfiguration compareConfiguration) {
+ Control tree= getControl();
+
+ INavigatable nav= new INavigatable() {
+ public boolean gotoDifference(boolean next) {
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return internalNavigate(next, true);
+ }
+ };
+ tree.setData(INavigatable.NAVIGATOR_PROPERTY, nav);
+
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ IOpenable openable= new IOpenable() {
+ public void openSelected() {
+ internalOpen();
+ }
+ };
+ tree.setData(IOpenable.OPENABLE_PROPERTY, openable);
+
+ fBundle= ResourceBundle.getBundle("org.eclipse.compare.structuremergeviewer.DiffTreeViewerResources"); //$NON-NLS-1$
+
+ setContentProvider(new CheckboxDiffViewerContentProvider());
+ setLabelProvider(new CheckboxDiffViewerLabelProvider());
+
+ addSelectionChangedListener(
+ new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent se) {
+ //updateActions();
+ }
+ }
+ );
+
+ }
+
+/**
+ * Selects the next (or previous) node of the current selection.
+ * If there is no current selection the first (last) node in the tree is selected.
+ * Wraps around at end or beginning.
+ * Clients may override.
+ *
+ * @param next if <code>true</code> the next node is selected, otherwise the previous node
+ * @param fireOpen if <code>true</code> an open event is fired.
+ * @return <code>true</code> if at end (or beginning)
+ */
+private boolean internalNavigate(boolean next, boolean fireOpen) {
+
+ Control c= getControl();
+ if (!(c instanceof Tree))
+ return false;
+
+ Tree tree= (Tree) c;
+ TreeItem item= null;
+ TreeItem children[]= tree.getSelection();
+ if (children != null && children.length > 0)
+ item= children[0];
+ if (item == null) {
+ children= tree.getItems();
+ if (children != null && children.length > 0) {
+ item= children[0];
+ if (item != null && item.getItemCount() <= 0) {
+ internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return false;
+ }
+ }
+ }
+
+ while (true) {
+ item= findNextPrev(item, next);
+ if (item == null)
+ break;
+ if (item.getItemCount() <= 0)
+ break;
+ }
+
+ if (item != null) {
+ internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return false;
+ }
+ return true;
+}
+
+private TreeItem findNextPrev(TreeItem item, boolean next) {
+
+ if (item == null)
+ return null;
+
+ TreeItem children[]= null;
+
+ if (!next) {
+
+ TreeItem parent= item.getParentItem();
+ if (parent != null)
+ children= parent.getItems();
+ else
+ children= item.getParent().getItems();
+
+ if (children != null && children.length > 0) {
+ // goto previous child
+ int index= 0;
+ for (; index < children.length; index++)
+ if (children[index] == item)
+ break;
+
+ if (index > 0) {
+
+ item= children[index-1];
+
+ while (true) {
+ createChildren(item);
+ int n= item.getItemCount();
+ if (n <= 0)
+ break;
+
+ item.setExpanded(true);
+ item= item.getItems()[n-1];
+ }
+
+ // previous
+ return item;
+ }
+ }
+
+ // go up
+ item= parent;
+
+ } else {
+ item.setExpanded(true);
+ createChildren(item);
+
+ if (item.getItemCount() > 0) {
+ // has children: go down
+ children= item.getItems();
+ return children[0];
+ }
+
+ while (item != null) {
+ children= null;
+ TreeItem parent= item.getParentItem();
+ if (parent != null)
+ children= parent.getItems();
+ else
+ children= item.getParent().getItems();
+
+ if (children != null && children.length > 0) {
+ // goto next child
+ int index= 0;
+ for (; index < children.length; index++)
+ if (children[index] == item)
+ break;
+
+ if (index < children.length-1) {
+ // next
+ return children[index+1];
+ }
+ }
+
+ // go up
+ item= parent;
+ }
+ }
+
+ return item;
+}
+
+private void internalSetSelection(TreeItem ti, boolean fireOpen) {
+ if (ti != null) {
+ Object data= ti.getData();
+ if (data != null) {
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ ISelection selection= new StructuredSelection(data);
+ setSelection(selection, true);
+ ISelection currentSelection= getSelection();
+ if (fireOpen && currentSelection != null && selection.equals(currentSelection)) {
+ fireOpen(new OpenEvent(this, selection));
+ }
+ }
+ }
+}
+
+/*
+ * Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ */
+private void internalOpen() {
+ ISelection selection= getSelection();
+ if (selection != null && !selection.isEmpty()) {
+ fireOpen(new OpenEvent(this, selection));
+ }
+}
+
+/**
+ * Creates a new DecoratingLabelProvider (using the passed in ILabelDecorator) and sets
+ * it as the label provider for the tree
+ * @param decorator
+ */
+public void setLabelDecorator(ILabelDecorator decorator) {
+ setLabelProvider(new DecoratingLabelProvider(new CheckboxDiffViewerLabelProvider(), decorator));
+}
+
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
index 6da4e19..b8545b0 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
@@ -14,14 +14,17 @@
import java.util.Iterator;
import java.util.List;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.ITypedElement;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.model.IWorkbenchAdapter;
-public class DiffProject implements IWorkbenchAdapter, IAdaptable {
+public class DiffProject implements IWorkbenchAdapter, IAdaptable, ITypedElement {
List fDiffs= new ArrayList();
IProject fProject;
@@ -48,7 +51,7 @@
return this.fProject;
}
- String getName() {
+ public String getName() {
return fProject.getName();
}
@@ -125,4 +128,12 @@
public String getOriginalProjectName() {
return fOriginalProjectName;
}
+
+ public Image getImage() {
+ return CompareUI.getImage(fProject);
+ }
+
+ public String getType() {
+ return ITypedElement.FOLDER_TYPE;
+ }
}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
index 75b3c6b..d60d1d3 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
@@ -26,6 +26,9 @@
public static String PatchAction_AlwaysSaveQuestion;
public static String PatchAction_SaveAllQuestion;
public static String PatchAction_SaveAllDescription;
+ public static String PatcherCompareEditorInput_AfterPatch;
+ public static String PatcherCompareEditorInput_LocalCopy;
+ public static String PatcherCompareEditorInput_PatchContents;
public static String PatchWizard_title;
public static String PatchWizard_unexpectedException_message;
public static String InputPatchPage_title;
@@ -87,4 +90,8 @@
public static String PreviewPatchPage_SelectProject;
public static String PreviewPatchPage_Target;
public static String PreviewPatchLabelDecorator_ProjectDoesNotExist;
+ public static String PreviewPatchPage2_IgnoreWSAction;
+ public static String PreviewPatchPage2_IgnoreWSTooltip;
+ public static String PreviewPatchPage2_RetargetAction;
+ public static String PreviewPatchPage2_RetargetTooltip;
}
\ No newline at end of file
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
index a44d187..a482462 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
@@ -16,6 +16,8 @@
PatchAction_ExceptionTitle=Saving Resources
PatchAction_Exception=Unexpected exception. See log for details
PatchAction_SavingDirtyEditorsTask=Saving dirty editors
+PatcherCompareEditorInput_LocalCopy=Local Copy
+PatcherCompareEditorInput_AfterPatch=After Patch
PatchAction_AlwaysSaveQuestion=&Always save all modified resources automatically prior to patching
PatchAction_SaveAllQuestion=Save all modified resources
PatchAction_SaveAllDescription=All modified resources have to be saved before this operation.\nClick 'OK' to confirm or click 'Cancel'.
@@ -25,6 +27,7 @@
#
PatchWizard_title=Apply Patch
PatchWizard_unexpectedException_message= Unexpected exception while applying the patch. See log for a detailed error description.
+PatcherCompareEditorInput_PatchContents=Patch Contents
#
# InputPatchPage
@@ -73,10 +76,14 @@
PreviewPatchPage_IgnoreSegments_text=&Ignore leading path name segments:
PreviewPatchPage_ReversePatch_text=&Reverse patch
PreviewPatchPage_FuzzFactor_text=&Maximum fuzz factor:
+PreviewPatchPage2_RetargetAction=Retarget
+PreviewPatchPage2_IgnoreWSAction=Ignore WhiteSpace
PreviewPatchPage_FuzzFactor_tooltip=Allow Context to Shift This Number of Lines from the Original Location
PreviewPatchPage_IgnoreWhitespace_text=Ignore &white space
PreviewPatchPage_NoName_text=no name
PreviewPatchPage_FileExists_error=(file already exists)
+PreviewPatchPage2_RetargetTooltip=Retarget Project
+PreviewPatchPage2_IgnoreWSTooltip=Ignore WhiteSpace
PreviewPatchPage_FileDoesNotExist_error=(file does not exist)
PreviewPatchPage_NoMatch_error=(no match)
PreviewPatchPage_MatchProjects=Retarget &Patch...
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
index 9ae3aa3..740ce77 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
@@ -79,7 +79,7 @@
addPage(fPatchWizardPage= new InputPatchPage(this));
addPage(new PatchTargetPage(this));
- addPage(new PreviewPatchPage(this));
+ addPage(new PreviewPatchPage2(this));
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java
new file mode 100644
index 0000000..395c661
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java
@@ -0,0 +1,593 @@
+package org.eclipse.compare.internal.patch;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.CompareEditorInput;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.CompareViewerPane;
+import org.eclipse.compare.IStreamContentAccessor;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.ResourceNode;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.DiffImage;
+import org.eclipse.compare.internal.Utilities;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.IDiffContainer;
+import org.eclipse.compare.structuremergeviewer.IDiffElement;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+
+public class PatcherCompareEditorInput extends CompareEditorInput {
+
+ class PatchedFileNode implements ITypedElement, IStreamContentAccessor {
+
+ byte[] bytes;
+ String type;
+ String name;
+
+
+ public PatchedFileNode(byte[] bytes, String type, String name){
+ this.bytes = bytes;
+ this.type = type;
+ this.name = name;
+ }
+
+ public Image getImage() {
+ return null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public InputStream getContents() throws CoreException {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ }
+
+ class MyDiffNode extends DiffNode {
+
+ //Diff associated with this MyDiffNode
+ private Diff diff = null;
+ //Hunk associated with this MyDiffNode
+ private Hunk hunk = null;
+
+
+ public MyDiffNode(IDiffContainer parent, int kind, ITypedElement ancestor, ITypedElement left, ITypedElement right, Diff diff) {
+ super(parent, kind, ancestor, left, right);
+ this.diff = diff;
+ }
+
+ public MyDiffNode(IDiffContainer parent, int kind, ITypedElement ancestor, ITypedElement left, ITypedElement right, Hunk hunk) {
+ super(parent, kind, ancestor, left, right);
+ this.hunk = hunk;
+ }
+
+ public String getName() {
+ if (diff != null)
+ return diff.getLabel(diff);
+
+ if (hunk != null)
+ return hunk.getLabel(hunk);
+
+ return ""; //$NON-NLS-1$
+ }
+
+ Diff getDiff() {
+ return diff;
+ }
+
+
+ Hunk getHunk() {
+ return hunk;
+ }
+
+ }
+
+ class PatcherCompareEditorDecorator implements ILabelDecorator {
+
+ /** Maps strings to images */
+ private Map fImages= new Hashtable(10);
+ private List fDisposeOnShutdownImages= new ArrayList();
+
+ ImageDescriptor errId= CompareUIPlugin.getImageDescriptor("ovr16/error_ov.gif"); //$NON-NLS-1$
+
+ static final String error = "error"; //$NON-NLS-1$
+ static final String add = "add"; //$NON-NLS-1$
+ static final String delete = "del"; //$NON-NLS-1$
+
+ public Image decorateImage(Image image, Object element) {
+ if (element instanceof MyDiffNode){
+ MyDiffNode myDiffNode = (MyDiffNode) element;
+ Diff diff = myDiffNode.getDiff();
+ Hunk hunk = myDiffNode.getHunk();
+ if (diff != null){
+ switch (diff.getType()){
+ case Differencer.ADDITION:
+ return getImageFor(add + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$
+
+ case Differencer.DELETION:
+ return getImageFor(delete + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$
+
+ default:
+ return getImageFor(diff.fMatches ? "" : error, image, diff.fMatches); //$NON-NLS-1$
+ }
+ } else if (hunk != null){
+ return getImageFor((hunk.fMatches ? "" : error),image, hunk.fMatches); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ private Image getImageFor(String id, Image image, boolean hasMatches) {
+ Image cached_image = (Image) fImages.get(id);
+ if (cached_image == null){
+ DiffImage diffImage = new DiffImage(image, hasMatches ? null : errId, 16, false);
+ cached_image = diffImage.createImage();
+ fImages.put(id, cached_image);
+ fDisposeOnShutdownImages.add(cached_image);
+ }
+ return cached_image;
+ }
+
+ public String decorateText(String text, Object element) {
+ if (element instanceof DiffNode){
+ ITypedElement typedElement = ((DiffNode) element).getLeft();
+ if (typedElement != null && typedElement instanceof DiffProject){
+ DiffProject project = (DiffProject) typedElement;
+ if (!project.getName().equals(project.getOriginalProjectName()))
+ return NLS.bind(PatchMessages.Diff_2Args,
+ new String[]{project.getOriginalProjectName(),
+ NLS.bind(PatchMessages.PreviewPatchPage_Target, new String[]{project.getName()})});
+ }
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ if (fDisposeOnShutdownImages != null) {
+ Iterator i= fDisposeOnShutdownImages.iterator();
+ while (i.hasNext()) {
+ Image img= (Image) i.next();
+ if (!img.isDisposed())
+ img.dispose();
+ }
+ fImages= null;
+ }
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ //don't need listener
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ //don't need listener
+ }
+
+ }
+ private DiffNode root;
+ private List failedHunks;
+
+ private CheckboxDiffTreeViewer viewer;
+ private final static int LEFT = 0;
+ private final static int RIGHT = 1;
+ private PreviewPatchPage2 previewPatchPage;
+
+ private HashMap nodesToDiffs;
+
+ public PatcherCompareEditorInput() {
+ super(new CompareConfiguration());
+ root = new DiffNode(Differencer.NO_CHANGE) {
+ public boolean hasChildren() {
+ return true;
+ }
+ };
+ }
+
+ protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ initLabels();
+ return root;
+ }
+
+ private void initLabels() {
+ CompareConfiguration cc = getCompareConfiguration();
+ cc.setLeftEditable(false);
+ cc.setRightEditable(false);
+ String leftLabel = PatchMessages.PatcherCompareEditorInput_LocalCopy;
+ cc.setLeftLabel(leftLabel);
+ String rightLabel = PatchMessages.PatcherCompareEditorInput_AfterPatch;
+ cc.setRightLabel(rightLabel);
+ }
+
+ public void updateInput(WorkspacePatcher patcher) {
+ buildTree(patcher);
+ updateTree(patcher);
+ }
+
+ private void updateTree(WorkspacePatcher patcher){
+ if (viewer == null)
+ return;
+
+ int strip= previewPatchPage.getStripPrefixSegments();
+ //Get the elements from the content provider
+ ITreeContentProvider contentProvider= (ITreeContentProvider) viewer.getContentProvider();
+ Object[] projects= contentProvider.getElements(root);
+ ArrayList hunksToCheck= new ArrayList();
+ ArrayList nodesToCheck=new ArrayList();
+ //Iterate through projects and call reset on each project
+ for (int j= 0; j<projects.length; j++) {
+ if (!(projects[j] instanceof MyDiffNode)) {
+ DiffNode projectNode = (DiffNode) projects[j];
+ ITypedElement project = projectNode.getLeft();
+ Assert.isNotNull(project);
+ Assert.isTrue(project instanceof DiffProject);
+ hunksToCheck.addAll(((DiffProject)project).reset(patcher, strip, previewPatchPage.getFuzzFactor()));
+ IDiffElement[] diffNodes = projectNode.getChildren();
+
+ Iterator iter = hunksToCheck.iterator();
+ while (iter.hasNext()){
+ Hunk hunkToMatch = (Hunk) iter.next();
+ Object matchingHunkNode = nodesToDiffs.get(hunkToMatch);
+ if (matchingHunkNode != null)
+ nodesToCheck.add(matchingHunkNode);
+
+ }
+ for (int i = 0; i < diffNodes.length; i++) {
+ viewer.update(diffNodes[i], null);
+ IDiffElement[] hunkNodes =((MyDiffNode) diffNodes[i]).getChildren();
+ for (int k = 0; k < hunkNodes.length; k++) {
+ viewer.update(hunkNodes[k],null);
+ }
+ }
+
+ } else {
+ if (projects[j] instanceof MyDiffNode) {
+ Diff diff= ((MyDiffNode) projects[j]).getDiff();
+ hunksToCheck.addAll(diff.reset(patcher, strip, previewPatchPage.getFuzzFactor()));
+ viewer.update(diff, null);
+ }
+ }
+ }
+ viewer.refresh();
+ viewer.setCheckedElements(nodesToCheck.toArray());
+
+ updateEnablements();
+ }
+
+ private void buildTree(WorkspacePatcher patcher) {
+
+ if (patcher.isWorkspacePatch()) {
+
+ if (root.hasChildren()) {
+ IDiffElement[] children = root.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ root.remove(children[i]);
+ }
+ }
+
+ nodesToDiffs = new HashMap();
+
+ DiffProject[] projects = patcher.getDiffProjects();
+ try {
+ for (int i = 0; i < projects.length; i++) {
+ DiffNode projectNode = new DiffNode(root, Differencer.CHANGE, null, projects[i], null);
+ Iterator iter = projects[i].fDiffs.iterator();
+ while (iter.hasNext()) {
+ Object obj = iter.next();
+ if (obj instanceof Diff) {
+ Diff diff = (Diff) obj;
+ IFile tempFile = projects[i].getFile(new Path(diff.getLabel(diff)));
+ byte[] bytes = quickPatch(tempFile, patcher, diff);
+ int differencer = Differencer.CHANGE;
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ }
+ if (!tempFile.exists())
+ tempFile = null;
+
+ ResourceNode tempNode = new ResourceNode(tempFile);
+ PatchedFileNode patchedNode = new PatchedFileNode(bytes, tempNode.getType(), tempFile.getProjectRelativePath().toString());
+ MyDiffNode allFile = new MyDiffNode(projectNode, differencer, tempNode, tempNode, patchedNode, diff);
+ //Add individual hunks to each Diff node
+ Hunk[] hunks = diff.getHunks();
+ for (int j = 0; j < hunks.length; j++) {
+ Diff tempDiff = new Diff(diff.fOldPath, diff.fOldDate, diff.fNewPath, diff.fNewDate);
+ tempDiff.add(hunks[j]);
+ bytes = quickPatch(tempFile, patcher, tempDiff);
+ differencer = Differencer.NO_CHANGE;
+ switch (hunks[j].getHunkType()) {
+ case Hunk.ADDED :
+ differencer += Differencer.ADDITION;
+ break;
+
+ case Hunk.CHANGED :
+ differencer += Differencer.CHANGE;
+ break;
+
+ case Hunk.DELETED :
+ differencer += Differencer.DELETION;
+ break;
+ }
+
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ String[] hunkContents = createInput(hunks[j]);
+ PatchedFileNode ancestor = new PatchedFileNode(hunkContents[LEFT].getBytes(), hunks[j].fParent.getPath().getFileExtension(), hunks[j].getDescription());
+ patchedNode = new PatchedFileNode(hunkContents[RIGHT].getBytes(), tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, ancestor, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ } else {
+ patchedNode = new PatchedFileNode(bytes, tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, tempNode, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ }
+ }
+
+ }
+
+ }
+
+ }
+
+ } catch (CoreException e) {
+ //ignore
+ }
+ viewer.setInput(root);
+ viewer.refresh();
+ } else {
+ if (root.hasChildren()) {
+ IDiffElement[] children = root.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ root.remove(children[i]);
+ }
+ }
+
+ nodesToDiffs = new HashMap();
+
+ Diff[] diffs = patcher.getDiffs();
+ try {
+ for (int i = 0; i < diffs.length; i++) {
+ Diff diff = diffs[i];
+ IFile tempFile = patcher.existsInTarget(new Path(diff.getLabel(diff)));
+
+ byte[] bytes = quickPatch(tempFile, patcher, diff);
+ int differencer = Differencer.CHANGE;
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ }
+ ResourceNode tempNode = new ResourceNode(tempFile);
+ PatchedFileNode patchedNode = new PatchedFileNode(bytes, tempNode.getType(), tempFile.getProjectRelativePath().toString());
+ MyDiffNode allFile = new MyDiffNode(root, differencer, tempNode, tempNode, patchedNode, diff);
+ //Add individual hunks to each Diff node
+ Hunk[] hunks = diff.getHunks();
+ for (int j = 0; j < hunks.length; j++) {
+ Diff tempDiff = new Diff(diff.fOldPath, diff.fOldDate, diff.fNewPath, diff.fNewDate);
+ tempDiff.add(hunks[j]);
+ bytes = quickPatch(tempFile, patcher, tempDiff);
+ differencer = Differencer.NO_CHANGE;
+ switch (hunks[j].getHunkType()) {
+ case Hunk.ADDED :
+ differencer += Differencer.ADDITION;
+ break;
+
+ case Hunk.CHANGED :
+ differencer += Differencer.CHANGE;
+ break;
+
+ case Hunk.DELETED :
+ differencer += Differencer.DELETION;
+ break;
+ }
+
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ String[] hunkContents = createInput(hunks[j]);
+ PatchedFileNode ancestor = new PatchedFileNode(hunkContents[LEFT].getBytes(), hunks[j].fParent.getPath().getFileExtension(), hunks[j].getDescription());
+ patchedNode = new PatchedFileNode(hunkContents[RIGHT].getBytes(), tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, ancestor, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ } else {
+ patchedNode = new PatchedFileNode(bytes, tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, tempNode, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ }
+ }
+
+ }
+ } catch (CoreException ex) {//ignore
+ }
+
+ }
+
+ }
+
+ private byte[] quickPatch(IFile tempFile, WorkspacePatcher patcher, Diff diff) throws CoreException {
+
+ failedHunks = new ArrayList();
+ List result = patcher.apply(diff, tempFile, diff.getType() == Differencer.ADDITION, failedHunks);
+ String patchedResults = patcher.createString(result);
+ byte[] bytes;
+ try {
+ bytes = patchedResults.getBytes(Utilities.getCharset(tempFile));
+ } catch (UnsupportedEncodingException e) {
+ // uses default encoding
+ bytes = patchedResults.getBytes();
+ }
+
+ return bytes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.CompareEditorInput#createDiffViewer(org.eclipse.swt.widgets.Composite)
+ */
+ public Viewer createDiffViewer(Composite parent) {
+ viewer = new CheckboxDiffTreeViewer(parent, getCompareConfiguration());
+ viewer.setLabelDecorator(new PatcherCompareEditorDecorator());
+ viewer.getTree().setData(CompareUI.COMPARE_VIEWER_TITLE, PatchMessages.PatcherCompareEditorInput_PatchContents);
+ viewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ viewer.setSubtreeChecked(event.getElement(),event.getChecked());
+ updateEnablements();
+ }
+ });
+ viewer.setInput(this);
+ return viewer;
+ }
+
+ private String[] createInput(Hunk hunk) {
+
+ String[] lines= hunk.fLines;
+ StringBuffer left= new StringBuffer();
+ StringBuffer right= new StringBuffer();
+
+ for (int i= 0; i<lines.length; i++) {
+ String line= lines[i];
+ String rest= line.substring(1);
+ switch (line.charAt(0)) {
+ case ' ' :
+ left.append(rest);
+ right.append(rest);
+ break;
+ case '-' :
+ left.append(rest);
+ break;
+ case '+' :
+ right.append(rest);
+ break;
+ }
+ }
+
+
+ return new String[]{left.toString(),right.toString()};
+ }
+
+ public void contributeDiffViewerToolbarItems(Action[] actions, boolean workspacePatch){
+ ToolBarManager tbm= CompareViewerPane.getToolBarManager(viewer.getControl().getParent());
+ if (tbm != null) {
+ tbm.removeAll();
+
+ tbm.add(new Separator("contributed")); //$NON-NLS-1$
+
+ for (int i = 0; i < actions.length; i++) {
+ //If this is a workspace patch, make sure all actions are enabled
+ if (workspacePatch)
+ actions[i].setEnabled(true);
+
+ tbm.appendToGroup("contributed", actions[i]); //$NON-NLS-1$
+ }
+
+ tbm.update(true);
+ }
+ }
+
+ public CheckboxDiffTreeViewer getViewer() {
+ return viewer;
+ }
+
+ /**
+ * Makes sure that at least one hunk is checked off in the tree before
+ * allowing the patch to be applied.
+ */
+ /* private */void updateEnablements() {
+ boolean atLeastOneIsEnabled= false;
+ if (viewer!=null) {
+ ITreeContentProvider contentProvider= (ITreeContentProvider) viewer.getContentProvider();
+ Object[] projects= contentProvider.getElements(root);
+ //Iterate through projects
+ for (int j= 0; j<projects.length; j++) {
+ if (!(projects[j] instanceof MyDiffNode)) {
+ DiffNode project = (DiffNode) projects[j];
+ //Iterate through project diffs
+ Object[] diffs= project.getChildren();
+ for (int i= 0; i<diffs.length; i++) {
+ MyDiffNode diff= (MyDiffNode) diffs[i];
+ atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, diff);
+ }
+ } else if (projects[j] instanceof MyDiffNode) {
+ atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, (MyDiffNode) projects[j]);
+ }
+ }
+ }
+
+ previewPatchPage.setPageComplete(atLeastOneIsEnabled);
+ }
+
+ private boolean updateEnablement(boolean oneIsEnabled, MyDiffNode diffNode) {
+ boolean checked= viewer.getChecked(diffNode);
+ Diff diff = diffNode.getDiff();
+ Assert.isNotNull(diff);
+ diff.setEnabled(checked);
+ if (checked) {
+ Object[] hunkItems= diffNode.getChildren();
+ for (int h= 0; h<hunkItems.length; h++) {
+ MyDiffNode hunkNode = (MyDiffNode) hunkItems[h];
+ checked= viewer.getChecked(hunkNode);
+ Hunk hunk= hunkNode.getHunk();
+ Assert.isNotNull(hunk);
+ hunk.setEnabled(checked);
+ if (checked) {
+ //For workspace patch: before setting enabled flag, make sure that the project
+ //that contains this hunk actually exists in the workspace. This is to guard against the
+ //case of having a new file in a patch that is being applied to a project that
+ //doesn't currently exist.
+ boolean projectExists= true;
+ DiffProject project= (DiffProject)diff.getParent(null);
+ if (project!= null){
+ projectExists=project.getProject().exists();
+ }
+ if (projectExists)
+ oneIsEnabled= true;
+ }
+
+ }
+ }
+
+ return oneIsEnabled;
+ }
+
+
+ /**
+ * Stores a pointer back to the PreviewPatchPage
+ * @param page
+ */
+ public void setPreviewPatchPage(PreviewPatchPage2 page) {
+ previewPatchPage = page;
+ }
+}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java
new file mode 100644
index 0000000..c8bc66a
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java
@@ -0,0 +1,506 @@
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.ICompareUIConstants;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.BaseWorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+
+import com.ibm.icu.text.MessageFormat;
+
+
+public class PreviewPatchPage2 extends WizardPage {
+
+ protected final static String PREVIEWPATCHPAGE_NAME= "PreviewPatchPage"; //$NON-NLS-1$
+ private PatchWizard fPatchWizard;
+ private PatcherCompareEditorInput patcherCompareEditorInput = new PatcherCompareEditorInput();
+
+ private Combo fStripPrefixSegments;
+ private Text fFuzzField;
+
+ private Action fRetargetSelection;
+ private Action fIgnoreWhiteSpace;
+ private Action fReversePatch;
+
+ protected boolean pageRecalculate= true;
+
+ class RetargetPatchDialog extends Dialog {
+
+ protected TreeViewer rpTreeViewer;
+ protected DiffNode rpSelectedNode;
+ protected DiffProject rpSelectedProject;
+ protected IProject rpTargetProject;
+
+ public RetargetPatchDialog(Shell shell, ISelection selection) {
+ super(shell);
+ setShellStyle(getShellStyle()|SWT.RESIZE);
+ if (selection instanceof IStructuredSelection) {
+ rpSelectedNode= (DiffNode) ((IStructuredSelection) selection).getFirstElement();
+ }
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite= (Composite) super.createDialogArea(parent);
+
+ initializeDialogUnits(parent);
+
+ getShell().setText(PatchMessages.PreviewPatchPage_RetargetPatch);
+
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 1;
+ layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ composite.setLayout(layout);
+ final GridData data= new GridData(SWT.FILL, SWT.FILL, true, true);
+ composite.setLayoutData(data);
+
+ //add controls to composite as necessary
+ Label label= new Label(composite, SWT.LEFT|SWT.WRAP);
+ label.setText(NLS.bind(PatchMessages.PreviewPatchPage_SelectProject, rpSelectedNode.getName()));
+ final GridData data2= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
+ label.setLayoutData(data2);
+
+ rpTreeViewer= new TreeViewer(composite, SWT.BORDER);
+ GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.widthHint= 0;
+ gd.heightHint= 0;
+ rpTreeViewer.getTree().setLayoutData(gd);
+
+ rpTreeViewer.setContentProvider(new RetargetPatchContentProvider());
+ rpTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
+ rpTreeViewer.setSorter(new ResourceSorter(ResourceSorter.NAME));
+ rpTreeViewer.setInput(ResourcesPlugin.getWorkspace());
+ ITypedElement tempProject = rpSelectedNode.getLeft();
+ if (tempProject instanceof DiffProject){
+ rpSelectedProject = (DiffProject)tempProject;
+ rpTreeViewer.setSelection(new StructuredSelection(rpSelectedProject.getProject()));
+ }
+
+ setupListeners();
+
+ Dialog.applyDialogFont(composite);
+
+ return parent;
+ }
+
+ protected void okPressed() {
+ rpSelectedProject.setProject(rpTargetProject);
+ super.okPressed();
+ }
+
+ void setupListeners() {
+ rpTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection s= (IStructuredSelection) event.getSelection();
+ Object obj= s.getFirstElement();
+ if (obj instanceof IProject)
+ rpTargetProject= (IProject) obj;
+ }
+ });
+
+ rpTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ ISelection s= event.getSelection();
+ if (s instanceof IStructuredSelection) {
+ Object item= ((IStructuredSelection) s).getFirstElement();
+ if (rpTreeViewer.getExpandedState(item))
+ rpTreeViewer.collapseToLevel(item, 1);
+ else
+ rpTreeViewer.expandToLevel(item, 1);
+ }
+ }
+ });
+
+ }
+
+ protected Point getInitialSize() {
+ final Point size= super.getInitialSize();
+ size.x= convertWidthInCharsToPixels(75);
+ size.y+= convertHeightInCharsToPixels(20);
+ return size;
+ }
+ }
+
+ class RetargetPatchContentProvider extends BaseWorkbenchContentProvider {
+ //Never show closed projects
+ boolean showClosedProjects= false;
+
+ public Object[] getChildren(Object element) {
+ if (element instanceof IWorkspace) {
+ // check if closed projects should be shown
+ IProject[] allProjects= ((IWorkspace) element).getRoot().getProjects();
+ if (showClosedProjects)
+ return allProjects;
+
+ ArrayList accessibleProjects= new ArrayList();
+ for (int i= 0; i<allProjects.length; i++) {
+ if (allProjects[i].isOpen()) {
+ accessibleProjects.add(allProjects[i]);
+ }
+ }
+ return accessibleProjects.toArray();
+ }
+
+ if (element instanceof IProject) {
+ return new Object[0];
+ }
+ return super.getChildren(element);
+ }
+ }
+
+ public PreviewPatchPage2(PatchWizard pw) {
+ super(PREVIEWPATCHPAGE_NAME, PatchMessages.PreviewPatchPage_title, null);
+
+ fPatchWizard= pw;
+
+ }
+
+ public void createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ initializeDialogUnits(parent);
+
+ buildPatchOptionsGroup(composite);
+
+ try {
+ patcherCompareEditorInput.run(null);
+ } catch (InterruptedException e) {//ignore
+ } catch (InvocationTargetException e) {//ignore
+ }
+
+
+ Control c = patcherCompareEditorInput.createContents(composite);
+ patcherCompareEditorInput.contributeDiffViewerToolbarItems(getContributedActions(), fPatchWizard.getPatcher().isWorkspacePatch());
+ patcherCompareEditorInput.setPreviewPatchPage(this);
+ c.setLayoutData(new GridData(GridData.FILL_BOTH));
+ setControl(composite);
+
+ }
+
+ private Action[] getContributedActions() {
+ fRetargetSelection= new Action(PatchMessages.PreviewPatchPage2_RetargetAction, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.RETARGET_PROJECT)) {
+ public void run() {
+ Shell shell = getShell();
+ ISelection selection = patcherCompareEditorInput.getViewer().getSelection();
+ final RetargetPatchDialog dialog= new RetargetPatchDialog(shell, selection);
+ dialog.open();
+ patcherCompareEditorInput.updateInput(fPatchWizard.getPatcher());
+ }
+ };
+ fRetargetSelection.setToolTipText(PatchMessages.PreviewPatchPage2_RetargetTooltip);
+ fRetargetSelection.setEnabled(false);
+
+ fIgnoreWhiteSpace = new Action(PatchMessages.PreviewPatchPage2_IgnoreWSAction, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IGNORE_WHITESPACE_ENABLED)){
+ public void run(){
+ fIgnoreWhiteSpace.setChecked(isChecked());
+ if (fPatchWizard.getPatcher().setIgnoreWhitespace(fIgnoreWhiteSpace.isChecked())){
+ fillTree();
+ }
+ }
+ };
+ fIgnoreWhiteSpace.setChecked(false);
+ fIgnoreWhiteSpace.setToolTipText(PatchMessages.PreviewPatchPage2_IgnoreWSTooltip);
+ fIgnoreWhiteSpace.setDisabledImageDescriptor(CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IGNORE_WHITESPACE_DISABLED));
+
+ fReversePatch = new Action(PatchMessages.PreviewPatchPage_ReversePatch_text, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.REVERSE_PATCH_ENABLED)){
+ public void run(){
+ fReversePatch.setChecked(isChecked());
+ if (fPatchWizard.getPatcher().setReversed(isChecked())){
+ fillTree();
+ }
+ }
+ };
+ fReversePatch.setChecked(false);
+ fReversePatch.setToolTipText(PatchMessages.PreviewPatchPage_ReversePatch_text);
+
+ return new Action[]{fIgnoreWhiteSpace, fRetargetSelection, fReversePatch};
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ //Need to handle input and rebuild tree only when becoming visible
+ if(visible){
+ fillTree();
+ }
+ }
+
+ private void fillTree(){
+ //Update prefix count - go through all of the diffs and find the smallest
+ //path segment contained in all diffs.
+ int length= 99;
+ if (fStripPrefixSegments!=null&& pageRecalculate) {
+ length= fPatchWizard.getPatcher().calculatePrefixSegmentCount();
+ if (length!=99) {
+ for (int k= 1; k<length; k++)
+ fStripPrefixSegments.add(Integer.toString(k));
+ pageRecalculate= false;
+ }
+ }
+
+ patcherCompareEditorInput.updateInput(fPatchWizard.getPatcher());
+
+ }
+ /*
+ * Create the group for setting various patch options
+ */
+ private void buildPatchOptionsGroup(Composite parent) {
+
+ GridLayout gl;
+ GridData gd;
+ Label l;
+
+ final WorkspacePatcher patcher= fPatchWizard.getPatcher();
+
+ Group group= new Group(parent, SWT.NONE);
+ group.setText(PatchMessages.PreviewPatchPage_PatchOptions_title);
+ gl= new GridLayout(); gl.numColumns= 4;
+ group.setLayout(gl);
+ group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL|GridData.GRAB_HORIZONTAL));
+
+ // 1st row
+
+ Composite pair= new Composite(group, SWT.NONE);
+ gl= new GridLayout(); gl.numColumns= 2; gl.marginHeight= gl.marginWidth= 0;
+ pair.setLayout(gl);
+ gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ pair.setLayoutData(gd);
+
+ l= new Label(pair, SWT.NONE);
+ l.setText(PatchMessages.PreviewPatchPage_IgnoreSegments_text);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL);
+ l.setLayoutData(gd);
+
+ fStripPrefixSegments= new Combo(pair, SWT.DROP_DOWN|SWT.READ_ONLY|SWT.SIMPLE);
+ int prefixCnt= patcher.getStripPrefixSegments();
+ String prefix= Integer.toString(prefixCnt);
+ fStripPrefixSegments.add(prefix);
+ fStripPrefixSegments.setText(prefix);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_END);
+ fStripPrefixSegments.setLayoutData(gd);
+
+ addSpacer(group);
+
+ // 2nd row
+ pair= new Composite(group, SWT.NONE);
+ gl= new GridLayout(); gl.numColumns= 3; gl.marginHeight= gl.marginWidth= 0;
+ pair.setLayout(gl);
+ gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ pair.setLayoutData(gd);
+
+ l= new Label(pair, SWT.NONE);
+ l.setText(PatchMessages.PreviewPatchPage_FuzzFactor_text);
+ l.setToolTipText(PatchMessages.PreviewPatchPage_FuzzFactor_tooltip);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL);
+ l.setLayoutData(gd);
+
+ fFuzzField= new Text(pair, SWT.BORDER);
+ fFuzzField.setText("2"); //$NON-NLS-1$
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END); gd.widthHint= 30;
+ fFuzzField.setLayoutData(gd);
+
+ Button b= new Button(pair, SWT.PUSH);
+ b.setText(PatchMessages.PreviewPatchPage_GuessFuzz_text);
+ b.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ int fuzz= guessFuzzFactor(patcher);
+ if (fuzz>=0)
+ fFuzzField.setText(Integer.toString(fuzz));
+ }
+ }
+ );
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER);
+ int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+ Point minSize = b.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+ gd.widthHint = Math.max(widthHint, minSize.x);
+ b.setLayoutData(gd);
+
+ // register listeners
+
+ if (fStripPrefixSegments!=null)
+ fStripPrefixSegments.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
+ patcherCompareEditorInput.updateInput(patcher);
+ }
+ }
+ );
+
+
+ fFuzzField.addModifyListener(
+ new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (patcher.setFuzz(getFuzzFactor()))
+ patcherCompareEditorInput.updateInput(patcher);
+ }
+ });
+ }
+
+ private void addSpacer(Composite parent) {
+ Label label= new Label(parent, SWT.NONE);
+ GridData gd= new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint= 10;
+ label.setLayoutData(gd);
+ }
+
+ public int getFuzzFactor() {
+ int fuzzFactor= 0;
+ if (fFuzzField!=null) {
+ String s= fFuzzField.getText();
+ try {
+ fuzzFactor= Integer.parseInt(s);
+ } catch (NumberFormatException ex) {
+ // silently ignored
+ }
+ }
+ return fuzzFactor;
+ }
+
+ public int getStripPrefixSegments() {
+ int stripPrefixSegments= 0;
+ if (fStripPrefixSegments!=null) {
+ String s= fStripPrefixSegments.getText();
+ try {
+ stripPrefixSegments= Integer.parseInt(s);
+ } catch (NumberFormatException ex) {
+ // silently ignored
+ }
+ }
+ return stripPrefixSegments;
+ }
+
+ private int guessFuzzFactor(final WorkspacePatcher patcher) {
+ final int strip= getStripPrefixSegments();
+ final int[] result= new int[1];
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true,
+ //TimeoutContext.run(true, GUESS_TIMEOUT, getControl().getShell(),
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ result[0]= guess(patcher, monitor, strip);
+ }
+ }
+ );
+ return result[0];
+ } catch (InvocationTargetException ex) {
+ // NeedWork
+ } catch (InterruptedException ex) {
+ // NeedWork
+ }
+ return -1;
+ }
+
+ private int guess(WorkspacePatcher patcher, IProgressMonitor pm, int strip) {
+
+ Diff[] diffs= patcher.getDiffs();
+ if (diffs==null||diffs.length<=0)
+ return -1;
+
+ // now collect files and determine "work"
+ IFile[] files= new IFile[diffs.length];
+ int work= 0;
+ for (int i= 0; i<diffs.length; i++) {
+ Diff diff= diffs[i];
+ if (diff==null)
+ continue;
+ if (diff.getType()!=Differencer.ADDITION) {
+ IPath p= diff.fOldPath;
+ if (strip>0&&strip<p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ IFile file= existsInSelection(p);
+ if (file!=null) {
+ files[i]= file;
+ work+= diff.fHunks.size();
+ }
+ }
+ }
+
+ // do the "work"
+ int[] fuzzRef= new int[1];
+ String format= PatchMessages.PreviewPatchPage_GuessFuzzProgress_format;
+ pm.beginTask(PatchMessages.PreviewPatchPage_GuessFuzzProgress_text, work);
+ try {
+ int fuzz= 0;
+ for (int i= 0; i<diffs.length; i++) {
+ Diff d= diffs[i];
+ IFile file= files[i];
+ if (d!=null&&file!=null) {
+ List lines= patcher.load(file, false);
+ String name= d.getPath().lastSegment();
+ Iterator iter= d.fHunks.iterator();
+ int shift= 0;
+ for (int hcnt= 1; iter.hasNext(); hcnt++) {
+ pm.subTask(MessageFormat.format(format, new String[] {name, Integer.toString(hcnt)}));
+ Hunk h= (Hunk) iter.next();
+ shift= patcher.calculateFuzz(h, lines, shift, pm, fuzzRef);
+ int f= fuzzRef[0];
+ if (f==-1) // cancel
+ return -1;
+ if (f>fuzz)
+ fuzz= f;
+ pm.worked(1);
+ }
+ }
+ }
+ return fuzz;
+ } finally {
+ pm.done();
+ }
+ }
+
+ private IFile existsInSelection(IPath path) {
+ return fPatchWizard.getPatcher().existsInTarget(path);
+ }
+
+
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
index 94f1050..3c6d65c 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/CompareUI.java
@@ -14,6 +14,7 @@
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.internal.DocumentManager;
+import org.eclipse.compare.internal.ICompareUIConstants;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.content.IContentType;
@@ -57,33 +58,33 @@
* Image descriptor for the disabled icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_DTOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.DTOOL_NEXT);
+ public static final ImageDescriptor DESC_DTOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.DTOOL_NEXT);
/**
* Image descriptor for the normal icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_CTOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.CTOOL_NEXT);
+ public static final ImageDescriptor DESC_CTOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.CTOOL_NEXT);
/**
* Image descriptor for the roll-over icon of the 'Next' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_ETOOL_NEXT= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.ETOOL_NEXT);
+ public static final ImageDescriptor DESC_ETOOL_NEXT= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.ETOOL_NEXT);
/**
* Image descriptor for the disabled icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_DTOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.DTOOL_PREV);
+ public static final ImageDescriptor DESC_DTOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.DTOOL_PREV);
/**
* Image descriptor for the normal icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_CTOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.CTOOL_PREV);
+ public static final ImageDescriptor DESC_CTOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.CTOOL_PREV);
/**
* Image descriptor for the roll-over icon of the 'Previous' tool bar button.
* @since 2.0
*/
- public static final ImageDescriptor DESC_ETOOL_PREV= CompareUIPlugin.getImageDescriptor(CompareUIPlugin.ETOOL_PREV);
+ public static final ImageDescriptor DESC_ETOOL_PREV= CompareUIPlugin.getImageDescriptor(ICompareUIConstants.ETOOL_PREV);
/**
* Name of the title property of a compare viewer.
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
index 3cdfe35..34a04bf 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -134,14 +134,6 @@
}
}
- public static final String DTOOL_NEXT= "dlcl16/next_nav.gif"; //$NON-NLS-1$
- public static final String ETOOL_NEXT= "elcl16/next_nav.gif"; //$NON-NLS-1$
- public static final String CTOOL_NEXT= ETOOL_NEXT;
-
- public static final String DTOOL_PREV= "dlcl16/prev_nav.gif"; //$NON-NLS-1$
- public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
- public static final String CTOOL_PREV= ETOOL_PREV;
-
/** Status code describing an internal error */
public static final int INTERNAL_ERROR= 1;
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java
new file mode 100644
index 0000000..3e17776
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java
@@ -0,0 +1,21 @@
+package org.eclipse.compare.internal;
+
+
+public interface ICompareUIConstants {
+ public final String PREFIX = CompareUIPlugin.getPluginId() + "."; //$NON-NLS-1$
+
+ public static final String DTOOL_NEXT= "dlcl16/next_nav.gif"; //$NON-NLS-1$
+ public static final String ETOOL_NEXT= "elcl16/next_nav.gif"; //$NON-NLS-1$
+ public static final String CTOOL_NEXT= ETOOL_NEXT;
+
+ public static final String DTOOL_PREV= "dlcl16/prev_nav.gif"; //$NON-NLS-1$
+ public static final String ETOOL_PREV= "elcl16/prev_nav.gif"; //$NON-NLS-1$
+ public static final String CTOOL_PREV= ETOOL_PREV;
+
+ public static final String RETARGET_PROJECT= "eview16/compare_view.gif"; //$NON-NLS-1$
+
+ public static final String IGNORE_WHITESPACE_ENABLED= "etool16/ignorews_edit.gif"; //$NON-NLS-1$
+ public static final String IGNORE_WHITESPACE_DISABLED= "dtool16/ignorews_edit.gif"; //$NON-NLS-1$
+
+ public static final String REVERSE_PATCH_ENABLED = "etool16/reverse_enabled.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java
new file mode 100644
index 0000000..6d91532
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/CheckboxDiffTreeViewer.java
@@ -0,0 +1,297 @@
+package org.eclipse.compare.internal.patch;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.internal.INavigatable;
+import org.eclipse.compare.internal.IOpenable;
+import org.eclipse.compare.internal.Utilities;
+import org.eclipse.compare.structuremergeviewer.IDiffContainer;
+import org.eclipse.compare.structuremergeviewer.IDiffElement;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.OpenEvent;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
+
+public class CheckboxDiffTreeViewer extends ContainerCheckedTreeViewer {
+
+ class CheckboxDiffViewerContentProvider implements ITreeContentProvider {
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // empty implementation
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ public void dispose() {
+ inputChanged(CheckboxDiffTreeViewer.this, getInput(), null);
+ }
+
+ public Object getParent(Object element) {
+ if (element instanceof IDiffElement)
+ return ((IDiffElement)element).getParent();
+ return null;
+ }
+
+ public final boolean hasChildren(Object element) {
+ if (element instanceof IDiffContainer)
+ return ((IDiffContainer)element).hasChildren();
+ return false;
+ }
+
+ public final Object[] getChildren(Object element) {
+ if (element instanceof IDiffContainer)
+ return ((IDiffContainer)element).getChildren();
+ return new Object[0];
+ }
+
+ public Object[] getElements(Object element) {
+ return getChildren(element);
+ }
+ }
+
+ /*
+ * Takes care of swapping left and right if fLeftIsLocal
+ * is true.
+ */
+ class CheckboxDiffViewerLabelProvider extends LabelProvider {
+
+ public String getText(Object element) {
+
+ if (element instanceof IDiffElement)
+ return ((IDiffElement)element).getName();
+
+
+ return Utilities.getString(fBundle, "defaultLabel"); //$NON-NLS-1$
+ }
+
+ public Image getImage(Object element) {
+ if (element instanceof IDiffElement) {
+ IDiffElement input= (IDiffElement) element;
+ return input.getImage();
+ }
+ return null;
+ }
+ }
+
+ CompareConfiguration fCompareConfiguration;
+ private ResourceBundle fBundle;
+
+ public CheckboxDiffTreeViewer(Composite parent, CompareConfiguration compareConfiguration) {
+ super(parent);
+ initialize(compareConfiguration);
+ }
+
+ private void initialize(CompareConfiguration compareConfiguration) {
+ Control tree= getControl();
+
+ INavigatable nav= new INavigatable() {
+ public boolean gotoDifference(boolean next) {
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return internalNavigate(next, true);
+ }
+ };
+ tree.setData(INavigatable.NAVIGATOR_PROPERTY, nav);
+
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ IOpenable openable= new IOpenable() {
+ public void openSelected() {
+ internalOpen();
+ }
+ };
+ tree.setData(IOpenable.OPENABLE_PROPERTY, openable);
+
+ fBundle= ResourceBundle.getBundle("org.eclipse.compare.structuremergeviewer.DiffTreeViewerResources"); //$NON-NLS-1$
+
+ setContentProvider(new CheckboxDiffViewerContentProvider());
+ setLabelProvider(new CheckboxDiffViewerLabelProvider());
+
+ addSelectionChangedListener(
+ new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent se) {
+ //updateActions();
+ }
+ }
+ );
+
+ }
+
+/**
+ * Selects the next (or previous) node of the current selection.
+ * If there is no current selection the first (last) node in the tree is selected.
+ * Wraps around at end or beginning.
+ * Clients may override.
+ *
+ * @param next if <code>true</code> the next node is selected, otherwise the previous node
+ * @param fireOpen if <code>true</code> an open event is fired.
+ * @return <code>true</code> if at end (or beginning)
+ */
+private boolean internalNavigate(boolean next, boolean fireOpen) {
+
+ Control c= getControl();
+ if (!(c instanceof Tree))
+ return false;
+
+ Tree tree= (Tree) c;
+ TreeItem item= null;
+ TreeItem children[]= tree.getSelection();
+ if (children != null && children.length > 0)
+ item= children[0];
+ if (item == null) {
+ children= tree.getItems();
+ if (children != null && children.length > 0) {
+ item= children[0];
+ if (item != null && item.getItemCount() <= 0) {
+ internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return false;
+ }
+ }
+ }
+
+ while (true) {
+ item= findNextPrev(item, next);
+ if (item == null)
+ break;
+ if (item.getItemCount() <= 0)
+ break;
+ }
+
+ if (item != null) {
+ internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ return false;
+ }
+ return true;
+}
+
+private TreeItem findNextPrev(TreeItem item, boolean next) {
+
+ if (item == null)
+ return null;
+
+ TreeItem children[]= null;
+
+ if (!next) {
+
+ TreeItem parent= item.getParentItem();
+ if (parent != null)
+ children= parent.getItems();
+ else
+ children= item.getParent().getItems();
+
+ if (children != null && children.length > 0) {
+ // goto previous child
+ int index= 0;
+ for (; index < children.length; index++)
+ if (children[index] == item)
+ break;
+
+ if (index > 0) {
+
+ item= children[index-1];
+
+ while (true) {
+ createChildren(item);
+ int n= item.getItemCount();
+ if (n <= 0)
+ break;
+
+ item.setExpanded(true);
+ item= item.getItems()[n-1];
+ }
+
+ // previous
+ return item;
+ }
+ }
+
+ // go up
+ item= parent;
+
+ } else {
+ item.setExpanded(true);
+ createChildren(item);
+
+ if (item.getItemCount() > 0) {
+ // has children: go down
+ children= item.getItems();
+ return children[0];
+ }
+
+ while (item != null) {
+ children= null;
+ TreeItem parent= item.getParentItem();
+ if (parent != null)
+ children= parent.getItems();
+ else
+ children= item.getParent().getItems();
+
+ if (children != null && children.length > 0) {
+ // goto next child
+ int index= 0;
+ for (; index < children.length; index++)
+ if (children[index] == item)
+ break;
+
+ if (index < children.length-1) {
+ // next
+ return children[index+1];
+ }
+ }
+
+ // go up
+ item= parent;
+ }
+ }
+
+ return item;
+}
+
+private void internalSetSelection(TreeItem ti, boolean fireOpen) {
+ if (ti != null) {
+ Object data= ti.getData();
+ if (data != null) {
+ // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ ISelection selection= new StructuredSelection(data);
+ setSelection(selection, true);
+ ISelection currentSelection= getSelection();
+ if (fireOpen && currentSelection != null && selection.equals(currentSelection)) {
+ fireOpen(new OpenEvent(this, selection));
+ }
+ }
+ }
+}
+
+/*
+ * Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
+ */
+private void internalOpen() {
+ ISelection selection= getSelection();
+ if (selection != null && !selection.isEmpty()) {
+ fireOpen(new OpenEvent(this, selection));
+ }
+}
+
+/**
+ * Creates a new DecoratingLabelProvider (using the passed in ILabelDecorator) and sets
+ * it as the label provider for the tree
+ * @param decorator
+ */
+public void setLabelDecorator(ILabelDecorator decorator) {
+ setLabelProvider(new DecoratingLabelProvider(new CheckboxDiffViewerLabelProvider(), decorator));
+}
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
index 6da4e19..b8545b0 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/DiffProject.java
@@ -14,14 +14,17 @@
import java.util.Iterator;
import java.util.List;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.ITypedElement;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.model.IWorkbenchAdapter;
-public class DiffProject implements IWorkbenchAdapter, IAdaptable {
+public class DiffProject implements IWorkbenchAdapter, IAdaptable, ITypedElement {
List fDiffs= new ArrayList();
IProject fProject;
@@ -48,7 +51,7 @@
return this.fProject;
}
- String getName() {
+ public String getName() {
return fProject.getName();
}
@@ -125,4 +128,12 @@
public String getOriginalProjectName() {
return fOriginalProjectName;
}
+
+ public Image getImage() {
+ return CompareUI.getImage(fProject);
+ }
+
+ public String getType() {
+ return ITypedElement.FOLDER_TYPE;
+ }
}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
index 75b3c6b..d60d1d3 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.java
@@ -26,6 +26,9 @@
public static String PatchAction_AlwaysSaveQuestion;
public static String PatchAction_SaveAllQuestion;
public static String PatchAction_SaveAllDescription;
+ public static String PatcherCompareEditorInput_AfterPatch;
+ public static String PatcherCompareEditorInput_LocalCopy;
+ public static String PatcherCompareEditorInput_PatchContents;
public static String PatchWizard_title;
public static String PatchWizard_unexpectedException_message;
public static String InputPatchPage_title;
@@ -87,4 +90,8 @@
public static String PreviewPatchPage_SelectProject;
public static String PreviewPatchPage_Target;
public static String PreviewPatchLabelDecorator_ProjectDoesNotExist;
+ public static String PreviewPatchPage2_IgnoreWSAction;
+ public static String PreviewPatchPage2_IgnoreWSTooltip;
+ public static String PreviewPatchPage2_RetargetAction;
+ public static String PreviewPatchPage2_RetargetTooltip;
}
\ No newline at end of file
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
index a44d187..a482462 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchMessages.properties
@@ -16,6 +16,8 @@
PatchAction_ExceptionTitle=Saving Resources
PatchAction_Exception=Unexpected exception. See log for details
PatchAction_SavingDirtyEditorsTask=Saving dirty editors
+PatcherCompareEditorInput_LocalCopy=Local Copy
+PatcherCompareEditorInput_AfterPatch=After Patch
PatchAction_AlwaysSaveQuestion=&Always save all modified resources automatically prior to patching
PatchAction_SaveAllQuestion=Save all modified resources
PatchAction_SaveAllDescription=All modified resources have to be saved before this operation.\nClick 'OK' to confirm or click 'Cancel'.
@@ -25,6 +27,7 @@
#
PatchWizard_title=Apply Patch
PatchWizard_unexpectedException_message= Unexpected exception while applying the patch. See log for a detailed error description.
+PatcherCompareEditorInput_PatchContents=Patch Contents
#
# InputPatchPage
@@ -73,10 +76,14 @@
PreviewPatchPage_IgnoreSegments_text=&Ignore leading path name segments:
PreviewPatchPage_ReversePatch_text=&Reverse patch
PreviewPatchPage_FuzzFactor_text=&Maximum fuzz factor:
+PreviewPatchPage2_RetargetAction=Retarget
+PreviewPatchPage2_IgnoreWSAction=Ignore WhiteSpace
PreviewPatchPage_FuzzFactor_tooltip=Allow Context to Shift This Number of Lines from the Original Location
PreviewPatchPage_IgnoreWhitespace_text=Ignore &white space
PreviewPatchPage_NoName_text=no name
PreviewPatchPage_FileExists_error=(file already exists)
+PreviewPatchPage2_RetargetTooltip=Retarget Project
+PreviewPatchPage2_IgnoreWSTooltip=Ignore WhiteSpace
PreviewPatchPage_FileDoesNotExist_error=(file does not exist)
PreviewPatchPage_NoMatch_error=(no match)
PreviewPatchPage_MatchProjects=Retarget &Patch...
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
index 9ae3aa3..740ce77 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatchWizard.java
@@ -79,7 +79,7 @@
addPage(fPatchWizardPage= new InputPatchPage(this));
addPage(new PatchTargetPage(this));
- addPage(new PreviewPatchPage(this));
+ addPage(new PreviewPatchPage2(this));
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java
new file mode 100644
index 0000000..395c661
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PatcherCompareEditorInput.java
@@ -0,0 +1,593 @@
+package org.eclipse.compare.internal.patch;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.CompareEditorInput;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.CompareViewerPane;
+import org.eclipse.compare.IStreamContentAccessor;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.ResourceNode;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.DiffImage;
+import org.eclipse.compare.internal.Utilities;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.IDiffContainer;
+import org.eclipse.compare.structuremergeviewer.IDiffElement;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+
+public class PatcherCompareEditorInput extends CompareEditorInput {
+
+ class PatchedFileNode implements ITypedElement, IStreamContentAccessor {
+
+ byte[] bytes;
+ String type;
+ String name;
+
+
+ public PatchedFileNode(byte[] bytes, String type, String name){
+ this.bytes = bytes;
+ this.type = type;
+ this.name = name;
+ }
+
+ public Image getImage() {
+ return null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public InputStream getContents() throws CoreException {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ }
+
+ class MyDiffNode extends DiffNode {
+
+ //Diff associated with this MyDiffNode
+ private Diff diff = null;
+ //Hunk associated with this MyDiffNode
+ private Hunk hunk = null;
+
+
+ public MyDiffNode(IDiffContainer parent, int kind, ITypedElement ancestor, ITypedElement left, ITypedElement right, Diff diff) {
+ super(parent, kind, ancestor, left, right);
+ this.diff = diff;
+ }
+
+ public MyDiffNode(IDiffContainer parent, int kind, ITypedElement ancestor, ITypedElement left, ITypedElement right, Hunk hunk) {
+ super(parent, kind, ancestor, left, right);
+ this.hunk = hunk;
+ }
+
+ public String getName() {
+ if (diff != null)
+ return diff.getLabel(diff);
+
+ if (hunk != null)
+ return hunk.getLabel(hunk);
+
+ return ""; //$NON-NLS-1$
+ }
+
+ Diff getDiff() {
+ return diff;
+ }
+
+
+ Hunk getHunk() {
+ return hunk;
+ }
+
+ }
+
+ class PatcherCompareEditorDecorator implements ILabelDecorator {
+
+ /** Maps strings to images */
+ private Map fImages= new Hashtable(10);
+ private List fDisposeOnShutdownImages= new ArrayList();
+
+ ImageDescriptor errId= CompareUIPlugin.getImageDescriptor("ovr16/error_ov.gif"); //$NON-NLS-1$
+
+ static final String error = "error"; //$NON-NLS-1$
+ static final String add = "add"; //$NON-NLS-1$
+ static final String delete = "del"; //$NON-NLS-1$
+
+ public Image decorateImage(Image image, Object element) {
+ if (element instanceof MyDiffNode){
+ MyDiffNode myDiffNode = (MyDiffNode) element;
+ Diff diff = myDiffNode.getDiff();
+ Hunk hunk = myDiffNode.getHunk();
+ if (diff != null){
+ switch (diff.getType()){
+ case Differencer.ADDITION:
+ return getImageFor(add + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$
+
+ case Differencer.DELETION:
+ return getImageFor(delete + (diff.fMatches ? "" : error), image, diff.fMatches); //$NON-NLS-1$
+
+ default:
+ return getImageFor(diff.fMatches ? "" : error, image, diff.fMatches); //$NON-NLS-1$
+ }
+ } else if (hunk != null){
+ return getImageFor((hunk.fMatches ? "" : error),image, hunk.fMatches); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ private Image getImageFor(String id, Image image, boolean hasMatches) {
+ Image cached_image = (Image) fImages.get(id);
+ if (cached_image == null){
+ DiffImage diffImage = new DiffImage(image, hasMatches ? null : errId, 16, false);
+ cached_image = diffImage.createImage();
+ fImages.put(id, cached_image);
+ fDisposeOnShutdownImages.add(cached_image);
+ }
+ return cached_image;
+ }
+
+ public String decorateText(String text, Object element) {
+ if (element instanceof DiffNode){
+ ITypedElement typedElement = ((DiffNode) element).getLeft();
+ if (typedElement != null && typedElement instanceof DiffProject){
+ DiffProject project = (DiffProject) typedElement;
+ if (!project.getName().equals(project.getOriginalProjectName()))
+ return NLS.bind(PatchMessages.Diff_2Args,
+ new String[]{project.getOriginalProjectName(),
+ NLS.bind(PatchMessages.PreviewPatchPage_Target, new String[]{project.getName()})});
+ }
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ if (fDisposeOnShutdownImages != null) {
+ Iterator i= fDisposeOnShutdownImages.iterator();
+ while (i.hasNext()) {
+ Image img= (Image) i.next();
+ if (!img.isDisposed())
+ img.dispose();
+ }
+ fImages= null;
+ }
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ //don't need listener
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ //don't need listener
+ }
+
+ }
+ private DiffNode root;
+ private List failedHunks;
+
+ private CheckboxDiffTreeViewer viewer;
+ private final static int LEFT = 0;
+ private final static int RIGHT = 1;
+ private PreviewPatchPage2 previewPatchPage;
+
+ private HashMap nodesToDiffs;
+
+ public PatcherCompareEditorInput() {
+ super(new CompareConfiguration());
+ root = new DiffNode(Differencer.NO_CHANGE) {
+ public boolean hasChildren() {
+ return true;
+ }
+ };
+ }
+
+ protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ initLabels();
+ return root;
+ }
+
+ private void initLabels() {
+ CompareConfiguration cc = getCompareConfiguration();
+ cc.setLeftEditable(false);
+ cc.setRightEditable(false);
+ String leftLabel = PatchMessages.PatcherCompareEditorInput_LocalCopy;
+ cc.setLeftLabel(leftLabel);
+ String rightLabel = PatchMessages.PatcherCompareEditorInput_AfterPatch;
+ cc.setRightLabel(rightLabel);
+ }
+
+ public void updateInput(WorkspacePatcher patcher) {
+ buildTree(patcher);
+ updateTree(patcher);
+ }
+
+ private void updateTree(WorkspacePatcher patcher){
+ if (viewer == null)
+ return;
+
+ int strip= previewPatchPage.getStripPrefixSegments();
+ //Get the elements from the content provider
+ ITreeContentProvider contentProvider= (ITreeContentProvider) viewer.getContentProvider();
+ Object[] projects= contentProvider.getElements(root);
+ ArrayList hunksToCheck= new ArrayList();
+ ArrayList nodesToCheck=new ArrayList();
+ //Iterate through projects and call reset on each project
+ for (int j= 0; j<projects.length; j++) {
+ if (!(projects[j] instanceof MyDiffNode)) {
+ DiffNode projectNode = (DiffNode) projects[j];
+ ITypedElement project = projectNode.getLeft();
+ Assert.isNotNull(project);
+ Assert.isTrue(project instanceof DiffProject);
+ hunksToCheck.addAll(((DiffProject)project).reset(patcher, strip, previewPatchPage.getFuzzFactor()));
+ IDiffElement[] diffNodes = projectNode.getChildren();
+
+ Iterator iter = hunksToCheck.iterator();
+ while (iter.hasNext()){
+ Hunk hunkToMatch = (Hunk) iter.next();
+ Object matchingHunkNode = nodesToDiffs.get(hunkToMatch);
+ if (matchingHunkNode != null)
+ nodesToCheck.add(matchingHunkNode);
+
+ }
+ for (int i = 0; i < diffNodes.length; i++) {
+ viewer.update(diffNodes[i], null);
+ IDiffElement[] hunkNodes =((MyDiffNode) diffNodes[i]).getChildren();
+ for (int k = 0; k < hunkNodes.length; k++) {
+ viewer.update(hunkNodes[k],null);
+ }
+ }
+
+ } else {
+ if (projects[j] instanceof MyDiffNode) {
+ Diff diff= ((MyDiffNode) projects[j]).getDiff();
+ hunksToCheck.addAll(diff.reset(patcher, strip, previewPatchPage.getFuzzFactor()));
+ viewer.update(diff, null);
+ }
+ }
+ }
+ viewer.refresh();
+ viewer.setCheckedElements(nodesToCheck.toArray());
+
+ updateEnablements();
+ }
+
+ private void buildTree(WorkspacePatcher patcher) {
+
+ if (patcher.isWorkspacePatch()) {
+
+ if (root.hasChildren()) {
+ IDiffElement[] children = root.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ root.remove(children[i]);
+ }
+ }
+
+ nodesToDiffs = new HashMap();
+
+ DiffProject[] projects = patcher.getDiffProjects();
+ try {
+ for (int i = 0; i < projects.length; i++) {
+ DiffNode projectNode = new DiffNode(root, Differencer.CHANGE, null, projects[i], null);
+ Iterator iter = projects[i].fDiffs.iterator();
+ while (iter.hasNext()) {
+ Object obj = iter.next();
+ if (obj instanceof Diff) {
+ Diff diff = (Diff) obj;
+ IFile tempFile = projects[i].getFile(new Path(diff.getLabel(diff)));
+ byte[] bytes = quickPatch(tempFile, patcher, diff);
+ int differencer = Differencer.CHANGE;
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ }
+ if (!tempFile.exists())
+ tempFile = null;
+
+ ResourceNode tempNode = new ResourceNode(tempFile);
+ PatchedFileNode patchedNode = new PatchedFileNode(bytes, tempNode.getType(), tempFile.getProjectRelativePath().toString());
+ MyDiffNode allFile = new MyDiffNode(projectNode, differencer, tempNode, tempNode, patchedNode, diff);
+ //Add individual hunks to each Diff node
+ Hunk[] hunks = diff.getHunks();
+ for (int j = 0; j < hunks.length; j++) {
+ Diff tempDiff = new Diff(diff.fOldPath, diff.fOldDate, diff.fNewPath, diff.fNewDate);
+ tempDiff.add(hunks[j]);
+ bytes = quickPatch(tempFile, patcher, tempDiff);
+ differencer = Differencer.NO_CHANGE;
+ switch (hunks[j].getHunkType()) {
+ case Hunk.ADDED :
+ differencer += Differencer.ADDITION;
+ break;
+
+ case Hunk.CHANGED :
+ differencer += Differencer.CHANGE;
+ break;
+
+ case Hunk.DELETED :
+ differencer += Differencer.DELETION;
+ break;
+ }
+
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ String[] hunkContents = createInput(hunks[j]);
+ PatchedFileNode ancestor = new PatchedFileNode(hunkContents[LEFT].getBytes(), hunks[j].fParent.getPath().getFileExtension(), hunks[j].getDescription());
+ patchedNode = new PatchedFileNode(hunkContents[RIGHT].getBytes(), tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, ancestor, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ } else {
+ patchedNode = new PatchedFileNode(bytes, tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, tempNode, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ }
+ }
+
+ }
+
+ }
+
+ }
+
+ } catch (CoreException e) {
+ //ignore
+ }
+ viewer.setInput(root);
+ viewer.refresh();
+ } else {
+ if (root.hasChildren()) {
+ IDiffElement[] children = root.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ root.remove(children[i]);
+ }
+ }
+
+ nodesToDiffs = new HashMap();
+
+ Diff[] diffs = patcher.getDiffs();
+ try {
+ for (int i = 0; i < diffs.length; i++) {
+ Diff diff = diffs[i];
+ IFile tempFile = patcher.existsInTarget(new Path(diff.getLabel(diff)));
+
+ byte[] bytes = quickPatch(tempFile, patcher, diff);
+ int differencer = Differencer.CHANGE;
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ }
+ ResourceNode tempNode = new ResourceNode(tempFile);
+ PatchedFileNode patchedNode = new PatchedFileNode(bytes, tempNode.getType(), tempFile.getProjectRelativePath().toString());
+ MyDiffNode allFile = new MyDiffNode(root, differencer, tempNode, tempNode, patchedNode, diff);
+ //Add individual hunks to each Diff node
+ Hunk[] hunks = diff.getHunks();
+ for (int j = 0; j < hunks.length; j++) {
+ Diff tempDiff = new Diff(diff.fOldPath, diff.fOldDate, diff.fNewPath, diff.fNewDate);
+ tempDiff.add(hunks[j]);
+ bytes = quickPatch(tempFile, patcher, tempDiff);
+ differencer = Differencer.NO_CHANGE;
+ switch (hunks[j].getHunkType()) {
+ case Hunk.ADDED :
+ differencer += Differencer.ADDITION;
+ break;
+
+ case Hunk.CHANGED :
+ differencer += Differencer.CHANGE;
+ break;
+
+ case Hunk.DELETED :
+ differencer += Differencer.DELETION;
+ break;
+ }
+
+ if (failedHunks.size() != 0) {
+ differencer += Differencer.CONFLICTING;
+ String[] hunkContents = createInput(hunks[j]);
+ PatchedFileNode ancestor = new PatchedFileNode(hunkContents[LEFT].getBytes(), hunks[j].fParent.getPath().getFileExtension(), hunks[j].getDescription());
+ patchedNode = new PatchedFileNode(hunkContents[RIGHT].getBytes(), tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, ancestor, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ } else {
+ patchedNode = new PatchedFileNode(bytes, tempNode.getType(), hunks[j].getDescription());
+ MyDiffNode hunkNode = new MyDiffNode(allFile, differencer, tempNode, tempNode, patchedNode, hunks[j]);
+ nodesToDiffs.put(hunks[j], hunkNode);
+ }
+ }
+
+ }
+ } catch (CoreException ex) {//ignore
+ }
+
+ }
+
+ }
+
+ private byte[] quickPatch(IFile tempFile, WorkspacePatcher patcher, Diff diff) throws CoreException {
+
+ failedHunks = new ArrayList();
+ List result = patcher.apply(diff, tempFile, diff.getType() == Differencer.ADDITION, failedHunks);
+ String patchedResults = patcher.createString(result);
+ byte[] bytes;
+ try {
+ bytes = patchedResults.getBytes(Utilities.getCharset(tempFile));
+ } catch (UnsupportedEncodingException e) {
+ // uses default encoding
+ bytes = patchedResults.getBytes();
+ }
+
+ return bytes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.CompareEditorInput#createDiffViewer(org.eclipse.swt.widgets.Composite)
+ */
+ public Viewer createDiffViewer(Composite parent) {
+ viewer = new CheckboxDiffTreeViewer(parent, getCompareConfiguration());
+ viewer.setLabelDecorator(new PatcherCompareEditorDecorator());
+ viewer.getTree().setData(CompareUI.COMPARE_VIEWER_TITLE, PatchMessages.PatcherCompareEditorInput_PatchContents);
+ viewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ viewer.setSubtreeChecked(event.getElement(),event.getChecked());
+ updateEnablements();
+ }
+ });
+ viewer.setInput(this);
+ return viewer;
+ }
+
+ private String[] createInput(Hunk hunk) {
+
+ String[] lines= hunk.fLines;
+ StringBuffer left= new StringBuffer();
+ StringBuffer right= new StringBuffer();
+
+ for (int i= 0; i<lines.length; i++) {
+ String line= lines[i];
+ String rest= line.substring(1);
+ switch (line.charAt(0)) {
+ case ' ' :
+ left.append(rest);
+ right.append(rest);
+ break;
+ case '-' :
+ left.append(rest);
+ break;
+ case '+' :
+ right.append(rest);
+ break;
+ }
+ }
+
+
+ return new String[]{left.toString(),right.toString()};
+ }
+
+ public void contributeDiffViewerToolbarItems(Action[] actions, boolean workspacePatch){
+ ToolBarManager tbm= CompareViewerPane.getToolBarManager(viewer.getControl().getParent());
+ if (tbm != null) {
+ tbm.removeAll();
+
+ tbm.add(new Separator("contributed")); //$NON-NLS-1$
+
+ for (int i = 0; i < actions.length; i++) {
+ //If this is a workspace patch, make sure all actions are enabled
+ if (workspacePatch)
+ actions[i].setEnabled(true);
+
+ tbm.appendToGroup("contributed", actions[i]); //$NON-NLS-1$
+ }
+
+ tbm.update(true);
+ }
+ }
+
+ public CheckboxDiffTreeViewer getViewer() {
+ return viewer;
+ }
+
+ /**
+ * Makes sure that at least one hunk is checked off in the tree before
+ * allowing the patch to be applied.
+ */
+ /* private */void updateEnablements() {
+ boolean atLeastOneIsEnabled= false;
+ if (viewer!=null) {
+ ITreeContentProvider contentProvider= (ITreeContentProvider) viewer.getContentProvider();
+ Object[] projects= contentProvider.getElements(root);
+ //Iterate through projects
+ for (int j= 0; j<projects.length; j++) {
+ if (!(projects[j] instanceof MyDiffNode)) {
+ DiffNode project = (DiffNode) projects[j];
+ //Iterate through project diffs
+ Object[] diffs= project.getChildren();
+ for (int i= 0; i<diffs.length; i++) {
+ MyDiffNode diff= (MyDiffNode) diffs[i];
+ atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, diff);
+ }
+ } else if (projects[j] instanceof MyDiffNode) {
+ atLeastOneIsEnabled= updateEnablement(atLeastOneIsEnabled, (MyDiffNode) projects[j]);
+ }
+ }
+ }
+
+ previewPatchPage.setPageComplete(atLeastOneIsEnabled);
+ }
+
+ private boolean updateEnablement(boolean oneIsEnabled, MyDiffNode diffNode) {
+ boolean checked= viewer.getChecked(diffNode);
+ Diff diff = diffNode.getDiff();
+ Assert.isNotNull(diff);
+ diff.setEnabled(checked);
+ if (checked) {
+ Object[] hunkItems= diffNode.getChildren();
+ for (int h= 0; h<hunkItems.length; h++) {
+ MyDiffNode hunkNode = (MyDiffNode) hunkItems[h];
+ checked= viewer.getChecked(hunkNode);
+ Hunk hunk= hunkNode.getHunk();
+ Assert.isNotNull(hunk);
+ hunk.setEnabled(checked);
+ if (checked) {
+ //For workspace patch: before setting enabled flag, make sure that the project
+ //that contains this hunk actually exists in the workspace. This is to guard against the
+ //case of having a new file in a patch that is being applied to a project that
+ //doesn't currently exist.
+ boolean projectExists= true;
+ DiffProject project= (DiffProject)diff.getParent(null);
+ if (project!= null){
+ projectExists=project.getProject().exists();
+ }
+ if (projectExists)
+ oneIsEnabled= true;
+ }
+
+ }
+ }
+
+ return oneIsEnabled;
+ }
+
+
+ /**
+ * Stores a pointer back to the PreviewPatchPage
+ * @param page
+ */
+ public void setPreviewPatchPage(PreviewPatchPage2 page) {
+ previewPatchPage = page;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java
new file mode 100644
index 0000000..c8bc66a
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/patch/PreviewPatchPage2.java
@@ -0,0 +1,506 @@
+package org.eclipse.compare.internal.patch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.ICompareUIConstants;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.model.BaseWorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+
+import com.ibm.icu.text.MessageFormat;
+
+
+public class PreviewPatchPage2 extends WizardPage {
+
+ protected final static String PREVIEWPATCHPAGE_NAME= "PreviewPatchPage"; //$NON-NLS-1$
+ private PatchWizard fPatchWizard;
+ private PatcherCompareEditorInput patcherCompareEditorInput = new PatcherCompareEditorInput();
+
+ private Combo fStripPrefixSegments;
+ private Text fFuzzField;
+
+ private Action fRetargetSelection;
+ private Action fIgnoreWhiteSpace;
+ private Action fReversePatch;
+
+ protected boolean pageRecalculate= true;
+
+ class RetargetPatchDialog extends Dialog {
+
+ protected TreeViewer rpTreeViewer;
+ protected DiffNode rpSelectedNode;
+ protected DiffProject rpSelectedProject;
+ protected IProject rpTargetProject;
+
+ public RetargetPatchDialog(Shell shell, ISelection selection) {
+ super(shell);
+ setShellStyle(getShellStyle()|SWT.RESIZE);
+ if (selection instanceof IStructuredSelection) {
+ rpSelectedNode= (DiffNode) ((IStructuredSelection) selection).getFirstElement();
+ }
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite= (Composite) super.createDialogArea(parent);
+
+ initializeDialogUnits(parent);
+
+ getShell().setText(PatchMessages.PreviewPatchPage_RetargetPatch);
+
+ GridLayout layout= new GridLayout();
+ layout.numColumns= 1;
+ layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ composite.setLayout(layout);
+ final GridData data= new GridData(SWT.FILL, SWT.FILL, true, true);
+ composite.setLayoutData(data);
+
+ //add controls to composite as necessary
+ Label label= new Label(composite, SWT.LEFT|SWT.WRAP);
+ label.setText(NLS.bind(PatchMessages.PreviewPatchPage_SelectProject, rpSelectedNode.getName()));
+ final GridData data2= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
+ label.setLayoutData(data2);
+
+ rpTreeViewer= new TreeViewer(composite, SWT.BORDER);
+ GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.widthHint= 0;
+ gd.heightHint= 0;
+ rpTreeViewer.getTree().setLayoutData(gd);
+
+ rpTreeViewer.setContentProvider(new RetargetPatchContentProvider());
+ rpTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
+ rpTreeViewer.setSorter(new ResourceSorter(ResourceSorter.NAME));
+ rpTreeViewer.setInput(ResourcesPlugin.getWorkspace());
+ ITypedElement tempProject = rpSelectedNode.getLeft();
+ if (tempProject instanceof DiffProject){
+ rpSelectedProject = (DiffProject)tempProject;
+ rpTreeViewer.setSelection(new StructuredSelection(rpSelectedProject.getProject()));
+ }
+
+ setupListeners();
+
+ Dialog.applyDialogFont(composite);
+
+ return parent;
+ }
+
+ protected void okPressed() {
+ rpSelectedProject.setProject(rpTargetProject);
+ super.okPressed();
+ }
+
+ void setupListeners() {
+ rpTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection s= (IStructuredSelection) event.getSelection();
+ Object obj= s.getFirstElement();
+ if (obj instanceof IProject)
+ rpTargetProject= (IProject) obj;
+ }
+ });
+
+ rpTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ ISelection s= event.getSelection();
+ if (s instanceof IStructuredSelection) {
+ Object item= ((IStructuredSelection) s).getFirstElement();
+ if (rpTreeViewer.getExpandedState(item))
+ rpTreeViewer.collapseToLevel(item, 1);
+ else
+ rpTreeViewer.expandToLevel(item, 1);
+ }
+ }
+ });
+
+ }
+
+ protected Point getInitialSize() {
+ final Point size= super.getInitialSize();
+ size.x= convertWidthInCharsToPixels(75);
+ size.y+= convertHeightInCharsToPixels(20);
+ return size;
+ }
+ }
+
+ class RetargetPatchContentProvider extends BaseWorkbenchContentProvider {
+ //Never show closed projects
+ boolean showClosedProjects= false;
+
+ public Object[] getChildren(Object element) {
+ if (element instanceof IWorkspace) {
+ // check if closed projects should be shown
+ IProject[] allProjects= ((IWorkspace) element).getRoot().getProjects();
+ if (showClosedProjects)
+ return allProjects;
+
+ ArrayList accessibleProjects= new ArrayList();
+ for (int i= 0; i<allProjects.length; i++) {
+ if (allProjects[i].isOpen()) {
+ accessibleProjects.add(allProjects[i]);
+ }
+ }
+ return accessibleProjects.toArray();
+ }
+
+ if (element instanceof IProject) {
+ return new Object[0];
+ }
+ return super.getChildren(element);
+ }
+ }
+
+ public PreviewPatchPage2(PatchWizard pw) {
+ super(PREVIEWPATCHPAGE_NAME, PatchMessages.PreviewPatchPage_title, null);
+
+ fPatchWizard= pw;
+
+ }
+
+ public void createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ initializeDialogUnits(parent);
+
+ buildPatchOptionsGroup(composite);
+
+ try {
+ patcherCompareEditorInput.run(null);
+ } catch (InterruptedException e) {//ignore
+ } catch (InvocationTargetException e) {//ignore
+ }
+
+
+ Control c = patcherCompareEditorInput.createContents(composite);
+ patcherCompareEditorInput.contributeDiffViewerToolbarItems(getContributedActions(), fPatchWizard.getPatcher().isWorkspacePatch());
+ patcherCompareEditorInput.setPreviewPatchPage(this);
+ c.setLayoutData(new GridData(GridData.FILL_BOTH));
+ setControl(composite);
+
+ }
+
+ private Action[] getContributedActions() {
+ fRetargetSelection= new Action(PatchMessages.PreviewPatchPage2_RetargetAction, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.RETARGET_PROJECT)) {
+ public void run() {
+ Shell shell = getShell();
+ ISelection selection = patcherCompareEditorInput.getViewer().getSelection();
+ final RetargetPatchDialog dialog= new RetargetPatchDialog(shell, selection);
+ dialog.open();
+ patcherCompareEditorInput.updateInput(fPatchWizard.getPatcher());
+ }
+ };
+ fRetargetSelection.setToolTipText(PatchMessages.PreviewPatchPage2_RetargetTooltip);
+ fRetargetSelection.setEnabled(false);
+
+ fIgnoreWhiteSpace = new Action(PatchMessages.PreviewPatchPage2_IgnoreWSAction, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IGNORE_WHITESPACE_ENABLED)){
+ public void run(){
+ fIgnoreWhiteSpace.setChecked(isChecked());
+ if (fPatchWizard.getPatcher().setIgnoreWhitespace(fIgnoreWhiteSpace.isChecked())){
+ fillTree();
+ }
+ }
+ };
+ fIgnoreWhiteSpace.setChecked(false);
+ fIgnoreWhiteSpace.setToolTipText(PatchMessages.PreviewPatchPage2_IgnoreWSTooltip);
+ fIgnoreWhiteSpace.setDisabledImageDescriptor(CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IGNORE_WHITESPACE_DISABLED));
+
+ fReversePatch = new Action(PatchMessages.PreviewPatchPage_ReversePatch_text, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.REVERSE_PATCH_ENABLED)){
+ public void run(){
+ fReversePatch.setChecked(isChecked());
+ if (fPatchWizard.getPatcher().setReversed(isChecked())){
+ fillTree();
+ }
+ }
+ };
+ fReversePatch.setChecked(false);
+ fReversePatch.setToolTipText(PatchMessages.PreviewPatchPage_ReversePatch_text);
+
+ return new Action[]{fIgnoreWhiteSpace, fRetargetSelection, fReversePatch};
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ //Need to handle input and rebuild tree only when becoming visible
+ if(visible){
+ fillTree();
+ }
+ }
+
+ private void fillTree(){
+ //Update prefix count - go through all of the diffs and find the smallest
+ //path segment contained in all diffs.
+ int length= 99;
+ if (fStripPrefixSegments!=null&& pageRecalculate) {
+ length= fPatchWizard.getPatcher().calculatePrefixSegmentCount();
+ if (length!=99) {
+ for (int k= 1; k<length; k++)
+ fStripPrefixSegments.add(Integer.toString(k));
+ pageRecalculate= false;
+ }
+ }
+
+ patcherCompareEditorInput.updateInput(fPatchWizard.getPatcher());
+
+ }
+ /*
+ * Create the group for setting various patch options
+ */
+ private void buildPatchOptionsGroup(Composite parent) {
+
+ GridLayout gl;
+ GridData gd;
+ Label l;
+
+ final WorkspacePatcher patcher= fPatchWizard.getPatcher();
+
+ Group group= new Group(parent, SWT.NONE);
+ group.setText(PatchMessages.PreviewPatchPage_PatchOptions_title);
+ gl= new GridLayout(); gl.numColumns= 4;
+ group.setLayout(gl);
+ group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL|GridData.GRAB_HORIZONTAL));
+
+ // 1st row
+
+ Composite pair= new Composite(group, SWT.NONE);
+ gl= new GridLayout(); gl.numColumns= 2; gl.marginHeight= gl.marginWidth= 0;
+ pair.setLayout(gl);
+ gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ pair.setLayoutData(gd);
+
+ l= new Label(pair, SWT.NONE);
+ l.setText(PatchMessages.PreviewPatchPage_IgnoreSegments_text);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL);
+ l.setLayoutData(gd);
+
+ fStripPrefixSegments= new Combo(pair, SWT.DROP_DOWN|SWT.READ_ONLY|SWT.SIMPLE);
+ int prefixCnt= patcher.getStripPrefixSegments();
+ String prefix= Integer.toString(prefixCnt);
+ fStripPrefixSegments.add(prefix);
+ fStripPrefixSegments.setText(prefix);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_END);
+ fStripPrefixSegments.setLayoutData(gd);
+
+ addSpacer(group);
+
+ // 2nd row
+ pair= new Composite(group, SWT.NONE);
+ gl= new GridLayout(); gl.numColumns= 3; gl.marginHeight= gl.marginWidth= 0;
+ pair.setLayout(gl);
+ gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ pair.setLayoutData(gd);
+
+ l= new Label(pair, SWT.NONE);
+ l.setText(PatchMessages.PreviewPatchPage_FuzzFactor_text);
+ l.setToolTipText(PatchMessages.PreviewPatchPage_FuzzFactor_tooltip);
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER|GridData.HORIZONTAL_ALIGN_BEGINNING|GridData.GRAB_HORIZONTAL);
+ l.setLayoutData(gd);
+
+ fFuzzField= new Text(pair, SWT.BORDER);
+ fFuzzField.setText("2"); //$NON-NLS-1$
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END); gd.widthHint= 30;
+ fFuzzField.setLayoutData(gd);
+
+ Button b= new Button(pair, SWT.PUSH);
+ b.setText(PatchMessages.PreviewPatchPage_GuessFuzz_text);
+ b.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ int fuzz= guessFuzzFactor(patcher);
+ if (fuzz>=0)
+ fFuzzField.setText(Integer.toString(fuzz));
+ }
+ }
+ );
+ gd= new GridData(GridData.VERTICAL_ALIGN_CENTER);
+ int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+ Point minSize = b.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+ gd.widthHint = Math.max(widthHint, minSize.x);
+ b.setLayoutData(gd);
+
+ // register listeners
+
+ if (fStripPrefixSegments!=null)
+ fStripPrefixSegments.addSelectionListener(
+ new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
+ patcherCompareEditorInput.updateInput(patcher);
+ }
+ }
+ );
+
+
+ fFuzzField.addModifyListener(
+ new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (patcher.setFuzz(getFuzzFactor()))
+ patcherCompareEditorInput.updateInput(patcher);
+ }
+ });
+ }
+
+ private void addSpacer(Composite parent) {
+ Label label= new Label(parent, SWT.NONE);
+ GridData gd= new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint= 10;
+ label.setLayoutData(gd);
+ }
+
+ public int getFuzzFactor() {
+ int fuzzFactor= 0;
+ if (fFuzzField!=null) {
+ String s= fFuzzField.getText();
+ try {
+ fuzzFactor= Integer.parseInt(s);
+ } catch (NumberFormatException ex) {
+ // silently ignored
+ }
+ }
+ return fuzzFactor;
+ }
+
+ public int getStripPrefixSegments() {
+ int stripPrefixSegments= 0;
+ if (fStripPrefixSegments!=null) {
+ String s= fStripPrefixSegments.getText();
+ try {
+ stripPrefixSegments= Integer.parseInt(s);
+ } catch (NumberFormatException ex) {
+ // silently ignored
+ }
+ }
+ return stripPrefixSegments;
+ }
+
+ private int guessFuzzFactor(final WorkspacePatcher patcher) {
+ final int strip= getStripPrefixSegments();
+ final int[] result= new int[1];
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(true, true,
+ //TimeoutContext.run(true, GUESS_TIMEOUT, getControl().getShell(),
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ result[0]= guess(patcher, monitor, strip);
+ }
+ }
+ );
+ return result[0];
+ } catch (InvocationTargetException ex) {
+ // NeedWork
+ } catch (InterruptedException ex) {
+ // NeedWork
+ }
+ return -1;
+ }
+
+ private int guess(WorkspacePatcher patcher, IProgressMonitor pm, int strip) {
+
+ Diff[] diffs= patcher.getDiffs();
+ if (diffs==null||diffs.length<=0)
+ return -1;
+
+ // now collect files and determine "work"
+ IFile[] files= new IFile[diffs.length];
+ int work= 0;
+ for (int i= 0; i<diffs.length; i++) {
+ Diff diff= diffs[i];
+ if (diff==null)
+ continue;
+ if (diff.getType()!=Differencer.ADDITION) {
+ IPath p= diff.fOldPath;
+ if (strip>0&&strip<p.segmentCount())
+ p= p.removeFirstSegments(strip);
+ IFile file= existsInSelection(p);
+ if (file!=null) {
+ files[i]= file;
+ work+= diff.fHunks.size();
+ }
+ }
+ }
+
+ // do the "work"
+ int[] fuzzRef= new int[1];
+ String format= PatchMessages.PreviewPatchPage_GuessFuzzProgress_format;
+ pm.beginTask(PatchMessages.PreviewPatchPage_GuessFuzzProgress_text, work);
+ try {
+ int fuzz= 0;
+ for (int i= 0; i<diffs.length; i++) {
+ Diff d= diffs[i];
+ IFile file= files[i];
+ if (d!=null&&file!=null) {
+ List lines= patcher.load(file, false);
+ String name= d.getPath().lastSegment();
+ Iterator iter= d.fHunks.iterator();
+ int shift= 0;
+ for (int hcnt= 1; iter.hasNext(); hcnt++) {
+ pm.subTask(MessageFormat.format(format, new String[] {name, Integer.toString(hcnt)}));
+ Hunk h= (Hunk) iter.next();
+ shift= patcher.calculateFuzz(h, lines, shift, pm, fuzzRef);
+ int f= fuzzRef[0];
+ if (f==-1) // cancel
+ return -1;
+ if (f>fuzz)
+ fuzz= f;
+ pm.worked(1);
+ }
+ }
+ }
+ return fuzz;
+ } finally {
+ pm.done();
+ }
+ }
+
+ private IFile existsInSelection(IPath path) {
+ return fPatchWizard.getPatcher().existsInTarget(path);
+ }
+
+
+
+}