/** * This file Copyright (c) 2005-2010 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain Eclipse Public Licensed code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.core.ui.editors; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.HashSet; import java.util.Set; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.internal.BufferedResourceNode; import org.eclipse.compare.internal.Utilities; import org.eclipse.compare.structuremergeviewer.DiffNode; import org.eclipse.compare.structuremergeviewer.DiffTreeViewer; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.compare.structuremergeviewer.IDiffContainer; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Composite; /** * @author Kevin Sawicki (ksawicki@aptana.com) */ public class FileCompareEditorInput extends CompareEditorInput { private Object fRoot; private FileNode fLeft; private FileNode fRight; private File fLeftResource; private File fRightResource; private DiffTreeViewer fDiffViewer; private IAction fOpenAction; class MyDiffNode extends DiffNode { private boolean fDirty = false; private ITypedElement fLastId; private String fLastName; /** * MyDiffNode constructor * * @param parent * @param description * @param ancestor * @param left * @param right */ public MyDiffNode(IDiffContainer parent, int description, ITypedElement ancestor, ITypedElement left, ITypedElement right) { super(parent, description, ancestor, left, right); } /** * @see org.eclipse.compare.structuremergeviewer.DiffNode#fireChange() */ public void fireChange() { super.fireChange(); setDirty(true); fDirty = true; if (fDiffViewer != null) fDiffViewer.refresh(this); } void clearDirty() { fDirty = false; } /** * @see org.eclipse.compare.structuremergeviewer.DiffNode#getName() */ public String getName() { if (fLastName == null) fLastName = super.getName(); if (fDirty) return '<' + fLastName + '>'; return fLastName; } /** * @see org.eclipse.compare.structuremergeviewer.DiffNode#getId() */ public ITypedElement getId() { ITypedElement id = super.getId(); if (id == null) return fLastId; fLastId = id; return id; } } /** * Creates an compare editor input for the given selection. * * @param config */ public FileCompareEditorInput(CompareConfiguration config) { super(config); } /** * @see org.eclipse.compare.CompareEditorInput#createDiffViewer(org.eclipse.swt.widgets.Composite) */ public Viewer createDiffViewer(Composite parent) { fDiffViewer = new DiffTreeViewer(parent, getCompareConfiguration()) { protected void fillContextMenu(IMenuManager manager) { if (fOpenAction == null) { fOpenAction = new Action() { public void run() { handleOpen(null); } }; Utilities.initAction(fOpenAction, getBundle(), "action.CompareContents."); //$NON-NLS-1$ } boolean enable = false; ISelection selection = getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() == 1) { Object element = ss.getFirstElement(); if (element instanceof MyDiffNode) { ITypedElement te = ((MyDiffNode) element).getId(); if (te != null) enable = !ITypedElement.FOLDER_TYPE.equals(te.getType()); } else enable = true; } } fOpenAction.setEnabled(enable); manager.add(fOpenAction); super.fillContextMenu(manager); } }; return fDiffViewer; } /** * Sets the left resource * * @param resource */ public void setLeftResource(File resource) { this.fLeftResource = resource; this.fLeft = new FileNode(this.fLeftResource); } /** * Sets the right resource * * @param resource */ public void setRightResource(File resource) { this.fRightResource = resource; this.fRight = new FileNode(this.fRightResource); } /** * Initializes the images in the compare configuration. */ void initializeCompareConfiguration() { CompareConfiguration cc = getCompareConfiguration(); if (fLeft != null) { cc.setLeftLabel(fLeft.getName()); cc.setLeftImage(fLeft.getImage()); } if (fRight != null) { cc.setRightLabel(fRight.getName()); cc.setRightImage(fRight.getImage()); } } /** * Method for any file prep-work before running the differencer */ protected void prepareFiles() { // Does nothing by default, subclasses should override } /** * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor) */ public Object prepareInput(IProgressMonitor pm) throws InvocationTargetException { try { pm.beginTask(Utilities.getString("ResourceCompare.taskName"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ prepareFiles(); String leftLabel = fLeftResource.getName(); String rightLabel = fRightResource.getName(); String format = Utilities.getString("ResourceCompare.twoWay.title"); //$NON-NLS-1$ String title = MessageFormat.format(format, new String[] { leftLabel, rightLabel }); setTitle(title); Differencer d = new Differencer() { protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) { return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement) ancestor, (ITypedElement) left, (ITypedElement) right); } }; fRoot = d.findDifferences(false, pm, null, null, fLeft, fRight); return fRoot; } finally { pm.done(); } } /** * @see org.eclipse.compare.CompareEditorInput#getToolTipText() */ public String getToolTipText() { if (fLeftResource != null && fRightResource != null) { String leftLabel = fLeftResource.getAbsolutePath(); String rightLabel = fRightResource.getAbsolutePath(); String format = Utilities.getString("ResourceCompare.twoWay.tooltip"); //$NON-NLS-1$ return MessageFormat.format(format, new String[] { leftLabel, rightLabel }); } // fall back return super.getToolTipText(); } /** * @see org.eclipse.compare.CompareEditorInput#saveChanges(org.eclipse.core.runtime.IProgressMonitor) */ public void saveChanges(IProgressMonitor pm) throws CoreException { super.saveChanges(pm); if (fRoot instanceof DiffNode) { try { commit(pm, (DiffNode) fRoot); } finally { if (fDiffViewer != null) fDiffViewer.refresh(); setDirty(false); } } } /* * Recursively walks the diff tree and commits all changes. */ private static void commit(IProgressMonitor pm, DiffNode node) throws CoreException { if (node instanceof MyDiffNode) ((MyDiffNode) node).clearDirty(); ITypedElement left = node.getLeft(); if (left instanceof BufferedResourceNode) ((BufferedResourceNode) left).commit(pm); ITypedElement right = node.getRight(); if (right instanceof BufferedResourceNode) ((BufferedResourceNode) right).commit(pm); IDiffElement[] children = node.getChildren(); if (children != null) { for (int i = 0; i < children.length; i++) { IDiffElement element = children[i]; if (element instanceof DiffNode) commit(pm, (DiffNode) element); } } } /** * @see org.eclipse.compare.CompareEditorInput#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { if (IFile[].class.equals(adapter)) { HashSet collector = new HashSet(); collectDirtyResources(fRoot, collector); return collector.toArray(new IFile[collector.size()]); } return super.getAdapter(adapter); } private void collectDirtyResources(Object o, Set collector) { if (o instanceof DiffNode) { DiffNode node = (DiffNode) o; ITypedElement left = node.getLeft(); if (left instanceof BufferedResourceNode) { BufferedResourceNode bn = (BufferedResourceNode) left; if (bn.isDirty()) { IResource resource = bn.getResource(); if (resource instanceof IFile) collector.add(resource); } } ITypedElement right = node.getRight(); if (right instanceof BufferedResourceNode) { BufferedResourceNode bn = (BufferedResourceNode) right; if (bn.isDirty()) { IResource resource = bn.getResource(); if (resource instanceof IFile) collector.add(resource); } } IDiffElement[] children = node.getChildren(); if (children != null) { for (int i = 0; i < children.length; i++) { IDiffElement element = children[i]; if (element instanceof DiffNode) collectDirtyResources(element, collector); } } } } }