### Eclipse Workspace Patch 1.0 #P org.eclipse.compare Index: compare/org/eclipse/compare/internal/CompareMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.java,v retrieving revision 1.20 diff -u -r1.20 CompareMessages.java --- compare/org/eclipse/compare/internal/CompareMessages.java 10 Oct 2008 14:55:31 -0000 1.20 +++ compare/org/eclipse/compare/internal/CompareMessages.java 10 Dec 2008 13:49:08 -0000 @@ -130,6 +130,45 @@ public static String CompareWithOtherResourceDialog_workspaceMainButton; public static String CompareWithOtherResourceDialog_workspaceRadioButton; + public static String CreatePatchActionTitle; + public static String WorkspacePatchDialogTitle; + public static String WorkspacePatchDialogDescription; + public static String Save_Patch_As_5; + public static String Save_To_Clipboard_2; + public static String Save_In_File_System_3; + public static String Browse____4; + public static String patch_txt_6; + public static String Save_In_Workspace_7; + public static String Fi_le_name__9; + public static String Context_14; + public static String Standard_15; + public static String Diff_output_format_12; + public static String Advanced_options_19; + public static String Configure_the_options_used_for_the_CVS_diff_command_20; + public static String Unified__format_required_by_Compare_With_Patch_feature__13; + public static String GenerateLocalDiff_title; + public static String GenerateLocalDiff_pageTitle; + public static String GenerateLocalDiff_pageDescription; + public static String GenerateLocalDiff_Specify_the_file_which_contributes_the_changes; + public static String GenerateLocalDiff_overwriteTitle; + public static String GenerateLocalDiff_overwriteMsg; + public static String GenerateLocalDiff_1; + public static String GenerateLocalDiff_2; + public static String GenerateDiffFileWizard_6; + public static String GenerateDiffFileWizard_7; + public static String GenerateDiffFileWizard_8; + public static String GenerateDiffFileWizard_9; + public static String GenerateDiffFileWizard_10; + public static String GenerateDiffFileWizard_0; + public static String GenerateDiffFileWizard_2; + public static String GenerateDiffFileWizard_3; + public static String GenerateDiffFileWizard_4; + public static String GenerateDiffFileWizard_5; + public static String GenerateDiffFileWizard_browseFilesystem; + public static String GenerateDiffFileWizard_FolderExists; + public static String GenerateDiffFileWizard_ProjectClosed; + public static String GenerateDiffFileWizard_13; + static { NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class); } Index: compare/org/eclipse/compare/internal/CompareMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareMessages.properties,v retrieving revision 1.31 diff -u -r1.31 CompareMessages.properties --- compare/org/eclipse/compare/internal/CompareMessages.properties 10 Oct 2008 14:55:31 -0000 1.31 +++ compare/org/eclipse/compare/internal/CompareMessages.properties 10 Dec 2008 13:49:08 -0000 @@ -141,3 +141,42 @@ CompareWithOtherResourceDialog_externalFolderRadioButton=External folder CompareWithOtherResourceDialog_workspaceMainButton=Browse... CompareWithOtherResourceDialog_workspaceRadioButton=Workspace + +CreatePatchActionTitle=Save Diffs... +WorkspacePatchDialogTitle=Set a Patch Location +WorkspacePatchDialogDescription=Select a folder in the workspace and enter a name for the patch. +Save_To_Clipboard_2=&Clipboard +Save_In_File_System_3=Fil&e +Browse____4=Br&owse... +Save_Patch_As_5=Save Patch As +patch_txt_6=patch.txt +Save_In_Workspace_7=&Workspace +Fi_le_name__9=Fi&le name: +Context_14=&Context +Standard_15=&Standard +Diff_output_format_12=Diff Output Format +Advanced_options_19=Advanced Options +Configure_the_options_used_for_the_CVS_diff_command_20=Configure the options used for the command. +Unified__format_required_by_Compare_With_Patch_feature__13=&Unified (format required by the Apply Patch wizard) +GenerateLocalDiff_title=Save Diffs +GenerateLocalDiff_pageTitle=Save Diffs into a Patch +GenerateLocalDiff_pageDescription=Specify the input and the location for the patch. +GenerateLocalDiff_Specify_the_file_which_contributes_the_changes=Select which side of the compare editor is contributing the changes. +GenerateLocalDiff_overwriteTitle=Confirm Overwrite +GenerateLocalDiff_overwriteMsg=A file with that name already exists. Overwrite? +GenerateLocalDiff_1=Read-only file +GenerateLocalDiff_2=The specified file is read-only and cannot be overwritten. +GenerateDiffFileWizard_6=&Workspace (Multi-project Apply Patch wizard specific) +GenerateDiffFileWizard_7=&Project +GenerateDiffFileWizard_8=S&election +GenerateDiffFileWizard_9=Save Patch +GenerateDiffFileWizard_10=Patch Root +GenerateDiffFileWizard_0=Please enter a valid location. +GenerateDiffFileWizard_2=Please enter a file name. +GenerateDiffFileWizard_3=The specified directory does not exist. +GenerateDiffFileWizard_4=Please select a location in the workspace by browsing. +GenerateDiffFileWizard_5=Please enter a valid filename. +GenerateDiffFileWizard_browseFilesystem=Please select a location in the filesystem by browsing. +GenerateDiffFileWizard_FolderExists=The specified path points to an existing folder. +GenerateDiffFileWizard_ProjectClosed=The specified path points to a closed project. +GenerateDiffFileWizard_13=&Use only file path: \ No newline at end of file Index: compare/org/eclipse/compare/internal/ICompareUIConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ICompareUIConstants.java,v retrieving revision 1.13 diff -u -r1.13 ICompareUIConstants.java --- compare/org/eclipse/compare/internal/ICompareUIConstants.java 3 Mar 2008 13:30:41 -0000 1.13 +++ compare/org/eclipse/compare/internal/ICompareUIConstants.java 10 Dec 2008 13:49:08 -0000 @@ -49,4 +49,6 @@ public static final String PREF_VALUE_NEXT = "next"; //$NON-NLS-1$ public static final String COMMAND_IGNORE_WHITESPACE = PREFIX + "ignoreWhiteSpace"; //$NON-NLS-1$ + + public final String IMG_WIZBAN_DIFF = "wizban/createpatch_wizban.png"; //$NON-NLS-1$ } Index: compare/org/eclipse/compare/internal/MergeSourceViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeSourceViewer.java,v retrieving revision 1.46 diff -u -r1.46 MergeSourceViewer.java --- compare/org/eclipse/compare/internal/MergeSourceViewer.java 14 Oct 2008 08:29:40 -0000 1.46 +++ compare/org/eclipse/compare/internal/MergeSourceViewer.java 10 Dec 2008 13:49:08 -0000 @@ -99,6 +99,7 @@ public static final String SAVE_ID= "save"; //$NON-NLS-1$ public static final String FIND_ID= "find"; //$NON-NLS-1$ public static final String GOTO_LINE_ID= "gotoLine"; //$NON-NLS-1$ + public static final String CREATE_PATCH_ID= "createPatch"; //$NON-NLS-1$ class TextOperationAction extends MergeViewerAction { @@ -789,6 +790,7 @@ addMenu(menu, SELECT_ALL_ID); menu.add(new Separator("edit")); //$NON-NLS-1$ + addMenu(menu, CREATE_PATCH_ID); menu.add(new Separator("find")); //$NON-NLS-1$ addMenu(menu, FIND_ID); Index: compare/org/eclipse/compare/internal/merge/DocumentMerger.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java,v retrieving revision 1.7 diff -u -r1.7 DocumentMerger.java --- compare/org/eclipse/compare/internal/merge/DocumentMerger.java 28 Feb 2008 16:47:01 -0000 1.7 +++ compare/org/eclipse/compare/internal/merge/DocumentMerger.java 10 Dec 2008 13:49:09 -0000 @@ -1343,5 +1343,9 @@ } return null; } - + + public ArrayList getAllDiffs() { + return fAllDiffs; + } + } Index: compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java,v retrieving revision 1.237 diff -u -r1.237 TextMergeViewer.java --- compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java 27 Nov 2008 16:44:59 -0000 1.237 +++ compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java 10 Dec 2008 13:49:08 -0000 @@ -43,6 +43,7 @@ import org.eclipse.compare.internal.CompareMessages; import org.eclipse.compare.internal.ComparePreferencePage; import org.eclipse.compare.internal.CompareUIPlugin; +import org.eclipse.compare.internal.CreatePatchAction; import org.eclipse.compare.internal.DocumentManager; import org.eclipse.compare.internal.ICompareContextIds; import org.eclipse.compare.internal.ICompareUIConstants; @@ -170,195 +171,192 @@ /** * A text merge viewer uses the RangeDifferencer to perform a - * textual, line-by-line comparison of two (or three) input documents. - * It is based on the ContentMergeViewer and uses TextViewers - * to implement the ancestor, left, and right content areas. + * textual, line-by-line comparison of two (or three) input documents. It is + * based on the ContentMergeViewer and uses TextViewer + * s to implement the ancestor, left, and right content areas. *

- * In the three-way compare case ranges of differing lines are highlighted and framed - * with different colors to show whether the difference is an incoming, outgoing, or conflicting change. - * The TextMergeViewer supports the notion of a current "differing range" - * and provides toolbar buttons to navigate from one range to the next (or previous). + * In the three-way compare case ranges of differing lines are highlighted and + * framed with different colors to show whether the difference is an incoming, + * outgoing, or conflicting change. The TextMergeViewer supports + * the notion of a current "differing range" and provides toolbar buttons to + * navigate from one range to the next (or previous). *

- * If there is a current "differing range" and the underlying document is editable - * the TextMergeViewer enables actions in context menu and toolbar to - * copy a range from one side to the other side, thereby performing a merge operation. + * If there is a current "differing range" and the underlying document is + * editable the TextMergeViewer enables actions in context menu and + * toolbar to copy a range from one side to the other side, thereby performing a + * merge operation. *

* In addition to a line-by-line comparison the TextMergeViewer - * uses a token based compare on differing lines. - * The token compare is activated when navigating into - * a range of differing lines. At first the lines are selected as a block. - * When navigating into this block the token compare shows for every line - * the differing token by selecting them. + * uses a token based compare on differing lines. The token compare is activated + * when navigating into a range of differing lines. At first the lines are + * selected as a block. When navigating into this block the token compare shows + * for every line the differing token by selecting them. *

- * The TextMergeViewer's default token compare works on characters separated - * by whitespace. If a different strategy is needed (for example, Java tokens in - * a Java-aware merge viewer), clients can create their own token - * comparators by implementing the ITokenComparator interface and overriding the - * TextMergeViewer.createTokenComparator factory method). + * The TextMergeViewer's default token compare works on characters + * separated by whitespace. If a different strategy is needed (for example, Java + * tokens in a Java-aware merge viewer), clients can create their own token + * comparators by implementing the ITokenComparator interface and + * overriding the TextMergeViewer.createTokenComparator factory + * method). *

* Access to the TextMergeViewer's model is by means of an - * IMergeViewerContentProvider. Its getXContent methods must return - * either an IDocument, an IDocumentRange, or an IStreamContentAccessor. - * In the IDocumentRange case the TextMergeViewer - * works on a subrange of a document. In the IStreamContentAccessor case + * IMergeViewerContentProvider. Its getX + * Content methods must return either an IDocument, an + * IDocumentRange, or an IStreamContentAccessor. In + * the IDocumentRange case the TextMergeViewer works + * on a subrange of a document. In the IStreamContentAccessor case * a document is created internally and initialized from the stream. *

