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

Collapse All | Expand All

(-)compare/org/eclipse/compare/internal/CompareMessages.java (+45 lines)
Lines 130-135 Link Here
130
	public static String CompareWithOtherResourceDialog_workspaceMainButton;
130
	public static String CompareWithOtherResourceDialog_workspaceMainButton;
131
	public static String CompareWithOtherResourceDialog_workspaceRadioButton;
131
	public static String CompareWithOtherResourceDialog_workspaceRadioButton;
132
132
133
	public static String CreatePatchActionTitle;
134
	public static String WorkspacePatchDialogTitle;
135
	public static String WorkspacePatchDialogDescription;
136
	public static String Save_Patch_As_5;
137
	public static String Save_To_Clipboard_2;
138
	public static String Save_In_File_System_3;
139
	public static String Browse____4;
140
	public static String patch_txt_6;
141
	public static String Save_In_Workspace_7;
142
	public static String Fi_le_name__9;
143
	public static String Context_14;
144
	public static String Standard_15;
145
	public static String Diff_output_format_12;
146
	public static String Advanced_options_19;
147
	public static String Configure_options_diff_command;
148
	public static String Unified__format_required_by_Compare_With_Patch_feature__13;
149
	public static String GenerateLocalDiff_title;
150
	public static String GenerateLocalDiff_pageTitle;
151
	public static String GenerateLocalDiff_pageDescription;
152
	public static String GenerateLocalDiff_Specify_the_file_which_contributes_the_changes;
153
	public static String GenerateLocalDiff_overwriteTitle;
154
	public static String GenerateLocalDiff_overwriteMsg;
155
	public static String GenerateLocalDiff_1;
156
	public static String GenerateLocalDiff_2;
157
	public static String GenerateDiffFileWizard_6;
158
	public static String GenerateDiffFileWizard_7;
159
	public static String GenerateDiffFileWizard_8;
160
	public static String GenerateDiffFileWizard_9;
161
	public static String GenerateDiffFileWizard_10;
162
	public static String GenerateDiffFileWizard_0;
163
	public static String GenerateDiffFileWizard_2;
164
	public static String GenerateDiffFileWizard_3;
165
	public static String GenerateDiffFileWizard_4;
166
	public static String GenerateDiffFileWizard_5;
167
	public static String GenerateDiffFileWizard_browseFilesystem;
168
	public static String GenerateDiffFileWizard_FolderExists;
169
	public static String GenerateDiffFileWizard_ProjectClosed;
170
	public static String GenerateDiffFileWizard_13;
171
	public static String GenerateDiffFileWizard_Left;
172
	public static String GenerateDiffFileWizard_Right;
173
	public static String GenerateLocalDiff_3;
174
	public static String GenerateLocalDiff_4;
175
	public static String GenerateLocalDiff_5;
176
	public static String GenerateLocalDiff_6;
177
133
	static {
178
	static {
134
		NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class);
179
		NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class);
135
	}
180
	}
(-)compare/org/eclipse/compare/internal/CompareMessages.properties (+89 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
CreatePatchActionTitle=Save Diffs...
146
WorkspacePatchDialogTitle=Set a Patch Location
147
WorkspacePatchDialogDescription=Select a folder in the workspace and enter a name for the patch.
148
Save_To_Clipboard_2=&Clipboard
149
Save_In_File_System_3=Fil&e
150
Browse____4=Br&owse...
151
Save_Patch_As_5=Save Patch As
152
patch_txt_6=patch.txt
153
Save_In_Workspace_7=&Workspace
154
Fi_le_name__9=Fi&le name:
155
Context_14=&Context
156
Standard_15=&Standard
157
Diff_output_format_12=Diff Output Format
158
Advanced_options_19=Advanced Options
159
Configure_options_diff_command=Configure the options used for the command.
160
Unified__format_required_by_Compare_With_Patch_feature__13=&Unified (format required by the Apply Patch wizard)
161
GenerateLocalDiff_title=Create Patch...
162
GenerateLocalDiff_pageTitle=Save Diffs into a Patch
163
GenerateLocalDiff_pageDescription=Specify the input and the location for the patch.
164
GenerateLocalDiff_Specify_the_file_which_contributes_the_changes=Select which side of the compare editor is contributing the changes. 
165
GenerateLocalDiff_overwriteTitle=Confirm Overwrite
166
GenerateLocalDiff_overwriteMsg=A output file with that name already exists. Overwrite?
167
GenerateLocalDiff_1=Read-only file
168
GenerateLocalDiff_2=The specified file is read-only and cannot be overwritten.
169
GenerateLocalDiff_3=File does not exist.
170
GenerateLocalDiff_4=Specified root patch file does not exist.
171
GenerateLocalDiff_5=File is not readable.
172
GenerateLocalDiff_6=Specified rot patch file is not readable.
173
GenerateDiffFileWizard_6=&Workspace (Multi-project Apply Patch wizard specific)
174
GenerateDiffFileWizard_7=&Project
175
GenerateDiffFileWizard_8=S&election
176
GenerateDiffFileWizard_9=Save Patch
177
GenerateDiffFileWizard_10=Patch Root
178
GenerateDiffFileWizard_0=Please enter a valid location.
179
GenerateDiffFileWizard_2=Please enter a file name.
180
GenerateDiffFileWizard_3=The specified directory does not exist.
181
GenerateDiffFileWizard_4=Please select a location in the workspace by browsing.
182
GenerateDiffFileWizard_5=Please enter a valid filename.
183
GenerateDiffFileWizard_browseFilesystem=Please select a location in the filesystem by browsing.
184
GenerateDiffFileWizard_FolderExists=The specified path points to an existing folder.
185
GenerateDiffFileWizard_ProjectClosed=The specified path points to a closed project.
186
GenerateDiffFileWizard_13=Use only &file path:
187
GenerateDiffFileWizard_Left=&Left:
188
GenerateDiffFileWizard_Right=&Right:
189
CreatePatchActionTitle=Save Diffs...
190
WorkspacePatchDialogTitle=Set a Patch Location
191
WorkspacePatchDialogDescription=Select a folder in the workspace and enter a name for the patch.
192
Save_To_Clipboard_2=&Clipboard
193
Save_In_File_System_3=Fil&e
194
Browse____4=Br&owse...
195
Save_Patch_As_5=Save Patch As
196
patch_txt_6=patch.txt
197
Save_In_Workspace_7=&Workspace
198
Fi_le_name__9=Fi&le name:
199
Context_14=&Context
200
Standard_15=&Standard
201
Diff_output_format_12=Diff Output Format
202
Advanced_options_19=Advanced Options
203
Configure_options_diff_command=Configure the options used for the command.
204
Unified__format_required_by_Compare_With_Patch_feature__13=&Unified (format required by the Apply Patch wizard)
205
GenerateLocalDiff_title=Save Diffs
206
GenerateLocalDiff_pageTitle=Save Diffs into a Patch
207
GenerateLocalDiff_pageDescription=Specify the input and the location for the patch.
208
GenerateLocalDiff_Specify_the_file_which_contributes_the_changes=Select which side of the compare editor is contributing the changes. 
209
GenerateLocalDiff_overwriteTitle=Confirm Overwrite
210
GenerateLocalDiff_overwriteMsg=A output file with that name already exists. Overwrite?
211
GenerateLocalDiff_1=Read-only file
212
GenerateLocalDiff_2=The specified file is read-only and cannot be overwritten.
213
GenerateLocalDiff_3=File does not exist.
214
GenerateLocalDiff_4=Specified root patch file does not exist.
215
GenerateLocalDiff_5=File is not readable.
216
GenerateLocalDiff_6=Specified rot patch file is not readable.
217
GenerateDiffFileWizard_6=&Workspace (Multi-project Apply Patch wizard specific)
218
GenerateDiffFileWizard_7=&Project
219
GenerateDiffFileWizard_8=S&election
220
GenerateDiffFileWizard_9=Save Patch
221
GenerateDiffFileWizard_10=Patch Root
222
GenerateDiffFileWizard_0=Please enter a valid location.
223
GenerateDiffFileWizard_2=Please enter a file name.
224
GenerateDiffFileWizard_3=The specified directory does not exist.
225
GenerateDiffFileWizard_4=Please select a location in the workspace by browsing.
226
GenerateDiffFileWizard_5=Please enter a valid filename.
227
GenerateDiffFileWizard_browseFilesystem=Please select a location in the filesystem by browsing.
228
GenerateDiffFileWizard_FolderExists=The specified path points to an existing folder.
229
GenerateDiffFileWizard_ProjectClosed=The specified path points to a closed project.
230
GenerateDiffFileWizard_13=Use only &file path:
231
GenerateDiffFileWizard_Left=&Left:
232
GenerateDiffFileWizard_Right=&Right:
(-)compare/org/eclipse/compare/internal/ICompareUIConstants.java (+2 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 final String IMG_WIZBAN_DIFF = "wizban/createpatch_wizban.png";   //$NON-NLS-1$
52
}
54
}
(-)compare/org/eclipse/compare/internal/MergeSourceViewer.java (+2 lines)
Lines 106-111 Link Here
106
	public static final String SAVE_ID= "save"; //$NON-NLS-1$
106
	public static final String SAVE_ID= "save"; //$NON-NLS-1$
107
	public static final String FIND_ID= "find"; //$NON-NLS-1$
107
	public static final String FIND_ID= "find"; //$NON-NLS-1$
108
	public static final String GOTO_LINE_ID= "gotoLine"; //$NON-NLS-1$
108
	public static final String GOTO_LINE_ID= "gotoLine"; //$NON-NLS-1$
109
	public static final String CREATE_PATCH_ID= "createPatch"; //$NON-NLS-1$
109
	public static final String CHANGE_ENCODING_ID= "changeEncoding"; //$NON-NLS-1$
110
	public static final String CHANGE_ENCODING_ID= "changeEncoding"; //$NON-NLS-1$
110
111
111
	class TextOperationAction extends MergeViewerAction {
112
	class TextOperationAction extends MergeViewerAction {
Lines 802-807 Link Here
802
803
803
		menu.add(new Separator("edit")); //$NON-NLS-1$
804
		menu.add(new Separator("edit")); //$NON-NLS-1$
804
		addMenu(menu, CHANGE_ENCODING_ID);
805
		addMenu(menu, CHANGE_ENCODING_ID);
806
		addMenu(menu, CREATE_PATCH_ID);
805
		menu.add(new Separator("find")); //$NON-NLS-1$
807
		menu.add(new Separator("find")); //$NON-NLS-1$
806
		addMenu(menu, FIND_ID);
808
		addMenu(menu, FIND_ID);
807
		
809
		
(-)compare/org/eclipse/compare/internal/merge/DocumentMerger.java (-2 / +6 lines)
Lines 626-632 Link Here
626
		return Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
626
		return Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
627
	}
627
	}
628
	
628
	
629
	private IDocument getDocument(char contributor) {
629
	public IDocument getDocument(char contributor) {
630
		return fInput.getDocument(contributor);
630
		return fInput.getDocument(contributor);
631
	}
631
	}
632
632
Lines 1343-1347 Link Here
1343
		}
1343
		}
1344
		return null;
1344
		return null;
1345
	}
1345
	}
1346
	
1346
1347
	public ArrayList getAllDiffs() {
1348
		return fAllDiffs;
1349
	}
1350
1347
}
1351
}
(-)compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java (-1 / +11 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 2020-2025 Link Here
2020
				service.activateContext("org.eclipse.ui.textEditorScope"); //$NON-NLS-1$
2021
				service.activateContext("org.eclipse.ui.textEditorScope"); //$NON-NLS-1$
2021
			}
2022
			}
2022
		}
2023
		}
2024
		
2025
		contributeCreatePatchAction(fLeft, false);
2026
		contributeCreatePatchAction(fRight, true);
2023
	}
2027
	}
2024
	
2028
	
