View | Details | Raw Unified | Return to bug 71374 | Differences between
and this patch

Collapse All | Expand All

(-)compare/org/eclipse/compare/internal/CompareMessages.java (+54 lines)
Lines 22-27 Link Here
22
		// Do not instantiate
22
		// Do not instantiate
23
	}
23
	}
24
24
25
	public static String CreatePatchAction_pageDescription;
26
	public static String CreatePatchActionTitle;
25
	public static String CompareContainer_0;
27
	public static String CompareContainer_0;
26
	public static String CompareDialog_commit_button;
28
	public static String CompareDialog_commit_button;
27
	public static String CompareDialog_error_message;
29
	public static String CompareDialog_error_message;
Lines 130-135 Link Here
130
	public static String CompareWithOtherResourceDialog_workspaceMainButton;
132
	public static String CompareWithOtherResourceDialog_workspaceMainButton;
131
	public static String CompareWithOtherResourceDialog_workspaceRadioButton;
133
	public static String CompareWithOtherResourceDialog_workspaceRadioButton;
132
134
135
	public static String GenerateLocalDiff_title;
136
	public static String WorkspacePatchDialogTitle;
137
	public static String WorkspacePatchDialogDescription;
138
	public static String GenerateDiffFileWizard_9;
139
	public static String Fi_le_name__9;
140
	public static String GenerateDiffFileWizard_5;
141
	public static String GenerateDiffFileWizard_FolderExists;
142
	public static String GenerateDiffFileWizard_noChangesSelected;
143
	public static String GenerateDiffFileWizard_0;
144
	public static String GenerateDiffFileWizard_browseFilesystem;
145
	public static String GenerateDiffFileWizard_2;
146
	public static String GenerateDiffFileWizard_3;
147
	public static String GenerateDiffFileWizard_4;
148
	public static String GenerateDiffFileWizard_ProjectClosed;
149
	public static String GenerateDiffFileWizard_SelectAll;
150
	public static String GenerateDiffFileWizard_DeselectAll;
151
	public static String Save_To_Clipboard_2;
152
	public static String Save_In_File_System_3;
153
	public static String Browse____4;
154
	public static String Save_In_Workspace_7;
155
	public static String CommitWizardCommitPage_1;
156
	public static String CommitWizardCommitPage_5;
157
	public static String Save_Patch_As_5;
158
	public static String patch_txt_6;
159
	public static String CommitWizard_4;
160
	public static String Diff_output_format_12;
161
	public static String Unified__format_required_by_Compare_With_Patch_feature__13;
162
	public static String Context_14;
163
	public static String Standard_15;
164
	public static String GenerateDiffFileWizard_10;
165
	public static String GenerateDiffFileWizard_6;
166
	public static String GenerateDiffFileWizard_7;
167
	public static String GenerateDiffFileWizard_8;
168
	public static String CreatePatchAction_pageTitle;
169
	public static String GenerateLocalDiff_pageTitle;
170
	public static String GenerateLocalDiff_pageDescription;
171
	public static String Advanced_options_19;
172
	public static String Configure_the_options_used_for_the_local_diff_command_20;
173
	public static String GenerateCVSDiff_error;
174
	public static String GenerateDiffFileWizard_11;
175
	public static String GenerateDiffFileWizard_12;
176
	public static String GenerateLocalDiff_1;
177
	public static String GenerateLocalDiff_2;
178
	public static String GenerateLocalDiff_sourceChoose_left;
179
	public static String GenerateLocalDiff_sourceChoose_right;
180
	public static String GenerateLocalDiff_overwriteTitle;
181
	public static String GenerateLocalDiff_overwriteMsg;
182
183
	public static String GenerateLocalDiffFile_CheckSourceFile_pageTitle;
184
	public static String GenerateLocalDiffFile_CheckSourceFile_pageDescription;
185
186
	
133
	static {
187
	static {
134
		NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class);
188
		NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class);
135
	}
189
	}
(-)compare/org/eclipse/compare/internal/CompareMessages.properties (+54 lines)
Lines 141-143 Link Here
141
CompareWithOtherResourceDialog_externalFolderRadioButton=External folder
141
CompareWithOtherResourceDialog_externalFolderRadioButton=External folder
142
CompareWithOtherResourceDialog_workspaceMainButton=Browse...
142
CompareWithOtherResourceDialog_workspaceMainButton=Browse...
143
CompareWithOtherResourceDialog_workspaceRadioButton=Workspace
143
CompareWithOtherResourceDialog_workspaceRadioButton=Workspace
144
145
CreatePatchAction_pageTitle=Create Patch from local file
146
CommitWizardCommitPage_1=Hiding changes. The {0} changes exceeds the display threshold of {1}. It may take a long time to show this number of changes.
147
CommitWizardCommitPage_5=Show &Changes
148
GenerateLocalDiff_title=Create Patch
149
GenerateLocalDiff_pageTitle=Create a Patch Using the local Diff Command
150
GenerateLocalDiff_pageDescription=Specify the input and the location for the patch.
151
GenerateLocalDiff_overwriteTitle=Confirm Overwrite
152
GenerateLocalDiff_overwriteMsg=A file with that name already exists. Overwrite?
153
GenerateCVSDiff_error=Error running the CVS diff command
154
GenerateLocalDiff_1=Read-only file
155
GenerateLocalDiff_2=The specified file is read-only and cannot be overwritten.
156
GenerateLocalDiff_sourceChoose_left=Left:
157
GenerateLocalDiff_sourceChoose_right=Right:
158
Save_To_Clipboard_2=&Clipboard
159
Save_In_File_System_3=Fil&e
160
Browse____4=Br&owse...
161
Save_Patch_As_5=Save Patch As
162
patch_txt_6=patch.txt
163
Save_In_Workspace_7=&Workspace
164
WorkspacePatchDialogTitle=Set a Patch Location
165
WorkspacePatchDialogDescription=Select a folder in the workspace and enter a name for the patch.
166
Fi_le_name__9=Fi&le name:
167
Diff_output_format_12=Diff Output Format
168
Unified__format_required_by_Compare_With_Patch_feature__13=&Unified (format required by the Apply Patch wizard)
169
Context_14=&Context
170
Standard_15=&Standard
171
Advanced_options_19=Advanced Options
172
Configure_the_options_used_for_the_local_diff_command_20=Configure the options used for the local diff command.
173
GenerateDiffFileWizard_0=Please enter a valid location.
174
GenerateDiffFileWizard_2=Please enter a file name.
175
GenerateDiffFileWizard_3=The specified directory does not exist.
176
GenerateDiffFileWizard_4=Please select a location in the workspace by browsing.
177
GenerateDiffFileWizard_5=Please enter a valid filename.
178
GenerateDiffFileWizard_6=&Workspace (Multi-project Apply Patch wizard specific)
179
GenerateDiffFileWizard_7=&Project
180
GenerateDiffFileWizard_8=S&election
181
GenerateDiffFileWizard_9=Save Patch
182
GenerateDiffFileWizard_10=Patch Root
183
GenerateDiffFileWizard_11=Include Binary Files?
184
GenerateDiffFileWizard_12=The selected resources include files marked as binary. CVS does not handle the creation of patches for binary files. Should the files marked as binary be included?
185
GenerateDiffFileWizard_SelectAll=Select &All
186
GenerateDiffFileWizard_DeselectAll=&Deselect All
187
GenerateDiffFileWizard_browseFilesystem=Please select a location in the filesystem by browsing.
188
GenerateDiffFileWizard_noChangesSelected=No changes selected.
189
GenerateDiffFileWizard_FolderExists=The specified path points to an existing folder.
190
GenerateDiffFileWizard_ProjectClosed=The specified path points to a closed project.
191
CommitWizard_4=Collecting outgoing changes
192
193
CreatePatchAction_pageDescription=Description
194
GenerateLocalDiffFile_CheckSourceFile_pageTitle=Choose source/goal file
195
GenerateLocalDiffFile_CheckSourceFile_pageDescription=Choose source file = left or goal = right
196
197
CreatePatchActionTitle=Create Patch...
(-)compare/org/eclipse/compare/internal/ICompareUIConstants.java (+3 lines)
Lines 49-52 Link Here
49
	public static final String PREF_VALUE_NEXT = "next"; //$NON-NLS-1$
49
	public static final String PREF_VALUE_NEXT = "next"; //$NON-NLS-1$
50
50
51
	public static final String COMMAND_IGNORE_WHITESPACE = PREFIX + "ignoreWhiteSpace"; //$NON-NLS-1$
51
	public static final String COMMAND_IGNORE_WHITESPACE = PREFIX + "ignoreWhiteSpace"; //$NON-NLS-1$
52
	
53
	public static final String IMG_WIZBAN_DIFF = "wizban/createpatch_wizban.png"; //$NON-NLS-1$
54
	
52
}
55
}
(-)compare/org/eclipse/compare/internal/MergeSourceViewer.java (+2 lines)
Lines 99-104 Link Here
99
	public static final String SAVE_ID= "save"; //$NON-NLS-1$
99
	public static final String SAVE_ID= "save"; //$NON-NLS-1$
100
	public static final String FIND_ID= "find"; //$NON-NLS-1$
100
	public static final String FIND_ID= "find"; //$NON-NLS-1$
101
	public static final String GOTO_LINE_ID= "gotoLine"; //$NON-NLS-1$
101
	public static final String GOTO_LINE_ID= "gotoLine"; //$NON-NLS-1$
102
	public static final String CREATE_PATCH_ID= "createPatch"; //$NON-NLS-1$
102
103
103
	class TextOperationAction extends MergeViewerAction {
104
	class TextOperationAction extends MergeViewerAction {
104
		
105
		
Lines 789-794 Link Here
789
		addMenu(menu, SELECT_ALL_ID);
790
		addMenu(menu, SELECT_ALL_ID);
790
791
791
		menu.add(new Separator("edit")); //$NON-NLS-1$
792
		menu.add(new Separator("edit")); //$NON-NLS-1$
793
		addMenu(menu, CREATE_PATCH_ID);
792
		menu.add(new Separator("find")); //$NON-NLS-1$
794
		menu.add(new Separator("find")); //$NON-NLS-1$
793
		addMenu(menu, FIND_ID);
795
		addMenu(menu, FIND_ID);
794
		
796
		
(-)compare/org/eclipse/compare/internal/merge/DocumentMerger.java (+8 lines)
Lines 33-38 Link Here
33
 * This class should not have any UI dependencies.
33
 * This class should not have any UI dependencies.
34
 */
34
 */
35
public class DocumentMerger {
35
public class DocumentMerger {
36
	
37
	public static final char ANCESTOR_CONTRIBUTOR = 'A';
38
	public static final char RIGHT_CONTRIBUTOR = 'R';
39
	public static final char LEFT_CONTRIBUTOR = 'L';
36
40
37
	private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$
41
	private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$
38
	
42
	
Lines 1344-1347 Link Here
1344
		return null;
1348
		return null;
1345
	}
1349
	}
1346
	
1350
	
1351
	public ArrayList getAllDiffs(){
1352
		return this.fAllDiffs;
1353
	}
1347
}
1354
}
1355
(-)compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java (+8 lines)
Lines 43-48 Link Here
43
import org.eclipse.compare.internal.CompareMessages;
43
import org.eclipse.compare.internal.CompareMessages;
44
import org.eclipse.compare.internal.ComparePreferencePage;
44
import org.eclipse.compare.internal.ComparePreferencePage;
45
import org.eclipse.compare.internal.CompareUIPlugin;
45
import org.eclipse.compare.internal.CompareUIPlugin;
46
import org.eclipse.compare.internal.CreatePatchAction;
46
import org.eclipse.compare.internal.DocumentManager;
47
import org.eclipse.compare.internal.DocumentManager;
47
import org.eclipse.compare.internal.ICompareContextIds;
48
import org.eclipse.compare.internal.ICompareContextIds;
48
import org.eclipse.compare.internal.ICompareUIConstants;
49
import org.eclipse.compare.internal.ICompareUIConstants;
Lines 2301-2306 Link Here
2301
		contributeFindAction(part);
