diff options
author | Tomasz Zarna | 2011-10-13 11:36:27 +0000 |
---|---|---|
committer | Tomasz Zarna | 2011-10-13 11:36:27 +0000 |
commit | f0e53ee2640b02d1f95f87dfcfa88331c3336845 (patch) | |
tree | 666e298f81221c128f3c0249c32154b1aef93861 /bundles/org.eclipse.compare.win32 | |
parent | e4281ecfd04ac79545ba778419a1cfa257818d4c (diff) | |
download | eclipse.platform.team-f0e53ee2640b02d1f95f87dfcfa88331c3336845.tar.gz eclipse.platform.team-f0e53ee2640b02d1f95f87dfcfa88331c3336845.tar.xz eclipse.platform.team-f0e53ee2640b02d1f95f87dfcfa88331c3336845.zip |
bug 359032: Move plugins under bundles/org.eclipse.compare/plugins/ to
bundles/
Diffstat (limited to 'bundles/org.eclipse.compare.win32')
21 files changed, 1603 insertions, 0 deletions
diff --git a/bundles/org.eclipse.compare.win32/.classpath b/bundles/org.eclipse.compare.win32/.classpath new file mode 100644 index 000000000..2fbb7a23e --- /dev/null +++ b/bundles/org.eclipse.compare.win32/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.compare.win32/.project b/bundles/org.eclipse.compare.win32/.project new file mode 100644 index 000000000..dd687751b --- /dev/null +++ b/bundles/org.eclipse.compare.win32/.project @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.compare.win32</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.compare.win32/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 000000000..c522e1f4a --- /dev/null +++ b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..32a523dbe --- /dev/null +++ b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,23 @@ +#Tue Feb 01 14:37:12 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.launching.prefs b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 000000000..44fca4e83 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,3 @@ +#Tue Feb 01 14:37:12 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=error diff --git a/bundles/org.eclipse.compare.win32/META-INF/MANIFEST.MF b/bundles/org.eclipse.compare.win32/META-INF/MANIFEST.MF new file mode 100644 index 000000000..9e6ffa1ed --- /dev/null +++ b/bundles/org.eclipse.compare.win32/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.compare.win32;singleton:=true +Bundle-Version: 1.0.200.qualifier +Bundle-Vendor: %providerName +Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Eclipse-PlatformFilter: (osgi.os=win32) +Require-Bundle: org.eclipse.compare;bundle-version="[3.5.0,4.0.0)", + org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)", + org.eclipse.ui.forms;bundle-version="[3.4.0,4.0.0)", + org.eclipse.ui.workbench;bundle-version="[3.5.0,4.0.0)", + org.eclipse.jface;bundle-version="[3.5.0,4.0.0)", + org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", + org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)" +Export-Package: org.eclipse.compare.internal.win32;x-internal:=true +Bundle-Activator: org.eclipse.compare.internal.win32.Activator +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin diff --git a/bundles/org.eclipse.compare.win32/about.html b/bundles/org.eclipse.compare.win32/about.html new file mode 100644 index 000000000..460233046 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/about.html @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>June 2, 2006</p> +<h3>License</h3> + +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> + +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p> + +</body> +</html>
\ No newline at end of file diff --git a/bundles/org.eclipse.compare.win32/build.properties b/bundles/org.eclipse.compare.win32/build.properties new file mode 100644 index 000000000..1b473f7ff --- /dev/null +++ b/bundles/org.eclipse.compare.win32/build.properties @@ -0,0 +1,19 @@ +############################################################################### +# Copyright (c) 2008, 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + icons/,\ + about.html,\ + plugin.properties +src.includes = about.html diff --git a/bundles/org.eclipse.compare.win32/icons/full/dlcl16/save.gif b/bundles/org.eclipse.compare.win32/icons/full/dlcl16/save.gif Binary files differnew file mode 100644 index 000000000..ad505a9c2 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/icons/full/dlcl16/save.gif diff --git a/bundles/org.eclipse.compare.win32/icons/full/elcl16/editor_area.gif b/bundles/org.eclipse.compare.win32/icons/full/elcl16/editor_area.gif Binary files differnew file mode 100644 index 000000000..4b6b76831 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/icons/full/elcl16/editor_area.gif diff --git a/bundles/org.eclipse.compare.win32/icons/full/elcl16/save.gif b/bundles/org.eclipse.compare.win32/icons/full/elcl16/save.gif Binary files differnew file mode 100644 index 000000000..499dd0ca6 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/icons/full/elcl16/save.gif diff --git a/bundles/org.eclipse.compare.win32/plugin.properties b/bundles/org.eclipse.compare.win32/plugin.properties new file mode 100644 index 000000000..5b550f1b4 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/plugin.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2009 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +# +# Resource strings for Compare Win32 Plug-in +# +pluginName = Compare Support for Word +providerName = Eclipse.org + +wordDocumentContentTypeName = Word Document diff --git a/bundles/org.eclipse.compare.win32/plugin.xml b/bundles/org.eclipse.compare.win32/plugin.xml new file mode 100644 index 000000000..76b02ea6d --- /dev/null +++ b/bundles/org.eclipse.compare.win32/plugin.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.2"?>
<!-- + Copyright (c) 2008, 2011 IBM Corporation and others. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html + + Contributors: + IBM Corporation - initial API and implementation + --> + +<plugin> + <extension + point="org.eclipse.compare.contentMergeViewers"> + <viewer + class="org.eclipse.compare.internal.win32.WordViewerCreator" + extensions="doc" + id="org.eclipse.compare.wordMergeViewer"> + </viewer> + <contentTypeBinding + contentMergeViewerId="org.eclipse.compare.wordMergeViewer" + contentTypeId="org.eclipse.compare.wordDoc"> + </contentTypeBinding> + </extension> + + <extension + point="org.eclipse.core.contenttype.contentTypes"> + <content-type + file-extensions="doc, docx" + id="org.eclipse.compare.wordDoc" + name="%wordDocumentContentTypeName"> + </content-type> + </extension> + +</plugin> diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/AbstractMergeViewer.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/AbstractMergeViewer.java new file mode 100644 index 000000000..a66f37104 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/AbstractMergeViewer.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.IEditableContent; +import org.eclipse.compare.IResourceProvider; +import org.eclipse.compare.IStreamContentAccessor; +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; + +/** + * Abstract class that caches any remote contents in local so that external + * tools can be used to show a comparison. + */ +public abstract class AbstractMergeViewer extends Viewer { + + private Object input; + private File leftFile; + private File rightFile; + private File resultFile; + private final CompareConfiguration configuration; + + public AbstractMergeViewer(CompareConfiguration configuration) { + this.configuration = configuration; + } + + public Object getInput() { + return input; + } + + public ISelection getSelection() { + return StructuredSelection.EMPTY; + } + + public void refresh() { + // Nothing to do + } + + public void setInput(Object input) { + this.input = input; + reset(); + } + + protected void reset() { + if (leftFile != null && leftFile.exists()) { + leftFile.delete(); + } + if (rightFile != null && rightFile.exists()) { + rightFile.delete(); + } + if (resultFile != null && resultFile.exists()) { + resultFile.delete(); + } + leftFile = null; + rightFile = null; + resultFile = null; + } + + public void setSelection(ISelection selection, boolean reveal) { + // Nothing to do + } + + protected boolean isOneSided() { + if (input instanceof ICompareInput) { + ICompareInput ci = (ICompareInput) input; + int type = ci.getKind() & Differencer.CHANGE_TYPE_MASK; + return type != Differencer.CHANGE; + } + return false; + } + + protected File getFileForSingleSide() throws CoreException { + File file = getFileForLeft(); + if (file != null && file.exists()) + return file; + return getFileForRight(); + } + + protected File getFileForRight() throws CoreException { + if (rightFile != null) + return rightFile; + ICompareInput ci = getCompareInput(); + if (ci != null) { + ITypedElement right = ci.getRight(); + File file = getLocalFile(right); + if (file != null) { + return file; + } + rightFile = cacheContents(right); + return rightFile; + } + return null; + } + + protected File getFileForLeft() throws CoreException { + if (leftFile != null) + return leftFile; + ICompareInput ci = getCompareInput(); + if (ci != null) { + ITypedElement left = ci.getLeft(); + File file = getLocalFile(left); + if (file != null) { + return file; + } + leftFile = cacheContents(left); + return leftFile; + } + return null; + } + + protected File getResultFile() throws IOException { + if (resultFile != null) + return resultFile; + resultFile = File.createTempFile("merge", ".doc"); //$NON-NLS-1$ //$NON-NLS-2$ + resultFile.deleteOnExit(); + // Need to delete the file so that clients will know that the files doesn't exist yet + resultFile.delete(); + return resultFile; + } + + protected boolean hasResultFile() { + return resultFile != null; + } + + private File cacheContents(ITypedElement element) throws CoreException { + if (element instanceof IStreamContentAccessor) { + IStreamContentAccessor sca = (IStreamContentAccessor) element; + InputStream contents = sca.getContents(); + if (contents != null) { + try { + return createTempFile(contents); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } finally { + try { + contents.close(); + } catch (IOException e) { + // Ignore + } + } + } + } + return null; + } + + private File createTempFile(InputStream contents) throws IOException { + File file = File.createTempFile("compare", ".doc"); //$NON-NLS-1$ //$NON-NLS-2$ + file.deleteOnExit(); + OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + try { + byte[] buffer = new byte[1024]; + int length; + while ((length = contents.read(buffer)) != -1) { + out.write(buffer, 0, length); + } + return file; + } finally { + out.close(); + } + } + + protected ICompareInput getCompareInput() { + if (input instanceof ICompareInput) { + return (ICompareInput) input; + } + return null; + } + + protected File getLocalFile(ITypedElement left) throws CoreException { + IFile file = getEclipseFile(left); + if (file != null) { + URI uri = file.getLocationURI(); + IFileStore store = EFS.getStore(uri); + if (store != null) { + return store.toLocalFile(EFS.NONE, null); + } + } + return null; + } + + protected IFile getEclipseFile(Object element) { + if (element instanceof IResourceProvider) { + IResourceProvider rp = (IResourceProvider) element; + IResource resource = rp.getResource(); + if (resource.getType() == IResource.FILE) { + return (IFile)resource; + } + } + if (element instanceof IAdaptable) { + IAdaptable a = (IAdaptable) element; + Object result = a.getAdapter(IResource.class); + if (result == null) { + result = a.getAdapter(IFile.class); + } + if (result instanceof IFile) { + return (IFile) result; + } + } + return null; + } + + protected IEditableContent getSaveTarget() { + IEditableContent left = getEditableLeft(); + IEditableContent right = getEditableRight(); + if (left != null && right == null) { + return left; + } + if (left == null && right != null) { + return right; + } + return null; + } + + private IEditableContent getEditableLeft() { + ICompareInput compareInput = getCompareInput(); + if (compareInput != null) { + ITypedElement left = compareInput.getLeft(); + if (left instanceof IEditableContent && configuration.isLeftEditable()) { + return (IEditableContent) left; + } + } + return null; + } + + private IEditableContent getEditableRight() { + ICompareInput compareInput = getCompareInput(); + if (compareInput != null) { + ITypedElement right = compareInput.getRight(); + if (right instanceof IEditableContent && configuration.isRightEditable()) { + return (IEditableContent) right; + + } + } + return null; + } + + protected byte[] asBytes(File file) throws IOException { + InputStream in = new BufferedInputStream(new FileInputStream(file)); + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = in.read(buffer)) != -1) { + out.write(buffer, 0, length); + } + out.close(); + return out.toByteArray(); + } finally { + in.close(); + } + } + + public CompareConfiguration getConfiguration() { + return configuration; + } +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/Activator.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/Activator.java new file mode 100644 index 000000000..7b935df48 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/Activator.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; +import org.osgi.framework.BundleContext; + +public class Activator extends Plugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.compare.win32"; + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + public static void log(Throwable e) { + log(new Status(IStatus.ERROR, PLUGIN_ID, 0, "Internal error", e)); + } + + public static void log(IStatus status) { + getDefault().getLog().log(status); + } +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/CompareWin32Messages.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/CompareWin32Messages.java new file mode 100644 index 000000000..80fc1254b --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/CompareWin32Messages.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import org.eclipse.osgi.util.NLS; + +public class CompareWin32Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.compare.internal.win32.messages"; //$NON-NLS-1$ + public static String WordComparison_0; + public static String WordComparison_1; + public static String WordComparison_16; + public static String WordComparison_2; + public static String WordComparison_3; + public static String WordComparison_4; + public static String WordComparison_6; + public static String WordComparison_9; + public static String WordMergeViewer_1; + public static String WordMergeViewer_2; + public static String WordMergeViewer_3; + public static String WordMergeViewer_4; + public static String WordMergeViewer_5; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, CompareWin32Messages.class); + } + + private CompareWin32Messages() { + } +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordComparison.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordComparison.java new file mode 100644 index 000000000..def6628bc --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordComparison.java @@ -0,0 +1,480 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import java.io.File; +import java.util.Vector; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.ole.win32.OLE; +import org.eclipse.swt.ole.win32.OleAutomation; +import org.eclipse.swt.ole.win32.OleClientSite; +import org.eclipse.swt.ole.win32.OleFrame; +import org.eclipse.swt.ole.win32.Variant; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchWindow; + +/** + * Class that manages a Word document comparison using OLE. + */ +public class WordComparison { + + private final OleFrame frame; + private OleClientSite site; + private boolean inplace; + private OleAutomation document; + + public WordComparison(Composite composite) { + frame = new OleFrame(composite, SWT.NONE); + } + + // These helper methods facilitate writing the OLE apps + private static Variant invoke(OleAutomation auto, String command) { + return auto.invoke(property(auto, command), new Variant[0]); + } + + private static Variant invoke(OleAutomation auto, OleAutomation reference, String command) { + return auto.invoke(property(auto, reference, command), new Variant[0]); + } + + private static Variant invoke(OleAutomation auto, OleAutomation reference, String command, String value) { + return auto.invoke(property(auto, reference, command), new Variant[] { new Variant(value) }); + } + + private static Variant invoke(OleAutomation auto, String command, int value) { + return auto.invoke(property(auto, command), new Variant[] { new Variant(value) }); + } + + private static Variant invoke(OleAutomation auto, String command, String value) { + return auto.invoke(property(auto, command), new Variant[] { new Variant(value) }); + } + + private static Variant getVariantProperty(OleAutomation auto, String name) { + Variant varResult = auto.getProperty(property(auto, name)); + if (varResult != null && varResult.getType() != OLE.VT_EMPTY) { + return varResult; + } + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_0, name)); + } + + private static OleAutomation getAutomationProperty(OleAutomation auto, String name) { + Variant varResult = getVariantProperty(auto, name); + try { + OleAutomation automation = varResult.getAutomation(); + if (automation != null) + return automation; + } finally { + varResult.dispose(); + } + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_1, name)); + } + + private static OleAutomation getAutomationResult(OleAutomation auto, String command, int value) { + Variant varResult = invoke(auto, command, value); + if (varResult != null) { + try { + OleAutomation result = varResult.getAutomation(); + if (result != null) + return result; + } finally { + varResult.dispose(); + } + } + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_2, command, Integer.toString(value))); + } + + private static OleAutomation getAutomationResult(OleAutomation auto, String command, String value) { + Variant varResult = invoke(auto, command, value); + if (varResult != null) { + try { + OleAutomation result = varResult.getAutomation(); + if (result != null) + return result; + } finally { + varResult.dispose(); + } + } + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_3, command, value)); + } + + + /** + * <p>This methods workarounds the feature in doc documents. Some properties are not accessible + * using names when a diff document is created. The workaround is to obtain the id of the + * method from an original document and use it in the newly created one.</p> + * + * <p>An exception is thrown if the id cannot be retrieved</p> + * + * Reference information for id assignment: <a href=" + * http://msdn.microsoft.com/en-us/library/w7a36sdf%28VS.80%29.aspx">http://msdn.microsoft.com/en-us/library/w7a36sdf%28VS.80%29.aspx</a> + * + * @param auto - object from which we want to get the property, must not be <code>null</code> + * @param reference - an reference object from which the property will be obtained. + * @param name - the name of the property, must not be <code>null</code> + */ + private static int property(OleAutomation auto, OleAutomation reference, String name) { + int[] ids = auto.getIDsOfNames(new String[] { name }); + if (ids != null) { + return ids[0]; + } + if(reference == null) throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name)) ; + + // the property was not retrieved at that point, try to get it from the reference object + ids = reference.getIDsOfNames(new String[] { name }); + if (ids == null) { + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name)); + } + return ids[0]; + } + + private static int property(OleAutomation auto, String name) { + int[] ids = auto.getIDsOfNames(new String[] { name }); + if (ids == null) throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_4, name)); + return ids[0]; + } + + private static boolean setProperty(OleAutomation auto, String name, boolean value) { + return auto.setProperty(property(auto, name), new Variant(value)); + } + + /** + * Open the file at the given path as a document in Word. + * + * @param filePath + * the path of the file containing the document + * @param inplace + * whether Word is to be opened in-place or in a separate window + * @throws SWTException + * if the document could not be opened for some reason + */ + public void openDocument(String filePath, boolean inplace) throws SWTException { + resetSite(inplace ? filePath : null); + if (inplace) { + site.doVerb(OLE.OLEIVERB_SHOW); + } else { + OleAutomation application = createApplication(); + try { + // Track the external document we just opened + document = openDocument(application, filePath); + setDocumentVisible(document, true); + } finally { + application.dispose(); + } + } + } + + /** + * Compares the base document with the revised document and saves the + * comparison in the working copy which can then be opened using + * openDocument. + * + * @param baseDocument + * the base document + * @param revisedDocument + * the revised document + * @param workingCopy + * the working copy (will be overwritten) + * @throws SWTException + * if an SWT error occurs + */ + public void createWorkingCopy(String baseDocument, String revisedDocument, String workingCopy) throws SWTException { + resetSite(null); + OleAutomation application = createApplication(); + try { + OleAutomation document = openDocument(application, revisedDocument); + try { + setDocumentVisible(document,false); + compareDocument(document, baseDocument, revisedDocument); + OleAutomation activeDocument = getActiveDocument(application); + try { + Variant varResult = invoke(activeDocument, document, "SaveAs", workingCopy); //$NON-NLS-1$ + if (varResult == null) + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_6, workingCopy)); + varResult.dispose(); + } finally { + closeDocument(activeDocument, document); + } + } finally { + closeDocument(document, null); + } + } finally { + try { + //Quit application without saving any changes + int [] ids = application.getIDsOfNames(new String [] {"Quit", "SaveChanges"}); + final Variant wdDoNotSaveChanges = new Variant(0); + Variant varResult = application.invoke(ids[0], new Variant[]{ wdDoNotSaveChanges }, new int[] {ids[1]}); + if (varResult != null) { + varResult.dispose(); + } + } catch (SWTException e) { + // We don't want to throw the exception as we may mask another exception + Activator.log(e); + } finally { + application.dispose(); + } + } + } + + private void closeDocument(OleAutomation document, OleAutomation reference) { + // Close the first document: destination.Close() + try { + Variant varResult = invoke(document, reference, "Close"); //$NON-NLS-1$ + if (varResult != null) { + varResult.dispose(); + } + } catch (SWTException e) { + // We don't want to throw the exception as we may mask another + // exception + Activator.log(e); + } finally { + document.dispose(); + } + } + + private void compareDocument(OleAutomation document, String baseDocument, String revisedDocument) { + // Compare to the second document: compare = destination.Compare(p1) + Variant varResult = invoke(document, "Compare", baseDocument); //$NON-NLS-1$ + if (varResult == null) + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_9, baseDocument, revisedDocument)); + varResult.dispose(); + } + + private boolean getDocumentDirty(OleAutomation document) { + // word.document.Saved + if (document != null) { + Variant variantProperty = getVariantProperty(document, "Saved"); //$NON-NLS-1$ + if (variantProperty != null) { + try { + return !variantProperty.getBoolean(); + } finally { + variantProperty.dispose(); + } + } + } + return false; + } + + private void setDocumentVisible(OleAutomation document, boolean visible) { + // Hide it: destination.Windows[0].Visible=0|1 + OleAutomation windows = getAutomationProperty(document, "Windows"); //$NON-NLS-1$ + try { + OleAutomation window = getAutomationResult(windows, "Item", 1); //$NON-NLS-1$ + try { + setProperty(window, "Visible", visible); //$NON-NLS-1$ + } finally { + window.dispose(); + } + } finally { + windows.dispose(); + } + } + + private OleAutomation openDocument(OleAutomation application, String doc) { + // Open the first document: word.Documents.Open(p2) + OleAutomation documents = getAutomationProperty(application, "Documents"); //$NON-NLS-1$ + try { + OleAutomation document = getAutomationResult(documents, "Open", doc); //$NON-NLS-1$ + if (document == null) { + throw new SWTException(NLS.bind(CompareWin32Messages.WordComparison_16, doc)); + } + return document; + } finally { + documents.dispose(); + } + } + + private OleAutomation getActiveDocument(OleAutomation application) { + return getAutomationProperty(application, "ActiveDocument"); //$NON-NLS-1$ + } + + /* + * Create a handle to the application + */ + private OleAutomation createApplication() { + return new OleAutomation(site); + } + + /* + * When opening a new comparison, we want to close any existing site + * and create a new one. + */ + private void resetSite(String filePath) { + if (site != null && !site.isDisposed()) { + disposeSite(); + } + inplace = filePath != null; + if (inplace) { + site = new OleClientSite(frame, SWT.NONE, "Word.Document", new File(filePath)); //$NON-NLS-1$ + } else { + site = new OleClientSite(frame, SWT.NONE, "Word.Application"); //$NON-NLS-1$ + } + } + + private void disposeSite() { + if (document != null) { + closeDocument(document, null); + document = null; + OleAutomation application = createApplication(); + try { + OleAutomation documents = getAutomationProperty(application, "Documents"); //$NON-NLS-1$ + try { + Variant property = getVariantProperty(documents, "Count"); //$NON-NLS-1$ + if (property != null) { + try { + if (property.getLong() == 0) { + // There are no other documents open so close the application + Variant result = invoke(application, "Quit"); //$NON-NLS-1$ + if (result != null) { + result.dispose(); + } + } + } finally { + property.dispose(); + } + } + } finally { + documents.dispose(); + } + } finally { + application.dispose(); + } + } + site.dispose(); + site = null; + } + + public void saveAsDocument(String doc) { + if (site == null || site.isDisposed()) return; + if (inplace) { + site.deactivateInPlaceClient(); + site.save(new File(doc), true); + site.doVerb(OLE.OLEIVERB_SHOW); + } else if (document != null) { + try { + Variant variant = invoke(document, "SaveAs", doc); //$NON-NLS-1$ + if (variant != null) { + variant.dispose(); + } + } catch (SWTException e) { + // Ignore since this probably means the document was closed by the user + } + } + } + + /** + * Return the OLEFrame for the comparison document. + * @return the OLEFrame for the comparison document + */ + public OleFrame getFrame() { + return frame; + } + + /** + * Dispose of the comparison. + */ + public void dispose() { + try { + disposeSite(); + } finally { + if (!frame.isDisposed()) { + frame.dispose(); + } + } + } + + /** + * Return whether the comparison document is dirty. This method handles + * both an in-place document and a document opened in a separate window. + * @return weather the comparison document is dirty + */ + public boolean isDirty() { + return (inplace && site != null && !site.isDisposed() && site.isDirty()) + || (!inplace && getDocumentDirty(document)); + } + + /** + * Initialize the workbench menus for proper menu merging + * Copied from org.eclipse.ui.internal.editorsupport.win32OleEditor + */ + protected void initializeWorkbenchMenus(IWorkbenchWindow window) { + //If there was an OLE Error or nothing has been created yet + if (frame == null || frame.isDisposed()) + return; + // Get the browser menu bar. If one does not exist then + // create it. + Shell shell = frame.getShell(); + Menu menuBar = shell.getMenuBar(); + if (menuBar == null) { + menuBar = new Menu(shell, SWT.BAR); + shell.setMenuBar(menuBar); + } + + // Swap the file and window menus. + MenuItem[] windowMenu = new MenuItem[1]; + MenuItem[] fileMenu = new MenuItem[1]; + Vector containerItems = new Vector(); + + for (int i = 0; i < menuBar.getItemCount(); i++) { + MenuItem item = menuBar.getItem(i); + String id = ""; //$NON-NLS-1$ + if (item.getData() instanceof IMenuManager) + id = ((IMenuManager) item.getData()).getId(); + if (id.equals(IWorkbenchActionConstants.M_FILE)) + fileMenu[0] = item; + else if (id.equals(IWorkbenchActionConstants.M_WINDOW)) + windowMenu[0] = item; + else { + if (window.isApplicationMenu(id)) { + containerItems.addElement(item); + } + } + } + MenuItem[] containerMenu = new MenuItem[containerItems.size()]; + containerItems.copyInto(containerMenu); + frame.setFileMenus(fileMenu); + frame.setContainerMenus(containerMenu); + frame.setWindowMenus(windowMenu); + } + + /** + * Return whether the comparison document is being shown in-place or in + * a separate window. + * @return whether the comparison document is being shown in-place or in + * a separate window + */ + public boolean isInplace() { + return inplace; + } + + /** + * Return whether the comparison document is open. + * @return whether the comparison document is open + */ + public boolean isOpen() { + return site != null && !site.isDisposed(); + } + + /** + * Close any open documents + */ + public void close() { + if (isOpen()) { + disposeSite(); + } + } +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.java new file mode 100644 index 000000000..ac17d303f --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.java @@ -0,0 +1,472 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.CompareUI; +import org.eclipse.compare.CompareViewerPane; +import org.eclipse.compare.IEditableContent; +import org.eclipse.compare.IPropertyChangeNotifier; +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.contentmergeviewer.IFlushable; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.part.PageBook; + +public class WordMergeViewer extends AbstractMergeViewer implements IFlushable, IPropertyChangeNotifier { + + private static final String RESOURCE_BUNDLE_NAME = "org.eclipse.compare.internal.win32.WordMergeViewer"; //$NON-NLS-1$ + + private FormToolkit formToolkit; + private PageBook composite; + private Composite docArea; + private Composite textArea; + private Label description; + private WordComparison wordArea; + private boolean isDirty; + private ListenerList listeners = new ListenerList(ListenerList.IDENTITY); + private Action saveAction; + private ResourceBundle resourceBundle; + private Action inplaceAction; + private long resultFileTimestamp = -1; + + public WordMergeViewer(Composite parent, CompareConfiguration configuration) { + super(configuration); + createContentArea(parent); + getControl().addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handleDispose(); + } + }); + getControl().setData(CompareUI.COMPARE_VIEWER_TITLE, CompareWin32Messages.WordMergeViewer_1); + IToolBarManager toolBarManager = CompareViewerPane.getToolBarManager(parent); + if (toolBarManager != null) { + toolBarManager.removeAll(); + initializeToolbar(toolBarManager); + } + updateEnablements(); + } + + private void createContentArea(Composite parent) { + formToolkit = new FormToolkit(parent.getDisplay()); + composite = new PageBook(parent, SWT.NONE); + createDocArea(composite); + createTextArea(composite); + } + + private void initializeToolbar(IToolBarManager toolBarManager) { + toolBarManager.add(new Separator("modes")); //$NON-NLS-1$ + toolBarManager.add(new Separator("file")); //$NON-NLS-1$ + CompareConfiguration configuration = getConfiguration(); + // For now, only support saving if one side is editable + if (configuration.isRightEditable() || configuration.isLeftEditable() + && (configuration.isRightEditable() != configuration.isLeftEditable())) { + saveAction = new Action() { + public void run() { + saveDocument(); + } + }; + initAction(saveAction, getResourceBundle(), "action.save."); //$NON-NLS-1$ + toolBarManager.appendToGroup("file", saveAction); //$NON-NLS-1$ + } + + inplaceAction = new Action(CompareWin32Messages.WordMergeViewer_2, Action.AS_CHECK_BOX) { + public void run() { + toggleInplaceExternalState(); + } + }; + initAction(inplaceAction, getResourceBundle(), "action.inplace."); //$NON-NLS-1$ + toolBarManager.appendToGroup("modes", inplaceAction); //$NON-NLS-1$ + + toolBarManager.update(true); + } + + /* + * Initialize the given Action from a ResourceBundle. + */ + private static void initAction(IAction a, ResourceBundle bundle, String prefix) { + + String labelKey= "label"; //$NON-NLS-1$ + String tooltipKey= "tooltip"; //$NON-NLS-1$ + String imageKey= "image"; //$NON-NLS-1$ + String descriptionKey= "description"; //$NON-NLS-1$ + + if (prefix != null && prefix.length() > 0) { + labelKey= prefix + labelKey; + tooltipKey= prefix + tooltipKey; + imageKey= prefix + imageKey; + descriptionKey= prefix + descriptionKey; + } + + a.setText(getString(bundle, labelKey, labelKey)); + a.setToolTipText(getString(bundle, tooltipKey, null)); + a.setDescription(getString(bundle, descriptionKey, null)); + + String relPath= getString(bundle, imageKey, null); + if (relPath != null && relPath.trim().length() > 0) { + + String dPath; + String ePath; + + if (relPath.indexOf("/") >= 0) { //$NON-NLS-1$ + String path= relPath.substring(1); + dPath= 'd' + path; + ePath= 'e' + path; + } else { + dPath= "dlcl16/" + relPath; //$NON-NLS-1$ + ePath= "elcl16/" + relPath; //$NON-NLS-1$ + } + + ImageDescriptor id= getImageDescriptor(dPath); // we set the disabled image first (see PR 1GDDE87) + if (id != null) + a.setDisabledImageDescriptor(id); + id= getImageDescriptor(ePath); + if (id != null) { + a.setImageDescriptor(id); + a.setHoverImageDescriptor(id); + } + } + } + + private static ImageDescriptor getImageDescriptor(String relativePath) { + IPath path= new Path("$nl$/icons/full/").append(relativePath); + URL url= FileLocator.find(Activator.getDefault().getBundle(), path, null); + if (url == null) + return null; + return ImageDescriptor.createFromURL(url); + } + + private static String getString(ResourceBundle bundle, String key, String dfltValue) { + + if (bundle != null) { + try { + return bundle.getString(key); + } catch (MissingResourceException x) { + // fall through + } + } + return dfltValue; + } + + private ResourceBundle getResourceBundle() { + if (resourceBundle == null) { + resourceBundle = ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME); + } + return resourceBundle; + } + + private Composite createComposite(Composite parent) { + return formToolkit.createComposite(parent); + } + + private void updateEnablements() { + if (saveAction != null) + saveAction.setEnabled(isDirty()); + inplaceAction.setChecked(wordArea.isInplace()); + inplaceAction.setEnabled(wordArea.isOpen()); + } + + + private void createDocArea(PageBook book) { + docArea = createComposite(book); + docArea.setLayout(GridLayoutFactory.fillDefaults().create()); + wordArea = new WordComparison(docArea); + IWorkbenchPart workbenchPart = getConfiguration().getContainer().getWorkbenchPart(); + if (workbenchPart != null) { + wordArea.initializeWorkbenchMenus(workbenchPart.getSite().getWorkbenchWindow()); + } + wordArea.getFrame().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + wordArea.getFrame().setBackground(formToolkit.getColors().getBackground()); + updateDirtyFlag(); + } + + private void createTextArea(PageBook book) { + textArea = createComposite(book); + textArea.setLayout(GridLayoutFactory.fillDefaults().extendedMargins(10, 10, 10, 10).create()); + description = formToolkit.createLabel(textArea, getTextDescription(), SWT.WRAP); + description.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + + protected void saveDocument() { + try { + File result = getResultFile(); + wordArea.saveAsDocument(result.getAbsolutePath()); + // Forward the saved content to the save target + IEditableContent saveTarget = getSaveTarget(); + if (saveTarget == null) { + if (MessageDialog.openQuestion(WordMergeViewer.this.composite.getShell(), "Save to File?", "The compare editor is not saveable. Would you like to save your changes to another file?")) { + FileDialog dialog = new FileDialog(WordMergeViewer.this.composite.getShell(), SWT.SAVE); + String filename = dialog.open(); + if (filename != null) { + wordArea.saveAsDocument(filename); + } + } + } else { + synchronized (result) { + if (result.exists()) { + saveTarget.setContent(asBytes(result)); + resultFileTimestamp = result.lastModified(); + } + } + } + updateEnablements(); + } catch (IOException e) { + ErrorDialog.openError(WordMergeViewer.this.composite.getShell(), null, null, new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } catch (SWTException e) { + ErrorDialog.openError(WordMergeViewer.this.composite.getShell(), null, null, new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } + } + + public void flush(IProgressMonitor monitor) { + Display.getDefault().syncExec(new Runnable() { + public void run() { + if (isReallyDirty()) + saveDocument(); + } + }); + } + + + protected void toggleInplaceExternalState() { + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + public void run() { + try { + if (isReallyDirty()) { + // If the file is dirty, save the result file before switching so our changes are not lost + try { + File result = getResultFile(); + wordArea.saveAsDocument(result.getAbsolutePath()); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } + } + openComparison(!wordArea.isInplace()); + } catch (CoreException e) { + ErrorDialog.openError(WordMergeViewer.this.composite.getShell(), null, null, e.getStatus()); + Activator.log(e); + } + } + }); + } + + private boolean isReallyDirty() { + return isDirty() || wordArea.isDirty(); + } + + private void openComparison(boolean inplace) throws CoreException { + try { + if (isOneSided()) { + File file = getFileForSingleSide(); + if (file != null) { + try { + wordArea.openDocument(file.getAbsolutePath(), inplace); + } catch (SWTException e) { + throw new CoreException(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, NLS.bind( + CompareWin32Messages.WordComparison_16, + file.getAbsolutePath()), e)); + } + } + } else { + File left = getFileForLeft(); + File right = getFileForRight(); + if (left != null && right != null) { + File result = getResultFile(); + int direction = getCompareInput().getKind() & Differencer.DIRECTION_MASK; + File base, revised; + if (direction == Differencer.RIGHT) { + base = left; + revised = right; + } else { + base = right; + revised = left; + } + synchronized (result) { + if (!result.exists()) { + wordArea.createWorkingCopy(base.getAbsolutePath(), revised.getAbsolutePath(), result.getAbsolutePath()); + resultFileTimestamp = result.lastModified(); + description.setText(getTextDescription()); + } + try { + wordArea.openDocument(result.getAbsolutePath(), inplace); + } catch (SWTException e) { + throw new CoreException(new Status(IStatus.ERROR, + Activator.PLUGIN_ID, NLS.bind( + CompareWin32Messages.WordComparison_16, + result.getAbsolutePath()), e)); + } + } + } + } + if (wordArea.isInplace()) { + composite.showPage(docArea); + } else { + composite.showPage(textArea); + } + } catch (SWTException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e)); + } + updateEnablements(); + } + + private String getTextDescription() { + if (saveAction != null &&hasResultFile()) { + IEditableContent saveTarget = getSaveTarget(); + String name = CompareWin32Messages.WordMergeViewer_3; + if (saveTarget instanceof ITypedElement) { + ITypedElement te = (ITypedElement) saveTarget; + name = te.getName(); + } + try { + return NLS.bind(CompareWin32Messages.WordMergeViewer_4, getResultFile().getName(), name); + } catch (IOException e) { + // This shouldn't happen since the result file has already been created + } + } + return CompareWin32Messages.WordMergeViewer_5; + } + + public Control getControl() { + return composite; + } + + public void setInput(Object input) { + super.setInput(input); + try { + openComparison(true); + } catch (CoreException e) { + ErrorDialog.openError(WordMergeViewer.this.composite.getShell(), null, null, e.getStatus()); + Activator.log(e); + } + } + + private void updateDirtyFlag() { + final Runnable dirtyFlagUpdater = new Runnable() { + public void run() { + if (wordArea.getFrame().isDisposed()) + return; + boolean dirty = wordArea.isDirty(); + if (hasResultFile()) { + try { + File resultFile = getResultFile(); + synchronized (resultFile) { + if (resultFile.exists()) { + long lastModified = resultFile.lastModified(); + if (lastModified != resultFileTimestamp) { + dirty = true; + } + } + } + } catch (IOException e) { + // Shouldn't happen since we only get the result file if it has already been created + } + } + if (isDirty() != dirty) { + setDirty(dirty); + } + composite.getDisplay().timerExec(1000, this); + } + }; + dirtyFlagUpdater.run(); + } + + protected boolean isDirty() { + return isDirty; + } + + protected void setDirty(boolean dirty) { + if (isDirty != dirty) { + isDirty = dirty; + updateEnablements(); + firePropertyChange(CompareEditorInput.DIRTY_STATE, Boolean.valueOf(!isDirty), Boolean.valueOf(isDirty)); + } + } + + private void firePropertyChange(String property, Object oldValue, Object newValue) { + Object[] allListeners = listeners.getListeners(); + final PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue); + for (int i = 0; i < allListeners.length; i++) { + final IPropertyChangeListener listener = (IPropertyChangeListener)allListeners[i]; + SafeRunner.run(new SafeRunnable() { + public void run() throws Exception { + listener.propertyChange(event); + } + }); + } + } + + public void addPropertyChangeListener(IPropertyChangeListener listener) { + listeners.add(listener); + } + + public void removePropertyChangeListener(IPropertyChangeListener listener) { + listeners.remove(listener); + } + + private void handleDispose() { + BusyIndicator.showWhile(Display.getDefault(), new Runnable() { + public void run() { + wordArea.dispose(); + formToolkit.dispose(); + reset(); + } + }); + } + + protected void reset() { + if (wordArea.isOpen()) { + wordArea.close(); + } + super.reset(); + } +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.properties b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.properties new file mode 100644 index 000000000..6118d570c --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordMergeViewer.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### + +action.save.label=Save +action.save.tooltip=Save the changes to the Word document comparison +action.save.image=save.gif + +action.inplace.label=Edit Inplace +action.inplace.tooltip=Toggle whether the word document is edited in-place or in a separate window +action.inplace.image=editor_area.gif
\ No newline at end of file diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordViewerCreator.java b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordViewerCreator.java new file mode 100644 index 000000000..85d6e05b6 --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/WordViewerCreator.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.compare.internal.win32; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.IViewerCreator; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; + +/** + * Factory registered with the <code>org.eclipse.compare.contentMergeViewers</code> + * extension point to create a Word document comparison. + */ +public class WordViewerCreator implements IViewerCreator { + + public Viewer createViewer(Composite parent, CompareConfiguration config) { + return new WordMergeViewer(parent, config); + } + + +} diff --git a/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/messages.properties b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/messages.properties new file mode 100644 index 000000000..0d0e4904e --- /dev/null +++ b/bundles/org.eclipse.compare.win32/src/org/eclipse/compare/internal/win32/messages.properties @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (c) 2008 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +# NLS_ENCODING=UTF-8 +# NLS_MESSAGEFORMAT_VAR +WordMergeViewer_1=Word Document Compare +WordMergeViewer_2=Inplace +WordMergeViewer_3=<unknown> +WordMergeViewer_4=The Word document comparison is being shown in a separate window. The comparison is using the temporary file ''{0}'' to host the comparison. To save this file back to ''{1}'', you will need to save this compare editor. +WordMergeViewer_5=The Word document comparison is being shown in a separate window. You can click the 'Toggle in-place' toolbar button to have the document appear inside this pane. +WordComparison_0=The property ''{0}'' could not be retrieved +WordComparison_1=The property ''{0}'' could not be retrieved +WordComparison_2=The command ''{0}'' with value ''{1}'' had no result +WordComparison_3=The command ''{0}'' with value ''{1}'' had no result +WordComparison_4=Invalid property name: {0}. +WordComparison_6=Document ''{0}'' could not be saved +WordComparison_9=The request to the Word application to perform the comparison between ''{0}'' and ''{1}'' failed. Comparing the files manually may succeed. +WordComparison_16=The document at {0} could not be opened |