KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > ui > history > RevisionAnnotationController


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.history;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.resources.IFile;
17 import org.eclipse.core.resources.IStorage;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.jface.text.revisions.*;
20 import org.eclipse.jface.viewers.*;
21 import org.eclipse.swt.events.DisposeEvent;
22 import org.eclipse.swt.events.DisposeListener;
23 import org.eclipse.team.core.history.IFileRevision;
24 import org.eclipse.team.core.variants.IResourceVariant;
25 import org.eclipse.team.internal.ui.TeamUIMessages;
26 import org.eclipse.team.internal.ui.Utils;
27 import org.eclipse.team.internal.ui.history.FileRevisionEditorInput;
28 import org.eclipse.ui.*;
29 import org.eclipse.ui.editors.text.EditorsUI;
30 import org.eclipse.ui.ide.IDE;
31 import org.eclipse.ui.internal.registry.EditorDescriptor;
32 import org.eclipse.ui.part.FileEditorInput;
33 import org.eclipse.ui.part.MultiPageEditorPart;
34 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
35 import org.eclipse.ui.texteditor.ITextEditor;
36
37 /**
38  * Helper class that coordinates the selection behavior between an editor
39  * revision ruler and a history list such as one shown in the history view. In
40  * other words, the selection in the history list will be reflected in the
41  * revision rule and vice versa.
42  *
43  * @see Revision
44  * @see RevisionInformation
45  * @since 3.3
46  */