2302
		contributeFindAction(part);
2302
		
2303
		
2303
		contributeGotoLineAction(part);
2304
		contributeGotoLineAction(part);
2305
		
2306
		contributeCreatePatchAction(part);
2304
2307
2305
		configureTextViewer(part);
2308
		configureTextViewer(part);
2306
		
2309
		
Lines 2332-2337 Link Here
2332
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
2335
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
2333
		viewer.addAction(MergeSourceViewer.GOTO_LINE_ID, action);
2336
		viewer.addAction(MergeSourceViewer.GOTO_LINE_ID, action);
2334
	}
2337
	}
2338
	private void contributeCreatePatchAction(MergeSourceViewer viewer) {
2339
		IAction action = new CreatePatchAction(viewer, getCompareConfiguration().getContainer().getWorkbenchPart());
2340
		action.setActionDefinitionId(MergeSourceViewer.CREATE_PATCH_ID);
2341
		viewer.addAction(MergeSourceViewer.CREATE_PATCH_ID, action);
2342
	}
2335
2343
2336
	private void connectGlobalActions(final MergeSourceViewer part) {
2344
	private void connectGlobalActions(final MergeSourceViewer part) {
2337
		if (fHandlerService != null) {
2345
		if (fHandlerService != null) {
(-)compare/org/eclipse/compare/internal/GenerateLocalDiffFileWizard.java (+1444 lines)
Added Link Here
1
package org.eclipse.compare.internal;
2
3
/*******************************************************************************
4
 * Copyright (c) 2000, 2008 IBM Corporation and others.
5
 * All rights reserved. This program and the accompanying materials
6
 * are made available under the terms of the Eclipse Public License v1.0
7
 * which accompanies this distribution, and is available at
8
 * http://www.eclipse.org/legal/epl-v10.html
9
 *
10
 * Contributors:
11
 *     IBM Corporation - initial API and implementation
12
 *     Benjamin Muskalla (b.muskalla@gmx.net) - Bug 149672 [Patch] Create Patch wizard should remember previous settings
13
 *******************************************************************************/
14
15
import java.io.File;
16
import java.util.ArrayList;
17
import java.util.Iterator;
18
import java.util.List;
19
import org.eclipse.core.resources.IContainer;
20
import org.eclipse.core.resources.IFile;
21
import org.eclipse.core.resources.IProject;
22
import org.eclipse.core.resources.IResource;
23
import org.eclipse.core.resources.IWorkspace;
24
import org.eclipse.core.resources.IWorkspaceRoot;
25
import org.eclipse.core.resources.ResourcesPlugin;
26
import org.eclipse.core.runtime.IPath;
27
import org.eclipse.core.runtime.IStatus;
28
import org.eclipse.core.runtime.Path;
29
import org.eclipse.jface.dialogs.Dialog;
30
import org.eclipse.jface.dialogs.IDialogConstants;
31
import org.eclipse.jface.dialogs.IDialogSettings;
32
import org.eclipse.jface.dialogs.MessageDialog;
33
import org.eclipse.jface.dialogs.TitleAreaDialog;
34
import org.eclipse.jface.resource.ImageDescriptor;
35
import org.eclipse.jface.viewers.DoubleClickEvent;
36
import org.eclipse.jface.viewers.IDoubleClickListener;
37
import org.eclipse.jface.viewers.ISelection;
38
import org.eclipse.jface.viewers.ISelectionChangedListener;
39
import org.eclipse.jface.viewers.IStructuredSelection;
40
import org.eclipse.jface.viewers.SelectionChangedEvent;
41
import org.eclipse.jface.viewers.StructuredSelection;
42
import org.eclipse.jface.viewers.TreeViewer;
43
import org.eclipse.jface.wizard.Wizard;
44
import org.eclipse.jface.wizard.WizardDialog;
45
import org.eclipse.jface.wizard.WizardPage;
46
import org.eclipse.swt.SWT;
47
import org.eclipse.swt.events.ModifyEvent;
48
import org.eclipse.swt.events.ModifyListener;
49
import org.eclipse.swt.events.SelectionAdapter;
50
import org.eclipse.swt.events.SelectionEvent;
51
import org.eclipse.swt.graphics.Image;
52
import org.eclipse.swt.graphics.Point;
53
import org.eclipse.swt.layout.GridData;
54
import org.eclipse.swt.layout.GridLayout;
55
import org.eclipse.swt.widgets.Button;
56
import org.eclipse.swt.widgets.Combo;
57
import org.eclipse.swt.widgets.Composite;
58
import org.eclipse.swt.widgets.Control;
59
import org.eclipse.swt.widgets.Event;
60
import org.eclipse.swt.widgets.FileDialog;
61
import org.eclipse.swt.widgets.Group;
62
import org.eclipse.swt.widgets.Label;
63
import org.eclipse.swt.widgets.Listener;
64
import org.eclipse.swt.widgets.Shell;
65
import org.eclipse.swt.widgets.Text;
66
import org.eclipse.ui.IWorkbenchPart;
67
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
68
import org.eclipse.ui.model.WorkbenchLabelProvider;
69
import org.eclipse.ui.views.navigator.ResourceComparator;
70
71
/**
72
 * A wizard for creating a patch file for local files.
73
 */
74
public class GenerateLocalDiffFileWizard extends Wizard {
75
		
76
	//The initial size of this wizard.
77
    private final static int INITIAL_WIDTH = 300;
78
    private final static int INITIAL_HEIGHT = 350;
79
    private IResource fLeft;
80
    private IResource fRight;
81
   
82
	public static void run(IWorkbenchPart part, final IResource leftResource, final IResource rightResource, boolean unifiedSelectionEnabled) {
83
		final String title = CompareMessages.GenerateLocalDiff_title; 
84
		final GenerateLocalDiffFileWizard wizard = new GenerateLocalDiffFileWizard(part,leftResource, rightResource, unifiedSelectionEnabled);
85
		wizard.setWindowTitle(title);
86
		WizardDialog dialog = new WizardDialog(part.getSite().getShell(), wizard);
87
		dialog.setMinimumPageSize(INITIAL_WIDTH, INITIAL_HEIGHT);
88
		dialog.open();
89
	}
90
	
91
	public static void run(IWorkbenchPart part, final IResource leftResource, final IResource rightResource) {
92
		GenerateLocalDiffFileWizard.run(part,leftResource, rightResource, true);
93
	}
94
	
95
	
96
	/**
97
	 * Page to select a source and goal file.
98
	 */	
99
	public class SourceChoosePage extends WizardPage {	
100
			public final static int FIRST_FILE= 0;
101
			public final static int SECOND_FILE= 1;
102
			private Combo lCombo;
103
			private Combo rCombo;
104
			private IResource firstFile;
105
			private IResource secondFile;
106
			
107
			
108
			protected SourceChoosePage(String pageName) {
109
				super(pageName);
110
				firstFile = fLeft;
111
				secondFile = fRight;
112
			}
113
			
114
			protected SourceChoosePage(String pageName, IResource defaultLeftResource) {
115
				super(pageName);
116
				firstFile = defaultLeftResource;
117
				secondFile = (fRight!=firstFile?fRight:fLeft);
118
			}
119
			
120
			private void addComboBox(Combo box){
121
				box.add(firstFile.getFullPath().toString(), FIRST_FILE);
122
				box.add(secondFile.getFullPath().toString(), SECOND_FILE);
123
			}
124
	
125
			public void createControl(Composite parent) {
126
				// create the composite to hold the widgets
127
	
128
				Composite composite = new Composite(parent, SWT.NULL);
129
				GridLayout gridLayout = new GridLayout();
130
				gridLayout.numColumns= 2;
131
				gridLayout.marginHeight= 10;
132
				gridLayout.marginWidth= 10;
133
				composite.setLayout(gridLayout);
134
				composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
135
				
136
				new Label(composite, SWT.CENTER).setText(CompareMessages.GenerateLocalDiff_sourceChoose_left);
137
				lCombo = new Combo(composite,SWT.BORDER|SWT.READ_ONLY);
138
				addComboBox(lCombo);
139
				lCombo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL|GridData.GRAB_HORIZONTAL|GridData.BEGINNING));
140
				
141
				GridData rgData = new GridData();
142
				rgData.horizontalAlignment=GridData.BEGINNING;
143
				
144
				Label l = new Label(composite,SWT.NONE);
145
				l.setText(CompareMessages.GenerateLocalDiff_sourceChoose_right);
146
				l.setLayoutData(rgData);
147
				rCombo = new Combo(composite, SWT.BORDER|SWT.READ_ONLY);
148
				addComboBox(rCombo);
149
				rCombo.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL|GridData.HORIZONTAL_ALIGN_FILL|GridData.BEGINNING));
150
				lCombo.addSelectionListener(new SelectionAdapter(){
151
					public void widgetSelected(SelectionEvent e){
152
						rCombo.select((lCombo.getSelectionIndex()+1)%2);
153
					}
154
				});
155
				rCombo.addSelectionListener(new SelectionAdapter(){
156
					public void widgetSelected(SelectionEvent e){
157
						lCombo.select((rCombo.getSelectionIndex()+1)%2);
158
						}
159
				});
160
				lCombo.select(FIRST_FILE);//default option
161
				rCombo.select(SECOND_FILE);
162
				
163
				setControl(composite);
164
	
165
			}
166
			public boolean canFlipToNextPage() {
167
				if(firstFile==null || secondFile==null)
168
					return false;
169
				return true;
170
				
171
			}
172
			
173
			public IResource getLeftResource(){
174
				return lCombo.getSelectionIndex()==FIRST_FILE?firstFile:secondFile;
175
			}
176
			
177
			public IResource getRightResource(){	
178
				return rCombo.getSelectionIndex()==FIRST_FILE?firstFile:secondFile;	
179
			}
180
	
181
	}
182
183
	
184
	
185
    /**
186
     * Page to select a patch file. Overriding validatePage was necessary to allow
187
     * entering a file name that already exists.
188
     */
189
    public class LocationPage extends WizardPage {
190
        
191
        /**
192
         * The possible locations to save a patch.
193
         */
194
        public final static int CLIPBOARD = 1;
195
        public final static int FILESYSTEM = 2;
196
        public final static int WORKSPACE = 3;
197
        
198
        /**
199
         * GUI controls for clipboard (cp), filesystem (fs) and workspace (ws).
200
         */
201
        private Button cpRadio;
202
        
203
        private Button fsRadio;
204
        protected Text fsPathText;
205
        private Button fsBrowseButton;
206
        private boolean fsBrowsed = false;
207
        
208
        private Button wsRadio;
209
    	protected Text wsPathText;
210
        private Button wsBrowseButton;
211
        private boolean wsBrowsed = false;
212
        
213
        /**
214
         * State information of this page, updated by the listeners.
215
         */
216
        protected boolean canValidate;
217
        protected boolean pageValid;
218
        protected IContainer wsSelectedContainer;
219
        protected IPath[] foldersToCreate;
220
        protected int selectedLocation;
221
        
222
        /**
223
         * The default values store used to initialize the selections.
224
         */
225
        private final DefaultValuesStore store;
226
	
227
        
228
    	class LocationPageContentProvider extends BaseWorkbenchContentProvider {
229
    		//Never show closed projects
230
    		boolean showClosedProjects=false;
231
    		
232
    		public Object[] getChildren(Object element) {
233
    			if (element instanceof IWorkspace) {
234
    	            // check if closed projects should be shown
235
    	            IProject[] allProjects = ((IWorkspace) element).getRoot().getProjects();
236
    	            if (showClosedProjects)
237
    	                return allProjects;
238
239
    	            ArrayList accessibleProjects = new ArrayList();
240
    	            for (int i = 0; i < allProjects.length; i++) {
241
    	                if (allProjects[i].isOpen()) {
242
    	                    accessibleProjects.add(allProjects[i]);
243
    	                }
244
    	            }
245
    	            return accessibleProjects.toArray();
246
    	        } 
247
    			
248
    			return super.getChildren(element);
249
    		}
250
    	}
251
    	
252
    	class WorkspaceDialog extends TitleAreaDialog {
253
254
    		protected TreeViewer wsTreeViewer;
255
    	    protected Text wsFilenameText;
256
    	    protected Image dlgTitleImage;
257
258
    	    private boolean modified = false;
259
260
			public WorkspaceDialog(Shell shell) {
261
				super(shell);
262
			}
263
			
264
			protected Control createContents(Composite parent) {
265
		        Control control = super.createContents(parent);
266
				setTitle(CompareMessages.WorkspacePatchDialogTitle);
267
				setMessage(CompareMessages.WorkspacePatchDialogDescription);
268
			    //create title image
269
270
				dlgTitleImage = CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF).createImage();
271
				setTitleImage(dlgTitleImage);
272
				
273
		        return control;
274
			}
275
			
276
			protected Control createDialogArea(Composite parent){
277
				Composite parentComposite = (Composite) super.createDialogArea(parent);
278
				
279
				 // create a composite with standard margins and spacing
280
		        Composite composite = new Composite(parentComposite, SWT.NONE);
281
		        GridLayout layout = new GridLayout();
282
		        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
283
		        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
284
		        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
285
		        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
286
		        composite.setLayout(layout);
287
		        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
288
		        composite.setFont(parentComposite.getFont());
289
				
290
//				getShell().setText(CompareMessages.GenerateDiffFileWizard_9); 
291
		
292
                wsTreeViewer = new TreeViewer(composite, SWT.BORDER);
293
                final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
294
                gd.widthHint= 550;
295
                gd.heightHint= 250;
296
                wsTreeViewer.getTree().setLayoutData(gd);
297
               
298
                wsTreeViewer.setContentProvider(new LocationPageContentProvider());
299
                wsTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
300
                wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
301
                wsTreeViewer.setInput(ResourcesPlugin.getWorkspace());
302
                
303
                //Open to whatever is selected in the workspace field
304
                IPath existingWorkspacePath = new Path(wsPathText.getText());
305
                if (existingWorkspacePath != null){
306
                	//Ensure that this workspace path is valid
307
                	IResource selectedResource = ResourcesPlugin.getWorkspace().getRoot().findMember(existingWorkspacePath);
308
                	if (selectedResource != null) {
309
                		wsTreeViewer.expandToLevel(selectedResource, 0);
310
                		wsTreeViewer.setSelection(new StructuredSelection(selectedResource));
311
            		}
312
                }
313
                
314
                final Composite group = new Composite(composite, SWT.NONE);
315
                layout = new GridLayout(2, false);
316
                layout.marginWidth = 0;
317
                group.setLayout(layout);
318
                group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
319
                
320
                final Label label = new Label(group, SWT.NONE);
321
                label.setLayoutData(new GridData());
322
                label.setText(CompareMessages.Fi_le_name__9); 
323
                
324
                wsFilenameText = new Text(group,SWT.BORDER);
325
                wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
326
				
327
                setupListeners();
328
				
329
				return parent;
330
			}
331
332
			protected Button createButton(Composite parent, int id,
333
					String label, boolean defaultButton) {
334
				Button button = super.createButton(parent, id, label,
335
						defaultButton);
336
				if (id == IDialogConstants.OK_ID) {
337
					button.setEnabled(false);
338
				}
339
				return button;
340
			}
341
342
			private void validateDialog() {
343
				String fileName = wsFilenameText.getText();
344
345
				if (fileName.equals("")) { //$NON-NLS-1$
346
					if (modified) {
347
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_2);
348
						getButton(IDialogConstants.OK_ID).setEnabled(false);
349
						return;
350
					} else {
351
						setErrorMessage(null);
352
						getButton(IDialogConstants.OK_ID).setEnabled(false);
353
						return;
354
					}
355
				}
356
357
				// make sure that the filename is valid
358
				if (!(ResourcesPlugin.getWorkspace().validateName(fileName,
359
						IResource.FILE)).isOK() && modified) {
360
//					setErrorMessage(CompareMessages.GenerateDiffFileWizard_5);
361
					getButton(IDialogConstants.OK_ID).setEnabled(false);
362
					return;
363
				}
364
365
				// Make sure that a container has been selected
366
				if (getSelectedContainer() == null) {
367
//					setErrorMessage(CompareMessages.GenerateDiffFileWizard_0);
368
					getButton(IDialogConstants.OK_ID).setEnabled(false);
369
					return;
370
				} else {
371
					IWorkspace workspace = ResourcesPlugin.getWorkspace();
372
					IPath fullPath = wsSelectedContainer.getFullPath().append(
373
							fileName);
374
					if (workspace.getRoot().getFolder(fullPath).exists()) {
375
//						setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists);
376
						getButton(IDialogConstants.OK_ID).setEnabled(false);
377
						return;
378
					}
379
				}
380
381
				setErrorMessage(null);
382
				getButton(IDialogConstants.OK_ID).setEnabled(true);
383
			}
384
385
			protected void okPressed() {
386
				IFile file = wsSelectedContainer.getFile(new Path(
387
						wsFilenameText.getText()));
388
				if (file != null)
389
					wsPathText.setText(file.getFullPath().toString());
390
				
391
				validatePage();
392
				super.okPressed();
393
			}
394
			
395
			private IContainer getSelectedContainer() {
396
				Object obj = ((IStructuredSelection)wsTreeViewer.getSelection()).getFirstElement();
397
                if (obj instanceof IContainer) {
398
                	wsSelectedContainer = (IContainer) obj;
399
                } else if (obj instanceof IFile) {
400
                	wsSelectedContainer = ((IFile) obj).getParent();
401
                }
402
                return wsSelectedContainer;
403
			}
404
405
			protected void cancelPressed() {
406
			  validatePage();
407
			  super.cancelPressed();
408
			}
409
		 
410
		   public boolean close() {
411
		        if (dlgTitleImage != null)
412
		            dlgTitleImage.dispose();
413
		        return super.close();
414
		    }
415
			  
416
			void setupListeners(){
417
				 wsTreeViewer.addSelectionChangedListener(
418
                new ISelectionChangedListener() {
419
                    public void selectionChanged(SelectionChangedEvent event) {
420
                        IStructuredSelection s = (IStructuredSelection)event.getSelection();
421
                        Object obj=s.getFirstElement();
422
                        if (obj instanceof IContainer)
423
                        	wsSelectedContainer = (IContainer) obj;
424
                        else if (obj instanceof IFile){
425
                        	IFile tempFile = (IFile) obj;
426
                        	wsSelectedContainer = tempFile.getParent();
427
                        	wsFilenameText.setText(tempFile.getName());
428
                        }
429
                        validateDialog();
430
                    }
431
                });
432
        
433
		        wsTreeViewer.addDoubleClickListener(
434
		                new IDoubleClickListener() {
435
		                    public void doubleClick(DoubleClickEvent event) {
436
		                        ISelection s= event.getSelection();
437
		                        if (s instanceof IStructuredSelection) {
438
		                            Object item = ((IStructuredSelection)s).getFirstElement();
439
		                            if (wsTreeViewer.getExpandedState(item))
440
		                                wsTreeViewer.collapseToLevel(item, 1);
441
		                            else
442
		                                wsTreeViewer.expandToLevel(item, 1);
443
		                        }
444
		                        validateDialog();
445
		                    }
446
		                });
447
        
448
		        wsFilenameText.addModifyListener(new ModifyListener() {
449
					public void modifyText(ModifyEvent e) {
450
						modified = true;
451
						validateDialog();
452
					}
453
				});
454
			}
455
		}