- * A TextMergeViewer can be used as is. However clients may subclass - * to customize the behavior. For example a MergeTextViewer for Java would override - * the configureTextViewer method to configure the TextViewer for Java source code, - * the createTokenComparator method to create a Java specific tokenizer. - * + * A TextMergeViewer can be used as is. However clients may + * subclass to customize the behavior. For example a + * MergeTextViewer for Java would override the + * configureTextViewer method to configure the + * TextViewer for Java source code, the + * createTokenComparator method to create a Java specific + * tokenizer. + * * @see org.eclipse.compare.rangedifferencer.RangeDifferencer * @see org.eclipse.jface.text.TextViewer * @see ITokenComparator * @see IDocumentRange * @see org.eclipse.compare.IStreamContentAccessor */ -public class TextMergeViewer extends ContentMergeViewer implements IAdaptable { - +public class TextMergeViewer extends ContentMergeViewer implements IAdaptable { + private static final String COPY_LEFT_TO_RIGHT_INDICATOR = ">"; //$NON-NLS-1$ private static final String COPY_RIGHT_TO_LEFT_INDICATOR = "<"; //$NON-NLS-1$ private static final char ANCESTOR_CONTRIBUTOR = MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR; private static final char RIGHT_CONTRIBUTOR = MergeViewerContentProvider.RIGHT_CONTRIBUTOR; private static final char LEFT_CONTRIBUTOR = MergeViewerContentProvider.LEFT_CONTRIBUTOR; - - private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$ - static final boolean DEBUG= false; - - private static final boolean FIX_47640= true; - - private static final String[] GLOBAL_ACTIONS= { - ActionFactory.UNDO.getId(), - ActionFactory.REDO.getId(), - ActionFactory.CUT.getId(), - ActionFactory.COPY.getId(), - ActionFactory.PASTE.getId(), - ActionFactory.DELETE.getId(), - ActionFactory.SELECT_ALL.getId(), - ActionFactory.SAVE.getId(), - ActionFactory.FIND.getId(), - ITextEditorActionDefinitionIds.LINE_GOTO - }; - private static final String[] TEXT_ACTIONS= { - MergeSourceViewer.UNDO_ID, - MergeSourceViewer.REDO_ID, - MergeSourceViewer.CUT_ID, - MergeSourceViewer.COPY_ID, - MergeSourceViewer.PASTE_ID, - MergeSourceViewer.DELETE_ID, - MergeSourceViewer.SELECT_ALL_ID, - MergeSourceViewer.SAVE_ID, - MergeSourceViewer.FIND_ID, - MergeSourceViewer.GOTO_LINE_ID - }; - - private static final String BUNDLE_NAME= "org.eclipse.compare.contentmergeviewer.TextMergeViewerResources"; //$NON-NLS-1$ - - // the following symbolic constants must match the IDs in Compare's plugin.xml - private static final String INCOMING_COLOR= "INCOMING_COLOR"; //$NON-NLS-1$ - private static final String OUTGOING_COLOR= "OUTGOING_COLOR"; //$NON-NLS-1$ - private static final String CONFLICTING_COLOR= "CONFLICTING_COLOR"; //$NON-NLS-1$ - private static final String RESOLVED_COLOR= "RESOLVED_COLOR"; //$NON-NLS-1$ - + private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$ + + static final boolean DEBUG = false; + + private static final boolean FIX_47640 = true; + + private static final String[] GLOBAL_ACTIONS = { + ActionFactory.UNDO.getId(), ActionFactory.REDO.getId(), + ActionFactory.CUT.getId(), ActionFactory.COPY.getId(), + ActionFactory.PASTE.getId(), ActionFactory.DELETE.getId(), + ActionFactory.SELECT_ALL.getId(), ActionFactory.SAVE.getId(), + ActionFactory.FIND.getId(), + ITextEditorActionDefinitionIds.LINE_GOTO }; + private static final String[] TEXT_ACTIONS = { MergeSourceViewer.UNDO_ID, + MergeSourceViewer.REDO_ID, MergeSourceViewer.CUT_ID, + MergeSourceViewer.COPY_ID, MergeSourceViewer.PASTE_ID, + MergeSourceViewer.DELETE_ID, MergeSourceViewer.SELECT_ALL_ID, + MergeSourceViewer.SAVE_ID, MergeSourceViewer.FIND_ID, + MergeSourceViewer.GOTO_LINE_ID }; + + private static final String BUNDLE_NAME = "org.eclipse.compare.contentmergeviewer.TextMergeViewerResources"; //$NON-NLS-1$ + + // the following symbolic constants must match the IDs in Compare's + // plugin.xml + private static final String INCOMING_COLOR = "INCOMING_COLOR"; //$NON-NLS-1$ + private static final String OUTGOING_COLOR = "OUTGOING_COLOR"; //$NON-NLS-1$ + private static final String CONFLICTING_COLOR = "CONFLICTING_COLOR"; //$NON-NLS-1$ + private static final String RESOLVED_COLOR = "RESOLVED_COLOR"; //$NON-NLS-1$ + // constants /** Width of left and right vertical bar */ - private static final int MARGIN_WIDTH= 6; + private static final int MARGIN_WIDTH = 6; /** Width of center bar */ - private static final int CENTER_WIDTH= 34; + private static final int CENTER_WIDTH = 34; /** Width of birds eye view */ - private static final int BIRDS_EYE_VIEW_WIDTH= 12; + private static final int BIRDS_EYE_VIEW_WIDTH = 12; /** Width of birds eye view */ - private static final int BIRDS_EYE_VIEW_INSET= 2; + private static final int BIRDS_EYE_VIEW_INSET = 2; /** */ - private static final int RESOLVE_SIZE= 5; + private static final int RESOLVE_SIZE = 5; /** line width of change borders */ - private static final int LW= 1; - - // determines whether a change between left and right is considered incoming or outgoing + private static final int LW = 1; + + // determines whether a change between left and right is considered incoming + // or outgoing private boolean fLeftIsLocal; - private boolean fShowCurrentOnly= false; - private boolean fShowCurrentOnly2= false; - private int fMarginWidth= MARGIN_WIDTH; + private boolean fShowCurrentOnly = false; + private boolean fShowCurrentOnly2 = false; + private int fMarginWidth = MARGIN_WIDTH; private int fTopInset; - + // Colors private RGB fBackground; private RGB fForeground; - private boolean fIsUsingSystemForeground= true; - private boolean fIsUsingSystemBackground= true; - + private boolean fIsUsingSystemForeground = true; + private boolean fIsUsingSystemBackground = true; + private RGB SELECTED_INCOMING; private RGB INCOMING; private RGB INCOMING_FILL; private RGB INCOMING_TEXT_FILL; - + private RGB SELECTED_CONFLICT; private RGB CONFLICT; private RGB CONFLICT_FILL; private RGB CONFLICT_TEXT_FILL; - + private RGB SELECTED_OUTGOING; private RGB OUTGOING; private RGB OUTGOING_FILL; private RGB OUTGOING_TEXT_FILL; - + private RGB RESOLVED; - + private IPreferenceStore fPreferenceStore; private IPropertyChangeListener fPreferenceChangeListener; - - private HashMap fNewAncestorRanges= new HashMap(); - private HashMap fNewLeftRanges= new HashMap(); - private HashMap fNewRightRanges= new HashMap(); - + + private HashMap fNewAncestorRanges = new HashMap(); + private HashMap fNewLeftRanges = new HashMap(); + private HashMap fNewRightRanges = new HashMap(); + private MergeSourceViewer fAncestor; private MergeSourceViewer fLeft; private MergeSourceViewer fRight; - + private int fLeftLineCount; private int fRightLineCount; - + private boolean fInScrolling; - - private int fPts[]= new int[8]; // scratch area for polygon drawing - - private int fInheritedDirection; // inherited direction - private int fTextDirection; // requested direction for embedded SourceViewer - + + private int fPts[] = new int[8]; // scratch area for polygon drawing + + private int fInheritedDirection; // inherited direction + private int fTextDirection; // requested direction for embedded SourceViewer + private ActionContributionItem fIgnoreAncestorItem; private boolean fHighlightRanges; - - private boolean fShowPseudoConflicts= false; - - private boolean fUseSplines= true; - private boolean fUseSingleLine= true; - private boolean fUseResolveUI= true; + + private boolean fShowPseudoConflicts = false; + + private boolean fUseSplines = true; + private boolean fUseSingleLine = true; + private boolean fUseResolveUI = true; private boolean fHighlightTokenChanges = false; private String fSymbolicFontName; - private ActionContributionItem fNextDiff; // goto next difference - private ActionContributionItem fPreviousDiff; // goto previous difference + private ActionContributionItem fNextDiff; // goto next difference + private ActionContributionItem fPreviousDiff; // goto previous difference private ActionContributionItem fCopyDiffLeftToRightItem; private ActionContributionItem fCopyDiffRightToLeftItem; - + private CompareHandlerService fHandlerService; - - private boolean fSynchronizedScrolling= true; - private boolean fShowMoreInfo= false; - + + private boolean fSynchronizedScrolling = true; + private boolean fShowMoreInfo = false; + private MergeSourceViewer fFocusPart; - - private boolean fSubDoc= true; + + private boolean fSubDoc = true; private IPositionUpdater fPositionUpdater; private boolean fIsMotif; private boolean fIsCarbon; - + private boolean fHasErrors; - // SWT widgets private BufferedCanvas fAncestorCanvas; @@ -369,14 +367,14 @@ private Canvas fBirdsEyeCanvas; private Canvas fSummaryHeader; private HeaderPainter fHeaderPainter; - + // SWT resources to be disposed private Map fColors; private Cursor fBirdsEyeCursor; - + // points for center curves private double[] fBasicCenterCurve; - + private Button fCenterButton; private Diff fButtonDiff; @@ -395,37 +393,40 @@ private DocumentMerger fMerger; /** The current diff */ private Diff fCurrentDiff; - + /** * Preference key for highlighting current line. */ - private final static String CURRENT_LINE= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE; + private final static String CURRENT_LINE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE; /** * Preference key for highlight color of current line. */ - private final static String CURRENT_LINE_COLOR= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR; - + private final static String CURRENT_LINE_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR; + private List fSourceViewerDecorationSupport = new ArrayList(3); - private final class InternalOutlineViewerCreator extends OutlineViewerCreator implements ISelectionChangedListener { + private final class InternalOutlineViewerCreator extends + OutlineViewerCreator implements ISelectionChangedListener { public Viewer findStructureViewer(Viewer oldViewer, ICompareInput input, Composite parent, CompareConfiguration configuration) { if (input != getInput()) return null; - final Viewer v = CompareUI.findStructureViewer(oldViewer, input, parent, configuration); + final Viewer v = CompareUI.findStructureViewer(oldViewer, input, + parent, configuration); if (v != null) { v.getControl().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { - v.removeSelectionChangedListener(InternalOutlineViewerCreator.this); + v + .removeSelectionChangedListener(InternalOutlineViewerCreator.this); } }); v.addSelectionChangedListener(this); } - + return v; } - + public boolean hasViewerFor(Object input) { return true; } @@ -453,9 +454,10 @@ } return null; } - - private Diff findDiff(Position p, boolean left) { - for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) { + + private Diff findDiff(Position p, boolean left) { + for (Iterator iterator = fMerger.rangesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); Position diffPos; if (left) { @@ -464,9 +466,11 @@ diffPos = diff.getPosition(RIGHT_CONTRIBUTOR); } // If the element falls within a diff, highlight that diff - if (diffPos.offset + diffPos.length >= p.offset && diff.getKind() != RangeDifference.NOCHANGE) + if (diffPos.offset + diffPos.length >= p.offset + && diff.getKind() != RangeDifference.NOCHANGE) return diff; - // Otherwise, highlight the first diff after the elements position + // Otherwise, highlight the first diff after the elements + // position if (diffPos.offset >= p.offset) return diff; } @@ -486,7 +490,8 @@ } } - class ContributorInfo implements IElementStateListener, VerifyListener, IDocumentListener { + class ContributorInfo implements IElementStateListener, VerifyListener, + IDocumentListener { private final TextMergeViewer fViewer; private final Object fElement; private char fLeg; @@ -497,20 +502,21 @@ private int fTopIndex = -1; private boolean fNeedsValidation = false; private MergeSourceViewer fSourceViewer; - + public ContributorInfo(TextMergeViewer viewer, Object element, char leg) { fViewer = viewer; fElement = element; fLeg = leg; if (fElement instanceof IEncodedStreamContentAccessor) { try { - fEncoding = ((IEncodedStreamContentAccessor)fElement).getCharset(); + fEncoding = ((IEncodedStreamContentAccessor) fElement) + .getCharset(); } catch (CoreException e) { // silently ignored } } } - + public String getEncoding() { if (fEncoding == null) return ResourcesPlugin.getEncoding(); @@ -521,10 +527,11 @@ if (fEncoding == null) fEncoding = otherContributor.fEncoding; } - + public IDocument getDocument() { if (fDocumentProvider != null) { - IDocument document = fDocumentProvider.getDocument(getDocumentKey()); + IDocument document = fDocumentProvider + .getDocument(getDocumentKey()); if (document != null) return document; } @@ -536,7 +543,7 @@ return DocumentManager.get(fElement); return null; } - + public void setDocument(MergeSourceViewer viewer, boolean isEditable) { // Ensure that this method is only called once Assert.isTrue(fSourceViewer == null); @@ -544,7 +551,8 @@ try { internalSetDocument(viewer); } catch (RuntimeException e) { - // The error may be due to a stale entry in the DocumentManager (see bug 184489) + // The error may be due to a stale entry in the DocumentManager + // (see bug 184489) clearCachedDocument(); throw e; } @@ -555,81 +563,96 @@ viewer.getTextWidget().addVerifyListener(this); } } - + /* * Returns true if a new Document could be installed. */ private boolean internalSetDocument(MergeSourceViewer tp) { - + if (tp == null) return false; - + IDocument newDocument = null; - Position range= null; + Position range = null; if (fElement instanceof IDocumentRange) { - newDocument= ((IDocumentRange)fElement).getDocument(); - range= ((IDocumentRange)fElement).getRange(); + newDocument = ((IDocumentRange) fElement).getDocument(); + range = ((IDocumentRange) fElement).getRange(); connectToSharedDocument(); } else if (fElement instanceof IDocument) { - newDocument= (IDocument) fElement; - + newDocument = (IDocument) fElement; + } else if (fElement instanceof IStreamContentAccessor) { - newDocument= DocumentManager.get(fElement); + newDocument = DocumentManager.get(fElement); if (newDocument == null) { newDocument = createDocument(); DocumentManager.put(fElement, newDocument); setupDocument(newDocument); } else if (fDocumentProvider == null) { - // Connect to a shared document so we can get the proper save synchronization + // Connect to a shared document so we can get the proper + // save synchronization connectToSharedDocument(); } - } else if (fElement == null) { // deletion on one side - - ITypedElement parent= this.fViewer.getParent(fLeg); // we try to find an insertion position within the deletion's parent - + } else if (fElement == null) { // deletion on one side + + ITypedElement parent = this.fViewer.getParent(fLeg); // we try + // to + // find + // an + // insertion + // position + // within + // the + // deletion's + // parent + if (parent instanceof IDocumentRange) { - newDocument= ((IDocumentRange)parent).getDocument(); + newDocument = ((IDocumentRange) parent).getDocument(); newDocument.addPositionCategory(DIFF_RANGE_CATEGORY); - Object input= this.fViewer.getInput(); - range= this.fViewer.getNewRange(fLeg, input); + Object input = this.fViewer.getInput(); + range = this.fViewer.getNewRange(fLeg, input); if (range == null) { - int pos= 0; + int pos = 0; if (input instanceof ICompareInput) - pos= this.fViewer.findInsertionPosition(fLeg, (ICompareInput)input); - range= new Position(pos, 0); + pos = this.fViewer.findInsertionPosition(fLeg, + (ICompareInput) input); + range = new Position(pos, 0); try { newDocument.addPosition(DIFF_RANGE_CATEGORY, range); } catch (BadPositionCategoryException ex) { // silently ignored - if (TextMergeViewer.DEBUG) System.out.println("BadPositionCategoryException: " + ex); //$NON-NLS-1$ + if (TextMergeViewer.DEBUG) + System.out + .println("BadPositionCategoryException: " + ex); //$NON-NLS-1$ } catch (BadLocationException ex) { // silently ignored - if (TextMergeViewer.DEBUG) System.out.println("BadLocationException: " + ex); //$NON-NLS-1$ + if (TextMergeViewer.DEBUG) + System.out + .println("BadLocationException: " + ex); //$NON-NLS-1$ } this.fViewer.addNewRange(fLeg, input, range); } } else if (parent instanceof IDocument) { - newDocument= ((IDocumentRange)fElement).getDocument(); + newDocument = ((IDocumentRange) fElement).getDocument(); } } - boolean enabled= true; + boolean enabled = true; if (newDocument == null) { - newDocument= new Document(""); //$NON-NLS-1$ - enabled= false; + newDocument = new Document(""); //$NON-NLS-1$ + enabled = false; } - + // Update the viewer document or range - IDocument oldDoc= tp.getDocument(); + IDocument oldDoc = tp.getDocument(); if (newDocument != oldDoc) { updateViewerDocument(tp, newDocument, range); - } else { // same document but different range + } else { // same document but different range updateViewerDocumentRange(tp, range); } newDocument.addDocumentListener(this); - + tp.setEnabled(enabled); return enabled; @@ -638,11 +661,13 @@ /* * The viewer document is the same but the range has changed */ - private void updateViewerDocumentRange(MergeSourceViewer tp, Position range) { + private void updateViewerDocumentRange(MergeSourceViewer tp, + Position range) { tp.setRegion(range); if (this.fViewer.fSubDoc) { if (range != null) { - IRegion r= this.fViewer.normalizeDocumentRegion(tp.getDocument(), TextMergeViewer.toRegion(range)); + IRegion r = this.fViewer.normalizeDocumentRegion(tp + .getDocument(), TextMergeViewer.toRegion(range)); tp.setVisibleRegion(r.getOffset(), r.getLength()); } else tp.resetVisibleRegion(); @@ -653,15 +678,17 @@ /* * The viewer has a new document */ - private void updateViewerDocument(MergeSourceViewer tp, IDocument document, Position range) { + private void updateViewerDocument(MergeSourceViewer tp, + IDocument document, Position range) { unsetDocument(tp); if (document == null) return; - + // Add a position updater to the document document.addPositionCategory(DIFF_RANGE_CATEGORY); if (this.fViewer.fPositionUpdater == null) - this.fViewer.fPositionUpdater= this.fViewer.new ChildPositionUpdater(DIFF_RANGE_CATEGORY); + this.fViewer.fPositionUpdater = this.fViewer.new ChildPositionUpdater( + DIFF_RANGE_CATEGORY); else document.removePositionUpdater(this.fViewer.fPositionUpdater); document.addPositionUpdater(this.fViewer.fPositionUpdater); @@ -670,18 +697,19 @@ tp.setRegion(range); if (this.fViewer.fSubDoc) { if (range != null) { - IRegion r= this.fViewer.normalizeDocumentRegion(document, TextMergeViewer.toRegion(range)); + IRegion r = this.fViewer.normalizeDocumentRegion(document, + TextMergeViewer.toRegion(range)); tp.setDocument(document, r.getOffset(), r.getLength()); } else tp.setDocument(document); } else tp.setDocument(document); - + tp.rememberDocument(document); } - + private void unsetDocument(MergeSourceViewer tp) { - IDocument oldDoc= internalGetDocument(tp); + IDocument oldDoc = internalGetDocument(tp); if (oldDoc != null) { tp.rememberDocument(null); try { @@ -694,15 +722,16 @@ oldDoc.removeDocumentListener(this); } } - + private IDocument createDocument() { - // If the content provider is a text content provider, attempt to obtain + // If the content provider is a text content provider, attempt to + // obtain // a shared document (i.e. file buffer) IDocument newDoc = connectToSharedDocument(); - + if (newDoc == null) { - IStreamContentAccessor sca= (IStreamContentAccessor) fElement; - String s= null; + IStreamContentAccessor sca = (IStreamContentAccessor) fElement; + String s = null; try { String encoding = getEncoding(); @@ -711,16 +740,17 @@ this.fViewer.setError(fLeg, ex.getMessage()); } - newDoc= new Document(s != null ? s : ""); //$NON-NLS-1$ + newDoc = new Document(s != null ? s : ""); //$NON-NLS-1$ } return newDoc; } /** - * Connect to a shared document if possible. Return null - * if the connection was not possible. + * Connect to a shared document if possible. Return null if + * the connection was not possible. + * * @return the shared document or null if connection to a - * shared document was not possible + * shared document was not possible */ private IDocument connectToSharedDocument() { IEditorInput key = getDocumentKey(); @@ -733,31 +763,35 @@ if (documentProvider != null) { try { connect(documentProvider, key); - setCachedDocumentProvider(key, - documentProvider); + setCachedDocumentProvider(key, documentProvider); IDocument newDoc = documentProvider.getDocument(key); - this.fViewer.updateDirtyState(key, documentProvider, fLeg); + this.fViewer.updateDirtyState(key, documentProvider, + fLeg); return newDoc; } catch (CoreException e) { - // Connection failed. Log the error and continue without a shared document + // Connection failed. Log the error and continue without + // a shared document CompareUIPlugin.log(e); } } } return null; } - - private void connect(IDocumentProvider documentProvider, IEditorInput input) throws CoreException { - final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities.getAdapter(fElement, ISharedDocumentAdapter.class); + + private void connect(IDocumentProvider documentProvider, + IEditorInput input) throws CoreException { + final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities + .getAdapter(fElement, ISharedDocumentAdapter.class); if (sda != null) { sda.connect(documentProvider, input); } else { documentProvider.connect(input); } } - + private void disconnect(IDocumentProvider provider, IEditorInput input) { - final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities.getAdapter(fElement, ISharedDocumentAdapter.class); + final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities + .getAdapter(fElement, ISharedDocumentAdapter.class); if (sda != null) { sda.disconnect(provider, input); } else { @@ -771,11 +805,11 @@ fDocumentProvider = documentProvider; documentProvider.addElementStateListener(this); } - + public void disconnect() { IDocumentProvider provider = null; IEditorInput input = getDocumentKey(); - synchronized(this) { + synchronized (this) { if (fDocumentProvider != null) { provider = fDocumentProvider; fDocumentProvider = null; @@ -787,12 +821,13 @@ provider.removeElementStateListener(this); } // If we have a listener registered with the widget, remove it - if (fSourceViewer != null && !fSourceViewer.getTextWidget().isDisposed()) { + if (fSourceViewer != null + && !fSourceViewer.getTextWidget().isDisposed()) { if (fNeedsValidation) { fSourceViewer.getTextWidget().removeVerifyListener(this); fNeedsValidation = false; } - IDocument oldDoc= internalGetDocument(fSourceViewer); + IDocument oldDoc = internalGetDocument(fSourceViewer); if (oldDoc != null) { oldDoc.removeDocumentListener(this); } @@ -806,41 +841,48 @@ if (doc != null) DocumentManager.remove(doc); } - + private IDocument internalGetDocument(MergeSourceViewer tp) { - IDocument oldDoc= tp.getDocument(); + IDocument oldDoc = tp.getDocument(); if (oldDoc == null) { - oldDoc= tp.getRememberedDocument(); + oldDoc = tp.getRememberedDocument(); } return oldDoc; } - + /** - * Return the document key used to obtain a shared document. A null - * is returned in the following cases: + * Return the document key used to obtain a shared document. A + * null is returned in the following cases: *

    *
  1. This contributor does not have a shared document adapter.
  2. - *
  3. This text merge viewer has a document partitioner but uses the default partitioning.
  4. + *
  5. This text merge viewer has a document partitioner but uses the + * default partitioning.
  6. *
  7. This text merge viewer does not use he default content provider.
  8. *
- * @return the document key used to obtain a shared document or null + * + * @return the document key used to obtain a shared document or + * null */ private IEditorInput getDocumentKey() { if (fDocumentKey != null) return fDocumentKey; - if (isUsingDefaultContentProvider() && fElement != null && canHaveSharedDocument()) { - ISharedDocumentAdapter sda = (ISharedDocumentAdapter)Utilities.getAdapter(fElement, ISharedDocumentAdapter.class, true); + if (isUsingDefaultContentProvider() && fElement != null + && canHaveSharedDocument()) { + ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities + .getAdapter(fElement, ISharedDocumentAdapter.class, + true); if (sda != null) { return sda.getDocumentKey(fElement); } } return null; } - + private IDocumentProvider getDocumentProvider() { if (fDocumentProvider != null) return fDocumentProvider; - // We will only use document providers if the content provider is the + // We will only use document providers if the content provider is + // the // default content provider if (isUsingDefaultContentProvider()) { IEditorInput input = getDocumentKey(); @@ -853,30 +895,33 @@ private boolean isUsingDefaultContentProvider() { return fViewer.isUsingDefaultContentProvider(); } - + private boolean canHaveSharedDocument() { return fViewer.canHaveSharedDocument(); } - + boolean hasSharedDocument(Object object) { - return (fElement == object && - fDocumentProvider != null - && fDocumentProvider.getDocument(getDocumentKey()) != null); + return (fElement == object && fDocumentProvider != null && fDocumentProvider + .getDocument(getDocumentKey()) != null); } - + public boolean flush() throws CoreException { if (fDocumentProvider != null) { IEditorInput input = getDocumentKey(); IDocument document = fDocumentProvider.getDocument(input); if (document != null) { - final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities.getAdapter(fElement, ISharedDocumentAdapter.class); + final ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utilities + .getAdapter(fElement, ISharedDocumentAdapter.class); if (sda != null) { - sda.flushDocument(fDocumentProvider, input, document, false); + sda.flushDocument(fDocumentProvider, input, document, + false); return true; } try { fDocumentProvider.aboutToChange(input); - fDocumentProvider.saveDocument(new NullProgressMonitor(), input, document, false); + fDocumentProvider.saveDocument( + new NullProgressMonitor(), input, document, + false); return true; } finally { fDocumentProvider.changed(input); @@ -885,7 +930,7 @@ } return false; } - + public void elementMoved(Object originalElement, Object movedElement) { IEditorInput input = getDocumentKey(); if (input != null && input.equals(originalElement)) { @@ -893,12 +938,14 @@ resetDocument(); } } + public void elementDirtyStateChanged(Object element, boolean isDirty) { if (!checkState()) return; IEditorInput input = getDocumentKey(); if (input != null && input.equals(element)) { - this.fViewer.updateDirtyState(input, getDocumentProvider(), fLeg); + this.fViewer.updateDirtyState(input, getDocumentProvider(), + fLeg); } } @@ -909,12 +956,15 @@ resetDocument(); } } + private void resetDocument() { // Need to remove the document from the manager before refreshing // or the old document will still be found clearCachedDocument(); - // TODO: This is fine for now but may need to be revisited if a refresh is performed - // higher up as well (e.g. perhaps a refresh request that waits until after all parties + // TODO: This is fine for now but may need to be revisited if a + // refresh is performed + // higher up as well (e.g. perhaps a refresh request that waits + // until after all parties // have been notified). if (checkState()) fViewer.refresh(); @@ -934,9 +984,11 @@ return; IEditorInput input = getDocumentKey(); if (input != null && input.equals(element)) { - this.fViewer.updateDirtyState(input, getDocumentProvider(), fLeg); + this.fViewer.updateDirtyState(input, getDocumentProvider(), + fLeg); } } + public void elementContentAboutToBeReplaced(Object element) { // Nothing to do } @@ -955,7 +1007,8 @@ } } - public void updateSelection(MergeSourceViewer viewer, boolean includeScroll) { + public void updateSelection(MergeSourceViewer viewer, + boolean includeScroll) { if (fSelection != null) viewer.setSelection(fSelection); if (includeScroll && fTopIndex != -1) { @@ -963,38 +1016,45 @@ } } - public void transferContributorStateFrom( - ContributorInfo oldContributor) { + public void transferContributorStateFrom(ContributorInfo oldContributor) { if (oldContributor != null) { fSelection = oldContributor.fSelection; fTopIndex = oldContributor.fTopIndex; } - + } public boolean validateChange() { if (fElement == null) return true; if (fDocumentProvider instanceof IDocumentProviderExtension) { - IDocumentProviderExtension ext = (IDocumentProviderExtension)fDocumentProvider; + IDocumentProviderExtension ext = (IDocumentProviderExtension) fDocumentProvider; if (ext.isReadOnly(fDocumentKey)) { try { - ext.validateState(fDocumentKey, getControl().getShell()); + ext + .validateState(fDocumentKey, getControl() + .getShell()); ext.updateStateCache(fDocumentKey); } catch (CoreException e) { - ErrorDialog.openError(getControl().getShell(), CompareMessages.TextMergeViewer_12, CompareMessages.TextMergeViewer_13, e.getStatus()); + ErrorDialog.openError(getControl().getShell(), + CompareMessages.TextMergeViewer_12, + CompareMessages.TextMergeViewer_13, e + .getStatus()); return false; } } return !ext.isReadOnly(fDocumentKey); } - IEditableContentExtension ext = (IEditableContentExtension)Utilities.getAdapter(fElement, IEditableContentExtension.class); + IEditableContentExtension ext = (IEditableContentExtension) Utilities + .getAdapter(fElement, IEditableContentExtension.class); if (ext != null) { if (ext.isReadOnly()) { IStatus status = ext.validateEdit(getControl().getShell()); if (!status.isOK()) { if (status.getSeverity() == IStatus.ERROR) { - ErrorDialog.openError(getControl().getShell(), CompareMessages.TextMergeViewer_14, CompareMessages.TextMergeViewer_15, status); + ErrorDialog.openError(getControl().getShell(), + CompareMessages.TextMergeViewer_14, + CompareMessages.TextMergeViewer_15, status); return false; } if (status.getSeverity() == IStatus.CANCEL) @@ -1005,24 +1065,36 @@ return true; } - /* (non-Javadoc) - * @see org.eclipse.swt.events.VerifyListener#verifyText(org.eclipse.swt.events.VerifyEvent) + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.events.VerifyListener#verifyText(org.eclipse.swt. + * events.VerifyEvent) */ public void verifyText(VerifyEvent e) { if (!validateChange()) { - e.doit= false; + e.doit = false; } } - - /* (non-Javadoc) - * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged + * (org.eclipse.jface.text.DocumentEvent) */ public void documentAboutToBeChanged(DocumentEvent e) { // nothing to do } - - /* (non-Javadoc) - * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse + * .jface.text.DocumentEvent) */ public void documentChanged(DocumentEvent e) { boolean dirty = true; @@ -1031,80 +1103,86 @@ } TextMergeViewer.this.documentChanged(e, dirty); // Remove our verify listener since the document is now dirty - if (fNeedsValidation && fSourceViewer != null && !fSourceViewer.getTextWidget().isDisposed()) { + if (fNeedsValidation && fSourceViewer != null + && !fSourceViewer.getTextWidget().isDisposed()) { fSourceViewer.getTextWidget().removeVerifyListener(this); fNeedsValidation = false; } } } - + class HeaderPainter implements PaintListener { - - private static final int INSET= BIRDS_EYE_VIEW_INSET; + + private static final int INSET = BIRDS_EYE_VIEW_INSET; private RGB fIndicatorColor; private Color fSeparatorColor; - + public HeaderPainter() { - fSeparatorColor= fSummaryHeader.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); + fSeparatorColor = fSummaryHeader.getDisplay().getSystemColor( + SWT.COLOR_WIDGET_NORMAL_SHADOW); } - + /* * Returns true on color change */ public boolean setColor(RGB color) { - RGB oldColor= fIndicatorColor; - fIndicatorColor= color; + RGB oldColor = fIndicatorColor; + fIndicatorColor = color; if (color == null) return oldColor != null; if (oldColor != null) return !color.equals(oldColor); return true; } - - private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topLeft, Color bottomRight) { + + private void drawBevelRect(GC gc, int x, int y, int w, int h, + Color topLeft, Color bottomRight) { gc.setForeground(topLeft); - gc.drawLine(x, y, x + w -1, y); - gc.drawLine(x, y, x, y + h -1); - + gc.drawLine(x, y, x + w - 1, y); + gc.drawLine(x, y, x, y + h - 1); + gc.setForeground(bottomRight); gc.drawLine(x + w, y, x + w, y + h); gc.drawLine(x, y + h, x + w, y + h); } - + public void paintControl(PaintEvent e) { - - Point s= fSummaryHeader.getSize(); - + + Point s = fSummaryHeader.getSize(); + if (fIndicatorColor != null) { - Display d= fSummaryHeader.getDisplay(); + Display d = fSummaryHeader.getDisplay(); e.gc.setBackground(getColor(d, fIndicatorColor)); - int min= Math.min(s.x, s.y)-2*INSET; - Rectangle r= new Rectangle((s.x-min)/2, (s.y-min)/2, min, min); + int min = Math.min(s.x, s.y) - 2 * INSET; + Rectangle r = new Rectangle((s.x - min) / 2, (s.y - min) / 2, + min, min); e.gc.fillRectangle(r); if (d != null) - drawBevelRect(e.gc, r.x, r.y, r.width -1, r.height -1, d.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), d.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); + drawBevelRect(e.gc, r.x, r.y, r.width - 1, r.height - 1, d + .getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), d + .getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); e.gc.setForeground(fSeparatorColor); e.gc.setLineWidth(0 /* 1 */); - e.gc.drawLine(0+1, s.y-1, s.x-1-1, s.y-1); + e.gc.drawLine(0 + 1, s.y - 1, s.x - 1 - 1, s.y - 1); } } } /* - * The position updater used to adapt the positions representing - * the child document ranges to changes of the parent document. + * The position updater used to adapt the positions representing the child + * document ranges to changes of the parent document. */ class ChildPositionUpdater extends DefaultPositionUpdater { - + /* * Creates the position updated. */ protected ChildPositionUpdater(String category) { super(category); } - + /* * Child document ranges cannot be deleted other then by calling * freeChildDocument. @@ -1112,7 +1190,7 @@ protected boolean notDeleted() { return true; } - + /* * If an insertion happens at a child document's start offset, the * position is extended rather than shifted. Also, if something is added @@ -1120,19 +1198,20 @@ * than kept stable. */ protected void adaptToInsert() { - - if (fPosition == fLeft.getRegion() || fPosition == fRight.getRegion()) { - int myStart= fPosition.offset; - int myEnd= fPosition.offset + fPosition.length; - myEnd= Math.max(myStart, myEnd); - - int yoursStart= fOffset; - int yoursEnd= fOffset + fReplaceLength -1; - yoursEnd= Math.max(yoursStart, yoursEnd); - + + if (fPosition == fLeft.getRegion() + || fPosition == fRight.getRegion()) { + int myStart = fPosition.offset; + int myEnd = fPosition.offset + fPosition.length; + myEnd = Math.max(myStart, myEnd); + + int yoursStart = fOffset; + int yoursEnd = fOffset + fReplaceLength - 1; + yoursEnd = Math.max(yoursStart, yoursEnd); + if (myEnd < yoursStart) return; - + if (myStart <= yoursStart) fPosition.length += fReplaceLength; else @@ -1142,7 +1221,7 @@ } } } - + private class ChangeHighlighter implements ITextPresentationListener { private final MergeSourceViewer viewer; @@ -1151,13 +1230,17 @@ this.viewer = viewer; } - /* (non-Javadoc) - * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation) + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation + * (org.eclipse.jface.text.TextPresentation) */ public void applyTextPresentation(TextPresentation textPresentation) { if (!fHighlightTokenChanges) return; - IRegion region= textPresentation.getExtent(); + IRegion region = textPresentation.getExtent(); Diff[] changeDiffs = fMerger.getChangeDiffs(getLeg(viewer), region); for (int i = 0; i < changeDiffs.length; i++) { Diff diff = changeDiffs[i]; @@ -1168,7 +1251,7 @@ } private StyleRange getStyleRange(Diff diff, IRegion region) { - //Color cText = getColor(null, getTextColor()); + // Color cText = getColor(null, getTextColor()); Color cTextFill = getColor(null, getTextFillColor(diff)); if (cTextFill == null) return null; @@ -1187,10 +1270,10 @@ } if (length < 0) return null; - + return new StyleRange(start, length, null, cTextFill); } - + private RGB getTextFillColor(Diff diff) { if (isThreeWay() && !isIgnoreAncestor()) { switch (diff.getKind()) { @@ -1211,9 +1294,9 @@ } return OUTGOING_TEXT_FILL; } - + } - + private class FindReplaceTarget implements IFindReplaceTarget { public boolean canPerformFind() { @@ -1222,7 +1305,9 @@ public int findAndSelect(int widgetOffset, String findString, boolean searchForward, boolean caseSensitive, boolean wholeWord) { - return fFocusPart.getFindReplaceTarget().findAndSelect(widgetOffset, findString, searchForward, caseSensitive, wholeWord); + return fFocusPart.getFindReplaceTarget().findAndSelect( + widgetOffset, findString, searchForward, caseSensitive, + wholeWord); } public Point getSelection() { @@ -1240,38 +1325,46 @@ public void replaceSelection(String text) { fFocusPart.getFindReplaceTarget().replaceSelection(text); } - + } - //---- MergeTextViewer - + // ---- MergeTextViewer + /** * Creates a text merge viewer under the given parent control. - * - * @param parent the parent control - * @param configuration the configuration object + * + * @param parent + * the parent control + * @param configuration + * the configuration object */ public TextMergeViewer(Composite parent, CompareConfiguration configuration) { this(parent, SWT.NULL, configuration); } - + /** * Creates a text merge viewer under the given parent control. - * - * @param parent the parent control - * @param style SWT style bits for top level composite of this viewer - * @param configuration the configuration object + * + * @param parent + * the parent control + * @param style + * SWT style bits for top level composite of this viewer + * @param configuration + * the configuration object */ - public TextMergeViewer(Composite parent, int style, CompareConfiguration configuration) { + public TextMergeViewer(Composite parent, int style, + CompareConfiguration configuration) { super(style, ResourceBundle.getBundle(BUNDLE_NAME), configuration); - + fMerger = new DocumentMerger(new IDocumentMergerInput() { public ITokenComparator createTokenComparator(String line) { return TextMergeViewer.this.createTokenComparator(line); } + public CompareConfiguration getCompareConfiguration() { return TextMergeViewer.this.getCompareConfiguration(); } + public IDocument getDocument(char contributor) { switch (contributor) { case LEFT_CONTRIBUTOR: @@ -1283,9 +1376,11 @@ } return null; } + public int getHunkStart() { return TextMergeViewer.this.getHunkStart(); } + public Position getRegion(char contributor) { switch (contributor) { case LEFT_CONTRIBUTOR: @@ -1297,13 +1392,17 @@ } return null; } + public boolean isHunkOnLeft() { - ITypedElement left = ((ICompareInput)getInput()).getRight(); - return left != null && Utilities.getAdapter(left, IHunk.class) != null; + ITypedElement left = ((ICompareInput) getInput()).getRight(); + return left != null + && Utilities.getAdapter(left, IHunk.class) != null; } + public boolean isIgnoreAncestor() { return TextMergeViewer.this.isIgnoreAncestor(); } + public boolean isPatchHunk() { return TextMergeViewer.this.isPatchHunk(); } @@ -1311,102 +1410,124 @@ public boolean isShowPseudoConflicts() { return fShowPseudoConflicts; } + public boolean isThreeWay() { return TextMergeViewer.this.isThreeWay(); } + public boolean isPatchHunkOk() { return TextMergeViewer.this.isPatchHunkOk(); } - + }); - - int inheritedStyle= parent.getStyle(); + + int inheritedStyle = parent.getStyle(); if ((inheritedStyle & SWT.LEFT_TO_RIGHT) != 0) - fInheritedDirection= SWT.LEFT_TO_RIGHT; + fInheritedDirection = SWT.LEFT_TO_RIGHT; else if ((inheritedStyle & SWT.RIGHT_TO_LEFT) != 0) - fInheritedDirection= SWT.RIGHT_TO_LEFT; + fInheritedDirection = SWT.RIGHT_TO_LEFT; else - fInheritedDirection= SWT.NONE; - + fInheritedDirection = SWT.NONE; + if ((style & SWT.LEFT_TO_RIGHT) != 0) - fTextDirection= SWT.LEFT_TO_RIGHT; + fTextDirection = SWT.LEFT_TO_RIGHT; else if ((style & SWT.RIGHT_TO_LEFT) != 0) - fTextDirection= SWT.RIGHT_TO_LEFT; + fTextDirection = SWT.RIGHT_TO_LEFT; else - fTextDirection= SWT.NONE; - - fSymbolicFontName= getSymbolicFontName(); - - String platform= SWT.getPlatform(); - fIsMotif= "motif".equals(platform); //$NON-NLS-1$ - fIsCarbon= "carbon".equals(platform); //$NON-NLS-1$ - + fTextDirection = SWT.NONE; + + fSymbolicFontName = getSymbolicFontName(); + + String platform = SWT.getPlatform(); + fIsMotif = "motif".equals(platform); //$NON-NLS-1$ + fIsCarbon = "carbon".equals(platform); //$NON-NLS-1$ + if (fIsMotif) - fMarginWidth= 0; - - fPreferenceChangeListener= new IPropertyChangeListener() { + fMarginWidth = 0; + + fPreferenceChangeListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { TextMergeViewer.this.handlePropertyChangeEvent(event); } }; - fPreferenceStore= createChainedPreferenceStore(); + fPreferenceStore = createChainedPreferenceStore(); if (fPreferenceStore != null) { - fPreferenceStore.addPropertyChangeListener(fPreferenceChangeListener); - - fLeftIsLocal= Utilities.getBoolean(getCompareConfiguration(), "LEFT_IS_LOCAL", false); //$NON-NLS-1$ - fSynchronizedScrolling= fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING); - fShowMoreInfo= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_MORE_INFO); - fShowPseudoConflicts= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS); - //fUseSplines= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES); - fUseSingleLine= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SINGLE_LINE); - fHighlightTokenChanges= fPreferenceStore.getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES); - //fUseResolveUI= fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI); + fPreferenceStore + .addPropertyChangeListener(fPreferenceChangeListener); + + fLeftIsLocal = Utilities.getBoolean(getCompareConfiguration(), + "LEFT_IS_LOCAL", false); //$NON-NLS-1$ + fSynchronizedScrolling = fPreferenceStore + .getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING); + fShowMoreInfo = fPreferenceStore + .getBoolean(ComparePreferencePage.SHOW_MORE_INFO); + fShowPseudoConflicts = fPreferenceStore + .getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS); + // fUseSplines= + // fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES); + fUseSingleLine = fPreferenceStore + .getBoolean(ComparePreferencePage.USE_SINGLE_LINE); + fHighlightTokenChanges = fPreferenceStore + .getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES); + // fUseResolveUI= + // fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI); } - + buildControl(parent); - + setColors(); - INavigatable nav= new INavigatable() { + INavigatable nav = new INavigatable() { public boolean selectChange(int flag) { - if (flag == INavigatable.FIRST_CHANGE || flag == INavigatable.LAST_CHANGE) { + if (flag == INavigatable.FIRST_CHANGE + || flag == INavigatable.LAST_CHANGE) { selectFirstDiff(flag == INavigatable.FIRST_CHANGE); return false; } return navigate(flag == INavigatable.NEXT_CHANGE, false, false); } + public Object getInput() { return TextMergeViewer.this.getInput(); } + public boolean openSelectedChange() { return false; } + public boolean hasChange(int flag) { - return getNextVisibleDiff(flag == INavigatable.NEXT_CHANGE, false) != null; + return getNextVisibleDiff(flag == INavigatable.NEXT_CHANGE, + false) != null; } }; fComposite.setData(INavigatable.NAVIGATOR_PROPERTY, nav); - - fBirdsEyeCursor= new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); - + + fBirdsEyeCursor = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); + JFaceResources.getFontRegistry().addListener(fPreferenceChangeListener); - JFaceResources.getColorRegistry().addListener(fPreferenceChangeListener); + JFaceResources.getColorRegistry() + .addListener(fPreferenceChangeListener); updateFont(); } - + private ChainedPreferenceStore createChainedPreferenceStore() { - ArrayList stores= new ArrayList(2); + ArrayList stores = new ArrayList(2); stores.add(getCompareConfiguration().getPreferenceStore()); stores.add(EditorsUI.getPreferenceStore()); - return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()])); - } - + return new ChainedPreferenceStore((IPreferenceStore[]) stores + .toArray(new IPreferenceStore[stores.size()])); + } + /** - * Creates a color from the information stored in the given preference store. - * Returns null if there is no such information available. - * @param store preference store - * @param key preference key + * Creates a color from the information stored in the given preference + * store. Returns null if there is no such information + * available. + * + * @param store + * preference store + * @param key + * preference key * @return the color or null */ private static RGB createColor(IPreferenceStore store, String key) { @@ -1418,31 +1539,35 @@ } private void setColors() { - fIsUsingSystemBackground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT); + fIsUsingSystemBackground = fPreferenceStore + .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT); if (!fIsUsingSystemBackground) - fBackground= createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND); + fBackground = createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND); - fIsUsingSystemForeground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT); + fIsUsingSystemForeground = fPreferenceStore + .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT); if (!fIsUsingSystemForeground) - fForeground= createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND); + fForeground = createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND); updateColors(null); } private String getSymbolicFontName() { - Class clazz= getClass(); + Class clazz = getClass(); do { - String fontName= clazz.getName(); + String fontName = clazz.getName(); if (JFaceResources.getFontRegistry().hasValueFor(fontName)) return fontName; - clazz= clazz.getSuperclass(); + clazz = clazz.getSuperclass(); } while (clazz != null); // use text compare font if no font has been registered for subclass return getClass().getName(); } - + private void updateFont() { - Font f= JFaceResources.getFont(fSymbolicFontName); + Font f = JFaceResources.getFont(fSymbolicFontName); if (f != null) { if (fAncestor != null) fAncestor.setFont(f); @@ -1452,52 +1577,58 @@ fRight.setFont(f); } } - + private void checkForColorUpdate(Display display) { if (fIsUsingSystemBackground) { - RGB bg= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB(); + RGB bg = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB(); if (!bg.equals(getBackground(display))) { updateColors(display); } } } - + /** - * Sets the viewer's background color to the given RGB value. - * If the value is null the system's default background color is used. - * @param background the background color or null to use the system's default background color + * Sets the viewer's background color to the given RGB value. If the value + * is null the system's default background color is used. + * + * @param background + * the background color or null to use the system's + * default background color * @since 2.0 */ public void setBackgroundColor(RGB background) { - fIsUsingSystemBackground= (background == null); - fBackground= background; + fIsUsingSystemBackground = (background == null); + fBackground = background; updateColors(null); } - + private RGB getBackground(Display display) { if (fBackground != null) return fBackground; if (display == null) - display= fComposite.getDisplay(); + display = fComposite.getDisplay(); return display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB(); } - + /** - * Sets the viewer's foreground color to the given RGB value. - * If the value is null the system's default foreground color is used. - * @param foreground the foreground color or null to use the system's default foreground color + * Sets the viewer's foreground color to the given RGB value. If the value + * is null the system's default foreground color is used. + * + * @param foreground + * the foreground color or null to use the system's + * default foreground color * @since 2.0 */ public void setForegroundColor(RGB foreground) { - fIsUsingSystemForeground= (foreground == null); - fForeground= foreground; + fIsUsingSystemForeground = (foreground == null); + fForeground = foreground; updateColors(null); } - + private void updateColors(Display display) { - + if (display == null) display = fComposite.getDisplay(); @@ -1521,49 +1652,51 @@ fLeft.setForegroundColor(color); if (fRight != null) fRight.setForegroundColor(color); - - ColorRegistry registry= JFaceResources.getColorRegistry(); - - RGB bg= getBackground(display); - SELECTED_INCOMING= registry.getRGB(INCOMING_COLOR); + + ColorRegistry registry = JFaceResources.getColorRegistry(); + + RGB bg = getBackground(display); + SELECTED_INCOMING = registry.getRGB(INCOMING_COLOR); if (SELECTED_INCOMING == null) - SELECTED_INCOMING= new RGB(0, 0, 255); // BLUE - INCOMING= interpolate(SELECTED_INCOMING, bg, 0.6); - INCOMING_FILL= interpolate(SELECTED_INCOMING, bg, 0.97); - INCOMING_TEXT_FILL= interpolate(SELECTED_INCOMING, bg, 0.85); + SELECTED_INCOMING = new RGB(0, 0, 255); // BLUE + INCOMING = interpolate(SELECTED_INCOMING, bg, 0.6); + INCOMING_FILL = interpolate(SELECTED_INCOMING, bg, 0.97); + INCOMING_TEXT_FILL = interpolate(SELECTED_INCOMING, bg, 0.85); - SELECTED_OUTGOING= registry.getRGB(OUTGOING_COLOR); + SELECTED_OUTGOING = registry.getRGB(OUTGOING_COLOR); if (SELECTED_OUTGOING == null) - SELECTED_OUTGOING= new RGB(0, 0, 0); // BLACK - OUTGOING= interpolate(SELECTED_OUTGOING, bg, 0.6); - OUTGOING_FILL= interpolate(SELECTED_OUTGOING, bg, 0.97); - OUTGOING_TEXT_FILL= interpolate(SELECTED_OUTGOING, bg, 0.85); - - SELECTED_CONFLICT= registry.getRGB(CONFLICTING_COLOR); + SELECTED_OUTGOING = new RGB(0, 0, 0); // BLACK + OUTGOING = interpolate(SELECTED_OUTGOING, bg, 0.6); + OUTGOING_FILL = interpolate(SELECTED_OUTGOING, bg, 0.97); + OUTGOING_TEXT_FILL = interpolate(SELECTED_OUTGOING, bg, 0.85); + + SELECTED_CONFLICT = registry.getRGB(CONFLICTING_COLOR); if (SELECTED_CONFLICT == null) - SELECTED_CONFLICT= new RGB(255, 0, 0); // RED - CONFLICT= interpolate(SELECTED_CONFLICT, bg, 0.6); - CONFLICT_FILL= interpolate(SELECTED_CONFLICT, bg, 0.97); - CONFLICT_TEXT_FILL= interpolate(SELECTED_CONFLICT, bg, 0.85); - - RESOLVED= registry.getRGB(RESOLVED_COLOR); + SELECTED_CONFLICT = new RGB(255, 0, 0); // RED + CONFLICT = interpolate(SELECTED_CONFLICT, bg, 0.6); + CONFLICT_FILL = interpolate(SELECTED_CONFLICT, bg, 0.97); + CONFLICT_TEXT_FILL = interpolate(SELECTED_CONFLICT, bg, 0.85); + + RESOLVED = registry.getRGB(RESOLVED_COLOR); if (RESOLVED == null) - RESOLVED= new RGB(0, 255, 0); // GREEN - + RESOLVED = new RGB(0, 255, 0); // GREEN + updatePresentation(display); } private void updatePresentation(Display display) { if (display == null) - display= fComposite.getDisplay(); + display = fComposite.getDisplay(); refreshBirdsEyeView(); invalidateLines(); updateAllDiffBackgrounds(display); invalidateTextPresentation(); } - + /** - * Invalidates the current presentation by invalidating the three text viewers. + * Invalidates the current presentation by invalidating the three text + * viewers. + * * @since 2.0 */ public void invalidateTextPresentation() { @@ -1574,14 +1707,13 @@ if (fRight != null) fRight.invalidateTextPresentation(); } - + /** * Configures the passed text viewer. This method is called after the three * text viewers have been created for the content areas. The - * TextMergeViewer implementation of this method will - * configure the viewer with a {@link SourceViewerConfiguration}. - * Subclasses may reimplement to provide a specific configuration for the - * text viewer. + * TextMergeViewer implementation of this method will configure + * the viewer with a {@link SourceViewerConfiguration}. Subclasses may + * reimplement to provide a specific configuration for the text viewer. * * @param textViewer * the text viewer to configure @@ -1589,33 +1721,36 @@ protected void configureTextViewer(TextViewer textViewer) { // to get undo for all text files // bugzilla 131895, 33665 - if(textViewer instanceof MergeSourceViewer){ - SourceViewerConfiguration configuration= new SourceViewerConfiguration(); - ((MergeSourceViewer)textViewer).configure(configuration); + if (textViewer instanceof MergeSourceViewer) { + SourceViewerConfiguration configuration = new SourceViewerConfiguration(); + ((MergeSourceViewer) textViewer).configure(configuration); } } - + /** - * Creates an ITokenComparator which is used to show the - * intra line differences. - * The TextMergeViewer implementation of this method returns a - * tokenizer that breaks a line into words separated by whitespace. - * Subclasses may reimplement to provide a specific tokenizer. - * @param line the line for which to create the ITokenComparator - * @return a ITokenComparator which is used for a second level token compare. + * Creates an ITokenComparator which is used to show the intra + * line differences. The TextMergeViewer implementation of this + * method returns a tokenizer that breaks a line into words separated by + * whitespace. Subclasses may reimplement to provide a specific tokenizer. + * + * @param line + * the line for which to create the ITokenComparator + * @return a ITokenComparator which is used for a second level token + * compare. */ protected ITokenComparator createTokenComparator(String line) { return new TokenComparator(line); } - + /** - * Setup the given document for use with this viewer. By default, - * the partitioner returned from {@link #getDocumentPartitioner()} - * is registered as the default partitioner for the document. - * Subclasses that return a partitioner must also override - * {@link #getDocumentPartitioning()} if they wish to be able to use shared - * documents (i.e. file buffers). - * @param document the document to be set up + * Setup the given document for use with this viewer. By default, the + * partitioner returned from {@link #getDocumentPartitioner()} is registered + * as the default partitioner for the document. Subclasses that return a + * partitioner must also override {@link #getDocumentPartitioning()} if they + * wish to be able to use shared documents (i.e. file buffers). + * + * @param document + * the document to be set up * * @since 3.3 */ @@ -1623,7 +1758,7 @@ String partitioning = getDocumentPartitioning(); if (partitioning == null || !(document instanceof IDocumentExtension3)) { if (document.getDocumentPartitioner() == null) { - IDocumentPartitioner partitioner= getDocumentPartitioner(); + IDocumentPartitioner partitioner = getDocumentPartitioner(); if (partitioner != null) { document.setDocumentPartitioner(partitioner); partitioner.connect(document); @@ -1632,7 +1767,7 @@ } else { IDocumentExtension3 ex3 = (IDocumentExtension3) document; if (ex3.getDocumentPartitioner(partitioning) == null) { - IDocumentPartitioner partitioner= getDocumentPartitioner(); + IDocumentPartitioner partitioner = getDocumentPartitioner(); if (partitioner != null) { ex3.setDocumentPartitioner(partitioning, partitioner); partitioner.connect(document); @@ -1640,33 +1775,35 @@ } } } - + /** - * Returns a document partitioner which is suitable for the underlying content type. - * This method is only called if the input provided by the content provider is a - * IStreamContentAccessor and an internal document must be obtained. This - * document is initialized with the partitioner returned from this method. + * Returns a document partitioner which is suitable for the underlying + * content type. This method is only called if the input provided by the + * content provider is a IStreamContentAccessor and an internal + * document must be obtained. This document is initialized with the + * partitioner returned from this method. *

* The TextMergeViewer implementation of this method returns - * null. Subclasses may reimplement to create a partitioner for a - * specific content type. Subclasses that do return a partitioner should also - * return a partitioning from {@link #getDocumentPartitioning()} in order to make - * use of shared documents (e.g. file buffers). - * + * null. Subclasses may reimplement to create a partitioner for + * a specific content type. Subclasses that do return a partitioner should + * also return a partitioning from {@link #getDocumentPartitioning()} in + * order to make use of shared documents (e.g. file buffers). + * * @return a document partitioner, or null */ protected IDocumentPartitioner getDocumentPartitioner() { return null; } - + /** * Return the partitioning to which the partitioner returned from - * {@link #getDocumentPartitioner()} is to be associated. Return null - * only if partitioning is not needed or if the subclass - * overrode {@link #setupDocument(IDocument)} directly. - * By default, null is returned which means that shared - * documents that return a partitioner from {@link #getDocumentPartitioner()} - * will not be able to use shared documents. + * {@link #getDocumentPartitioner()} is to be associated. Return + * null only if partitioning is not needed or if the subclass + * overrode {@link #setupDocument(IDocument)} directly. By default, + * null is returned which means that shared documents that + * return a partitioner from {@link #getDocumentPartitioner()} will not be + * able to use shared documents. + * * @see IDocumentExtension3 * @return a partitioning * @@ -1675,264 +1812,286 @@ protected String getDocumentPartitioning() { return null; } - + /** - * Called on the viewer disposal. - * Unregisters from the compare configuration. - * Clients may extend if they have to do additional cleanup. + * Called on the viewer disposal. Unregisters from the compare + * configuration. Clients may extend if they have to do additional cleanup. + * * @param event */ protected void handleDispose(DisposeEvent event) { - + if (fHandlerService != null) fHandlerService.dispose(); - - Object input= getInput(); + + Object input = getInput(); removeFromDocumentManager(ANCESTOR_CONTRIBUTOR, input); removeFromDocumentManager(LEFT_CONTRIBUTOR, input); removeFromDocumentManager(RIGHT_CONTRIBUTOR, input); - + if (DEBUG) DocumentManager.dump(); if (fPreferenceChangeListener != null) { - JFaceResources.getFontRegistry().removeListener(fPreferenceChangeListener); - JFaceResources.getColorRegistry().removeListener(fPreferenceChangeListener); + JFaceResources.getFontRegistry().removeListener( + fPreferenceChangeListener); + JFaceResources.getColorRegistry().removeListener( + fPreferenceChangeListener); if (fPreferenceStore != null) - fPreferenceStore.removePropertyChangeListener(fPreferenceChangeListener); - fPreferenceChangeListener= null; + fPreferenceStore + .removePropertyChangeListener(fPreferenceChangeListener); + fPreferenceChangeListener = null; } - - fLeftCanvas= null; - fRightCanvas= null; - fVScrollBar= null; - fBirdsEyeCanvas= null; - fSummaryHeader= null; + + fLeftCanvas = null; + fRightCanvas = null; + fVScrollBar = null; + fBirdsEyeCanvas = null; + fSummaryHeader = null; fAncestorContributor.unsetDocument(fAncestor); fLeftContributor.unsetDocument(fLeft); fRightContributor.unsetDocument(fRight); - + disconnect(fLeftContributor); disconnect(fRightContributor); disconnect(fAncestorContributor); - + if (fColors != null) { - Iterator i= fColors.values().iterator(); + Iterator i = fColors.values().iterator(); while (i.hasNext()) { - Color color= (Color) i.next(); + Color color = (Color) i.next(); if (!color.isDisposed()) color.dispose(); } - fColors= null; + fColors = null; } - + if (fBirdsEyeCursor != null) { fBirdsEyeCursor.dispose(); - fBirdsEyeCursor= null; + fBirdsEyeCursor = null; } - + if (showWhitespaceAction != null) showWhitespaceAction.dispose(); - + if (toggleLineNumbersAction != null) toggleLineNumbersAction.dispose(); - + if (fIgnoreWhitespace != null) fIgnoreWhitespace.dispose(); - + if (fSourceViewerDecorationSupport != null) { - for (Iterator iterator = fSourceViewerDecorationSupport.iterator(); iterator.hasNext();) { + for (Iterator iterator = fSourceViewerDecorationSupport.iterator(); iterator + .hasNext();) { ((SourceViewerDecorationSupport) iterator.next()).dispose(); } fSourceViewerDecorationSupport = null; } super.handleDispose(event); - } - + } + private void disconnect(ContributorInfo legInfo) { if (legInfo != null) legInfo.disconnect(); } - //------------------------------------------------------------------------------------------------------------- - //--- internal ------------------------------------------------------------------------------------------------ - //------------------------------------------------------------------------------------------------------------- - + // ------------------------------------------------------------------------------------------------------------- + // --- internal + // ------------------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------------------------------- + /* - * Creates the specific SWT controls for the content areas. - * Clients must not call or override this method. + * Creates the specific SWT controls for the content areas. Clients must not + * call or override this method. */ protected void createControls(Composite composite) { - - PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.TEXT_MERGE_VIEW); - + + PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, + ICompareContextIds.TEXT_MERGE_VIEW); + // 1st row if (fMarginWidth > 0) { - fAncestorCanvas= new BufferedCanvas(composite, SWT.NONE) { + fAncestorCanvas = new BufferedCanvas(composite, SWT.NONE) { public void doPaint(GC gc) { paintSides(gc, fAncestor, fAncestorCanvas, false); } }; - fAncestorCanvas.addMouseListener( - new MouseAdapter() { - public void mouseDown(MouseEvent e) { - setCurrentDiff2(handleMouseInSides(fAncestorCanvas, fAncestor, e.y), false); - } + fAncestorCanvas.addMouseListener(new MouseAdapter() { + public void mouseDown(MouseEvent e) { + setCurrentDiff2(handleMouseInSides(fAncestorCanvas, + fAncestor, e.y), false); } - ); + }); } - - fAncestor= createPart(composite); + + fAncestor = createPart(composite); fAncestor.setEditable(false); - fAncestor.getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() { - public void getName(AccessibleEvent e) { - e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_ancestor, getCompareConfiguration().getAncestorLabel(getInput())); - } - }); + fAncestor.getTextWidget().getAccessible().addAccessibleListener( + new AccessibleAdapter() { + public void getName(AccessibleEvent e) { + e.result = NLS + .bind( + CompareMessages.TextMergeViewer_accessible_ancestor, + getCompareConfiguration() + .getAncestorLabel(getInput())); + } + }); fAncestor.addTextPresentationListener(new ChangeHighlighter(fAncestor)); - - fSummaryHeader= new Canvas(composite, SWT.NONE); - fHeaderPainter= new HeaderPainter(); + + fSummaryHeader = new Canvas(composite, SWT.NONE); + fHeaderPainter = new HeaderPainter(); fSummaryHeader.addPaintListener(fHeaderPainter); updateResolveStatus(); - + // 2nd row if (fMarginWidth > 0) { - fLeftCanvas= new BufferedCanvas(composite, SWT.NONE) { + fLeftCanvas = new BufferedCanvas(composite, SWT.NONE) { public void doPaint(GC gc) { paintSides(gc, fLeft, fLeftCanvas, false); } }; - fLeftCanvas.addMouseListener( - new MouseAdapter() { - public void mouseDown(MouseEvent e) { - setCurrentDiff2(handleMouseInSides(fLeftCanvas, fLeft, e.y), false); - } + fLeftCanvas.addMouseListener(new MouseAdapter() { + public void mouseDown(MouseEvent e) { + setCurrentDiff2( + handleMouseInSides(fLeftCanvas, fLeft, e.y), false); } - ); + }); } - - fLeft= createPart(composite); - fLeft.getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling); + + fLeft = createPart(composite); + fLeft.getTextWidget().getVerticalBar().setVisible( + !fSynchronizedScrolling); fLeft.addAction(MergeSourceViewer.SAVE_ID, fLeftSaveAction); - fLeft.getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() { - public void getName(AccessibleEvent e) { - e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_left, getCompareConfiguration().getLeftLabel(getInput())); - } - }); + fLeft.getTextWidget().getAccessible().addAccessibleListener( + new AccessibleAdapter() { + public void getName(AccessibleEvent e) { + e.result = NLS + .bind( + CompareMessages.TextMergeViewer_accessible_left, + getCompareConfiguration().getLeftLabel( + getInput())); + } + }); fLeft.addTextPresentationListener(new ChangeHighlighter(fLeft)); - - fRight= createPart(composite); - fRight.getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling); + + fRight = createPart(composite); + fRight.getTextWidget().getVerticalBar().setVisible( + !fSynchronizedScrolling); fRight.addAction(MergeSourceViewer.SAVE_ID, fRightSaveAction); - fRight.getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() { - public void getName(AccessibleEvent e) { - e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_right, getCompareConfiguration().getRightLabel(getInput())); - } - }); + fRight.getTextWidget().getAccessible().addAccessibleListener( + new AccessibleAdapter() { + public void getName(AccessibleEvent e) { + e.result = NLS + .bind( + CompareMessages.TextMergeViewer_accessible_right, + getCompareConfiguration() + .getRightLabel(getInput())); + } + }); fRight.addTextPresentationListener(new ChangeHighlighter(fRight)); - - IWorkbenchPart part = getCompareConfiguration().getContainer().getWorkbenchPart(); - // part is not available for contexts different than editor - if (part != null) { - ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); - if (selectionProvider instanceof CompareEditorSelectionProvider) { - CompareEditorSelectionProvider cesp = (CompareEditorSelectionProvider) selectionProvider; - cesp.setViewers(new TextViewer[] { fLeft, fRight, fAncestor }, fFocusPart /* null */); - } - } - + + IWorkbenchPart part = getCompareConfiguration().getContainer() + .getWorkbenchPart(); + // part is not available for contexts different than editor + if (part != null) { + ISelectionProvider selectionProvider = part.getSite() + .getSelectionProvider(); + if (selectionProvider instanceof CompareEditorSelectionProvider) { + CompareEditorSelectionProvider cesp = (CompareEditorSelectionProvider) selectionProvider; + cesp.setViewers(new TextViewer[] { fLeft, fRight, fAncestor }, + fFocusPart /* null */); + } + } + hsynchViewport(fAncestor, fLeft, fRight); hsynchViewport(fLeft, fAncestor, fRight); hsynchViewport(fRight, fAncestor, fLeft); if (fMarginWidth > 0) { - fRightCanvas= new BufferedCanvas(composite, SWT.NONE) { + fRightCanvas = new BufferedCanvas(composite, SWT.NONE) { public void doPaint(GC gc) { paintSides(gc, fRight, fRightCanvas, fSynchronizedScrolling); } }; - fRightCanvas.addMouseListener( - new MouseAdapter() { - public void mouseDown(MouseEvent e) { - setCurrentDiff2(handleMouseInSides(fRightCanvas, fRight, e.y), false); - } + fRightCanvas.addMouseListener(new MouseAdapter() { + public void mouseDown(MouseEvent e) { + setCurrentDiff2(handleMouseInSides(fRightCanvas, fRight, + e.y), false); } - ); + }); } - - fScrollCanvas= new Canvas(composite, SWT.V_SCROLL); - Rectangle trim= fLeft.getTextWidget().computeTrim(0, 0, 0, 0); - fTopInset= trim.y; - - fVScrollBar= fScrollCanvas.getVerticalBar(); + + fScrollCanvas = new Canvas(composite, SWT.V_SCROLL); + Rectangle trim = fLeft.getTextWidget().computeTrim(0, 0, 0, 0); + fTopInset = trim.y; + + fVScrollBar = fScrollCanvas.getVerticalBar(); fVScrollBar.setIncrement(1); fVScrollBar.setVisible(true); - fVScrollBar.addListener(SWT.Selection, - new Listener() { - public void handleEvent(Event e) { - int vpos= ((ScrollBar)e.widget).getSelection(); - synchronizedScrollVertical(vpos); - } + fVScrollBar.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + int vpos = ((ScrollBar) e.widget).getSelection(); + synchronizedScrollVertical(vpos); } - ); - - fBirdsEyeCanvas= new BufferedCanvas(composite, SWT.NONE) { + }); + + fBirdsEyeCanvas = new BufferedCanvas(composite, SWT.NONE) { public void doPaint(GC gc) { paintBirdsEyeView(this, gc); } }; - fBirdsEyeCanvas.addMouseListener( - new MouseAdapter() { - public void mouseDown(MouseEvent e) { - setCurrentDiff2(handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y), true); - } + fBirdsEyeCanvas.addMouseListener(new MouseAdapter() { + public void mouseDown(MouseEvent e) { + setCurrentDiff2( + handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y), true); } - ); - fBirdsEyeCanvas.addMouseMoveListener( - new MouseMoveListener() { - - private Cursor fLastCursor; - - public void mouseMove(MouseEvent e) { - Cursor cursor= null; - Diff diff= handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y); - if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) - cursor= fBirdsEyeCursor; - if (fLastCursor != cursor) { - fBirdsEyeCanvas.setCursor(cursor); - fLastCursor= cursor; - } + }); + fBirdsEyeCanvas.addMouseMoveListener(new MouseMoveListener() { + + private Cursor fLastCursor; + + public void mouseMove(MouseEvent e) { + Cursor cursor = null; + Diff diff = handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y); + if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) + cursor = fBirdsEyeCursor; + if (fLastCursor != cursor) { + fBirdsEyeCanvas.setCursor(cursor); + fLastCursor = cursor; } } - ); + }); + + contributeCreatePatchAction(fAncestor, false); + contributeCreatePatchAction(fLeft, false); + contributeCreatePatchAction(fRight, true); } - - private void hsynchViewport(final TextViewer tv1, final TextViewer tv2, final TextViewer tv3) { - final StyledText st1= tv1.getTextWidget(); - final StyledText st2= tv2.getTextWidget(); - final StyledText st3= tv3.getTextWidget(); - final ScrollBar sb1= st1.getHorizontalBar(); + + private void hsynchViewport(final TextViewer tv1, final TextViewer tv2, + final TextViewer tv3) { + final StyledText st1 = tv1.getTextWidget(); + final StyledText st2 = tv2.getTextWidget(); + final StyledText st3 = tv3.getTextWidget(); + final ScrollBar sb1 = st1.getHorizontalBar(); sb1.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { - if (fSynchronizedScrolling) { - int v= sb1.getSelection(); + if (fSynchronizedScrolling) { + int v = sb1.getSelection(); if (st2.isVisible()) st2.setHorizontalPixel(v); if (st3.isVisible()) st3.setHorizontalPixel(v); workaround65205(); - } + } } }); } /** - * A workaround for bug #65205. - * On MacOS X a Display.update() is required to flush pending paint requests after - * programmatically scrolling. + * A workaround for bug #65205. On MacOS X a Display.update() is required to + * flush pending paint requests after programmatically scrolling. */ private void workaround65205() { if (fIsCarbon && fComposite != null && !fComposite.isDisposed()) @@ -1941,25 +2100,26 @@ private void setCurrentDiff2(Diff diff, boolean reveal) { if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) { - //fCurrentDiff= null; + // fCurrentDiff= null; setCurrentDiff(diff, reveal); } } - + private Diff handleMouseInSides(Canvas canvas, MergeSourceViewer tp, int my) { - int lineHeight= tp.getTextWidget().getLineHeight(); - int visibleHeight= tp.getViewportHeight(); + int lineHeight = tp.getTextWidget().getLineHeight(); + int visibleHeight = tp.getViewportHeight(); - if (! fHighlightRanges) + if (!fHighlightRanges) return null; if (fMerger.hasChanges()) { - int shift= tp.getVerticalScrollOffset() + (2-LW); + int shift = tp.getVerticalScrollOffset() + (2 - LW); - Point region= new Point(0, 0); + Point region = new Point(0, 0); char leg = getLeg(tp); - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); if (diff.isDeleted()) continue; @@ -1968,42 +2128,43 @@ continue; tp.getLineRange(diff.getPosition(leg), region); - int y= (region.x * lineHeight) + shift; - int h= region.y * lineHeight; + int y = (region.x * lineHeight) + shift; + int h = region.y * lineHeight; - if (y+h < 0) + if (y + h < 0) continue; if (y >= visibleHeight) break; - - if (my >= y && my < y+h) + + if (my >= y && my < y + h) return diff; } } return null; } - + private Diff getDiffUnderMouse(Canvas canvas, int mx, int my, Rectangle r) { - if (! fSynchronizedScrolling) + if (!fSynchronizedScrolling) return null; - int lineHeight= fLeft.getTextWidget().getLineHeight(); - int visibleHeight= fRight.getViewportHeight(); + int lineHeight = fLeft.getTextWidget().getLineHeight(); + int visibleHeight = fRight.getViewportHeight(); - Point size= canvas.getSize(); - int w= size.x; + Point size = canvas.getSize(); + int w = size.x; - if (! fHighlightRanges) + if (!fHighlightRanges) return null; if (fMerger.hasChanges()) { - int lshift= fLeft.getVerticalScrollOffset(); - int rshift= fRight.getVerticalScrollOffset(); + int lshift = fLeft.getVerticalScrollOffset(); + int rshift = fRight.getVerticalScrollOffset(); - Point region= new Point(0, 0); + Point region = new Point(0, 0); - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); if (diff.isDeleted()) continue; @@ -2012,27 +2173,30 @@ continue; fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region); - int ly= (region.x * lineHeight) + lshift; - int lh= region.y * lineHeight; + int ly = (region.x * lineHeight) + lshift; + int lh = region.y * lineHeight; - fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region); - int ry= (region.x * lineHeight) + rshift; - int rh= region.y * lineHeight; + fRight + .getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), + region); + int ry = (region.x * lineHeight) + rshift; + int rh = region.y * lineHeight; - if (Math.max(ly+lh, ry+rh) < 0) + if (Math.max(ly + lh, ry + rh) < 0) continue; if (Math.min(ly, ry) >= visibleHeight) break; - int cx= (w-RESOLVE_SIZE)/2; - int cy= ((ly+lh/2) + (ry+rh/2) - RESOLVE_SIZE)/2; - if (my >= cy && my < cy+RESOLVE_SIZE && mx >= cx && mx < cx+RESOLVE_SIZE) { + int cx = (w - RESOLVE_SIZE) / 2; + int cy = ((ly + lh / 2) + (ry + rh / 2) - RESOLVE_SIZE) / 2; + if (my >= cy && my < cy + RESOLVE_SIZE && mx >= cx + && mx < cx + RESOLVE_SIZE) { if (r != null) { - int SIZE= fIsCarbon ? 30 : 20; - r.x= cx+(RESOLVE_SIZE-SIZE)/2; - r.y= cy+(RESOLVE_SIZE-SIZE)/2; - r.width= SIZE; - r.height= SIZE; + int SIZE = fIsCarbon ? 30 : 20; + r.x = cx + (RESOLVE_SIZE - SIZE) / 2; + r.y = cy + (RESOLVE_SIZE - SIZE) / 2; + r.width = SIZE; + r.height = SIZE; } return diff; } @@ -2042,47 +2206,50 @@ } private Diff handlemouseInBirdsEyeView(Canvas canvas, int my) { - return fMerger.findDiff(getViewportHeight(), fSynchronizedScrolling, canvas.getSize(), my); + return fMerger.findDiff(getViewportHeight(), fSynchronizedScrolling, + canvas.getSize(), my); } - + private void paintBirdsEyeView(Canvas canvas, GC gc) { - + Color c; - Rectangle r= new Rectangle(0, 0, 0, 0); + Rectangle r = new Rectangle(0, 0, 0, 0); int yy, hh; - - Point size= canvas.getSize(); - - int virtualHeight= fSynchronizedScrolling ? fMerger.getVirtualHeight() : fMerger.getRightHeight(); + + Point size = canvas.getSize(); + + int virtualHeight = fSynchronizedScrolling ? fMerger.getVirtualHeight() + : fMerger.getRightHeight(); if (virtualHeight < getViewportHeight()) return; - - Display display= canvas.getDisplay(); - int y= 0; + + Display display = canvas.getDisplay(); + int y = 0; for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) { Diff diff = (Diff) iterator.next(); - int h= fSynchronizedScrolling ? diff.getMaxDiffHeight() - : diff.getRightHeight(); - + int h = fSynchronizedScrolling ? diff.getMaxDiffHeight() : diff + .getRightHeight(); + if (fMerger.useChange(diff)) { - - yy= (y*size.y)/virtualHeight; - hh= (h*size.y)/virtualHeight; + + yy = (y * size.y) / virtualHeight; + hh = (h * size.y) / virtualHeight; if (hh < 3) - hh= 3; - - c= getColor(display, getFillColor(diff)); + hh = 3; + + c = getColor(display, getFillColor(diff)); if (c != null) { gc.setBackground(c); - gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh); + gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x + - (2 * BIRDS_EYE_VIEW_INSET), hh); } - c= getColor(display, getStrokeColor(diff)); + c = getColor(display, getStrokeColor(diff)); if (c != null) { gc.setForeground(c); - r.x= BIRDS_EYE_VIEW_INSET; - r.y= yy; - r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1; - r.height= hh; + r.x = BIRDS_EYE_VIEW_INSET; + r.y = yy; + r.width = size.x - (2 * BIRDS_EYE_VIEW_INSET) - 1; + r.height = hh; if (isCurrentDiff(diff)) { gc.setLineWidth(2); r.x++; @@ -2095,129 +2262,143 @@ gc.drawRectangle(r); } } - - y+= h; + + y += h; } } - + private void refreshBirdsEyeView() { if (fBirdsEyeCanvas != null) fBirdsEyeCanvas.redraw(); } - + /** - * Override to give focus to the pane that previously had focus or to a suitable - * default pane. + * Override to give focus to the pane that previously had focus or to a + * suitable default pane. + * * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handleSetFocus() * @since 3.3 */ protected boolean handleSetFocus() { if (fFocusPart == null) { if (fLeft != null && fLeft.getEnabled()) { - fFocusPart= fLeft; + fFocusPart = fLeft; } else if (fRight != null && fRight.getEnabled()) { - fFocusPart= fRight; + fFocusPart = fRight; } else if (fAncestor != null && fAncestor.getEnabled()) { - fFocusPart= fAncestor; + fFocusPart = fAncestor; } } if (fFocusPart != null) { - StyledText st= fFocusPart.getTextWidget(); + StyledText st = fFocusPart.getTextWidget(); if (st != null) return st.setFocus(); } - return false; // could not set focus + return false; // could not set focus } - - + class HoverResizer extends Resizer { Canvas fCanvas; + public HoverResizer(Canvas c, int dir) { super(c, dir); - fCanvas= c; + fCanvas = c; } + public void mouseMove(MouseEvent e) { - if (!fIsDown && fUseSingleLine && showResolveUI() && handleMouseMoveOverCenter(fCanvas, e.x, e.y)) + if (!fIsDown && fUseSingleLine && showResolveUI() + && handleMouseMoveOverCenter(fCanvas, e.x, e.y)) return; super.mouseMove(e); } } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#createCenterControl(org.eclipse.swt.widgets.Composite) + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.compare.contentmergeviewer.ContentMergeViewer#createCenterControl + * (org.eclipse.swt.widgets.Composite) */ protected final Control createCenterControl(Composite parent) { if (fSynchronizedScrolling) { - final Canvas canvas= new BufferedCanvas(parent, SWT.NONE) { + final Canvas canvas = new BufferedCanvas(parent, SWT.NONE) { public void doPaint(GC gc) { paintCenter(this, gc); } }; if (fUseResolveUI) { - + new HoverResizer(canvas, HORIZONTAL); - - fCenterButton= new Button(canvas, fIsCarbon ? SWT.FLAT : SWT.PUSH); - if (fNormalCursor == null) fNormalCursor= new Cursor(canvas.getDisplay(), SWT.CURSOR_ARROW); + + fCenterButton = new Button(canvas, fIsCarbon ? SWT.FLAT + : SWT.PUSH); + if (fNormalCursor == null) + fNormalCursor = new Cursor(canvas.getDisplay(), + SWT.CURSOR_ARROW); fCenterButton.setCursor(fNormalCursor); fCenterButton.setText(COPY_RIGHT_TO_LEFT_INDICATOR); fCenterButton.pack(); fCenterButton.setVisible(false); - fCenterButton.addSelectionListener( - new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - fCenterButton.setVisible(false); - if (fButtonDiff != null) { - setCurrentDiff(fButtonDiff, false); - copy(fCurrentDiff, - fCenterButton.getText().equals(COPY_LEFT_TO_RIGHT_INDICATOR), - fCurrentDiff.getKind() != RangeDifference.CONFLICT); - } + fCenterButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fCenterButton.setVisible(false); + if (fButtonDiff != null) { + setCurrentDiff(fButtonDiff, false); + copy(fCurrentDiff, fCenterButton.getText().equals( + COPY_LEFT_TO_RIGHT_INDICATOR), fCurrentDiff + .getKind() != RangeDifference.CONFLICT); } } - ); + }); } else { new Resizer(canvas, HORIZONTAL); } - + return canvas; } return super.createCenterControl(parent); } - + private boolean handleMouseMoveOverCenter(Canvas canvas, int x, int y) { - Rectangle r= new Rectangle(0, 0, 0, 0); - Diff diff= getDiffUnderMouse(canvas, x, y, r); + Rectangle r = new Rectangle(0, 0, 0, 0); + Diff diff = getDiffUnderMouse(canvas, x, y, r); if (diff != null && !diff.isUnresolvedIncomingOrConflicting()) - diff= null; + diff = null; if (diff != fButtonDiff) { if (diff != null) { if (fLeft.isEditable()) { - fButtonDiff= diff; + fButtonDiff = diff; fCenterButton.setText(COPY_RIGHT_TO_LEFT_INDICATOR); - String tt= fCopyDiffRightToLeftItem.getAction().getToolTipText(); + String tt = fCopyDiffRightToLeftItem.getAction() + .getToolTipText(); fCenterButton.setToolTipText(tt); fCenterButton.setBounds(r); fCenterButton.setVisible(true); } else if (fRight.isEditable()) { - fButtonDiff= diff; + fButtonDiff = diff; fCenterButton.setText(COPY_LEFT_TO_RIGHT_INDICATOR); - String tt= fCopyDiffLeftToRightItem.getAction().getToolTipText(); + String tt = fCopyDiffLeftToRightItem.getAction() + .getToolTipText(); fCenterButton.setToolTipText(tt); fCenterButton.setBounds(r); fCenterButton.setVisible(true); } else - fButtonDiff= null; + fButtonDiff = null; } else { fCenterButton.setVisible(false); - fButtonDiff= null; + fButtonDiff = null; } } return fButtonDiff != null; } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getCenterWidth() + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getCenterWidth + * () */ protected final int getCenterWidth() { if (fSynchronizedScrolling) @@ -2235,122 +2416,132 @@ } return fInheritedDirection; } - + /* * Creates and initializes a text part. */ private MergeSourceViewer createPart(Composite parent) { - - final MergeSourceViewer part= new MergeSourceViewer(parent, getDirection(), getResourceBundle(), getCompareConfiguration().getContainer()); - final StyledText te= part.getTextWidget(); - + + final MergeSourceViewer part = new MergeSourceViewer(parent, + getDirection(), getResourceBundle(), getCompareConfiguration() + .getContainer()); + final StyledText te = part.getTextWidget(); + if (!fConfirmSave) part.hideSaveAction(); - - te.addPaintListener( - new PaintListener() { - public void paintControl(PaintEvent e) { - paint(e, part); - } - } - ); - te.addKeyListener( - new KeyAdapter() { - public void keyPressed(KeyEvent e) { - handleSelectionChanged(part); - } - } - ); - te.addMouseListener( - new MouseAdapter() { - public void mouseDown(MouseEvent e) { - //syncViewport(part); - handleSelectionChanged(part); - } + + te.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + paint(e, part); } - ); - - te.addFocusListener( - new FocusAdapter() { - public void focusGained(FocusEvent fe) { - fFocusPart= part; - connectGlobalActions(fFocusPart); - } - public void focusLost(FocusEvent fe) { - connectGlobalActions(null); - } + }); + te.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + handleSelectionChanged(part); } - ); - - part.addViewportListener( - new IViewportListener() { - public void viewportChanged(int verticalPosition) { - syncViewport(part); - } + }); + te.addMouseListener(new MouseAdapter() { + public void mouseDown(MouseEvent e) { + // syncViewport(part); + handleSelectionChanged(part); + } + }); + + te.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent fe) { + fFocusPart = part; + connectGlobalActions(fFocusPart); + } + + public void focusLost(FocusEvent fe) { + connectGlobalActions(null); + } + }); + + part.addViewportListener(new IViewportListener() { + public void viewportChanged(int verticalPosition) { + syncViewport(part); } - ); - - Font font= JFaceResources.getFont(fSymbolicFontName); + }); + + Font font = JFaceResources.getFont(fSymbolicFontName); if (font != null) te.setFont(font); - - if (fBackground != null) // not default + + if (fBackground != null) // not default te.setBackground(getColor(parent.getDisplay(), fBackground)); - + // Add the find action to the popup menu of the viewer contributeFindAction(part); - + contributeGotoLineAction(part); configureTextViewer(part); - + getSourceViewerDecorationSupport(part).install(fPreferenceStore); return part; } - private SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) { - SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(viewer, null, null, EditorsUI.getSharedTextColors()); - support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR); + private SourceViewerDecorationSupport getSourceViewerDecorationSupport( + ISourceViewer viewer) { + SourceViewerDecorationSupport support = new SourceViewerDecorationSupport( + viewer, null, null, EditorsUI.getSharedTextColors()); + support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, + CURRENT_LINE_COLOR); fSourceViewerDecorationSupport.add(support); return support; } private void contributeFindAction(MergeSourceViewer viewer) { IAction action; - IWorkbenchPart wp = getCompareConfiguration().getContainer().getWorkbenchPart(); + IWorkbenchPart wp = getCompareConfiguration().getContainer() + .getWorkbenchPart(); if (wp != null) - action = new FindReplaceAction(getResourceBundle(), "Editor.FindReplace.", wp); //$NON-NLS-1$ + action = new FindReplaceAction(getResourceBundle(), + "Editor.FindReplace.", wp); //$NON-NLS-1$ else - action = new FindReplaceAction(getResourceBundle(), "Editor.FindReplace.", viewer.getControl().getShell(), getFindReplaceTarget()); //$NON-NLS-1$ - action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE); + action = new FindReplaceAction( + getResourceBundle(), + "Editor.FindReplace.", viewer.getControl().getShell(), getFindReplaceTarget()); //$NON-NLS-1$ + action + .setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE); viewer.addAction(MergeSourceViewer.FIND_ID, action); } - + private void contributeGotoLineAction(MergeSourceViewer viewer) { IAction action = new GotoLineAction(viewer.getTextEditorAdapter()); action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO); viewer.addAction(MergeSourceViewer.GOTO_LINE_ID, action); } + private void contributeCreatePatchAction(MergeSourceViewer viewer, + boolean rightToLeft) { + IAction action = new CreatePatchAction(this, rightToLeft); + viewer.addAction(MergeSourceViewer.CREATE_PATCH_ID, action); + } + private void connectGlobalActions(final MergeSourceViewer part) { if (fHandlerService != null) { if (part != null) part.updateActions(); fHandlerService.updatePaneActionHandlers(new Runnable() { public void run() { - for (int i= 0; i < GLOBAL_ACTIONS.length; i++) { - IAction action= null; + for (int i = 0; i < GLOBAL_ACTIONS.length; i++) { + IAction action = null; if (part != null) { - action= part.getAction(TEXT_ACTIONS[i]); - if (action == null && TEXT_ACTIONS[i].equals(MergeSourceViewer.SAVE_ID)) { + action = part.getAction(TEXT_ACTIONS[i]); + if (action == null + && TEXT_ACTIONS[i] + .equals(MergeSourceViewer.SAVE_ID)) { if (part == fLeft) - action= fLeftSaveAction; + action = fLeftSaveAction; else - action= fRightSaveAction; + action = fRightSaveAction; } } - fHandlerService.setGlobalActionHandler(GLOBAL_ACTIONS[i], action); + fHandlerService.setGlobalActionHandler( + GLOBAL_ACTIONS[i], action); } } }); @@ -2361,7 +2552,7 @@ if (element instanceof IDocument) { return (IDocument) element; } - ITypedElement te= Utilities.getLeg(type, element); + ITypedElement te = Utilities.getLeg(type, element); // First check the contributors for the document IDocument document = null; switch (type) { @@ -2377,215 +2568,240 @@ } if (document != null) return document; - // The document is not associated with the input of the viewer so try to find the document - return Utilities.getDocument(type, element, isUsingDefaultContentProvider(), canHaveSharedDocument()); + // The document is not associated with the input of the viewer so try to + // find the document + return Utilities.getDocument(type, element, + isUsingDefaultContentProvider(), canHaveSharedDocument()); } - + private boolean isUsingDefaultContentProvider() { return getContentProvider() instanceof MergeViewerContentProvider; } - + private boolean canHaveSharedDocument() { return getDocumentPartitioning() != null - || getDocumentPartitioner() == null; + || getDocumentPartitioner() == null; } - + private IDocument getDocument(ITypedElement te, ContributorInfo info) { if (info != null && info.getElement() == te) return info.getDocument(); return null; } - + IDocument getDocument(char type, Object input) { - IDocument doc= getElementDocument(type, input); + IDocument doc = getElementDocument(type, input); if (doc != null) return doc; - + if (input instanceof IDiffElement) { - IDiffContainer parent= ((IDiffElement)input).getParent(); + IDiffContainer parent = ((IDiffElement) input).getParent(); return getElementDocument(type, parent); } return null; } - + /* * Returns true if the given inputs map to the same documents */ boolean sameDoc(char type, Object newInput, Object oldInput) { - IDocument newDoc= getDocument(type, newInput); - IDocument oldDoc= getDocument(type, oldInput); + IDocument newDoc = getDocument(type, newInput); + IDocument oldDoc = getDocument(type, oldInput); return newDoc == oldDoc; } - + /** - * Overridden to prevent save confirmation if new input is sub document of current input. - * @param newInput the new input of this viewer, or null if there is no new input - * @param oldInput the old input element, or null if there was previously no input - * @return true if saving was successful, or if the user didn't want to save (by pressing 'NO' in the confirmation dialog). + * Overridden to prevent save confirmation if new input is sub document of + * current input. + * + * @param newInput + * the new input of this viewer, or null if there is + * no new input + * @param oldInput + * the old input element, or null if there was + * previously no input + * @return true if saving was successful, or if the user didn't + * want to save (by pressing 'NO' in the confirmation dialog). * @since 2.0 */ protected boolean doSave(Object newInput, Object oldInput) { - // TODO: Would be good if this could be restated in terms of Saveables and moved up + // TODO: Would be good if this could be restated in terms of Saveables + // and moved up if (oldInput != null && newInput != null) { // check whether underlying documents have changed. - if (sameDoc(ANCESTOR_CONTRIBUTOR, newInput, oldInput) && - sameDoc(LEFT_CONTRIBUTOR, newInput, oldInput) && - sameDoc(RIGHT_CONTRIBUTOR, newInput, oldInput)) { - if (DEBUG) System.out.println("----- Same docs !!!!"); //$NON-NLS-1$ + if (sameDoc(ANCESTOR_CONTRIBUTOR, newInput, oldInput) + && sameDoc(LEFT_CONTRIBUTOR, newInput, oldInput) + && sameDoc(RIGHT_CONTRIBUTOR, newInput, oldInput)) { + if (DEBUG) + System.out.println("----- Same docs !!!!"); //$NON-NLS-1$ return false; } } - - if (DEBUG) System.out.println("***** New docs !!!!"); //$NON-NLS-1$ - + + if (DEBUG) + System.out.println("***** New docs !!!!"); //$NON-NLS-1$ + removeFromDocumentManager(ANCESTOR_CONTRIBUTOR, oldInput); removeFromDocumentManager(LEFT_CONTRIBUTOR, oldInput); removeFromDocumentManager(RIGHT_CONTRIBUTOR, oldInput); - + if (DEBUG) DocumentManager.dump(); - + return super.doSave(newInput, oldInput); } - + private void removeFromDocumentManager(char leg, Object oldInput) { - IDocument document= getDocument(leg, oldInput); + IDocument document = getDocument(leg, oldInput); if (document != null) DocumentManager.remove(document); } - + private ITypedElement getParent(char type) { - Object input= getInput(); + Object input = getInput(); if (input instanceof IDiffElement) { - IDiffContainer parent= ((IDiffElement)input).getParent(); + IDiffContainer parent = ((IDiffElement) input).getParent(); return Utilities.getLeg(type, parent); } return null; } - + /* - * Initializes the text viewers of the three content areas with the given input objects. - * Subclasses may extend. + * Initializes the text viewers of the three content areas with the given + * input objects. Subclasses may extend. */ protected void updateContent(Object ancestor, Object left, Object right) { - - boolean emptyInput= (ancestor == null && left == null && right == null); - Object input= getInput(); + boolean emptyInput = (ancestor == null && left == null && right == null); + + Object input = getInput(); + + Position leftRange = null; + Position rightRange = null; - Position leftRange= null; - Position rightRange= null; - // if one side is empty use container if (FIX_47640 && !emptyInput && (left == null || right == null)) { if (input instanceof IDiffElement) { - IDiffContainer parent= ((IDiffElement)input).getParent(); + IDiffContainer parent = ((IDiffElement) input).getParent(); if (parent instanceof ICompareInput) { - ICompareInput ci= (ICompareInput) parent; - - if (ci.getAncestor() instanceof IDocumentRange - || ci.getLeft() instanceof IDocumentRange - || ci.getRight() instanceof IDocumentRange) { - - if (left instanceof IDocumentRange) - leftRange= ((IDocumentRange)left).getRange(); - if (right instanceof IDocumentRange) - rightRange= ((IDocumentRange)right).getRange(); - - ancestor= ci.getAncestor(); - left= ci.getLeft(); - right= ci.getRight(); - } + ICompareInput ci = (ICompareInput) parent; + + if (ci.getAncestor() instanceof IDocumentRange + || ci.getLeft() instanceof IDocumentRange + || ci.getRight() instanceof IDocumentRange) { + + if (left instanceof IDocumentRange) + leftRange = ((IDocumentRange) left).getRange(); + if (right instanceof IDocumentRange) + rightRange = ((IDocumentRange) right).getRange(); + + ancestor = ci.getAncestor(); + left = ci.getLeft(); + right = ci.getRight(); + } } } } - int n= 0; + int n = 0; if (left != null) n++; if (right != null) n++; - fHighlightRanges= n > 1; - + fHighlightRanges = n > 1; + resetDiffs(); - fHasErrors= false; // start with no errors - - CompareConfiguration cc= getCompareConfiguration(); - IMergeViewerContentProvider cp= getMergeContentProvider(); - + fHasErrors = false; // start with no errors + + CompareConfiguration cc = getCompareConfiguration(); + IMergeViewerContentProvider cp = getMergeContentProvider(); + if (cp instanceof MergeViewerContentProvider) { - MergeViewerContentProvider mcp= (MergeViewerContentProvider) cp; + MergeViewerContentProvider mcp = (MergeViewerContentProvider) cp; mcp.setAncestorError(null); mcp.setLeftError(null); mcp.setRightError(null); } - // Record current contributors so we disconnect after creating the new ones. + // Record current contributors so we disconnect after creating the new + // ones. // This is done in case the old and new use the same document. ContributorInfo oldLeftContributor = fLeftContributor; ContributorInfo oldRightContributor = fRightContributor; ContributorInfo oldAncestorContributor = fAncestorContributor; - + // Create the new contributor fLeftContributor = createLegInfoFor(left, LEFT_CONTRIBUTOR); fRightContributor = createLegInfoFor(right, RIGHT_CONTRIBUTOR); fAncestorContributor = createLegInfoFor(ancestor, ANCESTOR_CONTRIBUTOR); - + fLeftContributor.transferContributorStateFrom(oldLeftContributor); fRightContributor.transferContributorStateFrom(oldRightContributor); - fAncestorContributor.transferContributorStateFrom(oldAncestorContributor); - + fAncestorContributor + .transferContributorStateFrom(oldAncestorContributor); + // Now disconnect the old ones disconnect(oldLeftContributor); disconnect(oldRightContributor); disconnect(oldAncestorContributor); - - // Get encodings from streams. If an encoding is null, abide by the other one + + // Get encodings from streams. If an encoding is null, abide by the + // other one // Defaults to workbench encoding only if both encodings are null fLeftContributor.setEncodingIfAbsent(fRightContributor); fRightContributor.setEncodingIfAbsent(fLeftContributor); fAncestorContributor.setEncodingIfAbsent(fLeftContributor); - + // set new documents - fLeftContributor.setDocument(fLeft, cc.isLeftEditable() && cp.isLeftEditable(input)); - fLeftLineCount= fLeft.getLineCount(); - - fRightContributor.setDocument(fRight, cc.isRightEditable() && cp.isRightEditable(input)); - fRightLineCount= fRight.getLineCount(); - + fLeftContributor.setDocument(fLeft, cc.isLeftEditable() + && cp.isLeftEditable(input)); + fLeftLineCount = fLeft.getLineCount(); + + fRightContributor.setDocument(fRight, cc.isRightEditable() + && cp.isRightEditable(input)); + fRightLineCount = fRight.getLineCount(); + fAncestorContributor.setDocument(fAncestor, false); - //if the input is part of a patch hunk, toggle synchronized scrolling - /*if (isPatchHunk()){ - setSyncScrolling(false); - } else { - setSyncScrolling(fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING)); - }*/ - setSyncScrolling(fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING)); - + // if the input is part of a patch hunk, toggle synchronized scrolling + /* + * if (isPatchHunk()){ setSyncScrolling(false); } else { + * setSyncScrolling + * (fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING + * )); } + */ + setSyncScrolling(fPreferenceStore + .getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING)); + update(false); - + if (!fHasErrors && !emptyInput && !fComposite.isDisposed()) { if (isRefreshing()) { - fLeftContributor.updateSelection(fLeft, !fSynchronizedScrolling); - fRightContributor.updateSelection(fRight, !fSynchronizedScrolling); - fAncestorContributor.updateSelection(fAncestor, !fSynchronizedScrolling); + fLeftContributor + .updateSelection(fLeft, !fSynchronizedScrolling); + fRightContributor.updateSelection(fRight, + !fSynchronizedScrolling); + fAncestorContributor.updateSelection(fAncestor, + !fSynchronizedScrolling); if (fSynchronizedScrolling && fSynchronziedScrollPosition != -1) { synchronizedScrollVertical(fSynchronziedScrollPosition); } } else { if (isPatchHunk()) { - if (right != null && Utilities.getAdapter(right, IHunk.class) != null) + if (right != null + && Utilities.getAdapter(right, IHunk.class) != null) fLeft.setTopIndex(getHunkStart()); else fRight.setTopIndex(getHunkStart()); } else { - Diff selectDiff= null; + Diff selectDiff = null; if (FIX_47640) { if (leftRange != null) - selectDiff= fMerger.findDiff(LEFT_CONTRIBUTOR, leftRange); + selectDiff = fMerger.findDiff(LEFT_CONTRIBUTOR, + leftRange); else if (rightRange != null) - selectDiff= fMerger.findDiff(RIGHT_CONTRIBUTOR, rightRange); + selectDiff = fMerger.findDiff(RIGHT_CONTRIBUTOR, + rightRange); } if (selectDiff != null) setCurrentDiff(selectDiff, true); @@ -2594,7 +2810,7 @@ } } } - + } private boolean isRefreshing() { @@ -2604,51 +2820,55 @@ private ContributorInfo createLegInfoFor(Object element, char leg) { return new ContributorInfo(this, element, leg); } - + private void updateDiffBackground(Diff diff) { - - if (! fHighlightRanges) + + if (!fHighlightRanges) return; - + if (diff == null || diff.isToken()) return; - + if (fShowCurrentOnly && !isCurrentDiff(diff)) return; - - Color c= getColor(null, getFillColor(diff)); + + Color c = getColor(null, getFillColor(diff)); if (c == null) return; - + if (isThreeWay()) - fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c); + fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), + c); fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c); fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c); } - + private void updateAllDiffBackgrounds(Display display) { if (fMerger.hasChanges()) { - boolean threeWay= isThreeWay(); - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + boolean threeWay = isThreeWay(); + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); - Color c= getColor(display, getFillColor(diff)); + Color c = getColor(display, getFillColor(diff)); if (threeWay) - fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c); + fAncestor.setLineBackground(diff + .getPosition(ANCESTOR_CONTRIBUTOR), c); fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c); - fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c); + fRight + .setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), + c); } } } - + /* - * Called whenever one of the documents changes. - * Sets the dirty state of this viewer and updates the lines. - * Implements IDocumentListener. + * Called whenever one of the documents changes. Sets the dirty state of + * this viewer and updates the lines. Implements IDocumentListener. */ private void documentChanged(DocumentEvent e, boolean dirty) { - - IDocument doc= e.getDocument(); - + + IDocument doc = e.getDocument(); + if (doc == fLeft.getDocument()) { setLeftDirty(dirty); } else if (doc == fRight.getDocument()) { @@ -2657,64 +2877,70 @@ updateLines(doc); } - + /* - * This method is called if a range of text on one side is copied into an empty sub-document - * on the other side. The method returns the position where the sub-document is placed into the base document. - * This default implementation determines the position by using the text range differencer. - * However this position is not always optimal for specific types of text. - * So subclasses (which are aware of the type of text they are dealing with) - * may override this method to find a better position where to insert a newly added - * piece of text. - * @param type the side for which the insertion position should be determined: 'A' for ancestor, 'L' for left hand side, 'R' for right hand side. + * This method is called if a range of text on one side is copied into an + * empty sub-document on the other side. The method returns the position + * where the sub-document is placed into the base document. This default + * implementation determines the position by using the text range + * differencer. However this position is not always optimal for specific + * types of text. So subclasses (which are aware of the type of text they + * are dealing with) may override this method to find a better position + * where to insert a newly added piece of text. + * + * @param type the side for which the insertion position should be + * determined: 'A' for ancestor, 'L' for left hand side, 'R' for right hand + * side. + * * @param input the current input object of this viewer + * * @since 2.0 */ protected int findInsertionPosition(char type, ICompareInput input) { - - ITypedElement other= null; - char otherType= 0; - + + ITypedElement other = null; + char otherType = 0; + switch (type) { case ANCESTOR_CONTRIBUTOR: - other= input.getLeft(); - otherType= LEFT_CONTRIBUTOR; + other = input.getLeft(); + otherType = LEFT_CONTRIBUTOR; if (other == null) { - other= input.getRight(); - otherType= RIGHT_CONTRIBUTOR; + other = input.getRight(); + otherType = RIGHT_CONTRIBUTOR; } break; case LEFT_CONTRIBUTOR: - other= input.getRight(); - otherType= RIGHT_CONTRIBUTOR; + other = input.getRight(); + otherType = RIGHT_CONTRIBUTOR; if (other == null) { - other= input.getAncestor(); - otherType= ANCESTOR_CONTRIBUTOR; + other = input.getAncestor(); + otherType = ANCESTOR_CONTRIBUTOR; } break; case RIGHT_CONTRIBUTOR: - other= input.getLeft(); - otherType= LEFT_CONTRIBUTOR; + other = input.getLeft(); + otherType = LEFT_CONTRIBUTOR; if (other == null) { - other= input.getAncestor(); - otherType= ANCESTOR_CONTRIBUTOR; + other = input.getAncestor(); + otherType = ANCESTOR_CONTRIBUTOR; } break; } - + if (other instanceof IDocumentRange) { - IDocumentRange dr= (IDocumentRange) other; - Position p= dr.getRange(); - Diff diff= findDiff(otherType, p.offset); + IDocumentRange dr = (IDocumentRange) other; + Position p = dr.getRange(); + Diff diff = findDiff(otherType, p.offset); return fMerger.findInsertionPoint(diff, type); } return 0; } - + private void setError(char type, String message) { - IMergeViewerContentProvider cp= getMergeContentProvider(); + IMergeViewerContentProvider cp = getMergeContentProvider(); if (cp instanceof MergeViewerContentProvider) { - MergeViewerContentProvider mcp= (MergeViewerContentProvider) cp; + MergeViewerContentProvider mcp = (MergeViewerContentProvider) cp; switch (type) { case ANCESTOR_CONTRIBUTOR: mcp.setAncestorError(message); @@ -2727,7 +2953,7 @@ break; } } - fHasErrors= true; + fHasErrors = true; } private void updateDirtyState(IEditorInput key, @@ -2750,7 +2976,7 @@ } return null; } - + private void addNewRange(char type, Object input, Position range) { switch (type) { case ANCESTOR_CONTRIBUTOR: @@ -2764,26 +2990,31 @@ break; } } - + /** - * Returns the contents of the underlying document as an array of bytes using the current workbench encoding. + * Returns the contents of the underlying document as an array of bytes + * using the current workbench encoding. * - * @param left if true the contents of the left side is returned; otherwise the right side + * @param left + * if true the contents of the left side is + * returned; otherwise the right side * @return the contents of the left or right document or null */ protected byte[] getContents(boolean left) { - MergeSourceViewer v= left ? fLeft : fRight; + MergeSourceViewer v = left ? fLeft : fRight; if (v != null) { - IDocument d= v.getDocument(); + IDocument d = v.getDocument(); if (d != null) { - String contents= d.get(); + String contents = d.get(); if (contents != null) { byte[] bytes; try { - bytes= contents.getBytes(left ? fLeftContributor.getEncoding() : fRightContributor.getEncoding()); - } catch(UnsupportedEncodingException ex) { + bytes = contents.getBytes(left ? fLeftContributor + .getEncoding() : fRightContributor + .getEncoding()); + } catch (UnsupportedEncodingException ex) { // use default encoding - bytes= contents.getBytes(); + bytes = contents.getBytes(); } return bytes; } @@ -2791,146 +3022,165 @@ } return null; } - + private IRegion normalizeDocumentRegion(IDocument doc, IRegion region) { - + if (region == null || doc == null) return region; - - int maxLength= doc.getLength(); - - int start= region.getOffset(); + + int maxLength = doc.getLength(); + + int start = region.getOffset(); if (start < 0) - start= 0; + start = 0; else if (start > maxLength) - start= maxLength; - - int length= region.getLength(); + start = maxLength; + + int length = region.getLength(); if (length < 0) - length= 0; + length = 0; else if (start + length > maxLength) - length= maxLength - start; - + length = maxLength - start; + return new Region(start, length); } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handleResizeAncestor(int, int, int, int) + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.compare.contentmergeviewer.ContentMergeViewer# + * handleResizeAncestor(int, int, int, int) */ - protected final void handleResizeAncestor(int x, int y, int width, int height) { + protected final void handleResizeAncestor(int x, int y, int width, + int height) { if (width > 0) { - Rectangle trim= fLeft.getTextWidget().computeTrim(0, 0, 0, 0); - int scrollbarHeight= trim.height; + Rectangle trim = fLeft.getTextWidget().computeTrim(0, 0, 0, 0); + int scrollbarHeight = trim.height; if (Utilities.okToUse(fAncestorCanvas)) fAncestorCanvas.setVisible(true); if (fAncestor.isControlOkToUse()) fAncestor.getTextWidget().setVisible(true); - + if (fAncestorCanvas != null) { - fAncestorCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight); - x+= fMarginWidth; - width-= fMarginWidth; + fAncestorCanvas.setBounds(x, y, fMarginWidth, height + - scrollbarHeight); + x += fMarginWidth; + width -= fMarginWidth; } fAncestor.setBounds(x, y, width, height); } else { if (Utilities.okToUse(fAncestorCanvas)) fAncestorCanvas.setVisible(false); if (fAncestor.isControlOkToUse()) { - StyledText t= fAncestor.getTextWidget(); + StyledText t = fAncestor.getTextWidget(); t.setVisible(false); fAncestor.setBounds(0, 0, 0, 0); if (fFocusPart == fAncestor) { - fFocusPart= fLeft; + fFocusPart = fLeft; fFocusPart.getTextWidget().setFocus(); } } } } - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handleResizeLeftRight(int, int, int, int, int, int) - */ - protected final void handleResizeLeftRight(int x, int y, int width1, int centerWidth, int width2, int height) { - - if (fBirdsEyeCanvas != null) - width2-= BIRDS_EYE_VIEW_WIDTH; - - Rectangle trim= fLeft.getTextWidget().computeTrim(0, 0, 0, 0); - int scrollbarHeight= trim.height + trim.x; + /* + * (non-Javadoc) + * + * @seeorg.eclipse.compare.contentmergeviewer.ContentMergeViewer# + * handleResizeLeftRight(int, int, int, int, int, int) + */ + protected final void handleResizeLeftRight(int x, int y, int width1, + int centerWidth, int width2, int height) { + + if (fBirdsEyeCanvas != null) + width2 -= BIRDS_EYE_VIEW_WIDTH; + + Rectangle trim = fLeft.getTextWidget().computeTrim(0, 0, 0, 0); + int scrollbarHeight = trim.height + trim.x; - Composite composite= (Composite) getControl(); + Composite composite = (Composite) getControl(); - int leftTextWidth= width1; + int leftTextWidth = width1; if (fLeftCanvas != null) { - fLeftCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight); - x+= fMarginWidth; - leftTextWidth-= fMarginWidth; + fLeftCanvas.setBounds(x, y, fMarginWidth, height - scrollbarHeight); + x += fMarginWidth; + leftTextWidth -= fMarginWidth; } - + fLeft.setBounds(x, y, leftTextWidth, height); - x+= leftTextWidth; - + x += leftTextWidth; + if (fCenter == null || fCenter.isDisposed()) - fCenter= createCenterControl(composite); - fCenter.setBounds(x, y, centerWidth, height-scrollbarHeight); - x+= centerWidth; - - if (!fSynchronizedScrolling) { // canvas is to the left of text + fCenter = createCenterControl(composite); + fCenter.setBounds(x, y, centerWidth, height - scrollbarHeight); + x += centerWidth; + + if (!fSynchronizedScrolling) { // canvas is to the left of text if (fRightCanvas != null) { - fRightCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight); + fRightCanvas.setBounds(x, y, fMarginWidth, height + - scrollbarHeight); fRightCanvas.redraw(); - x+= fMarginWidth; + x += fMarginWidth; } // we draw the canvas to the left of the text widget } - - int scrollbarWidth= 0; + + int scrollbarWidth = 0; if (fSynchronizedScrolling && fScrollCanvas != null) { - trim= fLeft.getTextWidget().computeTrim(0, 0, 0, 0); - // one pixel was cut off - scrollbarWidth= trim.width + 2*trim.x+1; + trim = fLeft.getTextWidget().computeTrim(0, 0, 0, 0); + // one pixel was cut off + scrollbarWidth = trim.width + 2 * trim.x + 1; } - int rightTextWidth= width2-scrollbarWidth; + int rightTextWidth = width2 - scrollbarWidth; if (fRightCanvas != null) - rightTextWidth-= fMarginWidth; + rightTextWidth -= fMarginWidth; fRight.setBounds(x, y, rightTextWidth, height); - x+= rightTextWidth; - + x += rightTextWidth; + if (fSynchronizedScrolling) { - if (fRightCanvas != null) { // canvas is to the right of the text - fRightCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight); - x+= fMarginWidth; + if (fRightCanvas != null) { // canvas is to the right of the text + fRightCanvas.setBounds(x, y, fMarginWidth, height + - scrollbarHeight); + x += fMarginWidth; } if (fScrollCanvas != null) - fScrollCanvas.setBounds(x, y, scrollbarWidth, height-scrollbarHeight); + fScrollCanvas.setBounds(x, y, scrollbarWidth, height + - scrollbarHeight); } - - if (fBirdsEyeCanvas != null) { - int verticalScrollbarButtonHeight= scrollbarWidth; - int horizontalScrollbarButtonHeight= scrollbarHeight; + + if (fBirdsEyeCanvas != null) { + int verticalScrollbarButtonHeight = scrollbarWidth; + int horizontalScrollbarButtonHeight = scrollbarHeight; if (fIsCarbon) { - verticalScrollbarButtonHeight+= 2; - horizontalScrollbarButtonHeight= 18; + verticalScrollbarButtonHeight += 2; + horizontalScrollbarButtonHeight = 18; } - if (fSummaryHeader != null) - fSummaryHeader.setBounds(x+scrollbarWidth, y, BIRDS_EYE_VIEW_WIDTH, verticalScrollbarButtonHeight); - y+= verticalScrollbarButtonHeight; - fBirdsEyeCanvas.setBounds(x+scrollbarWidth, y, BIRDS_EYE_VIEW_WIDTH, height-(2*verticalScrollbarButtonHeight+horizontalScrollbarButtonHeight)); - } - + if (fSummaryHeader != null) + fSummaryHeader.setBounds(x + scrollbarWidth, y, + BIRDS_EYE_VIEW_WIDTH, verticalScrollbarButtonHeight); + y += verticalScrollbarButtonHeight; + fBirdsEyeCanvas + .setBounds( + x + scrollbarWidth, + y, + BIRDS_EYE_VIEW_WIDTH, + height + - (2 * verticalScrollbarButtonHeight + horizontalScrollbarButtonHeight)); + } + // doesn't work since TextEditors don't have their correct size yet. updateVScrollBar(); refreshBirdsEyeView(); } - + /* * Track selection changes to update the current Diff. */ private void handleSelectionChanged(MergeSourceViewer tw) { - Point p= tw.getSelectedRange(); - Diff d= findDiff(tw, p.x, p.x+p.y); + Point p = tw.getSelectedRange(); + Diff d = findDiff(tw, p.x, p.x + p.y); updateStatus(d); - setCurrentDiff(d, false); // don't select or reveal + setCurrentDiff(d, false); // don't select or reveal } private static IRegion toRegion(Position position) { @@ -2938,55 +3188,64 @@ return new Region(position.getOffset(), position.getLength()); return null; } - - //---- the differencing - + + // ---- the differencing + /** - * Perform a two level 2- or 3-way diff. - * The first level is based on line comparison, the second level on token comparison. + * Perform a two level 2- or 3-way diff. The first level is based on line + * comparison, the second level on token comparison. */ private void doDiff() { - IDocument lDoc= fLeft.getDocument(); - IDocument rDoc= fRight.getDocument(); + IDocument lDoc = fLeft.getDocument(); + IDocument rDoc = fRight.getDocument(); if (lDoc == null || rDoc == null) return; fAncestor.resetLineBackground(); fLeft.resetLineBackground(); fRight.resetLineBackground(); - - fCurrentDiff= null; + + fCurrentDiff = null; try { fMerger.doDiff(); } catch (CoreException e) { CompareUIPlugin.log(e.getStatus()); - String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$ - String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$ - String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } ); + String title = Utilities.getString(getResourceBundle(), + "tooComplexError.title"); //$NON-NLS-1$ + String format = Utilities.getString(getResourceBundle(), + "tooComplexError.format"); //$NON-NLS-1$ + String msg = MessageFormat.format(format, new Object[] { Integer + .toString(PlatformUI.getWorkbench().getProgressService() + .getLongOperationTime() / 1000) }); MessageDialog.openError(fComposite.getShell(), title, msg); } - + if (fMerger.hasChanges()) { - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); updateDiffBackground(diff); } } invalidateTextPresentation(); } - + private Diff findDiff(char type, int pos) { try { return fMerger.findDiff(type, pos); } catch (CoreException e) { CompareUIPlugin.log(e.getStatus()); - String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$ - String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$ - String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } ); + String title = Utilities.getString(getResourceBundle(), + "tooComplexError.title"); //$NON-NLS-1$ + String format = Utilities.getString(getResourceBundle(), + "tooComplexError.format"); //$NON-NLS-1$ + String msg = MessageFormat.format(format, new Object[] { Integer + .toString(PlatformUI.getWorkbench().getProgressService() + .getLongOperationTime() / 1000) }); MessageDialog.openError(fComposite.getShell(), title, msg); return null; } } - + private void resetPositions(IDocument doc) { if (doc == null) return; @@ -2997,164 +3256,177 @@ } doc.addPositionCategory(DIFF_RANGE_CATEGORY); } - - //---- update UI stuff - + + // ---- update UI stuff + private void updateControls() { - - boolean leftToRight= false; - boolean rightToLeft= false; - + + boolean leftToRight = false; + boolean rightToLeft = false; + updateStatus(fCurrentDiff); updateResolveStatus(); if (fCurrentDiff != null) { - IMergeViewerContentProvider cp= getMergeContentProvider(); + IMergeViewerContentProvider cp = getMergeContentProvider(); if (cp != null) { if (!isPatchHunk()) { - rightToLeft= cp.isLeftEditable(getInput()); - leftToRight= cp.isRightEditable(getInput()); + rightToLeft = cp.isLeftEditable(getInput()); + leftToRight = cp.isRightEditable(getInput()); } } } - + if (fDirectionLabel != null) { - if (fHighlightRanges && fCurrentDiff != null && isThreeWay() && !isIgnoreAncestor()) { + if (fHighlightRanges && fCurrentDiff != null && isThreeWay() + && !isIgnoreAncestor()) { fDirectionLabel.setImage(fCurrentDiff.getImage()); } else { fDirectionLabel.setImage(null); } } - + if (fCopyDiffLeftToRightItem != null) - ((Action)fCopyDiffLeftToRightItem.getAction()).setEnabled(leftToRight); + ((Action) fCopyDiffLeftToRightItem.getAction()) + .setEnabled(leftToRight); if (fCopyDiffRightToLeftItem != null) - ((Action)fCopyDiffRightToLeftItem.getAction()).setEnabled(rightToLeft); - - boolean enableNavigation= isNavigationPossible(); + ((Action) fCopyDiffRightToLeftItem.getAction()) + .setEnabled(rightToLeft); + + boolean enableNavigation = isNavigationPossible(); if (fNextDiff != null) { - IAction a= fNextDiff.getAction(); + IAction a = fNextDiff.getAction(); a.setEnabled(enableNavigation || hasNextElement(true)); } if (fPreviousDiff != null) { - IAction a= fPreviousDiff.getAction(); + IAction a = fPreviousDiff.getAction(); a.setEnabled(enableNavigation || hasNextElement(false)); } if (fNextChange != null) { - IAction a= fNextChange.getAction(); + IAction a = fNextChange.getAction(); a.setEnabled(enableNavigation); } if (fPreviousChange != null) { - IAction a= fPreviousChange.getAction(); + IAction a = fPreviousChange.getAction(); a.setEnabled(enableNavigation); } } - + private void updateResolveStatus() { - - RGB rgb= null; - + + RGB rgb = null; + if (showResolveUI()) { - // we only show red or green if there is at least one incoming or conflicting change - int incomingOrConflicting= 0; - int unresolvedIncoming= 0; - int unresolvedConflicting= 0; + // we only show red or green if there is at least one incoming or + // conflicting change + int incomingOrConflicting = 0; + int unresolvedIncoming = 0; + int unresolvedConflicting = 0; if (fMerger.hasChanges()) { for (Iterator iterator = fMerger.changesIterator(); iterator .hasNext();) { Diff d = (Diff) iterator.next(); - if (d.isIncomingOrConflicting() /* && useChange(d.fDirection) && !d.fIsWhitespace */) { + if (d.isIncomingOrConflicting() /* + * && + * useChange(d.fDirection) + * && !d.fIsWhitespace + */) { incomingOrConflicting++; if (!d.isResolved()) { if (d.getKind() == RangeDifference.CONFLICT) { unresolvedConflicting++; - break; // we can stop here because a conflict has the maximum priority + break; // we can stop here because a conflict + // has the maximum priority } unresolvedIncoming++; } } } } - + if (incomingOrConflicting > 0) { if (unresolvedConflicting > 0) - rgb= SELECTED_CONFLICT; + rgb = SELECTED_CONFLICT; else if (unresolvedIncoming > 0) - rgb= SELECTED_INCOMING; + rgb = SELECTED_INCOMING; else - rgb= RESOLVED; + rgb = RESOLVED; } } - + if (fHeaderPainter.setColor(rgb)) fSummaryHeader.redraw(); } private void updateStatus(Diff diff) { - - if (! fShowMoreInfo) + + if (!fShowMoreInfo) return; - + String diffDescription; - + if (diff == null) { - diffDescription= CompareMessages.TextMergeViewer_diffDescription_noDiff_format; + diffDescription = CompareMessages.TextMergeViewer_diffDescription_noDiff_format; } else { - - if (diff.isToken()) // we don't show special info for token diffs - diff= diff.getParent(); - - String format= CompareMessages.TextMergeViewer_diffDescription_diff_format; - diffDescription= MessageFormat.format(format, - new String[] { - getDiffType(diff), // 0: diff type - getDiffNumber(diff), // 1: diff number - getDiffRange(fLeft, diff.getPosition(LEFT_CONTRIBUTOR)), // 2: left start line - getDiffRange(fRight, diff.getPosition(RIGHT_CONTRIBUTOR)) // 3: left end line - } - ); - } - - String format= CompareMessages.TextMergeViewer_statusLine_format; - String s= MessageFormat.format(format, - new String[] { - getCursorPosition(fLeft), // 0: left column - getCursorPosition(fRight), // 1: right column - diffDescription // 2: diff description - } - ); - + + if (diff.isToken()) // we don't show special info for token diffs + diff = diff.getParent(); + + String format = CompareMessages.TextMergeViewer_diffDescription_diff_format; + diffDescription = MessageFormat.format(format, new String[] { + getDiffType(diff), // 0: diff type + getDiffNumber(diff), // 1: diff number + getDiffRange(fLeft, diff.getPosition(LEFT_CONTRIBUTOR)), // 2: + // left + // start + // line + getDiffRange(fRight, diff.getPosition(RIGHT_CONTRIBUTOR)) // 3: + // left + // end + // line + }); + } + + String format = CompareMessages.TextMergeViewer_statusLine_format; + String s = MessageFormat.format(format, new String[] { + getCursorPosition(fLeft), // 0: left column + getCursorPosition(fRight), // 1: right column + diffDescription // 2: diff description + }); + getCompareConfiguration().getContainer().setStatusMessage(s); } private void clearStatus() { getCompareConfiguration().getContainer().setStatusMessage(null); } - + private String getDiffType(Diff diff) { - String s= ""; //$NON-NLS-1$ - switch(diff.getKind()) { + String s = ""; //$NON-NLS-1$ + switch (diff.getKind()) { case RangeDifference.LEFT: - s= CompareMessages.TextMergeViewer_direction_outgoing; + s = CompareMessages.TextMergeViewer_direction_outgoing; break; case RangeDifference.RIGHT: - s= CompareMessages.TextMergeViewer_direction_incoming; + s = CompareMessages.TextMergeViewer_direction_incoming; break; case RangeDifference.CONFLICT: - s= CompareMessages.TextMergeViewer_direction_conflicting; + s = CompareMessages.TextMergeViewer_direction_conflicting; break; } - String format= CompareMessages.TextMergeViewer_diffType_format; - return MessageFormat.format(format, new String[] { s, diff.changeType() } ); + String format = CompareMessages.TextMergeViewer_diffType_format; + return MessageFormat.format(format, + new String[] { s, diff.changeType() }); } - + private String getDiffNumber(Diff diff) { // find the diff's number - int diffNumber= 0; + int diffNumber = 0; if (fMerger.hasChanges()) { - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff d = (Diff) iterator.next(); diffNumber++; if (d == diff) @@ -3163,22 +3435,21 @@ } return Integer.toString(diffNumber); } - + private String getDiffRange(MergeSourceViewer v, Position pos) { - Point p= v.getLineRange(pos, new Point(0, 0)); - int startLine= p.x+1; - int endLine= p.x+p.y; - + Point p = v.getLineRange(pos, new Point(0, 0)); + int startLine = p.x + 1; + int endLine = p.x + p.y; + String format; if (endLine < startLine) - format= CompareMessages.TextMergeViewer_beforeLine_format; + format = CompareMessages.TextMergeViewer_beforeLine_format; else - format= CompareMessages.TextMergeViewer_range_format; - return MessageFormat.format(format, - new String[] { Integer.toString(startLine), - Integer.toString(endLine) } ); + format = CompareMessages.TextMergeViewer_range_format; + return MessageFormat.format(format, new String[] { + Integer.toString(startLine), Integer.toString(endLine) }); } - + /* * Returns a description of the cursor position. * @@ -3186,75 +3457,86 @@ */ private String getCursorPosition(MergeSourceViewer v) { if (v != null) { - StyledText styledText= v.getTextWidget(); - - IDocument document= v.getDocument(); + StyledText styledText = v.getTextWidget(); + + IDocument document = v.getDocument(); if (document != null) { - int offset= v.getVisibleRegion().getOffset(); - int caret= offset + styledText.getCaretOffset(); - + int offset = v.getVisibleRegion().getOffset(); + int caret = offset + styledText.getCaretOffset(); + try { - - int line=document.getLineOfOffset(caret); - - int lineOffset= document.getLineOffset(line); - int occurrences= 0; - for (int i= lineOffset; i < caret; i++) + + int line = document.getLineOfOffset(caret); + + int lineOffset = document.getLineOffset(line); + int occurrences = 0; + for (int i = lineOffset; i < caret; i++) if ('\t' == document.getChar(i)) - ++ occurrences; - - int tabWidth= styledText.getTabs(); - int column= caret - lineOffset + (tabWidth -1) * occurrences; - - String format= CompareMessages.TextMergeViewer_cursorPosition_format; - return MessageFormat.format(format, - new String[] { Integer.toString(line + 1), Integer.toString(column + 1) } ); - + ++occurrences; + + int tabWidth = styledText.getTabs(); + int column = caret - lineOffset + (tabWidth - 1) + * occurrences; + + String format = CompareMessages.TextMergeViewer_cursorPosition_format; + return MessageFormat.format(format, new String[] { + Integer.toString(line + 1), + Integer.toString(column + 1) }); + } catch (BadLocationException x) { // silently ignored } } } - return ""; //$NON-NLS-1$ + return ""; //$NON-NLS-1$ } protected void updateHeader() { - + super.updateHeader(); - + updateControls(); } /* - * Creates the two items for copying a difference range from one side to the other - * and adds them to the given toolbar manager. + * Creates the two items for copying a difference range from one side to the + * other and adds them to the given toolbar manager. */ protected void createToolItems(ToolBarManager tbm) { - fHandlerService= CompareHandlerService.createFor(getCompareConfiguration().getContainer(), fLeft.getControl().getShell()); - - final String ignoreAncestorActionKey= "action.IgnoreAncestor."; //$NON-NLS-1$ - Action ignoreAncestorAction= new Action() { + fHandlerService = CompareHandlerService.createFor( + getCompareConfiguration().getContainer(), fLeft.getControl() + .getShell()); + + final String ignoreAncestorActionKey = "action.IgnoreAncestor."; //$NON-NLS-1$ + Action ignoreAncestorAction = new Action() { public void run() { // First make sure the ancestor is hidden if (!isIgnoreAncestor()) - getCompareConfiguration().setProperty(ICompareUIConstants.PROP_ANCESTOR_VISIBLE, Boolean.FALSE); + getCompareConfiguration().setProperty( + ICompareUIConstants.PROP_ANCESTOR_VISIBLE, + Boolean.FALSE); // Then set the property to ignore the ancestor - getCompareConfiguration().setProperty(ICompareUIConstants.PROP_IGNORE_ANCESTOR, Boolean.valueOf(!isIgnoreAncestor())); - Utilities.initToggleAction(this, getResourceBundle(), ignoreAncestorActionKey, isIgnoreAncestor()); + getCompareConfiguration().setProperty( + ICompareUIConstants.PROP_IGNORE_ANCESTOR, + Boolean.valueOf(!isIgnoreAncestor())); + Utilities.initToggleAction(this, getResourceBundle(), + ignoreAncestorActionKey, isIgnoreAncestor()); } }; ignoreAncestorAction.setChecked(isIgnoreAncestor()); - Utilities.initAction(ignoreAncestorAction, getResourceBundle(), ignoreAncestorActionKey); - Utilities.initToggleAction(ignoreAncestorAction, getResourceBundle(), ignoreAncestorActionKey, isIgnoreAncestor()); - - fIgnoreAncestorItem= new ActionContributionItem(ignoreAncestorAction); + Utilities.initAction(ignoreAncestorAction, getResourceBundle(), + ignoreAncestorActionKey); + Utilities.initToggleAction(ignoreAncestorAction, getResourceBundle(), + ignoreAncestorActionKey, isIgnoreAncestor()); + + fIgnoreAncestorItem = new ActionContributionItem(ignoreAncestorAction); fIgnoreAncestorItem.setVisible(false); tbm.appendToGroup("modes", fIgnoreAncestorItem); //$NON-NLS-1$ tbm.add(new Separator()); - - Action a= new Action() { + + Action a = new Action() { public void run() { if (navigate(true, false, false)) { endOfDocumentReached(true); @@ -3262,11 +3544,12 @@ } }; Utilities.initAction(a, getResourceBundle(), "action.NextDiff."); //$NON-NLS-1$ - fNextDiff= new ActionContributionItem(a); + fNextDiff = new ActionContributionItem(a); tbm.appendToGroup("navigation", fNextDiff); //$NON-NLS-1$ - // Don't register this action since it is probably registered by the container - - a= new Action() { + // Don't register this action since it is probably registered by the + // container + + a = new Action() { public void run() { if (navigate(false, false, false)) { endOfDocumentReached(false); @@ -3274,11 +3557,12 @@ } }; Utilities.initAction(a, getResourceBundle(), "action.PrevDiff."); //$NON-NLS-1$ - fPreviousDiff= new ActionContributionItem(a); + fPreviousDiff = new ActionContributionItem(a); tbm.appendToGroup("navigation", fPreviousDiff); //$NON-NLS-1$ - // Don't register this action since it is probably registered by the container - - a= new Action() { + // Don't register this action since it is probably registered by the + // container + + a = new Action() { public void run() { if (navigate(true, false, true)) { endOfDocumentReached(true); @@ -3286,11 +3570,12 @@ } }; Utilities.initAction(a, getResourceBundle(), "action.NextChange."); //$NON-NLS-1$ - fNextChange= new ActionContributionItem(a); + fNextChange = new ActionContributionItem(a); tbm.appendToGroup("navigation", fNextChange); //$NON-NLS-1$ - fHandlerService.registerAction(a, "org.eclipse.compare.selectNextChange"); //$NON-NLS-1$ - - a= new Action() { + fHandlerService.registerAction(a, + "org.eclipse.compare.selectNextChange"); //$NON-NLS-1$ + + a = new Action() { public void run() { if (navigate(false, false, true)) { endOfDocumentReached(false); @@ -3298,110 +3583,131 @@ } }; Utilities.initAction(a, getResourceBundle(), "action.PrevChange."); //$NON-NLS-1$ - fPreviousChange= new ActionContributionItem(a); + fPreviousChange = new ActionContributionItem(a); tbm.appendToGroup("navigation", fPreviousChange); //$NON-NLS-1$ - fHandlerService.registerAction(a, "org.eclipse.compare.selectPreviousChange"); //$NON-NLS-1$ + fHandlerService.registerAction(a, + "org.eclipse.compare.selectPreviousChange"); //$NON-NLS-1$ + + CompareConfiguration cc = getCompareConfiguration(); - CompareConfiguration cc= getCompareConfiguration(); - if (cc.isRightEditable()) { - a= new Action() { + a = new Action() { public void run() { copyDiffLeftToRight(); } }; - Utilities.initAction(a, getResourceBundle(), "action.CopyDiffLeftToRight."); //$NON-NLS-1$ - fCopyDiffLeftToRightItem= new ActionContributionItem(a); + Utilities.initAction(a, getResourceBundle(), + "action.CopyDiffLeftToRight."); //$NON-NLS-1$ + fCopyDiffLeftToRightItem = new ActionContributionItem(a); fCopyDiffLeftToRightItem.setVisible(true); tbm.appendToGroup("merge", fCopyDiffLeftToRightItem); //$NON-NLS-1$ - fHandlerService.registerAction(a, "org.eclipse.compare.copyLeftToRight"); //$NON-NLS-1$ + fHandlerService.registerAction(a, + "org.eclipse.compare.copyLeftToRight"); //$NON-NLS-1$ } - + if (cc.isLeftEditable()) { - a= new Action() { + a = new Action() { public void run() { copyDiffRightToLeft(); } }; - Utilities.initAction(a, getResourceBundle(), "action.CopyDiffRightToLeft."); //$NON-NLS-1$ - fCopyDiffRightToLeftItem= new ActionContributionItem(a); + Utilities.initAction(a, getResourceBundle(), + "action.CopyDiffRightToLeft."); //$NON-NLS-1$ + fCopyDiffRightToLeftItem = new ActionContributionItem(a); fCopyDiffRightToLeftItem.setVisible(true); tbm.appendToGroup("merge", fCopyDiffRightToLeftItem); //$NON-NLS-1$ - fHandlerService.registerAction(a, "org.eclipse.compare.copyRightToLeft"); //$NON-NLS-1$ + fHandlerService.registerAction(a, + "org.eclipse.compare.copyRightToLeft"); //$NON-NLS-1$ } - - fIgnoreWhitespace= ChangePropertyAction.createIgnoreWhiteSpaceAction(getResourceBundle(), getCompareConfiguration()); - fIgnoreWhitespace.setActionDefinitionId(ICompareUIConstants.COMMAND_IGNORE_WHITESPACE); + + fIgnoreWhitespace = ChangePropertyAction.createIgnoreWhiteSpaceAction( + getResourceBundle(), getCompareConfiguration()); + fIgnoreWhitespace + .setActionDefinitionId(ICompareUIConstants.COMMAND_IGNORE_WHITESPACE); fLeft.addTextAction(fIgnoreWhitespace); fRight.addTextAction(fIgnoreWhitespace); fAncestor.addTextAction(fIgnoreWhitespace); - fHandlerService.registerAction(fIgnoreWhitespace, fIgnoreWhitespace.getActionDefinitionId()); - - showWhitespaceAction = new ShowWhitespaceAction(new MergeSourceViewer[] { - fLeft, fRight, fAncestor - }); - fHandlerService.registerAction(showWhitespaceAction, ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS); - - toggleLineNumbersAction = new TextEditorPropertyAction(CompareMessages.TextMergeViewer_16, new MergeSourceViewer[] { - fLeft, fRight, fAncestor - }, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER); - fHandlerService.registerAction(toggleLineNumbersAction, ITextEditorActionDefinitionIds.LINENUMBER_TOGGLE); - } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handlePropertyChangeEvent(org.eclipse.jface.util.PropertyChangeEvent) + fHandlerService.registerAction(fIgnoreWhitespace, fIgnoreWhitespace + .getActionDefinitionId()); + + showWhitespaceAction = new ShowWhitespaceAction( + new MergeSourceViewer[] { fLeft, fRight, fAncestor }); + fHandlerService.registerAction(showWhitespaceAction, + ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS); + + toggleLineNumbersAction = new TextEditorPropertyAction( + CompareMessages.TextMergeViewer_16, + new MergeSourceViewer[] { fLeft, fRight, fAncestor }, + AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER); + fHandlerService.registerAction(toggleLineNumbersAction, + ITextEditorActionDefinitionIds.LINENUMBER_TOGGLE); + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.compare.contentmergeviewer.ContentMergeViewer# + * handlePropertyChangeEvent(org.eclipse.jface.util.PropertyChangeEvent) */ protected void handlePropertyChangeEvent(PropertyChangeEvent event) { - - String key= event.getProperty(); - + + String key = event.getProperty(); + if (key.equals(CompareConfiguration.IGNORE_WHITESPACE) || key.equals(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS)) { - - fShowPseudoConflicts= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS); - + + fShowPseudoConflicts = fPreferenceStore + .getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS); + update(true); selectFirstDiff(true); - -// } else if (key.equals(ComparePreferencePage.USE_SPLINES)) { -// fUseSplines= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES); -// invalidateLines(); + + // } else if (key.equals(ComparePreferencePage.USE_SPLINES)) { + // fUseSplines= + // fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES); + // invalidateLines(); } else if (key.equals(ComparePreferencePage.USE_SINGLE_LINE)) { - fUseSingleLine= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SINGLE_LINE); -// fUseResolveUI= fUseSingleLine; - fBasicCenterCurve= null; + fUseSingleLine = fPreferenceStore + .getBoolean(ComparePreferencePage.USE_SINGLE_LINE); + // fUseResolveUI= fUseSingleLine; + fBasicCenterCurve = null; updateResolveStatus(); invalidateLines(); - + } else if (key.equals(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES)) { - fHighlightTokenChanges= fPreferenceStore.getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES); + fHighlightTokenChanges = fPreferenceStore + .getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES); updateResolveStatus(); updatePresentation(null); - -// } else if (key.equals(ComparePreferencePage.USE_RESOLVE_UI)) { -// fUseResolveUI= fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI); -// updateResolveStatus(); -// invalidateLines(); - + + // } else if (key.equals(ComparePreferencePage.USE_RESOLVE_UI)) { + // fUseResolveUI= + // fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI); + // updateResolveStatus(); + // invalidateLines(); + } else if (key.equals(fSymbolicFontName)) { updateFont(); invalidateLines(); - } else if (key.equals(INCOMING_COLOR) || key.equals(OUTGOING_COLOR) || key.equals(CONFLICTING_COLOR) || key.equals(RESOLVED_COLOR)) { + } else if (key.equals(INCOMING_COLOR) || key.equals(OUTGOING_COLOR) + || key.equals(CONFLICTING_COLOR) || key.equals(RESOLVED_COLOR)) { updateColors(null); invalidateLines(); invalidateTextPresentation(); - + } else if (key.equals(ComparePreferencePage.SYNCHRONIZE_SCROLLING)) { - boolean b= fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING); + boolean b = fPreferenceStore + .getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING); setSyncScrolling(b); - + } else if (key.equals(ComparePreferencePage.SHOW_MORE_INFO)) { - - boolean b= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_MORE_INFO); + + boolean b = fPreferenceStore + .getBoolean(ComparePreferencePage.SHOW_MORE_INFO); if (b != fShowMoreInfo) { - fShowMoreInfo= b; + fShowMoreInfo = b; if (fShowMoreInfo) updateStatus(fCurrentDiff); else @@ -3409,119 +3715,127 @@ } } else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)) { if (!fIsUsingSystemBackground) { - setBackgroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)); + setBackgroundColor(createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)); } - } else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) { - fIsUsingSystemBackground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT); + } else if (key + .equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) { + fIsUsingSystemBackground = fPreferenceStore + .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT); if (fIsUsingSystemBackground) { setBackgroundColor(null); } else { - setBackgroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)); + setBackgroundColor(createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)); } } else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)) { if (!fIsUsingSystemForeground) { - setForegroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)); + setForegroundColor(createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)); } - } else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT)) { - fIsUsingSystemForeground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT); + } else if (key + .equals(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT)) { + fIsUsingSystemForeground = fPreferenceStore + .getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT); if (fIsUsingSystemForeground) { setForegroundColor(null); } else { - setForegroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)); + setForegroundColor(createColor(fPreferenceStore, + AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)); } } else { super.handlePropertyChangeEvent(event); - + if (key.equals(ICompareUIConstants.PROP_IGNORE_ANCESTOR)) { update(false); selectFirstDiff(true); } } } - + private void selectFirstDiff(boolean first) { - + if (fLeft == null || fRight == null) { return; } if (fLeft.getDocument() == null || fRight.getDocument() == null) { return; } - - Diff firstDiff= null; + + Diff firstDiff = null; if (first) - firstDiff= findNext(fRight, -1, -1, false); + firstDiff = findNext(fRight, -1, -1, false); else - firstDiff= findPrev(fRight, 9999999, 9999999, false); + firstDiff = findPrev(fRight, 9999999, 9999999, false); setCurrentDiff(firstDiff, true); } - - - + private void setSyncScrolling(boolean newMode) { if (fSynchronizedScrolling != newMode) { - fSynchronizedScrolling= newMode; - + fSynchronizedScrolling = newMode; + scrollVertical(0, 0, 0, null); - + // throw away central control (Sash or Canvas) - Control center= getCenterControl(); + Control center = getCenterControl(); if (center != null && !center.isDisposed()) center.dispose(); - - fLeft.getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling); - fRight.getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling); - + + fLeft.getTextWidget().getVerticalBar().setVisible( + !fSynchronizedScrolling); + fRight.getTextWidget().getVerticalBar().setVisible( + !fSynchronizedScrolling); + fComposite.layout(true); } } - + protected void updateToolItems() { - //only update toolbar items if diffs need to be calculated (which - //dictates whether a toolbar gets added at all) - if (!isPatchHunk()){ + // only update toolbar items if diffs need to be calculated (which + // dictates whether a toolbar gets added at all) + if (!isPatchHunk()) { if (fIgnoreAncestorItem != null) fIgnoreAncestorItem.setVisible(isThreeWay()); - + if (fCopyDiffLeftToRightItem != null) { - IAction a= fCopyDiffLeftToRightItem.getAction(); + IAction a = fCopyDiffLeftToRightItem.getAction(); if (a != null) a.setEnabled(a.isEnabled() && !fHasErrors); } if (fCopyDiffRightToLeftItem != null) { - IAction a= fCopyDiffRightToLeftItem.getAction(); + IAction a = fCopyDiffRightToLeftItem.getAction(); if (a != null) a.setEnabled(a.isEnabled() && !fHasErrors); } - + super.updateToolItems(); } } - - //---- painting lines - + + // ---- painting lines + private void updateLines(IDocument d) { - boolean left= false; - boolean right= false; - + boolean left = false; + boolean right = false; + // FIXME: this optimization is incorrect because // it doesn't take replace operations into account where // the old and new line count does not differ if (d == fLeft.getDocument()) { - int l= fLeft.getLineCount(); - left= fLeftLineCount != l; - fLeftLineCount= l; + int l = fLeft.getLineCount(); + left = fLeftLineCount != l; + fLeftLineCount = l; } else if (d == fRight.getDocument()) { - int l= fRight.getLineCount(); - right= fRightLineCount != l; - fRightLineCount= l; + int l = fRight.getLineCount(); + right = fRightLineCount != l; + fRightLineCount = l; } - + if (left || right) { - + if (left) { if (fLeftCanvas != null) fLeftCanvas.redraw(); @@ -3529,7 +3843,7 @@ if (fRightCanvas != null) fRightCanvas.redraw(); } - Control center= getCenterControl(); + Control center = getCenterControl(); if (center != null) center.redraw(); @@ -3537,7 +3851,7 @@ refreshBirdsEyeView(); } } - + private void invalidateLines() { if (isThreeWay()) { if (Utilities.okToUse(fAncestorCanvas)) @@ -3545,117 +3859,129 @@ if (fAncestor != null && fAncestor.isControlOkToUse()) fAncestor.getTextWidget().redraw(); } - + if (Utilities.okToUse(fLeftCanvas)) fLeftCanvas.redraw(); - + if (fLeft != null && fLeft.isControlOkToUse()) fLeft.getTextWidget().redraw(); - + if (Utilities.okToUse(getCenterControl())) getCenterControl().redraw(); - + if (fRight != null && fRight.isControlOkToUse()) fRight.getTextWidget().redraw(); - + if (Utilities.okToUse(fRightCanvas)) fRightCanvas.redraw(); } - + private boolean showResolveUI() { if (!fUseResolveUI || !isThreeWay() || isIgnoreAncestor()) return false; - CompareConfiguration cc= getCompareConfiguration(); + CompareConfiguration cc = getCompareConfiguration(); // we only enable the new resolve UI if exactly one side is editable - boolean l= cc.isLeftEditable(); - boolean r= cc.isRightEditable(); - //return (l && !r) || (r && !l); + boolean l = cc.isLeftEditable(); + boolean r = cc.isRightEditable(); + // return (l && !r) || (r && !l); return l || r; } - + private void paintCenter(Canvas canvas, GC g) { - - Display display= canvas.getDisplay(); - + + Display display = canvas.getDisplay(); + checkForColorUpdate(display); - - if (! fSynchronizedScrolling) + + if (!fSynchronizedScrolling) return; - int lineHeightLeft= fLeft.getTextWidget().getLineHeight(); - int lineHeightRight= fRight.getTextWidget().getLineHeight(); - int visibleHeight= fRight.getViewportHeight(); - - Point size= canvas.getSize(); - int x= 0; - int w= size.x; - + int lineHeightLeft = fLeft.getTextWidget().getLineHeight(); + int lineHeightRight = fRight.getTextWidget().getLineHeight(); + int visibleHeight = fRight.getViewportHeight(); + + Point size = canvas.getSize(); + int x = 0; + int w = size.x; + g.setBackground(canvas.getBackground()); - g.fillRectangle(x+1, 0, w-2, size.y); - + g.fillRectangle(x + 1, 0, w - 2, size.y); + if (!fIsMotif) { // draw thin line between center ruler and both texts - g.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); + g.setBackground(display + .getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); g.fillRectangle(0, 0, 1, size.y); - g.fillRectangle(w-1, 0, 1, size.y); + g.fillRectangle(w - 1, 0, 1, size.y); } - - if (! fHighlightRanges) + + if (!fHighlightRanges) return; - boolean showResolveUI= showResolveUI(); + boolean showResolveUI = showResolveUI(); if (fMerger.hasChanges()) { - int lshift= fLeft.getVerticalScrollOffset(); - int rshift= fRight.getVerticalScrollOffset(); - - Point region= new Point(0, 0); - - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + int lshift = fLeft.getVerticalScrollOffset(); + int rshift = fRight.getVerticalScrollOffset(); + + Point region = new Point(0, 0); + + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); if (diff.isDeleted()) continue; - + if (fShowCurrentOnly2 && !isCurrentDiff(diff)) continue; fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region); - int ly= (region.x * lineHeightLeft) + lshift; - int lh= region.y * lineHeightLeft; - - fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region); - int ry= (region.x * lineHeightRight) + rshift; - int rh= region.y * lineHeightRight; - - if (Math.max(ly+lh, ry+rh) < 0) + int ly = (region.x * lineHeightLeft) + lshift; + int lh = region.y * lineHeightLeft; + + fRight + .getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), + region); + int ry = (region.x * lineHeightRight) + rshift; + int rh = region.y * lineHeightRight; + + if (Math.max(ly + lh, ry + rh) < 0) continue; if (Math.min(ly, ry) >= visibleHeight) break; - - fPts[0]= x; fPts[1]= ly; fPts[2]= w; fPts[3]= ry; - fPts[6]= x; fPts[7]= ly+lh; fPts[4]= w; fPts[5]= ry+rh; - - Color fillColor= getColor(display, getFillColor(diff)); - Color strokeColor= getColor(display, getStrokeColor(diff)); - + + fPts[0] = x; + fPts[1] = ly; + fPts[2] = w; + fPts[3] = ry; + fPts[6] = x; + fPts[7] = ly + lh; + fPts[4] = w; + fPts[5] = ry + rh; + + Color fillColor = getColor(display, getFillColor(diff)); + Color strokeColor = getColor(display, getStrokeColor(diff)); + if (fUseSingleLine) { - int w2= 3; + int w2 = 3; g.setBackground(fillColor); - g.fillRectangle(0, ly, w2, lh); // left - g.fillRectangle(w-w2, ry, w2, rh); // right + g.fillRectangle(0, ly, w2, lh); // left + g.fillRectangle(w - w2, ry, w2, rh); // right g.setLineWidth(0 /* LW */); g.setForeground(strokeColor); - g.drawRectangle(0-1, ly, w2, lh); // left - g.drawRectangle(w-w2, ry, w2, rh); // right + g.drawRectangle(0 - 1, ly, w2, lh); // left + g.drawRectangle(w - w2, ry, w2, rh); // right if (fUseSplines) { - int[] points= getCenterCurvePoints(w2, ly+lh/2, w-w2, ry+rh/2); - for (int i= 1; i < points.length; i++) - g.drawLine(w2+i-1, points[i-1], w2+i, points[i]); + int[] points = getCenterCurvePoints(w2, ly + lh / 2, w + - w2, ry + rh / 2); + for (int i = 1; i < points.length; i++) + g.drawLine(w2 + i - 1, points[i - 1], w2 + i, + points[i]); } else { - g.drawLine(w2, ly+lh/2, w-w2, ry+rh/2); + g.drawLine(w2, ly + lh / 2, w - w2, ry + rh / 2); } } else { // two lines @@ -3665,16 +3991,21 @@ g.setLineWidth(0 /* LW */); g.setForeground(strokeColor); - int[] topPoints= getCenterCurvePoints(fPts[0], fPts[1], fPts[2], fPts[3]); - int[] bottomPoints= getCenterCurvePoints(fPts[6], fPts[7], fPts[4], fPts[5]); + int[] topPoints = getCenterCurvePoints(fPts[0], + fPts[1], fPts[2], fPts[3]); + int[] bottomPoints = getCenterCurvePoints(fPts[6], + fPts[7], fPts[4], fPts[5]); g.setForeground(fillColor); g.drawLine(0, bottomPoints[0], 0, topPoints[0]); - for (int i= 1; i < bottomPoints.length; i++) { + for (int i = 1; i < bottomPoints.length; i++) { g.setForeground(fillColor); g.drawLine(i, bottomPoints[i], i, topPoints[i]); g.setForeground(strokeColor); - g.drawLine(i-1, topPoints[i-1], i, topPoints[i]); - g.drawLine(i-1, bottomPoints[i-1], i, bottomPoints[i]); + g + .drawLine(i - 1, topPoints[i - 1], i, + topPoints[i]); + g.drawLine(i - 1, bottomPoints[i - 1], i, + bottomPoints[i]); } } else { g.setBackground(fillColor); @@ -3686,158 +4017,164 @@ g.drawLine(fPts[6], fPts[7], fPts[4], fPts[5]); } } - - if (fUseSingleLine && showResolveUI && diff.isUnresolvedIncomingOrConflicting()) { + + if (fUseSingleLine && showResolveUI + && diff.isUnresolvedIncomingOrConflicting()) { // draw resolve state - int cx= (w-RESOLVE_SIZE)/2; - int cy= ((ly+lh/2) + (ry+rh/2) - RESOLVE_SIZE)/2; - + int cx = (w - RESOLVE_SIZE) / 2; + int cy = ((ly + lh / 2) + (ry + rh / 2) - RESOLVE_SIZE) / 2; + g.setBackground(fillColor); g.fillRectangle(cx, cy, RESOLVE_SIZE, RESOLVE_SIZE); - + g.setForeground(strokeColor); g.drawRectangle(cx, cy, RESOLVE_SIZE, RESOLVE_SIZE); } } } } - - private int[] getCenterCurvePoints(int startx, int starty, int endx, int endy) { + + private int[] getCenterCurvePoints(int startx, int starty, int endx, + int endy) { if (fBasicCenterCurve == null) - buildBaseCenterCurve(endx-startx); - double height= endy - starty; - height= height/2; - int width= endx-startx; - int[] points= new int[width]; - for (int i= 0; i < width; i++) { - points[i]= (int) (-height * fBasicCenterCurve[i] + height + starty); + buildBaseCenterCurve(endx - startx); + double height = endy - starty; + height = height / 2; + int width = endx - startx; + int[] points = new int[width]; + for (int i = 0; i < width; i++) { + points[i] = (int) (-height * fBasicCenterCurve[i] + height + starty); } return points; } private void buildBaseCenterCurve(int w) { - double width= w; - fBasicCenterCurve= new double[getCenterWidth()]; - for (int i= 0; i < getCenterWidth(); i++) { - double r= i / width; - fBasicCenterCurve[i]= Math.cos(Math.PI * r); + double width = w; + fBasicCenterCurve = new double[getCenterWidth()]; + for (int i = 0; i < getCenterWidth(); i++) { + double r = i / width; + fBasicCenterCurve[i] = Math.cos(Math.PI * r); } } - private void paintSides(GC g, MergeSourceViewer tp, Canvas canvas, boolean right) { - - Display display= canvas.getDisplay(); - - int lineHeight= tp.getTextWidget().getLineHeight(); - int visibleHeight= tp.getViewportHeight(); - - Point size= canvas.getSize(); - int x= 0; - int w= fMarginWidth; - int w2= w/2; - + private void paintSides(GC g, MergeSourceViewer tp, Canvas canvas, + boolean right) { + + Display display = canvas.getDisplay(); + + int lineHeight = tp.getTextWidget().getLineHeight(); + int visibleHeight = tp.getViewportHeight(); + + Point size = canvas.getSize(); + int x = 0; + int w = fMarginWidth; + int w2 = w / 2; + g.setBackground(canvas.getBackground()); g.fillRectangle(x, 0, w, size.y); if (!fIsMotif) { // draw thin line between ruler and text - g.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); + g.setBackground(display + .getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); if (right) g.fillRectangle(0, 0, 1, size.y); else - g.fillRectangle(size.x-1, 0, 1, size.y); + g.fillRectangle(size.x - 1, 0, 1, size.y); } - if (! fHighlightRanges) + if (!fHighlightRanges) return; if (fMerger.hasChanges()) { - int shift= tp.getVerticalScrollOffset() + (2-LW); - - Point region= new Point(0, 0); + int shift = tp.getVerticalScrollOffset() + (2 - LW); + + Point region = new Point(0, 0); char leg = getLeg(tp); - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); if (diff.isDeleted()) continue; - + if (fShowCurrentOnly2 && !isCurrentDiff(diff)) continue; tp.getLineRange(diff.getPosition(leg), region); - int y= (region.x * lineHeight) + shift; - int h= region.y * lineHeight; - - if (y+h < 0) + int y = (region.x * lineHeight) + shift; + int h = region.y * lineHeight; + + if (y + h < 0) continue; if (y >= visibleHeight) break; - + g.setBackground(getColor(display, getFillColor(diff))); if (right) g.fillRectangle(x, y, w2, h); else - g.fillRectangle(x+w2, y, w2, h); - + g.fillRectangle(x + w2, y, w2, h); + g.setLineWidth(0 /* LW */); g.setForeground(getColor(display, getStrokeColor(diff))); if (right) - g.drawRectangle(x-1, y-1, w2, h); + g.drawRectangle(x - 1, y - 1, w2, h); else - g.drawRectangle(x+w2, y-1, w2, h); + g.drawRectangle(x + w2, y - 1, w2, h); } } } - + private void paint(PaintEvent event, MergeSourceViewer tp) { - - if (! fHighlightRanges) + + if (!fHighlightRanges) return; if (!fMerger.hasChanges()) return; - Control canvas= (Control) event.widget; - GC g= event.gc; - - Display display= canvas.getDisplay(); - - int lineHeight= tp.getTextWidget().getLineHeight(); - int w= canvas.getSize().x; - int shift= tp.getVerticalScrollOffset() + (2-LW); - int maxh= event.y+event.height; // visibleHeight - - //if (fIsMotif) - shift+= fTopInset; - - Point range= new Point(0, 0); - + Control canvas = (Control) event.widget; + GC g = event.gc; + + Display display = canvas.getDisplay(); + + int lineHeight = tp.getTextWidget().getLineHeight(); + int w = canvas.getSize().x; + int shift = tp.getVerticalScrollOffset() + (2 - LW); + int maxh = event.y + event.height; // visibleHeight + + // if (fIsMotif) + shift += fTopInset; + + Point range = new Point(0, 0); + char leg = getLeg(tp); for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { Diff diff = (Diff) iterator.next(); if (diff.isDeleted()) continue; - + if (fShowCurrentOnly && !isCurrentDiff(diff)) continue; tp.getLineRange(diff.getPosition(leg), range); - int y= (range.x * lineHeight) + shift; - int h= range.y * lineHeight; - - if (y+h < event.y) + int y = (range.x * lineHeight) + shift; + int h = range.y * lineHeight; + + if (y + h < event.y) continue; if (y > maxh) break; - + g.setBackground(getColor(display, getStrokeColor(diff))); - g.fillRectangle(0, y-1, w, LW); - g.fillRectangle(0, y+h-1, w, LW); + g.fillRectangle(0, y - 1, w, LW); + g.fillRectangle(0, y + h - 1, w, LW); } } private RGB getFillColor(Diff diff) { - boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff; - RGB selected_fill= getBackground(null); + boolean selected = fCurrentDiff != null + && fCurrentDiff.getParent() == diff; + RGB selected_fill = getBackground(null); if (isThreeWay() && !isIgnoreAncestor()) { switch (diff.getKind()) { case RangeDifference.RIGHT: @@ -3857,10 +4194,11 @@ } return selected ? selected_fill : OUTGOING_FILL; } - + private RGB getStrokeColor(Diff diff) { - boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff; - + boolean selected = fCurrentDiff != null + && fCurrentDiff.getParent() == diff; + if (isThreeWay() && !isIgnoreAncestor()) { switch (diff.getKind()) { case RangeDifference.RIGHT: @@ -3880,39 +4218,37 @@ } return selected ? SELECTED_OUTGOING : OUTGOING; } - + private Color getColor(Display display, RGB rgb) { if (rgb == null) return null; if (fColors == null) - fColors= new HashMap(20); - Color c= (Color) fColors.get(rgb); + fColors = new HashMap(20); + Color c = (Color) fColors.get(rgb); if (c == null) { - c= new Color(display, rgb); + c = new Color(display, rgb); fColors.put(rgb, c); } return c; } - + static RGB interpolate(RGB fg, RGB bg, double scale) { if (fg != null && bg != null) - return new RGB( - (int)((1.0-scale) * fg.red + scale * bg.red), - (int)((1.0-scale) * fg.green + scale * bg.green), - (int)((1.0-scale) * fg.blue + scale * bg.blue) - ); + return new RGB((int) ((1.0 - scale) * fg.red + scale * bg.red), + (int) ((1.0 - scale) * fg.green + scale * bg.green), + (int) ((1.0 - scale) * fg.blue + scale * bg.blue)); if (fg != null) return fg; if (bg != null) return bg; - return new RGB(128, 128, 128); // a gray + return new RGB(128, 128, 128); // a gray } - - //---- Navigating and resolving Diffs - + + // ---- Navigating and resolving Diffs + private Diff getNextVisibleDiff(boolean down, boolean deep) { - Diff diff= null; - MergeSourceViewer part= getNavigationPart(); + Diff diff = null; + MergeSourceViewer part = getNavigationPart(); if (part == null) return null; Point s = part.getSelectedRange(); @@ -3924,39 +4260,40 @@ && !isAncestorVisible()) { Position position = diff.getPosition(leg); s = new Point(position.getOffset(), position.getLength()); - diff= null; + diff = null; continue; } break; } return diff; } - - private Diff internalGetNextDiff(boolean down, boolean deep, MergeSourceViewer part, Point s) { + + private Diff internalGetNextDiff(boolean down, boolean deep, + MergeSourceViewer part, Point s) { if (fMerger.hasChanges()) { if (down) - return findNext(part, s.x, s.x+s.y, deep); - return findPrev(part, s.x, s.x+s.y, deep); + return findNext(part, s.x, s.x + s.y, deep); + return findPrev(part, s.x, s.x + s.y, deep); } return null; } - + private MergeSourceViewer getNavigationPart() { - MergeSourceViewer part= fFocusPart; + MergeSourceViewer part = fFocusPart; if (part == null) - part= fRight; + part = fRight; return part; } private Diff getWrappedDiff(Diff diff, boolean down) { return fMerger.getWrappedDiff(diff, down); } - + /* * Returns true if end (or beginning) of document reached. */ private boolean navigate(boolean down, boolean wrap, boolean deep) { - Diff diff= null; + Diff diff = null; boolean wrapped = false; for (;;) { diff = getNextVisibleDiff(down, deep); @@ -3976,22 +4313,29 @@ } return diff == null; } - + private void endOfDocumentReached(boolean down) { - Control c= getControl(); + Control c = getControl(); if (Utilities.okToUse(c)) { handleEndOfDocumentReached(c.getShell(), down); } } - + private void handleEndOfDocumentReached(Shell shell, boolean next) { boolean hasNextElement = hasNextElement(next); - IPreferenceStore store = CompareUIPlugin.getDefault().getPreferenceStore(); - String value = store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION); + IPreferenceStore store = CompareUIPlugin.getDefault() + .getPreferenceStore(); + String value = store + .getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION); if (!value.equals(ICompareUIConstants.PREF_VALUE_PROMPT)) { - // We only want to do the automatic thing if there is something to do - if (hasNextElement || store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION).equals(ICompareUIConstants.PREF_VALUE_LOOP)) { - performEndOfDocumentAction(shell, store, ICompareUIConstants.PREF_NAVIGATION_END_ACTION, next); + // We only want to do the automatic thing if there is something to + // do + if (hasNextElement + || store.getString( + ICompareUIConstants.PREF_NAVIGATION_END_ACTION) + .equals(ICompareUIConstants.PREF_VALUE_LOOP)) { + performEndOfDocumentAction(shell, store, + ICompareUIConstants.PREF_NAVIGATION_END_ACTION, next); return; } } @@ -4012,21 +4356,24 @@ loopMessage = CompareMessages.TextMergeViewer_6; nextMessage = CompareMessages.TextMergeViewer_7; } - String[] localLoopOption = new String[] { loopMessage, ICompareUIConstants.PREF_VALUE_LOOP }; - String[] nextElementOption = new String[] { nextMessage, ICompareUIConstants.PREF_VALUE_NEXT}; - NavigationEndDialog dialog = new NavigationEndDialog(shell, - title, - null, - message, - new String[][] { - localLoopOption, - nextElementOption, - }); + String[] localLoopOption = new String[] { loopMessage, + ICompareUIConstants.PREF_VALUE_LOOP }; + String[] nextElementOption = new String[] { nextMessage, + ICompareUIConstants.PREF_VALUE_NEXT }; + NavigationEndDialog dialog = new NavigationEndDialog(shell, title, + null, message, new String[][] { localLoopOption, + nextElementOption, }); int result = dialog.open(); if (result == Window.OK) { - performEndOfDocumentAction(shell, store, ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, next); + performEndOfDocumentAction(shell, store, + ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, + next); if (dialog.getToggleState()) { - store.putValue(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL)); + store + .putValue( + ICompareUIConstants.PREF_NAVIGATION_END_ACTION, + store + .getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL)); } } } else { @@ -4044,11 +4391,13 @@ } } } - - private void performEndOfDocumentAction(Shell shell, IPreferenceStore store, String key, boolean next) { + + private void performEndOfDocumentAction(Shell shell, + IPreferenceStore store, String key, boolean next) { String value = store.getString(key); if (value.equals(ICompareUIConstants.PREF_VALUE_NEXT)) { - ICompareNavigator navigator = getCompareConfiguration().getContainer().getNavigator(); + ICompareNavigator navigator = getCompareConfiguration() + .getContainer().getNavigator(); if (hasNextElement(next)) navigator.selectChange(next); else @@ -4057,9 +4406,10 @@ selectFirstDiff(next); } } - + private boolean hasNextElement(boolean down) { - ICompareNavigator navigator = getCompareConfiguration().getContainer().getNavigator(); + ICompareNavigator navigator = getCompareConfiguration().getContainer() + .getNavigator(); if (navigator instanceof CompareNavigator) { CompareNavigator n = (CompareNavigator) navigator; return n.hasChange(down); @@ -4068,160 +4418,170 @@ } /* - * Find the Diff that overlaps with the given TextPart's text range. - * If the range doesn't overlap with any range null - * is returned. + * Find the Diff that overlaps with the given TextPart's text range. If the + * range doesn't overlap with any range null is returned. */ private Diff findDiff(MergeSourceViewer tp, int rangeStart, int rangeEnd) { char contributor = getLeg(tp); return fMerger.findDiff(contributor, rangeStart, rangeEnd); } - + private Diff findNext(MergeSourceViewer tp, int start, int end, boolean deep) { return fMerger.findNext(getLeg(tp), start, end, deep); } - + private Diff findPrev(MergeSourceViewer tp, int start, int end, boolean deep) { return fMerger.findPrev(getLeg(tp), start, end, deep); } /* * Set the currently active Diff and update the toolbars controls and lines. - * If revealAndSelect is true the Diff is revealed and - * selected in both TextParts. + * If revealAndSelect is true the Diff is revealed + * and selected in both TextParts. */ private void setCurrentDiff(Diff d, boolean revealAndSelect) { setCurrentDiff(d, revealAndSelect, false); } - + /* * Set the currently active Diff and update the toolbars controls and lines. - * If revealAndSelect is true the Diff is revealed and - * selected in both TextParts. + * If revealAndSelect is true the Diff is revealed + * and selected in both TextParts. */ private void setCurrentDiff(Diff d, boolean revealAndSelect, boolean deep) { -// if (d == fCurrentDiff) -// return; + // if (d == fCurrentDiff) + // return; if (fCenterButton != null && !fCenterButton.isDisposed()) fCenterButton.setVisible(false); - Diff oldDiff= fCurrentDiff; - + Diff oldDiff = fCurrentDiff; + if (d != null && revealAndSelect) { - + // before we set fCurrentDiff we change the selection // so that the paint code uses the old background colors // otherwise selection isn't drawn correctly - if (d.isToken() || !fHighlightTokenChanges || deep || !d.hasChildren()) { + if (d.isToken() || !fHighlightTokenChanges || deep + || !d.hasChildren()) { if (isThreeWay() && !isIgnoreAncestor()) fAncestor.setSelection(d.getPosition(ANCESTOR_CONTRIBUTOR)); fLeft.setSelection(d.getPosition(LEFT_CONTRIBUTOR)); fRight.setSelection(d.getPosition(RIGHT_CONTRIBUTOR)); } else { if (isThreeWay() && !isIgnoreAncestor()) - fAncestor.setSelection(new Position(d.getPosition(ANCESTOR_CONTRIBUTOR).offset, 0)); - fLeft.setSelection(new Position(d.getPosition(LEFT_CONTRIBUTOR).offset, 0)); - fRight.setSelection(new Position(d.getPosition(RIGHT_CONTRIBUTOR).offset, 0)); + fAncestor.setSelection(new Position(d + .getPosition(ANCESTOR_CONTRIBUTOR).offset, 0)); + fLeft.setSelection(new Position( + d.getPosition(LEFT_CONTRIBUTOR).offset, 0)); + fRight.setSelection(new Position(d + .getPosition(RIGHT_CONTRIBUTOR).offset, 0)); } - + // now switch diffs - fCurrentDiff= d; + fCurrentDiff = d; revealDiff(d, d.isToken()); } else { - fCurrentDiff= d; + fCurrentDiff = d; } - - Diff d1= oldDiff != null ? oldDiff.getParent() : null; - Diff d2= fCurrentDiff != null ? fCurrentDiff.getParent() : null; + + Diff d1 = oldDiff != null ? oldDiff.getParent() : null; + Diff d2 = fCurrentDiff != null ? fCurrentDiff.getParent() : null; if (d1 != d2) { updateDiffBackground(d1); updateDiffBackground(d2); } - + updateControls(); invalidateLines(); refreshBirdsEyeView(); } - + /* * Smart determines whether */ private void revealDiff(Diff d, boolean smart) { - - boolean ancestorIsVisible= false; - boolean leftIsVisible= false; - boolean rightIsVisible= false; + + boolean ancestorIsVisible = false; + boolean leftIsVisible = false; + boolean rightIsVisible = false; if (smart) { - Point region= new Point(0, 0); + Point region = new Point(0, 0); // find the starting line of the diff in all text widgets - int ls= fLeft.getLineRange(d.getPosition(LEFT_CONTRIBUTOR), region).x; - int rs= fRight.getLineRange(d.getPosition(RIGHT_CONTRIBUTOR), region).x; - + int ls = fLeft + .getLineRange(d.getPosition(LEFT_CONTRIBUTOR), region).x; + int rs = fRight.getLineRange(d.getPosition(RIGHT_CONTRIBUTOR), + region).x; + if (isThreeWay() && !isIgnoreAncestor()) { - int as= fAncestor.getLineRange(d.getPosition(ANCESTOR_CONTRIBUTOR), region).x; - if (as >= fAncestor.getTopIndex() && as <= fAncestor.getBottomIndex()) - ancestorIsVisible= true; + int as = fAncestor.getLineRange(d + .getPosition(ANCESTOR_CONTRIBUTOR), region).x; + if (as >= fAncestor.getTopIndex() + && as <= fAncestor.getBottomIndex()) + ancestorIsVisible = true; } if (ls >= fLeft.getTopIndex() && ls <= fLeft.getBottomIndex()) - leftIsVisible= true; + leftIsVisible = true; if (rs >= fRight.getTopIndex() && rs <= fRight.getBottomIndex()) - rightIsVisible= true; + rightIsVisible = true; } // vertical scrolling if (!leftIsVisible || !rightIsVisible) { - int avpos= 0, lvpos= 0, rvpos= 0; - - MergeSourceViewer allButThis= null; + int avpos = 0, lvpos = 0, rvpos = 0; + + MergeSourceViewer allButThis = null; if (leftIsVisible) { - avpos= lvpos= rvpos= realToVirtualPosition(LEFT_CONTRIBUTOR, fLeft.getTopIndex()); - allButThis= fLeft; + avpos = lvpos = rvpos = realToVirtualPosition(LEFT_CONTRIBUTOR, + fLeft.getTopIndex()); + allButThis = fLeft; } else if (rightIsVisible) { - avpos= lvpos= rvpos= realToVirtualPosition(RIGHT_CONTRIBUTOR, fRight.getTopIndex()); - allButThis= fRight; + avpos = lvpos = rvpos = realToVirtualPosition( + RIGHT_CONTRIBUTOR, fRight.getTopIndex()); + allButThis = fRight; } else if (ancestorIsVisible) { - avpos= lvpos= rvpos= realToVirtualPosition(ANCESTOR_CONTRIBUTOR, fAncestor.getTopIndex()); - allButThis= fAncestor; + avpos = lvpos = rvpos = realToVirtualPosition( + ANCESTOR_CONTRIBUTOR, fAncestor.getTopIndex()); + allButThis = fAncestor; } else { - int vpos= 0; + int vpos = 0; for (Iterator iterator = fMerger.rangesIterator(); iterator .hasNext();) { Diff diff = (Diff) iterator.next(); if (diff == d) break; if (fSynchronizedScrolling) { - vpos+= diff.getMaxDiffHeight(); + vpos += diff.getMaxDiffHeight(); } else { - avpos+= diff.getAncestorHeight(); - lvpos+= diff.getLeftHeight(); - rvpos+= diff.getRightHeight(); + avpos += diff.getAncestorHeight(); + lvpos += diff.getLeftHeight(); + rvpos += diff.getRightHeight(); } } if (fSynchronizedScrolling) - avpos= lvpos= rvpos= vpos; - int delta= fRight.getViewportLines()/4; - avpos-= delta; + avpos = lvpos = rvpos = vpos; + int delta = fRight.getViewportLines() / 4; + avpos -= delta; if (avpos < 0) - avpos= 0; - lvpos-= delta; + avpos = 0; + lvpos -= delta; if (lvpos < 0) - lvpos= 0; - rvpos-= delta; + lvpos = 0; + rvpos -= delta; if (rvpos < 0) - rvpos= 0; + rvpos = 0; } - + scrollVertical(avpos, lvpos, rvpos, allButThis); - + if (fVScrollBar != null) fVScrollBar.setSelection(avpos); } - + // horizontal scrolling if (d.isToken()) { // we only scroll horizontally for token diffs @@ -4235,41 +4595,44 @@ hscroll(fRight); } } - + private static void reveal(MergeSourceViewer v, Position p) { if (v != null && p != null) { - StyledText st= v.getTextWidget(); + StyledText st = v.getTextWidget(); if (st != null) { - Rectangle r= st.getClientArea(); - if (!r.isEmpty()) // workaround for #7320: Next diff scrolls when going into current diff + Rectangle r = st.getClientArea(); + if (!r.isEmpty()) // workaround for #7320: Next diff scrolls + // when going into current diff v.revealRange(p.offset, p.length); } } } - + private static void hscroll(MergeSourceViewer v) { if (v != null) { - StyledText st= v.getTextWidget(); + StyledText st = v.getTextWidget(); if (st != null) st.setHorizontalIndex(0); } } - - //-------------------------------------------------------------------------------- - + + // -------------------------------------------------------------------------------- + void copyAllUnresolved(boolean leftToRight) { if (fMerger.hasChanges() && isThreeWay() && !isIgnoreAncestor()) { - IRewriteTarget target= leftToRight ? fRight.getRewriteTarget() : fLeft.getRewriteTarget(); - boolean compoundChangeStarted= false; + IRewriteTarget target = leftToRight ? fRight.getRewriteTarget() + : fLeft.getRewriteTarget(); + boolean compoundChangeStarted = false; try { - for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) { + for (Iterator iterator = fMerger.changesIterator(); iterator + .hasNext();) { Diff diff = (Diff) iterator.next(); switch (diff.getKind()) { case RangeDifference.LEFT: if (leftToRight) { if (!compoundChangeStarted) { target.beginCompoundChange(); - compoundChangeStarted= true; + compoundChangeStarted = true; } copy(diff, leftToRight); } @@ -4278,7 +4641,7 @@ if (!leftToRight) { if (!compoundChangeStarted) { target.beginCompoundChange(); - compoundChangeStarted= true; + compoundChangeStarted = true; } copy(diff, leftToRight); } @@ -4294,7 +4657,7 @@ } } } - + /* * Copy whole document from one side to the other. */ @@ -4306,11 +4669,11 @@ invalidateLines(); return; } - + if (leftToRight) { if (fLeft.getEnabled()) { // copy text - String text= fLeft.getTextWidget().getText(); + String text = fLeft.getTextWidget().getText(); fRight.getTextWidget().setText(text); fRight.setEnabled(true); } else { @@ -4318,12 +4681,12 @@ fRight.getTextWidget().setText(""); //$NON-NLS-1$ fRight.setEnabled(false); } - fRightLineCount= fRight.getLineCount(); + fRightLineCount = fRight.getLineCount(); setRightDirty(true); } else { if (fRight.getEnabled()) { // copy text - String text= fRight.getTextWidget().getText(); + String text = fRight.getTextWidget().getText(); fLeft.getTextWidget().setText(text); fLeft.setEnabled(true); } else { @@ -4331,7 +4694,7 @@ fLeft.getTextWidget().setText(""); //$NON-NLS-1$ fLeft.setEnabled(false); } - fLeftLineCount= fLeft.getLineCount(); + fLeftLineCount = fLeft.getLineCount(); setLeftDirty(true); } update(false); @@ -4345,7 +4708,7 @@ private void copyDiffRightToLeft() { copy(fCurrentDiff, false, false); } - + /* * Copy the contents of the given diff from one side to the other. */ @@ -4362,11 +4725,10 @@ /* * Copy the contents of the given diff from one side to the other but - * doesn't reveal anything. - * Returns true if copy was successful. + * doesn't reveal anything. Returns true if copy was successful. */ private boolean copy(Diff diff, boolean leftToRight) { - + if (diff != null && !diff.isResolved()) { if (!validateChange(!leftToRight)) return false; @@ -4389,171 +4751,188 @@ info = fLeftContributor; else info = fRightContributor; - + return info.validateChange(); } - //---- scrolling - + // ---- scrolling + /* * The height of the TextEditors in lines. */ private int getViewportHeight() { - StyledText te= fLeft.getTextWidget(); - - int vh= te.getClientArea().height; + StyledText te = fLeft.getTextWidget(); + + int vh = te.getClientArea().height; if (vh == 0) { - Rectangle trim= te.computeTrim(0, 0, 0, 0); - int scrollbarHeight= trim.height; - - int headerHeight= getHeaderHeight(); - - Composite composite= (Composite) getControl(); - Rectangle r= composite.getClientArea(); - - vh= r.height-headerHeight-scrollbarHeight; + Rectangle trim = te.computeTrim(0, 0, 0, 0); + int scrollbarHeight = trim.height; + + int headerHeight = getHeaderHeight(); + + Composite composite = (Composite) getControl(); + Rectangle r = composite.getClientArea(); + + vh = r.height - headerHeight - scrollbarHeight; } return vh / te.getLineHeight(); } - + /* * Returns the virtual position for the given view position. */ private int realToVirtualPosition(char contributor, int vpos) { - if (! fSynchronizedScrolling) + if (!fSynchronizedScrolling) return vpos; return fMerger.realToVirtualPosition(contributor, vpos); } - - private void scrollVertical(int avpos, int lvpos, int rvpos, MergeSourceViewer allBut) { - - int s= 0; - + + private void scrollVertical(int avpos, int lvpos, int rvpos, + MergeSourceViewer allBut) { + + int s = 0; + if (fSynchronizedScrolling) { - s= fMerger.getVirtualHeight() - rvpos; - int height= fRight.getViewportLines()/4; + s = fMerger.getVirtualHeight() - rvpos; + int height = fRight.getViewportLines() / 4; if (s < 0) - s= 0; + s = 0; if (s > height) - s= height; + s = height; } - fInScrolling= true; - + fInScrolling = true; + if (isThreeWay() && allBut != fAncestor) { if (fSynchronizedScrolling || allBut == null) { - int y= virtualToRealPosition(ANCESTOR_CONTRIBUTOR, avpos+s)-s; + int y = virtualToRealPosition(ANCESTOR_CONTRIBUTOR, avpos + s) + - s; fAncestor.vscroll(y); } } if (allBut != fLeft) { if (fSynchronizedScrolling || allBut == null) { - int y= virtualToRealPosition(LEFT_CONTRIBUTOR, lvpos+s)-s; + int y = virtualToRealPosition(LEFT_CONTRIBUTOR, lvpos + s) - s; fLeft.vscroll(y); } } if (allBut != fRight) { if (fSynchronizedScrolling || allBut == null) { - int y= virtualToRealPosition(RIGHT_CONTRIBUTOR, rvpos+s)-s; + int y = virtualToRealPosition(RIGHT_CONTRIBUTOR, rvpos + s) - s; fRight.vscroll(y); } } - - fInScrolling= false; - + + fInScrolling = false; + if (isThreeWay() && fAncestorCanvas != null) fAncestorCanvas.repaint(); - + if (fLeftCanvas != null) fLeftCanvas.repaint(); - - Control center= getCenterControl(); + + Control center = getCenterControl(); if (center instanceof BufferedCanvas) - ((BufferedCanvas)center).repaint(); - + ((BufferedCanvas) center).repaint(); + if (fRightCanvas != null) fRightCanvas.repaint(); } - + /* * Updates Scrollbars with viewports. */ private void syncViewport(MergeSourceViewer w) { - + if (fInScrolling) return; - int ix= w.getTopIndex(); - int ix2= w.getDocumentRegionOffset(); - - int viewPosition= realToVirtualPosition(getLeg(w), ix-ix2); - - scrollVertical(viewPosition, viewPosition, viewPosition, w); // scroll all but the given views - + int ix = w.getTopIndex(); + int ix2 = w.getDocumentRegionOffset(); + + int viewPosition = realToVirtualPosition(getLeg(w), ix - ix2); + + scrollVertical(viewPosition, viewPosition, viewPosition, w); // scroll + // all + // but + // the + // given + // views + if (fVScrollBar != null) { - int value= Math.max(0, Math.min(viewPosition, fMerger.getVirtualHeight() - getViewportHeight())); + int value = Math.max(0, Math.min(viewPosition, fMerger + .getVirtualHeight() + - getViewportHeight())); fVScrollBar.setSelection(value); - //refreshBirdEyeView(); + // refreshBirdEyeView(); } } /** */ private void updateVScrollBar() { - + if (Utilities.okToUse(fVScrollBar) && fSynchronizedScrolling) { - int virtualHeight= fMerger.getVirtualHeight(); - int viewPortHeight= getViewportHeight(); - int pageIncrement= viewPortHeight-1; - int thumb= (viewPortHeight > virtualHeight) ? virtualHeight : viewPortHeight; - + int virtualHeight = fMerger.getVirtualHeight(); + int viewPortHeight = getViewportHeight(); + int pageIncrement = viewPortHeight - 1; + int thumb = (viewPortHeight > virtualHeight) ? virtualHeight + : viewPortHeight; + fVScrollBar.setPageIncrement(pageIncrement); fVScrollBar.setMaximum(virtualHeight); fVScrollBar.setThumb(thumb); } } - + /* * maps given virtual position into a real view position of this view. */ private int virtualToRealPosition(char contributor, int v) { - if (! fSynchronizedScrolling) + if (!fSynchronizedScrolling) return v; return fMerger.virtualToRealPosition(contributor, v); } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#flushContent(java.lang.Object, org.eclipse.core.runtime.IProgressMonitor) + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.compare.contentmergeviewer.ContentMergeViewer#flushContent + * (java.lang.Object, org.eclipse.core.runtime.IProgressMonitor) */ protected void flushContent(Object oldInput, IProgressMonitor monitor) { - + // check and handle any shared buffers - IMergeViewerContentProvider content= getMergeContentProvider(); + IMergeViewerContentProvider content = getMergeContentProvider(); Object leftContent = content.getLeftContent(oldInput); Object rightContent = content.getRightContent(oldInput); - - if (leftContent != null && getCompareConfiguration().isLeftEditable() && isLeftDirty()) { + + if (leftContent != null && getCompareConfiguration().isLeftEditable() + && isLeftDirty()) { if (fLeftContributor.hasSharedDocument(leftContent)) { if (flush(fLeftContributor)) setLeftDirty(false); } } - - if (rightContent != null && getCompareConfiguration().isRightEditable() && isRightDirty()) { + + if (rightContent != null && getCompareConfiguration().isRightEditable() + && isRightDirty()) { if (fRightContributor.hasSharedDocument(rightContent)) { if (flush(fRightContributor)) setRightDirty(false); } } - - if (!(content instanceof MergeViewerContentProvider) || isLeftDirty() || isRightDirty()) { + + if (!(content instanceof MergeViewerContentProvider) || isLeftDirty() + || isRightDirty()) { super.flushContent(oldInput, monitor); } } - + private boolean flush(final ContributorInfo info) { try { return info.flush(); @@ -4573,7 +4952,9 @@ CompareUIPlugin.log(throwable); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { @@ -4604,9 +4985,12 @@ return fHandlerService; return null; } - - /* (non-Javadoc) - * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handleCompareInputChange() + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.compare.contentmergeviewer.ContentMergeViewer# + * handleCompareInputChange() */ protected void handleCompareInputChange() { try { @@ -4625,9 +5009,9 @@ if (fSynchronizedScrolling) { fSynchronziedScrollPosition = fVScrollBar.getSelection(); } - + } - + private void endRefresh() { isRefreshing = false; fLeftContributor.cacheSelection(null); @@ -4640,12 +5024,13 @@ scrollVertical(vpos, vpos, vpos, null); workaround65205(); } - + private boolean isIgnoreAncestor() { - return Utilities.getBoolean(getCompareConfiguration(), ICompareUIConstants.PROP_IGNORE_ANCESTOR, false); + return Utilities.getBoolean(getCompareConfiguration(), + ICompareUIConstants.PROP_IGNORE_ANCESTOR, false); } - - /* package */ void update(boolean includeControls) { + + /* package */void update(boolean includeControls) { if (getControl().isDisposed()) return; if (fHasErrors) { @@ -4653,17 +5038,17 @@ } else { doDiff(); } - + if (includeControls) updateControls(); - + updateVScrollBar(); updatePresentation(null); } private void resetDiffs() { // clear stuff - fCurrentDiff= null; + fCurrentDiff = null; fMerger.reset(); resetPositions(fLeft.getDocument()); resetPositions(fRight.getDocument()); @@ -4673,43 +5058,44 @@ private boolean isPatchHunk() { return Utilities.isHunk(getInput()); } - + private boolean isPatchHunkOk() { if (isPatchHunk()) return Utilities.isHunkOk(getInput()); return false; } - + /** * Return the provided start position of the hunk in the target file. + * * @return the provided start position of the hunk in the target file */ private int getHunkStart() { Object input = getInput(); - if (input != null && input instanceof DiffNode){ + if (input != null && input instanceof DiffNode) { ITypedElement right = ((DiffNode) input).getRight(); if (right != null) { Object element = Utilities.getAdapter(right, IHunk.class); if (element instanceof IHunk) - return ((IHunk)element).getStartPosition(); + return ((IHunk) element).getStartPosition(); } ITypedElement left = ((DiffNode) input).getLeft(); if (left != null) { Object element = Utilities.getAdapter(left, IHunk.class); if (element instanceof IHunk) - return ((IHunk)element).getStartPosition(); + return ((IHunk) element).getStartPosition(); } } return 0; } - + private IFindReplaceTarget getFindReplaceTarget() { if (fFindReplaceTarget == null) - fFindReplaceTarget= new FindReplaceTarget(); + fFindReplaceTarget = new FindReplaceTarget(); return fFindReplaceTarget; } - - /* package */ char getLeg(MergeSourceViewer w) { + + /* package */char getLeg(MergeSourceViewer w) { if (w == fLeft) return LEFT_CONTRIBUTOR; if (w == fRight) @@ -4718,7 +5104,7 @@ return ANCESTOR_CONTRIBUTOR; return ANCESTOR_CONTRIBUTOR; } - + private boolean isCurrentDiff(Diff diff) { if (diff == null) return false; @@ -4728,7 +5114,7 @@ return true; return false; } - + private boolean isNavigationPossible() { if (fCurrentDiff == null && fMerger.hasChanges()) return true; Index: compare/org/eclipse/compare/internal/SaveDiffFileWizard.java =================================================================== RCS file: compare/org/eclipse/compare/internal/SaveDiffFileWizard.java diff -N compare/org/eclipse/compare/internal/SaveDiffFileWizard.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compare/org/eclipse/compare/internal/SaveDiffFileWizard.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1384 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Benjamin Muskalla (b.muskalla@gmx.net) - Bug 149672 [Patch] Create Patch wizard should remember previous settings + *******************************************************************************/ +package org.eclipse.compare.internal; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.compare.internal.merge.DocumentMerger; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.IDocument; +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.Wizard; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +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.Image; +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.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.model.BaseWorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.views.navigator.ResourceComparator; + +/** + * A wizard for creating a patch file by running the CVS diff command. + */ +public class SaveDiffFileWizard extends Wizard { + + private final static int INITIAL_WIDTH = 300; + private final static int INITIAL_HEIGHT = 350; + + public static void run(DocumentMerger merger, IDocument leftDoc, + IDocument rightDoc, String leftLabel, String rightLabel, + String leftPath, String rightPath, Shell shell, boolean rightToLeft) { + final String title = CompareMessages.GenerateLocalDiff_title; + final SaveDiffFileWizard wizard = new SaveDiffFileWizard(merger, + leftDoc, rightDoc, leftLabel, rightLabel, leftPath, rightPath, + rightToLeft); + wizard.setWindowTitle(title); + WizardDialog dialog = new WizardDialog(shell, wizard); + dialog.setMinimumPageSize(INITIAL_WIDTH, INITIAL_HEIGHT); + dialog.open(); + } + + private class DirectionSelectionPage extends WizardPage { + + public final static int LEFT_OPTION = 1; + public final static int RIGHT_OPTION = 2; + + private Button fromLeftOption; + private Button fromRightOption; + private RadioButtonGroup fromRadioGroup = new RadioButtonGroup(); + + protected DirectionSelectionPage(String pageName, String title, + ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + layout.marginLeft = 5; + layout.marginTop = 9; + composite.setLayout(layout); + composite.setLayoutData(new GridData()); + setControl(composite); + + fromLeftOption = new Button(composite, SWT.RADIO); + fromLeftOption.setText(leftLabel); + + fromRightOption = new Button(composite, SWT.RADIO); + fromRightOption.setText(rightLabel); + GridData data = new GridData(); + data.verticalIndent = 6; + fromRightOption.setLayoutData(data); + + fromRadioGroup.add(LEFT_OPTION, fromLeftOption); + fromRadioGroup.add(RIGHT_OPTION, fromRightOption); + + Dialog.applyDialogFont(parent); + + // Add listeners + fromLeftOption.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fromRadioGroup.setSelection(LEFT_OPTION, true); + targetFileEdited = false; + } + }); + + fromRightOption.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + fromRadioGroup.setSelection(RIGHT_OPTION, true); + targetFileEdited = false; + } + }); + + fromRadioGroup.setSelection(rightToLeft ? RIGHT_OPTION + : LEFT_OPTION, true); + } + + public boolean isRightToLeft() { + return fromRadioGroup.getSelected() != LEFT_OPTION; + } + + } + + /** + * Page to select a patch file. Overriding validatePage was necessary to + * allow entering a file name that already exists. + */ + private class LocationPage extends WizardPage { + + public final static int CLIPBOARD = 1; + public final static int FILESYSTEM = 2; + public final static int WORKSPACE = 3; + + private Button cpRadio; + + private Button fsRadio; + protected Text fsPathText; + private Button fsBrowseButton; + private boolean fsBrowsed = false; + + private Button wsRadio; + protected Text wsPathText; + private Button wsBrowseButton; + private boolean wsBrowsed = false; + + protected boolean pageValid; + protected IContainer wsSelectedContainer; + protected IPath[] foldersToCreate; + protected int selectedLocation; + + /** + * The default values store used to initialize the selections. + */ + private final DefaultValuesStore store; + + class LocationPageContentProvider extends BaseWorkbenchContentProvider { + 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(); + } + return super.getChildren(element); + } + } + + class WorkspaceDialog extends TitleAreaDialog { + + protected TreeViewer wsTreeViewer; + protected Text wsFilenameText; + protected Image dlgTitleImage; + + private boolean modified = false; + + public WorkspaceDialog(Shell shell) { + super(shell); + } + + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + setTitle(CompareMessages.WorkspacePatchDialogTitle); + setMessage(CompareMessages.WorkspacePatchDialogDescription); + dlgTitleImage = CompareUIPlugin.getImageDescriptor( + ICompareUIConstants.IMG_WIZBAN_DIFF).createImage(); + setTitleImage(dlgTitleImage); + return control; + } + + protected Control createDialogArea(Composite parent) { + Composite parentComposite = (Composite) super + .createDialogArea(parent); + + // Create a composite with standard margins and spacing + Composite composite = new Composite(parentComposite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + composite.setFont(parentComposite.getFont()); + + getShell().setText(CompareMessages.GenerateDiffFileWizard_9); + + wsTreeViewer = new TreeViewer(composite, SWT.BORDER); + final GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint = 550; + gd.heightHint = 250; + wsTreeViewer.getTree().setLayoutData(gd); + + wsTreeViewer + .setContentProvider(new LocationPageContentProvider()); + wsTreeViewer.setComparator(new ResourceComparator( + ResourceComparator.NAME)); + wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider()); + wsTreeViewer.setInput(ResourcesPlugin.getWorkspace()); + + // Open to whatever is selected in the workspace field + IPath existingWorkspacePath = new Path(wsPathText.getText()); + if (existingWorkspacePath != null) { + // Ensure that this workspace path is valid + IResource selectedResource = ResourcesPlugin.getWorkspace() + .getRoot().findMember(existingWorkspacePath); + if (selectedResource != null) { + wsTreeViewer.expandToLevel(selectedResource, 0); + wsTreeViewer.setSelection(new StructuredSelection( + selectedResource)); + } + } + + final Composite group = new Composite(composite, SWT.NONE); + layout = new GridLayout(2, false); + layout.marginWidth = 0; + group.setLayout(layout); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, + false)); + + final Label label = new Label(group, SWT.NONE); + label.setLayoutData(new GridData()); + label.setText(CompareMessages.Fi_le_name__9); + + wsFilenameText = new Text(group, SWT.BORDER); + wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, + true, false)); + + setupListeners(); + + return parent; + } + + protected Button createButton(Composite parent, int id, + String label, boolean defaultButton) { + Button button = super.createButton(parent, id, label, + defaultButton); + if (id == IDialogConstants.OK_ID) { + button.setEnabled(false); + } + return button; + } + + private void validateDialog() { + String fileName = wsFilenameText.getText(); + + if (fileName.equals("")) { //$NON-NLS-1$ + if (modified) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_2); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + setErrorMessage(null); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + + // Make sure that the filename is valid + if (!(ResourcesPlugin.getWorkspace().validateName(fileName, + IResource.FILE)).isOK() + && modified) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_5); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + + // Make sure that a container has been selected + if (getSelectedContainer() == null) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_0); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IPath fullPath = wsSelectedContainer.getFullPath().append( + fileName); + if (workspace.getRoot().getFolder(fullPath).exists()) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + + } + + setErrorMessage(null); + getButton(IDialogConstants.OK_ID).setEnabled(true); + } + + protected void okPressed() { + IFile file = wsSelectedContainer.getFile(new Path( + wsFilenameText.getText())); + if (file != null) + wsPathText.setText(file.getFullPath().toString()); + + validatePage(); + super.okPressed(); + } + + private IContainer getSelectedContainer() { + Object obj = ((IStructuredSelection) wsTreeViewer + .getSelection()).getFirstElement(); + if (obj instanceof IContainer) { + wsSelectedContainer = (IContainer) obj; + } else if (obj instanceof IFile) { + wsSelectedContainer = ((IFile) obj).getParent(); + } + return wsSelectedContainer; + } + + protected void cancelPressed() { + validatePage(); + super.cancelPressed(); + } + + public boolean close() { + if (dlgTitleImage != null) + dlgTitleImage.dispose(); + return super.close(); + } + + void setupListeners() { + wsTreeViewer + .addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged( + SelectionChangedEvent event) { + IStructuredSelection s = (IStructuredSelection) event + .getSelection(); + Object obj = s.getFirstElement(); + if (obj instanceof IContainer) + wsSelectedContainer = (IContainer) obj; + else if (obj instanceof IFile) { + IFile tempFile = (IFile) obj; + wsSelectedContainer = tempFile.getParent(); + wsFilenameText.setText(tempFile.getName()); + } + validateDialog(); + } + }); + + wsTreeViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + ISelection s = event.getSelection(); + if (s instanceof IStructuredSelection) { + Object item = ((IStructuredSelection) s) + .getFirstElement(); + if (wsTreeViewer.getExpandedState(item)) + wsTreeViewer.collapseToLevel(item, 1); + else + wsTreeViewer.expandToLevel(item, 1); + } + validateDialog(); + } + }); + + wsFilenameText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + modified = true; + validateDialog(); + } + }); + } + } + + LocationPage(String pageName, String title, ImageDescriptor image, + DefaultValuesStore store) { + super(pageName, title, image); + setPageComplete(false); + this.store = store; + } + + protected boolean validatePage() { + switch (selectedLocation) { + case WORKSPACE: + pageValid = validateWorkspaceLocation(); + break; + case FILESYSTEM: + pageValid = validateFilesystemLocation(); + break; + case CLIPBOARD: + pageValid = true; + break; + } + + // Avoid draw flicker by clearing error message if all is valid. + if (pageValid) { + setMessage(null); + setErrorMessage(null); + } + setPageComplete(pageValid); + return pageValid; + } + + private boolean validateFilesystemLocation() { + // Conditions for the file system location to be valid: + // - the path must be valid and non-empty + // - the path must be absolute + // - the specified file must be of type file + // - the parent must exist (new folders can be created via browse) + final String pathString = fsPathText.getText().trim(); + if (pathString.length() == 0 + || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$ + if (fsBrowsed) + setErrorMessage(CompareMessages.GenerateDiffFileWizard_0); + else + setErrorMessage(CompareMessages.GenerateDiffFileWizard_browseFilesystem); + return false; + } + + final File file = new File(pathString); + if (!file.isAbsolute()) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_0); + return false; + } + + if (file.isDirectory()) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_2); + return false; + } + + if (pathString.endsWith("/") || pathString.endsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$ + setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); + return false; + } + + final File parent = file.getParentFile(); + if (!(parent.exists() && parent.isDirectory())) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); + return false; + } + return true; + } + + private boolean validateWorkspaceLocation() { + // Conditions for the file system location to be valid: + // - a parent must be selected in the workspace tree view + // - the resource name must be valid + if (wsPathText.getText().equals("")) { //$NON-NLS-1$ + // Make sure that the field actually has a filename in it + // amd make sure that the user has had a chance to browse + if (selectedLocation == WORKSPACE && wsBrowsed) + setErrorMessage(CompareMessages.GenerateDiffFileWizard_5); + else + setErrorMessage(CompareMessages.GenerateDiffFileWizard_4); + return false; + } + + // Make sure that all the segments but the last one (i.e. project + + // all folders) exist - file doesn't have to exist. It may have + // happened that some folder refactoring has been done since this + // path was last saved. + // + // The path will always be in format project/{folders}*/file - this + // is controlled by the workspace location dialog and by + // validatePath method when path has been entered manually. + IPath pathToWorkspaceFile = new Path(wsPathText.getText()); + IStatus status = ResourcesPlugin.getWorkspace().validatePath( + wsPathText.getText(), IResource.FILE); + if (status.isOK()) { + // Trim file name from path + IPath containerPath = pathToWorkspaceFile.removeLastSegments(1); + IResource container = ResourcesPlugin.getWorkspace().getRoot() + .findMember(containerPath); + if (container == null) { + if (selectedLocation == WORKSPACE) + setErrorMessage(CompareMessages.GenerateDiffFileWizard_4); + return false; + } else if (!container.isAccessible()) { + if (selectedLocation == WORKSPACE) + setErrorMessage(CompareMessages.GenerateDiffFileWizard_ProjectClosed); + return false; + } else { + if (ResourcesPlugin.getWorkspace().getRoot().getFolder( + pathToWorkspaceFile).exists()) { + setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists); + return false; + } + } + } else { + setErrorMessage(status.getMessage()); + return false; + } + + return true; + } + + /** + * Answers a full path to a file system file or null if the + * user selected to save the patch in the clipboard. + */ + public File getFile() { + if (pageValid && selectedLocation == FILESYSTEM) { + return new File(fsPathText.getText().trim()); + } + if (pageValid && selectedLocation == WORKSPACE) { + final String filename = wsPathText.getText().trim(); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + final IFile file = root.getFile(new Path(filename)); + return file.getLocation().toFile(); + } + return null; + } + + /** + * Answers the workspace string entered in the dialog or + * null if the user selected to save the patch in the + * clipboard or file system. + * + * @return workspace location or null + */ + public String getWorkspaceLocation() { + if (pageValid && selectedLocation == WORKSPACE) { + final String filename = wsPathText.getText().trim(); + return filename; + } + return null; + } + + /** + * Get the selected workspace resource if the patch is to be saved in + * the workspace, or null otherwise. + * + * @return selected resource or null + */ + public IResource getResource() { + if (pageValid && selectedLocation == WORKSPACE) { + IPath pathToWorkspaceFile = new Path(wsPathText.getText() + .trim()); + // Trim file name from path + IPath containerPath = pathToWorkspaceFile.removeLastSegments(1); + return ResourcesPlugin.getWorkspace().getRoot().findMember( + containerPath); + } + return null; + } + + public void createControl(Composite parent) { + final Composite composite = new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout()); + setControl(composite); + initializeDialogUnits(composite); + + setupLocationControls(composite); + + initializeDefaultValues(); + + Dialog.applyDialogFont(parent); + + validatePage(); + + updateEnablements(); + setupListeners(); + } + + private void setupLocationControls(final Composite parent) { + final Composite composite = new Composite(parent, SWT.NULL); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 3; + composite.setLayout(gridLayout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Clipboard + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalSpan = 3; + cpRadio = new Button(composite, SWT.RADIO); + cpRadio.setText(CompareMessages.Save_To_Clipboard_2); + cpRadio.setLayoutData(gd); + + // Filesystem + fsRadio = new Button(composite, SWT.RADIO); + fsRadio.setText(CompareMessages.Save_In_File_System_3); + + fsPathText = new Text(composite, SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + fsPathText.setLayoutData(gd); + + fsBrowseButton = new Button(composite, SWT.PUSH); + fsBrowseButton.setText(CompareMessages.Browse____4); + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT, + SWT.DEFAULT, true); + data.widthHint = Math.max(widthHint, minSize.x); + fsBrowseButton.setLayoutData(data); + + // Workspace + wsRadio = new Button(composite, SWT.RADIO); + wsRadio.setText(CompareMessages.Save_In_Workspace_7); + + wsPathText = new Text(composite, SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + wsPathText.setLayoutData(gd); + + wsBrowseButton = new Button(composite, SWT.PUSH); + wsBrowseButton.setText(CompareMessages.Browse____4); + data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + minSize = fsBrowseButton + .computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + data.widthHint = Math.max(widthHint, minSize.x); + wsBrowseButton.setLayoutData(data); + + ((GridData) cpRadio.getLayoutData()).heightHint = minSize.y; + } + + private void initializeDefaultValues() { + selectedLocation = store.getLocationSelection(); + + updateRadioButtons(); + + // We need to ensure that we have a valid workspace path - user + // could have altered workspace since last time this was saved + wsPathText.setText(store.getWorkspacePath()); + if (!validateWorkspaceLocation()) { + wsPathText.setText(""); //$NON-NLS-1$ + // Don't open wizard with an error - change to clipboard + if (selectedLocation == WORKSPACE) { + // Clear the error message caused by the workspace not + // having any workspace path entered + setErrorMessage(null); + selectedLocation = CLIPBOARD; + updateRadioButtons(); + } + } + // Do the same thing for the filesystem field + fsPathText.setText(store.getFilesystemPath()); + if (!validateFilesystemLocation()) { + fsPathText.setText(""); //$NON-NLS-1$ + if (selectedLocation == FILESYSTEM) { + setErrorMessage(null); + selectedLocation = CLIPBOARD; + updateRadioButtons(); + } + } + + } + + private void updateRadioButtons() { + cpRadio.setSelection(selectedLocation == CLIPBOARD); + fsRadio.setSelection(selectedLocation == FILESYSTEM); + wsRadio.setSelection(selectedLocation == WORKSPACE); + } + + private void setupListeners() { + cpRadio.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + selectedLocation = CLIPBOARD; + validatePage(); + updateEnablements(); + } + }); + fsRadio.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + selectedLocation = FILESYSTEM; + validatePage(); + updateEnablements(); + } + }); + + wsRadio.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + selectedLocation = WORKSPACE; + validatePage(); + updateEnablements(); + } + }); + + ModifyListener pathTextModifyListener = new ModifyListener() { + public void modifyText(ModifyEvent e) { + validatePage(); + } + }; + fsPathText.addModifyListener(pathTextModifyListener); + wsPathText.addModifyListener(pathTextModifyListener); + + fsBrowseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + final FileDialog dialog = new FileDialog(getShell(), + SWT.PRIMARY_MODAL | SWT.SAVE); + if (pageValid) { + final File file = new File(fsPathText.getText()); + dialog.setFilterPath(file.getParent()); + } + dialog.setText(CompareMessages.Save_Patch_As_5); + dialog.setFileName(CompareMessages.patch_txt_6); + final String path = dialog.open(); + fsBrowsed = true; + if (path != null) { + fsPathText.setText(new Path(path).toOSString()); + } + validatePage(); + } + }); + + wsBrowseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + final WorkspaceDialog dialog = new WorkspaceDialog( + getShell()); + wsBrowsed = true; + dialog.open(); + validatePage(); + } + }); + + } + + public void updateEnablements() { + // Enable and disable controls based on the selected radio button. + fsBrowseButton.setEnabled(selectedLocation == FILESYSTEM); + fsPathText.setEnabled(selectedLocation == FILESYSTEM); + if (selectedLocation == FILESYSTEM) + fsBrowsed = false; + wsPathText.setEnabled(selectedLocation == WORKSPACE); + wsBrowseButton.setEnabled(selectedLocation == WORKSPACE); + if (selectedLocation == WORKSPACE) + wsBrowsed = false; + } + + public int getSelectedLocation() { + return selectedLocation; + } + + } + + private class OptionsPage extends WizardPage { + + public final static int FORMAT_UNIFIED = 1; + public final static int FORMAT_CONTEXT = 2; + public final static int FORMAT_STANDARD = 3; + + public final static int ROOT_WORKSPACE = 1; + public final static int ROOT_PROJECT = 2; + public final static int ROOT_SELECTION = 3; + public final static int ROOT_CUSTOM = 4; + + private boolean initialized = false; + + private Button unifiedDiffOption; + private Button contextDiffOption; + private Button regularDiffOption; + + private Button unified_workspaceRelativeOption; + private Button unified_projectRelativeOption; + private Button unified_selectionRelativeOption; + private Button unified_customRelativeOption; + private Text unified_customRelativeText; + + private final RadioButtonGroup diffTypeRadioGroup = new RadioButtonGroup(); + private final RadioButtonGroup unifiedRadioGroup = new RadioButtonGroup(); + + private final DefaultValuesStore store; + + protected OptionsPage(String pageName, String title, + ImageDescriptor titleImage, DefaultValuesStore store) { + super(pageName, title, titleImage); + this.store = store; + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + if (!initialized && visible) { + File toFile = null; + if (directionSelectionPage.isRightToLeft()) { + toFile = new File(leftPath); + } else { + toFile = new File(rightPath); + } + String toPath = toFile.getPath(); + unified_customRelativeText.setText(toPath); + targetFileEdited = true; + } + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(); + composite.setLayout(layout); + composite.setLayoutData(new GridData()); + setControl(composite); + + Group diffTypeGroup = new Group(composite, SWT.NONE); + layout = new GridLayout(); + layout.marginHeight = 0; + diffTypeGroup.setLayout(layout); + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL + | GridData.GRAB_HORIZONTAL); + diffTypeGroup.setLayoutData(data); + diffTypeGroup.setText(CompareMessages.Diff_output_format_12); + + unifiedDiffOption = new Button(diffTypeGroup, SWT.RADIO); + unifiedDiffOption + .setText(CompareMessages.Unified__format_required_by_Compare_With_Patch_feature__13); + + contextDiffOption = new Button(diffTypeGroup, SWT.RADIO); + contextDiffOption.setText(CompareMessages.Context_14); + regularDiffOption = new Button(diffTypeGroup, SWT.RADIO); + regularDiffOption.setText(CompareMessages.Standard_15); + + diffTypeRadioGroup.add(FORMAT_UNIFIED, unifiedDiffOption); + diffTypeRadioGroup.add(FORMAT_CONTEXT, contextDiffOption); + diffTypeRadioGroup.add(FORMAT_STANDARD, regularDiffOption); + + // Unified Format Options + Group unifiedGroup = new Group(composite, SWT.None); + layout = new GridLayout(); + layout.numColumns = 2; + unifiedGroup.setLayout(layout); + data = new GridData(GridData.HORIZONTAL_ALIGN_FILL + | GridData.GRAB_HORIZONTAL); + unifiedGroup.setLayoutData(data); + unifiedGroup.setText(CompareMessages.GenerateDiffFileWizard_10); + + unified_workspaceRelativeOption = new Button(unifiedGroup, + SWT.RADIO); + unified_workspaceRelativeOption + .setText(CompareMessages.GenerateDiffFileWizard_6); + unified_workspaceRelativeOption.setLayoutData(new GridData( + SWT.BEGINNING, SWT.CENTER, false, false, 2, 1)); + + unified_projectRelativeOption = new Button(unifiedGroup, SWT.RADIO); + unified_projectRelativeOption + .setText(CompareMessages.GenerateDiffFileWizard_7); + unified_projectRelativeOption.setLayoutData(new GridData( + SWT.BEGINNING, SWT.CENTER, false, false, 2, 1)); + + unified_selectionRelativeOption = new Button(unifiedGroup, + SWT.RADIO); + unified_selectionRelativeOption + .setText(CompareMessages.GenerateDiffFileWizard_8); + unified_selectionRelativeOption.setLayoutData(new GridData( + SWT.BEGINNING, SWT.CENTER, false, false, 2, 1)); + + unified_customRelativeOption = new Button(unifiedGroup, SWT.RADIO); + unified_customRelativeOption + .setText(CompareMessages.GenerateDiffFileWizard_13); + unified_customRelativeOption.setSelection(true); + unified_customRelativeOption.setLayoutData(new GridData( + SWT.BEGINNING, SWT.CENTER, false, false, 1, 1)); + + unified_customRelativeText = new Text(unifiedGroup, SWT.BORDER); + unified_customRelativeText.setLayoutData(new GridData(SWT.FILL, + SWT.CENTER, true, false, 1, 1)); + + unifiedRadioGroup.add(ROOT_WORKSPACE, + unified_workspaceRelativeOption); + unifiedRadioGroup.add(ROOT_PROJECT, unified_projectRelativeOption); + unifiedRadioGroup.add(ROOT_SELECTION, + unified_selectionRelativeOption); + unifiedRadioGroup.add(ROOT_CUSTOM, unified_customRelativeOption); + + Dialog.applyDialogFont(parent); + + initializeDefaultValues(); + + // add listeners + unifiedDiffOption.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + diffTypeRadioGroup.setSelection(FORMAT_UNIFIED, false); + } + }); + + contextDiffOption.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + diffTypeRadioGroup.setSelection(FORMAT_CONTEXT, false); + } + }); + + regularDiffOption.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + diffTypeRadioGroup.setSelection(FORMAT_STANDARD, false); + } + }); + + unified_workspaceRelativeOption + .addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + unifiedRadioGroup.setSelection(ROOT_WORKSPACE, + false); + } + }); + + unified_projectRelativeOption + .addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + unifiedRadioGroup.setSelection(ROOT_PROJECT, false); + } + }); + + unified_selectionRelativeOption + .addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + unifiedRadioGroup.setSelection(ROOT_SELECTION, + false); + } + }); + + unified_selectionRelativeOption + .addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + unifiedRadioGroup.setSelection(ROOT_CUSTOM, false); + } + }); + + // calculatePatchRoot(); + updateEnablements(); + + // update selection + diffTypeRadioGroup.selectEnabledOnly(); + unifiedRadioGroup.selectEnabledOnly(); + } + + public int getFormatSelection() { + return diffTypeRadioGroup.getSelected(); + } + + public int getRootSelection() { + return unifiedRadioGroup.getSelected(); + } + + public String getPath() { + return unified_customRelativeText.getText(); + } + + private void initializeDefaultValues() { + // Radio buttons for format + diffTypeRadioGroup.setSelection(store.getFormatSelection(), true); + // Radio buttons for patch root + unifiedRadioGroup.setSelection(store.getRootSelection(), true); + } + + protected void updateEnablements() { + diffTypeRadioGroup.setEnablement(false, new int[] { FORMAT_CONTEXT, + FORMAT_STANDARD }, FORMAT_UNIFIED); + unifiedRadioGroup.setEnablement(false, new int[] { ROOT_WORKSPACE, + ROOT_PROJECT, ROOT_SELECTION }, ROOT_CUSTOM); + } + + } + + /** + * Class to retrieve and store the default selected values. + */ + private final class DefaultValuesStore { + + private static final String PREF_LAST_SELECTION = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.lastselection"; //$NON-NLS-1$ + private static final String PREF_LAST_FS_PATH = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.filesystem.path"; //$NON-NLS-1$ + private static final String PREF_LAST_WS_PATH = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.workspace.path"; //$NON-NLS-1$ + private static final String PREF_LAST_AO_FORMAT = "org.eclipse.compare.internal.GenerateDiffFileWizard.OptionsPage.diff.format"; //$NON-NLS-1$ + private static final String PREF_LAST_AO_ROOT = "org.eclipse.compare.internal.GenerateDiffFileWizard.OptionsPage.patch.root"; //$NON-NLS-1$ + + private final IDialogSettings dialogSettings; + + public DefaultValuesStore() { + dialogSettings = CompareUIPlugin.getDefault().getDialogSettings(); + } + + public int getLocationSelection() { + int value = LocationPage.CLIPBOARD; + try { + value = dialogSettings.getInt(PREF_LAST_SELECTION); + } catch (NumberFormatException e) { + // Ignore + } + + switch (value) { + case LocationPage.FILESYSTEM: + case LocationPage.WORKSPACE: + case LocationPage.CLIPBOARD: + return value; + default: + return LocationPage.CLIPBOARD; + } + } + + public String getFilesystemPath() { + final String path = dialogSettings.get(PREF_LAST_FS_PATH); + return path != null ? path : ""; //$NON-NLS-1$ + } + + public String getWorkspacePath() { + final String path = dialogSettings.get(PREF_LAST_WS_PATH); + return path != null ? path : ""; //$NON-NLS-1$ + } + + public int getFormatSelection() { + int value = OptionsPage.FORMAT_UNIFIED; + try { + value = dialogSettings.getInt(PREF_LAST_AO_FORMAT); + } catch (NumberFormatException e) { + // Ignore + } + + switch (value) { + case OptionsPage.FORMAT_UNIFIED: + case OptionsPage.FORMAT_CONTEXT: + case OptionsPage.FORMAT_STANDARD: + return value; + default: + return OptionsPage.FORMAT_UNIFIED; + } + } + + public int getRootSelection() { + int value = OptionsPage.ROOT_WORKSPACE; + try { + value = dialogSettings.getInt(PREF_LAST_AO_ROOT); + } catch (NumberFormatException e) { + // Ignore + } + + switch (value) { + case OptionsPage.ROOT_WORKSPACE: + case OptionsPage.ROOT_PROJECT: + case OptionsPage.ROOT_SELECTION: + return value; + default: + return OptionsPage.ROOT_WORKSPACE; + } + } + + public void storeLocationSelection(int defaultSelection) { + dialogSettings.put(PREF_LAST_SELECTION, defaultSelection); + } + + public void storeFilesystemPath(String path) { + dialogSettings.put(PREF_LAST_FS_PATH, path); + } + + public void storeWorkspacePath(String path) { + dialogSettings.put(PREF_LAST_WS_PATH, path); + } + + public void storeOutputFormat(int selection) { + dialogSettings.put(PREF_LAST_AO_FORMAT, selection); + } + + public void storePatchRoot(int selection) { + dialogSettings.put(PREF_LAST_AO_ROOT, selection); + } + } + + private DirectionSelectionPage directionSelectionPage; + private LocationPage locationPage; + private OptionsPage optionsPage; + + // protected IResource[] resources; + private final DefaultValuesStore defaultValuesStore; + // private final IWorkbenchPart part; + + private DocumentMerger merger; + private IDocument leftDoc; + private IDocument rightDoc; + private String leftLabel; + private String rightLabel; + private String leftPath; + private String rightPath; + private boolean rightToLeft; + + private boolean targetFileEdited = false; + + public SaveDiffFileWizard(DocumentMerger merger, IDocument leftDoc, + IDocument rightDoc, String leftLabel, String rightLabel, + String leftPath, String rightPath, boolean rightToLeft) { + super(); + setWindowTitle(CompareMessages.GenerateLocalDiff_title); + initializeDefaultPageImageDescriptor(); + defaultValuesStore = new DefaultValuesStore(); + this.merger = merger; + this.leftDoc = leftDoc; + this.rightDoc = rightDoc; + this.leftLabel = leftLabel; + this.rightLabel = rightLabel; + this.leftPath = leftPath; + this.rightPath = rightPath; + this.rightToLeft = rightToLeft; + } + + public void addPages() { + String pageTitle = CompareMessages.GenerateLocalDiff_pageTitle; + String pageDescription = CompareMessages.GenerateLocalDiff_Specify_the_file_which_contributes_the_changes; + directionSelectionPage = new DirectionSelectionPage( + pageTitle, + pageTitle, + CompareUIPlugin + .getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF)); + directionSelectionPage.setDescription(pageDescription); + addPage(directionSelectionPage); + + pageTitle = CompareMessages.GenerateLocalDiff_pageTitle; + pageDescription = CompareMessages.GenerateLocalDiff_pageDescription; + locationPage = new LocationPage(pageTitle, pageTitle, CompareUIPlugin + .getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF), + defaultValuesStore); + locationPage.setDescription(pageDescription); + addPage(locationPage); + + pageTitle = CompareMessages.Advanced_options_19; + pageDescription = CompareMessages.Configure_the_options_used_for_the_CVS_diff_command_20; + optionsPage = new OptionsPage(pageTitle, pageTitle, CompareUIPlugin + .getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF), + defaultValuesStore); + optionsPage.setDescription(pageDescription); + addPage(optionsPage); + } + + /** + * Declares the wizard banner iamge descriptor + */ + protected void initializeDefaultPageImageDescriptor() { + final String iconPath = "icons/full/"; //$NON-NLS-1$ + try { + final URL installURL = CompareUIPlugin.getDefault().getBundle() + .getEntry("/"); //$NON-NLS-1$ + final URL url = new URL(installURL, iconPath + + "wizards/newconnect_wiz.gif"); //$NON-NLS-1$ + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + setDefaultPageImageDescriptor(desc); + } catch (MalformedURLException e) { + // Should not happen. Ignore. + } + } + + /* + * (Non-javadoc) Method declared on IWizard. + */ + public boolean needsProgressMonitor() { + return true; + } + + public boolean performFinish() { + final int location = locationPage.getSelectedLocation(); + final File file = location != LocationPage.CLIPBOARD ? locationPage + .getFile() : null; + + if (!(file == null || validateFile(file))) { + return false; + } + + // Create the patch + generateDiffFile(file); + + // Refresh workspace if necessary and save default selection. + switch (location) { + case LocationPage.WORKSPACE: + final String workspaceResource = locationPage + .getWorkspaceLocation(); + if (workspaceResource != null) { + defaultValuesStore + .storeLocationSelection(LocationPage.WORKSPACE); + defaultValuesStore.storeWorkspacePath(workspaceResource); + } else { + // Problem with workspace location, choose clipboard next time + defaultValuesStore + .storeLocationSelection(LocationPage.CLIPBOARD); + } + break; + case LocationPage.FILESYSTEM: + defaultValuesStore.storeFilesystemPath(file.getPath()); + defaultValuesStore.storeLocationSelection(LocationPage.FILESYSTEM); + break; + case LocationPage.CLIPBOARD: + defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD); + break; + default: + return false; + } + + defaultValuesStore.storeOutputFormat(optionsPage.getFormatSelection()); + defaultValuesStore.storePatchRoot(optionsPage.getRootSelection()); + + return true; + } + + private void generateDiffFile(File file) { + String toPath = null; + if (targetFileEdited) { + toPath = optionsPage.getPath(); + } else { + File toFile = null; + if (directionSelectionPage.isRightToLeft()) { + toFile = new File(leftPath); + } else { + toFile = new File(rightPath); + } + toPath = toFile.getPath(); + } + + UnifiedDiffFormatter formatter = new UnifiedDiffFormatter(merger, + leftDoc, rightDoc, toPath, directionSelectionPage + .isRightToLeft()); + try { + if (file == null) { + formatter.generateDiff(getShell().getDisplay()); + } else { + formatter.generateDiff(file); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public boolean validateFile(File file) { + if (file == null) + return false; + + // Consider file valid if it doesn't exist for now. + if (!file.exists()) + return true; + + // The file exists. + if (!file.canWrite()) { + final String title = CompareMessages.GenerateLocalDiff_1; + final String msg = CompareMessages.GenerateLocalDiff_2; + final MessageDialog dialog = new MessageDialog(getShell(), title, + null, msg, MessageDialog.ERROR, + new String[] { IDialogConstants.OK_LABEL }, 0); + dialog.open(); + return false; + } + + final String title = CompareMessages.GenerateLocalDiff_overwriteTitle; + final String msg = CompareMessages.GenerateLocalDiff_overwriteMsg; + final MessageDialog dialog = new MessageDialog(getShell(), title, null, + msg, MessageDialog.QUESTION, new String[] { + IDialogConstants.YES_LABEL, + IDialogConstants.CANCEL_LABEL }, 0); + dialog.open(); + if (dialog.getReturnCode() != 0) { + return false; + } + return true; + } + + /** + * The class maintain proper selection of radio button within the group: + *

+ */ + private class RadioButtonGroup { + + private List buttons = new ArrayList(3); + + private int selected = 0; + + public void add(int buttonCode, Button button) { + if (button != null && (button.getStyle() & SWT.RADIO) != 0) { + if (button.getSelection() && !buttons.isEmpty()) { + deselectAll(); + selected = buttonCode - 1; + } + buttons.add(buttonCode - 1, button); + } + } + + public int getSelected() { + return selected + 1; + } + + public int setSelection(int buttonCode, boolean selectEnabledOnly) { + deselectAll(); + + ((Button) buttons.get(buttonCode - 1)).setSelection(true); + selected = buttonCode - 1; + if (selectEnabledOnly) + selected = selectEnabledOnly() - 1; + return getSelected(); + } + + public int selectEnabledOnly() { + deselectAll(); + Button selectedButton = (Button) buttons.get(selected); + if (!selectedButton.isEnabled()) { + // If the button is disabled, set selection to an enabled one + for (Iterator iterator = buttons.iterator(); iterator.hasNext();) { + Button b = (Button) iterator.next(); + if (b.isEnabled()) { + b.setSelection(true); + selected = buttons.indexOf(b); + return selected + 1; + } + } + // If none found, reset the initial selection + selectedButton.setSelection(true); + } else { + // Because selection has been cleared, set it again + selectedButton.setSelection(true); + } + // Return selected button's code so the value can be stored + return getSelected(); + } + + public void setEnablement(boolean enabled, int[] buttonsToChange, + int defaultSelection) { + // Enable (or disable) given buttons + for (int i = 0; i < buttonsToChange.length; i++) { + ((Button) this.buttons.get(buttonsToChange[i] - 1)) + .setEnabled(enabled); + } + // Check whether the selected button is enabled + if (!((Button) this.buttons.get(selected)).isEnabled()) { + if (defaultSelection != -1) + // Set the default selection and check if it's enabled + setSelection(defaultSelection, true); + else + // No default selection is given, select any enabled button + selectEnabledOnly(); + } + } + + public void setEnablement(boolean enabled, int[] buttonsToChange) { + // Value -1 means that no default selection is given + setEnablement(enabled, buttonsToChange, -1); + } + + private void deselectAll() { + for (Iterator iterator = buttons.iterator(); iterator.hasNext();) + ((Button) iterator.next()).setSelection(false); + } + } + +} Index: compare/org/eclipse/compare/internal/CreatePatchAction.java =================================================================== RCS file: compare/org/eclipse/compare/internal/CreatePatchAction.java diff -N compare/org/eclipse/compare/internal/CreatePatchAction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compare/org/eclipse/compare/internal/CreatePatchAction.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal; + +import java.lang.reflect.Field; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.contentmergeviewer.ContentMergeViewer; +import org.eclipse.compare.contentmergeviewer.TextMergeViewer; +import org.eclipse.compare.internal.merge.DocumentMerger; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.part.FileEditorInput; + +public class CreatePatchAction extends Action { + + private TextMergeViewer viewer; + private boolean rightToLeft; + + public CreatePatchAction(TextMergeViewer viewer, boolean rightToLeft) { + super(CompareMessages.CreatePatchActionTitle); + this.viewer = viewer; + this.rightToLeft = rightToLeft; + } + + public void run() { + SaveDiffFileWizard.run(getMerger(), getDocument(true), + getDocument(false), getLabel(true), getLabel(false), + getPath(true), getPath(false), viewer.getControl().getShell(), + rightToLeft); + } + + private String getPath(boolean left) { + try { + Field ciField = null; + if (left) { + ciField = TextMergeViewer.class + .getDeclaredField("fLeftContributor"); //$NON-NLS-1$ + } else { + ciField = TextMergeViewer.class + .getDeclaredField("fRightContributor"); //$NON-NLS-1$ + } + ciField.setAccessible(true); + Object ciObj = ciField.get(viewer); + Class clazz = ciObj.getClass(); + Field field = clazz.getDeclaredField("fDocumentKey"); //$NON-NLS-1$ + field.setAccessible(true); + IEditorInput editorInput = (IEditorInput) field.get(ciObj); + if (editorInput instanceof FileEditorInput) { + FileEditorInput fei = (FileEditorInput) editorInput; + String path = fei.getFile().getProjectRelativePath().toString(); + return path; + } + } catch (Exception e) { + e.printStackTrace(); + } + return ""; //$NON-NLS-1$ + } + + private String getLabel(boolean left) { + try { + Field field = ContentMergeViewer.class + .getDeclaredField("fCompareConfiguration"); //$NON-NLS-1$ + field.setAccessible(true); + CompareConfiguration cc = (CompareConfiguration) field.get(viewer); + if (left) { + field = CompareConfiguration.class + .getDeclaredField("fLeftLabel"); //$NON-NLS-1$ + } else { + field = CompareConfiguration.class + .getDeclaredField("fRightLabel"); //$NON-NLS-1$ + } + field.setAccessible(true); + return (String) field.get(cc); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public DocumentMerger getMerger() { + try { + Field field = TextMergeViewer.class.getDeclaredField("fMerger"); //$NON-NLS-1$ + field.setAccessible(true); + return (DocumentMerger) field.get(viewer); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private IDocument getDocument(boolean left) { + try { + Field field = null; + if (left) { + field = TextMergeViewer.class.getDeclaredField("fLeft"); //$NON-NLS-1$ + } else { + field = TextMergeViewer.class.getDeclaredField("fRight"); //$NON-NLS-1$ + } + field.setAccessible(true); + MergeSourceViewer msv = (MergeSourceViewer) field.get(viewer); + field = MergeSourceViewer.class + .getDeclaredField("fRememberedDocument"); //$NON-NLS-1$ + field.setAccessible(true); + return (IDocument) field.get(msv); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} Index: compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java =================================================================== RCS file: compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java diff -N compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,303 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Krzysztof Poglodzinski (intuicje@gmail.com) - initial API and implementation + * Mariusz Tanski (mariusztanski@gmail.com) - initial API and implementation + * Kacper Zdanowicz (kacper.zdanowicz@gmail.com) - initial API and implementation + * IBM Corportation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +import org.eclipse.compare.internal.merge.DocumentMerger; +import org.eclipse.compare.internal.merge.DocumentMerger.Diff; +import org.eclipse.compare.rangedifferencer.RangeDifference; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Display; + +public class UnifiedDiffFormatter { + + public static final char RIGHT_CONTRIBUTOR = 'R'; + public static final char LEFT_CONTRIBUTOR = 'L'; + + public final static int FORMAT_UNIFIED = 1; + public final static int FORMAT_CONTEXT = 2; + public final static int FORMAT_STANDARD = 3; + + public static final String INDEX_MARKER = "Index: "; //$NON-NLS-1$ + public static final String DELIMITER = "==================================================================="; //$NON-NLS-1$ + public static final String OLD_FILE_PREFIX = "--- "; //$NON-NLS-1$ + public static final String NEW_FILE_PREFIX = "+++ "; //$NON-NLS-1$ + public static final String OLD_LINE_PREFIX = "-"; //$NON-NLS-1$ + public static final String NEW_LINE_PREFIX = "+"; //$NON-NLS-1$ + public static final String CONTEXT_LINE_PREFIX = " "; //$NON-NLS-1$ + + private DocumentMerger merger; + private IDocument leftDoc; + private IDocument rightDoc; + private String resourcePath; + private boolean rightToLeft; + + public UnifiedDiffFormatter(DocumentMerger merger, IDocument leftDoc, + IDocument rightDoc, String resourcePath, boolean rightToLeft) { + this.merger = merger; + this.leftDoc = leftDoc; + this.rightDoc = rightDoc; + this.resourcePath = resourcePath; + this.rightToLeft = rightToLeft; + } + + public void generateDiff(Display dis) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(bos); + + createDiff(ps); + ps.close(); + + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + Clipboard clipboard = new Clipboard(dis); + clipboard.setContents(new String[] { bos.toString() }, + new Transfer[] { plainTextTransfer }); + clipboard.dispose(); + + bos.close(); + } + + public void generateDiff(File file) throws IOException { + FileOutputStream fos = null; + PrintStream ps = null; + try { + fos = new FileOutputStream(file); + try { + ps = new PrintStream(fos); + createDiff(ps); + if (ps.checkError()) { + throw new IOException("Error while writing patch file: " //$NON-NLS-1$ + + file); + } + } finally { + if (ps != null) { + ps.close(); + } + } + } finally { + if (fos != null) { + fos.close(); + } + } + } + + public void createDiff(PrintStream output) { + ArrayList allDiffs = merger.getAllDiffs(); + // If the first block isn't the only one, or first block is different + if (allDiffs.size() > 1 || isPartDifferent(allDiffs, 0)) { + output.println(INDEX_MARKER + resourcePath); + output.println(DELIMITER); + + SimpleDateFormat format = new SimpleDateFormat( + "dd MMM yyyy hh:mm:ss", Locale.US); //$NON-NLS-1$ + Date oldDate = Calendar.getInstance(Locale.US).getTime(); + Date newDate = Calendar.getInstance(Locale.US).getTime(); + output.println(OLD_FILE_PREFIX + resourcePath + '\t' + + format.format(oldDate) + " -0000"); //$NON-NLS-1$ + output.println(NEW_FILE_PREFIX + resourcePath + '\t' + + format.format(newDate) + " -0000"); //$NON-NLS-1$ + + boolean firstHunk = true; + Hunk currentHunk = null; + + int currentLineNumberOld = 0; + int currentLineNumberNew = 0; + + for (int partNumber = 0; partNumber < allDiffs.size(); partNumber++) { + + ArrayList oldPart = getPart(partNumber, 'R'); + ArrayList newPart = getPart(partNumber, 'L'); + + if (isPartDifferent(allDiffs, partNumber)) { + // This part has some changes + if (firstHunk) { + // Hunk will start with changed block + currentHunk = new Hunk(0, 0); + firstHunk = false; + } + if (partNumber == (allDiffs.size() - 1)) { + // If it is the last part + currentHunk.addPartRangeToOld(oldPart, 0, oldPart + .size(), true); + currentHunk.addPartRangeToNew(newPart, 0, newPart + .size(), true); + } else { + currentHunk.addPartRangeToOld(oldPart, 0, oldPart + .size(), false); + currentHunk.addPartRangeToNew(newPart, 0, newPart + .size(), false); + } + } else { + if (firstHunk) { + // Hunk will start with context + currentHunk = new Hunk(oldPart.size() - 3, oldPart + .size() - 3); + firstHunk = false; + currentHunk.addPartRangeToBoth(oldPart, + oldPart.size() - 3, oldPart.size(), false); + } else { + if (partNumber == (allDiffs.size() - 1)) { + // If it is the last part + currentHunk.addPartRangeToBoth(oldPart, 0, 3, true); + } else { + if (oldPart.size() < 6) { + // Context too short to start new hunk + currentHunk.addPartRangeToBoth(oldPart, 0, + oldPart.size(), false); + } else { + // Context long enough to start new hunk + currentHunk.addPartRangeToBoth(oldPart, 0, 3, + false); + currentHunk.printTo(output); + currentHunk = new Hunk(currentLineNumberOld + + oldPart.size() - 3, + currentLineNumberNew + oldPart.size() + - 3); + currentHunk.addPartRangeToBoth(oldPart, oldPart + .size() - 3, oldPart.size(), false); + } + } + } + } + currentLineNumberOld += oldPart.size(); + currentLineNumberNew += newPart.size(); + } + // Print the last hunk + currentHunk.printTo(output); + } + } + + private ArrayList getPart(int nr, char side) { + try { + String s = extract(nr, side).replaceAll("\r\n", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + s.replaceAll("\r", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + ArrayList diffLines = new ArrayList(Arrays + .asList(s.split("\n", -1))); //$NON-NLS-1$ + return diffLines; + } catch (BadLocationException e) { + CompareUIPlugin.log(e); + } + return null; + } + + private String extract(int nr, char side) throws BadLocationException { + Diff diff = ((Diff) merger.getAllDiffs().get(nr)); + if (side == LEFT_CONTRIBUTOR && !rightToLeft + || side == RIGHT_CONTRIBUTOR && rightToLeft) { + return leftDoc.get(diff.getPosition(LEFT_CONTRIBUTOR).offset, diff + .getPosition(LEFT_CONTRIBUTOR).length); + } + return rightDoc.get(diff.getPosition(RIGHT_CONTRIBUTOR).offset, diff + .getPosition(RIGHT_CONTRIBUTOR).length); + } + + public boolean isPartDifferent(ArrayList allDiffs, int nr) { + Diff diff = ((Diff) allDiffs.get(nr)); + if (diff.getKind() == RangeDifference.CHANGE) { + return true; + } + return false; + } + + private class Hunk { + private int oldStart; + private int oldEnd; + private int newStart; + private int newEnd; + ArrayList lines; + + public Hunk(int oldStart, int newStart) { + if (oldStart < 0) + oldStart = 0; + if (newStart < 0) + newStart = 0; + this.oldStart = oldStart; + this.newStart = newStart; + this.oldEnd = oldStart; + this.newEnd = newStart; + lines = new ArrayList(); + } + + public void addPartRangeToOld(ArrayList part, int start, int end, + boolean lastPart) { + if (start < 0) + start = 0; + if (lastPart) + end = Math.min(end, part.size()); + else + end = Math.min(end, part.size() - 1); + for (int lineNr = start; lineNr < end; lineNr++) { + lines.add(OLD_LINE_PREFIX + part.get(lineNr)); + oldEnd++; + } + } + + public void addPartRangeToNew(ArrayList part, int start, int end, + boolean lastPart) { + if (start < 0) + start = 0; + if (lastPart) + end = Math.min(end, part.size()); + else + end = Math.min(end, part.size() - 1); + for (int lineNr = start; lineNr < end; lineNr++) { + lines.add(NEW_LINE_PREFIX + part.get(lineNr)); + newEnd++; + } + } + + public void addPartRangeToBoth(ArrayList part, int start, int end, + boolean lastPart) { + if (start < 0) + start = 0; + if (lastPart) + end = Math.min(end, part.size()); + else + end = Math.min(end, part.size() - 1); + for (int lineNr = start; lineNr < end; lineNr++) { + lines.add(CONTEXT_LINE_PREFIX + part.get(lineNr)); + oldEnd++; + newEnd++; + } + } + + private void printMarkerTo(PrintStream output) { + output.println("@@ -" + oldStart + "," + oldEnd + " +" + newStart //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + "," + newEnd + " @@"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public void printTo(PrintStream output) { + printMarkerTo(output); + for (int i = 0; i < lines.size(); i++) { + output.println(lines.get(i)); + } + } + } + +}