Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 273450 | Differences between
and this patch

Collapse All | Expand All

(-)compare/org/eclipse/compare/CompareEditorInput.java (-29 / +87 lines)
Lines 14-19 Link Here
14
import java.util.ArrayList;
14
import java.util.ArrayList;
15
import java.util.ResourceBundle;
15
import java.util.ResourceBundle;
16
16
17
import org.eclipse.compare.contentmergeviewer.ContentMergeViewer;
17
import org.eclipse.compare.contentmergeviewer.IFlushable;
18
import org.eclipse.compare.contentmergeviewer.IFlushable;
18
import org.eclipse.compare.internal.BinaryCompareViewer;
19
import org.eclipse.compare.internal.BinaryCompareViewer;
19
import org.eclipse.compare.internal.ChangePropertyAction;
20
import org.eclipse.compare.internal.ChangePropertyAction;
Lines 192-199 Link Here
192
	private String fTitle;
193
	private String fTitle;
193
	private ListenerList fListenerList= new ListenerList();
194
	private ListenerList fListenerList= new ListenerList();
194
	private CompareNavigator fNavigator;
195
	private CompareNavigator fNavigator;
195
	private boolean fDirty= false;
196
	private ArrayList fLeftDirtyViewers = new ArrayList();
196
	private ArrayList fDirtyViewers= new ArrayList();
197
	private ArrayList fRightDirtyViewers = new ArrayList();
197
	private IPropertyChangeListener fDirtyStateListener;
198
	private IPropertyChangeListener fDirtyStateListener;
198
	
199
	
199
	boolean fStructureCompareOnSingleClick= true;
200
	boolean fStructureCompareOnSingleClick= true;
Lines 1015-1032 Link Here
1015
	}
1016
	}
1016
	
1017
	
1017
	/**
1018
	/**
1018
	 * Returns <code>true</code> if there are unsaved changes.
1019
	 * Returns <code>true</code> if there are unsaved changes in either left or
1019
	 * The value returned is the value of the <code>DIRTY_STATE</code> property of this input object.
1020
	 * right side. The value returned is the value of the
1020
	 
1021
	 * <code>DIRTY_STATE</code> property of this input object.
1021
	 * Returns <code>true</code> if this input has unsaved changes,
1022
	 * 
1022
	 * that is if <code>setDirty(true)</code> has been called.
1023
	 * Returns <code>true</code> if left or right side has unsaved changes
1023
	 * Subclasses don't have to override if the functionality provided by <code>setDirty</code>
1024
	 * Subclasses don't have to override if the functionality provided by
1024
	 * is sufficient.
1025
	 * <code>setDirty</code> is sufficient.
1025
	 *
1026
	 * 
1026
	 * @return <code>true</code> if there are changes that need to be saved
1027
	 * @return <code>true</code> if there are changes that need to be saved
1027
	 */
1028
	 */
1028
	public boolean isSaveNeeded() {
1029
	public boolean isSaveNeeded() {
1029
		return fDirty || fDirtyViewers.size() > 0;
1030
		return isLeftSaveNeeded() || isRightSaveNeeded();
1031
	}
1032
1033
	/**
1034
	 * Returns <code>true</code> if there are unsaved changes for left side.
1035
	 * 
1036
	 * @return <code>true</code> if there are changes that need to be saved
1037
	 */
1038
	protected boolean isLeftSaveNeeded() {
1039
		return fLeftDirtyViewers.size() > 0;
1040
	}
1041
1042
	/**
1043
	 * Returns <code>true</code> if there are unsaved changes for right side.
1044
	 * 
1045
	 * @return <code>true</code> if there are changes that need to be saved
1046
	 */
1047
	protected boolean isRightSaveNeeded() {
1048
		return fRightDirtyViewers.size() > 0;
1030
	}
1049
	}
1031
	
1050
	
1032
	/**
1051
	/**
Lines 1043-1073 Link Here
1043
	}
1062
	}
1044
		
1063
		
1045
	/**
1064
	/**
1046
	 * Sets the dirty state of this input to the given
1065
	 * Sets the dirty state of this input to the given value and sends out a
1047
	 * value and sends out a <code>PropertyChangeEvent</code> if the new value differs from the old value.
1066
	 * <code>PropertyChangeEvent</code> if the new value differs from the old
1048
	 *
1067
	 * value. Direct calling this method with parameter dirty equal to
1049
	 * @param dirty the dirty state for this compare input
1068
	 * <code>false</code> when there are unsaved changes in viewers, results in
1069
	 * inconsistent state. The dirty state of compare input should be based only
1070
	 * on the information if there are changes in viewers for left or right
1071
	 * side.
1072
	 * 
1073
	 * @param dirty
1074
	 *            the dirty state for this compare input
1050
	 */
