1 11 package org.eclipse.compare.structuremergeviewer; 12 13 import java.lang.reflect.InvocationTargetException ; 14 15 import org.eclipse.compare.*; 16 import org.eclipse.compare.contentmergeviewer.IDocumentRange; 17 import org.eclipse.compare.internal.*; 18 import org.eclipse.core.runtime.*; 19 import org.eclipse.jface.operation.IRunnableWithProgress; 20 import org.eclipse.jface.text.BadPositionCategoryException; 21 import org.eclipse.jface.text.IDocument; 22 import org.eclipse.jface.util.PropertyChangeEvent; 23 import org.eclipse.swt.custom.BusyIndicator; 24 import org.eclipse.swt.events.DisposeEvent; 25 import org.eclipse.swt.widgets.*; 26 import org.eclipse.ui.services.IDisposable; 27 28 29 41 42 public class StructureDiffViewer extends DiffTreeViewer { 43 private Differencer fDifferencer; 44 private boolean fThreeWay= false; 45 46 private StructureInfo fAncestorStructure = new StructureInfo(); 47 private StructureInfo fLeftStructure = new StructureInfo(); 48 private StructureInfo fRightStructure = new StructureInfo(); 49 50 private IStructureCreator fStructureCreator; 51 private IDiffContainer fRoot; 52 private IContentChangeListener fContentChangedListener; 53 private CompareViewerSwitchingPane fParent; 54 private ICompareInputChangeListener fCompareInputChangeListener; 55 56 59 private IRunnableWithProgress diffTask = new IRunnableWithProgress() { 60 public void run(IProgressMonitor monitor) throws InvocationTargetException , 61 InterruptedException { 62 monitor.beginTask(CompareMessages.StructureDiffViewer_0, 100); 63 diff(new SubProgressMonitor(monitor, 100)); 64 monitor.done(); 65 } 66 }; 67 68 private IRunnableWithProgress inputChangedTask = new IRunnableWithProgress() { 69 public void run(IProgressMonitor monitor) throws InvocationTargetException , 70 InterruptedException { 71 monitor.beginTask(CompareMessages.StructureDiffViewer_1, 100); 72 compareInputChanged((ICompareInput)getInput(), true, new SubProgressMonitor(monitor, 100)); 74 monitor.done(); 75 } 76 }; 77 78 82 private class StructureInfo { 83 private ITypedElement fInput; 84 private IStructureComparator fStructureComparator; 85 private IRunnableWithProgress refreshTask = new IRunnableWithProgress() { 86 public void run(IProgressMonitor monitor) throws InvocationTargetException , 87 InterruptedException { 88 refresh(monitor); 89 } 90 }; 91 92 public boolean setInput(ITypedElement newInput, boolean force, IProgressMonitor monitor) { 93 boolean changed = false; 94 if (force || newInput != fInput) { 95 removeDocumentRangeUpdaters(); 96 if (fInput instanceof IContentChangeNotifier && fContentChangedListener != null) 97 ((IContentChangeNotifier)fInput).removeContentChangeListener(fContentChangedListener); 98 fInput= newInput; 99 if (fInput == null) { 100 if (fStructureComparator instanceof IDisposable) { 101 IDisposable disposable = (IDisposable) fStructureComparator; 102 disposable.dispose(); 103 } 104 fStructureComparator= null; 105 } else { 106 refresh(monitor); 107 changed= true; 108 } 109 if (fInput instanceof IContentChangeNotifier && fContentChangedListener != null) 110 ((IContentChangeNotifier)fInput).addContentChangeListener(fContentChangedListener); 111 } 112 return changed; 113 } 114 115 118 private void removeDocumentRangeUpdaters() { 119 if (fStructureComparator instanceof IDocumentRange) { 120 IDocument doc = ((IDocumentRange) fStructureComparator).getDocument(); 121 try { 122 doc.removePositionCategory(IDocumentRange.RANGE_CATEGORY); 123 } catch (BadPositionCategoryException ex) { 124 } 126 } 127 } 128 129 public IStructureComparator getStructureComparator() { 130 return fStructureComparator; 131 } 132 133 public void refresh(IProgressMonitor monitor) { 134 IStructureComparator oldComparator = fStructureComparator; 135 fStructureComparator= createStructure(monitor); 136 if (oldComparator instanceof IDisposable) { 140 IDisposable disposable = (IDisposable) oldComparator; 141 disposable.dispose(); 142 } 143 } 144 145 public Object getInput() { 146 return fInput; 147 } 148 149 private IStructureComparator createStructure(IProgressMonitor monitor) { 150 Object input = fInput; 152 if (input == null) 153 return null; 154 if (fStructureCreator instanceof IStructureCreator2) { 155 IStructureCreator2 sc2 = (IStructureCreator2) fStructureCreator; 156 try { 157 return sc2.createStructure(input, monitor); 158 } catch (CoreException e) { 159 CompareUIPlugin.log(e); 160 } 161 } 162 return fStructureCreator.getStructure(input); 163 } 164 165 public void dispose() { 166 if (fStructureComparator != null && fStructureCreator instanceof IStructureCreator2) { 167 IStructureCreator2 sc2 = (IStructureCreator2) fStructureCreator; 168 sc2.destroy(fStructureComparator); 169 } 170 } 171 172 public IRunnableWithProgress getRefreshTask() { 173 return refreshTask; 174 } 175 } 176 177 183 public StructureDiffViewer(Tree tree, CompareConfiguration configuration) { 184 super(tree, configuration); 185 Composite c= tree.getParent(); 186 if (c instanceof CompareViewerSwitchingPane) 187 fParent= (CompareViewerSwitchingPane) c; 188 initialize(); 189 } 190 191 197 public StructureDiffViewer(Composite parent, CompareConfiguration configuration) { 198 super(parent, configuration); 199 if (parent instanceof CompareViewerSwitchingPane) 200 fParent= (CompareViewerSwitchingPane) parent; 201 initialize(); 202 } 203 204 private void initialize() { 205 206 setAutoExpandLevel(3); 207 208 fContentChangedListener= new IContentChangeListener() { 209 public void contentChanged(IContentChangeNotifier changed) { 210 StructureDiffViewer.this.contentChanged(changed); 211 } 212 }; 213 fCompareInputChangeListener = new ICompareInputChangeListener() { 214 public void compareInputChanged(ICompareInput input) { 215 StructureDiffViewer.this.compareInputChanged(input, true); 216 } 217 }; 218 } 219 220 227 public void setStructureCreator(IStructureCreator structureCreator) { 228 if (fStructureCreator != structureCreator) { 229 fStructureCreator= structureCreator; 230 Control tree= getControl(); 231 if (tree != null && !tree.isDisposed()) 232 tree.setData(CompareUI.COMPARE_VIEWER_TITLE, getTitle()); 233 } 234 } 235 236 242 public IStructureCreator getStructureCreator() { 243 return fStructureCreator; 244 } 245 246 250 public String getTitle() { 251 if (fStructureCreator != null) 252 return fStructureCreator.getName(); 253 return super.getTitle(); 254 } 255 256 262 protected Object getRoot() { 263 return fRoot; 264 } 265 266 272 protected void inputChanged(Object input, Object oldInput) { 273 if (oldInput instanceof ICompareInput) { 274 ICompareInput old = (ICompareInput) oldInput; 275 old.removeCompareInputChangeListener(fCompareInputChangeListener); 276 } 277 if (input instanceof ICompareInput) { 278 ICompareInput ci = (ICompareInput) input; 279 ci.addCompareInputChangeListener(fCompareInputChangeListener); 280 compareInputChanged(ci); 281 if (input != oldInput) 282 initialSelection(); 283 } 284 } 285 286 protected void initialSelection() { 287 expandToLevel(2); 288 } 289 290 293 protected void handleDispose(DisposeEvent event) { 294 Object input = getInput(); 295 if (input instanceof ICompareInput) { 296 ICompareInput ci = (ICompareInput) input; 297 ci.removeCompareInputChangeListener(fCompareInputChangeListener); 298 } 299 compareInputChanged(null); 300 fContentChangedListener= null; 301 super.handleDispose(event); 302 } 303 304 308 protected void compareInputChanged(ICompareInput input) { 309 compareInputChanged(input, false); 310 } 311 312 void compareInputChanged(final ICompareInput input, final boolean force) { 313 if (input == null) { 314 compareInputChanged(input, force, null); 316 return; 317 } 318 CompareConfiguration cc = getCompareConfiguration(); 319 if (cc != null) { 321 BusyIndicator.showWhile(Display.getDefault(), new Runnable () { 322 public void run() { 323 try { 324 inputChangedTask.run(new NullProgressMonitor()); 325 } catch (InvocationTargetException e) { 326 CompareUIPlugin.log(e.getTargetException()); 327 } catch (InterruptedException e) { 328 } 330 } 331 }); 332 } 333 } 334 335 void compareInputChanged(ICompareInput input, boolean force, IProgressMonitor monitor) { 336 ITypedElement t= null; 337 boolean changed= false; 338 339 if (input != null) 340 t= input.getAncestor(); 341 fThreeWay= (t != null); 342 beginWork(monitor, 400); 343 try { 344 if (fAncestorStructure.setInput(t, force, subMonitor(monitor, 100))) 345 changed = true; 346 347 if (input != null) 348 t= input.getLeft(); 349 if (fLeftStructure.setInput(t, force, subMonitor(monitor, 100))) 350 changed = true; 351 352 if (input != null) 353 t= input.getRight(); 354 if (fRightStructure.setInput(t, force, subMonitor(monitor, 100))) 355 changed = true; 356 357 CompareConfiguration cc = getCompareConfiguration(); 359 if (changed && cc != null) 360 cc.getContainer().runAsynchronously(diffTask); 361 } finally { 362 endWork(monitor); 363 } 364 } 365 366 private void endWork(IProgressMonitor monitor) { 367 if (monitor != null) 368 monitor.done(); 369 } 370 371 private IProgressMonitor subMonitor(IProgressMonitor monitor, int work) { 372 if (monitor != null) { 373 if (monitor.isCanceled() || getControl().isDisposed()) 374 throw new OperationCanceledException(); 375 return new SubProgressMonitor(monitor, work); 376 } 377 return null; 378 } 379 380 private void beginWork(IProgressMonitor monitor, int totalWork) { 381 if (monitor != null) 382 monitor.beginTask(null, totalWork); 383 } 384 385 389 protected void contentChanged(final IContentChangeNotifier changed) { 390 391 if (fStructureCreator == null) 392 return; 393 394 if (changed == null) { 395 getCompareConfiguration().getContainer().runAsynchronously(fAncestorStructure.getRefreshTask()); 396 getCompareConfiguration().getContainer().runAsynchronously(fLeftStructure.getRefreshTask()); 397 getCompareConfiguration().getContainer().runAsynchronously(fRightStructure.getRefreshTask()); 398 } else if (changed == fAncestorStructure.getInput()) { 399 getCompareConfiguration().getContainer().runAsynchronously(fAncestorStructure.getRefreshTask()); 400 } else if (changed == fLeftStructure.getInput()) { 401 getCompareConfiguration().getContainer().runAsynchronously(fLeftStructure.getRefreshTask()); 402 } else if (changed == fRightStructure.getInput()) { 403 getCompareConfiguration().getContainer().runAsynchronously(fRightStructure.getRefreshTask()); 404 } else { 405 return; 406 } 407 getCompareConfiguration().getContainer().runAsynchronously(diffTask); 408 } 409 410 423 protected void preDiffHook(IStructureComparator ancestor, IStructureComparator left, IStructureComparator right) { 424 } 426 427 443 protected void preDiffHook(final IStructureComparator ancestor, final IStructureComparator left, final IStructureComparator right, IProgressMonitor monitor) { 444 syncExec(new Runnable () { 445 public void run() { 446 preDiffHook(ancestor, left, right); 447 } 448 }); 449 } 450 451 456 protected void diff(IProgressMonitor monitor) { 457 try { 458 beginWork(monitor, 150); 459 460 IStructureComparator ancestorComparator = fAncestorStructure.getStructureComparator(); 461 IStructureComparator leftComparator = fLeftStructure.getStructureComparator(); 462 IStructureComparator rightComparator = fRightStructure.getStructureComparator(); 463 464 preDiffHook(ancestorComparator, 465 leftComparator, 466 rightComparator, 467 subMonitor(monitor, 25)); 468 469 String message= null; 470 471 if ((fThreeWay && ancestorComparator == null) || leftComparator == null || rightComparator == null) { 472 fRoot= null; 474 message= CompareMessages.StructureDiffViewer_StructureError; 475 476 } else { 478 if (fDifferencer == null) 479 fDifferencer= new Differencer() { 480 protected boolean contentsEqual(Object o1, Object o2) { 481 return StructureDiffViewer.this.contentsEqual(o1, o2); 482 } 483 protected Object visit(Object data, int result, Object ancestor, Object left, Object right) { 484 Object o= super.visit(data, result, ancestor, left, right); 485 if (fLeftIsLocal && o instanceof DiffNode) 486 ((DiffNode)o).swapSides(fLeftIsLocal); 487 return o; 488 } 489 }; 490 491 fRoot= (IDiffContainer) fDifferencer.findDifferences(fThreeWay, subMonitor(monitor, 100), null, 492 ancestorComparator, leftComparator, rightComparator); 493 494 if (fRoot == null || fRoot.getChildren().length == 0) { 495 message= CompareMessages.StructureDiffViewer_NoStructuralDifferences; 496 } else { 497 postDiffHook(fDifferencer, fRoot, subMonitor(monitor, 25)); 498 } 499 } 500 501 if (Display.getCurrent() != null) 502 refreshAfterDiff(message); 503 else { 504 final String theMessage = message; 505 Display.getDefault().asyncExec(new Runnable () { 506 public void run() { 507 refreshAfterDiff(theMessage); 508 } 509 }); 510 } 511 } finally { 512 endWork(monitor); 513 } 514 } 515 516 private void refreshAfterDiff(String message) { 517 if (getControl().isDisposed()) 518 return; 519 if (fParent != null) 520 fParent.setTitleArgument(message); 521 522 refresh(getRoot()); 523 expandToLevel(3); 525 } 526 527 530 protected void diff() { 531 try { 532 CompareConfiguration compareConfiguration = getCompareConfiguration(); 533 if (compareConfiguration != null) { 535 compareConfiguration.getContainer().run(true, true, new IRunnableWithProgress() { 536 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 537 monitor.beginTask(CompareMessages.StructureDiffViewer_2, 100); 538 diffTask.run(new SubProgressMonitor(monitor, 100)); 539 monitor.done(); 540 } 541 }); 542 } 543 } catch (InvocationTargetException e) { 544 CompareUIPlugin.log(e.getTargetException()); 546 handleFailedRefresh(e.getTargetException().getMessage()); 547 } catch (InterruptedException e) { 548 handleFailedRefresh(CompareMessages.StructureDiffViewer_3); 550 } 551 } 552 553 private void handleFailedRefresh(final String message) { 554 Runnable runnable = new Runnable () { 555 public void run() { 556 if (getControl().isDisposed()) 557 return; 558 refreshAfterDiff(message); 559 } 560 }; 561 if (Display.getCurrent() != null) 562 runnable.run(); 563 else 564 Display.getDefault().asyncExec(runnable); 565 } 566 567 580 protected void postDiffHook(Differencer differencer, IDiffContainer root) { 581 } 583 584 600 protected void postDiffHook(final Differencer differencer, final IDiffContainer root, IProgressMonitor monitor) { 601 syncExec(new Runnable () { 602 public void run() { 603 postDiffHook(differencer, root); 604 } 605 }); 606 } 607 608 613 private boolean contentsEqual(Object o1, Object o2) { 614 if (fStructureCreator != null) { 615 boolean ignoreWhiteSpace= Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false); 616 String s1= fStructureCreator.getContents(o1, ignoreWhiteSpace); 617 String s2= fStructureCreator.getContents(o2, ignoreWhiteSpace); 618 if (s1 == null || s2 == null) 619 return false; 620 return s1.equals(s2); 621 } 622 return false; 623 } 624 625 631 protected void propertyChange(PropertyChangeEvent event) { 632 String key= event.getProperty(); 633 if (key.equals(CompareConfiguration.IGNORE_WHITESPACE)) 634 diff(); 635 else 636 super.propertyChange(event); 637 } 638 639 646 protected void copySelected(boolean leftToRight) { 647 super.copySelected(leftToRight); 648 649 if (fStructureCreator != null) 650 fStructureCreator.save( 651 leftToRight ? fRightStructure.getStructureComparator() : fLeftStructure.getStructureComparator(), 652 leftToRight ? fRightStructure.getInput() : fLeftStructure.getInput()); 653 } 654 655 private void syncExec(final Runnable runnable) { 656 if (getControl().isDisposed()) 657 return; 658 if (Display.getCurrent() != null) 659 runnable.run(); 660 else 661 getControl().getDisplay().syncExec(new Runnable () { 662 public void run() { 663 if (!getControl().isDisposed()) 664 runnable.run(); 665 } 666 }); 667 } 668 } 669 670 | Popular Tags |