View | Details | Raw Unified | Return to bug 193324 | Differences between
and this patch

Collapse All | Expand All

(-)plugin.properties (+2 lines)
Lines 79-81 Link Here
79
CompareLocalHistory.tooltip= Compare the Selected Resource with Local History
79
CompareLocalHistory.tooltip= Compare the Selected Resource with Local History
80
ReplaceLocalHistory.label= &Local History...
80
ReplaceLocalHistory.label= &Local History...
81
ReplaceLocalHistory.tooltip= Replace the Selected Resource with Local History
81
ReplaceLocalHistory.tooltip= Replace the Selected Resource with Local History
82
CompareWithEachOtherAction.label= &Each Other
83
CompareWithEachOtherAction.tooltip= Compare the Selected Resources
(-)plugin.xml (+9 lines)
Lines 154-159 Link Here
154
               enablesFor="1"
154
               enablesFor="1"
155
               overrideActionId="replaceFromHistory"
155
               overrideActionId="replaceFromHistory"
156
               tooltip="%ReplaceLocalHistory.tooltip"/>
156
               tooltip="%ReplaceLocalHistory.tooltip"/>
157
         <action
158
               class="org.eclipse.team.internal.ui.actions.CompareAction"
159
               enablesFor="2+"
160
               id="org.eclipse.team.ui.compareWithEachOther"
161
               label="%CompareWithEachOtherAction.label"
162
               menubarPath="compareWithMenu/compareWithGroup"
163
               overrideActionId="compareWithEachOther"
164
               tooltip="CompareWithEachOtherAction.tooltip">
165
         </action>
157
      </objectContribution>
166
      </objectContribution>
158
      <objectContribution
167
      <objectContribution
159
            objectClass="org.eclipse.core.resources.IResource"
168
            objectClass="org.eclipse.core.resources.IResource"
(-)src/org/eclipse/team/ui/synchronize/SaveableCompareEditorInput.java (-332 / +11 lines)
Lines 10-43 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.team.ui.synchronize;
11
package org.eclipse.team.ui.synchronize;
12
12
13
import java.lang.reflect.InvocationTargetException;
14
15
import org.eclipse.compare.*;
13
import org.eclipse.compare.*;
16
import org.eclipse.compare.structuremergeviewer.*;
14
import org.eclipse.compare.structuremergeviewer.*;
17
import org.eclipse.core.resources.IFile;
15
import org.eclipse.core.resources.IFile;
18
import org.eclipse.core.resources.IResource;
16
import org.eclipse.core.runtime.Assert;
19
import org.eclipse.core.runtime.*;
17
import org.eclipse.core.runtime.IProgressMonitor;
20
import org.eclipse.jface.action.*;
18
import org.eclipse.jface.action.*;
21
import org.eclipse.jface.resource.ImageDescriptor;
22
import org.eclipse.jface.resource.ImageRegistry;
23
import org.eclipse.jface.text.IDocument;
24
import org.eclipse.jface.text.ITextViewer;
25
import org.eclipse.jface.util.IPropertyChangeListener;
19
import org.eclipse.jface.util.IPropertyChangeListener;
26
import org.eclipse.jface.viewers.*;
20
import org.eclipse.jface.viewers.ISelectionProvider;
27
import org.eclipse.osgi.util.NLS;
21
import org.eclipse.jface.viewers.Viewer;
28
import org.eclipse.swt.events.DisposeEvent;
22
import org.eclipse.swt.events.DisposeEvent;
29
import org.eclipse.swt.events.DisposeListener;
23
import org.eclipse.swt.events.DisposeListener;
30
import org.eclipse.swt.graphics.Image;
24
import org.eclipse.swt.widgets.Composite;
31
import org.eclipse.swt.widgets.*;
25
import org.eclipse.swt.widgets.Control;
32
import org.eclipse.team.internal.ui.*;
33
import org.eclipse.team.internal.ui.history.CompareFileRevisionEditorInput;
34
import org.eclipse.team.internal.ui.synchronize.LocalResourceSaveableComparison;
26
import org.eclipse.team.internal.ui.synchronize.LocalResourceSaveableComparison;
35
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
36
import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener;
37
import org.eclipse.team.ui.mapping.SaveableComparison;
27
import org.eclipse.team.ui.mapping.SaveableComparison;
38
import org.eclipse.ui.*;
28
import org.eclipse.ui.*;
39
import org.eclipse.ui.actions.*;
40
import org.eclipse.ui.keys.IBindingService;
41
import org.eclipse.ui.services.IDisposable;
29
import org.eclipse.ui.services.IDisposable;
42
30
43
/**
31
/**
Lines 51-151 Link Here
51
 * </p>
39
 * </p>
52
 * @since 3.3
40
 * @since 3.3
53
 */
41
 */