2025
	private void hsynchViewport(final TextViewer tv1, final TextViewer tv2, final TextViewer tv3) {
2029
	private void hsynchViewport(final TextViewer tv1, final TextViewer tv2, final TextViewer tv3) {
Lines 2519-2525 Link Here
2519
		IAction action = new ChangeEncodingAction(getTextEditorAdapter());
2523
		IAction action = new ChangeEncodingAction(getTextEditorAdapter());
2520
		viewer.addAction(MergeSourceViewer.CHANGE_ENCODING_ID, action);
2524
		viewer.addAction(MergeSourceViewer.CHANGE_ENCODING_ID, action);
2521
	}
2525
	}
2522
2526
	 
2527
	private void contributeCreatePatchAction(MergeSourceViewer viewer,
2528
			boolean rightToLeft) {
2529
		IAction action = new CreatePatchAction(this, fMerger, rightToLeft);
2530
		viewer.addAction(MergeSourceViewer.CREATE_PATCH_ID, action);
2531
	}
2532
	
2523
	private void connectGlobalActions(final MergeSourceViewer part) {
2533
	private void connectGlobalActions(final MergeSourceViewer part) {
2524
		if (fHandlerService != null) {
2534
		if (fHandlerService != null) {
2525
			if (part != null)
2535
			if (part != null)
(-)compare/org/eclipse/compare/internal/GenerateDiffFileWizard.java (+1651 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2008, 2009 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
 *     IBM Corportation - initial API and implementation
13
 *******************************************************************************/
14
package org.eclipse.compare.internal;
15
16
import java.io.File;
17
import java.io.IOException;
18
import java.net.MalformedURLException;
19
import java.net.URL;
20
import java.util.ArrayList;
21
import java.util.Iterator;
22
import java.util.List;
23
24
import org.eclipse.compare.internal.merge.DocumentMerger;
25
import org.eclipse.core.resources.IContainer;
26
import org.eclipse.core.resources.IFile;
27
import org.eclipse.core.resources.IProject;
28
import org.eclipse.core.resources.IResource;
29
import org.eclipse.core.resources.IWorkspace;
30
import org.eclipse.core.resources.IWorkspaceRoot;
31
import org.eclipse.core.resources.ResourcesPlugin;
32
import org.eclipse.core.runtime.IPath;
33
import org.eclipse.core.runtime.IStatus;
34
import org.eclipse.core.runtime.Path;
35
import org.eclipse.jface.dialogs.Dialog;
36
import org.eclipse.jface.dialogs.IDialogConstants;
37
import org.eclipse.jface.dialogs.IDialogSettings;
38
import org.eclipse.jface.dialogs.MessageDialog;
39
import org.eclipse.jface.dialogs.TitleAreaDialog;
40
import org.eclipse.jface.resource.ImageDescriptor;
41
import org.eclipse.jface.text.IDocument;
42
import org.eclipse.jface.viewers.DoubleClickEvent;
43
import org.eclipse.jface.viewers.IDoubleClickListener;
44
import org.eclipse.jface.viewers.ISelection;
45
import org.eclipse.jface.viewers.ISelectionChangedListener;
46
import org.eclipse.jface.viewers.IStructuredSelection;
47
import org.eclipse.jface.viewers.SelectionChangedEvent;
48
import org.eclipse.jface.viewers.StructuredSelection;
49
import org.eclipse.jface.viewers.TreeViewer;
50
import org.eclipse.jface.wizard.Wizard;
51
import org.eclipse.jface.wizard.WizardDialog;
52
import org.eclipse.jface.wizard.WizardPage;
53
import org.eclipse.swt.SWT;
54
import org.eclipse.swt.events.ModifyEvent;
55
import org.eclipse.swt.events.ModifyListener;
56
import org.eclipse.swt.events.SelectionAdapter;
57
import org.eclipse.swt.events.SelectionEvent;
58
import org.eclipse.swt.graphics.Image;
59
import org.eclipse.swt.graphics.Point;
60
import org.eclipse.swt.layout.GridData;
61
import org.eclipse.swt.layout.GridLayout;
62
import org.eclipse.swt.widgets.Button;
63
import org.eclipse.swt.widgets.Composite;
64
import org.eclipse.swt.widgets.Control;
65
import org.eclipse.swt.widgets.Event;
66
import org.eclipse.swt.widgets.FileDialog;
67
import org.eclipse.swt.widgets.Group;
68
import org.eclipse.swt.widgets.Label;
69
import org.eclipse.swt.widgets.Listener;
70
import org.eclipse.swt.widgets.Shell;
71
import org.eclipse.swt.widgets.Text;
72
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
73
import org.eclipse.ui.model.WorkbenchLabelProvider;
74
import org.eclipse.ui.views.navigator.ResourceComparator;
75
76
/**
77
 *	Wizard for generating patch from currently open comparison. Part of the code 
78
 *  is taken from original org.eclipse.team.internal.ccvs.ui.wizards.GenerateDiffFileWizard,
79
 *  which now has been changed into a subclass of this class.
80
 */
81
public class GenerateDiffFileWizard extends Wizard {
82
83
	//The initial size of this wizard.
84
	protected final static int INITIAL_WIDTH = 300;
85
	protected final static int INITIAL_HEIGHT = 350;
86
	
87
	public static void run(DocumentMerger merger, Shell shell, boolean rightToLeft) {
88
		final String title = CompareMessages.GenerateLocalDiff_title;
89
		final GenerateDiffFileWizard wizard = new GenerateDiffFileWizard(merger, rightToLeft);
90
		wizard.setWindowTitle(title);
91
		WizardDialog dialog = new WizardDialog(shell, wizard);
92
		dialog.setMinimumPageSize(INITIAL_WIDTH, INITIAL_HEIGHT);
93
		dialog.open();
94
	}
95
96
	protected class DirectionSelectionPage extends WizardPage {
97
98
		public final static int LEFT_OPTION = 1;
99
		public final static int RIGHT_OPTION = 2;
100
101
		private Button fromLeftOption;
102
		private Button fromRightOption;
103
		
104
		private Label fromLeftLabel;
105
		private Label fromRightLabel;
106
		
107
		private RadioButtonGroup fromRadioGroup = new RadioButtonGroup();
108
109
		protected DirectionSelectionPage(String pageName, String title,
110
				ImageDescriptor titleImage) {
111
			super(pageName, title, titleImage);
112
		}
113
114
		public void createControl(Composite parent) {
115
			Composite composite = new Composite(parent, SWT.NULL);
116
			GridLayout layout = new GridLayout();
117
			
118
			initializeDialogUnits(composite);
119
			
120
			layout.marginHeight = IDialogConstants.VERTICAL_MARGIN;
121
			layout.marginWidth = IDialogConstants.HORIZONTAL_MARGIN;
122
			layout.verticalSpacing = IDialogConstants.VERTICAL_SPACING*2;
123
			layout.horizontalSpacing = IDialogConstants.HORIZONTAL_SPACING*2;
124
			layout.numColumns = 2;
125
			
126
			composite.setLayout(layout);
127
			composite.setLayoutData(new GridData());
128
			setControl(composite);
129
			
130
			fromLeftLabel = new Label(composite, SWT.HORIZONTAL|SWT.SHADOW_OUT);
131
			fromLeftLabel.setText(CompareMessages.GenerateDiffFileWizard_Left);
132
			fromLeftLabel.setLayoutData(new GridData(
133
					SWT.BEGINNING, SWT.CENTER, false, false, 1, 1));
134
			
135
			fromLeftOption = new Button(composite, SWT.RADIO);
136
			fromLeftOption.setText(leftPath);
137
			fromLeftOption.setLayoutData(new GridData(
138
					SWT.BEGINNING, SWT.CENTER, false, false, 1, 1));
139
			
140
			fromRightLabel = new Label(composite, SWT.HORIZONTAL|SWT.SHADOW_OUT);			
141
			fromRightLabel.setText(CompareMessages.GenerateDiffFileWizard_Right);
142
			fromRightLabel.setLayoutData(new GridData(
143
					SWT.BEGINNING, SWT.CENTER, false, false, 1, 1));
144
			
145
			fromRightOption = new Button(composite, SWT.RADIO);
146
			fromRightOption.setText(rightPath);
147
			fromRightOption.setLayoutData(new GridData(
148
					SWT.BEGINNING, SWT.CENTER, false, false, 1, 1));
149
			
150
			fromRadioGroup.add(LEFT_OPTION, fromLeftOption);
151
			fromRadioGroup.add(RIGHT_OPTION, fromRightOption);
152
153
			Dialog.applyDialogFont(parent);
154
155
			// Add listeners
156
			fromLeftOption.addSelectionListener(new SelectionAdapter() {
157
				public void widgetSelected(SelectionEvent e) {
158
					fromRadioGroup.setSelection(LEFT_OPTION, true);
159
					targetFileEdited = false;
160
				}
161
			});
162
163
			fromRightOption.addSelectionListener(new SelectionAdapter() {
164
				public void widgetSelected(SelectionEvent e) {
165
					fromRadioGroup.setSelection(RIGHT_OPTION, true);
166
					targetFileEdited = false;
167
				}
168
			});
169
170
			fromRadioGroup.setSelection(rightToLeft ? RIGHT_OPTION
171
					: LEFT_OPTION, true);
172
		}
173
174
		public boolean isRightToLeft() {
175
			return fromRadioGroup.getSelected() == LEFT_OPTION;
176
		}
177
178
	}
179
180
	/**
181
	 * Page to select a patch file. Overriding validatePage was necessary to
182
	 * allow entering a file name that already exists.
183
	 */
184
	protected class LocationPage extends WizardPage {
185
186
        /**
187
         * The possible locations to save a patch.
188
         */
189
        public final static int CLIPBOARD = 1;
190
        public final static int FILESYSTEM = 2;
191
        public final static int WORKSPACE = 3;
192
193
        /**
194
         * GUI controls for clipboard (cp), filesystem (fs) and workspace (ws).
195
         */
196
        private Button cpRadio;
197
198
        private Button fsRadio;
199
        protected Text fsPathText;
200
        private Button fsBrowseButton;
201
        private boolean fsBrowsed = false;
202
203
        private Button wsRadio;
204
    	protected Text wsPathText;
205
        private Button wsBrowseButton;
206
        private boolean wsBrowsed = false;
207
208
        protected boolean pageValid;
209
        protected IContainer wsSelectedContainer;
210
        protected IPath[] foldersToCreate;
211
        protected int selectedLocation;
212
213
        /**
214
         * The default values store used to initialize the selections.
215
         */
216
        private final DefaultValuesStore store;
217
218
219
    	class LocationPageContentProvider extends BaseWorkbenchContentProvider {
220
    		//Never show closed projects
221
    		boolean showClosedProjects=false;
222
    		
223
    		public Object[] getChildren(Object element) {
224
    			if (element instanceof IWorkspace) {
225
    	            // check if closed projects should be shown
226
    	            IProject[] allProjects = ((IWorkspace) element).getRoot().getProjects();
227
    	            if (showClosedProjects)
228
    	                return allProjects;
229
230
    	            ArrayList accessibleProjects = new ArrayList();
231
    	            for (int i = 0; i < allProjects.length; i++) {
232
    	                if (allProjects[i].isOpen()) {
233
    	                    accessibleProjects.add(allProjects[i]);
234
    	                }
235
    	            }
236
    	            return accessibleProjects.toArray();
237
    	        } 
238
    			
239
    			return super.getChildren(element);
240
    		}
241
    	}
242
243
    	class WorkspaceDialog extends TitleAreaDialog {
244
245
    		protected TreeViewer wsTreeViewer;
246
    	    protected Text wsFilenameText;
247
    	    protected Image dlgTitleImage;
248
249
    	    private boolean modified = false;
250
251
			public WorkspaceDialog(Shell shell) {
252
				super(shell);
253
			}
254
255
			protected Control createContents(Composite parent) {
256
		        Control control = super.createContents(parent);
257
				setTitle(CompareMessages.WorkspacePatchDialogTitle);
258
				setMessage(CompareMessages.WorkspacePatchDialogDescription);
259
			    //create title image
260
				dlgTitleImage = CompareUIPlugin.getImageDescriptor(
261
						ICompareUIConstants.IMG_WIZBAN_DIFF).createImage();
262
				setTitleImage(dlgTitleImage);
263
				
264
		        return control;
265
			}
266
			
267
			protected Control createDialogArea(Composite parent) {
268
				Composite parentComposite = (Composite) super.createDialogArea(parent);
269
270
				 // create a composite with standard margins and spacing
271
		        Composite composite = new Composite(parentComposite, SWT.NONE);
272
		        GridLayout layout = new GridLayout();
273
		        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
274
		        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
275
		        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
276
		        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
277
		        composite.setLayout(layout);
278
		        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
279
		        composite.setFont(parentComposite.getFont());
280
				
281
				getShell().setText(CompareMessages.GenerateDiffFileWizard_9);
282
		
283
                wsTreeViewer = new TreeViewer(composite, SWT.BORDER);
284
                final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
285
                gd.widthHint= 550;
286
                gd.heightHint= 250;
287
                wsTreeViewer.getTree().setLayoutData(gd);
288
289
                wsTreeViewer.setContentProvider(new LocationPageContentProvider());
290
                wsTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
291
                wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
292
                wsTreeViewer.setInput(ResourcesPlugin.getWorkspace());
293
                
294
                //Open to whatever is selected in the workspace field
295
                IPath existingWorkspacePath = new Path(wsPathText.getText());
296
                if (existingWorkspacePath != null){
297
                	//Ensure that this workspace path is valid
298
                	IResource selectedResource = ResourcesPlugin.getWorkspace().getRoot().findMember(existingWorkspacePath);
299
                	if (selectedResource != null) {
300
                		wsTreeViewer.expandToLevel(selectedResource, 0);
301
                		wsTreeViewer.setSelection(new StructuredSelection(selectedResource));
302
            		}
303
                }
304
                
305
                final Composite group = new Composite(composite, SWT.NONE);
306
                layout = new GridLayout(2, false);
307
                layout.marginWidth = 0;
308
                group.setLayout(layout);
309
                group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
310
311
                final Label label = new Label(group, SWT.NONE);
312
                label.setLayoutData(new GridData());
313
                label.setText(CompareMessages.Fi_le_name__9);
314
                
315
                wsFilenameText = new Text(group,SWT.BORDER);
316
                wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
317
				
318
                setupListeners();
319
				
320
				return parent;
321
			}
322
323
			protected Button createButton(Composite parent, int id,
324
					String label, boolean defaultButton) {
325
				Button button = super.createButton(parent, id, label,
326
						defaultButton);
327
				if (id == IDialogConstants.OK_ID) {
328
					button.setEnabled(false);
329
				}
330
				return button;
331
			}
332
333
			private void validateDialog() {
334
				String fileName = wsFilenameText.getText();
335
336
				if (fileName.equals("")) { //$NON-NLS-1$
337
					if (modified) {
338
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_2);
339
						getButton(IDialogConstants.OK_ID).setEnabled(false);
340
						return;
341
					} else {
342
						setErrorMessage(null);
343
						getButton(IDialogConstants.OK_ID).setEnabled(false);
344
						return;
345
					}
346
				}
347
				// make sure that the filename is valid
348
				if (!(ResourcesPlugin.getWorkspace().validateName(fileName,
349
						IResource.FILE)).isOK() && modified) {
350
					setErrorMessage(CompareMessages.GenerateDiffFileWizard_5);
351
					getButton(IDialogConstants.OK_ID).setEnabled(false);
352
					return;
353
				}
354
355
				// Make sure that a container has been selected
356
				if (getSelectedContainer() == null) {
357
					setErrorMessage(CompareMessages.GenerateDiffFileWizard_0);
358
					getButton(IDialogConstants.OK_ID).setEnabled(false);
359
					return;
360
				} else {
361
					IWorkspace workspace = ResourcesPlugin.getWorkspace();
362
					IPath fullPath = wsSelectedContainer.getFullPath().append(
363
							fileName);
364
					if (workspace.getRoot().getFolder(fullPath).exists()) {
365
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists);
366
						getButton(IDialogConstants.OK_ID).setEnabled(false);
367
						return;
368
					}
369
				}
370
371
				setErrorMessage(null);
372
				getButton(IDialogConstants.OK_ID).setEnabled(true);
373
			}
374
375
			protected void okPressed() {
376
				IFile file = wsSelectedContainer.getFile(new Path(
377
						wsFilenameText.getText()));
378
				if (file != null)
379
					wsPathText.setText(file.getFullPath().toString());
380
				
381
				validatePage();
382
				super.okPressed();
383
			}
384
			
385
			private IContainer getSelectedContainer() {
386
				Object obj = ((IStructuredSelection)wsTreeViewer.getSelection()).getFirstElement();
387
                if (obj instanceof IContainer) {
388
                	wsSelectedContainer = (IContainer) obj;
389
                } else if (obj instanceof IFile) {
390
                	wsSelectedContainer = ((IFile) obj).getParent();
391
                }
392
                return wsSelectedContainer;
393
			}
394
395
			protected void cancelPressed() {
396
			  validatePage();
397
			  super.cancelPressed();
398
			}
399
		 
400
		   public boolean close() {
401
		        if (dlgTitleImage != null)
402
		            dlgTitleImage.dispose();
403
		        return super.close();
404
		    }
405
			  
406
			void setupListeners(){
407
				 wsTreeViewer.addSelectionChangedListener(
408
                new ISelectionChangedListener() {
409
                    public void selectionChanged(SelectionChangedEvent event) {
410
                        IStructuredSelection s = (IStructuredSelection)event.getSelection();
411
                        Object obj=s.getFirstElement();
412
                        if (obj instanceof IContainer)
413
                        	wsSelectedContainer = (IContainer) obj;
414
                        else if (obj instanceof IFile){
415
                        	IFile tempFile = (IFile) obj;
416
                        	wsSelectedContainer = tempFile.getParent();
417
                        	wsFilenameText.setText(tempFile.getName());
418
                        }
419
                        validateDialog();
420
                    }
421
                });
422
        
423
		        wsTreeViewer.addDoubleClickListener(
424
		                new IDoubleClickListener() {
425
		                    public void doubleClick(DoubleClickEvent event) {
426
		                        ISelection s= event.getSelection();
427
		                        if (s instanceof IStructuredSelection) {
428
		                            Object item = ((IStructuredSelection)s).getFirstElement();
429
		                            if (wsTreeViewer.getExpandedState(item))
430
		                                wsTreeViewer.collapseToLevel(item, 1);
431
		                            else
432
		                                wsTreeViewer.expandToLevel(item, 1);
433
		                        }
434
		                        validateDialog();
435
		                    }
436
		                });
437
        
438
		        wsFilenameText.addModifyListener(new ModifyListener() {
439
					public void modifyText(ModifyEvent e) {
440
						modified = true;
441
						validateDialog();
442
					}
443
				});
444
			}
445
		}
446
    	
447
        LocationPage(String pageName, String title, ImageDescriptor image, DefaultValuesStore store) {
448
            super(pageName, title, image);
449
            setPageComplete(false);
450
            this.store= store;
451
		}
452
453
        /**
454
         * Allow the user to finish if a valid file has been entered. 
455
         */
456
        protected boolean validatePage() {
457
            switch (selectedLocation) {
458
            case WORKSPACE:
459
                pageValid= validateWorkspaceLocation();
460
                break;
461
            case FILESYSTEM:
462
                pageValid= validateFilesystemLocation();
463
                break;
464
            case CLIPBOARD:
465
                pageValid= true;
466
                break;
467
            }
468
            
469
            /**
470
             * Avoid draw flicker by clearing error message
471
             * if all is valid.
472
             */
473
            if (pageValid) {
474
                setMessage(null);
475
                setErrorMessage(null);
476
            }
477
            setPageComplete(pageValid);
478
            return pageValid;
479
        }
480
        
481
        /**
482
         * The following conditions must hold for the file system location
483
         * to be valid:
484
         * - the path must be valid and non-empty
485
         * - the path must be absolute
486
         * - the specified file must be of type file
487
         * - the parent must exist (new folders can be created via the browse button)
488
         */
489
        private boolean validateFilesystemLocation() {
490
            final String pathString= fsPathText.getText().trim();
491
            if (pathString.length() == 0 || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$
492
            	if (fsBrowsed)
493
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_0);
494
            	else 
495
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_browseFilesystem);
496
                return false;
497
            }
498
            
499
            final File file= new File(pathString);
500
            if (!file.isAbsolute()) {
501
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_0); 
502
                return false;
503
            }
504
            
505
            if (file.isDirectory()) {
506
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_2); 
507
                return false;
508
            }
509
            
510
            if (pathString.endsWith("/") || pathString.endsWith("\\")) {  //$NON-NLS-1$//$NON-NLS-2$
511
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); 
512
                return false;
513
            }
514
            
515
            final File parent= file.getParentFile();
516
            if (!(parent.exists() && parent.isDirectory())) {
517
                setErrorMessage(CompareMessages.GenerateDiffFileWizard_3); 
518
                return false;
519
            }
520
            return true;
521
        }