456
    	
457
        LocationPage(String pageName, String title, ImageDescriptor image, DefaultValuesStore store) {
458
            super(pageName, title, image);
459
            setPageComplete(false);
460
            this.store= store;
461
            this.canValidate=false;
462
        }
463
        
464
        /**
465
         * Allow the user to finish if a valid file has been entered. 
466
         */
467
        protected boolean validatePage() {
468
            
469
        	if (!canValidate)
470
        		return false;
471
        	
472
            switch (selectedLocation) {
473
            case WORKSPACE:
474
                pageValid= validateWorkspaceLocation();
475
                break;
476
            case FILESYSTEM:
477
                pageValid= validateFilesystemLocation();
478
                break;
479
            case CLIPBOARD:
480
                pageValid= true;
481
                break;
482
            }
483
            
484
            /**
485
             * Avoid draw flicker by clearing error message
486
             * if all is valid.
487
             */
488
            if (pageValid) {
489
                setMessage(null);
490
                setErrorMessage(null);
491
            }
492
            setPageComplete(pageValid);
493
            return pageValid;
494
        }
495
        
496
        /**
497
         * The following conditions must hold for the file system location
498
         * to be valid:
499
         * - the path must be valid and non-empty
500
         * - the path must be absolute
501
         * - the specified file must be of type file
502
         * - the parent must exist (new folders can be created via the browse button)
503
         */
504
        private boolean validateFilesystemLocation() {
505
            final String pathString= fsPathText.getText().trim();
506
            if (pathString.length() == 0 || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$
507
            	if (fsBrowsed)
508
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_0);
509
            	else 
510
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_browseFilesystem);
511
                return false;
512
            }
513
            
514
            final File file= new File(pathString);
515
            if (!file.isAbsolute()) {
516
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_0); 
517
                return false;
518
            }
519
            
520
            if (file.isDirectory()) {
521
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_2); 
522
                return false;
523
            }
524
            
525
            if (pathString.endsWith("/") || pathString.endsWith("\\")) {  //$NON-NLS-1$//$NON-NLS-2$
526
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); 
527
                return false;
528
            }
529
            
530
            final File parent= file.getParentFile();
531
            if (!(parent.exists() && parent.isDirectory())) {
532
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); 
533
                return false;
534
            }
535
            return true;
536
        }
537
        
