1 12 package org.eclipse.compare.internal; 13 14 import java.lang.reflect.InvocationTargetException ; 15 import com.ibm.icu.text.MessageFormat; 16 import java.util.HashSet ; 17 import java.util.Set ; 18 19 import org.eclipse.core.resources.*; 20 import org.eclipse.core.runtime.*; 21 22 import org.eclipse.osgi.util.NLS; 23 import org.eclipse.swt.SWT; 24 import org.eclipse.swt.events.*; 25 import org.eclipse.swt.layout.*; 26 import org.eclipse.swt.widgets.*; 27 28 import org.eclipse.jface.action.*; 29 import org.eclipse.jface.dialogs.*; 30 import org.eclipse.jface.viewers.*; 31 import org.eclipse.jface.window.Window; 32 33 import org.eclipse.compare.*; 34 import org.eclipse.compare.structuremergeviewer.*; 35 36 37 40 class ResourceCompareInput extends CompareEditorInput { 41 42 private static final boolean NORMALIZE_CASE= true; 43 44 private boolean fThreeWay= false; 45 private Object fRoot; 46 private IStructureComparator fAncestor; 47 private IStructureComparator fLeft; 48 private IStructureComparator fRight; 49 private IResource fAncestorResource; 50 private IResource fLeftResource; 51 private IResource fRightResource; 52 private DiffTreeViewer fDiffViewer; 53 private IAction fOpenAction; 54 55 class MyDiffNode extends DiffNode { 56 57 private boolean fDirty= false; 58 private ITypedElement fLastId; 59 private String fLastName; 60 61 62 public MyDiffNode(IDiffContainer parent, int description, ITypedElement ancestor, ITypedElement left, ITypedElement right) { 63 super(parent, description, ancestor, left, right); 64 } 65 public void fireChange() { 66 super.fireChange(); 67 setDirty(true); 68 fDirty= true; 69 if (fDiffViewer != null) 70 fDiffViewer.refresh(this); 71 } 72 void clearDirty() { 73 fDirty= false; 74 } 75 public String getName() { 76 if (fLastName == null) 77 fLastName= super.getName(); 78 if (fDirty) 79 return '<' + fLastName + '>'; 80 return fLastName; 81 } 82 83 public ITypedElement getId() { 84 ITypedElement id= super.getId(); 85 if (id == null) 86 return fLastId; 87 fLastId= id; 88 return id; 89 } 90 } 91 92 static class FilteredBufferedResourceNode extends BufferedResourceNode { 93 FilteredBufferedResourceNode(IResource resource) { 94 super(resource); 95 } 96 protected IStructureComparator createChild(IResource child) { 97 String name= child.getName(); 98 if (CompareUIPlugin.getDefault().filter(name, child instanceof IContainer, false)) 99 return null; 100 return new FilteredBufferedResourceNode(child); 101 } 102 } 103 104 107 ResourceCompareInput(CompareConfiguration config) { 108 super(config); 109 } 110 111 public Viewer createDiffViewer(Composite parent) { 112 fDiffViewer= new DiffTreeViewer(parent, getCompareConfiguration()) { 113 protected void fillContextMenu(IMenuManager manager) { 114 115 if (fOpenAction == null) { 116 fOpenAction= new Action() { 117 public void run() { 118 handleOpen(null); 119 } 120 }; 121 Utilities.initAction(fOpenAction, getBundle(), "action.CompareContents."); } 123 124 boolean enable= false; 125 ISelection selection= getSelection(); 126 if (selection instanceof IStructuredSelection) { 127 IStructuredSelection ss= (IStructuredSelection)selection; 128 if (ss.size() == 1) { 129 Object element= ss.getFirstElement(); 130 if (element instanceof MyDiffNode) { 131 ITypedElement te= ((MyDiffNode) element).getId(); 132 if (te != null) 133 enable= !ITypedElement.FOLDER_TYPE.equals(te.getType()); 134 } else 135 enable= true; 136 } 137 } 138 fOpenAction.setEnabled(enable); 139 140 manager.add(fOpenAction); 141 142 super.fillContextMenu(manager); 143 } 144 }; 145 return fDiffViewer; 146 } 147 148 class SelectAncestorDialog extends MessageDialog { 149 private IResource[] theResources; 150 IResource ancestorResource; 151 IResource leftResource; 152 IResource rightResource; 153 154 private Button[] buttons; 155 156 public SelectAncestorDialog(Shell parentShell, IResource[] theResources) { 157 super(parentShell, CompareMessages.SelectAncestorDialog_title, 158 null, CompareMessages.SelectAncestorDialog_message, 159 MessageDialog.QUESTION, 160 new String [] { IDialogConstants.OK_LABEL, 161 IDialogConstants.CANCEL_LABEL }, 0); 162 this.theResources = theResources; 163 } 164 165 protected Control createCustomArea(Composite parent) { 166 Composite composite = new Composite(parent, SWT.NONE); 167 composite.setLayout(new GridLayout()); 168 buttons = new Button[3]; 169 for (int i = 0; i < 3; i++) { 170 buttons[i] = new Button(composite, SWT.RADIO); 171 buttons[i].addSelectionListener(selectionListener); 172 buttons[i].setText(NLS.bind(CompareMessages.SelectAncestorDialog_option, 173 theResources[i].getFullPath().toPortableString())); 174 buttons[i].setFont(parent.getFont()); 175 buttons[i].setSelection(i == 0); 177 } 178 pickAncestor(0); 179 return composite; 180 } 181 182 private void pickAncestor(int i) { 183 ancestorResource = theResources[i]; 184 leftResource = theResources[i == 0 ? 1 : 0]; 185 rightResource = theResources[i == 2 ? 1 : 2]; 186 } 187 188 private SelectionListener selectionListener = new SelectionAdapter() { 189 public void widgetSelected(SelectionEvent e) { 190 Button selectedButton = (Button) e.widget; 191 if (!selectedButton.getSelection()) 192 return; 193 for (int i = 0; i < 3; i++) 194 if (selectedButton == buttons[i]) 195 pickAncestor(i); 196 } 197 }; 198 } 199 200 boolean setSelection(ISelection s, Shell shell) { 204 205 IResource[] selection= Utilities.getResources(s); 206 207 fThreeWay= selection.length == 3; 208 209 if (fThreeWay) { 210 SelectAncestorDialog dialog = 211 new SelectAncestorDialog(shell, selection); 212 int code = dialog.open(); 213 if (code == Window.CANCEL) 214 return false; 215 216 fAncestorResource= dialog.ancestorResource; 217 fAncestor= getStructure(fAncestorResource); 218 fLeftResource= dialog.leftResource; 219 fRightResource= dialog.rightResource; 220 } else { 221 fAncestorResource= null; 222 fAncestor= null; 223 fLeftResource= selection[0]; 224 fRightResource= selection[1]; 225 } 226 227 fLeft= getStructure(fLeftResource); 228 fRight= getStructure(fRightResource); 229 return true; 230 } 231 232 235 public boolean isEnabled(ISelection s) { 236 237 IResource[] selection= Utilities.getResources(s); 238 if (selection.length < 2 || selection.length > 3) 239 return false; 240 241 boolean threeWay= selection.length == 3; 242 243 if (threeWay) 244 return comparable(selection[0], selection[1]) 247 && comparable(selection[0], selection[2]) 248 && comparable(selection[1], selection[2]); 249 250 return comparable(selection[0], selection[1]); 251 } 252 253 256 void initializeCompareConfiguration() { 257 CompareConfiguration cc= getCompareConfiguration(); 258 if (fLeftResource != null) { 259 cc.setLeftLabel(buildLabel(fLeftResource)); 260 cc.setLeftImage(CompareUIPlugin.getImage(fLeftResource)); 261 } 262 if (fRightResource != null) { 263 cc.setRightLabel(buildLabel(fRightResource)); 264 cc.setRightImage(CompareUIPlugin.getImage(fRightResource)); 265 } 266 if (fThreeWay && fAncestorResource != null) { 267 cc.setAncestorLabel(buildLabel(fAncestorResource)); 268 cc.setAncestorImage(CompareUIPlugin.getImage(fAncestorResource)); 269 } 270 } 271 272 275 private boolean comparable(IResource c1, IResource c2) { 276 return hasStructure(c1) == hasStructure(c2); 277 } 278 279 282 private boolean hasStructure(IResource input) { 283 284 if (input instanceof IContainer) 285 return true; 286 287 if (input instanceof IFile) { 288 IFile file= (IFile) input; 289 String type= file.getFileExtension(); 290 if (type != null) { 291 type= normalizeCase(type); 292 return "JAR".equals(type) || "ZIP".equals(type); } 294 } 295 296 return false; 297 } 298 299 304 private IStructureComparator getStructure(IResource input) { 305 306 if (input instanceof IContainer) 307 return new FilteredBufferedResourceNode(input); 308 309 if (input instanceof IFile) { 310 IStructureComparator rn= new FilteredBufferedResourceNode(input); 311 IFile file= (IFile) input; 312 String type= normalizeCase(file.getFileExtension()); 313 if ("JAR".equals(type) || "ZIP".equals(type)) return new ZipFileStructureCreator().getStructure(rn); 315 return rn; 316 } 317 return null; 318 } 319 320 323 public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException { 324 325 try { 326 fLeftResource.refreshLocal(IResource.DEPTH_INFINITE, pm); 328 fRightResource.refreshLocal(IResource.DEPTH_INFINITE, pm); 329 if (fThreeWay && fAncestorResource != null) 330 fAncestorResource.refreshLocal(IResource.DEPTH_INFINITE, pm); 331 333 pm.beginTask(Utilities.getString("ResourceCompare.taskName"), IProgressMonitor.UNKNOWN); 335 String leftLabel= fLeftResource.getName(); 336 String rightLabel= fRightResource.getName(); 337 338 String title; 339 if (fThreeWay) { 340 String format= Utilities.getString("ResourceCompare.threeWay.title"); String ancestorLabel= fAncestorResource.getName(); 342 title= MessageFormat.format(format, new String [] {ancestorLabel, leftLabel, rightLabel}); 343 } else { 344 String format= Utilities.getString("ResourceCompare.twoWay.title"); title= MessageFormat.format(format, new String [] {leftLabel, rightLabel}); 346 } 347 setTitle(title); 348 349 Differencer d= new Differencer() { 350 protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) { 351 return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right); 352 } 353 }; 354 355 fRoot= d.findDifferences(fThreeWay, pm, null, fAncestor, fLeft, fRight); 356 return fRoot; 357 358 } catch (CoreException ex) { 359 throw new InvocationTargetException (ex); 360 } finally { 361 pm.done(); 362 } 363 } 364 365 public String getToolTipText() { 366 if (fLeftResource != null && fRightResource != null) { 367 String leftLabel= fLeftResource.getFullPath().makeRelative().toString(); 368 String rightLabel= fRightResource.getFullPath().makeRelative().toString(); 369 if (fThreeWay) { 370 String format= Utilities.getString("ResourceCompare.threeWay.tooltip"); String ancestorLabel= fAncestorResource.getFullPath().makeRelative().toString(); 372 return MessageFormat.format(format, new String [] {ancestorLabel, leftLabel, rightLabel}); 373 } 374 String format= Utilities.getString("ResourceCompare.twoWay.tooltip"); return MessageFormat.format(format, new String [] {leftLabel, rightLabel}); 376 } 377 return super.getToolTipText(); 379 } 380 381 private String buildLabel(IResource r) { 382 String n= r.getFullPath().toString(); 383 if (n.charAt(0) == IPath.SEPARATOR) 384 return n.substring(1); 385 return n; 386 } 387 388 public void saveChanges(IProgressMonitor pm) throws CoreException { 389 super.saveChanges(pm); 390 if (fRoot instanceof DiffNode) { 391 try { 392 commit(pm, (DiffNode) fRoot); 393 } finally { 394 if (fDiffViewer != null) 395 fDiffViewer.refresh(); 396 setDirty(false); 397 } 398 } 399 } 400 401 404 private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException { 405 406 if (node instanceof MyDiffNode) 407 ((MyDiffNode)node).clearDirty(); 408 409 ITypedElement left= node.getLeft(); 410 if (left instanceof BufferedResourceNode) 411 ((BufferedResourceNode) left).commit(pm); 412 413 ITypedElement right= node.getRight(); 414 if (right instanceof BufferedResourceNode) 415 ((BufferedResourceNode) right).commit(pm); 416 417 IDiffElement[] children= node.getChildren(); 418 if (children != null) { 419 for (int i= 0; i < children.length; i++) { 420 IDiffElement element= children[i]; 421 if (element instanceof DiffNode) 422 commit(pm, (DiffNode) element); 423 } 424 } 425 } 426 427 430 public Object getAdapter(Class adapter) { 431 if (IFile.class.equals(adapter)) { 432 IProgressMonitor pm= new NullProgressMonitor(); 433 flushViewers(pm); 435 IFile[] files= (IFile[]) getAdapter(IFile[].class); 436 if (files != null && files.length > 0) 437 return files[0]; return null; 439 } 440 if (IFile[].class.equals(adapter)) { 441 HashSet collector= new HashSet (); 442 collectDirtyResources(fRoot, collector); 443 return collector.toArray(new IFile[collector.size()]); 444 } 445 return super.getAdapter(adapter); 446 } 447 448 private void collectDirtyResources(Object o, Set collector) { 449 if (o instanceof DiffNode) { 450 DiffNode node= (DiffNode) o; 451 452 ITypedElement left= node.getLeft(); 453 if (left instanceof BufferedResourceNode) { 454 BufferedResourceNode bn= (BufferedResourceNode) left; 455 if (bn.isDirty()) { 456 IResource resource= bn.getResource(); 457 if (resource instanceof IFile) 458 collector.add(resource); 459 } 460 } 461 462 ITypedElement right= node.getRight(); 463 if (right instanceof BufferedResourceNode) { 464 BufferedResourceNode bn= (BufferedResourceNode) right; 465 if (bn.isDirty()) { 466 IResource resource= bn.getResource(); 467 if (resource instanceof IFile) 468 collector.add(resource); 469 } 470 } 471 472 IDiffElement[] children= node.getChildren(); 473 if (children != null) { 474 for (int i= 0; i < children.length; i++) { 475 IDiffElement element= children[i]; 476 if (element instanceof DiffNode) 477 collectDirtyResources(element, collector); 478 } 479 } 480 } 481 } 482 483 private static String normalizeCase(String s) { 484 if (NORMALIZE_CASE && s != null) 485 return s.toUpperCase(); 486 return s; 487 } 488 489 public boolean canRunAsJob() { 490 return true; 491 } 492 } 493 494 | Popular Tags |