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
109
110
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;
124 } else {
125 result = Math.max(0, put.getLevel());
126 }
127 }
128 return result;
129 }
130 });
131 treeViewer.addFilter(new ViewerFilter() {
132
133
134
135
136
137
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
175
176
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
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
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
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
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
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
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
420
421
422
423 }