538
        /**
539
         * The following conditions must hold for the file system location to be valid:
540
         * - a parent must be selected in the workspace tree view
541
         * - the resource name must be valid 
542
         */
543
        private boolean validateWorkspaceLocation() {
544
            //make sure that the field actually has a filename in it - making
545
        	//sure that the user has had a chance to browse the workspace first
546
            if (wsPathText.getText().equals("")){ //$NON-NLS-1$
547
            	if (selectedLocation ==WORKSPACE && wsBrowsed)
548
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_5);
549
            	else 
550
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_4);
551
            	return false;
552
            }
553
            
554
            //Make sure that all the segments but the last one (i.e. project + all
555
            //folders) exist - file doesn't have to exist. It may have happened that
556
            //some folder refactoring has been done since this path was last saved.
557
            //
558
            // The path will always be in format project/{folders}*/file - this
559
			// is controlled by the workspace location dialog and by
560
			// validatePath method when path has been entered manually.
561
            
562
            
563
            IPath pathToWorkspaceFile = new Path(wsPathText.getText());
564
            IStatus status = ResourcesPlugin.getWorkspace().validatePath(wsPathText.getText(), IResource.FILE);
565
            if (status.isOK()) {
566
            	//Trim file name from path
567
            	IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
568
            	IResource container =ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
569
            	if (container == null) {
570
            		if (selectedLocation == WORKSPACE)
571
            			setErrorMessage(CompareMessages.GenerateDiffFileWizard_4); 
572
            		return false;
573
				} else if (!container.isAccessible()) {
574
					if (selectedLocation == WORKSPACE)
575
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_ProjectClosed);
576
					return false;
577
				} else {
578
					if (ResourcesPlugin.getWorkspace().getRoot().getFolder(
579
							pathToWorkspaceFile).exists()) {
580
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists);
581
						return false;
582
					}
583
				}
584
            } else {
585
            	setErrorMessage(status.getMessage());
586
            	return false;
587
            }
588
            
589
            return true;
590
        }
591
        
592
        /**
593
         * Answers a full path to a file system file or <code>null</code> if the user
594
         * selected to save the patch in the clipboard.
595
         */
596
        public File getFile() {
597
            if (pageValid && selectedLocation == FILESYSTEM) {
598
                return new File(fsPathText.getText().trim());
599
            } 
600
            if (pageValid && selectedLocation == WORKSPACE) {
601
                final String filename= wsPathText.getText().trim();
602
                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
603
                final IFile file= root.getFile(new Path(filename));
604
                return file.getLocation().toFile();
605
            }
606
            return null;
607
        }
608
        
609
        /**
610
         * Answers the workspace string entered in the dialog or <code>null</code> if the user
611
         * selected to save the patch in the clipboard or file system.
612
         */
613
        public String getWorkspaceLocation() {
614
           
615
            if (pageValid && selectedLocation == WORKSPACE) {
616
                final String filename= wsPathText.getText().trim();
617
                return filename;
618
            }
619
            return null;
620
        }
621
        
622
        /**
623
         * Allow the user to chose to save the patch to the workspace or outside
624
         * of the workspace.
625
         */
626
        public void createControl(Composite parent) {
627
            
628
            final Composite composite= new Composite(parent, SWT.NULL);
629
            composite.setLayout(new GridLayout());
630
            setControl(composite);
631
            initializeDialogUnits(composite);
632
                        
633
            //Create a location group
634
            setupLocationControls(composite);
635
            
636
            initializeDefaultValues();
637
            
638
            canValidate=true;
639
            validatePage();
640
641
			createSelectionButtons(composite);
642
           
643
            Dialog.applyDialogFont(parent);
644
     
645
            /**
646
             * Ensure the page is in a valid state. 
647
             */
648
            /*if (!validatePage()) {
649
                store.storeRadioSelection(CLIPBOARD);
650
                initializeDefaultValues();
651
                validatePage();
652
            }
653
            pageValid= true;*/
654
            validatePage();
655
            
656
            updateEnablements();
657
            setupListeners();
658
        }
659
        
660
        
661
        private void createSelectionButtons(Composite composite) {
662
        	final Composite buttonGroup = new Composite(composite,SWT.NONE);
663
            GridLayout layout = new GridLayout();
664
            layout.numColumns = 2;
665
            layout.marginWidth = 0;
666
            layout.marginHeight = 0;
667
            layout.horizontalSpacing = 0;
668
            layout.verticalSpacing = 0;
669
            buttonGroup.setLayout(layout);
670
            GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
671
                    | GridData.VERTICAL_ALIGN_CENTER);
672
            buttonGroup.setLayoutData(data);
673
            
674
		}
675
676
        
677
        /**
678
         * Setup the controls for the location.
679
         */
680
        private void setupLocationControls(final Composite parent) {
681
			final Composite composite = new Composite(parent, SWT.NULL);
682
			GridLayout gridLayout = new GridLayout();
683
			gridLayout.numColumns = 3;
684
			composite.setLayout(gridLayout);
685
			composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
686
687
			// clipboard
688
			GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
689
			gd.horizontalSpan = 3;
690
			cpRadio = new Button(composite, SWT.RADIO);
691
			cpRadio.setText(CompareMessages.Save_To_Clipboard_2);
692
			cpRadio.setLayoutData(gd);
693
694
			// filesystem
695
			fsRadio = new Button(composite, SWT.RADIO);
696
			fsRadio.setText(CompareMessages.Save_In_File_System_3);
697
698
			fsPathText = new Text(composite, SWT.BORDER);
699
			gd = new GridData(GridData.FILL_HORIZONTAL);
700
			fsPathText.setLayoutData(gd);
701
702
			fsBrowseButton = new Button(composite, SWT.PUSH);
703
			fsBrowseButton.setText(CompareMessages.Browse____4);
704
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
705
			int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
706
			Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT,
707
					SWT.DEFAULT, true);
708
			data.widthHint = Math.max(widthHint, minSize.x);
709
			fsBrowseButton.setLayoutData(data);
710
711
			// workspace
712
			wsRadio = new Button(composite, SWT.RADIO);
713
			wsRadio.setText(CompareMessages.Save_In_Workspace_7);
714
715
			wsPathText = new Text(composite, SWT.BORDER);
716
			gd = new GridData(GridData.FILL_HORIZONTAL);
717
			wsPathText.setLayoutData(gd);
718
719
			wsBrowseButton = new Button(composite, SWT.PUSH);
720
			wsBrowseButton.setText(CompareMessages.Browse____4);
721
			data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
722
			widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
723
			minSize = fsBrowseButton
724
					.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
725
			data.widthHint = Math.max(widthHint, minSize.x);
726
			wsBrowseButton.setLayoutData(data);
727
			
728
			// change the cpRadio layout to be of the same height as other rows' layout
729
			((GridData)cpRadio.getLayoutData()).heightHint = minSize.y;
730
		}
731
        
732
        /**
733
         * Initialize the controls with the saved default values which are
734
         * obtained from the DefaultValuesStore.
735
         */
736
        private void initializeDefaultValues() {
737
738
            selectedLocation= store.getLocationSelection();
739
            
740
            updateRadioButtons();
741
            
742
            /**
743
             * Text fields.
744
             */
745
            // We need to ensure that we have a valid workspace path - user
746
            //could have altered workspace since last time this was saved
747
            wsPathText.setText(store.getWorkspacePath());
748
            if(!validateWorkspaceLocation()) {
749
            	wsPathText.setText(""); //$NON-NLS-1$
750
            	
751
            	//Don't open wizard with an error - instead change selection
752
            	//to clipboard
753
            	if (selectedLocation == WORKSPACE){
754
            		//clear the error message caused by the workspace not having
755
            		//any workspace path entered
756
            		setErrorMessage(null);
757
            		selectedLocation=CLIPBOARD;
758
            		updateRadioButtons();
759
            	}
760
            }
761
            // Do the same thing for the filesystem field 
762
            fsPathText.setText(store.getFilesystemPath());
763
            if (!validateFilesystemLocation()) {
764
            	fsPathText.setText(""); //$NON-NLS-1$
765
            	if (selectedLocation == FILESYSTEM) {
766
            		setErrorMessage(null);
767
            		selectedLocation = CLIPBOARD;
768
            		updateRadioButtons();
769
            	}
770
            }
771
            
772
        }
773
774
		private void updateRadioButtons() {
775
			/**
776
             * Radio buttons
777
             */
778
            cpRadio.setSelection(selectedLocation == CLIPBOARD);
779
            fsRadio.setSelection(selectedLocation == FILESYSTEM);
780
            wsRadio.setSelection(selectedLocation == WORKSPACE);
781
		}
782
        
783
        /**
784
         * Setup all the listeners for the controls. 
785
         */
786
        private void setupListeners() {
787
788
            cpRadio.addListener(SWT.Selection, new Listener() {
789
                public void handleEvent(Event event) {
790
                    selectedLocation= CLIPBOARD;
791
                    validatePage();
792
                    updateEnablements();
793
                }
794
            });
795
            fsRadio.addListener(SWT.Selection, new Listener() {
796
                public void handleEvent(Event event) {
797
                    selectedLocation= FILESYSTEM;
798
                    validatePage();
799
                    updateEnablements();
800
                }
801
            });
802
            
803
            wsRadio.addListener(SWT.Selection, new Listener() {
804
                public void handleEvent(Event event) {
805
                    selectedLocation= WORKSPACE;
806
                    validatePage();
807
                    updateEnablements();
808
                }
809
            });
810
            
811
    		ModifyListener pathTextModifyListener = new ModifyListener() {
812
				public void modifyText(ModifyEvent e) {
813
					validatePage();
814
				}
815
			};
816
			fsPathText.addModifyListener(pathTextModifyListener);
817
			wsPathText.addModifyListener(pathTextModifyListener);
818
			
819
            fsBrowseButton.addListener(SWT.Selection, new Listener() {
820
                public void handleEvent(Event event) {
821
                    final FileDialog dialog = new FileDialog(getShell(), SWT.PRIMARY_MODAL | SWT.SAVE);
822
                    if (pageValid) {
823
                        final File file= new File(fsPathText.getText());
824
                        dialog.setFilterPath(file.getParent());
825
                    }
826
                    dialog.setText(CompareMessages.Save_Patch_As_5); 
827
                    dialog.setFileName(CompareMessages.patch_txt_6); 
828
                    final String path = dialog.open();
829
                    fsBrowsed = true;
830
                    if (path != null) {
831
                        fsPathText.setText(new Path(path).toOSString());
832
                    }			
833
                    validatePage();
834
                }
835
            });		
836
            
837
           
838
            
839
            wsBrowseButton.addListener(SWT.Selection, new Listener() {
840
                public void handleEvent(Event event) {
841
                	final WorkspaceDialog dialog = new WorkspaceDialog(getShell());
842
                	wsBrowsed = true;
843
                	dialog.open();
844
                	validatePage();
845
                }
846
            });		
847
848
        }
849
        
850
        /**
851
         * Enable and disable controls based on the selected radio button.
852
         */
853
        public void updateEnablements() {
854
            fsBrowseButton.setEnabled(selectedLocation == FILESYSTEM);
855
            fsPathText.setEnabled(selectedLocation == FILESYSTEM);
856
            if (selectedLocation == FILESYSTEM)
857
            	fsBrowsed=false;
858
            wsPathText.setEnabled(selectedLocation == WORKSPACE);
859
            wsBrowseButton.setEnabled(selectedLocation == WORKSPACE);
860
            if (selectedLocation == WORKSPACE)
861
            	wsBrowsed=false;
862
        }
