Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2008 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.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.IFile; |
18 |
import org.eclipse.core.resources.IResource; |
19 |
import org.eclipse.core.runtime.*; |
20 |
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; |
26 |
import org.eclipse.jface.viewers.*; |
27 |
import org.eclipse.osgi.util.NLS; |
28 |
import org.eclipse.swt.events.DisposeEvent; |
29 |
import org.eclipse.swt.events.DisposeListener; |
30 |
import org.eclipse.swt.graphics.Image; |
31 |
import org.eclipse.swt.widgets.*; |
32 |
import org.eclipse.team.internal.ui.*; |
33 |
import org.eclipse.team.internal.ui.history.CompareFileRevisionEditorInput; |
34 |
import org.eclipse.team.internal.ui.mapping.AbstractCompareInput; |
35 |
import org.eclipse.team.internal.ui.mapping.CompareInputChangeNotifier; |
36 |
import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener; |
37 |
import org.eclipse.team.ui.mapping.SaveableComparison; |
38 |
import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput; |
39 |
import org.eclipse.ui.*; |
40 |
import org.eclipse.ui.actions.*; |
41 |
import org.eclipse.ui.keys.IBindingService; |
42 |
import org.eclipse.ui.services.IDisposable; |
43 |
|
44 |
/** |
45 |
* A compare editor input that makes use of a {@link Saveable} to manage the |
46 |
* save lifecycle of the left and right sides of the comparison. The ancestor |
47 |
* part of the comparison is not editable. |
48 |
*/ |
49 |
public class SaveablesCompareEditorInput extends CompareEditorInput implements |
50 |
ISaveablesSource { |
51 |
|
52 |
private IPropertyListener fLeftPropertyListener; |
53 |
private IPropertyListener fRightPropertyListener; |
54 |
|
55 |
private Saveable fLeftSaveable; |
56 |
private Saveable fRightSaveable; |
57 |
|
58 |
private ITypedElement fAncestorElement; |
59 |
private ITypedElement fLeftElement; |
60 |
private ITypedElement fRightElement; |
61 |
|
62 |
private final IWorkbenchPage page; |
63 |
private final ListenerList inputChangeListeners = new ListenerList( |
64 |
ListenerList.IDENTITY); |
65 |
private ICompareInputChangeListener compareInputChangeListener; |
66 |
|
67 |
public SaveablesCompareEditorInput(ITypedElement ancestor, |
68 |
ITypedElement left, ITypedElement right, IWorkbenchPage page) { |
69 |
super(new CompareConfiguration()); |
70 |
this.page = page; |
71 |
this.fAncestorElement = ancestor; |
72 |
this.fLeftElement = left; |
73 |
this.fRightElement = right; |
74 |
} |
75 |
|
76 |
private static ITypedElement getFileElement(ITypedElement element, |
77 |
CompareEditorInput editorInput) { |
78 |
if (element instanceof LocalResourceTypedElement) { |
79 |
return (LocalResourceTypedElement) element; |
80 |
} |
81 |
if (editorInput instanceof CompareFileRevisionEditorInput) { |
82 |
return ((CompareFileRevisionEditorInput) editorInput) |
83 |
.getLocalElement(); |
84 |
} |
85 |
return null; |
86 |
} |
87 |
|
88 |
/** |
89 |
* Return a typed element that represents a local file. If the element |
90 |
* returned from this method is used as the left contributor of the compare |
91 |
* input for a {@link SaveableCompareEditorInput}, then the file will be |
92 |
* properly saved when the compare editor input or viewers are saved. |
93 |
* |
94 |
* @param file |
95 |
* the file |
96 |
* @return a typed element that represents a local file. |
97 |
*/ |
98 |
public static ITypedElement createFileElement(IFile file) { |
99 |
return new LocalResourceTypedElement(file); |
100 |
} |
101 |
|
102 |
private ISaveablesLifecycleListener getSaveablesLifecycleListener( |
103 |
IWorkbenchPart part) { |
104 |
ISaveablesLifecycleListener listener = (ISaveablesLifecycleListener) Utils |
105 |
.getAdapter(part, ISaveablesLifecycleListener.class); |
106 |
if (listener == null) |
107 |
listener = (ISaveablesLifecycleListener) part.getSite().getService( |
108 |
ISaveablesLifecycleListener.class); |
109 |
return listener; |
110 |
} |
111 |
|
112 |
/* |
113 |
* (non-Javadoc) |
114 |
* |
115 |
* @see org.eclipse.compare.CompareEditorInput#contentsCreated() |
116 |
*/ |
117 |
protected void contentsCreated() { |
118 |
super.contentsCreated(); |
119 |
compareInputChangeListener = new ICompareInputChangeListener() { |
120 |
public void compareInputChanged(ICompareInput source) { |
121 |
if (source == getCompareResult()) { |
122 |
boolean closed = false; |
123 |
if (source.getKind() == Differencer.NO_CHANGE) { |
124 |
closed = closeEditor(true); |
125 |
} |
126 |
if (!closed) { |
127 |
// The editor was closed either because the compare |
128 |
// input still has changes |
129 |
// or because the editor input is dirty. In either case, |
130 |
// fire the changes |
131 |
// to the registered listeners |
132 |
propogateInputChange(); |
133 |
} |
134 |
} |
135 |
} |
136 |
}; |
137 |
getCompareInput().addCompareInputChangeListener( |
138 |
compareInputChangeListener); |
139 |
|
140 |
if (getLeftSaveable() instanceof SaveableComparison) { |
141 |
SaveableComparison lscm = (SaveableComparison) fLeftSaveable; |
142 |
fLeftPropertyListener = new IPropertyListener() { |
143 |
public void propertyChanged(Object source, int propId) { |
144 |
if (propId == SaveableComparison.PROP_DIRTY) { |
145 |
setDirty(fLeftSaveable.isDirty()); |
146 |
} |
147 |
} |
148 |
}; |
149 |
lscm.addPropertyListener(fLeftPropertyListener); |
150 |
} |
151 |
|
152 |
if (getRightSaveable() instanceof SaveableComparison) { |
153 |
SaveableComparison rscm = (SaveableComparison) fRightSaveable; |
154 |
fRightPropertyListener = new IPropertyListener() { |
155 |
public void propertyChanged(Object source, int propId) { |
156 |
if (propId == SaveableComparison.PROP_DIRTY) { |
157 |
setDirty(fRightSaveable.isDirty()); |
158 |
} |
159 |
} |
160 |
}; |
161 |
rscm.addPropertyListener(fRightPropertyListener); |
162 |
} |
163 |
|
164 |
setDirty(fLeftSaveable.isDirty() || fRightSaveable.isDirty()); |
165 |
} |
166 |
|
167 |
/* |
168 |
* (non-Javadoc) |
169 |
* |
170 |
* @see org.eclipse.compare.CompareEditorInput#handleDispose() |
171 |
*/ |
172 |
protected void handleDispose() { |
173 |
super.handleDispose(); |
174 |
ICompareInput compareInput = getCompareInput(); |
175 |
if (compareInput != null) |
176 |
compareInput |
177 |
.removeCompareInputChangeListener(compareInputChangeListener); |
178 |
compareInputChangeListener = null; |
179 |
if (fLeftSaveable instanceof SaveableComparison) { |
180 |
SaveableComparison scm = (SaveableComparison) fLeftSaveable; |
181 |
scm.removePropertyListener(fLeftPropertyListener); |
182 |
} |
183 |
if (fLeftSaveable instanceof LocalResourceSaveableComparison) { |
184 |
LocalResourceSaveableComparison rsc = (LocalResourceSaveableComparison) fLeftSaveable; |
185 |
rsc.dispose(); |
186 |
} |
187 |
if (fRightSaveable instanceof SaveableComparison) { |
188 |
SaveableComparison scm = (SaveableComparison) fRightSaveable; |
189 |
scm.removePropertyListener(fRightPropertyListener); |
190 |
} |
191 |
if (fRightSaveable instanceof LocalResourceSaveableComparison) { |
192 |
LocalResourceSaveableComparison rsc = (LocalResourceSaveableComparison) fRightSaveable; |
193 |
rsc.dispose(); |
194 |
} |
195 |
|
196 |
if (getCompareResult() instanceof IDisposable) { |
197 |
((IDisposable) getCompareResult()).dispose(); |
198 |
} |
199 |
} |
200 |
|
201 |
private String[] getLabels() { |
202 |
IResource leftResource = getResource(fLeftElement); |
203 |
IResource rightResource = getResource(fRightElement); |
204 |
if (leftResource != null && rightResource != null) { |
205 |
String leftLabel = leftResource.getFullPath().makeRelative().toString(); |
206 |
String rightLabel = rightResource.getFullPath().makeRelative().toString(); |
207 |
if (fAncestorElement != null) { |
208 |
IResource ancestorResource = getResource(fAncestorElement); |
209 |
if (ancestorResource != null) { |
210 |
String ancestorLabel = rightResource.getFullPath().makeRelative().toString(); |
211 |
return new String[] { ancestorLabel, leftLabel, rightLabel }; |
212 |
} |
213 |
} |
214 |
return new String[] { leftLabel, rightLabel }; |
215 |
} |
216 |
if (fAncestorElement != null) { |
217 |
return new String[] { fAncestorElement.getName(), fLeftElement.getName(), fRightElement.getName() }; |
218 |
} |
219 |
return new String[] { fLeftElement.getName(), fRightElement.getName() }; |
220 |
} |
221 |
|
222 |
public String getToolTipText() { |
223 |
String[] labels = getLabels(); |
224 |
if (labels.length == 3) |
225 |
return NLS.bind(TeamUIMessages.SaveablesCompareEditorInput_threeWayTooltip, labels); |
226 |
return NLS.bind(TeamUIMessages.SaveablesCompareEditorInput_twoWayTooltip, labels); |
227 |
} |
228 |
|
229 |
public String getTitle() { |
230 |
String[] labels = getLabels(); |
231 |
if (labels.length == 3) |
232 |
return NLS.bind(TeamUIMessages.SaveablesCompareEditorInput_threeWayTitle, labels); |
233 |
return NLS.bind(TeamUIMessages.SaveablesCompareEditorInput_twoWayTitle, labels); |
234 |
} |
235 |
|
236 |
private IWorkbenchPage getPage() { |
237 |
if (page == null) |
238 |
return PlatformUI.getWorkbench().getActiveWorkbenchWindow() |
239 |
.getActivePage(); |
240 |
return page; |
241 |
} |
242 |
|
243 |
/** |
244 |
* Return the compare input of this editor input. |
245 |
* |
246 |
* @return the compare input of this editor input |
247 |
*/ |
248 |
protected final ICompareInput getCompareInput() { |
249 |
return (ICompareInput) getCompareResult(); |
250 |
} |
251 |
|
252 |
/** |
253 |
* Callback from the resource saveable that is invoked when the resource is |
254 |
* saved so that this input can fire a change event for its input. |
255 |
* Subclasses only need this method if the left side of their compare input |
256 |
* is an element returned from |
257 |
* {@link SaveableCompareEditorInput#createFileElement(IFile)}. |
258 |
*/ |
259 |
protected void fireInputChange() { |
260 |
((MyDiffNode) getCompareResult()).fireChange(); |
261 |
} |
262 |
|
263 |
protected Saveable getLeftSaveable() { |
264 |
if (fLeftSaveable == null) { |
265 |
fLeftSaveable = createLeftSaveable(); |
266 |
} |
267 |
return fLeftSaveable; |
268 |
} |
269 |
|
270 |
protected Saveable getRightSaveable() { |
271 |
if (fRightSaveable == null) { |
272 |
fRightSaveable = createRightSaveable(); |
273 |
} |
274 |
return fRightSaveable; |
275 |
} |
276 |
|
277 |
protected Saveable createLeftSaveable() { |
278 |
Object compareResult = getCompareResult(); |
279 |
Assert |
280 |
.isNotNull(compareResult, |
281 |
"This method cannot be called until after prepareInput is called"); //$NON-NLS-1$ |
282 |
ITypedElement leftFileElement = getFileElement(getCompareInput() |
283 |
.getLeft(), this); |
284 |
return new InternalResourceSaveableComparison( |
285 |
(ICompareInput) compareResult, this, leftFileElement); |
286 |
} |
287 |
|
288 |
protected Saveable createRightSaveable() { |
289 |
Object compareResult = getCompareResult(); |
290 |
Assert |
291 |
.isNotNull(compareResult, |
292 |
"This method cannot be called until after prepareInput is called"); //$NON-NLS-1$ |
293 |
ITypedElement rightFileElement = getFileElement(getCompareInput() |
294 |
.getRight(), this); |
295 |
return new InternalResourceSaveableComparison( |
296 |
(ICompareInput) compareResult, this, rightFileElement); |
297 |
} |
298 |
|
299 |
/* |
300 |
* (non-Javadoc) |
301 |
* |
302 |
* @see org.eclipse.ui.ISaveablesSource#getActiveSaveables() |
303 |
*/ |
304 |
public Saveable[] getActiveSaveables() { |
305 |
if (getCompareResult() == null) |
306 |
return new Saveable[0]; |
307 |
return new Saveable[] { getLeftSaveable(), getRightSaveable() }; |
308 |
} |
309 |
|
310 |
/* |
311 |
* (non-Javadoc) |
312 |
* |
313 |
* @see org.eclipse.ui.ISaveablesSource#getSaveables() |
314 |
*/ |
315 |
public Saveable[] getSaveables() { |
316 |
return getActiveSaveables(); |
317 |
} |
318 |
|
319 |
/* |
320 |
* (non-Javadoc) |
321 |
* |
322 |
* @see |
323 |
* org.eclipse.compare.CompareEditorInput#findContentViewer(org.eclipse. |
324 |
* jface.viewers.Viewer, |
325 |
* org.eclipse.compare.structuremergeviewer.ICompareInput, |
326 |
* org.eclipse.swt.widgets.Composite) |
327 |
*/ |
328 |
public Viewer findContentViewer(Viewer pOldViewer, ICompareInput pInput, |
329 |
Composite pParent) { |
330 |
Viewer newViewer = super.findContentViewer(pOldViewer, pInput, pParent); |
331 |
boolean isNewViewer = newViewer != pOldViewer; |
332 |
if (isNewViewer && newViewer instanceof IPropertyChangeNotifier |
333 |
&& fLeftSaveable instanceof IPropertyChangeListener |
334 |
&& fRightSaveable instanceof IPropertyChangeListener) { |
335 |
// Register the model for change events if appropriate |
336 |
final IPropertyChangeNotifier dsp = (IPropertyChangeNotifier) newViewer; |
337 |
final IPropertyChangeListener lpcl = (IPropertyChangeListener) fLeftSaveable; |
338 |
final IPropertyChangeListener rpcl = (IPropertyChangeListener) fRightSaveable; |
339 |
dsp.addPropertyChangeListener(lpcl); |
340 |
dsp.addPropertyChangeListener(rpcl); |
341 |
Control c = newViewer.getControl(); |
342 |
c.addDisposeListener(new DisposeListener() { |
343 |
public void widgetDisposed(DisposeEvent e) { |
344 |
dsp.removePropertyChangeListener(lpcl); |
345 |
dsp.removePropertyChangeListener(rpcl); |
346 |
} |
347 |
}); |
348 |
} |
349 |
return newViewer; |
350 |
} |
351 |
|
352 |
public boolean isDirty() { |
353 |
if (fLeftSaveable != null && fLeftSaveable.isDirty()) |
354 |
return true; |
355 |
if (fRightSaveable != null && fRightSaveable.isDirty()) |
356 |
return true; |
357 |
return super.isDirty(); |
358 |
} |
359 |
|
360 |
/** |
361 |
* Close the editor if it is not dirty. If it is still dirty, let the |
362 |
* content merge viewer handle the compare input change. |
363 |
* |
364 |
* @param checkForUnsavedChanges |
365 |
* whether to check for unsaved changes |
366 |
* @return <code>true</code> if the editor was closed (note that the close |
367 |
* may be asynchronous) |
368 |
*/ |
369 |
protected boolean closeEditor(boolean checkForUnsavedChanges) { |
370 |
if (isSaveNeeded() && checkForUnsavedChanges) { |
371 |
return false; |
372 |
} else { |
373 |
Runnable runnable = new Runnable() { |
374 |
public void run() { |
375 |
IEditorPart part = getPage().findEditor( |
376 |
SaveablesCompareEditorInput.this); |
377 |
getPage().closeEditor(part, false); |
378 |
} |
379 |
}; |
380 |
if (Display.getCurrent() != null) { |
381 |
runnable.run(); |
382 |
} else { |
383 |
Display display = getPage().getWorkbenchWindow().getShell() |
384 |
.getDisplay(); |
385 |
display.asyncExec(runnable); |
386 |
} |
387 |
return true; |
388 |
} |
389 |
} |
390 |
|
391 |
/** |
392 |
* Prepare the compare input of this editor input. This method is not |
393 |
* intended to be overridden of extended by subclasses (but is not final for |
394 |
* backwards compatibility reasons). The implementation of this method in |
395 |
* this class delegates the creation of the compare input to the |
396 |
* {@link #prepareCompareInput(IProgressMonitor)} method which subclasses |
397 |
* must implement. |
398 |
* |
399 |
* @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor) |
400 |
*/ |
401 |
protected Object prepareInput(IProgressMonitor monitor) |
402 |
throws InvocationTargetException, InterruptedException { |
403 |
final ICompareInput input = prepareCompareInput(monitor); |
404 |
if (input != null) |
405 |
setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title, |
406 |
new String[] { input.getName() })); |
407 |
return input; |
408 |
} |
409 |
|
410 |
/** |
411 |
* Method called from {@link #prepareInput(IProgressMonitor)} to obtain the |
412 |
* input. It's purpose is to ensure that the input is an instance of |
413 |
* {@link ICompareInput}. |
414 |
* |
415 |
* @param monitor |
416 |
* a progress monitor |
417 |
* @return the compare input |
418 |
* @throws InvocationTargetException |
419 |
* @throws InterruptedException |
420 |
*/ |
421 |
protected ICompareInput prepareCompareInput(IProgressMonitor monitor) |
422 |
throws InvocationTargetException, InterruptedException { |
423 |
ICompareInput input = createCompareInput(); |
424 |
getCompareConfiguration().setLeftEditable(isEditable(input.getLeft())); |
425 |
getCompareConfiguration() |
426 |
.setRightEditable(isEditable(input.getRight())); |
427 |
initLabels(); |
428 |
return input; |
429 |
} |
430 |
|
431 |
private boolean isEditable(Object obj) { |
432 |
if (obj instanceof IEditableContent) { |
433 |
return ((IEditableContent) obj).isEditable(); |
434 |
} |
435 |
return false; |
436 |
} |
437 |
|
438 |
private void initLabels() { |
439 |
CompareConfiguration cc = getCompareConfiguration(); |
440 |
|
441 |
IResource ancestorResource = getResource(fAncestorElement); |
442 |
IResource leftResource = getResource(fLeftElement); |
443 |
IResource rightResource = getResource(fRightElement); |
444 |
|
445 |
if (ancestorResource != null) { |
446 |
String ancestorLabel = ancestorResource.getFullPath() |
447 |
.makeRelative().toString(); |
448 |
|
449 |
cc.setAncestorLabel(ancestorLabel); |
450 |
} |
451 |
|
452 |
if (leftResource != null && rightResource != null) { |
453 |
String leftLabel = leftResource.getFullPath().makeRelative() |
454 |
.toString(); |
455 |
String rightLabel = rightResource.getFullPath().makeRelative() |
456 |
.toString(); |
457 |
|
458 |
cc.setLeftLabel(leftLabel); |
459 |
cc.setRightLabel(rightLabel); |
460 |
} |
461 |
} |
462 |
|
463 |
private ICompareInput createCompareInput() { |
464 |
return fAncestorElement == null ? new MyDiffNode(fLeftElement, |
465 |
fRightElement) : new MyDiffNode(fAncestorElement, fLeftElement, |
466 |
fRightElement); |
467 |
} |
468 |
|
469 |
private CompareInputChangeNotifier notifier = new CompareInputChangeNotifier() { |
470 |
protected IResource[] getResources(ICompareInput input) { |
471 |
IResource leftResource = getResource(fLeftElement); |
472 |
IResource rightResource = getResource(fRightElement); |
473 |
if (leftResource == null && rightResource == null) |
474 |
return new IResource[0]; |
475 |
if (leftResource == null && rightResource != null) |
476 |
return new IResource[] { rightResource }; |
477 |
if (leftResource != null && rightResource == null) |
478 |
return new IResource[] { leftResource }; |
479 |
return new IResource[] { leftResource, rightResource }; |
480 |
} |
481 |
}; |
482 |
|
483 |
private class MyDiffNode extends AbstractCompareInput { |
484 |
public MyDiffNode(ITypedElement left, ITypedElement right) { |
485 |
super(Differencer.CHANGE, null, left, right); |
486 |
} |
487 |
|
488 |
public MyDiffNode(ITypedElement ancestor, ITypedElement left, |
489 |
ITypedElement right) { |
490 |
super(Differencer.CONFLICTING, ancestor, left, right); |
491 |
} |
492 |
|
493 |
public void fireChange() { |
494 |
super.fireChange(); |
495 |
} |
496 |
|
497 |
protected CompareInputChangeNotifier getChangeNotifier() { |
498 |
return notifier; |
499 |
} |
500 |
|
501 |
public boolean needsUpdate() { |
502 |
return true; |
503 |
} |
504 |
|
505 |
public void update() { |
506 |
fireChange(); |
507 |
} |
508 |
} |
509 |
|
510 |
private IResource getResource(ITypedElement pElement) { |
511 |
if (pElement instanceof LocalResourceTypedElement |
512 |
&& pElement instanceof IResourceProvider) { |
513 |
return ((IResourceProvider) pElement).getResource(); |
514 |
} |
515 |
return null; |
516 |
} |
517 |
|
518 |
public void registerContextMenu(final MenuManager pMenuManager, |
519 |
final ISelectionProvider pSelectionProvider) { |
520 |
super.registerContextMenu(pMenuManager, pSelectionProvider); |
521 |
final Saveable lLeftSaveable = getLeftSaveable(); |
522 |
final ITypedElement lLeftElement = getFileElement(getCompareInput() |
523 |
.getLeft(), this); |
524 |
if (lLeftSaveable instanceof LocalResourceSaveableComparison) { |
525 |
pMenuManager.addMenuListener(new IMenuListener() { |
526 |
public void menuAboutToShow(IMenuManager manager) { |
527 |
handleMenuAboutToShow(manager, lLeftSaveable, lLeftElement, |
528 |
pSelectionProvider); |
529 |
} |
530 |
}); |
531 |
} |
532 |
final Saveable lRightSaveable = getRightSaveable(); |
533 |
final ITypedElement lRightElement = getFileElement(getCompareInput() |
534 |
.getRight(), this); |
535 |
if (lRightSaveable instanceof LocalResourceSaveableComparison) { |
536 |
pMenuManager.addMenuListener(new IMenuListener() { |
537 |
public void menuAboutToShow(IMenuManager manager) { |
538 |
handleMenuAboutToShow(manager, lRightSaveable, |
539 |
lRightElement, pSelectionProvider); |
540 |
} |
541 |
}); |
542 |
} |
543 |
} |
544 |
|
545 |
/* |
546 |
* (non-Javadoc) |
547 |
* |
548 |
* @see |
549 |
* org.eclipse.compare.CompareEditorInput#addCompareInputChangeListener( |
550 |
* org.eclipse.compare.structuremergeviewer.ICompareInput, |
551 |
* org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) |
552 |
*/ |
553 |
public void addCompareInputChangeListener(ICompareInput input, |
554 |
ICompareInputChangeListener listener) { |
555 |
if (input == getCompareResult()) { |
556 |
inputChangeListeners.add(listener); |
557 |
} else { |
558 |
super.addCompareInputChangeListener(input, listener); |
559 |
} |
560 |
} |
561 |
|
562 |
/* |
563 |
* (non-Javadoc) |
564 |
* |
565 |
* @see |
566 |
* org.eclipse.compare.CompareEditorInput#removeCompareInputChangeListener |
567 |
* (org.eclipse.compare.structuremergeviewer.ICompareInput, |
568 |
* org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) |
569 |
*/ |
570 |
public void removeCompareInputChangeListener(ICompareInput input, |
571 |
ICompareInputChangeListener listener) { |
572 |
if (input == getCompareResult()) { |
573 |
inputChangeListeners.remove(listener); |
574 |
} else { |
575 |
super.removeCompareInputChangeListener(input, listener); |
576 |
} |
577 |
} |
578 |
|
579 |
private void propogateInputChange() { |
580 |
if (!inputChangeListeners.isEmpty()) { |
581 |
Object[] allListeners = inputChangeListeners.getListeners(); |
582 |
final ICompareInput compareResult = (ICompareInput) getCompareResult(); |
583 |
for (int i = 0; i < allListeners.length; i++) { |
584 |
final ICompareInputChangeListener listener = (ICompareInputChangeListener) allListeners[i]; |
585 |
SafeRunner.run(new ISafeRunnable() { |
586 |
public void run() throws Exception { |
587 |
listener.compareInputChanged(compareResult); |
588 |
} |
589 |
|
590 |
public void handleException(Throwable exception) { |
591 |
// Logged by the safe runner |
592 |
} |
593 |
}); |
594 |
} |
595 |
} |
596 |
} |
597 |
|
598 |
/* |
599 |
* (non-Javadoc) |
600 |
* |
601 |
* @see org.eclipse.compare.CompareEditorInput#getTitleImage() |
602 |
*/ |
603 |
public Image getTitleImage() { |
604 |
ImageRegistry reg = TeamUIPlugin.getPlugin().getImageRegistry(); |
605 |
Image image = reg.get(ITeamUIImages.IMG_SYNC_VIEW); |
606 |
if (image == null) { |
607 |
image = getImageDescriptor().createImage(); |
608 |
reg.put(ITeamUIImages.IMG_SYNC_VIEW, image); |
609 |
} |
610 |
return image; |
611 |
} |
612 |
|
613 |
/* |
614 |
* (non-Javadoc) |
615 |
* |
616 |
* @see org.eclipse.ui.IEditorInput#getImageDescriptor() |
617 |
*/ |
618 |
public ImageDescriptor getImageDescriptor() { |
619 |
return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW); |
620 |
} |
621 |
|
622 |
/* |
623 |
* (non-Javadoc) |
624 |
* |
625 |
* @see org.eclipse.compare.CompareEditorInput#canRunAsJob() |
626 |
*/ |
627 |
public boolean canRunAsJob() { |
628 |
return true; |
629 |
} |
630 |
|
631 |
private void handleMenuAboutToShow(IMenuManager manager, Saveable saveable, |
632 |
ITypedElement element, ISelectionProvider provider) { |
633 |
if (provider instanceof ITextViewer) { |
634 |
ITextViewer v = (ITextViewer) provider; |
635 |
IDocument d = v.getDocument(); |
636 |
IDocument other = (IDocument) Utils.getAdapter(saveable, |
637 |
IDocument.class); |
638 |
if (d == other) { |
639 |
if (element instanceof IResourceProvider) { |
640 |
IResourceProvider rp = (IResourceProvider) element; |
641 |
IResource resource = rp.getResource(); |
642 |
StructuredSelection selection = new StructuredSelection( |
643 |
resource); |
644 |
IWorkbenchPart workbenchPart = getContainer() |
645 |
.getWorkbenchPart(); |
646 |
if (workbenchPart != null) { |
647 |
IWorkbenchSite ws = workbenchPart.getSite(); |
648 |
MenuManager submenu1 = new MenuManager( |
649 |
getShowInMenuLabel()); |
650 |
IContributionItem showInMenu = ContributionItemFactory.VIEWS_SHOW_IN |
651 |
.create(ws.getWorkbenchWindow()); |
652 |
submenu1.add(showInMenu); |
653 |
manager.insertAfter("file", submenu1); //$NON-NLS-1$ |
654 |
MenuManager submenu2 = new MenuManager( |
655 |
TeamUIMessages.OpenWithActionGroup_0); |
656 |
submenu2.add(new OpenWithMenu(ws.getPage(), resource)); |
657 |
manager.insertAfter("file", submenu2); //$NON-NLS-1$ |
658 |
|
659 |
OpenFileAction openFileAction = new OpenFileAction(ws |
660 |
.getPage()); |
661 |
openFileAction.selectionChanged(selection); |
662 |
manager.insertAfter("file", openFileAction); //$NON-NLS-1$ |
663 |
} |
664 |
} |
665 |
} |
666 |
} |
667 |
} |
668 |
|
669 |
private String getShowInMenuLabel() { |
670 |
String keyBinding = null; |
671 |
|
672 |
IBindingService bindingService = (IBindingService) PlatformUI |
673 |
.getWorkbench().getAdapter(IBindingService.class); |
674 |
if (bindingService != null) |
675 |
keyBinding = bindingService |
676 |
.getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$ |
677 |
|
678 |
if (keyBinding == null) |
679 |
keyBinding = ""; //$NON-NLS-1$ |
680 |
|
681 |
return NLS |
682 |
.bind(TeamUIMessages.SaveableCompareEditorInput_0, keyBinding); |
683 |
} |
684 |
|
685 |
// TODO: add getAdapter for IFile[] |
686 |
|
687 |
private class InternalResourceSaveableComparison extends |
688 |
LocalResourceSaveableComparison implements |
689 |
ISharedDocumentAdapterListener { |
690 |
private LocalResourceTypedElement lrte; |
691 |
private boolean connected = false; |
692 |
|
693 |
public InternalResourceSaveableComparison(ICompareInput input, |
694 |
CompareEditorInput editorInput, ITypedElement element) { |
695 |
super(input, editorInput, element); |
696 |
if (element instanceof LocalResourceTypedElement) { |
697 |
lrte = (LocalResourceTypedElement) element; |
698 |
if (lrte.isConnected()) { |
699 |
registerSaveable(true); |
700 |
} else { |
701 |
lrte.setSharedDocumentListener(this); |
702 |
} |
703 |
} |
704 |
} |
705 |
|
706 |
protected void fireInputChange() { |
707 |
SaveablesCompareEditorInput.this.fireInputChange(); |
708 |
} |
709 |
|
710 |
public void dispose() { |
711 |
super.dispose(); |
712 |
if (lrte != null) |
713 |
lrte.setSharedDocumentListener(null); |
714 |
} |
715 |
|
716 |
public void handleDocumentConnected() { |
717 |
if (connected) |
718 |
return; |
719 |
connected = true; |
720 |
registerSaveable(false); |
721 |
if (lrte != null) |
722 |
lrte.setSharedDocumentListener(null); |
723 |
} |
724 |
|
725 |
private void registerSaveable(boolean init) { |
726 |
ICompareContainer container = getContainer(); |
727 |
IWorkbenchPart part = container.getWorkbenchPart(); |
728 |
if (part != null) { |
729 |
ISaveablesLifecycleListener lifecycleListener = getSaveablesLifecycleListener(part); |
730 |
// Remove this saveable from the lifecycle listener |
731 |
if (!init) |
732 |
lifecycleListener |
733 |
.handleLifecycleEvent(new SaveablesLifecycleEvent( |
734 |
part, SaveablesLifecycleEvent.POST_CLOSE, |
735 |
new Saveable[] { this }, false)); |
736 |
// Now fix the hashing so it uses the connected document |
737 |
initializeHashing(); |
738 |
// Finally, add this saveable back to the listener |
739 |
lifecycleListener |
740 |
.handleLifecycleEvent(new SaveablesLifecycleEvent(part, |
741 |
SaveablesLifecycleEvent.POST_OPEN, |
742 |
new Saveable[] { this }, false)); |
743 |
} |
744 |
} |
745 |
|
746 |
public void handleDocumentDeleted() { |
747 |
// Ignore |
748 |
} |
749 |
|
750 |
public void handleDocumentDisconnected() { |
751 |
// Ignore |
752 |
} |
753 |
|
754 |
public void handleDocumentFlushed() { |
755 |
// Ignore |
756 |
} |
757 |
|
758 |
public void handleDocumentSaved() { |
759 |
// Ignore |
760 |
} |
761 |
|
762 |
/* |
763 |
* @see org.eclipse.ui.Saveable#equals(java.lang.Object) |
764 |
*/ |
765 |
public boolean equals(Object obj) { |
766 |
if (this == obj) |
767 |
return true; |
768 |
|
769 |
if (!(obj instanceof Saveable)) |
770 |
return false; |
771 |
|
772 |
Object document = getAdapter(IDocument.class); |
773 |
|
774 |
if (document != null) { |
775 |
Object otherDocument = ((Saveable) obj) |
776 |
.getAdapter(IDocument.class); |
777 |
|
778 |
if (document == null && otherDocument == null) |
779 |
return false; |
780 |
|
781 |
return document != null && document.equals(otherDocument); |
782 |
} |
783 |
|
784 |
if (obj instanceof InternalResourceSaveableComparison) { |
785 |
InternalResourceSaveableComparison rscm = (InternalResourceSaveableComparison) obj; |
786 |
return rscm.getInput().equals(getInput()) && rscm.lrte.equals(lrte); |
787 |
} |
788 |
return false; |
789 |
} |
790 |
} |
791 |
} |