54
public abstract class SaveableCompareEditorInput extends CompareEditorInput implements ISaveablesSource {
42
public abstract class SaveableCompareEditorInput extends AbstractSaveableCompareEditorInput {
55
43
56
	private ICompareInputChangeListener compareInputChangeListener;
44
	private ICompareInputChangeListener compareInputChangeListener;
57
	private final IWorkbenchPage page;
58
	private final ListenerList inputChangeListeners = new ListenerList(ListenerList.IDENTITY);
59
	private Saveable saveable;
45
	private Saveable saveable;
60
	private IPropertyListener propertyListener;
46
	private IPropertyListener propertyListener;
61
	
47
	
62
	/**
48
	/**
63
	 * Return a typed element that represents a local file. If the element
64
	 * returned from this method is used as the left contributor of the compare
65
	 * input for a {@link SaveableCompareEditorInput}, then the file will
66
	 * be properly saved when the compare editor input or viewers are saved.
67
	 * @param file the file
68
	 * @return a typed element that represents a local file.
69
	 */
70
	public static ITypedElement createFileElement(IFile file) {
71
		return new LocalResourceTypedElement(file);
72
	}
73
	
74
	private static ITypedElement getFileElement(ICompareInput input,
75
			CompareEditorInput editorInput) {
76
		if (input.getLeft() instanceof LocalResourceTypedElement) {
77
			return (LocalResourceTypedElement) input.getLeft();
78
		}
79
		if (editorInput instanceof CompareFileRevisionEditorInput) {
80
			return ((CompareFileRevisionEditorInput) editorInput).getLocalElement();
81
		}
82
		return null;
83
	}
84
	
85
	private class InternalResourceSaveableComparison extends LocalResourceSaveableComparison implements ISharedDocumentAdapterListener {
86
		private LocalResourceTypedElement lrte;
87
		private boolean connected = false;
88
		public InternalResourceSaveableComparison(
89
				ICompareInput input, CompareEditorInput editorInput) {
90
			super(input, editorInput, SaveableCompareEditorInput.getFileElement(input, editorInput));
91
			ITypedElement element = SaveableCompareEditorInput.getFileElement(input, editorInput);
92
			if (element instanceof LocalResourceTypedElement) {
93
				lrte = (LocalResourceTypedElement) element;
94
				if (lrte.isConnected()) {
95
					registerSaveable(true);
96
				} else {
97
					lrte.setSharedDocumentListener(this);
98
				}
99
			}
100
		}
101
		protected void fireInputChange() {
102
			SaveableCompareEditorInput.this.fireInputChange();
103
		}
104
		public void dispose() {
105
			super.dispose();
106
			if (lrte != null)
107
				lrte.setSharedDocumentListener(null);
108
		}
109
		public void handleDocumentConnected() {
110
			if (connected)
111
				return;
112
			connected = true;
113
			registerSaveable(false);
114
			if (lrte != null)
115
				lrte.setSharedDocumentListener(null);
116
		}
117
		
118
		private void registerSaveable(boolean init) {
119
			ICompareContainer container = getContainer();
120
			IWorkbenchPart part = container.getWorkbenchPart();
121
			if (part != null) {
122
				ISaveablesLifecycleListener lifecycleListener= getSaveablesLifecycleListener(part);
123
				// Remove this saveable from the lifecycle listener
124
				if (!init)
125
					lifecycleListener.handleLifecycleEvent(
126
							new SaveablesLifecycleEvent(part, SaveablesLifecycleEvent.POST_CLOSE, new Saveable[] { this }, false));
127
				// Now fix the hashing so it uses the connected document
128
				initializeHashing();
129
				// Finally, add this saveable back to the listener
130
				lifecycleListener.handleLifecycleEvent(
131
						new SaveablesLifecycleEvent(part, SaveablesLifecycleEvent.POST_OPEN, new Saveable[] { this }, false));
132
			}
133
		}
134
		public void handleDocumentDeleted() {
135
			// Ignore
136
		}
137
		public void handleDocumentDisconnected() {
138
			// Ignore
139
		}
140
		public void handleDocumentFlushed() {
141
			// Ignore
142
		}
143
		public void handleDocumentSaved() {
144
			// Ignore
145
		}
146
	}
147
	
148
	/**
149
	 * Creates a <code>LocalResourceCompareEditorInput</code> which is initialized with the given
49
	 * Creates a <code>LocalResourceCompareEditorInput</code> which is initialized with the given
150
	 * compare configuration.
50
	 * compare configuration.
151
	 * The compare configuration is passed to subsequently created viewers.
51
	 * The compare configuration is passed to subsequently created viewers.
Lines 154-161 Link Here
154
	 * @param page the workbench page that will contain the editor
54
	 * @param page the workbench page that will contain the editor
155
	 */
55
	 */
156
	public SaveableCompareEditorInput(CompareConfiguration configuration, IWorkbenchPage page) {
56
	public SaveableCompareEditorInput(CompareConfiguration configuration, IWorkbenchPage page) {
157
		super(configuration);
57
		super(configuration, page);
158
		this.page = page;
159
	}
58
	}
160
59
161
	/* (non-Javadoc)
60
	/* (non-Javadoc)
Lines 195-208 Link Here
195
		setDirty(saveable.isDirty());
94
		setDirty(saveable.isDirty());
196
	}
95
	}
197
96
198
	private ISaveablesLifecycleListener getSaveablesLifecycleListener(
199
			IWorkbenchPart part) {
200
		ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener)Utils.getAdapter(part, ISaveablesLifecycleListener.class);
201
		if (listener == null)
202
			listener = (ISaveablesLifecycleListener) part.getSite().getService(ISaveablesLifecycleListener.class);
203
		return listener;
204
	}
205
	
206
	/* (non-Javadoc)
97
	/* (non-Javadoc)
207
	 * @see org.eclipse.compare.CompareEditorInput#handleDispose()
98
	 * @see org.eclipse.compare.CompareEditorInput#handleDispose()
208
	 */
99
	 */
Lines 225-323 Link Here
225
	}
116
	}
226
	
117
	
227
	/**
118
	/**
228
	 * Prepare the compare input of this editor input. This method is not intended to be overridden of 
229
	 * extended by subclasses (but is not final for backwards compatibility reasons). 
230
	 * The implementation of this method in this class
231
	 * delegates the creation of the compare input to the {@link #prepareCompareInput(IProgressMonitor)}
232
	 * method which subclasses must implement.
233
	 * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor)
234
	 */
235
	protected Object prepareInput(IProgressMonitor monitor)
236
			throws InvocationTargetException, InterruptedException {
237
		final ICompareInput input = prepareCompareInput(monitor);
238
		if (input != null)
239
			setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title, new String[] { input.getName()}));
240
		return input;
241
	}
242
243
	/**
244
	 * Method called from {@link #prepareInput(IProgressMonitor)} to obtain the input.
245
	 * It's purpose is to ensure that the input is an instance of {@link ICompareInput}.
246
	 * @param monitor a progress monitor
247
	 * @return the compare input
248
	 * @throws InvocationTargetException
249
	 * @throws InterruptedException
250
	 */
251
	protected abstract ICompareInput prepareCompareInput(IProgressMonitor monitor) 
252
		throws InvocationTargetException, InterruptedException;
253
	
254
	/**
255
	 * Return the compare input of this editor input.
256
	 * @return the compare input of this editor input
257
	 */
258
	protected final ICompareInput getCompareInput() {
259
		return (ICompareInput)getCompareResult();
260
	}
261
	
262
	/**
263
	 * Callback from the resource saveable that is invoked when the resource is
264
	 * saved so that this input can fire a change event for its input. Subclasses
265
	 * only need this method if the left side of their compare input is
266
	 * an element returned from {@link #createFileElement(IFile)}.
267
	 */
268
	protected abstract void fireInputChange();
269
	
270
	/**
271
	 * Close the editor if it is not dirty. If it is still dirty, let the 
272
	 * content merge viewer handle the compare input change.
273
	 * @param checkForUnsavedChanges whether to check for unsaved changes
274
	 * @return <code>true</code> if the editor was closed (note that the 
275
	 * close may be asynchronous)
276
	 */
277
	protected boolean closeEditor(boolean checkForUnsavedChanges) {
278
		if (isSaveNeeded() && checkForUnsavedChanges) {
279
			return false;
280
		} else {
281
			Runnable runnable = new Runnable() {
282
				public void run() {
283
					IEditorPart part = getPage().findEditor(SaveableCompareEditorInput.this);
284
					getPage().closeEditor(part, false);
285
				}
286
			};
287
			if (Display.getCurrent() != null) {
288
				runnable.run();
289
			} else {
290
				Display display = getPage().getWorkbenchWindow().getShell().getDisplay();
291
				display.asyncExec(runnable);
292
			}
293
			return true;
294
		}
295
	}