863
        
864
        public int getSelectedLocation() {
865
            return selectedLocation;
866
        }
867
     
868
    }
869
        
870
    /**
871
     * Page to select the options for creating the patch.
872
     */
873
    private class OptionsPage extends WizardPage {
874
       
875
    	/**
876
    	* The possible file format to save a patch.
877
    	*/
878
    	public final static int FORMAT_UNIFIED = 1;
879
    	public final static int FORMAT_CONTEXT = 2;
880
    	public final static int FORMAT_STANDARD = 3;
881
882
    	/**
883
    	The possible root of the patch
884
    	*/
885
    	public final static int ROOT_WORKSPACE = 1;
886
    	public final static int ROOT_PROJECT = 2;
887
    	public final static int ROOT_SELECTION = 3;
888
    	
889
    	private Button unifiedDiffOption;
890
    	private Button unified_workspaceRelativeOption; //multi-patch format
891
    	private Button unified_projectRelativeOption; //full project path
892
    	private Button unified_selectionRelativeOption; //use path of whatever is selected
893
        private Button contextDiffOption;
894
        private Button regularDiffOption;
895
        private final RadioButtonGroup diffTypeRadioGroup = new RadioButtonGroup();
896
        private final RadioButtonGroup unifiedRadioGroup = new RadioButtonGroup();
897
898
        private boolean onlyUnifiedAllowed = true;
899
        protected IPath patchRoot=ResourcesPlugin.getWorkspace().getRoot().getFullPath();
900
        
901
        private final DefaultValuesStore store;
902
        
903
        /**
904
         * Constructor for PatchFileCreationOptionsPage.
905
         */
906
        protected OptionsPage(String pageName, String title, ImageDescriptor titleImage, DefaultValuesStore store) {
907
            super(pageName, title, titleImage);
908
            this.store = store;
909
        }
910
        
911
        /*
912
         * @see IDialogPage#createControl(Composite)
913
         */
914
        public void createControl(Composite parent) {
915
            Composite composite= new Composite(parent, SWT.NULL);
916
            GridLayout layout= new GridLayout();
917
            composite.setLayout(layout);
918
            composite.setLayoutData(new GridData());
919
            setControl(composite);
920
            
921
            // set F1 help
922
                        
923
            Group diffTypeGroup = new Group(composite, SWT.NONE);
924
            layout = new GridLayout();
925
            layout.marginHeight = 0;
926
            diffTypeGroup.setLayout(layout);
927
            GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
928
            diffTypeGroup.setLayoutData(data);
929
            diffTypeGroup.setText(CompareMessages.Diff_output_format_12); 
930
            
931
932
            unifiedDiffOption = new Button(diffTypeGroup, SWT.RADIO);
933
            unifiedDiffOption.setText(CompareMessages.Unified__format_required_by_Compare_With_Patch_feature__13);
934
            
935
            contextDiffOption = new Button(diffTypeGroup, SWT.RADIO);
936
            contextDiffOption.setText(CompareMessages.Context_14); 
937
            regularDiffOption = new Button(diffTypeGroup, SWT.RADIO);
938
            regularDiffOption.setText(CompareMessages.Standard_15); 
939
            
940
            diffTypeRadioGroup.add(FORMAT_UNIFIED, unifiedDiffOption);
941
			diffTypeRadioGroup.add(FORMAT_CONTEXT, contextDiffOption);
942
			diffTypeRadioGroup.add(FORMAT_STANDARD, regularDiffOption);
943
            
944
            //Unified Format Options
945
            Group unifiedGroup = new Group(composite, SWT.None);
946
            layout = new GridLayout();
947
            unifiedGroup.setLayout(layout);
948
            data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
949
            unifiedGroup.setLayoutData(data);
950
            unifiedGroup.setText(CompareMessages.GenerateDiffFileWizard_10);
951
            
952
            unified_workspaceRelativeOption = new Button(unifiedGroup, SWT.RADIO);
953
            unified_workspaceRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_6);
954
            unified_workspaceRelativeOption.setSelection(true);
955
            
956
            unified_projectRelativeOption = new Button(unifiedGroup, SWT.RADIO);
957
            unified_projectRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_7);
958
            
959
            unified_selectionRelativeOption = new Button(unifiedGroup, SWT.RADIO);
960
            unified_selectionRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_8);
961
            
962
            unifiedRadioGroup.add(ROOT_WORKSPACE, unified_workspaceRelativeOption);
963
            unifiedRadioGroup.add(ROOT_PROJECT, unified_projectRelativeOption);
964
            unifiedRadioGroup.add(ROOT_SELECTION, unified_selectionRelativeOption);
965
            
966
            Dialog.applyDialogFont(parent);
967
            
968
            initializeDefaultValues();
969
            
970
            //add listeners
971
            unifiedDiffOption.addSelectionListener(new SelectionAdapter() {
972
				public void widgetSelected(SelectionEvent e) {
973
					setEnableUnifiedGroup(true);
974
					updateEnablements();
975
					diffTypeRadioGroup.setSelection(FORMAT_UNIFIED, false);
976
				}
977
			});
978
            
979
            contextDiffOption.addSelectionListener(new SelectionAdapter() {
980
				public void widgetSelected(SelectionEvent e) {
981
					setEnableUnifiedGroup(false);
982
					updateEnablements();
983
					diffTypeRadioGroup.setSelection(FORMAT_CONTEXT, false);
984
				}
985
			});
986
            
987
            regularDiffOption.addSelectionListener(new SelectionAdapter() {
988
				public void widgetSelected(SelectionEvent e) {
989
					setEnableUnifiedGroup(false);
990
					updateEnablements();
991
					diffTypeRadioGroup.setSelection(FORMAT_STANDARD, false);
992
				}
993
			});
994
            
995
            unified_workspaceRelativeOption
996
					.addSelectionListener(new SelectionAdapter() {
997
						public void widgetSelected(SelectionEvent e) {
998
							unifiedRadioGroup.setSelection(ROOT_WORKSPACE, false);
999
						}
1000
					});
1001
1002
			unified_projectRelativeOption
1003
					.addSelectionListener(new SelectionAdapter() {
1004
						public void widgetSelected(SelectionEvent e) {
1005
							unifiedRadioGroup.setSelection(ROOT_PROJECT, false);
1006
						}
1007
					});
1008
1009
			unified_selectionRelativeOption
1010
					.addSelectionListener(new SelectionAdapter() {
1011
						public void widgetSelected(SelectionEvent e) {
1012
							unifiedRadioGroup.setSelection(ROOT_SELECTION, false);
1013
						}
1014
					});    
1015
            	
1016
//           calculatePatchRoot();
1017
           updateEnablements();
1018
			
1019
			// update selection 
1020
			diffTypeRadioGroup.selectEnabledOnly();
1021
			unifiedRadioGroup.selectEnabledOnly();
1022
        }
1023
        
1024
        public int getFormatSelection() {
1025
			return diffTypeRadioGroup.getSelected();
1026
		}
1027
1028
		public int getRootSelection() {
1029
			return unifiedRadioGroup.getSelected();
1030
		}
1031
1032
		private void initializeDefaultValues() {
1033
			// Radio buttons for format
1034
			diffTypeRadioGroup.setSelection(store.getFormatSelection(), true);
1035
			
1036
			if (store.getFormatSelection() != FORMAT_UNIFIED) {
1037
				setEnableUnifiedGroup(false);
1038
			}
1039
		}
1040
1041
        
1042
        protected void updateEnablements() {
1043
			if (onlyUnifiedAllowed){
1044
				diffTypeRadioGroup.setEnablement(false, new int[] {
1045
						FORMAT_CONTEXT, FORMAT_STANDARD }, FORMAT_UNIFIED);
1046
				unifiedRadioGroup.setEnablement(false, new int[] {
1047
						ROOT_PROJECT, ROOT_SELECTION }, ROOT_WORKSPACE);
1048
			}
1049
			
1050
			// temporary until we figure out best way to fix synchronize view
1051
			// selection
1052
			if (!unifiedSelectionEnabled)
1053
				unifiedRadioGroup.setEnablement(false, new int[] {ROOT_SELECTION});
1054
		}
1055
1056
        protected void setEnableUnifiedGroup(boolean enabled){
1057
        	unifiedRadioGroup.setEnablement(enabled, new int[] {
1058
					ROOT_WORKSPACE, ROOT_PROJECT, ROOT_SELECTION });
1059
        	
1060
        	//temporary until we figure out best way to fix synchronize view selection
1061
        	if (!unifiedSelectionEnabled)
1062
        		unifiedRadioGroup.setEnablement(false, new int[] {ROOT_SELECTION});
1063
        }
1064
    }
1065
 
1066
    /**
1067
     * Class to retrieve and store the default selected values. 
1068
     */
1069
    private final class DefaultValuesStore {
1070
        
1071
        private static final String PREF_LAST_SELECTION= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateLocalDiffFileWizard.PatchFileSelectionPage.lastselection"; //$NON-NLS-1$
1072
        private static final String PREF_LAST_FS_PATH= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateLocalDiffFileWizard.PatchFileSelectionPage.filesystem.path"; //$NON-NLS-1$
1073
        private static final String PREF_LAST_WS_PATH= "org.eclipse.team.internal.ccvs.ui.wizards.GenerateLocalDiffFileWizard.PatchFileSelectionPage.workspace.path"; //$NON-NLS-1$
1074
        private static final String PREF_LAST_AO_FORMAT = "org.eclipse.team.internal.ccvs.ui.wizards.GenerateLocalDiffFileWizard.OptionsPage.diff.format"; //$NON-NLS-1$
1075
1076
        
1077
        private final IDialogSettings dialogSettings;
1078
        
1079
        public DefaultValuesStore() {
1080
            dialogSettings= CompareUIPlugin.getDefault().getDialogSettings();
1081
        }
1082
        
1083
        public int getLocationSelection() {
1084
            int value= LocationPage.CLIPBOARD;
1085
            try {
1086
                value= dialogSettings.getInt(PREF_LAST_SELECTION);
1087
            } catch (NumberFormatException e) {
1088
//            	e.printStackTrace();
1089
            }
1090
            
1091
            switch (value) {
1092
            case LocationPage.FILESYSTEM:
1093
            case LocationPage.WORKSPACE:
1094
            case LocationPage.CLIPBOARD:
1095
                return value;
1096
            default:
1097
                return LocationPage.CLIPBOARD;
1098
            }
1099
        }
1100
        
1101
        public String getFilesystemPath() {
1102
            final String path= dialogSettings.get(PREF_LAST_FS_PATH);
1103
            return path != null ? path : "";  //$NON-NLS-1$
1104
        }
1105
        
1106
        public String getWorkspacePath() {
1107
            final String path= dialogSettings.get(PREF_LAST_WS_PATH);
1108
            return path != null ? path : ""; //$NON-NLS-1$
1109
        }
1110
        
1111
1112
		public int getFormatSelection() {
1113
			int value = OptionsPage.FORMAT_UNIFIED;
1114
			try {
1115
				value = dialogSettings.getInt(PREF_LAST_AO_FORMAT);
1116
			} catch (NumberFormatException e) {
1117
			}
1118
1119
			switch (value) {
1120
			case OptionsPage.FORMAT_UNIFIED:
1121
			case OptionsPage.FORMAT_CONTEXT:
1122
			case OptionsPage.FORMAT_STANDARD:
1123
				return value;
1124
			default:
1125
				return OptionsPage.FORMAT_UNIFIED;
1126
			}
1127
		}
1128
        	
1129
        public void storeLocationSelection(int defaultSelection) {
1130
            dialogSettings.put(PREF_LAST_SELECTION, defaultSelection);
1131
        }
1132
        
1133
        public void storeFilesystemPath(String path) {
1134
            dialogSettings.put(PREF_LAST_FS_PATH, path);
1135
        }
1136
        
1137
        public void storeWorkspacePath(String path) {
1138
            dialogSettings.put(PREF_LAST_WS_PATH, path);
1139
        }
1140
        
1141
		public void storeOutputFormat(int selection) {
1142
			dialogSettings.put(PREF_LAST_AO_FORMAT, selection);
1143
		}
1144
1145
    }