522
        
523
        /**
524
         * The following conditions must hold for the file system location to be valid:
525
         * - a parent must be selected in the workspace tree view
526
         * - the resource name must be valid 
527
         */
528
        private boolean validateWorkspaceLocation() {
529
            //make sure that the field actually has a filename in it - making
530
        	//sure that the user has had a chance to browse the workspace first
531
            if (wsPathText.getText().equals("")){ //$NON-NLS-1$
532
            	if (selectedLocation ==WORKSPACE && wsBrowsed)
533
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_5);
534
            	else 
535
            		setErrorMessage(CompareMessages.GenerateDiffFileWizard_4);
536
            	return false;
537
            }
538
            
539
            //Make sure that all the segments but the last one (i.e. project + all
540
            //folders) exist - file doesn't have to exist. It may have happened that
541
            //some folder refactoring has been done since this path was last saved.
542
            //
543
            // The path will always be in format project/{folders}*/file - this
544
			// is controlled by the workspace location dialog and by
545
			// validatePath method when path has been entered manually.
546
            
547
            
548
            IPath pathToWorkspaceFile = new Path(wsPathText.getText());
549
            IStatus status = ResourcesPlugin.getWorkspace().validatePath(wsPathText.getText(), IResource.FILE);
550
            if (status.isOK()) {
551
            	//Trim file name from path
552
            	IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
553
            	IResource container =ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
554
            	if (container == null) {
555
            		if (selectedLocation == WORKSPACE)
556
            			setErrorMessage(CompareMessages.GenerateDiffFileWizard_4); 
557
            		return false;
558
				} else if (!container.isAccessible()) {
559
					if (selectedLocation == WORKSPACE)
560
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_ProjectClosed);
561
					return false;
562
				} else {
563
					if (ResourcesPlugin.getWorkspace().getRoot().getFolder(
564
							pathToWorkspaceFile).exists()) {
565
						setErrorMessage(CompareMessages.GenerateDiffFileWizard_FolderExists);
566
						return false;
567
					}
568
				}
569
            } else {
570
            	setErrorMessage(status.getMessage());
571
            	return false;
572
            }
573
            
574
            return true;
575
        }
576
577
        /**
578
         * Answers a full path to a file system file or <code>null</code> if the user
579
         * selected to save the patch in the clipboard.
580
         */
581
        public File getFile() {
582
            if (pageValid && selectedLocation == FILESYSTEM) {
583
                return new File(fsPathText.getText().trim());
584
            } 
585
            if (pageValid && selectedLocation == WORKSPACE) {
586
                final String filename= wsPathText.getText().trim();
587
                IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
588
                final IFile file= root.getFile(new Path(filename));
589
                return file.getLocation().toFile();
590
            }
591
            return null;
592
        }
