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 |
} |