1146
    
1147
    private SourceChoosePage myFirstPage;
1148
    private LocationPage locationPage;
1149
    private OptionsPage optionsPage;
1150
    
1151
    protected IResource[] resources;
1152
    private final DefaultValuesStore defaultValuesStore;
1153
  
1154
	//temporary until we figure out best way to fix synchronize view selection
1155
	protected boolean unifiedSelectionEnabled;
1156
	
1157
    public GenerateLocalDiffFileWizard(IWorkbenchPart part, final IResource leftResource, final IResource rightResource, boolean unifiedSelectionEnabled) {
1158
        super();
1159
        this.fLeft = leftResource;
1160
        this.fRight = rightResource;
1161
        setWindowTitle(CompareMessages.GenerateLocalDiff_title); 
1162
        defaultValuesStore= new DefaultValuesStore();
1163
        this.unifiedSelectionEnabled=unifiedSelectionEnabled;
1164
    }
1165
    
1166
    public void addPages() {
1167
		String pageTitle = CompareMessages.CreatePatchAction_pageTitle;
1168
		myFirstPage = new SourceChoosePage(pageTitle);
1169
		myFirstPage.setTitle(CompareMessages.GenerateLocalDiffFile_CheckSourceFile_pageTitle);
1170
		myFirstPage.setDescription(CompareMessages.GenerateLocalDiffFile_CheckSourceFile_pageDescription);
1171
		addPage(myFirstPage);
1172
		
1173
        pageTitle = CompareMessages.GenerateLocalDiff_pageTitle; 
1174
        String pageDescription = CompareMessages.GenerateLocalDiff_pageDescription; 
1175
        locationPage = new LocationPage(pageTitle, pageTitle, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF), defaultValuesStore);
1176
        locationPage.setDescription(pageDescription);
1177
        addPage(locationPage);
1178
        
1179
        pageTitle = CompareMessages.Advanced_options_19; 
1180
        pageDescription = CompareMessages.Configure_the_options_used_for_the_local_diff_command_20; 
1181
        optionsPage = new OptionsPage(pageTitle, pageTitle, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF), defaultValuesStore);
1182
        optionsPage.setDescription(pageDescription);
1183
        addPage(optionsPage);		
1184
    }
1185
  
1186
    
1187
    /**
1188
     * Completes processing of the wizard. If this method returns <code>
1189
     * true</code>, the wizard will close; otherwise, it will stay active.
1190
     */
1191
    public boolean performFinish() {
1192
        
1193
        final int location= locationPage.getSelectedLocation();
1194
1195
        final File file= location != LocationPage.CLIPBOARD? locationPage.getFile() : null;
1196
        
1197
        if (!(file == null || validateFile(file))) {
1198
            return false;
1199
        }
1200
        
1201
        
1202
        /**
1203
         * Perform diff operation.
1204
         */
1205
        IResource left = myFirstPage.getLeftResource();
1206
        IResource right = myFirstPage.getRightResource();
1207
        
1208
	    try {
1209
	     if (file != null) {
1210
	    	 DiffGroup diffGroup = new DiffGroup(left, right);
1211
	 		 diffGroup.generateDiff(file.getAbsolutePath(), optionsPage.getFormatSelection());
1212
	     } else {
1213
	    	 DiffGroup diffGroup = new DiffGroup(left, right);
1214
	    	 diffGroup.generateDiffToClipboard(getShell().getDisplay(), optionsPage.getFormatSelection());
1215
	     }
1216
		} catch (Exception e) {
1217
			e.printStackTrace();
1218
		}
1219
        
1220
        /**
1221
         * Refresh workspace if necessary and save default selection.
1222
         */
1223
        switch (location) {
1224
        
1225
        case LocationPage.WORKSPACE:
1226
            final String workspaceResource= locationPage.getWorkspaceLocation();
1227
            if (workspaceResource != null){
1228
                defaultValuesStore.storeLocationSelection(LocationPage.WORKSPACE);
1229
	            defaultValuesStore.storeWorkspacePath(workspaceResource);
1230
            } else {
1231
            	//Problem with workspace location, open with clipboard next time 
1232
            	defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
1233
            }
1234
            break;
1235
            
1236
        case LocationPage.FILESYSTEM:
1237
            defaultValuesStore.storeFilesystemPath(file.getPath());
1238
        	defaultValuesStore.storeLocationSelection(LocationPage.FILESYSTEM);
1239
        	break;
1240
        	
1241
        case LocationPage.CLIPBOARD:
1242
            defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
1243
        	break;
1244
        	
1245
        default:
1246
            return false;
1247
        }
1248
        
1249
1250
		/**
1251
		 * Save default selections of Options Page
1252
		 */
1253
1254
		defaultValuesStore.storeOutputFormat(optionsPage.getFormatSelection());
1255
1256
        return true;
1257
    }
1258
1259
	public boolean validateFile(File file) {
1260
        
1261
        if (file == null)
1262
            return false;
1263
        
1264
        /**
1265
         * Consider file valid if it doesn't exist for now.
1266
         */
1267
        if (!file.exists())
1268
            return true;
1269
        
1270
    	/**
1271
    	 * The file exists.
1272
    	 */
1273
    	if (!file.canWrite()) {
1274
    	    final String title= CompareMessages.GenerateLocalDiff_1; 
1275
    	    final String msg= CompareMessages.GenerateLocalDiff_2; 
1276
    	    final MessageDialog dialog= new MessageDialog(getShell(), title, null, msg, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0);
1277
    	    dialog.open();
1278
    	    return false;
1279
    	}
1280
    	
1281
    	final String title = CompareMessages.GenerateLocalDiff_overwriteTitle; 
1282
    	final String msg = CompareMessages.GenerateLocalDiff_overwriteMsg; 
1283
    	final MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
1284
    	dialog.open();
1285
    	if (dialog.getReturnCode() != 0)            
1286
    	    return false;
1287
    	
1288
    	return true;
1289
    }
1290
1291
	/**
1292
	 * The class maintain proper selection of radio button within the group:
1293
	 * <ul>
1294
	 * <li>Only one button can be selected at the time.</li>
1295
	 * <li>Disabled button can't be selected unless all buttons in the group
1296
	 * are disabled.</li>
1297
	 * </ul>
1298
	 */
1299
	/*private*/ class RadioButtonGroup {
1300
1301
		/**
1302
		 * List of buttons in the group. Both radio groups contain 3 elements.
1303
		 */
1304
		private List buttons = new ArrayList(3);
1305
1306
		/**
1307
		 * Index of the selected button.
1308
		 */
1309
		private int selected = 0;
1310
1311
		/**
1312
		 * Add a button to the group. While adding a new button the method
1313
		 * checks if there is only one button selected in the group.
1314
		 * 
1315
		 * @param buttonCode
1316
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
1317
		 *            an index we need to subtract 1 from it.
1318
		 * @param button
1319
		 *            A button to add.
1320
		 */
1321
		public void add(int buttonCode, Button button) {
1322
			if (button != null && (button.getStyle() & SWT.RADIO) != 0) {
1323
				if (button.getSelection() && !buttons.isEmpty()) {
1324
					deselectAll();
1325
					selected = buttonCode - 1;
1326
				}
1327
				buttons.add(buttonCode - 1, button);
1328
			}
1329
		}
1330
1331
		/**
1332
		 * Returns selected button's code.
1333
		 * 
1334
		 * @return Selected button's code.
1335
		 */
1336
		public int getSelected() {
1337
			return selected + 1;
1338
		}
1339
1340
		/**
1341
		 * Set selection to the given button. When
1342
		 * <code>selectEnabledOnly</code> flag is true the returned value can
1343
		 * differ from the parameter when a button we want to set selection to
1344
		 * is disabled and there are other buttons which are enabled.
1345
		 * 
1346
		 * @param buttonCode
1347
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
1348
		 *            an index we need to subtract 1 from it.
1349
		 * @return Code of the button to which selection was finally set.
1350
		 */
1351
		public int setSelection(int buttonCode, boolean selectEnabledOnly) {
1352
			deselectAll();
1353
1354
			((Button) buttons.get(buttonCode - 1)).setSelection(true);
1355
			selected = buttonCode - 1;
1356
			if (selectEnabledOnly)
1357
				selected = selectEnabledOnly() - 1;
1358
			return getSelected();
1359
		}
1360
1361
		/**
1362
		 * Make sure that only an enabled radio button is selected.
1363
		 * 
1364
		 * @return A code of the selected button.
1365
		 */
1366
		public int selectEnabledOnly() {
1367
			deselectAll();
1368
1369
			Button selectedButton = (Button) buttons.get(selected);
1370
			if (!selectedButton.isEnabled()) {
1371
				// if the button is disabled, set selection to an enabled one
1372
				for (Iterator iterator = buttons.iterator(); iterator.hasNext();) {
1373
					Button b = (Button) iterator.next();
1374
					if (b.isEnabled()) {
1375
						b.setSelection(true);
1376
						selected = buttons.indexOf(b);
1377
						return selected + 1;
1378
					}
1379
				}
1380
				// if none found, reset the initial selection
1381
				selectedButton.setSelection(true);
1382
			} else {
1383
				// because selection has been cleared, set it again
1384
				selectedButton.setSelection(true);
1385
			}
1386
			// return selected button's code so the value can be stored
1387
			return getSelected();
1388
		}
1389
1390
		/**
1391
		 * Enable or disable given buttons.
1392
		 * 
1393
		 * @param enabled
1394
		 *            Indicates whether to enable or disable the buttons.
1395
		 * @param buttonsToChange
1396
		 *            Buttons to enable/disable.
1397
		 * @param defaultSelection
1398
		 *            The button to select if the currently selected button
1399
		 *            becomes disabled.
1400
		 */
1401
		public void setEnablement(boolean enabled, int[] buttonsToChange,
1402
				int defaultSelection) {
1403
1404
			// enable (or disable) given buttons
1405
			for (int i = 0; i < buttonsToChange.length; i++) {
1406
				((Button) this.buttons.get(buttonsToChange[i] - 1))
1407
						.setEnabled(enabled);
1408
			}
1409
			// check whether the selected button is enabled
1410
			if (!((Button) this.buttons.get(selected)).isEnabled()) {
1411
				if (defaultSelection != -1)
1412
					// set the default selection and check if it's enabled
1413
					setSelection(defaultSelection, true);
1414
				else
1415
					// no default selection is given, select any enabled button
1416
					selectEnabledOnly();
1417
			}
1418
		}
1419
1420
		/**
1421
		 * Enable or disable given buttons with no default selection. The selection
1422
		 * will be set to an enabled button using the <code>selectEnabledOnly</code> method.
1423
		 * 
1424
		 * @param enabled Indicates whether to enable or disable the buttons.
1425
		 * @param buttonsToChange Buttons to enable/disable.
1426
		 */
1427
		public void setEnablement(boolean enabled, int[] buttonsToChange) {
1428
			// -1 means that no default selection is given
1429
			setEnablement(enabled, buttonsToChange, -1);
1430
		}
1431
1432
		/**
1433
		 * Deselect all buttons in the group.
1434
		 */
1435
		private void deselectAll() {
1436
			// clear all selections
1437
			for (Iterator iterator = buttons.iterator(); iterator.hasNext();)
1438
				((Button) iterator.next()).setSelection(false);
1439
		}
1440
		
1441
		
1442
	}