593
594
        /**
595
         * Answers the workspace string entered in the dialog or <code>null</code> if the user
596
         * selected to save the patch in the clipboard or file system.
597
         */
598
        public String getWorkspaceLocation() {
599
           
600
            if (pageValid && selectedLocation == WORKSPACE) {
601
                final String filename= wsPathText.getText().trim();
602
                return filename;
603
            }
604
            return null;
605
        }
606
        
607
        /**
608
         * Get the selected workspace resource if the patch is to be saved in the 
609
         * workspace, or null otherwise.
610
         */
611
        public IResource getResource() {
612
            if (pageValid && selectedLocation == WORKSPACE) {
613
                IPath pathToWorkspaceFile = new Path(wsPathText.getText().trim());
614
                //Trim file name from path
615
                IPath containerPath = pathToWorkspaceFile.removeLastSegments(1);
616
                return ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath);
617
            }
618
            return null;
619
        }
620
        
621
        /**
622
         * Allow the user to chose to save the patch to the workspace or outside
623
         * of the workspace.
624
         */
625
        public void createControl(Composite parent) {
626
            
627
            final Composite composite= new Composite(parent, SWT.NULL);
628
            composite.setLayout(new GridLayout());
629
            setControl(composite);
630
            initializeDialogUnits(composite);
631
            
632
            // set F1 help
633
//            PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.PATCH_SELECTION_PAGE);
634
            
635
            //Create a location group
636
            setupLocationControls(composite);
637
            
638
            initializeDefaultValues();
639
640
            Dialog.applyDialogFont(parent);
641
642
            validatePage();
643
            
644
            updateEnablements();
645
            setupListeners();
646
		}
647
648
        /**
649
         * Setup the controls for the location.
650
         */
651
        private void setupLocationControls(final Composite parent) {
652
			final Composite composite = new Composite(parent, SWT.NULL);
653
			GridLayout gridLayout = new GridLayout();
654
			gridLayout.numColumns = 3;
655
			composite.setLayout(gridLayout);
656
			composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
657
658
			// clipboard
659
			GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
660
			gd.horizontalSpan = 3;
661
			cpRadio = new Button(composite, SWT.RADIO);
662
			cpRadio.setText(CompareMessages.Save_To_Clipboard_2);
663
			cpRadio.setLayoutData(gd);
664
665
			// filesystem
666
			fsRadio = new Button(composite, SWT.RADIO);
667
			fsRadio.setText(CompareMessages.Save_In_File_System_3);
668
669
			fsPathText = new Text(composite, SWT.BORDER);
670
			gd = new GridData(GridData.FILL_HORIZONTAL);
671
			fsPathText.setLayoutData(gd);
672
673
			fsBrowseButton = new Button(composite, SWT.PUSH);
674
			fsBrowseButton.setText(CompareMessages.Browse____4);
675
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
676
			int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
677
			Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT,
678
					SWT.DEFAULT, true);
679
			data.widthHint = Math.max(widthHint, minSize.x);
680
			fsBrowseButton.setLayoutData(data);
681
682
			// workspace
683
			wsRadio = new Button(composite, SWT.RADIO);
684
			wsRadio.setText(CompareMessages.Save_In_Workspace_7);
685
686
			wsPathText = new Text(composite, SWT.BORDER);
687
			gd = new GridData(GridData.FILL_HORIZONTAL);
688
			wsPathText.setLayoutData(gd);
689
690
			wsBrowseButton = new Button(composite, SWT.PUSH);
691
			wsBrowseButton.setText(CompareMessages.Browse____4);
692
			data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
693
			widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
694
			minSize = fsBrowseButton
695
					.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
696
			data.widthHint = Math.max(widthHint, minSize.x);
697
			wsBrowseButton.setLayoutData(data);
698
			
699
			// change the cpRadio layout to be of the same height as other rows' layout
700
			((GridData)cpRadio.getLayoutData()).heightHint = minSize.y;
701
		}
702
703
        /**
704
         * Initialize the controls with the saved default values which are
705
         * obtained from the DefaultValuesStore.
706
         */
707
        private void initializeDefaultValues() {
708
709
            selectedLocation= store.getLocationSelection();
710
            
711
            updateRadioButtons();
712
            
713
            /**
714
             * Text fields.
715
             */
716
            // We need to ensure that we have a valid workspace path - user
717
            //could have altered workspace since last time this was saved
718
            wsPathText.setText(store.getWorkspacePath());
719
            if(!validateWorkspaceLocation()) {
720
            	wsPathText.setText(""); //$NON-NLS-1$
721
            	
722
            	//Don't open wizard with an error - instead change selection
723
            	//to clipboard
724
            	if (selectedLocation == WORKSPACE){
725
            		//clear the error message caused by the workspace not having
726
            		//any workspace path entered
727
            		setErrorMessage(null);
728
            		selectedLocation=CLIPBOARD;
729
            		updateRadioButtons();
730
            	}
731
            }
732
            // Do the same thing for the filesystem field 
733
            fsPathText.setText(store.getFilesystemPath());
734
            if (!validateFilesystemLocation()) {
735
            	fsPathText.setText(""); //$NON-NLS-1$
736
            	if (selectedLocation == FILESYSTEM) {
737
            		setErrorMessage(null);
738
            		selectedLocation = CLIPBOARD;
739
            		updateRadioButtons();
740
            	}
741
            }
742
            
743
        }
744
745
		private void updateRadioButtons() {
746
			/**
747
             * Radio buttons
748
             */
749
            cpRadio.setSelection(selectedLocation == CLIPBOARD);
750
            fsRadio.setSelection(selectedLocation == FILESYSTEM);
751
            wsRadio.setSelection(selectedLocation == WORKSPACE);
752
		}
753
754
        /**
755
         * Setup all the listeners for the controls. 
756
         */
757
        private void setupListeners() {
758
759
            cpRadio.addListener(SWT.Selection, new Listener() {
760
                public void handleEvent(Event event) {
761
                    selectedLocation= CLIPBOARD;
762
                    validatePage();
763
                    updateEnablements();
764
                }
765
            });
766
            fsRadio.addListener(SWT.Selection, new Listener() {
767
                public void handleEvent(Event event) {
768
                    selectedLocation= FILESYSTEM;
769
                    validatePage();
770
                    updateEnablements();
771
                }
772
            });
773
            
774
            wsRadio.addListener(SWT.Selection, new Listener() {
775
                public void handleEvent(Event event) {
776
                    selectedLocation= WORKSPACE;
777
                    validatePage();
778
                    updateEnablements();
779
                }
780
            });
781
            
782
    		ModifyListener pathTextModifyListener = new ModifyListener() {
783
				public void modifyText(ModifyEvent e) {
784
					validatePage();
785
				}
786
			};
787
			fsPathText.addModifyListener(pathTextModifyListener);
788
			wsPathText.addModifyListener(pathTextModifyListener);
789
			
790
            fsBrowseButton.addListener(SWT.Selection, new Listener() {
791
                public void handleEvent(Event event) {
792
                    final FileDialog dialog = new FileDialog(getShell(), SWT.PRIMARY_MODAL | SWT.SAVE);
793
                    if (pageValid) {
794
                        final File file= new File(fsPathText.getText());
795
                        dialog.setFilterPath(file.getParent());
796
                    }
797
                    dialog.setText(CompareMessages.Save_Patch_As_5); 
798
                    dialog.setFileName(CompareMessages.patch_txt_6); 
799
                    final String path = dialog.open();
800
                    fsBrowsed = true;
801
                    if (path != null) {
802
                        fsPathText.setText(new Path(path).toOSString());
803
                    }			
804
                    validatePage();
805
                }
806
            });		
807
            
808
           
809
            
810
            wsBrowseButton.addListener(SWT.Selection, new Listener() {
811
                public void handleEvent(Event event) {
812
                	final WorkspaceDialog dialog = new WorkspaceDialog(getShell());
813
                	wsBrowsed = true;
814
                	dialog.open();
815
                	validatePage();
816
                }
817
            });	
818
819
		}
820
821
        /**
822
         * Enable and disable controls based on the selected radio button.
823
         */
824
        public void updateEnablements() {
825
            fsBrowseButton.setEnabled(selectedLocation == FILESYSTEM);
826
            fsPathText.setEnabled(selectedLocation == FILESYSTEM);
827
            if (selectedLocation == FILESYSTEM)
828
            	fsBrowsed=false;
829
            wsPathText.setEnabled(selectedLocation == WORKSPACE);
830
            wsBrowseButton.setEnabled(selectedLocation == WORKSPACE);
831
            if (selectedLocation == WORKSPACE)
832
            	wsBrowsed=false;
833
        }
834
        
835
        public int getSelectedLocation() {
836
            return selectedLocation;
837
        }
838
        
839
	}
840
841
    /**
842
     * Page to select the options for creating the patch.
843
     */
844
    private class OptionsPage extends WizardPage {
845
       
846
    	/**
847
    	* The possible file format to save a patch.
848
    	*/
849
    	public final static int FORMAT_UNIFIED = 1;
850
    	public final static int FORMAT_CONTEXT = 2;
851
    	public final static int FORMAT_STANDARD = 3;
852
853
    	/**
854
    	The possible root of the patch
855
    	*/
856
    	public final static int ROOT_WORKSPACE = 1;
857
    	public final static int ROOT_PROJECT = 2;
858
    	public final static int ROOT_SELECTION = 3;
859
		public final static int ROOT_CUSTOM = 4;
860
		
861
		protected boolean initialized = false;
862
863
    	protected Button unifiedDiffOption;
864
    	protected Button unified_workspaceRelativeOption; //multi-patch format
865
    	protected Button unified_projectRelativeOption; //full project path
866
    	protected Button unified_selectionRelativeOption; //use path of whatever is selected
867
        protected Button contextDiffOption;
868
        protected Button regularDiffOption;
869
		
870
		protected Group unifiedGroup;
871
		protected Group diffTypeGroup;
872
		
873
        protected final RadioButtonGroup diffTypeRadioGroup = new RadioButtonGroup();
874
        protected final RadioButtonGroup unifiedRadioGroup = new RadioButtonGroup();
875
876
        protected IPath patchRoot=ResourcesPlugin.getWorkspace().getRoot().getFullPath();
877
		        
878
        private final DefaultValuesStore store;
879
        
880
		public IPath getPatchRoot() {
881
			return patchRoot;
882
		}
883
884
        /**
885
         * Constructor for PatchFileCreationOptionsPage.
886
         */
887
        protected OptionsPage(String pageName, String title, ImageDescriptor titleImage, DefaultValuesStore store) {
888
            super(pageName, title, titleImage);
889
            this.store = store;
890
        }
891
892
        /*
893
         * @see IDialogPage#createControl(Composite)
894
         */
895
        public void createControl(Composite parent) {
896
            Composite composite= new Composite(parent, SWT.NULL);
897
            GridLayout layout= new GridLayout();
898
            composite.setLayout(layout);
899
            composite.setLayoutData(new GridData());
900
            setControl(composite);
901
902
            // set F1 help
903
//            PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.PATCH_OPTIONS_PAGE);
904
            
905
			diffTypeGroup = new Group(composite, SWT.NONE);
906
			layout = new GridLayout();
907
			layout.marginHeight = 0;
908
			diffTypeGroup.setLayout(layout);
909
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
910
					| GridData.GRAB_HORIZONTAL);
911
			diffTypeGroup.setLayoutData(data);
912
			diffTypeGroup.setText(CompareMessages.Diff_output_format_12);
913
914
            unifiedDiffOption = new Button(diffTypeGroup, SWT.RADIO);
915
            unifiedDiffOption.setText(CompareMessages.Unified__format_required_by_Compare_With_Patch_feature__13);
916
            
917
            contextDiffOption = new Button(diffTypeGroup, SWT.RADIO);
918
            contextDiffOption.setText(CompareMessages.Context_14); 
919
            regularDiffOption = new Button(diffTypeGroup, SWT.RADIO);
920
            regularDiffOption.setText(CompareMessages.Standard_15); 
921
            
922
            diffTypeRadioGroup.add(FORMAT_UNIFIED, unifiedDiffOption);
923
			diffTypeRadioGroup.add(FORMAT_CONTEXT, contextDiffOption);
924
			diffTypeRadioGroup.add(FORMAT_STANDARD, regularDiffOption);
925
            
926
			// Unified Format Options
927
            unifiedGroup = new Group(composite, SWT.None);
928
            layout = new GridLayout();
929
            layout.numColumns = 2;
930
            unifiedGroup.setLayout(layout);
931
            data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
932
					| GridData.GRAB_HORIZONTAL);
