|
Lines 25-40
Link Here
|
| 25 |
import org.eclipse.compare.internal.CompareHandlerService; |
25 |
import org.eclipse.compare.internal.CompareHandlerService; |
| 26 |
import org.eclipse.compare.internal.CompareMessages; |
26 |
import org.eclipse.compare.internal.CompareMessages; |
| 27 |
import org.eclipse.compare.internal.ICompareUIConstants; |
27 |
import org.eclipse.compare.internal.ICompareUIConstants; |
|
|
28 |
import org.eclipse.compare.internal.IFlushable2; |
| 29 |
import org.eclipse.compare.internal.ISavingSaveable; |
| 28 |
import org.eclipse.compare.internal.MergeViewerContentProvider; |
30 |
import org.eclipse.compare.internal.MergeViewerContentProvider; |
| 29 |
import org.eclipse.compare.internal.Utilities; |
31 |
import org.eclipse.compare.internal.Utilities; |
| 30 |
import org.eclipse.compare.internal.ViewerSwitchingCancelled; |
32 |
import org.eclipse.compare.internal.ViewerSwitchingCancelled; |
| 31 |
import org.eclipse.compare.structuremergeviewer.Differencer; |
33 |
import org.eclipse.compare.structuremergeviewer.Differencer; |
| 32 |
import org.eclipse.compare.structuremergeviewer.ICompareInput; |
34 |
import org.eclipse.compare.structuremergeviewer.ICompareInput; |
| 33 |
import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; |
35 |
import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; |
| 34 |
import org.eclipse.core.commands.ExecutionEvent; |
|
|
| 35 |
import org.eclipse.core.commands.ExecutionException; |
| 36 |
import org.eclipse.core.commands.IExecutionListener; |
| 37 |
import org.eclipse.core.commands.NotHandledException; |
| 38 |
import org.eclipse.core.runtime.Assert; |
36 |
import org.eclipse.core.runtime.Assert; |
| 39 |
import org.eclipse.core.runtime.CoreException; |
37 |
import org.eclipse.core.runtime.CoreException; |
| 40 |
import org.eclipse.core.runtime.IProgressMonitor; |
38 |
import org.eclipse.core.runtime.IProgressMonitor; |
|
Lines 71-79
Link Here
|
| 71 |
import org.eclipse.swt.widgets.Layout; |
69 |
import org.eclipse.swt.widgets.Layout; |
| 72 |
import org.eclipse.swt.widgets.Sash; |
70 |
import org.eclipse.swt.widgets.Sash; |
| 73 |
import org.eclipse.swt.widgets.Shell; |
71 |
import org.eclipse.swt.widgets.Shell; |
| 74 |
import org.eclipse.ui.IWorkbenchCommandConstants; |
72 |
import org.eclipse.ui.ISaveablesSource; |
| 75 |
import org.eclipse.ui.PlatformUI; |
73 |
import org.eclipse.ui.IWorkbenchPart; |
| 76 |
import org.eclipse.ui.commands.ICommandService; |
74 |
import org.eclipse.ui.Saveable; |
| 77 |
|
75 |
|
| 78 |
/** |
76 |
/** |
| 79 |
* An abstract compare and merge viewer with two side-by-side content areas |
77 |
* An abstract compare and merge viewer with two side-by-side content areas |
|
Lines 102-108
Link Here
|
| 102 |
* @see TextMergeViewer |
100 |
* @see TextMergeViewer |
| 103 |
*/ |
101 |
*/ |
| 104 |
public abstract class ContentMergeViewer extends ContentViewer |
102 |
public abstract class ContentMergeViewer extends ContentViewer |
| 105 |
implements IPropertyChangeNotifier, IFlushable { |
103 |
implements IPropertyChangeNotifier, IFlushable, IFlushable2 { |
| 106 |
|
104 |
|
| 107 |
/* package */ static final int HORIZONTAL= 1; |
105 |
/* package */ static final int HORIZONTAL= 1; |
| 108 |
/* package */ static final int VERTICAL= 2; |
106 |
/* package */ static final int VERTICAL= 2; |
|
Lines 295-304
Link Here
|
| 295 |
private boolean fIsLeftDirty; |
293 |
private boolean fIsLeftDirty; |
| 296 |
private boolean fIsRightDirty; |
294 |
private boolean fIsRightDirty; |
| 297 |
|
295 |
|
| 298 |
private boolean fIsSaving; |
|
|
| 299 |
private ICommandService fCommandService; |
| 300 |
private IExecutionListener fExecutionListener; |
| 301 |
|
| 302 |
private CompareHandlerService fHandlerService; |
296 |
private CompareHandlerService fHandlerService; |
| 303 |
|
297 |
|
| 304 |
// SWT widgets |
298 |
// SWT widgets |
|
Lines 371-413
Link Here
|
| 371 |
|
365 |
|
| 372 |
fIsLeftDirty = false; |
366 |
fIsLeftDirty = false; |
| 373 |
fIsRightDirty = false; |
367 |
fIsRightDirty = false; |
| 374 |
|
|
|
| 375 |
fIsSaving = false; |
| 376 |
fCommandService = (ICommandService)PlatformUI.getWorkbench().getAdapter(ICommandService.class); |
| 377 |
if (fCommandService != null) { |
| 378 |
fCommandService.addExecutionListener(getExecutionListener()); |
| 379 |
} |
| 380 |
} |
368 |
} |
| 381 |
|
369 |
|
| 382 |
private IExecutionListener getExecutionListener() { |
|
|
| 383 |
if (fExecutionListener == null) { |
| 384 |
fExecutionListener = new IExecutionListener() { |
| 385 |
public void preExecute(String commandId, ExecutionEvent event) { |
| 386 |
if (IWorkbenchCommandConstants.FILE_SAVE.equals(commandId) |
| 387 |
|| IWorkbenchCommandConstants.FILE_SAVE_ALL.equals(commandId)) |
| 388 |
fIsSaving = true; |
| 389 |
} |
| 390 |
|
| 391 |
public void postExecuteSuccess(String commandId, Object returnValue) { |
| 392 |
if (IWorkbenchCommandConstants.FILE_SAVE.equals(commandId) |
| 393 |
|| IWorkbenchCommandConstants.FILE_SAVE_ALL.equals(commandId)) |
| 394 |
fIsSaving= false; |
| 395 |
} |
| 396 |
|
| 397 |
public void postExecuteFailure(String commandId, ExecutionException exception) { |
| 398 |
if (IWorkbenchCommandConstants.FILE_SAVE.equals(commandId) |
| 399 |
|| IWorkbenchCommandConstants.FILE_SAVE_ALL.equals(commandId)) |
| 400 |
fIsSaving= false; |
| 401 |
} |
| 402 |
|
| 403 |
public void notHandled(String commandId, NotHandledException exception) { |
| 404 |
// not needed |
| 405 |
} |
| 406 |
}; |
| 407 |
} |
| 408 |
return fExecutionListener; |
| 409 |
} |
| 410 |
|
| 411 |
//---- hooks --------------------- |
370 |
//---- hooks --------------------- |
| 412 |
|
371 |
|
| 413 |
/** |
372 |
/** |
|
Lines 1037-1048
Link Here
|
| 1037 |
fHVSashCursor= null; |
996 |
fHVSashCursor= null; |
| 1038 |
} |
997 |
} |
| 1039 |
|
998 |
|
| 1040 |
if (fCommandService != null) { |
|
|
| 1041 |
fCommandService.removeExecutionListener(fExecutionListener); |
| 1042 |
fCommandService = null; |
| 1043 |
fExecutionListener = null; |
| 1044 |
} |
| 1045 |
|
| 1046 |
super.handleDispose(event); |
999 |
super.handleDispose(event); |
| 1047 |
} |
1000 |
} |
| 1048 |
|
1001 |
|
|
Lines 1168-1176
Link Here
|
| 1168 |
protected void setLeftDirty(boolean dirty) { |
1121 |
protected void setLeftDirty(boolean dirty) { |
| 1169 |
if (isLeftDirty() != dirty) { |
1122 |
if (isLeftDirty() != dirty) { |
| 1170 |
fIsLeftDirty = dirty; |
1123 |
fIsLeftDirty = dirty; |
| 1171 |
// Only fire the event if the combined dirty state has changed |
1124 |
// Always fire the event if the dirty state has changed |
| 1172 |
if (!isRightDirty()) |
1125 |
fireDirtyState(dirty); |
| 1173 |
fireDirtyState(dirty); |
|
|
| 1174 |
} |
1126 |
} |
| 1175 |
} |
1127 |
} |
| 1176 |
|
1128 |
|
|
Lines 1186-1194
Link Here
|
| 1186 |
protected void setRightDirty(boolean dirty) { |
1138 |
protected void setRightDirty(boolean dirty) { |
| 1187 |
if (isRightDirty() != dirty) { |
1139 |
if (isRightDirty() != dirty) { |
| 1188 |
fIsRightDirty = dirty; |
1140 |
fIsRightDirty = dirty; |
| 1189 |
// Only fire the event if the combined dirty state has changed |
1141 |
// Always fire the event if the dirty state has changed |
| 1190 |
if (!isLeftDirty()) |
1142 |
fireDirtyState(dirty); |
| 1191 |
fireDirtyState(dirty); |
|
|
| 1192 |
} |
1143 |
} |
| 1193 |
} |
1144 |
} |
| 1194 |
|
1145 |
|
|
Lines 1215-1221
Link Here
|
| 1215 |
public final void flush(IProgressMonitor monitor) { |
1166 |
public final void flush(IProgressMonitor monitor) { |
| 1216 |
flushContent(getInput(), monitor); |
1167 |
flushContent(getInput(), monitor); |
| 1217 |
} |
1168 |
} |
| 1218 |
|
1169 |
|
| 1219 |
/** |
1170 |
/** |
| 1220 |
* Flush the modified content back to input elements via the content provider. |
1171 |
* Flush the modified content back to input elements via the content provider. |
| 1221 |
* The provided input may be the current input of the viewer or it may be |
1172 |
* The provided input may be the current input of the viewer or it may be |
|
Lines 1227-1257
Link Here
|
| 1227 |
* @since 3.3 |
1178 |
* @since 3.3 |
| 1228 |
*/ |
1179 |
*/ |
| 1229 |
protected void flushContent(Object input, IProgressMonitor monitor) { |
1180 |
protected void flushContent(Object input, IProgressMonitor monitor) { |
| 1230 |
|
1181 |
flushLeftSide(input, monitor); |
| 1231 |
// write back modified contents |
1182 |
flushRightSide(input, monitor); |
| 1232 |
IMergeViewerContentProvider content= (IMergeViewerContentProvider) getContentProvider(); |
1183 |
} |
| 1233 |
|
1184 |
|
| 1234 |
boolean leftEmpty= content.getLeftContent(input) == null; |
1185 |
|
| 1235 |
boolean rightEmpty= content.getRightContent(input) == null; |
1186 |
void flushLeftSide(Object input, IProgressMonitor monitor) { |
|
|
1187 |
IMergeViewerContentProvider content = (IMergeViewerContentProvider) getContentProvider(); |
| 1188 |
|
| 1189 |
boolean rightEmpty = content.getRightContent(input) == null; |
| 1236 |
|
1190 |
|
| 1237 |
if (getCompareConfiguration().isLeftEditable() && isLeftDirty()) { |
1191 |
if (getCompareConfiguration().isLeftEditable() && isLeftDirty()) { |
| 1238 |
byte[] bytes= getContents(true); |
1192 |
byte[] bytes = getContents(true); |
| 1239 |
if (rightEmpty && bytes != null && bytes.length == 0) |
1193 |
if (rightEmpty && bytes != null && bytes.length == 0) |
| 1240 |
bytes= null; |
1194 |
bytes = null; |
| 1241 |
setLeftDirty(false); |
1195 |
setLeftDirty(false); |
| 1242 |
content.saveLeftContent(input, bytes); |
1196 |
content.saveLeftContent(input, bytes); |
| 1243 |
} |
1197 |
} |
| 1244 |
|
1198 |
} |
|
|
1199 |
|
| 1200 |
void flushRightSide(Object input, IProgressMonitor monitor) { |
| 1201 |
IMergeViewerContentProvider content = (IMergeViewerContentProvider) getContentProvider(); |
| 1202 |
|
| 1203 |
boolean leftEmpty = content.getLeftContent(input) == null; |
| 1204 |
|
| 1245 |
if (getCompareConfiguration().isRightEditable() && isRightDirty()) { |
1205 |
if (getCompareConfiguration().isRightEditable() && isRightDirty()) { |
| 1246 |
byte[] bytes= getContents(false); |
1206 |
byte[] bytes = getContents(false); |
| 1247 |
if (leftEmpty && bytes != null && bytes.length == 0) |
1207 |
if (leftEmpty && bytes != null && bytes.length == 0) |
| 1248 |
bytes= null; |
1208 |
bytes = null; |
| 1249 |
setRightDirty(false); |
1209 |
setRightDirty(false); |
| 1250 |
content.saveRightContent(input, bytes); |
1210 |
content.saveRightContent(input, bytes); |
| 1251 |
} |
1211 |
} |
| 1252 |
} |
1212 |
} |
| 1253 |
|
1213 |
|
| 1254 |
/** |
1214 |
/** |
|
|
1215 |
* @param monitor |
| 1216 |
* @noreference This method is not intended to be referenced by clients. |
| 1217 |
*/ |
| 1218 |
public void flushLeft(IProgressMonitor monitor) { |
| 1219 |
flushLeftSide(getInput(), monitor); |
| 1220 |
} |
| 1221 |
|
| 1222 |
/** |
| 1223 |
* @param monitor |
| 1224 |
* @noreference This method is not intended to be referenced by clients. |
| 1225 |
*/ |
| 1226 |
public void flushRight(IProgressMonitor monitor) { |
| 1227 |
flushRightSide(getInput(), monitor); |
| 1228 |
} |
| 1229 |
|
| 1230 |
/** |
| 1255 |
* Return the dirty state of the right side of this viewer. |
1231 |
* Return the dirty state of the right side of this viewer. |
| 1256 |
* @return the dirty state of the right side of this viewer |
1232 |
* @return the dirty state of the right side of this viewer |
| 1257 |
* @since 3.3 |
1233 |
* @since 3.3 |
|
Lines 1261-1266
Link Here
|
| 1261 |
} |
1237 |
} |
| 1262 |
|
1238 |
|
| 1263 |
/** |
1239 |
/** |
|
|
1240 |
* @return the dirty state of the right side of this viewer |
| 1241 |
* @since 3.7 |
| 1242 |
* @noreference This method is not intended to be referenced by clients. |
| 1243 |
*/ |
| 1244 |
public boolean internalIsRightDirty() { |
| 1245 |
return isRightDirty(); |
| 1246 |
} |
| 1247 |
|
| 1248 |
/** |
| 1264 |
* Return the dirty state of the left side of this viewer. |
1249 |
* Return the dirty state of the left side of this viewer. |
| 1265 |
* @return the dirty state of the left side of this viewer |
1250 |
* @return the dirty state of the left side of this viewer |
| 1266 |
* @since 3.3 |
1251 |
* @since 3.3 |
|
Lines 1270-1275
Link Here
|
| 1270 |
} |
1255 |
} |
| 1271 |
|
1256 |
|
| 1272 |
/** |
1257 |
/** |
|
|
1258 |
* @return the dirty state of the left side of this viewer |
| 1259 |
* @since 3.7 |
| 1260 |
* @noreference This method is not intended to be referenced by clients. |
| 1261 |
*/ |
| 1262 |
public boolean internalIsLeftDirty() { |
| 1263 |
return isLeftDirty(); |
| 1264 |
} |
| 1265 |
|
| 1266 |
/** |
| 1273 |
* Handle a change to the given input reported from an {@link org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener}. |
1267 |
* Handle a change to the given input reported from an {@link org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener}. |
| 1274 |
* This class registers a listener with its input and reports any change events through |
1268 |
* This class registers a listener with its input and reports any change events through |
| 1275 |
* this method. By default, this method prompts for any unsaved changes and then refreshes |
1269 |
* this method. By default, this method prompts for any unsaved changes and then refreshes |
|
Lines 1279-1285
Link Here
|
| 1279 |
protected void handleCompareInputChange() { |
1273 |
protected void handleCompareInputChange() { |
| 1280 |
// before setting the new input we have to save the old |
1274 |
// before setting the new input we have to save the old |
| 1281 |
Object input = getInput(); |
1275 |
Object input = getInput(); |
| 1282 |
if (!fIsSaving && (isLeftDirty() || isRightDirty())) { |
1276 |
if (!isSaving() && (isLeftDirty() || isRightDirty())) { |
| 1283 |
|
1277 |
|
| 1284 |
if (Utilities.RUNNING_TESTS) { |
1278 |
if (Utilities.RUNNING_TESTS) { |
| 1285 |
if (Utilities.TESTING_FLUSH_ON_COMPARE_INPUT_CHANGE) { |
1279 |
if (Utilities.TESTING_FLUSH_ON_COMPARE_INPUT_CHANGE) { |
|
Lines 1310-1320
Link Here
|
| 1310 |
break; |
1304 |
break; |
| 1311 |
} |
1305 |
} |
| 1312 |
} |
1306 |
} |
|
|
1307 |
refresh(); |
| 1313 |
} |
1308 |
} |
| 1314 |
refresh(); |
|
|
| 1315 |
} |
1309 |
} |
| 1316 |
|
1310 |
|
| 1317 |
CompareHandlerService getCompareHandlerService() { |
1311 |
CompareHandlerService getCompareHandlerService() { |
| 1318 |
return fHandlerService; |
1312 |
return fHandlerService; |
| 1319 |
} |
1313 |
} |
|
|
1314 |
|
| 1315 |
/** |
| 1316 |
* @return true if any of the Saveables is being saved |
| 1317 |
*/ |
| 1318 |
private boolean isSaving() { |
| 1319 |
ICompareContainer container = fCompareConfiguration.getContainer(); |
| 1320 |
ISaveablesSource source = null; |
| 1321 |
if (container instanceof ISaveablesSource) { |
| 1322 |
source = (ISaveablesSource) container; |
| 1323 |
} else { |
| 1324 |
IWorkbenchPart part = container.getWorkbenchPart(); |
| 1325 |
if (part instanceof ISaveablesSource) { |
| 1326 |
source = (ISaveablesSource) part; |
| 1327 |
} |
| 1328 |
} |
| 1329 |
if (source != null) { |
| 1330 |
Saveable[] saveables = source.getSaveables(); |
| 1331 |
for (int i = 0; i < saveables.length; i++) { |
| 1332 |
if (saveables[i] instanceof ISavingSaveable) { |
| 1333 |
ISavingSaveable saveable = (ISavingSaveable) saveables[i]; |
| 1334 |
if (saveable.isSaving()) |
| 1335 |
return true; |
| 1336 |
} |
| 1337 |
} |
| 1338 |
} |
| 1339 |
return false; |
| 1340 |
} |
| 1341 |
|
| 1320 |
} |
1342 |
} |