1443
	
1444
}
(-)compare/org/eclipse/compare/internal/DiffGroup.java (+112 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Krzysztof Poglodzinski (intuicje@gmail.com) - initial API and implementation
10
 *     Mariusz Tanski (mariusztanski@gmail.com) - initial API and implementation
11
 *     Kacper Zdanowicz (kacper.zdanowicz@gmail.com) - initial API and implementation
12
 *******************************************************************************/
13
package org.eclipse.compare.internal;
14
15
import java.io.ByteArrayOutputStream;
16
import java.io.FileNotFoundException;
17
import java.io.FileOutputStream;
18
import java.io.IOException;
19
import java.io.PrintStream;
20
import java.util.ArrayList;
21
22
23
import org.eclipse.core.resources.IFile;
24
import org.eclipse.core.resources.IResource;
25
import org.eclipse.swt.dnd.Clipboard;
26
import org.eclipse.swt.dnd.TextTransfer;
27
import org.eclipse.swt.dnd.Transfer;
28
import org.eclipse.swt.widgets.Display;
29
30
public class DiffGroup {
31
32
	public static final char RIGHT_CONTRIBUTOR = 'R';
33
	public static final char LEFT_CONTRIBUTOR = 'L';
34
	
35
	public final static int FORMAT_UNIFIED = 1;
36
	public final static int FORMAT_CONTEXT = 2;
37
	public final static int FORMAT_STANDARD = 3;
38
	
39
	private ArrayList diffFiles;
40
	private UnifiedDiffFormatter diffFormatter;
41
	
42
	
43
	public DiffGroup(IResource leftRes, IResource rightRes) {
44
		
45
		
46
		diffFiles = new ArrayList();
47
		
48
		if (leftRes.getType()==IResource.FILE && rightRes.getType()==IResource.FILE){
49
			IFile file1 = (IFile)leftRes;
50
			IFile file2 = (IFile)rightRes;
51
			
52
			DiffFile diffFile = new DiffFile(file1, file2);
53
			diffFiles.add(diffFile);
54
		}
55
		
56
	}
57
	
58
	public void generateDiffToClipboard(Display dis, int format) {
59
		if (format == FORMAT_UNIFIED){
60
					
61
			diffFormatter = new UnifiedDiffFormatter();
62
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
63
			PrintStream ps = new PrintStream(bos);
64
			
65
			diffFormatter.createDiff(diffFiles, ps);
66
			ps.close();
67
			
68
    		TextTransfer plainTextTransfer = TextTransfer.getInstance();
69
    		Clipboard clipboard = new Clipboard(dis);		
70
    		clipboard.setContents(
71
    			new String[]{bos.toString()}, 
72
    			new Transfer[]{plainTextTransfer});	
73
    		clipboard.dispose();
74
    		try {
75
				bos.close();
76
			} catch (IOException e) {
77
				e.printStackTrace();
78
			}
79
80
		}
81
	}
82
	
83
	
84
	
85
	public void generateDiff(String path, int format) {
86
		if (format == FORMAT_UNIFIED){
87
			
88
			diffFormatter = new UnifiedDiffFormatter();
89
			FileOutputStream fos;
90
			
91
			try {
92
				fos = new FileOutputStream(path);
93
				PrintStream ps = new PrintStream(fos);
94
				diffFormatter.createDiff(diffFiles, ps);
95
				ps.close();
96
				fos.close();
97
				
98
			} catch (FileNotFoundException e) {
99
				e.printStackTrace();
100
			} catch (IOException e) {
101
				e.printStackTrace();
102
			}
103
		} else {
104
			throw new UnsupportedOperationException();
105
		}
106
		 
107
	}
108
	
109
	
110
	
111
	
112
}
(-)compare/org/eclipse/compare/internal/DiffFile.java (+233 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Krzysztof Poglodzinski (intuicje@gmail.com) - initial API and implementation
10
 *     Mariusz Tanski (mariusztanski@gmail.com) - initial API and implementation
11
 *     Kacper Zdanowicz (kacper.zdanowicz@gmail.com) - initial API and implementation
12
 *******************************************************************************/
13
package org.eclipse.compare.internal;
14
15
import java.io.InputStream;
16
import java.util.ArrayList;
17
import java.util.Arrays;
18
import java.util.Date;
19
import org.eclipse.compare.CompareConfiguration;
20
import org.eclipse.compare.contentmergeviewer.ITokenComparator;
21
import org.eclipse.compare.contentmergeviewer.TokenComparator;
22
import org.eclipse.compare.internal.merge.DocumentMerger;
23
import org.eclipse.compare.internal.merge.DocumentMerger.Diff;
24
import org.eclipse.compare.internal.merge.DocumentMerger.IDocumentMergerInput;
25
import org.eclipse.compare.rangedifferencer.RangeDifference;
26
import org.eclipse.core.resources.IFile;
27
//import org.eclipse.core.resources.ResourcesPlugin;
28
import org.eclipse.core.runtime.CoreException;
29
import org.eclipse.jface.text.BadLocationException;
30
import org.eclipse.jface.text.Document;
31
import org.eclipse.jface.text.IDocument;
32
import org.eclipse.jface.text.Position;
33
34
public class DiffFile {
35
	
36
	private IFile leftFile;
37
	private IFile rightFile;
38
	private DocumentMerger docMerger; 
39
	private String leftName;
40
	private String rightName;
41
	
42
	private ArrayList allDiffs;
43
	
44
45
	public DiffFile(IFile leftFile, IFile rightFile) {
46
		this.leftFile = leftFile ;
47
		this.rightFile = rightFile;
48
		this.leftName= this.leftFile.getFullPath().toString();
49
		this.rightName= this.rightFile.getFullPath().toString(); 
50
		this.allDiffs = new ArrayList();
51
		IDocument leftDoc = convertFileToDocument(leftFile);
52
		IDocument rightDoc = convertFileToDocument(rightFile);		
53
		docMerger = new DocumentMerger(new LocalDiffMergerInput(leftDoc, rightDoc));
54
		this.doDiff();
55
	}
56
	
57
	public DiffFile(String leftName, String rightName, DocumentMerger docMerger){
58
		this.leftName= leftName;
59
		this.rightName= rightName;
60
		this.docMerger= docMerger;
61
		this.doDiff();	
62
	}
63
	
64
	public int getNumberOfParts()
65
	{
66
		return allDiffs.size();
67
	}
68
	
69
	public String getFilePathString(char side) {
70
		if (side == 'L')
71
			return leftName;
72
		else
73
			return rightName;
74
	}
75
	
76
	//ArrayList of Strings containing lines of part
77
	public ArrayList getPart(int nr, char side) //side = 'L' or 'R'
78
	{
79
		try{
80
		Diff diff = ((Diff)allDiffs.get(nr));
81
		
82
		String s = this.extract(nr, side).replaceAll("\r", "");		//extract and convert "\r\n" to "\n"
83
		ArrayList diffLines = new ArrayList(Arrays.asList(s.split("\n", -1)));
84
		return diffLines;
85
		} catch (IndexOutOfBoundsException e) {
86
			CompareUIPlugin.log(e);
87
		}catch (Exception e){
88
			CompareUIPlugin.log(e);
89
		}
90
		return null;
91
	}
92
	
93
	public Date getDate(char side) {
94
		Date date;
95
		if (side == DiffGroup.LEFT_CONTRIBUTOR)
96
			date = new Date(leftFile.getLocalTimeStamp()); 
97
		else
98
			date = new Date(rightFile.getLocalTimeStamp());
99
		return date;
100
	}
101
	
102
	public boolean isPartDifferent(int nr) {
103
		Diff diff = ((Diff)allDiffs.get(nr));
104
		
105
		if (diff.getKind() == RangeDifference.CHANGE)
106
			return true;
107
		else
108
			return false;
109
	}
110
111
	private String extract(int nr, char side) {
112
		IDocument leftDoc = convertFileToDocument(leftFile);
113
		IDocument rightDoc = convertFileToDocument(rightFile);
114
		try {
115
			Diff diff = ((Diff)allDiffs.get(nr));
116
			switch (side) {
117
			case DiffGroup.LEFT_CONTRIBUTOR:
118
			return leftDoc.get(diff.getPosition(DiffGroup.LEFT_CONTRIBUTOR).offset, 
119
							   diff.getPosition(DiffGroup.LEFT_CONTRIBUTOR).length);
120
			case DiffGroup.RIGHT_CONTRIBUTOR:
121
				return rightDoc.get(diff.getPosition(DiffGroup.RIGHT_CONTRIBUTOR).offset, 
122
								diff.getPosition(DiffGroup.RIGHT_CONTRIBUTOR).length);
123
124
		}
125
		}
126
		catch (IndexOutOfBoundsException e){
127
			CompareUIPlugin.log(e);
128
		}
129
		catch (BadLocationException e) {
130
			CompareUIPlugin.log(e);
131
		}
132
	    return null;
133
	}
134
	
135
	private void doDiff() {
136
		try {
137
			docMerger.doDiff();
138
			allDiffs = docMerger.getAllDiffs();
139
			
140
		} catch (CoreException e) {
141
			e.printStackTrace();
142
		}
143
	}
144
145
	private IDocument convertFileToDocument(IFile file) {
146
		StringBuffer str = new StringBuffer();
147
		int c;
148
		try{
149
			InputStream inputStream = file.getContents();
150
			while ((c = inputStream.read())!=-1){
151
				str.append((char)c);
152
			}
153
			inputStream.close();
154
			return new Document(str.toString());
155
		}catch(Exception ex){
156
			CompareUIPlugin.log(ex);
157
		}
158
	
159
		return null;
160
	}
161
	
162
	
163
164
	class LocalDiffMergerInput implements IDocumentMergerInput {
165
        
166
	private IDocument leftDoc;
167
	private IDocument rightDoc;
168
	
169
	public LocalDiffMergerInput(IDocument leftDoc, IDocument rightDoc) {
170
		this.leftDoc = leftDoc ;
171
		this.rightDoc= rightDoc;
172
	}
173
		
174
	public ITokenComparator createTokenComparator(String line) {
175
            return new TokenComparator(line);
176
    }
177
    public CompareConfiguration getCompareConfiguration() {
178
            return new CompareConfiguration();
179
    }
180
    public IDocument getDocument(char contributor) {
181
            switch (contributor) {
182
            case DocumentMerger.LEFT_CONTRIBUTOR:
183
                    return leftDoc;
184
            case DocumentMerger.RIGHT_CONTRIBUTOR:
185
                    return rightDoc;
186
            case DocumentMerger.ANCESTOR_CONTRIBUTOR: 
187
                    return null;
188
            }
189
            return null;
190
    }
191
    public int getHunkStart() {
192
            return 0;
193
    }
194
    public Position getRegion(char contributor) {
195
            switch (contributor) {
196
            case DocumentMerger.LEFT_CONTRIBUTOR:
197
                    return new Position(0, leftDoc.getLength());
198
            case DocumentMerger.RIGHT_CONTRIBUTOR:
199
                    return new Position(0, rightDoc.getLength());
200
            case DocumentMerger.ANCESTOR_CONTRIBUTOR:
201
                    return new Position(0, 0);
202
            }
203
            return null;
204
    }
205
    public boolean isHunkOnLeft() {
206
//            ITypedElement left = ((ICompareInput)getInput()).getRight();
207
//            return left != null && Utilities.getAdapter(left, IHunk.class) != null;
208
    	return false;
209
    }
210
    public boolean isIgnoreAncestor() {
211
//            return TextMergeViewer.this.isIgnoreAncestor();
212
    	return true;
213
    }
214
    public boolean isPatchHunk() {
215
//            return TextMergeViewer.this.isPatchHunk();
216
    	return false;
217
    }
218
219
    public boolean isShowPseudoConflicts() {
220
//            return fShowPseudoConflicts;
221
    	return false;
222
    }
223
    public boolean isThreeWay() {
224
//            return TextMergeViewer.this.isThreeWay();
225
    	return false;
226
    }
227
    public boolean isPatchHunkOk() {
228
//            return TextMergeViewer.this.isPatchHunkOk();
229
    	return false;
230
    }
231
    
232
}
233
}
(-)compare/org/eclipse/compare/internal/CreatePatchAction.java (+54 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Krzysztof Poglodzinski (intuicje@gmail.com) - initial API and implementation
10
 *     Mariusz Tanski (mariusztanski@gmail.com) - initial API and implementation
11
 *     Kacper Zdanowicz (kacper.zdanowicz@gmail.com) - initial API and implementation
12
 *******************************************************************************/
13
package org.eclipse.compare.internal;
14
15
import org.eclipse.compare.ResourceNode;
16
import org.eclipse.core.resources.IResource;
17
import org.eclipse.jface.action.Action;
18
import org.eclipse.ui.IWorkbenchPart;
19
20
21
public class CreatePatchAction extends Action {
22
23
	private IResource left;
24
	private IResource right;
25
	private IWorkbenchPart workbenchPart;
26
		
27
	public CreatePatchAction(MergeSourceViewer viewer, IWorkbenchPart workbenchPart) {
28
		super(CompareMessages.CreatePatchActionTitle);
29
		if(workbenchPart instanceof CompareEditor) {
30
						
31
			CompareEditor editor = (CompareEditor)workbenchPart;
32
			
33
			ResourceCompareInput input = (ResourceCompareInput)editor.getEditorInput();
34
			if(input.getCompareResult() instanceof ResourceCompareInput.MyDiffNode) {
35
				ResourceCompareInput.MyDiffNode node = (ResourceCompareInput.MyDiffNode)input.getCompareResult();
36
				ResourceNode leftResNode = (ResourceNode)node.getLeft();
37
				ResourceNode rightResNode = (ResourceNode)node.getRight();		
38
				
39
				left = leftResNode.getResource();
40
				right = rightResNode.getResource();
41
			}
42
			
43
		}
44
45
		this.workbenchPart = workbenchPart;
46
	}
47
	
48
	public void run() {
49
		
50
		GenerateLocalDiffFileWizard.run(workbenchPart, left, right);
51
	}
52
53
54
}
(-)compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java (+181 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Krzysztof Poglodzinski (intuicje@gmail.com) - initial API and implementation
10
 *     Mariusz Tanski (mariusztanski@gmail.com) - initial API and implementation
11
 *     Kacper Zdanowicz (kacper.zdanowicz@gmail.com) - initial API and implementation
12
 *******************************************************************************/
13
package org.eclipse.compare.internal;
14
15
import java.io.PrintStream;
16
import java.text.SimpleDateFormat;
17
import java.util.ArrayList;
18
import java.util.Date;
19
20
public class UnifiedDiffFormatter {
21
	public static final String INDEX_MARKER = "Index: ";	//$NON-NLS-1$
22
	public static final String DELIMITER = "===================================================================";	//$NON-NLS-1$
23
	public static final String OLD_FILE_PREFIX = "--- ";	//$NON-NLS-1$
24
	public static final String NEW_FILE_PREFIX = "+++ ";	//$NON-NLS-1$	
25
	public static final String OLD_LINE_PREFIX = "-";	//$NON-NLS-1$
26
	public static final String NEW_LINE_PREFIX = "+";	//$NON-NLS-1$
27
	public static final String CONTEXT_LINE_PREFIX = " ";	//$NON-NLS-1$
28
29
	private class Hunk {
30
		private int oldStart;
31
		private int oldEnd;
32
		private int newStart;
33
		private int newEnd;
34
		ArrayList lines;
35
36
		public Hunk (int oldStart, int newStart) {
37
			if (oldStart < 0)
38
				oldStart = 0;
39
			if (newStart < 0)
40
				newStart = 0;
41
			this.oldStart = oldStart;
42
			this.newStart = newStart;
43
			this.oldEnd = oldStart;
44
			this.newEnd = newStart;
45
			lines = new ArrayList();
46
		}
47
		
48
		public void addPartRangeToOld(ArrayList part, int start, int end, boolean lastPart) {
49
			if (start < 0)
50
				start = 0;
51
			if (lastPart)
52
				end = Math.min(end, part.size());
53
			else
54
				end = Math.min(end, part.size() - 1);				
55
			for (int lineNr = start; lineNr < end; lineNr++) {
56
				lines.add(OLD_LINE_PREFIX + part.get(lineNr));
57
				oldEnd++;
58
			}
59
		}
60
61
		public void addPartRangeToNew(ArrayList part, int start, int end, boolean lastPart) {
62
			if (start < 0)
63
				start = 0;
64
			if (lastPart)
65
				end = Math.min(end, part.size());
66
			else
67
				end = Math.min(end, part.size() - 1);				
68
			for (int lineNr = start; lineNr < end; lineNr++) {
69
				lines.add(NEW_LINE_PREFIX + part.get(lineNr));
70
				newEnd++;
71
			}
72
		}
73
74
		public void addPartRangeToBoth(ArrayList part, int start, int end, boolean lastPart) {
75
			if (start < 0)
76
				start = 0;
77
			if (lastPart)
78
				end = Math.min(end, part.size());
79
			else
80
				end = Math.min(end, part.size() - 1);	
81
			for (int lineNr = start; lineNr <  end; lineNr++) {
82
				lines.add(CONTEXT_LINE_PREFIX + part.get(lineNr));
83
				oldEnd++;
84
				newEnd++;
85
			}
86
		}
87
88
		private void printMarkerTo(PrintStream output) {
89
			output.println("@@ -" + oldStart + "," + oldEnd + " +" + newStart + "," + newEnd + " @@"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
90
		}
91
92
		public void printTo(PrintStream output) {
93
			printMarkerTo(output);
94
			for (int i = 0; i < lines.size(); i++) {
95
				output.println(lines.get(i));
96
			}
97
		}
98
	}
99
	
100
	public void createDiff(ArrayList diffFiles, PrintStream output) {
101
		for (int i=0;i<diffFiles.size();i++){
102
			Object element = diffFiles.get(i);
103
			if (element instanceof DiffFile) {
104
				DiffFile df = (DiffFile)diffFiles.get(i);
105
				//if the first block isn't the only one, or first block is different
106
				if (df.getNumberOfParts() > 1 || df.isPartDifferent(0))	{
107
					output.println(INDEX_MARKER + df.getFilePathString('L'));
108
					output.println(DELIMITER);
109
	
110
					SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy hh:mm:ss");	//$NON-NLS-1$
111
					Date oldDate = df.getDate('L');
112
					Date newDate = df.getDate('R');
113
					output.println(OLD_FILE_PREFIX + df.getFilePathString('L') + '\t' + sdf.format(oldDate) + " -0000");	//$NON-NLS-1$
114
					output.println(NEW_FILE_PREFIX + df.getFilePathString('R') + '\t' + sdf.format(newDate) + " -0000");	//$NON-NLS-1$
115
					
116
					boolean firstHunk = true;
117
	
118
					Hunk currentHunk = null;
119
	
120
					int currentLineNumberOld = 0;
121
					int currentLineNumberNew = 0;
122
	
123
					for (int filePartNumber = 0; filePartNumber < df.getNumberOfParts(); filePartNumber++) {
124
						
125
						ArrayList oldPart = df.getPart(filePartNumber, 'L');
126
						ArrayList newPart = df.getPart(filePartNumber, 'R');
127
					
128
						if (df.isPartDifferent(filePartNumber)) {
129
							//this part has some changes
130
							if (firstHunk) {
131
								//hunk will start with changed block
132
								currentHunk = new Hunk(0, 0);
133
								firstHunk = false;
134
							}
135
							if (filePartNumber == (df.getNumberOfParts() - 1)) {
136
								//if it is the last part
137
								currentHunk.addPartRangeToOld(oldPart, 0, oldPart.size(), true);
138
								currentHunk.addPartRangeToNew(newPart, 0, newPart.size(), true);
139
							}
140
							else {
141
								currentHunk.addPartRangeToOld(oldPart, 0, oldPart.size(), false);
142
								currentHunk.addPartRangeToNew(newPart, 0, newPart.size(), false);
143
							}
144
						}
145
						else {
146
							if (firstHunk) {
147
								//hunk will start with context
148
								currentHunk = new Hunk(oldPart.size()-3, oldPart.size()-3);
149
								firstHunk = false;
150
								currentHunk.addPartRangeToBoth(oldPart, oldPart.size()-3, oldPart.size(), false);
151
							}
152
							else {
153
								if (filePartNumber == (df.getNumberOfParts() - 1)) {
154
									//if it is the last part
155
									currentHunk.addPartRangeToBoth(oldPart, 0, 3, true);
156
								}
157
								else {
158
									if (oldPart.size() < 6) {
159
										//context too short to start new hunk
160
										currentHunk.addPartRangeToBoth(oldPart, 0, oldPart.size(), false);										
161
									}
162
									else {
163
										//context long enough to start new hunk
164
										currentHunk.addPartRangeToBoth(oldPart, 0, 3, false);
165
										currentHunk.printTo(output);
166
										currentHunk = new Hunk(currentLineNumberOld+oldPart.size()-3, currentLineNumberNew+oldPart.size()-3);
167
										currentHunk.addPartRangeToBoth(oldPart, oldPart.size()-3, oldPart.size(), false);										
168
									}
169
								}
170
							}
171
						}
172
						currentLineNumberOld += oldPart.size();
173
						currentLineNumberNew += newPart.size();
174
					}
175
					//print the last hunk
176
					currentHunk.printTo(output);
177
				}
178
			}
179
		}
180
	}
181
}

Return to bug 71374