933
            unifiedGroup.setLayoutData(data);
934
            unifiedGroup.setText(CompareMessages.GenerateDiffFileWizard_10);
935
936
			unified_workspaceRelativeOption = new Button(unifiedGroup, SWT.RADIO);
937
			unified_workspaceRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_6);
938
			unified_workspaceRelativeOption.setLayoutData(new GridData(
939
					SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
940
941
			unified_projectRelativeOption = new Button(unifiedGroup, SWT.RADIO);
942
			unified_projectRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_7);
943
			unified_projectRelativeOption.setLayoutData(new GridData(
944
					SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
945
946
			unified_selectionRelativeOption = new Button(unifiedGroup, SWT.RADIO);
947
			unified_selectionRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_8);
948
			unified_selectionRelativeOption.setLayoutData(new GridData(
949
					SWT.BEGINNING, SWT.CENTER, false, true, 2, 1));
950
			
951
			unifiedRadioGroup.add(ROOT_WORKSPACE, unified_workspaceRelativeOption);
952
			unifiedRadioGroup.add(ROOT_PROJECT, unified_projectRelativeOption);
953
			unifiedRadioGroup.add(ROOT_SELECTION, unified_selectionRelativeOption);
954
            
955
            Dialog.applyDialogFont(parent);
956
            
957
            initializeDefaultValues();
958
959
            //add listeners
960
            unifiedDiffOption.addSelectionListener(new SelectionAdapter() {
961
				public void widgetSelected(SelectionEvent e) {
962
					setEnableUnifiedGroup(true);
963
					updateEnablements();
964
					diffTypeRadioGroup.setSelection(FORMAT_UNIFIED, false);
965
				}
966
			});
967
            
968
            contextDiffOption.addSelectionListener(new SelectionAdapter() {
969
				public void widgetSelected(SelectionEvent e) {
970
					setEnableUnifiedGroup(false);
971
					updateEnablements();
972
					diffTypeRadioGroup.setSelection(FORMAT_CONTEXT, false);
973
				}
974
			});
975
            
976
            regularDiffOption.addSelectionListener(new SelectionAdapter() {
977
				public void widgetSelected(SelectionEvent e) {
978
					setEnableUnifiedGroup(false);
979
					updateEnablements();
980
					diffTypeRadioGroup.setSelection(FORMAT_STANDARD, false);
981
				}
982
			});
983
            
984
            unified_workspaceRelativeOption
985
					.addSelectionListener(new SelectionAdapter() {
986
						public void widgetSelected(SelectionEvent e) {
987
							unifiedRadioGroup.setSelection(ROOT_WORKSPACE, false);
988
						}
989
					});
990
991
			unified_projectRelativeOption
992
					.addSelectionListener(new SelectionAdapter() {
993
						public void widgetSelected(SelectionEvent e) {
994
							unifiedRadioGroup.setSelection(ROOT_PROJECT, false);
995
						}
996
					});
997
998
			unified_selectionRelativeOption
999
					.addSelectionListener(new SelectionAdapter() {
1000
						public void widgetSelected(SelectionEvent e) {
1001
							unifiedRadioGroup.setSelection(ROOT_SELECTION, false);
1002
						}
1003
					});
1004
1005
           updateEnablements();
1006
1007
           performSpecificActions();
1008
			
1009
			// update selection
1010
			diffTypeRadioGroup.selectEnabledOnly();
1011
			unifiedRadioGroup.selectEnabledOnly();
1012
        }
1013
1014
		protected void performSpecificActions() {
1015
			return;
1016
		}
1017
1018
		public int getFormatSelection() {
1019
			return diffTypeRadioGroup.getSelected();
1020
		}
1021
1022
		public int getRootSelection() {
1023
			return unifiedRadioGroup.getSelected();
1024
		}
1025
1026
		public String getPath() {
1027
			return unified_customRelativeText.getText();
1028
		}
1029
		
1030
		public Group getUnifiedGroup() {
1031
			return unifiedGroup;
1032
		}
1033
1034
		public Group getDiffTypeGroup() {
1035
			return diffTypeGroup;
1036
		}
1037
		
1038
		public RadioButtonGroup getDiffTypeRadioGroup() {
1039
			return diffTypeRadioGroup;
1040
		}
1041
1042
		public RadioButtonGroup getUnifiedRadioGroup() {
1043
			return unifiedRadioGroup;
1044
		}
1045
		
1046
1047
		public Button getUnifiedDiffOption() {
1048
			return unifiedDiffOption;
1049
		}
1050
1051
		public Button getContextDiffOption() {
1052
			return contextDiffOption;
1053
		}
1054
1055
		public Button getRegularDiffOption() {
1056
			return regularDiffOption;
1057
		}
1058
1059
		public Button getUnified_workspaceRelativeOption() {
1060
			return unified_workspaceRelativeOption;
1061
		}
1062
1063
		public Button getUnified_projectRelativeOption() {
1064
			return unified_projectRelativeOption;
1065
		}
1066
1067
		public Button getUnified_selectionRelativeOption() {
1068
			return unified_selectionRelativeOption;
1069
		}
1070
1071
		private void initializeDefaultValues() {
1072
			// Radio buttons for format
1073
			diffTypeRadioGroup.setSelection(store.getFormatSelection(), true);
1074
			// Radio buttons for patch root
1075
			unifiedRadioGroup.setSelection(store.getRootSelection(), true);
1076
		}
1077
1078
		protected void updateEnablements() {
1079
			if(diffTypeRadioGroup.selected != FORMAT_UNIFIED)
1080
				setEnableUnifiedGroup(false);
1081
		}
1082
		
1083
		public void updateDiffTypeEnablements(int[] disabled, int enabled) {
1084
			diffTypeRadioGroup.setEnablement(false, disabled, enabled);
1085
		}
1086
		
1087
		public void updateUnifiedEnablements(int[] disabled, int enabled) {
1088
			unifiedRadioGroup.setEnablement(false, disabled, enabled);
1089
		}
1090
		
1091
        protected void setEnableUnifiedGroup(boolean enabled) {
1092
        	unifiedRadioGroup.setEnablement(enabled, new int[] {
1093
					ROOT_WORKSPACE, ROOT_PROJECT, ROOT_SELECTION });
1094
        }
1095
1096
	}
1097
1098
	/**
1099
	 * Class to retrieve and store the default selected values.
1100
	 */
1101
	protected final class DefaultValuesStore {
1102
1103
		private static final String PREF_LAST_SELECTION = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.lastselection"; //$NON-NLS-1$
1104
		private static final String PREF_LAST_FS_PATH = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.filesystem.path"; //$NON-NLS-1$
1105
		private static final String PREF_LAST_WS_PATH = "org.eclipse.compare.internal.GenerateDiffFileWizard.PatchFileSelectionPage.workspace.path"; //$NON-NLS-1$
1106
		private static final String PREF_LAST_AO_FORMAT = "org.eclipse.compare.internal.GenerateDiffFileWizard.OptionsPage.diff.format"; //$NON-NLS-1$
1107
		private static final String PREF_LAST_AO_ROOT = "org.eclipse.compare.internal.GenerateDiffFileWizard.OptionsPage.patch.root"; //$NON-NLS-1$
1108
        
1109
        private final IDialogSettings dialogSettings;
1110
        
1111
        public DefaultValuesStore() {
1112
            dialogSettings= CompareUIPlugin.getDefault().getDialogSettings(); 
1113
        }
1114
        
1115
        public int getLocationSelection() {
1116
            int value= LocationPage.CLIPBOARD;
1117
            try {
1118
                value= dialogSettings.getInt(PREF_LAST_SELECTION);
1119
            } catch (NumberFormatException e) {
1120
            }
1121
            
1122
            switch (value) {
1123
            case LocationPage.FILESYSTEM:
1124
            case LocationPage.WORKSPACE:
1125
            case LocationPage.CLIPBOARD:
1126
                return value;
1127
            default:
1128
                return LocationPage.CLIPBOARD;
1129
            }
1130
        }
1131
        
1132
        public String getFilesystemPath() {
1133
            final String path= dialogSettings.get(PREF_LAST_FS_PATH);
1134
            return path != null ? path : "";  //$NON-NLS-1$
1135
        }
1136
        
1137
        public String getWorkspacePath() {
1138
            final String path= dialogSettings.get(PREF_LAST_WS_PATH);
1139
            return path != null ? path : ""; //$NON-NLS-1$
1140
        }
1141
        
1142
1143
		public int getFormatSelection() {
1144
			int value = OptionsPage.FORMAT_UNIFIED;
1145
			try {
1146
				value = dialogSettings.getInt(PREF_LAST_AO_FORMAT);
1147
			} catch (NumberFormatException e) {
1148
			}
1149
1150
			switch (value) {
1151
			case OptionsPage.FORMAT_UNIFIED:
1152
			case OptionsPage.FORMAT_CONTEXT:
1153
			case OptionsPage.FORMAT_STANDARD:
1154
				return value;
1155
			default:
1156
				return OptionsPage.FORMAT_UNIFIED;
1157
			}
1158
		}
1159
1160
		public int getRootSelection() {
1161
			int value = OptionsPage.ROOT_WORKSPACE;
1162
			try {
1163
				value = dialogSettings.getInt(PREF_LAST_AO_ROOT);
1164
			} catch (NumberFormatException e) {
1165
			}
1166
1167
			switch (value) {
1168
			case OptionsPage.ROOT_WORKSPACE:
1169
			case OptionsPage.ROOT_PROJECT:
1170
			case OptionsPage.ROOT_SELECTION:
1171
				return value;
1172
			default:
1173
				return OptionsPage.ROOT_WORKSPACE;
1174
			}
1175
		}  
1176
        	
1177
        public void storeLocationSelection(int defaultSelection) {
1178
            dialogSettings.put(PREF_LAST_SELECTION, defaultSelection);
1179
        }
1180
        
1181
        public void storeFilesystemPath(String path) {
1182
            dialogSettings.put(PREF_LAST_FS_PATH, path);
1183
        }
1184
        
1185
        public void storeWorkspacePath(String path) {
1186
            dialogSettings.put(PREF_LAST_WS_PATH, path);
1187
        }
1188
        
1189
		public void storeOutputFormat(int selection) {
1190
			dialogSettings.put(PREF_LAST_AO_FORMAT, selection);
1191
		}
1192
1193
		public void storePatchRoot(int selection) {
1194
			dialogSettings.put(PREF_LAST_AO_ROOT, selection);
1195
		}
1196
    }
1197
1198
    protected DirectionSelectionPage directionSelectionPage;
1199
    private LocationPage locationPage;
1200
    private OptionsPage optionsPage;
1201
1202
    protected final DefaultValuesStore defaultValuesStore;
1203
1204
    private DocumentMerger merger;
1205
	private IDocument leftDoc;
1206
    private IDocument rightDoc;
1207
    private String leftPath;
1208
    private String rightPath;
1209
    private boolean rightToLeft;
1210
1211
    private boolean targetFileEdited = false;
1212
1213
    private Text unified_customRelativeText;
1214
    private Button unified_customRelativeOption;
1215
	
