View Javadoc

1   package de.matthias_burbach.mosaique4eclipse.views;
2   
3   import java.io.File;
4   import java.util.Iterator;
5   import java.util.List;
6   
7   import org.eclipse.core.resources.IContainer;
8   import org.eclipse.core.resources.IFile;
9   import org.eclipse.core.resources.IFolder;
10  import org.eclipse.core.resources.IProject;
11  import org.eclipse.core.resources.IResource;
12  import org.eclipse.core.resources.ResourcesPlugin;
13  import org.eclipse.core.runtime.IAdaptable;
14  import org.eclipse.core.runtime.IPath;
15  import org.eclipse.core.runtime.Path;
16  import org.eclipse.jface.action.Action;
17  import org.eclipse.jface.action.IContributionItem;
18  import org.eclipse.jface.action.IMenuListener;
19  import org.eclipse.jface.action.IMenuManager;
20  import org.eclipse.jface.action.IToolBarManager;
21  import org.eclipse.jface.action.MenuManager;
22  import org.eclipse.jface.action.Separator;
23  import org.eclipse.jface.util.OpenStrategy;
24  import org.eclipse.jface.viewers.AbstractTreeViewer;
25  import org.eclipse.jface.viewers.IOpenListener;
26  import org.eclipse.jface.viewers.IStructuredSelection;
27  import org.eclipse.jface.viewers.OpenEvent;
28  import org.eclipse.jface.viewers.Viewer;
29  import org.eclipse.jface.viewers.ViewerFilter;
30  import org.eclipse.jface.viewers.ViewerSorter;
31  import org.eclipse.swt.widgets.Composite;
32  import org.eclipse.swt.widgets.Menu;
33  import org.eclipse.ui.IActionBars;
34  import org.eclipse.ui.IEditorDescriptor;
35  import org.eclipse.ui.IEditorInput;
36  import org.eclipse.ui.IEditorPart;
37  import org.eclipse.ui.IEditorRegistry;
38  import org.eclipse.ui.IWorkbench;
39  import org.eclipse.ui.IWorkbenchActionConstants;
40  import org.eclipse.ui.IWorkbenchPage;
41  import org.eclipse.ui.IWorkbenchWindow;
42  import org.eclipse.ui.PlatformUI;
43  import org.eclipse.ui.ide.IDE;
44  import org.eclipse.ui.part.DrillDownAdapter;
45  import org.eclipse.ui.part.ViewPart;
46  import org.eclipse.ui.texteditor.ITextEditor;
47  
48  import de.matthias_burbach.mosaique.core.model.AbstractFileItem;
49  import de.matthias_burbach.mosaique.core.model.Put;
50  import de.matthias_burbach.mosaique.swing.AbstractFileItemNode;
51  import de.matthias_burbach.mosaique.swing.JspNode;
52  import de.matthias_burbach.mosaique.swing.PutNode;
53  import de.matthias_burbach.mosaique4eclipse.MosaiquePlugin;
54  import de.matthias_burbach.mosaique4eclipse.util.ExternalEditorInput;
55  import de.matthias_burbach.mosaique4eclipse.util.FileStorage;
56  import de.matthias_burbach.mosaique4eclipse.util.Util;
57  
58  /***
59   * Is the Mosaique explorer-like workbench view. The view is connected to the
60   * model using a content provider.
61   * <p/>
62   * The view uses a label provider to define
63   * how model objects should be presented in the view.
64   * <p/>
65   */
66  public class MosaiqueView extends ViewPart {
67      /***
68       * The tree viewer.
69       */
70      private MosaiqueTreeViewer treeViewer;
71  
72      /***
73       * The content provider for the tree viewer (the model adapter).
74       */
75      private MosaiqueTreeContentProvider viewContentProvider;
76  
77      /***
78       * The drill down adapter. Allows to make inner node of the tree to be the
79       * root (of the current view).
80       */
81      private DrillDownAdapter drillDownAdapter;
82  
83      /***
84       * The action to refresh the tree.
85       */
86      private Action refreshAction;
87  
88      /***
89       * The action to collapse a tree node and all its sub nodes.
90       */
91      private Action collapseAllAction;
92  
93      /***
94       * This is a callback that will allow us to create the viewer and initialize
95       * it.
96       *
97       * @param parent The parent composite embedding this view.
98       */
99      public void createPartControl(final Composite parent) {
100         treeViewer = new MosaiqueTreeViewer(parent);
101         drillDownAdapter = new DrillDownAdapter(treeViewer);
102         viewContentProvider = new MosaiqueTreeContentProvider();
103         treeViewer.setContentProvider(viewContentProvider);
104         treeViewer.setLabelProvider(new MosaiqueLabelProvider(
105                 viewContentProvider));
106         treeViewer.setSorter(new ViewerSorter() {
107             /*
108              * (non-Javadoc)
109              * @see org.eclipse.jface.viewers.ViewerSorter#category(
110              *          java.lang.Object)
111              */
112             /***
113              * {@inheritDoc}
114              */
115             public int category(final Object element) {
116                 int result = 0;
117                 if (element instanceof JspNode) {
118                     result = 1;
119                 } else if (element instanceof PutNode) {
120                     Put put = ((PutNode) element).getPut();
121                     if (put.isDynamicPut()) {
122                         final int infinity = 9999;
123                         result = infinity; //dynamic puts go the very bottom
124                     } else {
125                         result = Math.max(0, put.getLevel());
126                     }
127                 }
128                 return result;
129             }
130         });
131         treeViewer.addFilter(new ViewerFilter() {
132             /*
133              * (non-Javadoc)
134              * @see org.eclipse.jface.viewers.ViewerFilter#select(
135              *          org.eclipse.jface.viewers.Viewer,
136              *          java.lang.Object,
137              *          java.lang.Object)
138              */
139             /***
140              * {@inheritDoc}
141              */
142             public boolean select(
143                     final Viewer theViewer,
144                     final Object parentElement,
145                     final Object element) {
146                 boolean result = false;
147                 if (element instanceof IFolder) {
148                     String name = ((IFolder) element).getName();
149                     if (name.equals("src") || name.equals("web")
150                             || name.equals("WEB-INF")) {
151                         result = true;
152                     }
153                 } else if (element instanceof IFile) {
154                     if (Util.isStrutsConfigFile(element)) {
155                         result = true;
156                     }
157                 } else if (element instanceof IProject) {
158                     IProject project = (IProject) element;
159                     String name = project.getName();
160                     if (name.indexOf("vrp-brand-") != -1
161                             && project.isAccessible()) {
162                         result = true;
163                     }
164                 } else {
165                     result = true;
166                 }
167                 return result;
168             };
169         });
170         treeViewer.setInput(getInitialInput());
171 
172         treeViewer.addOpenListener(new IOpenListener() {
173             /*
174              * (non-Javadoc)
175              * @see org.eclipse.jface.viewers.IOpenListener#open(
176              *          org.eclipse.jface.viewers.OpenEvent)
177              */
178             /***
179              * {@inheritDoc}
180              */
181             public void open(final OpenEvent event) {
182                 handleOpen(event);
183             }
184         });
185 
186         makeActions();
187         hookContextMenu();
188         contributeToActionBars();
189     }
190 
191     /***
192      * Passes the focus request to this viewer's tree control.
193      */
194     public void setFocus() {
195         treeViewer.getControl().setFocus();
196     }
197 
198     /***
199      * Handles an open event from the viewer. Opens an editor on the selected
200      * file.
201      *
202      * @param event The open event.
203      */
204     private void handleOpen(final OpenEvent event) {
205         IStructuredSelection selection = (IStructuredSelection) event
206                 .getSelection();
207         Object element = selection.getFirstElement();
208         String path = null;
209         int selectionBegin = 0;
210         int selectionEnd = 0;
211         if (element instanceof IFile) {
212             IFile iFile = (IFile) element;
213             path = Util.iFiletoFile(iFile).getAbsolutePath();
214         } else if (element instanceof AbstractFileItemNode) {
215             AbstractFileItemNode fileItemNode = (AbstractFileItemNode) element;
216             AbstractFileItem fileItem = fileItemNode.getFileItem();
217             path = fileItem.getFilePath();
218             selectionBegin = fileItem.getBegin();
219             selectionEnd = fileItem.getEnd();
220         }
221         if (path != null) {
222             openFile(path, selectionBegin, selectionEnd);
223         }
224     }
225 
226     /***
227      * Opens an editor on the given file resource.
228      *
229      * @param fileName The full path and name of the file to open.
230      * @param selectionBegin The character position to start the text selection
231      *                       at.
232      * @param selectionEnd The character position to end the text selection at.
233      */
234     void openFile(
235             final String fileName,
236             final int selectionBegin,
237             final int selectionEnd) {
238         // reject directories
239         if (new File(fileName).isDirectory()) {
240             return;
241         }
242 
243         IWorkbench workbench = PlatformUI.getWorkbench();
244         IWorkbenchWindow window = workbench.getWorkbenchWindows()[0];
245         IWorkbenchPage page = window.getActivePage();
246         IPath path = new Path(fileName);
247 
248         // If the file exists in the workspace, open it
249         IFile file = ResourcesPlugin.getWorkspace().getRoot()
250                 .getFileForLocation(path);
251         IEditorPart editor = null;
252         ITextEditor textEditor = null;
253         if (file != null && file.exists()) {
254             boolean activate = OpenStrategy.activateOnOpen();
255             try {
256                 IEditorPart editorPart = IDE.openEditor(getSite().getPage(),
257                         file, activate);
258                 textEditor = (ITextEditor) editorPart
259                         .getAdapter(ITextEditor.class);
260             } catch (Exception e) {
261                 e.printStackTrace();
262             }
263         } else {
264             // else open the stream directly (read-only)
265             if (page == null) {
266                 return;
267             }
268             FileStorage storage = new FileStorage(path);
269             IEditorRegistry registry = MosaiquePlugin.getDefault()
270                     .getWorkbench().getEditorRegistry();
271             IEditorDescriptor desc = registry.getDefaultEditor(fileName);
272             if (desc == null) {
273                 desc = registry
274                         .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
275             }
276             IEditorInput input = new ExternalEditorInput(storage);
277             try {
278                 editor = page.openEditor(input, desc.getId());
279                 textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
280             } catch (Exception e) {
281                 e.printStackTrace();
282             }
283             storage.setReadOnly();
284         }
285 
286         // If a selection range was given, go to it
287         if (textEditor != null && selectionEnd - selectionBegin > 0) {
288             try {
289                 textEditor.selectAndReveal(
290                         selectionBegin,
291                         selectionEnd - selectionBegin);
292             } catch (Exception e) {
293                 e.printStackTrace();
294             }
295         }
296     }
297 
298     /***
299      * Tries to convert the page input to a resource, either directly or via
300      * IAdaptable. If the resource is a container, it uses that.
301      * If the resource is a file, it uses its parent folder.
302      * If a resource could not be obtained, it uses the workspace root.
303      *
304      * @return The initial input for the viewer.
305      */
306     protected IAdaptable getInitialInput() {
307         IAdaptable input = getSite().getPage().getInput();
308         if (input != null) {
309             IResource resource = null;
310             if (input instanceof IResource) {
311                 resource = (IResource) input;
312             } else {
313                 resource = (IResource) input.getAdapter(IResource.class);
314             }
315             if (resource != null) {
316                 switch (resource.getType()) {
317                 case IResource.FILE:
318                     return resource.getParent();
319                 case IResource.FOLDER:
320                 case IResource.PROJECT:
321                 case IResource.ROOT:
322                     return (IContainer) resource;
323                 default:
324                     // Unknown resource type. Fall through.
325                     break;
326                 }
327             }
328         }
329         return ResourcesPlugin.getWorkspace().getRoot();
330     }
331 
332     /***
333      * Sets up the context menu for this view during initialization.
334      */
335     private void hookContextMenu() {
336         MenuManager menuMgr = new MenuManager("#PopupMenu");
337         menuMgr.setRemoveAllWhenShown(true);
338         menuMgr.addMenuListener(new IMenuListener() {
339             public void menuAboutToShow(final IMenuManager manager) {
340                 MosaiqueView.this.fillContextMenu(manager);
341             }
342         });
343         Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
344         treeViewer.getControl().setMenu(menu);
345         getSite().registerContextMenu(menuMgr, treeViewer);
346     }
347 
348     /***
349      * Contributes actions to the action bar of this view during initialization.
350      */
351     private void contributeToActionBars() {
352         IActionBars bars = getViewSite().getActionBars();
353         fillLocalPullDown(bars.getMenuManager());
354         fillLocalToolBar(bars.getToolBarManager());
355     }
356 
357     /***
358      * @param manager The menu manager to add pull down menu actions to.
359      */
360     private void fillLocalPullDown(final IMenuManager manager) {
361         manager.add(refreshAction);
362     }
363 
364     /***
365      * @param manager The menu manager to add context menu actions to.
366      */
367     private void fillContextMenu(final IMenuManager manager) {
368         manager.add(refreshAction);
369         manager.add(collapseAllAction);
370         // Other plug-ins can contribute there actions here
371         manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
372 
373         drillDownAdapter.addNavigationActions(manager);
374     }
375 
376     /***
377      * @param manager  The menu manager to tool bar menu actions to.
378      */
379     private void fillLocalToolBar(final IToolBarManager manager) {
380         manager.add(refreshAction);
381         drillDownAdapter.addNavigationActions(manager);
382     }
383 
384     /***
385      * Creates the actions for the view.
386      */
387     private void makeActions() {
388         refreshAction = new Action() {
389             public void run() {
390                 treeViewer.getControl().setRedraw(false);
391                 viewContentProvider.refresh();
392                 List elementPaths = treeViewer.getExpandedElementPaths();
393                 treeViewer.refresh();
394                 treeViewer.setExpandedElementPaths(elementPaths);
395                 treeViewer.getControl().setRedraw(true);
396             }
397         };
398         refreshAction.setText("Refresh");
399         refreshAction.setToolTipText("Refreshes the Mosaique view");
400         refreshAction.setImageDescriptor(MosaiquePlugin
401                 .getImageDescriptor("icons/" + "refresh.gif"));
402 
403         collapseAllAction = new Action() {
404             public void run() {
405                 IStructuredSelection selection =
406                     (IStructuredSelection) treeViewer.getSelection();
407                 for (Iterator iter = selection.iterator(); iter.hasNext();) {
408                     Object element = iter.next();
409                     treeViewer.collapseToLevel(
410                             element, AbstractTreeViewer.ALL_LEVELS);
411                 }
412             }
413         };
414         collapseAllAction.setText("Collapse all");
415         collapseAllAction.setToolTipText(
416                 "Collapses the selected node and all its sub nodes");
417     }
418 
419 //    private void showMessage(String message) {
420 //        MessageDialog.openInformation(viewer.getControl().getShell(),
421 //                "Mosaique", message);
422 //    }
423 }