1075
	 */
1051
	public void setDirty(boolean dirty) {
1076
	public void setDirty(boolean dirty) {
1052
		boolean oldDirty = fDirty || fDirtyViewers.size() > 0;
1077
		boolean oldDirty = isSaveNeeded();
1053
		fDirty= dirty;
1078
		boolean newDirty = dirty || isSaveNeeded();
1054
		if (!fDirty)
1079
		if (!newDirty) {
1055
			fDirtyViewers.clear();
1080
			fLeftDirtyViewers.clear();
1056
		if (oldDirty != dirty)
1081
			fRightDirtyViewers.clear();
1057
			Utilities.firePropertyChange(fListenerList, this, DIRTY_STATE, Boolean.valueOf(oldDirty), Boolean.valueOf(dirty));
1082
		}
1083
		if (oldDirty != isSaveNeeded()) {
1084
			Utilities.firePropertyChange(fListenerList, this, DIRTY_STATE, Boolean.valueOf(oldDirty), Boolean.valueOf(isSaveNeeded()));
1085
		}
1058
	}
1086
	}
1059
	
1087
	
1088
	/**
1089
	 * Method adds or removes viewers that changed left or right side of this
1090
	 * compare input. Any modification of any of the list of viewers may result
1091
	 * in dirty state change.
1092
	 * 
1093
	 * @param source
1094
	 *            the object that fired <code>PropertyChangeEvent</code>
1095
	 *            modifying the dirty state
1096
	 * @param dirty
1097
	 *            value that describes if the changes were added or removed
1098
	 */
1060
	private void setDirty(Object source, boolean dirty) {
1099
	private void setDirty(Object source, boolean dirty) {
1061
		Assert.isNotNull(source);
1100
		Assert.isNotNull(source);
1062
		boolean oldDirty= fDirty || fDirtyViewers.size() > 0;
1101
		boolean oldDirty = isSaveNeeded();
1063
		if (dirty)
1102
		ContentMergeViewer cmv = (ContentMergeViewer) source;
1064
			fDirtyViewers.add(source);
1103
		if (dirty) {
1065
		else
1104
			if (cmv.isLeftDirty()) {
1066
			fDirtyViewers.remove(source);
1105
				if (!fLeftDirtyViewers.contains(source)) {
1067
		boolean newDirty= fDirty || fDirtyViewers.size() > 0;
1106
					fLeftDirtyViewers.add(source);
1068
		if (DEBUG) System.out.println("setDirty("+source+", "+dirty+"): " + newDirty); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1107
				}
1069
		if (oldDirty != newDirty)
1108
			}
1109
			if (cmv.isRightDirty()) {
1110
				if (!fRightDirtyViewers.contains(source)) {
1111
					fRightDirtyViewers.add(source);
1112
				}
1113
			}
1114
		} else {
1115
			if (!cmv.isLeftDirty()) {
1116
				fLeftDirtyViewers.remove(source);
1117
			}
1118
			if (!cmv.isRightDirty()) {
1119
				fRightDirtyViewers.remove(source);
1120
			}
1121
		}
1122
		boolean newDirty = isSaveNeeded();
1123
		if (DEBUG) {
1124
			System.out.println("setDirty(" + source + ", " + dirty + "): " + newDirty); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1125
		}
1126
		if (oldDirty != newDirty) {
1070
			Utilities.firePropertyChange(fListenerList, this, DIRTY_STATE, Boolean.valueOf(oldDirty), Boolean.valueOf(newDirty));
1127
			Utilities.firePropertyChange(fListenerList, this, DIRTY_STATE, Boolean.valueOf(oldDirty), Boolean.valueOf(newDirty));
1128
		}
1071
	}
1129
	}
1072
	
1130
	