1216
	public GenerateDiffFileWizard() {
1217
		super();
1218
		setWindowTitle(CompareMessages.GenerateLocalDiff_title);
1219
		initializeDefaultPageImageDescriptor();
1220
		defaultValuesStore = new DefaultValuesStore();
1221
	}
1222
	
1223
	public GenerateDiffFileWizard(DocumentMerger merger, boolean rightToLeft) {
1224
		this();
1225
		this.merger = merger;
1226
		this.leftDoc = merger.getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
1227
		this.rightDoc = merger.getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
1228
		this.leftPath = merger.getCompareConfiguration().getLeftLabel(leftDoc);
1229
		this.rightPath = merger.getCompareConfiguration().getRightLabel(rightDoc);
1230
		this.rightToLeft = rightToLeft;
1231
	}
1232
1233
    public void addPages() {
1234
        String pageTitle = CompareMessages.GenerateLocalDiff_pageTitle;
1235
        String pageDescription = CompareMessages.GenerateLocalDiff_Specify_the_file_which_contributes_the_changes;
1236
        directionSelectionPage = new DirectionSelectionPage(
1237
				pageTitle,
1238
				pageTitle,
1239
				CompareUIPlugin
1240
						.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF));
1241
        directionSelectionPage.setDescription(pageDescription);
1242
        addPage(directionSelectionPage);
1243
1244
        pageTitle = CompareMessages.GenerateLocalDiff_pageTitle; 
1245
        pageDescription = CompareMessages.GenerateLocalDiff_pageDescription; 
1246
        locationPage = new LocationPage(pageTitle, pageTitle, CompareUIPlugin.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF), defaultValuesStore);
1247
        locationPage.setDescription(pageDescription);
1248
        addPage(locationPage);
1249
1250
        pageTitle = CompareMessages.Advanced_options_19; 
1251
        pageDescription = CompareMessages.Configure_options_diff_command; 
1252
        optionsPage = new OptionsPage(pageTitle, pageTitle, CompareUIPlugin
1253
				.getImageDescriptor(ICompareUIConstants.IMG_WIZBAN_DIFF),
1254
				defaultValuesStore) {
1255
			
1256
			public void setVisible(boolean visible) {
1257
				super.setVisible(visible);
1258
					if (!initialized && visible) {
1259
						if (directionSelectionPage.isRightToLeft()) {
1260
							unified_customRelativeText.setText(leftPath);
1261
						} else {
1262
							unified_customRelativeText.setText(rightPath);
1263
						}				
1264
						targetFileEdited = true;
1265
					}
1266
			}
1267
			
1268
			protected void performSpecificActions() {
1269
				createCustomRelativeControl();
1270
			}
1271
			
1272
			protected void updateEnablements() {
1273
				diffTypeRadioGroup.setEnablement(false, new int[] { FORMAT_CONTEXT,
1274
						FORMAT_STANDARD }, FORMAT_UNIFIED);
1275
				unifiedRadioGroup.setEnablement(false, new int[] {
1276
						ROOT_PROJECT, ROOT_SELECTION, ROOT_WORKSPACE } );
1277
			}
1278
			
1279
	        protected void setEnableUnifiedGroup(boolean enabled) {
1280
	        	unifiedRadioGroup.setEnablement(false, new int[] {
1281
						ROOT_WORKSPACE, ROOT_PROJECT, ROOT_SELECTION });
1282
	        }
1283
		};
1284
		optionsPage.setDescription(pageDescription);
1285
		addPage(optionsPage);
1286
	}
1287
1288
	private void createCustomRelativeControl() {
1289
		Group unifiedGroup = optionsPage.getUnifiedGroup();
1290
		final RadioButtonGroup unifiedRadioGroup = optionsPage.getUnifiedRadioGroup();
1291
		unified_customRelativeOption = new Button(unifiedGroup, SWT.RADIO);
1292
		unified_customRelativeOption.setText(CompareMessages.GenerateDiffFileWizard_13);
1293
		unified_customRelativeOption.setSelection(true);
1294
		unified_customRelativeOption.setLayoutData(new GridData(
1295
				SWT.BEGINNING, SWT.CENTER, false, false, 1, 1));
1296
1297
		unified_customRelativeText = new Text(unifiedGroup, SWT.BORDER);
1298
		unified_customRelativeText.setLayoutData(new GridData(
1299
				SWT.FILL, SWT.CENTER, true, false, 1, 1));
1300
		
1301
		optionsPage.getUnifiedRadioGroup().add(OptionsPage.ROOT_CUSTOM, unified_customRelativeOption);
1302
		unified_customRelativeOption.addSelectionListener(new SelectionAdapter() {
1303
			public void widgetSelected(SelectionEvent e) {
1304
				unifiedRadioGroup.setSelection(OptionsPage.ROOT_CUSTOM, false);
1305
			}
1306
		});
1307
		optionsPage.updateDiffTypeEnablements(new int[] {OptionsPage.FORMAT_CONTEXT, OptionsPage.FORMAT_STANDARD}, OptionsPage.FORMAT_UNIFIED);
1308
		optionsPage.updateUnifiedEnablements(new int[] {OptionsPage.ROOT_PROJECT, OptionsPage.ROOT_WORKSPACE, OptionsPage.ROOT_SELECTION}, OptionsPage.ROOT_CUSTOM);
1309
	}
1310
1311
    /**
1312
     * Declares the wizard banner iamge descriptor
1313
     */
1314
    protected void initializeDefaultPageImageDescriptor() {
1315
        final String iconPath= "icons/full/"; //$NON-NLS-1$
1316
        try {
1317
            final URL installURL = CompareUIPlugin.getDefault().getBundle().getEntry("/"); //$NON-NLS-1$
1318
            final URL url = new URL(installURL, iconPath + "wizards/newconnect_wiz.gif");	//$NON-NLS-1$
1319
            ImageDescriptor desc = ImageDescriptor.createFromURL(url);
1320
            setDefaultPageImageDescriptor(desc);
1321
        } catch (MalformedURLException e) {
1322
            // Should not happen.  Ignore.
1323
        }
1324
    }
1325
    
1326
    /* (Non-javadoc)
1327
     * Method declared on IWizard.
1328
     */
1329
    public boolean needsProgressMonitor() {
1330
        return true;
1331
    }
1332
    
1333
    /**
1334
     * Completes processing of the wizard. If this method returns <code>
1335
     * true</code>, the wizard will close; otherwise, it will stay active.
1336
     */
1337
	public boolean performFinish() {
1338
		final int location = locationPage.getSelectedLocation();
1339
		final File file = location != LocationPage.CLIPBOARD ? locationPage
1340
				.getFile() : null;
1341
1342
		if (!(file == null || validateFile(file))) {
1343
			return false;
1344
		}
1345
		
1346
		//Validation of patch root
1347
		if(optionsPage.getRootSelection() == OptionsPage.ROOT_CUSTOM) {
1348
			String path = optionsPage.getPath();
1349
			IFile file2;
1350
			try {
1351
				file2 = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
1352
			} catch(IllegalArgumentException e) {
1353
				final String title = CompareMessages.GenerateLocalDiff_3;
1354
				final String msg = CompareMessages.GenerateLocalDiff_4;
1355
				final MessageDialog dialog = new MessageDialog(getShell(), title,
1356
						null, msg, MessageDialog.ERROR,
1357
						new String[] { IDialogConstants.OK_LABEL }, 0);
1358
				dialog.open();
1359
				return false;
1360
			}
1361
			if(!validateFile2(file2)) {
1362
				return false;
1363
			}
1364
		}
1365
1366
		// Create the patch
1367
		generateDiffFile(file);
1368
1369
        /**
1370
         * Refresh workspace if necessary and save default selection.
1371
         */
1372
        switch (location) {
1373
        
1374
        case LocationPage.WORKSPACE:
1375
            final String workspaceResource= locationPage.getWorkspaceLocation();
1376
            if (workspaceResource != null){
1377
                defaultValuesStore.storeLocationSelection(LocationPage.WORKSPACE);
1378
	            defaultValuesStore.storeWorkspacePath(workspaceResource);
1379
	           /* try {
1380
	                workspaceResource.getParent().refreshLocal(IResource.DEPTH_ONE, null);
1381
	            } catch(CoreException e) {
1382
	                CVSUIPlugin.openError(getShell(), CVSUIMessages.GenerateCVSDiff_error, null, e); 
1383
	                return false;
1384
	            } */
1385
            } else {
1386
            	//Problem with workspace location, open with clipboard next time 
1387
            	defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
1388
            }
1389
            break;
1390
            
1391
        case LocationPage.FILESYSTEM:
1392
            defaultValuesStore.storeFilesystemPath(file.getPath());
1393
        	defaultValuesStore.storeLocationSelection(LocationPage.FILESYSTEM);
1394
        	break;
1395
        	
1396
        case LocationPage.CLIPBOARD:
1397
            defaultValuesStore.storeLocationSelection(LocationPage.CLIPBOARD);
1398
        	break;
1399
        	
1400
        default:
1401
            return false;
1402
        }
1403
        
1404
1405
		/**
1406
		 * Save default selections of Options Page
1407
		 */
1408
1409
		defaultValuesStore.storeOutputFormat(optionsPage.getFormatSelection());
1410
		defaultValuesStore.storePatchRoot(optionsPage.getRootSelection());
1411
1412
        return true;
1413
    }
1414
1415
	private void generateDiffFile(File file) {
1416
		String toPath, oldPath = null;
1417
		if (targetFileEdited) {
1418
			toPath = optionsPage.getPath();
1419
		} else {
1420
			if(directionSelectionPage.isRightToLeft()){
1421
				toPath = this.rightPath;
1422
			} else {
1423
				toPath = this.leftPath;
1424
			}
1425
		}
1426
		if(directionSelectionPage.isRightToLeft()){
1427
			oldPath = this.leftPath;
1428
		} else {
1429
			oldPath = this.rightPath;
1430
		}
1431
1432
		UnifiedDiffFormatter formatter = new UnifiedDiffFormatter(merger,
1433
				leftDoc, rightDoc, oldPath, toPath, directionSelectionPage
1434
						.isRightToLeft());
1435
		try {
1436
			if (file == null) {
1437
				formatter.generateDiff();
1438
			} else {
1439
				formatter.generateDiff(file);
1440
			}
1441
		} catch (IOException e) {
1442
			throw new RuntimeException(e);
1443
		}
1444
	}
1445
1446
	public boolean validateFile(File file) {
1447
        
1448
        if (file == null)
1449
            return false;
1450
        
1451
        /**
1452
         * Consider file valid if it doesn't exist for now.
1453
         */
1454
        if (!file.exists())
1455
            return true;
1456
        
1457
    	/**
1458
    	 * The file exists.
1459
    	 */
1460
    	if (!file.canWrite()) {
1461
    	    final String title= CompareMessages.GenerateLocalDiff_1; 
1462
    	    final String msg= CompareMessages.GenerateLocalDiff_2; 
1463
    	    final MessageDialog dialog= new MessageDialog(getShell(), title, null, msg, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0);
1464
    	    dialog.open();
1465
    	    return false;
1466
    	}
1467
    	
1468
    	final String title = CompareMessages.GenerateLocalDiff_overwriteTitle; 
1469
    	final String msg = CompareMessages.GenerateLocalDiff_overwriteMsg; 
1470
    	final MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
1471
    	dialog.open();
1472
    	if (dialog.getReturnCode() != 0)            
1473
    	    return false;
1474
    	
1475
    	return true;
1476
    }
1477
	
1478
	public boolean validateFile2(IFile file) {
1479
		if (file == null)
1480
			return false;
1481
1482
		// Consider file invalid if it doesn't exist.
1483
		if (!file.exists()) {
1484
			final String title = CompareMessages.GenerateLocalDiff_3;
1485
			final String msg = CompareMessages.GenerateLocalDiff_4;
1486
			final MessageDialog dialog = new MessageDialog(getShell(), title,
1487
					null, msg, MessageDialog.ERROR,
1488
					new String[] { IDialogConstants.OK_LABEL }, 0);
1489
			dialog.open();
1490
			return false;
1491
		}
1492
		
1493
		return true;
1494
	}