296
	
297
	private IWorkbenchPage getPage() {
298
		if (page == null)
299
			return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
300
		return page;
301
	}
302
	
303
	/* package */ void propogateInputChange() {
304
		if (!inputChangeListeners.isEmpty()) {
305
			Object[] allListeners = inputChangeListeners.getListeners();
306
			for (int i = 0; i < allListeners.length; i++) {
307
				final ICompareInputChangeListener listener = (ICompareInputChangeListener)allListeners[i];
308
				SafeRunner.run(new ISafeRunnable() {
309
					public void run() throws Exception {
310
						listener.compareInputChanged((ICompareInput)SaveableCompareEditorInput.this.getCompareResult());
311
					}
312
					public void handleException(Throwable exception) {
313
						// Logged by the safe runner
314
					}
315
				});
316
			}
317
		}
318
	}
319
320
	/**
321
	 * Get the saveable that provides the save behavior for this compare editor input.
119
	 * Get the saveable that provides the save behavior for this compare editor input.
322
	 * The {@link #createSaveable()} is called to create the saveable if it does not yet exist.
120
	 * The {@link #createSaveable()} is called to create the saveable if it does not yet exist.
323
	 * This method cannot be called until after the input is prepared (i.e. until after
121
	 * This method cannot be called until after the input is prepared (i.e. until after
Lines 340-346 Link Here
340
	protected Saveable createSaveable() {
138
	protected Saveable createSaveable() {
341
		Object compareResult = getCompareResult();
139
		Object compareResult = getCompareResult();
342
		Assert.isNotNull(compareResult, "This method cannot be called until after prepareInput is called"); //$NON-NLS-1$
140
		Assert.isNotNull(compareResult, "This method cannot be called until after prepareInput is called"); //$NON-NLS-1$
343
		return new InternalResourceSaveableComparison((ICompareInput)compareResult, this);
141
		return new InternalResourceSaveableComparison((ICompareInput)compareResult, this, getFileElement(getCompareInput().getLeft(), this));
344
	}
142
	}
345
143
346
	/* (non-Javadoc)
144
	/* (non-Javadoc)
Lines 353-424 Link Here
353
	}
151
	}
354
152
355
	/* (non-Javadoc)
153
	/* (non-Javadoc)
356
	 * @see org.eclipse.ui.ISaveablesSource#getSaveables()
357
	 */
358
	public Saveable[] getSaveables() {
359
		return getActiveSaveables();
360
	}
361
	
362
	/* (non-Javadoc)
363
	 * @see org.eclipse.compare.CompareEditorInput#addCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
364
	 */
365
	public void addCompareInputChangeListener(ICompareInput input,
366
			ICompareInputChangeListener listener) {
367
		if (input == getCompareResult()) {
368
			inputChangeListeners.add(listener);
369
		} else {
370
			super.addCompareInputChangeListener(input, listener);
371
		}
372
	}
373
	
374
	/* (non-Javadoc)
375
	 * @see org.eclipse.compare.CompareEditorInput#removeCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
376
	 */
377
	public void removeCompareInputChangeListener(ICompareInput input,
378
			ICompareInputChangeListener listener) {
379
		if (input == getCompareResult()) {
380
			inputChangeListeners.remove(listener);
381
		} else {
382
			super.removeCompareInputChangeListener(input, listener);
383
		}
384
	}
385
	
386
	/* (non-Javadoc)
387
	 * @see org.eclipse.compare.CompareEditorInput#getAdapter(java.lang.Class)
388
	 */
389
	public Object getAdapter(Class adapter) {
390
		if (IFile.class.equals(adapter)) {
391
			IResource resource = Utils.getResource(getCompareResult());
392
			if (resource instanceof IFile) {
393
				return resource;
394
			}
395
		}
396
		return super.getAdapter(adapter);
397
	}
398
	
399
	/*
400
	 * (non-Javadoc)
401
	 * @see org.eclipse.compare.CompareEditorInput#getTitleImage()
402
	 */
403
	public Image getTitleImage() {
404
		ImageRegistry reg = TeamUIPlugin.getPlugin().getImageRegistry();
405
		Image image = reg.get(ITeamUIImages.IMG_SYNC_VIEW);
406
		if (image == null) {
407
			image = getImageDescriptor().createImage();
408
			reg.put(ITeamUIImages.IMG_SYNC_VIEW, image);
409
		}
410
		return image;
411
	}
412
413
	/*
414
	 * (non-Javadoc)
415
	 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
416
	 */
417
	public ImageDescriptor getImageDescriptor() {
418
		return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW);
419
	}
420
	
421
	/* (non-Javadoc)
422
	 * @see org.eclipse.compare.CompareEditorInput#findContentViewer(org.eclipse.jface.viewers.Viewer, org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.swt.widgets.Composite)
154
	 * @see org.eclipse.compare.CompareEditorInput#findContentViewer(org.eclipse.jface.viewers.Viewer, org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.swt.widgets.Composite)
423
	 */
155
	 */
424
	public Viewer findContentViewer(Viewer oldViewer, ICompareInput input, Composite parent) {
156
	public Viewer findContentViewer(Viewer oldViewer, ICompareInput input, Composite parent) {
Lines 441-453 Link Here
441
		return newViewer;
173
		return newViewer;
442
	}
174
	}
443
175
444
	/* (non-Javadoc)
445
	 * @see org.eclipse.compare.CompareEditorInput#canRunAsJob()
446
	 */
447
	public boolean canRunAsJob() {
448
		return true;
449
	}
450
	
451
	public boolean isDirty() {
176
	public boolean isDirty() {
452
		if (saveable != null)
177
		if (saveable != null)
453
			return saveable.isDirty();
178
			return saveable.isDirty();
Lines 458-517 Link Here
458
			final ISelectionProvider selectionProvider) {
183
			final ISelectionProvider selectionProvider) {
459
		super.registerContextMenu(menu, selectionProvider);
184
		super.registerContextMenu(menu, selectionProvider);
460
		final Saveable saveable = getSaveable();
185
		final Saveable saveable = getSaveable();
186
		final ITypedElement element = getFileElement(getCompareInput().getLeft(), this);
461
		if (saveable instanceof LocalResourceSaveableComparison) {
187
		if (saveable instanceof LocalResourceSaveableComparison) {
462
			menu.addMenuListener(new IMenuListener() {
188
			menu.addMenuListener(new IMenuListener() {
463
				public void menuAboutToShow(IMenuManager manager) {
189
				public void menuAboutToShow(IMenuManager manager) {
464
					handleMenuAboutToShow(manager, saveable, selectionProvider);
190
					handleMenuAboutToShow(manager, saveable, element, selectionProvider);
465
				}
191
				}
466
			});
192
			});
467
		}
193
		}
468
	}
194
	}