1073
	/* (non Javadoc)
1131
	/* (non Javadoc)
(-)compare/org/eclipse/compare/contentmergeviewer/ContentMergeViewer.java (-8 / +6 lines)
Lines 1168-1176 Link Here
1168
	protected void setLeftDirty(boolean dirty) {
1168
	protected void setLeftDirty(boolean dirty) {
1169
		if (isLeftDirty() != dirty) {
1169
		if (isLeftDirty() != dirty) {
1170
			fIsLeftDirty = dirty;
1170
			fIsLeftDirty = dirty;
1171
			// Only fire the event if the combined dirty state has changed
1171
			// Always fire the event if the dirty state has changed
1172
			if (!isRightDirty())
1172
			fireDirtyState(dirty);
1173
				fireDirtyState(dirty);
1174
		}
1173
		}
1175
	}
1174
	}
1176
	
1175
	
Lines 1186-1194 Link Here
1186
	protected void setRightDirty(boolean dirty) {
1185
	protected void setRightDirty(boolean dirty) {
1187
		if (isRightDirty() != dirty) {
1186
		if (isRightDirty() != dirty) {
1188
			fIsRightDirty = dirty;
1187
			fIsRightDirty = dirty;
1189
			// Only fire the event if the combined dirty state has changed
1188
			// Always fire the event if the dirty state has changed
1190
			if (!isLeftDirty())
1189
			fireDirtyState(dirty);
1191
				fireDirtyState(dirty);
1192
		}
1190
		}
1193
	}
1191
	}
1194
	
1192
	
Lines 1256-1262 Link Here
1256
	 * @return the dirty state of the right side of this viewer
1254
	 * @return the dirty state of the right side of this viewer
1257
	 * @since 3.3
1255
	 * @since 3.3
1258
	 */
1256
	 */
1259
	protected boolean isRightDirty() {
1257
	public boolean isRightDirty() {
1260
		return fIsRightDirty;
1258
		return fIsRightDirty;
1261
	}
1259
	}
1262
1260
Lines 1265-1271 Link Here
1265
	 * @return the dirty state of the left side of this viewer
1263
	 * @return the dirty state of the left side of this viewer
1266
	 * @since 3.3
1264
	 * @since 3.3
1267
	 */
1265
	 */
1268
	protected boolean isLeftDirty() {
1266
	public boolean isLeftDirty() {
1269
		return fIsLeftDirty;
1267
		return fIsLeftDirty;
1270
	}
1268
	}
1271
1269
(-)src/org/eclipse/compare/tests/ContentMergeViewerTest.java (-6 / +13 lines)
Lines 21-26 Link Here
21
public class ContentMergeViewerTest extends TestCase {
21
public class ContentMergeViewerTest extends TestCase {
22
22
23
	private MyContentMergeViewer myContentMergeViewer;
23
	private MyContentMergeViewer myContentMergeViewer;
24
	/**
25
	 * result[0]-event occurred or not; result[1]-new state that was set
26
	 */
24
	boolean[] result = new boolean[] { false, false };
27
	boolean[] result = new boolean[] { false, false };
25
28
26
	public ContentMergeViewerTest() {
29
	public ContentMergeViewerTest() {
Lines 40-50 Link Here
40
		public boolean leftDirty = false;
43
		public boolean leftDirty = false;
41
		public boolean rightDirty = false;
44
		public boolean rightDirty = false;
42
45
43
		protected boolean isLeftDirty() {
46
		public boolean isLeftDirty() {
44
			return leftDirty;
47
			return leftDirty;
45
		}
48
		}
46
49
47
		protected boolean isRightDirty() {
50
		public boolean isRightDirty() {
48
			return rightDirty;
51
			return rightDirty;
49
		}
52
		}
50
53
Lines 109-115 Link Here
109
		myContentMergeViewer.rightDirty = true;
112
		myContentMergeViewer.rightDirty = true;
110
		myContentMergeViewer.setLeftDirty(true);
113
		myContentMergeViewer.setLeftDirty(true);
111
114
112
		Assert.assertEquals(false, result[0]);
115
		Assert.assertEquals(true, result[0]);
116
		Assert.assertEquals(true, result[1]);
113
	}
117
	}
114
118
115
	public void testTFTX() {
119
	public void testTFTX() {
Lines 160-166 Link Here
160
		myContentMergeViewer.rightDirty = true;
164
		myContentMergeViewer.rightDirty = true;
161
		myContentMergeViewer.setLeftDirty(false);
165
		myContentMergeViewer.setLeftDirty(false);
162
166
163
		Assert.assertEquals(false, result[0]);
167
		Assert.assertEquals(true, result[0]);
168
		Assert.assertEquals(false, result[1]);
164
	}
169
	}
165
170
166
	// set right to true
171
	// set right to true
Lines 187-193 Link Here
187
		myContentMergeViewer.rightDirty = false;
192
		myContentMergeViewer.rightDirty = false;
188
		myContentMergeViewer.setRightDirty(true);
193
		myContentMergeViewer.setRightDirty(true);
189
194
190
		Assert.assertEquals(false, result[0]);
195
		Assert.assertEquals(true, result[0]);
196
		Assert.assertEquals(true, result[1]);
191
	}
197
	}
