1 11 package org.eclipse.ui.operations; 12 13 import java.lang.reflect.InvocationTargetException ; 14 15 import org.eclipse.core.commands.ExecutionException; 16 import org.eclipse.core.commands.operations.IAdvancedUndoableOperation2; 17 import org.eclipse.core.commands.operations.IOperationHistory; 18 import org.eclipse.core.commands.operations.IOperationHistoryListener; 19 import org.eclipse.core.commands.operations.IUndoContext; 20 import org.eclipse.core.commands.operations.IUndoableOperation; 21 import org.eclipse.core.commands.operations.OperationHistoryEvent; 22 import org.eclipse.core.runtime.IAdaptable; 23 import org.eclipse.core.runtime.IProgressMonitor; 24 import org.eclipse.core.runtime.IStatus; 25 import org.eclipse.core.runtime.OperationCanceledException; 26 import org.eclipse.jface.action.Action; 27 import org.eclipse.jface.operation.IRunnableWithProgress; 28 import org.eclipse.osgi.util.NLS; 29 import org.eclipse.swt.widgets.Display; 30 import org.eclipse.swt.widgets.Shell; 31 import org.eclipse.ui.IPartListener; 32 import org.eclipse.ui.IWorkbenchPart; 33 import org.eclipse.ui.IWorkbenchPartSite; 34 import org.eclipse.ui.IWorkbenchWindow; 35 import org.eclipse.ui.PlatformUI; 36 import org.eclipse.ui.actions.ActionFactory; 37 import org.eclipse.ui.internal.WorkbenchMessages; 38 import org.eclipse.ui.internal.WorkbenchPlugin; 39 import org.eclipse.ui.internal.misc.StatusUtil; 40 import org.eclipse.ui.internal.operations.TimeTriggeredProgressMonitorDialog; 41 import org.eclipse.ui.internal.util.Util; 42 import org.eclipse.ui.part.MultiPageEditorSite; 43 import org.eclipse.ui.statushandlers.StatusManager; 44 45 74 public abstract class OperationHistoryActionHandler extends Action implements 75 ActionFactory.IWorkbenchAction, IAdaptable { 76 77 private static final int MAX_LABEL_LENGTH = 32; 78 79 private class PartListener implements IPartListener { 80 83 public void partActivated(IWorkbenchPart part) { 84 } 85 86 89 public void partBroughtToTop(IWorkbenchPart part) { 90 } 91 92 95 public void partClosed(IWorkbenchPart part) { 96 if (part.equals(site.getPart())) { 97 dispose(); 98 } else if ((site instanceof MultiPageEditorSite) 101 && (part.equals(((MultiPageEditorSite) site) 102 .getMultiPageEditor()))) { 103 dispose(); 104 } 105 } 106 107 110 public void partDeactivated(IWorkbenchPart part) { 111 } 112 113 116 public void partOpened(IWorkbenchPart part) { 117 } 118 119 } 120 121 private class HistoryListener implements IOperationHistoryListener { 122 public void historyNotification(final OperationHistoryEvent event) { 123 Display display = getWorkbenchWindow().getWorkbench().getDisplay(); 124 switch (event.getEventType()) { 125 case OperationHistoryEvent.OPERATION_ADDED: 126 case OperationHistoryEvent.OPERATION_REMOVED: 127 case OperationHistoryEvent.UNDONE: 128 case OperationHistoryEvent.REDONE: 129 if (display != null 130 && event.getOperation().hasContext(undoContext)) { 131 contextActive = true; 132 display.asyncExec(new Runnable () { 133 public void run() { 134 update(); 135 } 136 }); 137 } 138 break; 139 case OperationHistoryEvent.OPERATION_NOT_OK: 140 if (display != null 141 && event.getOperation().hasContext(undoContext)) { 142 contextActive = true; 143 display.asyncExec(new Runnable () { 144 public void run() { 145 if (pruning) { 146 IStatus status = event.getStatus(); 147 152 if (status == null 153 || status.getSeverity() != IStatus.CANCEL) { 154 flush(); 155 } 156 update(); 159 } else { 160 update(); 161 } 162 } 163 }); 164 } 165 break; 166 case OperationHistoryEvent.OPERATION_CHANGED: 167 if (event.getOperation().hasContext(undoContext)) { 168 contextActive = true; 169 } 170 if (display != null && event.getOperation() == getOperation()) { 171 display.asyncExec(new Runnable () { 172 public void run() { 173 update(); 174 } 175 }); 176 } 177 break; 178 default: 179 if (event.getOperation().hasContext(undoContext)) { 180 contextActive = true; 181 } 182 break; 183 } 184 } 185 } 186 187 private boolean contextActive = false; 188 189 private boolean pruning = false; 190 191 private IPartListener partListener = new PartListener(); 192 193 private IOperationHistoryListener historyListener = new HistoryListener(); 194 195 private TimeTriggeredProgressMonitorDialog progressDialog; 196 197 private IUndoContext undoContext = null; 198 199 IWorkbenchPartSite site; 200 201 210 OperationHistoryActionHandler(IWorkbenchPartSite site, IUndoContext context) { 211 super(""); this.site = site; 214 undoContext = context; 215 checkUndoContext(); 216 site.getPage().addPartListener(partListener); 217 getHistory().addOperationHistoryListener(historyListener); 218 update(); 221 } 222 223 228 public void dispose() { 229 230 IOperationHistory history = getHistory(); 231 if (history != null) { 232 history.removeOperationHistoryListener(historyListener); 233 } 234 235 if (isInvalid()) { 236 return; 237 } 238 239 site.getPage().removePartListener(partListener); 240 site = null; 241 progressDialog = null; 242 undoContext = null; 248 } 249 250 253 abstract void flush(); 254 255 259 abstract String getCommandString(); 260 261 265 abstract String getTooltipString(); 266 267 271 abstract String getSimpleCommandString(); 272 273 277 abstract String getSimpleTooltipString(); 278 279 282 IOperationHistory getHistory() { 283 if (PlatformUI.getWorkbench() == null) { 284 return null; 285 } 286 287 return PlatformUI.getWorkbench().getOperationSupport() 288 .getOperationHistory(); 289 } 290 291 294 abstract IUndoableOperation getOperation(); 295 296 301 public final void run() { 302 if (isInvalid()) { 303 return; 304 } 305 306 Shell parent = getWorkbenchWindow().getShell(); 307 progressDialog = new TimeTriggeredProgressMonitorDialog(parent, 308 getWorkbenchWindow().getWorkbench().getProgressService() 309 .getLongOperationTime()); 310 IRunnableWithProgress runnable = new IRunnableWithProgress() { 311 public void run(IProgressMonitor pm) 312 throws InvocationTargetException { 313 try { 314 runCommand(pm); 315 } catch (ExecutionException e) { 316 if (pruning) { 317 flush(); 318 } 319 throw new InvocationTargetException (e); 320 } 321 } 322 }; 323 try { 324 boolean runInBackground = false; 325 if (getOperation() instanceof IAdvancedUndoableOperation2) { 326 runInBackground = ((IAdvancedUndoableOperation2) getOperation()) 327 .runInBackground(); 328 } 329 progressDialog.run(runInBackground, true, runnable); 330 } catch (InvocationTargetException e) { 331 Throwable t = e.getTargetException(); 332 if (t == null) { 333 reportException(e); 334 } else { 335 reportException(t); 336 } 337 } catch (InterruptedException e) { 338 } catch (OperationCanceledException e) { 342 } finally { 344 progressDialog = null; 345 } 346 } 347 348 abstract IStatus runCommand(IProgressMonitor pm) throws ExecutionException; 349 350 355 public Object getAdapter(Class adapter) { 356 if (adapter.equals(IUndoContext.class)) { 357 return undoContext; 358 } 359 if (adapter.equals(IProgressMonitor.class)) { 360 if (progressDialog != null) { 361 return progressDialog.getProgressMonitor(); 362 } 363 } 364 if (site != null) { 365 if (adapter.equals(Shell.class)) { 366 return getWorkbenchWindow().getShell(); 367 } 368 if (adapter.equals(IWorkbenchWindow.class)) { 369 return getWorkbenchWindow(); 370 } 371 if (adapter.equals(IWorkbenchPart.class)) { 372 return site.getPart(); 373 } 374 IWorkbenchPart part = site.getPart(); 377 if (part != null) { 378 return Util.getAdapter(part, adapter); 379 } 380 } 381 return null; 382 } 383 384 387 private IWorkbenchWindow getWorkbenchWindow() { 388 if (site != null) { 389 return site.getWorkbenchWindow(); 390 } 391 return null; 392 } 393 394 399 abstract boolean shouldBeEnabled(); 400 401 409 public void setContext(IUndoContext context) { 410 if (context == undoContext) { 412 return; 413 } 414 undoContext = context; 415 checkUndoContext(); 416 update(); 417 } 418 419 429 public void setPruneHistory(boolean prune) { 430 pruning = prune; 431 } 432 433 437 public void update() { 438 if (isInvalid()) { 439 return; 440 } 441 442 boolean enabled = shouldBeEnabled(); 443 String text, tooltipText; 444 if (enabled) { 445 tooltipText = NLS.bind(getTooltipString(), getOperation() 446 .getLabel()); 447 text = NLS.bind(getCommandString(), shortenText(getOperation() 448 .getLabel())); 449 } else { 450 tooltipText = NLS.bind( 451 WorkbenchMessages.Operations_undoRedoCommandDisabled, 452 getSimpleTooltipString()); 453 text = getSimpleCommandString(); 454 458 if (undoContext != null && pruning) { 459 flush(); 460 } 461 } 462 setText(text); 463 setToolTipText(tooltipText); 464 setEnabled(enabled); 465 } 466 467 470 private String shortenText(String message) { 471 int length = message.length(); 472 if (length > MAX_LABEL_LENGTH) { 473 StringBuffer result = new StringBuffer (); 474 int mid = MAX_LABEL_LENGTH / 2; 475 result.append(message.substring(0, mid)); 476 result.append("..."); result.append(message.substring(length - mid)); 478 return result.toString(); 479 } 480 return message; 481 } 482 483 486 final void reportException(Throwable t) { 487 Throwable nestedException = StatusUtil.getCause(t); 489 Throwable exception = (nestedException == null) ? t : nestedException; 490 491 String exceptionMessage = exception.getMessage(); 493 if (exceptionMessage == null) { 494 exceptionMessage = WorkbenchMessages.WorkbenchWindow_exceptionMessage; 495 } 496 IStatus status = StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH, 497 exceptionMessage, exception); 498 499 WorkbenchPlugin.log(exceptionMessage, status); 501 StatusUtil.handleStatus(status, StatusManager.SHOW, 502 getWorkbenchWindow().getShell()); 503 } 504 505 509 final boolean isInvalid() { 510 return undoContext == null || site == null; 511 } 512 513 516 final IUndoContext getUndoContext() { 517 if (undoContext == null || !contextActive) { 520 return PlatformUI.getWorkbench().getOperationSupport() 521 .getUndoContext(); 522 } 523 return undoContext; 524 } 525 526 532 private void checkUndoContext() { 533 if (undoContext == null) { 534 return; 535 } 536 contextActive = getHistory().getUndoOperation(undoContext) != null 537 || getHistory().getRedoOperation(undoContext) != null; 538 } 539 } 540 | Popular Tags |