469
	
470
	/* package */ void handleMenuAboutToShow (IMenuManager manager, Saveable saveable, ISelectionProvider provider) {
471
		if (provider instanceof ITextViewer) {
472
			ITextViewer v = (ITextViewer) provider;
473
			IDocument d = v.getDocument();
474
			IDocument other = (IDocument)Utils.getAdapter(saveable, IDocument.class);
475
			if (d == other) {
476
				ITypedElement element = getFileElement(getCompareInput(), this);
477
				if (element instanceof IResourceProvider) {
478
					IResourceProvider rp = (IResourceProvider) element;
479
					IResource resource = rp.getResource();
480
					StructuredSelection selection = new StructuredSelection(resource);
481
					IWorkbenchPart workbenchPart = getContainer().getWorkbenchPart();
482
					if (workbenchPart != null) {
483
						IWorkbenchSite ws = workbenchPart.getSite();
484
						
485
						MenuManager submenu1 =
486
							new MenuManager(getShowInMenuLabel());
487
						IContributionItem showInMenu = ContributionItemFactory.VIEWS_SHOW_IN.create(ws.getWorkbenchWindow());
488
						submenu1.add(showInMenu);
489
						manager.insertAfter("file", submenu1); //$NON-NLS-1$
490
						MenuManager submenu2 =
491
							new MenuManager(TeamUIMessages.OpenWithActionGroup_0); 
492
						submenu2.add(new OpenWithMenu(ws.getPage(), resource));
493
						manager.insertAfter("file", submenu2); //$NON-NLS-1$
494
						
495
						OpenFileAction openFileAction = new OpenFileAction(ws.getPage());
496
						openFileAction.selectionChanged(selection);
497
						manager.insertAfter("file", openFileAction); //$NON-NLS-1$
498
					}
499
				}
500
			}
501
		}
502
	}
503
	
504
	private String getShowInMenuLabel() {
505
		String keyBinding= null;
506
		
507
		IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
508
		if (bindingService != null)
509
			keyBinding= bindingService.getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
510
		
511
		if (keyBinding == null)
512
			keyBinding= ""; //$NON-NLS-1$
513
		
514
		return NLS.bind(TeamUIMessages.SaveableCompareEditorInput_0, keyBinding);
515
	}
