1 11 package org.eclipse.ui.internal; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Set ; 20 21 import org.eclipse.core.runtime.CoreException; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.IStatus; 24 import org.eclipse.core.runtime.OperationCanceledException; 25 import org.eclipse.core.runtime.Status; 26 import org.eclipse.core.runtime.SubMonitor; 27 import org.eclipse.core.runtime.SubProgressMonitor; 28 import org.eclipse.core.runtime.jobs.IJobChangeEvent; 29 import org.eclipse.core.runtime.jobs.Job; 30 import org.eclipse.core.runtime.jobs.JobChangeAdapter; 31 import org.eclipse.jface.dialogs.IDialogConstants; 32 import org.eclipse.jface.dialogs.MessageDialog; 33 import org.eclipse.jface.operation.IRunnableContext; 34 import org.eclipse.jface.operation.IRunnableWithProgress; 35 import org.eclipse.jface.window.IShellProvider; 36 import org.eclipse.osgi.util.NLS; 37 import org.eclipse.ui.ISaveablePart; 38 import org.eclipse.ui.ISaveablePart2; 39 import org.eclipse.ui.ISaveablesLifecycleListener; 40 import org.eclipse.ui.ISaveablesSource; 41 import org.eclipse.ui.IWorkbenchPart; 42 import org.eclipse.ui.IWorkbenchWindow; 43 import org.eclipse.ui.PlatformUI; 44 import org.eclipse.ui.Saveable; 45 import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor; 46 import org.eclipse.ui.internal.misc.StatusUtil; 47 import org.eclipse.ui.progress.IJobRunnable; 48 import org.eclipse.ui.progress.IWorkbenchSiteProgressService; 49 import org.eclipse.ui.statushandlers.StatusManager; 50 51 56 public class SaveableHelper { 57 58 61 public static final int USER_RESPONSE = -1; 62 63 private static int AutomatedResponse = USER_RESPONSE; 64 65 72 public static void testSetAutomatedResponse(int response) { 73 AutomatedResponse = response; 74 } 75 76 83 public static int testGetAutomatedResponse() { 84 return AutomatedResponse; 85 } 86 87 97 static boolean savePart(final ISaveablePart saveable, IWorkbenchPart part, 98 IWorkbenchWindow window, boolean confirm) { 99 if (!saveable.isDirty()) { 101 return true; 102 } 103 104 if (confirm) { 106 int choice = AutomatedResponse; 107 if (choice == USER_RESPONSE) { 108 if (saveable instanceof ISaveablePart2) { 109 choice = ((ISaveablePart2)saveable).promptToSaveOnClose(); 110 } 111 if (choice == USER_RESPONSE || choice == ISaveablePart2.DEFAULT) { 112 String message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, part.getTitle()); 113 String [] buttons = new String [] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }; 115 MessageDialog d = new MessageDialog( 116 window.getShell(), WorkbenchMessages.Save_Resource, 117 null, message, MessageDialog.QUESTION, buttons, 0); 118 choice = d.open(); 119 } 120 } 121 122 switch (choice) { 125 case ISaveablePart2.YES : break; 127 case ISaveablePart2.NO : return true; 129 default : 130 case ISaveablePart2.CANCEL : return false; 132 } 133 } 134 135 if (saveable instanceof ISaveablesSource) { 136 return saveModels((ISaveablesSource) saveable, window, confirm); 137 } 138 139 IRunnableWithProgress progressOp = new IRunnableWithProgress() { 141 public void run(IProgressMonitor monitor) { 142 IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor); 143 saveable.doSave(monitorWrap); 144 } 145 }; 146 147 return runProgressMonitorOperation(WorkbenchMessages.Save, progressOp, window); 149 } 150 151 160 private static boolean saveModels(ISaveablesSource modelSource, final IWorkbenchWindow window, final boolean confirm) { 161 Saveable[] selectedModels = modelSource.getActiveSaveables(); 162 final ArrayList dirtyModels = new ArrayList (); 163 for (int i = 0; i < selectedModels.length; i++) { 164 Saveable model = selectedModels[i]; 165 if (model.isDirty()) { 166 dirtyModels.add(model); 167 } 168 } 169 if (dirtyModels.isEmpty()) { 170 return true; 171 } 172 173 IRunnableWithProgress progressOp = new IRunnableWithProgress() { 175 public void run(IProgressMonitor monitor) { 176 IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor); 177 monitorWrap.beginTask(WorkbenchMessages.Save, dirtyModels.size()); 178 for (Iterator i = dirtyModels.iterator(); i.hasNext();) { 179 Saveable model = (Saveable) i.next(); 180 if (!model.isDirty()) { 182 monitor.worked(1); 183 continue; 184 } 185 doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), 186 window, confirm); 187 if (monitor.isCanceled()) { 188 break; 189 } 190 } 191 monitorWrap.done(); 192 } 193 }; 194 195 return runProgressMonitorOperation(WorkbenchMessages.Save, progressOp, window); 197 } 198 199 211 static int savePart(final ISaveablePart2 saveable, 212 IWorkbenchWindow window, boolean confirm) { 213 if (!saveable.isDirty()) { 215 return ISaveablePart2.YES; 216 } 217 218 if (confirm) { 220 int choice = AutomatedResponse; 221 if (choice == USER_RESPONSE) { 222 choice = saveable.promptToSaveOnClose(); 223 } 224 225 if (choice!=ISaveablePart2.YES) { 228 return (choice==USER_RESPONSE?ISaveablePart2.DEFAULT:choice); 229 } 230 } 231 232 IRunnableWithProgress progressOp = new IRunnableWithProgress() { 234 public void run(IProgressMonitor monitor) { 235 IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor); 236 saveable.doSave(monitorWrap); 237 } 238 }; 239 240 if (!runProgressMonitorOperation(WorkbenchMessages.Save, progressOp,window)) { 242 return ISaveablePart2.CANCEL; 243 } 244 return ISaveablePart2.YES; 245 } 246 247 251 static boolean runProgressMonitorOperation(String opName, 252 IRunnableWithProgress progressOp, IWorkbenchWindow window) { 253 return runProgressMonitorOperation(opName, progressOp, window, window); 254 } 255 256 260 static boolean runProgressMonitorOperation(String opName, 261 final IRunnableWithProgress progressOp, 262 final IRunnableContext runnableContext, final IShellProvider shellProvider) { 263 final boolean[] success = new boolean[] { false }; 264 IRunnableWithProgress runnable = new IRunnableWithProgress() { 265 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 266 progressOp.run(monitor); 267 if (!monitor.isCanceled()) 269 success[0] = true; 270 } 271 }; 272 273 try { 274 runnableContext.run(false, true, runnable); 275 } catch (InvocationTargetException e) { 276 String title = NLS.bind(WorkbenchMessages.EditorManager_operationFailed, opName ); 277 Throwable targetExc = e.getTargetException(); 278 WorkbenchPlugin.log(title, new Status(IStatus.WARNING, 279 PlatformUI.PLUGIN_ID, 0, title, targetExc)); 280 StatusUtil.handleStatus(title, targetExc, StatusManager.SHOW, 281 shellProvider.getShell()); 282 } catch (InterruptedException e) { 284 } catch (OperationCanceledException e) { 286 } 288 return success[0]; 289 } 290 291 302 public static boolean needsSave(ISaveablesSource modelSource) { 303 Saveable[] selectedModels = modelSource.getActiveSaveables(); 304 for (int i = 0; i < selectedModels.length; i++) { 305 Saveable model = selectedModels[i]; 306 if (model.isDirty() && !((InternalSaveable)model).isSavingInBackground()) { 307 return true; 308 } 309 } 310 return false; 311 } 312 313 319 public static void doSaveModel(final Saveable model, 320 IProgressMonitor progressMonitor, 321 final IShellProvider shellProvider, boolean blockUntilSaved) { 322 try { 323 Job backgroundSaveJob = ((InternalSaveable)model).getBackgroundSaveJob(); 324 if (backgroundSaveJob != null) { 325 boolean canceled = waitForBackgroundSaveJob(model); 326 if (canceled) { 327 progressMonitor.setCanceled(true); 328 return; 329 } 330 if (!model.isDirty()) { 332 return; 333 } 334 } 335 final IJobRunnable[] backgroundSaveRunnable = new IJobRunnable[1]; 336 try { 337 SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 3); 338 backgroundSaveRunnable[0] = model.doSave( 339 subMonitor.newChild(2), shellProvider); 340 if (backgroundSaveRunnable[0] == null) { 341 return; 343 } 344 if (blockUntilSaved) { 345 IStatus result = backgroundSaveRunnable[0].run(subMonitor 348 .newChild(1)); 349 if (!result.isOK()) { 350 StatusUtil.handleStatus(result, StatusManager.SHOW, 351 shellProvider.getShell()); 352 progressMonitor.setCanceled(true); 353 } 354 return; 355 } 356 Job saveJob = new Job(NLS.bind( 360 WorkbenchMessages.EditorManager_backgroundSaveJobName, 361 model.getName())) { 362 public boolean belongsTo(Object family) { 363 if (family instanceof DynamicFamily) { 364 return ((DynamicFamily)family).contains(model); 365 } 366 return family.equals(model); 367 } 368 369 protected IStatus run(IProgressMonitor monitor) { 370 return backgroundSaveRunnable[0].run(monitor); 371 } 372 }; 373 ((InternalSaveable) model).setBackgroundSaveJob(saveJob); 375 SaveablesList saveablesList = (SaveablesList) PlatformUI 376 .getWorkbench().getService( 377 ISaveablesLifecycleListener.class); 378 final IWorkbenchPart[] parts = saveablesList 379 .getPartsForSaveable(model); 380 381 for (int i = 0; i < parts.length; i++) { 383 IWorkbenchPart workbenchPart = parts[i]; 384 IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService) workbenchPart 385 .getSite().getAdapter( 386 IWorkbenchSiteProgressService.class); 387 progressService.showBusyForFamily(model); 388 } 389 model.disableUI(parts, blockUntilSaved); 390 saveJob.addJobChangeListener(new JobChangeAdapter() { 394 public void done(final IJobChangeEvent event) { 395 ((InternalSaveable) model).setBackgroundSaveJob(null); 396 shellProvider.getShell().getDisplay().asyncExec( 397 new Runnable () { 398 public void run() { 399 notifySaveAction(parts); 400 model.enableUI(parts); 401 } 402 }); 403 } 404 }); 405 saveJob.schedule(); 407 notifySaveAction(parts); 411 } catch (CoreException e) { 412 StatusUtil.handleStatus(e.getStatus(), StatusManager.SHOW, 413 shellProvider.getShell()); 414 progressMonitor.setCanceled(true); 415 } 416 } finally { 417 progressMonitor.done(); 418 } 419 } 420 421 private static void notifySaveAction(final IWorkbenchPart[] parts) { 422 Set wwindows = new HashSet (); 423 for (int i = 0; i < parts.length; i++) { 424 wwindows.add(parts[i].getSite().getWorkbenchWindow()); 425 } 426 for (Iterator it = wwindows.iterator(); it.hasNext();) { 427 WorkbenchWindow wwin = (WorkbenchWindow) it.next(); 428 wwin.fireBackgroundSaveStarted(); 429 } 430 } 431 432 439 private static boolean waitForBackgroundSaveJob(final Saveable model) { 440 List models = new ArrayList (); 441 models.add(model); 442 return waitForBackgroundSaveJobs(models); 443 } 444 445 452 public static boolean waitForBackgroundSaveJobs(final List modelsToSave) { 453 try { 455 PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() { 456 public void run(IProgressMonitor monitor) throws InterruptedException { 457 Job.getJobManager().join(new DynamicFamily(modelsToSave), monitor); 458 } 459 }); 460 } catch (InvocationTargetException e) { 461 StatusUtil.handleStatus(e, StatusManager.SHOW | StatusManager.LOG); 462 } catch (InterruptedException e) { 463 return true; 464 } 465 for (Iterator it = modelsToSave.iterator(); it.hasNext();) { 467 Saveable model = (Saveable) it.next(); 468 if (!model.isDirty()) { 469 it.remove(); 470 } 471 } 472 return false; 473 } 474 475 private static class DynamicFamily extends HashSet { 476 private static final long serialVersionUID = 1L; 477 public DynamicFamily(Collection collection) { 478 super(collection); 479 } 480 } 481 482 } 483 | Popular Tags |