47 public abstract class RevisionAnnotationController {
48
49     private ISelectionProvider fRulerSelectionProvider;
50     private ISelectionProvider fHistoryListSelectionProvider;
51     private ISelectionChangedListener rulerListener = new ISelectionChangedListener() {
52         public void selectionChanged(SelectionChangedEvent event) {
53             ISelection selection= event.getSelection();
54             Revision selected= null;
55             if (selection instanceof IStructuredSelection)
56                 selected= (Revision) ((IStructuredSelection) selection).getFirstElement();
57         
58             if (selected == null)
59                 return;
60         
61             revisionSelected(selected);
62         }
63     };
64     private ISelectionChangedListener historyListListener = new ISelectionChangedListener() {
65         public void selectionChanged(SelectionChangedEvent event) {
66             ISelection selection= event.getSelection();
67             if (selection instanceof IStructuredSelection) {
68                 IStructuredSelection ss = (IStructuredSelection) selection;
69                 if (ss.size() == 1) {
70                     Object JavaDoc first= ss.getFirstElement();
71                     if (first != null)
72                         historyEntrySelected(first);
73                 }
74             }
75         }
76     };
77     
78     /**
79      * Open a text editor that supports the use of a revision ruler on the given
80      * file. If an appropriate editor is already open, it is returned. Otherwise
81      * a new editor is opened.
82      *
83      * @param page
84      * the page in which the editor is to be opened
85      * @param file
86      * the file to be edited
87      * @return the open editor on the file
88      * @throws PartInitException
89      */

90     public static AbstractDecoratedTextEditor openEditor(IWorkbenchPage page, IFile file) throws PartInitException {
91         if (file == null)
92             return null;
93         FileEditorInput input = new FileEditorInput(file);
94         IEditorPart[] openEditors = findOpenEditorsForFile(page, input);
95         if (openEditors.length > 0) {
96             AbstractDecoratedTextEditor te= findTextEditor(page, openEditors, input);
97             if (te != null) {
98                 return te;
99             }
100         }
101         
102         // No existing editor references found, try to open a new editor for the file
103
try {
104             IEditorDescriptor descrptr = IDE.getEditorDescriptor(file);
105             // Try to open the associated editor only if its an internal editor
106
// Also, if a non-text editor is already open, there is no need to try and open
107
// an editor since the open will find the non-text editor
108
if (descrptr.isInternal() && openEditors.length == 0){
109                 IEditorPart part = page.openEditor(input, IDE.getEditorDescriptor(file).getId(), true, IWorkbenchPage.MATCH_INPUT);
110                 AbstractDecoratedTextEditor te = findTextEditorPart(page, part, input);
111                 if (te != null)
112                     return te;
113                 
114                 //editor opened is not a text editor - close it
115
page.closeEditor(part, false);
116             }
117             //open file in default text editor
118
IEditorPart part = page.openEditor(input, EditorsUI.DEFAULT_TEXT_EDITOR_ID, true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID);
119             AbstractDecoratedTextEditor te = findTextEditorPart(page, part, input);
120             if (te != null)
121                 return te;
122             
123         } catch (PartInitException e) {
124         }
125     
126         return null;
127     }
128     
129     /**
130      * Open a text editor that supports the use of a revision ruler on the given
131      * file. If an appropriate editor is already open, it is returned. Otherwise
132      * a new editor is opened.
133      *
134      * @param page
135      * the page in which the editor is to be opened
136      * @param fileRevision
137      * the file revision object
138      * @param storage
139      * the storage that provides access to the contents of the file revision
140      * @return the open editor on the file revision
141      * @throws PartInitException
142      */

143     public static AbstractDecoratedTextEditor openEditor(IWorkbenchPage page,
144             Object JavaDoc fileRevision, IStorage storage) throws PartInitException {
145         String JavaDoc id = getEditorId(storage);
146         ITextEditor editor = getEditor(id, fileRevision, storage);
147         if (editor instanceof AbstractDecoratedTextEditor)
148             return (AbstractDecoratedTextEditor) editor;
149         return null;
150     }
151     
152
153     private static ITextEditor getEditor(String JavaDoc id, Object JavaDoc fileRevision, IStorage storage) throws PartInitException {
154         final IWorkbench workbench= PlatformUI.getWorkbench();
155         final IWorkbenchWindow window= workbench.getActiveWorkbenchWindow();
156         IWorkbenchPage page= window.getActivePage();
157         IEditorPart part = page.openEditor(new FileRevisionEditorInput(fileRevision, storage), id);
158         if (part instanceof ITextEditor) {
159             return (ITextEditor)part;
160         } else {
161             // We asked for a text editor but didn't get one
162
// so open a vanilla text editor
163
page.closeEditor(part, false);
164             part = page.openEditor(new FileRevisionEditorInput(fileRevision, storage), EditorsUI.DEFAULT_TEXT_EDITOR_ID);
165             if (part instanceof ITextEditor) {
166                 return (ITextEditor)part;
167             } else {
168                 // There is something really wrong so just bail
169
throw new PartInitException(TeamUIMessages.RevisionAnnotationController_0);
170             }
171         }
172     }
173
174     private static String JavaDoc getEditorId(IStorage storage) {
175         String JavaDoc id;
176         IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry();
177         IEditorDescriptor descriptor = registry.getDefaultEditor(storage.getName());
178         if (descriptor == null || !descriptor.isInternal()) {
179             id = EditorsUI.DEFAULT_TEXT_EDITOR_ID;
180         } else {
181             try {
182                 if (isTextEditor(descriptor)) {
183                     id = descriptor.getId();
184                 } else {
185                     id = EditorsUI.DEFAULT_TEXT_EDITOR_ID;
186                 }
187             } catch (CoreException e) {
188                 id = EditorsUI.DEFAULT_TEXT_EDITOR_ID;
189             }
190         }
191         return id;
192     }
193
194     private static boolean isTextEditor(IEditorDescriptor descriptor)
195             throws CoreException {
196         if (descriptor instanceof EditorDescriptor) {
197             EditorDescriptor desc = (EditorDescriptor) descriptor;
198             return desc.createEditor() instanceof AbstractDecoratedTextEditor;
199         }
200         return false;
201     }
202     
203     private static AbstractDecoratedTextEditor findOpenTextEditorForFile(IWorkbenchPage page, IFile file) {
204         if (file == null)
205             return null;
206         FileEditorInput input = new FileEditorInput(file);
207         IEditorPart[] editors = findOpenEditorsForFile(page, input);
208         return findTextEditor(page, editors, input);
209     }
210     
211     private static AbstractDecoratedTextEditor findTextEditor(IWorkbenchPage page, IEditorPart[] editors, IEditorInput input) {
212         for (int i = 0; i < editors.length; i++) {
213             IEditorPart editor = editors[i];
214             AbstractDecoratedTextEditor te = findTextEditorPart(page, editor, input);
215             if (te != null)
216                 return te;
217         }
218         return null;
219     }
220
221     private static AbstractDecoratedTextEditor findTextEditorPart(IWorkbenchPage page, IEditorPart editor, IEditorInput input) {
222         if (editor instanceof AbstractDecoratedTextEditor)
223             return (AbstractDecoratedTextEditor) editor;
224         if (editor instanceof MultiPageEditorPart) {
225             MultiPageEditorPart mpep = (MultiPageEditorPart) editor;
226             IEditorPart[] parts = mpep.findEditors(input);
227             for (int i = 0; i < parts.length; i++) {
228                 IEditorPart editorPart = parts[i];
229                 if (editorPart instanceof AbstractDecoratedTextEditor) {
230                     page.activate(mpep);
231                     mpep.setActiveEditor(editorPart);
232                     return (AbstractDecoratedTextEditor) editorPart;
233                 }
234             }
235         }
236         return null;
237     }
238     
239     private static IEditorPart[] findOpenEditorsForFile(IWorkbenchPage page, FileEditorInput input) {
240         final IEditorReference[] references= page.findEditors(input, null, IWorkbenchPage.MATCH_INPUT);
241         final List JavaDoc editors = new ArrayList JavaDoc();
242         for (int i= 0; i < references.length; i++) {
243             IEditorReference reference= references[i];
244             IEditorPart editor= reference.getEditor(false);
245             editors.add(editor);
246         }
247         
248         return (IEditorPart[]) editors.toArray(new IEditorPart[editors.size()]);
249     }
250     
251     private static AbstractDecoratedTextEditor findOpenTextEditorFor(IWorkbenchPage page, Object JavaDoc object) {
252         if (object == null)
253             return null;
254         if (object instanceof IFile) {
255             IFile file = (IFile) object;
256             return findOpenTextEditorForFile(page, file);
257         }
258         final IWorkbench workbench= PlatformUI.getWorkbench();
259         final IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
260         IEditorReference[] references= window.getActivePage().getEditorReferences();
261         for (int i= 0; i < references.length; i++) {
262             IEditorReference reference= references[i];
263             try {
264                 if (object.equals(reference.getEditorInput())) {
265                     IEditorPart editor= reference.getEditor(false);
266                     if (editor instanceof AbstractDecoratedTextEditor)
267                         return (AbstractDecoratedTextEditor) editor;
268                 }
269             } catch (PartInitException e) {
270                 // ignore
271
}
272         }
273         
274         return null;
275     }
276     
277     private static IRevisionRulerColumnExtension findEditorRevisonRulerColumn(IWorkbenchPage page, Object JavaDoc object) {
278         ITextEditor editor= findOpenTextEditorFor(page, object);
279         if (editor == null)
280             return null;
281
282         IRevisionRulerColumn column= (IRevisionRulerColumn) editor.getAdapter(IRevisionRulerColumn.class);
283         if (column instanceof IRevisionRulerColumnExtension) {
284             if (column.getControl() != null && column.getControl().isDisposed())
285                 return null;
286             return (IRevisionRulerColumnExtension) column;
287         }
288         
289         return null;
290     }
291     
292     private RevisionAnnotationController(IRevisionRulerColumnExtension revisionRuler, ISelectionProvider historyList) {
293         fHistoryListSelectionProvider = historyList;
294         if (revisionRuler == null) {
295             fRulerSelectionProvider = null;
296             return;
297         }
298         
299         fRulerSelectionProvider= revisionRuler.getRevisionSelectionProvider();
300         fRulerSelectionProvider.addSelectionChangedListener(rulerListener);
301         fHistoryListSelectionProvider.addSelectionChangedListener(historyListListener);
302         
303         ((IRevisionRulerColumn)revisionRuler).getControl().addDisposeListener(new DisposeListener() {
304             public void widgetDisposed(DisposeEvent e) {
305                 dispose();
306             }
307         });
308     }
309     
310     /**
311      * Create a controller that links an editor on a local file to a history list.
312      * @param page the workbench page
313      * @param file the local file
314      * @param historyList the history list selection provider
315      */

316     public RevisionAnnotationController(IWorkbenchPage page, IFile file, ISelectionProvider historyList) {
317         this(findEditorRevisonRulerColumn(page, file), historyList);
318     }
319     
320     /**
321      * Create a controller that links an editor input on a remote file to a history list.
322      * @param page the workbench page
323      * @param editorInput the editor input for the remote file
324      * @param historyList the history list selection provider
325      */

326     public RevisionAnnotationController(IWorkbenchPage page, IStorageEditorInput editorInput,
327             ISelectionProvider historyList) {
328         this(findEditorRevisonRulerColumn(page, editorInput), historyList);
329     }
330
331     /**
332      * Dispose of the controller.
333      */

334     public void dispose() {
335         if (fRulerSelectionProvider != null) {
336             fRulerSelectionProvider.removeSelectionChangedListener(rulerListener);
337             fHistoryListSelectionProvider.removeSelectionChangedListener(historyListListener);
338             rulerListener= null;
339             fRulerSelectionProvider= null;
340             historyListListener= null;
341             fHistoryListSelectionProvider= null;
342         }
343     }
344
345     /**
346      * Callback from the ruler when a particular revision has been selected by the user.
347      * By default, this method will set the selection of the history list selection
348      * provider that was passed in the constructor using the history entry returned
349      * by {@link #getHistoryEntry(Revision)}. Subclasses may override.
350      * @param selected the selected revision
351      */

352     protected void revisionSelected(Revision selected) {
353         Object JavaDoc entry= getHistoryEntry(selected);
354         
355         if (entry != null) {
356             IStructuredSelection selection = new StructuredSelection(entry);
357             if (fHistoryListSelectionProvider instanceof Viewer) {
358                 Viewer v = (Viewer) fHistoryListSelectionProvider;
359                 v.setSelection(selection, true);
360             } else if (fHistoryListSelectionProvider != null) {
361                 fHistoryListSelectionProvider.setSelection(selection);
362             }
363         }
364     }
365     
366     /**
367      * Return the history list entry corresponding to the provided revision.
368      * THis method is called by the {@link #revisionSelected(Revision)} method in
369      * order to determine what the selection of the history list selection provider
370      * should be set to.
371      * @param selected the selected revision.
372      * @return the history list entry that corresponds to the provided revision.
373      */

374     protected abstract Object JavaDoc getHistoryEntry(Revision selected);
375
376     /**
377      * Callback that is invoked when the selection in the history list changes.
378      * @param historyEntry the history entry
379      */

380     /* package */ void historyEntrySelected(Object JavaDoc historyEntry) {
381         String JavaDoc id = getRevisionId(historyEntry);
382         if (id != null && fRulerSelectionProvider != null) {
383             fRulerSelectionProvider.setSelection(new StructuredSelection(id));
384         }
385     }
386     
387     /**
388      * Return the revision id associated with the given history list entry.
389      * This method is used to determine which revision in the revision ruler should
390      * be highlighted when the history list selection provider fires a selection changed event.
391      * By default, this method tries to adapt the entry to either {@link IFileRevision} or
392      * {@link IResourceVariant} in order to obtain the content identifier. Subclasses may override.
393      *
394      * @param historyEntry the history list entry
395      * @return the id of the entry
396      */

397     protected String JavaDoc getRevisionId(Object JavaDoc historyEntry) {
398         IFileRevision revision= (IFileRevision)Utils.getAdapter(historyEntry, IFileRevision.class);
399         if (revision != null) {
400             return revision.getContentIdentifier();
401         }
402         IResourceVariant variant = (IResourceVariant)Utils.getAdapter(historyEntry, IResourceVariant.class);
403         if (variant != null)
404             return variant.getContentIdentifier();
405         return null;
406     }
407     
408 }
409
Popular Tags