516
195
517
}
196
}
(-)src/org/eclipse/team/ui/synchronize/TwoSidesSaveableCompareEditorInput.java (+339 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 * IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.team.ui.synchronize;
12
13
import java.lang.reflect.InvocationTargetException;
14
15
import org.eclipse.compare.*;
16
import org.eclipse.compare.structuremergeviewer.*;
17
import org.eclipse.core.resources.IResource;
18
import org.eclipse.core.runtime.*;
19
import org.eclipse.jface.action.*;
20
import org.eclipse.jface.util.IPropertyChangeListener;
21
import org.eclipse.jface.viewers.ISelectionProvider;
22
import org.eclipse.jface.viewers.Viewer;
23
import org.eclipse.osgi.util.NLS;
24
import org.eclipse.swt.events.DisposeEvent;
25
import org.eclipse.swt.events.DisposeListener;
26
import org.eclipse.swt.widgets.Composite;
27
import org.eclipse.swt.widgets.Control;
28
import org.eclipse.team.internal.ui.mapping.AbstractCompareInput;
29
import org.eclipse.team.internal.ui.mapping.CompareInputChangeNotifier;
30
import org.eclipse.team.internal.ui.synchronize.LocalResourceSaveableComparison;
31
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
32
import org.eclipse.team.ui.mapping.SaveableComparison;
33
import org.eclipse.ui.*;
34
import org.eclipse.ui.services.IDisposable;
35
36
public class TwoSidesSaveableCompareEditorInput extends
37
		AbstractSaveableCompareEditorInput {
38
	
39
	private ICompareInputChangeListener fCompareInputChangeListener;
40
	private IPropertyListener fLeftPropertyListener;
41
	private IPropertyListener fRightPropertyListener;
42
	
43
	private Saveable fLeftSaveable;
44
	private Saveable fRightSaveable;
45
	
46
	private ITypedElement fLeftElement;
47
	private ITypedElement fRightElement;
48
	
49
	public TwoSidesSaveableCompareEditorInput(ITypedElement left,
50
			ITypedElement right, IWorkbenchPage page) {
51
		super(new CompareConfiguration(), page);
52
		this.fLeftElement = left;
53
		this.fRightElement = right;
54
	}
55
	
56
	/* (non-Javadoc)
57
	 * @see org.eclipse.compare.CompareEditorInput#contentsCreated()
58
	 */
59
	protected void contentsCreated() {
60
		super.contentsCreated();
61
		fCompareInputChangeListener = new ICompareInputChangeListener() {
62
			public void compareInputChanged(ICompareInput source) {
63
				if (source == getCompareResult()) {
64
					boolean closed = false;
65
					if (source.getKind() == Differencer.NO_CHANGE) {
66
						closed = closeEditor(true);
67
					}
68
					if (!closed) {
69
						// The editor was closed either because the compare input still has changes
70
						// or because the editor input is dirty. In either case, fire the changes
71
						// to the registered listeners
72
						propogateInputChange();
73
					}
74
				}
75
			}
76
		};
77
		getCompareInput().addCompareInputChangeListener(fCompareInputChangeListener);
78
		
79
		if (getLeftSaveable() instanceof SaveableComparison) {
80
			SaveableComparison lscm = (SaveableComparison) fLeftSaveable;
81
			fLeftPropertyListener = new IPropertyListener() {
82
				public void propertyChanged(Object source, int propId) {
83
					if (propId == SaveableComparison.PROP_DIRTY) {
84
						setDirty(fLeftSaveable.isDirty());
85
					}
86
				}
87
			};
88
			lscm.addPropertyListener(fLeftPropertyListener);
89
		}
90
		
91
		if (getRightSaveable() instanceof SaveableComparison) {
92
			SaveableComparison rscm = (SaveableComparison) fRightSaveable;
93
			fRightPropertyListener = new IPropertyListener() {
94
				public void propertyChanged(Object source, int propId) {
95
					if (propId == SaveableComparison.PROP_DIRTY) {
96
						setDirty(fRightSaveable.isDirty());
97
					}
98
				}
99
			};
100
			rscm.addPropertyListener(fRightPropertyListener);
101
		}
102
		
103
		setDirty(fLeftSaveable.isDirty() || fRightSaveable.isDirty());
104
	}
105
	
106
	/* (non-Javadoc)
107
	 * @see org.eclipse.compare.CompareEditorInput#handleDispose()
108
	 */
109
	protected void handleDispose() {
110
		super.handleDispose();
111
		ICompareInput compareInput = getCompareInput();
112
		if (compareInput != null)
113
			compareInput.removeCompareInputChangeListener(fCompareInputChangeListener);
114
		if (fLeftSaveable instanceof SaveableComparison) {
115
			SaveableComparison scm = (SaveableComparison) fLeftSaveable;
116
			scm.removePropertyListener(fLeftPropertyListener);
117
		}
118
		if (fLeftSaveable instanceof LocalResourceSaveableComparison) {
119
			LocalResourceSaveableComparison rsc = (LocalResourceSaveableComparison) fLeftSaveable;
120
			rsc.dispose();
121
		}
122
		if (fRightSaveable instanceof SaveableComparison) {
123
			SaveableComparison scm = (SaveableComparison) fRightSaveable;
124
			scm.removePropertyListener(fRightPropertyListener);
125
		}
126
		if (fRightSaveable instanceof LocalResourceSaveableComparison) {
127
			LocalResourceSaveableComparison rsc = (LocalResourceSaveableComparison) fRightSaveable;
128
			rsc.dispose();
129
		}
130
131
		if (getCompareResult() instanceof IDisposable) {
132
			((IDisposable) getCompareResult()).dispose();
133
		}
134
	}
135
	
136
	public String getToolTipText() {
137
		IResource leftResource = getResource(fLeftElement);
138
		IResource rightResource = getResource(fRightElement);
139
140
		if (leftResource != null && rightResource != null) {
141
			String leftLabel = leftResource.getFullPath().makeRelative().toString();
142
			String rightLabel = rightResource.getFullPath().makeRelative().toString();
143
			// TODO (TomaszZarna): Externalize
144
			return NLS.bind("Two-way compare of {0} with {1}", new String[] { leftLabel, rightLabel });  //$NON-NLS-1$
145
		}
146
		// TODO (TomaszZarna): Externalize
147
		return NLS.bind("Two-way compare of {0} with {1}", new String[] { fLeftElement.getName(), fRightElement.getName() }); //$NON-NLS-1$
148
	}
149
	
150
	protected void fireInputChange() {
151
			((MyDiffNode)getCompareResult()).fireChange();
152
	}
153
	
154
	protected Saveable getLeftSaveable() {
155
		if (fLeftSaveable == null) {
156
			fLeftSaveable = createLeftSaveable();
157
		}
158
		return fLeftSaveable;
159
	}
160
	
161
	protected Saveable getRightSaveable() {
162
		if (fRightSaveable == null) {
163
			fRightSaveable = createRightSaveable();
164
		}
165
		return fRightSaveable;
166
	}
167
	
168
	protected Saveable createLeftSaveable() {
169
		Object compareResult = getCompareResult();
170
		Assert.isNotNull(compareResult, "This method cannot be called until after prepareInput is called"); //$NON-NLS-1$
171
		ITypedElement leftFileElement = getFileElement(getCompareInput().getLeft(), this);
172
		return new InternalResourceSaveableComparison((ICompareInput)compareResult, this, leftFileElement);
173
	}
174
	
175
	protected Saveable createRightSaveable() {
176
		Object compareResult = getCompareResult();
177
		Assert.isNotNull(compareResult, "This method cannot be called until after prepareInput is called"); //$NON-NLS-1$
178
		ITypedElement rightFileElement = getFileElement(getCompareInput().getRight(), this);
179
		return new InternalResourceSaveableComparison((ICompareInput)compareResult, this, rightFileElement);
180
	}
181
182
	/* (non-Javadoc)
183
	 * @see org.eclipse.ui.ISaveablesSource#getActiveSaveables()
184
	 */
185
	public Saveable[] getActiveSaveables() {
186
		if (getCompareResult() == null)
187
			return new Saveable[0];
188
		return new Saveable[] { getLeftSaveable(), getRightSaveable() };
189
	}
190
	
191
	/* (non-Javadoc)
192
	 * @see org.eclipse.compare.CompareEditorInput#findContentViewer(org.eclipse.jface.viewers.Viewer, org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.swt.widgets.Composite)
193
	 */
194
	public Viewer findContentViewer(Viewer pOldViewer, ICompareInput pInput, Composite pParent) {
195
		Viewer newViewer = super.findContentViewer(pOldViewer, pInput, pParent);
196
		boolean isNewViewer= newViewer != pOldViewer;
197
		if (isNewViewer && newViewer instanceof IPropertyChangeNotifier
198
				&& fLeftSaveable instanceof IPropertyChangeListener
199
				&& fRightSaveable instanceof IPropertyChangeListener) {
200
			// Register the model for change events if appropriate
201
			final IPropertyChangeNotifier dsp= (IPropertyChangeNotifier) newViewer;
202
			final IPropertyChangeListener lpcl = (IPropertyChangeListener) fLeftSaveable;
203
			final IPropertyChangeListener rpcl = (IPropertyChangeListener) fRightSaveable;
204
			dsp.addPropertyChangeListener(lpcl);
205
			dsp.addPropertyChangeListener(rpcl);
206
			Control c= newViewer.getControl();
207
			c.addDisposeListener(
208
				new DisposeListener() {
209
					public void widgetDisposed(DisposeEvent e) {
210
						dsp.removePropertyChangeListener(lpcl);
211
						dsp.removePropertyChangeListener(rpcl);
212
					}
213
				}
214
			);
215
		}
216
		return newViewer;
217
	}
218
	
219
	
220
	public boolean isDirty() {
221
		if (fLeftSaveable != null && fLeftSaveable.isDirty())
222
			return true;
223
		if (fRightSaveable != null && fRightSaveable.isDirty())
224
			return true;
225
		return super.isDirty();
226
	}
227
	
228
	protected ICompareInput prepareCompareInput(IProgressMonitor monitor)
229
			throws InvocationTargetException, InterruptedException {
230
		ICompareInput input = createCompareInput();
231
		getCompareConfiguration().setLeftEditable(isLeftEditable(input)); 
232
		getCompareConfiguration().setRightEditable(isRightEditable(input));
233
		// TODO (TomaszZarna): both are local
234
		// ensureContentsCached(getLeftRevision(), getRightRevision(), monitor);
235
		initLabels();
236
		return input;
237
	}
238
	
239
	private boolean isLeftEditable(ICompareInput pInput) {
240
		Object left = pInput.getLeft();
241
		if (left instanceof IEditableContent) {
242
			return ((IEditableContent) left).isEditable();
243
		}
244
		return false;
245
	}
246
	
247
	private boolean isRightEditable(ICompareInput pInput) {
248
		Object right = pInput.getRight();
249
		if (right instanceof IEditableContent) {
250
			return ((IEditableContent) right).isEditable();
251
		}
252
		return false;
253
	}
254
	
255
	private void initLabels() {
256
		CompareConfiguration cc = getCompareConfiguration();
257
		
258
		IResource leftResource = getResource(fLeftElement);
259
		IResource rightResource = getResource(fRightElement);
260
		
261
		if (leftResource != null && rightResource != null) {
262
			String leftLabel = leftResource.getFullPath().makeRelative()
263
					.toString();
264
			String rightLabel = rightResource.getFullPath().makeRelative()
265
					.toString();
266
			
267
			cc.setLeftLabel(leftLabel);
268
			cc.setRightLabel(rightLabel);
269
		}
270
	}
271
	
272
	private ICompareInput createCompareInput() {
273
		return new MyDiffNode(fLeftElement, fRightElement);
274
	}
275
	
276
	CompareInputChangeNotifier notifier = new CompareInputChangeNotifier() {
277
		protected IResource[] getResources(ICompareInput input) {
278
			IResource leftResource = getResource(fLeftElement);
279
			IResource rightResource = getResource(fRightElement);
280
			if (leftResource == null && rightResource == null)
281
				return new IResource[0];
282
			if (leftResource == null && rightResource != null)
283
				return new IResource[] { rightResource };
284
			if (leftResource != null && rightResource == null)
285
				return new IResource[] { leftResource };
286
			return new IResource[] { leftResource, rightResource };
287
		}
288
	};
289
	
290
	public class MyDiffNode extends AbstractCompareInput {
291
		public MyDiffNode(ITypedElement left, ITypedElement right) {
292
			super(Differencer.CHANGE, null, left, right);
293
		}
294
		public void fireChange() {
295
			super.fireChange();
296
		}
297
		protected CompareInputChangeNotifier getChangeNotifier() {
298
			return notifier;
299
		}
300
		public boolean needsUpdate() {
301
			return true;
302
		}
303
		public void update() {
304
			fireChange();
305
		}
306
	}
307
	
308
	private IResource getResource(ITypedElement pElement) {
309
		if (pElement instanceof LocalResourceTypedElement
310
				&& pElement instanceof IResourceProvider) {
311
			return ((IResourceProvider) pElement).getResource();
312
		}
313
		return null;
314
	}
315
316
	public void registerContextMenu(final MenuManager pMenuManager,
317
			final ISelectionProvider pSelectionProvider) {
318
		super.registerContextMenu(pMenuManager, pSelectionProvider);
319
		final Saveable lLeftSaveable = getLeftSaveable();
320
		final ITypedElement lLeftElement = getFileElement(getCompareInput().getLeft(), this);
321
		if (lLeftSaveable instanceof LocalResourceSaveableComparison) {
322
			pMenuManager.addMenuListener(new IMenuListener() {
323
				public void menuAboutToShow(IMenuManager manager) {
324
					handleMenuAboutToShow(manager, lLeftSaveable, lLeftElement, pSelectionProvider);
325
				}
326
			});
327
		}
328
		final Saveable lRightSaveable = getRightSaveable();
329
		final ITypedElement lRightElement = getFileElement(getCompareInput().getRight(), this);
330
		if (lRightSaveable instanceof LocalResourceSaveableComparison) {
331
			pMenuManager.addMenuListener(new IMenuListener() {
332
				public void menuAboutToShow(IMenuManager manager) {
333
					handleMenuAboutToShow(manager, lRightSaveable, lRightElement, pSelectionProvider);
334
				}
335
			});
336
		}
337
	}
338
	
339
}
(-)src/org/eclipse/team/internal/ui/actions/CompareAction.java (+83 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 * IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.team.internal.ui.actions;
12
13
import java.lang.reflect.InvocationTargetException;
14
15
import org.eclipse.compare.*;
16
import org.eclipse.core.resources.IFile;
17
import org.eclipse.core.resources.IResource;
18
import org.eclipse.jface.action.IAction;
19
import org.eclipse.jface.viewers.ISelection;
20
import org.eclipse.team.ui.synchronize.*;
21
import org.eclipse.ui.*;
22
23
public class CompareAction extends TeamAction {
24
25
	
26
	protected void execute(IAction action) throws InvocationTargetException,
27
			InterruptedException {
28
		
29
		IResource[] selectedResources = getSelectedResources();
30
		
31
		if (selectedResources.length == 2) {
32
33
			ITypedElement left = null;
34
			if (selectedResources[0] != null) {
35
				left = getElementFor(selectedResources[0]);
36
			}
37
38
			ITypedElement right = null;
39
			if (selectedResources[1] != null) {
40
				right = getElementFor(selectedResources[1]);
41
			}
42
43
			openInCompare(left, right);
44
		}
45
	}
46
	
47
	//XXX: from CompareRevisionAction*
48
	private void openInCompare(ITypedElement left, ITypedElement right) {
49
		IWorkbenchPage workBenchPage = getTargetPage();
50
		CompareEditorInput input = createCompareEditorInput(left, right, workBenchPage);
51
		IEditorPart editor = CompareRevisionAction.findReusableCompareEditor(workBenchPage);
52
		if (editor != null) {
53
			IEditorInput otherInput = editor.getEditorInput();
54
			if (otherInput.equals(input)) {
55
				// simply provide focus to editor
56
				workBenchPage.activate(editor);
57
			} else {
58
				// if editor is currently not open on that input either re-use
59
				// existing
60
				CompareUI.reuseCompareEditor(input, (IReusableEditor) editor);
61
				workBenchPage.activate(editor);
62
			}
63
		} else {
64
			CompareUI.openCompareEditor(input);
65
		}
66
	}
67
	
68
	protected AbstractSaveableCompareEditorInput createCompareEditorInput(
69
			ITypedElement left, ITypedElement right, IWorkbenchPage page) {
70
		return new TwoSidesSaveableCompareEditorInput(left,
71
				right, page);
72
	}
73
	
74
	public void selectionChanged(IAction action, ISelection selection) {
75
		super.selectionChanged(action, selection);
76
	}
77
	
78
	//XXX: from CompareRevisionAction
79
	private ITypedElement getElementFor(IResource resource) {
80
		return SaveableCompareEditorInput.createFileElement((IFile)resource);
81
	}
82
83
}
(-)src/org/eclipse/team/ui/synchronize/AbstractSaveableCompareEditorInput.java (+352 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 * IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.team.ui.synchronize;
12
13
import java.lang.reflect.InvocationTargetException;
14
15
import org.eclipse.compare.*;
16
import org.eclipse.compare.structuremergeviewer.ICompareInput;
17
import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener;
18
import org.eclipse.core.resources.IFile;
19
import org.eclipse.core.resources.IResource;
20
import org.eclipse.core.runtime.*;
21
import org.eclipse.jface.action.*;
22
import org.eclipse.jface.resource.ImageDescriptor;
23
import org.eclipse.jface.resource.ImageRegistry;
24
import org.eclipse.jface.text.IDocument;
25
import org.eclipse.jface.text.ITextViewer;
26
import org.eclipse.jface.viewers.ISelectionProvider;
27
import org.eclipse.jface.viewers.StructuredSelection;
28
import org.eclipse.osgi.util.NLS;
29
import org.eclipse.swt.graphics.Image;
30
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.team.internal.ui.*;
32
import org.eclipse.team.internal.ui.history.CompareFileRevisionEditorInput;
33
import org.eclipse.team.internal.ui.synchronize.LocalResourceSaveableComparison;
34
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
35
import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener;
36
import org.eclipse.ui.*;
37
import org.eclipse.ui.actions.*;
38
import org.eclipse.ui.keys.IBindingService;
39
40
public abstract class AbstractSaveableCompareEditorInput extends
41
		CompareEditorInput implements ISaveablesSource {
42
	
43
	final IWorkbenchPage page;
44
	protected final ListenerList inputChangeListeners = new ListenerList(ListenerList.IDENTITY);
45
46
	/**
47
	 * Return a typed element that represents a local file. If the element
48
	 * returned from this method is used as the left contributor of the compare
49
	 * input for a {@link SaveableCompareEditorInput}, then the file will
50
	 * be properly saved when the compare editor input or viewers are saved.
51
	 * @param file the file
52
	 * @return a typed element that represents a local file.
53
	 */
54
	public static ITypedElement createFileElement(IFile file) {
55
		return new LocalResourceTypedElement(file);
56
	}
57
58
	protected static ITypedElement getFileElement(ITypedElement element, CompareEditorInput editorInput) {
59
		if (element instanceof LocalResourceTypedElement) {
60
			return (LocalResourceTypedElement) element;
61
		}
62
		if (editorInput instanceof CompareFileRevisionEditorInput) {
63
			return ((CompareFileRevisionEditorInput) editorInput).getLocalElement();
64
		}
65
		return null;
66
	}
67
	
68
	class InternalResourceSaveableComparison extends LocalResourceSaveableComparison implements ISharedDocumentAdapterListener {
69
		private LocalResourceTypedElement lrte;
70
		private boolean connected = false;
71
		public InternalResourceSaveableComparison(
72
				ICompareInput input, CompareEditorInput editorInput, ITypedElement element) {
73
			super(input, editorInput, element);
74
			if (element instanceof LocalResourceTypedElement) {
75
				lrte = (LocalResourceTypedElement) element;
76
				if (lrte.isConnected()) {
77
					registerSaveable(true);
78
				} else {
79
					lrte.setSharedDocumentListener(this);
80
				}
81
			}
82
		}
83
		protected void fireInputChange() {
84
			AbstractSaveableCompareEditorInput.this.fireInputChange();
85
		}
86
		public void dispose() {
87
			super.dispose();
88
			if (lrte != null)
89
				lrte.setSharedDocumentListener(null);
90
		}
91
		public void handleDocumentConnected() {
92
			if (connected)
93
				return;
94
			connected = true;
95
			registerSaveable(false);
96
			if (lrte != null)
97
				lrte.setSharedDocumentListener(null);
98
		}
99
		private void registerSaveable(boolean init) {
100
			ICompareContainer container = getContainer();
101
			IWorkbenchPart part = container.getWorkbenchPart();
102
			if (part != null) {
103
				ISaveablesLifecycleListener lifecycleListener= getSaveablesLifecycleListener(part);
104
				// Remove this saveable from the lifecycle listener
105
				if (!init)
106
					lifecycleListener.handleLifecycleEvent(
107
							new SaveablesLifecycleEvent(part, SaveablesLifecycleEvent.POST_CLOSE, new Saveable[] { this }, false));
108
				// Now fix the hashing so it uses the connected document
109
				initializeHashing();
110
				// Finally, add this saveable back to the listener
111
				lifecycleListener.handleLifecycleEvent(
112
						new SaveablesLifecycleEvent(part, SaveablesLifecycleEvent.POST_OPEN, new Saveable[] { this }, false));
113
			}
114
		}
115
		public void handleDocumentDeleted() {
116
			// Ignore
117
		}
118
		public void handleDocumentDisconnected() {
119
			// Ignore
120
		}
121
		public void handleDocumentFlushed() {
122
			// Ignore
123
		}
124
		public void handleDocumentSaved() {
125
			// Ignore
126
		}
127
	}
128
	
129
	public AbstractSaveableCompareEditorInput(CompareConfiguration configuration, IWorkbenchPage page) {
130
		super(configuration);
131
		this.page = page;
132
	}
133
134
	protected ISaveablesLifecycleListener getSaveablesLifecycleListener(IWorkbenchPart part) {
135
		ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener)Utils.getAdapter(part, ISaveablesLifecycleListener.class);
136
		if (listener == null)
137
			listener = (ISaveablesLifecycleListener) part.getSite().getService(ISaveablesLifecycleListener.class);
138
		return listener;
139
	}
140
141
	/**
142
	 * Prepare the compare input of this editor input. This method is not intended to be overridden of 
143
	 * extended by subclasses (but is not final for backwards compatibility reasons). 
144
	 * The implementation of this method in this class
145
	 * delegates the creation of the compare input to the {@link #prepareCompareInput(IProgressMonitor)}
146
	 * method which subclasses must implement.
147
	 * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor)
148
	 */
149
	protected Object prepareInput(IProgressMonitor monitor)
150
			throws InvocationTargetException, InterruptedException {
151
				final ICompareInput input = prepareCompareInput(monitor);
152
				if (input != null)
153
					setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title, new String[] { input.getName()}));
154
				return input;
155
			}
156
	
157
	/**
158
	 * Close the editor if it is not dirty. If it is still dirty, let the 
159
	 * content merge viewer handle the compare input change.
160
	 * @param checkForUnsavedChanges whether to check for unsaved changes
161
	 * @return <code>true</code> if the editor was closed (note that the 
162
	 * close may be asynchronous)
163
	 */
164
	protected boolean closeEditor(boolean checkForUnsavedChanges) {
165
		if (isSaveNeeded() && checkForUnsavedChanges) {
166
			return false;
167
		} else {
168
			Runnable runnable = new Runnable() {
169
				public void run() {
170
					IEditorPart part = getPage().findEditor(AbstractSaveableCompareEditorInput.this);
171
					getPage().closeEditor(part, false);
172
				}
173
			};
174
			if (Display.getCurrent() != null) {
175
				runnable.run();
176
			} else {
177
				Display display = getPage().getWorkbenchWindow().getShell().getDisplay();
178
				display.asyncExec(runnable);
179
			}
180
			return true;
181
		}
182
	}
183
	
184
	/**
185
	 * Method called from {@link #prepareInput(IProgressMonitor)} to obtain the input.
186
	 * It's purpose is to ensure that the input is an instance of {@link ICompareInput}.
187
	 * @param monitor a progress monitor
188
	 * @return the compare input
189
	 * @throws InvocationTargetException
190
	 * @throws InterruptedException
191
	 */
192
	protected abstract ICompareInput prepareCompareInput(IProgressMonitor monitor)
193
			throws InvocationTargetException, InterruptedException;
194
195
	IWorkbenchPage getPage() {
196
		if (page == null)
197
			return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
198
		return page;
199
	}
200
201
	/**
202
	 * Return the compare input of this editor input.
203
	 * @return the compare input of this editor input
204
	 */
205
	protected final ICompareInput getCompareInput() {
206
		return (ICompareInput)getCompareResult();
207
	}
208
209
	/**
210
	 * Callback from the resource saveable that is invoked when the resource is
211
	 * saved so that this input can fire a change event for its input. Subclasses
212
	 * only need this method if the left side of their compare input is
213
	 * an element returned from {@link #createFileElement(IFile)}.
214
	 */
215
	protected abstract void fireInputChange();
216
	
217
	/* (non-Javadoc)
218
	 * @see org.eclipse.compare.CompareEditorInput#addCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
219
	 */
220
	public void addCompareInputChangeListener(ICompareInput input,
221
			ICompareInputChangeListener listener) {
222
		if (input == getCompareResult()) {
223
			inputChangeListeners.add(listener);
224
		} else {
225
			super.addCompareInputChangeListener(input, listener);
226
		}
227
	}
228
	
229
	/* (non-Javadoc)
230
	 * @see org.eclipse.compare.CompareEditorInput#removeCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener)
231
	 */
232
	public void removeCompareInputChangeListener(ICompareInput input,
233
			ICompareInputChangeListener listener) {
234
		if (input == getCompareResult()) {
235
			inputChangeListeners.remove(listener);
236
		} else {
237
			super.removeCompareInputChangeListener(input, listener);
238
		}
239
	}
240
	
241
	/* package */ void propogateInputChange() {
242
		if (!inputChangeListeners.isEmpty()) {
243
			Object[] allListeners = inputChangeListeners.getListeners();
244
			final ICompareInput compareResult = (ICompareInput) getCompareResult();
245
			for (int i = 0; i < allListeners.length; i++) {
246
				final ICompareInputChangeListener listener = (ICompareInputChangeListener)allListeners[i];
247
				SafeRunner.run(new ISafeRunnable() {
248
					public void run() throws Exception {
249
						listener.compareInputChanged(compareResult);
250
					}
251
					public void handleException(Throwable exception) {
252
						// Logged by the safe runner
253
					}
254
				});
255
			}
256
		}
257
	}
258
	
259
	public abstract Saveable[] getActiveSaveables();
260
	
261
	/* (non-Javadoc)
262
	 * @see org.eclipse.ui.ISaveablesSource#getSaveables()
263
	 */
264
	public Saveable[] getSaveables() {
265
		return getActiveSaveables();
266
	}
267
	
268
	public Object getAdapter(Class adapter) {
269
		if (IFile.class.equals(adapter)) {
270
			IResource resource = Utils.getResource(getCompareResult());
271
			if (resource instanceof IFile) {
272
				return resource;
273
			}
274
		}
275
		return super.getAdapter(adapter);
276
	}
277
	
278
	/*
279
	 * (non-Javadoc)
280
	 * @see org.eclipse.compare.CompareEditorInput#getTitleImage()
281
	 */
282
	public Image getTitleImage() {
283
		ImageRegistry reg = TeamUIPlugin.getPlugin().getImageRegistry();
284
		Image image = reg.get(ITeamUIImages.IMG_SYNC_VIEW);
285
		if (image == null) {
286
			image = getImageDescriptor().createImage();
287
			reg.put(ITeamUIImages.IMG_SYNC_VIEW, image);
288
		}
289
		return image;
290
	}
291
292
	/*
293
	 * (non-Javadoc)
294
	 * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
295
	 */
296
	public ImageDescriptor getImageDescriptor() {
297
		return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW);
298
	}