1495
	
1496
	public LocationPage getLocationPage() {
1497
		return locationPage;
1498
	}
1499
1500
	/**
1501
	 * The class maintain proper selection of radio button within the group:
1502
	 * <ul>
1503
	 * <li>Only one button can be selected at the time.</li>
1504
	 * <li>Disabled button can't be selected unless all buttons in the group
1505
	 * are disabled.</li>
1506
	 * </ul>
1507
	 */
1508
	/*private*/ class RadioButtonGroup {
1509
1510
		/**
1511
		 * List of buttons in the group. Both radio groups contain 3 elements.
1512
		 */
1513
		private List buttons = new ArrayList(3);
1514
1515
		/**
1516
		 * Index of the selected button.
1517
		 */
1518
		private int selected = 0;
1519
1520
		/**
1521
		 * Add a button to the group. While adding a new button the method
1522
		 * checks if there is only one button selected in the group.
1523
		 * 
1524
		 * @param buttonCode
1525
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
1526
		 *            an index we need to subtract 1 from it.
1527
		 * @param button
1528
		 *            A button to add.
1529
		 */
1530
		public void add(int buttonCode, Button button) {
1531
			if (button != null && (button.getStyle() & SWT.RADIO) != 0) {
1532
				if (button.getSelection() && !buttons.isEmpty()) {
1533
					deselectAll();
1534
					selected = buttonCode - 1;
1535
				}
1536
				buttons.add(buttonCode - 1, button);
1537
			}
1538
		}
1539
1540
		/**
1541
		 * Returns selected button's code.
1542
		 * 
1543
		 * @return Selected button's code.
1544
		 */
1545
		public int getSelected() {
1546
			return selected + 1;
1547
		}
1548
1549
		/**
1550
		 * Set selection to the given button. When
1551
		 * <code>selectEnabledOnly</code> flag is true the returned value can
1552
		 * differ from the parameter when a button we want to set selection to
1553
		 * is disabled and there are other buttons which are enabled.
1554
		 * 
1555
		 * @param buttonCode
1556
		 *            A button's code (eg. <code>ROOT_WORKSPACE</code>). To get
1557
		 *            an index we need to subtract 1 from it.
1558
		 * @return Code of the button to which selection was finally set.
1559
		 */
1560
		public int setSelection(int buttonCode, boolean selectEnabledOnly) {
1561
			deselectAll();
1562
1563
			((Button) buttons.get(buttonCode - 1)).setSelection(true);
1564
			selected = buttonCode - 1;
1565
			if (selectEnabledOnly)
1566
				selected = selectEnabledOnly() - 1;
1567
			return getSelected();
1568
		}
1569
1570
		/**
1571
		 * Make sure that only an enabled radio button is selected.
1572
		 * 
1573
		 * @return A code of the selected button.
1574
		 */
1575
		public int selectEnabledOnly() {
1576
			deselectAll();
1577
1578
			Button selectedButton = (Button) buttons.get(selected);
1579
			if (!selectedButton.isEnabled()) {
1580
				// if the button is disabled, set selection to an enabled one
1581
				for (Iterator iterator = buttons.iterator(); iterator.hasNext();) {
1582
					Button b = (Button) iterator.next();
1583
					if (b.isEnabled()) {
1584
						b.setSelection(true);
1585
						selected = buttons.indexOf(b);
1586
						return selected + 1;
1587
					}
1588
				}
1589
				// if none found, reset the initial selection
1590
				selectedButton.setSelection(true);
1591
			} else {
1592
				// because selection has been cleared, set it again
1593
				selectedButton.setSelection(true);
1594
			}
1595
			// return selected button's code so the value can be stored
1596
			return getSelected();
1597
		}
1598
1599
		/**
1600
		 * Enable or disable given buttons.
1601
		 * 
1602
		 * @param enabled
1603
		 *            Indicates whether to enable or disable the buttons.
1604
		 * @param buttonsToChange
1605
		 *            Buttons to enable/disable.
1606
		 * @param defaultSelection
1607
		 *            The button to select if the currently selected button
1608
		 *            becomes disabled.
1609
		 */
1610
		public void setEnablement(boolean enabled, int[] buttonsToChange,
1611
				int defaultSelection) {
1612
1613
			// enable (or disable) given buttons
1614
			for (int i = 0; i < buttonsToChange.length; i++) {
1615
				((Button) this.buttons.get(buttonsToChange[i] - 1))
1616
						.setEnabled(enabled);
1617
			}
1618
			// check whether the selected button is enabled
1619
			if (!((Button) this.buttons.get(selected)).isEnabled()) {
1620
				if (defaultSelection != -1)
1621
					// set the default selection and check if it's enabled
1622
					setSelection(defaultSelection, true);
1623
				else
1624
					// no default selection is given, select any enabled button
1625
					selectEnabledOnly();
1626
			}
1627
		}
1628
1629
		/**
1630
		 * Enable or disable given buttons with no default selection. The selection
1631
		 * will be set to an enabled button using the <code>selectEnabledOnly</code> method.
1632
		 * 
1633
		 * @param enabled Indicates whether to enable or disable the buttons.
1634
		 * @param buttonsToChange Buttons to enable/disable.
1635
		 */
1636
		public void setEnablement(boolean enabled, int[] buttonsToChange) {
1637
			// -1 means that no default selection is given
1638
			setEnablement(enabled, buttonsToChange, -1);
1639
		}
1640
1641
		/**
1642
		 * Deselect all buttons in the group.
1643
		 */
1644
		private void deselectAll() {
1645
			// clear all selections
1646
			for (Iterator iterator = buttons.iterator(); iterator.hasNext();)
1647
				((Button) iterator.next()).setSelection(false);
1648
		}
1649
	}
1650
		