192
198
193
	public void testTTXT() {
199
	public void testTTXT() {
Lines 230-235 Link Here
230
		myContentMergeViewer.rightDirty = true;
236
		myContentMergeViewer.rightDirty = true;
231
		myContentMergeViewer.setRightDirty(false);
237
		myContentMergeViewer.setRightDirty(false);
232
238
233
		Assert.assertEquals(false, result[0]);
239
		Assert.assertEquals(true, result[0]);
240
		Assert.assertEquals(false, result[1]);
234
	}
241
	}
235
}
242
}
(-)src/org/eclipse/team/internal/ui/synchronize/LocalResourceSaveableComparison.java (+15 lines)
Lines 206-211 Link Here
206
	public boolean isDirty() {
206
	public boolean isDirty() {
207
		// We need to get the dirty state from the compare editor input
207
		// We need to get the dirty state from the compare editor input
208
		// since it is our only connection to the merge viewer
208
		// since it is our only connection to the merge viewer
209
		if (editorInput instanceof SaveablesCompareEditorInput) {
210
			return ((SaveablesCompareEditorInput) editorInput).isSaveNeeded(this);
211
		}
209
		return editorInput.isSaveNeeded();
212
		return editorInput.isSaveNeeded();
210
	}
213
	}
211
	
214
	
Lines 232-237 Link Here
232
	 * @see org.eclipse.ui.Saveable#getName()
235
	 * @see org.eclipse.ui.Saveable#getName()
233
	 */
236
	 */
234
	public String getName() {
237
	public String getName() {
238
		// When we compare two files with each other we need to know the exact
239
		// name of each of the files, not the name taken from the input. Input
240
		// gives the name based on the main element of the input. The way how
241
		// the main element is calculated is described in method
242
		// org.eclipse.team.internal.ui.mapping.AbstractCompareInput#getMainElement()
243
		// See bug 273450.
244
		if (fileElement.equals(input.getLeft())) {
245
			return input.getLeft().getName();
246
		}
247
		if (fileElement.equals(input.getRight())) {
248
			return input.getRight().getName();
249
		}
235
		return input.getName();
250
		return input.getName();
236
	}
251
	}
237
252
(-)src/org/eclipse/team/internal/ui/synchronize/SaveablesCompareEditorInput.java (+21 lines)
Lines 357-362 Link Here
357
		return super.isDirty();
357
		return super.isDirty();
358
	}
358
	}
359
359
360
	public boolean isSaveNeeded(Saveable arg) {
361
		// Method gives information if the Saveable given as a parameter needs
362
		// to be saved. Parameter arg can be either equal to fLeftSaveable or to
363
		// fRightSaveable. If the parameter is null or differs from both left
364
		// and right Saveable then default isSaveNeeded() is called. Default
365
		// method isSaveNeeded() is not aware which Saveable we wish to check
366
		// therefore it returns the state of the whole CompareEditorInput.
367
		// Whenever possible this method should be called instead of default
368
		// isSaveNeeded(). See bug 273450.
369
		if (arg == null) {
370
			return isSaveNeeded();
371
		}
372
		if (arg.equals(fLeftSaveable)) {
373
			return isLeftSaveNeeded();
374
		}
375
		if (arg.equals(fRightSaveable)) {
376
			return isRightSaveNeeded();
377
		}
378
		return isSaveNeeded();
379
	}
380
	
360
	/**
381
	/**
361
	 * Close the editor if it is not dirty. If it is still dirty, let the
382
	 * Close the editor if it is not dirty. If it is still dirty, let the
362
	 * content merge viewer handle the compare input change.
383
	 * content merge viewer handle the compare input change.

Return to bug 273450