299
	
300
	/* (non-Javadoc)
301
	 * @see org.eclipse.compare.CompareEditorInput#canRunAsJob()
302
	 */
303
	public boolean canRunAsJob() {
304
		return true;
305
	}
306
	
307
	protected void handleMenuAboutToShow(IMenuManager manager, Saveable saveable, ITypedElement element,
308
			ISelectionProvider provider) {
309
		if (provider instanceof ITextViewer) {
310
			ITextViewer v = (ITextViewer) provider;
311
			IDocument d = v.getDocument();
312
			IDocument other = (IDocument)Utils.getAdapter(saveable, IDocument.class);
313
			if (d == other) {
314
				if (element instanceof IResourceProvider) {
315
					IResourceProvider rp = (IResourceProvider) element;
316
					IResource resource = rp.getResource();
317
					StructuredSelection selection = new StructuredSelection(resource);
318
					IWorkbenchPart workbenchPart = getContainer().getWorkbenchPart();
319
					if (workbenchPart != null) {
320
						IWorkbenchSite ws = workbenchPart.getSite();
321
						MenuManager submenu1 =
322
							new MenuManager(getShowInMenuLabel());
323
						IContributionItem showInMenu = ContributionItemFactory.VIEWS_SHOW_IN.create(ws.getWorkbenchWindow());
324
						submenu1.add(showInMenu);
325
						manager.insertAfter("file", submenu1); //$NON-NLS-1$
326
						MenuManager submenu2 =
327
							new MenuManager(TeamUIMessages.OpenWithActionGroup_0); 
328
						submenu2.add(new OpenWithMenu(ws.getPage(), resource));
329
						manager.insertAfter("file", submenu2); //$NON-NLS-1$
330
331
						OpenFileAction openFileAction = new OpenFileAction(ws.getPage());
332
						openFileAction.selectionChanged(selection);
333
						manager.insertAfter("file", openFileAction); //$NON-NLS-1$
334
					}
335
				}
336
			}
337
		}
338
	}
339
	
340
	protected String getShowInMenuLabel() {
341
		String keyBinding= null;
342
		
343
		IBindingService bindingService= (IBindingService)PlatformUI.getWorkbench().getAdapter(IBindingService.class);
344
		if (bindingService != null)
345
			keyBinding= bindingService.getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
346
		
347
		if (keyBinding == null)
348
			keyBinding= ""; //$NON-NLS-1$
349
		
350
		return NLS.bind(TeamUIMessages.SaveableCompareEditorInput_0, keyBinding);
351
	}
352
}

Return to bug 193324