1651
}
(-)compare/org/eclipse/compare/internal/CreatePatchAction.java (+39 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
 *     IBM Corportation - initial API and implementation
13
 *******************************************************************************/
14
package org.eclipse.compare.internal;
15
16
import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
17
import org.eclipse.compare.internal.merge.DocumentMerger;
18
import org.eclipse.jface.action.Action;
19
20
21
22
public class CreatePatchAction extends Action {
23
	
24
	private TextMergeViewer viewer;
25
	private boolean rightToLeft;
26
	private DocumentMerger fMerger;
27
28
	public CreatePatchAction(TextMergeViewer viewer,DocumentMerger fMerger, boolean rightToLeft) {
29
		super(CompareMessages.CreatePatchActionTitle);
30
		this.viewer = viewer;
31
		this.rightToLeft = rightToLeft;
32
		this.fMerger= fMerger;
33
	}
34
35
	public void run() {
36
		GenerateDiffFileWizard.run(fMerger,	viewer.getControl().getShell(),	rightToLeft);
37
	}
38
39
}
(-)compare/org/eclipse/compare/internal/UnifiedDiffFormatter.java (+422 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
 *     IBM Corportation - initial API and implementation
13
 *******************************************************************************/
14
package org.eclipse.compare.internal;
15
16
import java.io.ByteArrayOutputStream;
17
import java.io.File;
18
import java.io.FileOutputStream;
19
import java.io.IOException;
20
import java.io.PrintStream;
21
import java.util.ArrayList;
22
import java.util.Arrays;
23
import java.util.Calendar;
24
import java.util.Date;
25
26
import org.eclipse.compare.internal.merge.DocumentMerger;
27
import org.eclipse.compare.internal.merge.DocumentMerger.Diff;
28
import org.eclipse.compare.rangedifferencer.RangeDifference;
29
import org.eclipse.jface.text.BadLocationException;
30
import org.eclipse.jface.text.IDocument;
31
import org.eclipse.swt.dnd.Clipboard;
32
import org.eclipse.swt.dnd.TextTransfer;
33
import org.eclipse.swt.dnd.Transfer;
34
import org.eclipse.swt.widgets.Display;
35
36
import com.ibm.icu.text.DateFormat;
37
38
public class UnifiedDiffFormatter {
39
40
	private static final char RIGHT_CONTRIBUTOR = 'R';
41
	private static final char LEFT_CONTRIBUTOR = 'L';
42
	
43
	private final static int NUMBER_OF_CONTEXT_LINES = 3;
44
45
	public static final String INDEX_MARKER = "Index: "; //$NON-NLS-1$
46
	public static final String DELIMITER = "==================================================================="; //$NON-NLS-1$
47
	public static final String OLD_FILE_PREFIX = "--- "; //$NON-NLS-1$
48
	public static final String NEW_FILE_PREFIX = "+++ "; //$NON-NLS-1$	
49
	public static final String OLD_LINE_PREFIX = "-"; //$NON-NLS-1$
50
	public static final String NEW_LINE_PREFIX = "+"; //$NON-NLS-1$
51
	public static final String CONTEXT_LINE_PREFIX = " "; //$NON-NLS-1$
52
	public static final String RANGE_INFORMATION_PREFIX = "@@ -"; //$NON-NLS-1$
53
	public static final String RANGE_INFORMATION_AFFIX = " @@"; //$NON-NLS-1$
54
55
	private DocumentMerger merger;
56
	private IDocument leftDoc;
57
	private IDocument rightDoc;
58
	private String oldPath;
59
	private String newPath;
60
	private boolean rightToLeft;
61
62
	public UnifiedDiffFormatter(DocumentMerger merger, IDocument leftDoc,
63
			IDocument rightDoc, String oldPath, String newPath, boolean rightToLeft) {
64
		this.merger = merger;
65
		this.leftDoc = leftDoc;
66
		this.rightDoc = rightDoc;
67
		this.oldPath =oldPath;
68
		this.newPath =newPath;
69
		System.out.println(newPath);
70
		this.rightToLeft = rightToLeft;
71
	}
72
73
	/**
74
	 * Generates diff and writes it into the clipboard.
75
	 * 
76
	 * GNU diff command has default line format different than Eclipse has.
77
	 * This issue is the subject of bug 259636.
78
	 * 
79
	 * @throws IOException
80
	 */
81
	public void generateDiff() throws IOException {
82
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
83
		PrintStream ps = new PrintStream(bos);
84
85
		generateDiff(ps);
86
		ps.close();
87
88
		TextTransfer plainTextTransfer = TextTransfer.getInstance();
89
		Clipboard clipboard = new Clipboard(Display.getDefault());
90
		clipboard.setContents(new String[] { bos.toString() },
91
				new Transfer[] { plainTextTransfer });
92
		clipboard.dispose();
93
		bos.close();
94
	}
95
96
	/**
97
	 * Generates diff and writes it into the given file.
98
	 * 
99
	 * GNU diff command has default line format different than Eclipse has.
100
	 * This issue is the subject of bug 259636.
101
	 * 
102
	 * @param file file where diff will be written
103
	 * @throws IOException
104
	 */
105
	public void generateDiff(File file) throws IOException {
106
		FileOutputStream fos = null;
107
		PrintStream ps = null;
108
		try {
109
			fos = new FileOutputStream(file);
110
			try {
111
				ps = new PrintStream(fos);
112
				generateDiff(ps);
113
				if (ps.checkError()) {
114
					throw new IOException("Error while writing patch file: " //$NON-NLS-1$
115
							+ file);
116
				}
117
			} finally {
118
				if (ps != null) {
119
					ps.close();
120
				}
121
			}
122
		} finally {
123
			if (fos != null) {
124
				fos.close();
125
			}
126
		}
127
	}
128
129
	/**
130
	 * Generates diff and writes it into the given output.
131
	 * 
132
	 * GNU diff command has default line format different than Eclipse has.
133
	 * This issue is the subject of bug 259636.
134
	 * 
135
	 * @param output output to which diff will be written 
136
	 */
137
	public void generateDiff(PrintStream output) {
138
		generateDiff(output, false);
139
	}
140
141
	/**
142
	 * Generates diff in the specified format and writes it into the given output.
143
	 * 
144
	 * GNU diff command has default line format different than Eclipse has.
145
	 * This issue is the subject of bug 259636.
146
	 * 
147
	 * @param output output to which diff will be written 
148
	 * @param strictUnixFormat determinates if the format should be fully compatible with the Unix one.
149
	 */
150
	public void generateDiff(PrintStream output, boolean strictUnixFormat) {
151
		ArrayList allDiffs = merger.getAllDiffs();
152
		// If the first block isn't the only one, or first block is different
153
		if (allDiffs.size() > 1 || isPartDifferent(allDiffs, 0)) {
154
			output.println(INDEX_MARKER + oldPath);
155
			output.println(DELIMITER);
156
			Date oldDate = Calendar.getInstance().getTime();
157
			Date newDate = Calendar.getInstance().getTime();
158
			String oldDateFormat = DateFormat.getDateTimeInstance().format(oldDate);
159
			String newDateFormat = DateFormat.getDateTimeInstance().format(newDate);
160
			output.println(OLD_FILE_PREFIX + oldPath + '\t'
161
					+ oldDateFormat + " -0000"); //$NON-NLS-1$
162
			output.println(NEW_FILE_PREFIX + newPath + '\t'
163
					+ newDateFormat + " -0000"); //$NON-NLS-1$
164
165
			boolean firstHunk = true;
166
			Hunk currentHunk = null;
167
168
			int currentLineNumberOld = 0;
169
			int currentLineNumberNew = 0;
170
171
			for (int partNumber = 0; partNumber < allDiffs.size(); partNumber++) {
172
173
				ArrayList oldPart = getPart(partNumber, LEFT_CONTRIBUTOR);
174
				ArrayList newPart = getPart(partNumber, RIGHT_CONTRIBUTOR);
175
176
				if (isPartDifferent(allDiffs, partNumber)) {
177
					// This part has some changes
178
					if (firstHunk) {
179
						// Hunk will start with changed block
180
						currentHunk = new Hunk(0, 0, strictUnixFormat);
181
						firstHunk = false;
182
					}
183
					if (partNumber == (allDiffs.size() - 1)) {
184
						// If it is the last part
185
						currentHunk.addPartRangeToOld(oldPart, 0, oldPart
186
								.size(), true);
187
						currentHunk.addPartRangeToNew(newPart, 0, newPart
188
								.size(), true);
189
					} else {
190
						currentHunk.addPartRangeToOld(oldPart, 0, oldPart
191
								.size(), false);
192
						currentHunk.addPartRangeToNew(newPart, 0, newPart
193
								.size(), false);
194
					}
195
				} else {
196
					if (firstHunk) {
197
						// Hunk will start with context
198
						currentHunk = new Hunk((oldPart.size() - 1) - NUMBER_OF_CONTEXT_LINES,
199
								(oldPart.size() - 1) - NUMBER_OF_CONTEXT_LINES, strictUnixFormat);
200
						firstHunk = false;
201
						currentHunk.addPartRangeToBoth(oldPart,
202
								(oldPart.size() - 1) - NUMBER_OF_CONTEXT_LINES, oldPart.size(), false);
203
					} else {
204
						if (partNumber == (allDiffs.size() - 1)) {
205
							// If it is the last part
206
							currentHunk.addPartRangeToBoth(oldPart, 0, NUMBER_OF_CONTEXT_LINES, true);
207
						} else {
208
							if (oldPart.size() - 1 < 2*NUMBER_OF_CONTEXT_LINES) {
209
								// Context too short to start new hunk
210
								currentHunk.addPartRangeToBoth(oldPart, 0,
211
										oldPart.size(), false);
212
							} else {
213
								// Context long enough to start new hunk
214
								currentHunk.addPartRangeToBoth(oldPart, 0, NUMBER_OF_CONTEXT_LINES,
215
										false);
216
								currentHunk.printTo(output);
217
								currentHunk = new Hunk(currentLineNumberOld
218
										+ (oldPart.size() - 1) - NUMBER_OF_CONTEXT_LINES,
219
										currentLineNumberNew + (oldPart.size() - 1)
220
										- NUMBER_OF_CONTEXT_LINES, strictUnixFormat);
221
								currentHunk.addPartRangeToBoth(oldPart,
222
										(oldPart.size() - 1) - NUMBER_OF_CONTEXT_LINES,
223
										oldPart.size(), false);
224
							}
225
						}
226
					}
227
				}
228
				currentLineNumberOld += oldPart.size();
229
				currentLineNumberNew += newPart.size();
230
			}
231
			// Print the last hunk
232
			currentHunk.printTo(output);
233
		}
234
	}
235
236
	private ArrayList getPart(int nr, char side) {
237
		try {
238
			String s = extract(nr, side).replaceAll("\r\n", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
239
			s.replaceAll("\r", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
240
			ArrayList diffLines = new ArrayList(Arrays
241
					.asList(s.split("\n", -1))); //$NON-NLS-1$
242
			return diffLines;
243
		} catch (BadLocationException e) {
244
			CompareUIPlugin.log(e);
245
		}
246
		return null;
247
	}
248
249
	private String extract(int nr, char side) throws BadLocationException {
250
		Diff diff = ((Diff) merger.getAllDiffs().get(nr));
251
		if (side == LEFT_CONTRIBUTOR && !rightToLeft
252
				|| side == RIGHT_CONTRIBUTOR && rightToLeft) {
253
			return leftDoc.get(diff.getPosition(LEFT_CONTRIBUTOR).offset, diff
254
					.getPosition(LEFT_CONTRIBUTOR).length);
255
		}
256
		return rightDoc.get(diff.getPosition(RIGHT_CONTRIBUTOR).offset, diff
257
				.getPosition(RIGHT_CONTRIBUTOR).length);
258
	}
259
260
	private boolean isPartDifferent(ArrayList allDiffs, int nr) {
261
		Diff diff = ((Diff) allDiffs.get(nr));
262
		if (diff.getKind() == RangeDifference.CHANGE) {
263
			return true;
264
		}
265
		return false;
266
	}
267
268
	private class Hunk {
269
		private int oldStart;
270
		private int oldLength;
271
		private int newStart;
272
		private int newLength;
273
		private boolean strictUnixFormat;
274
		private boolean printNoNewlineMarker;
275
		ArrayList lines;
276
277
		public Hunk(int oldStart, int newStart, boolean strictUnixFormat) {
278
			if (oldStart < 0)
279
				oldStart = 0;
280
			if (newStart < 0)
281
				newStart = 0;
282
			this.oldStart = oldStart;
283
			this.newStart = newStart;
284
			this.oldLength = 0;
285
			this.newLength = 0;
286
			this.strictUnixFormat = strictUnixFormat;
287
			printNoNewlineMarker = false;
288
			lines = new ArrayList();
289
		}
290
291
		public void addPartRangeToOld(ArrayList part, int start, int end,
292
				boolean lastPart) {
293
			if (start < 0)
294
				start = 0;
295
			if (strictUnixFormat) {
296
				//in strictUnixFormat, if last line ends with newline character
297
				//add additional empty line
298
				if ((lastPart) && part.size() != 1)
299
					end = Math.min(end, part.size());
300
				else
301
					end = Math.min(end, part.size() - 1);
302
				for (int lineNr = start; lineNr < end; lineNr++) {
303
					lines.add(OLD_LINE_PREFIX + part.get(lineNr));
304
					oldLength++;
305
				}
306
			}
307
			else {
308
				//in not strictUnixFormat, if last line doesn't end with newline character
309
				//add an marker saying about this 
310
				end = Math.min(end, part.size() - 1);
311
				for (int lineNr = start; lineNr < end; lineNr++) {
312
					lines.add(OLD_LINE_PREFIX + part.get(lineNr));
313
					oldLength++;
314
				}
315
				if (!part.get(part.size() - 1).toString().equals(""))	//$NON-NLS-1$
316
				{
317
					//part doesn't end with newline character
318
					//don't cut the last line, because it isn't empty
319
					lines.add(OLD_LINE_PREFIX + part.get(part.size() - 1));
320
					oldLength++;
321
					printNoNewlineMarker = true;
322
				}
323
			}
324
		}
325
326
		public void addPartRangeToNew(ArrayList part, int start, int end,
327
				boolean lastPart) {
328
			if (start < 0)
329
				start = 0;
330
			if (strictUnixFormat) {
331
				//in strictUnixFormat, if last line ends with newline character
332
				//add additional empty line
333
				if ((lastPart) && part.size() != 1)
334
					end = Math.min(end, part.size());
335
				else
336
					end = Math.min(end, part.size() - 1);
337
				for (int lineNr = start; lineNr < end; lineNr++) {
338
					lines.add(NEW_LINE_PREFIX + part.get(lineNr));
339
					newLength++;
340
				}
341
			}
342
			else {
343
				//in not strictUnixFormat, if last line doesn't end with newline character
344
				//add an marker saying about this 
345
				end = Math.min(end, part.size() - 1);
346
				for (int lineNr = start; lineNr < end; lineNr++) {
347
					lines.add(NEW_LINE_PREFIX + part.get(lineNr));
348
					newLength++;
349
				}
350
				if (!part.get(part.size() - 1).toString().equals("")) {	//$NON-NLS-1$
351
					//part doesn't end with newline character
352
					//don't cut the last line, because it isn't empty
353
					lines.add(NEW_LINE_PREFIX + part.get(part.size() - 1));
354
					newLength++;
355
					printNoNewlineMarker = true;
356
				}
357
			}
358
		}
359
360
		public void addPartRangeToBoth(ArrayList part, int start, int end,
361
				boolean lastPart) {
362
			if (start < 0)
363
				start = 0;
364
			if (strictUnixFormat) {
365
				//in strictUnixFormat, if last line ends with newline character
366
				//add additional empty line
367
				if (lastPart)
368
					end = Math.min(end, part.size());
369
				else
370
					end = Math.min(end, part.size() - 1);
371
				for (int lineNr = start; lineNr < end; lineNr++) {
372
					lines.add(CONTEXT_LINE_PREFIX + part.get(lineNr));
373
					oldLength++;
374
					newLength++;
375
				}
376
			}
377
			else {
378
				//in not strictUnixFormat, if last line doesn't end with newline character
379
				//add an marker saying about this 
380
				end = Math.min(end, part.size() - 1);
381
				for (int lineNr = start; lineNr < end; lineNr++) {
382
					lines.add(CONTEXT_LINE_PREFIX + part.get(lineNr));
383
					oldLength++;
384
					newLength++;
385
				}
386
				if (!part.get(part.size() - 1).toString().equals("")) {	//$NON-NLS-1$
387
					//part doesn't end with newline character
388
					//don't cut the last line, because it isn't empty
389
					lines.add(CONTEXT_LINE_PREFIX + part.get(part.size() - 1));
390
					oldLength++;
391
					newLength++;
392
					printNoNewlineMarker = true;
393
				}
394
			}
395
		}
396
397
		private void printMarkerTo(PrintStream output) {
398
			if (oldLength == 0)	
399
			{
400
				//all lines are new lines
401
				oldStart = -1;
402
			}
403
			if (newLength == 0) {
404
				//all lines are old lines
405
				newStart = -1;
406
			}
407
			output.println(RANGE_INFORMATION_PREFIX + (oldStart+1) + "," + oldLength + " +" + (newStart+1) //$NON-NLS-1$ //$NON-NLS-2$
408
					+ "," + newLength + RANGE_INFORMATION_AFFIX); //$NON-NLS-1$
409
		}
410
411
		public void printTo(PrintStream output) {
412
			printMarkerTo(output);
413
			for (int i = 0; i < lines.size(); i++) {
414
				output.println(lines.get(i));
415
			}
416
			if (printNoNewlineMarker) {
417
				output.println("\\ No newline at end of file");	//$NON-NLS-1$
418
			}
419
		}
420
	}
421
422
}

Return to bug 71374