001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package net.refractions.udig.project.ui;
018:
019: import java.io.IOException;
020: import java.net.URL;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.List;
025:
026: import net.refractions.udig.catalog.IGeoResource;
027: import net.refractions.udig.internal.ui.UiPlugin;
028: import net.refractions.udig.project.ILayer;
029: import net.refractions.udig.project.IMap;
030: import net.refractions.udig.project.IProject;
031: import net.refractions.udig.project.IProjectElement;
032: import net.refractions.udig.project.internal.Project;
033: import net.refractions.udig.project.internal.ProjectElement;
034: import net.refractions.udig.project.internal.ProjectPlugin;
035: import net.refractions.udig.project.internal.commands.AddLayersCommand;
036: import net.refractions.udig.project.internal.commands.CreateMapCommand;
037: import net.refractions.udig.project.internal.impl.ProjectRegistryImpl;
038: import net.refractions.udig.project.ui.commands.OpenProjectElementCommand;
039: import net.refractions.udig.project.ui.internal.ApplicationGISInternal;
040: import net.refractions.udig.project.ui.internal.MapEditor;
041: import net.refractions.udig.project.ui.internal.Messages;
042: import net.refractions.udig.project.ui.internal.ProjectUIPlugin;
043: import net.refractions.udig.project.ui.internal.UDIGEditorInputDescriptor;
044: import net.refractions.udig.project.ui.internal.tool.ToolContext;
045: import net.refractions.udig.project.ui.internal.tool.display.ToolManager;
046: import net.refractions.udig.project.ui.internal.tool.impl.ToolContextImpl;
047: import net.refractions.udig.project.ui.tool.IToolContext;
048: import net.refractions.udig.project.ui.tool.IToolManager;
049: import net.refractions.udig.ui.PlatformGIS;
050:
051: import org.eclipse.core.runtime.CoreException;
052: import org.eclipse.core.runtime.IConfigurationElement;
053: import org.eclipse.core.runtime.IExtension;
054: import org.eclipse.core.runtime.IExtensionPoint;
055: import org.eclipse.core.runtime.IExtensionRegistry;
056: import org.eclipse.core.runtime.ISafeRunnable;
057: import org.eclipse.core.runtime.Platform;
058: import org.eclipse.emf.common.util.URI;
059: import org.eclipse.emf.ecore.resource.Resource;
060: import org.eclipse.swt.widgets.Display;
061: import org.eclipse.ui.IEditorPart;
062: import org.eclipse.ui.IEditorReference;
063: import org.eclipse.ui.IViewPart;
064: import org.eclipse.ui.IViewReference;
065: import org.eclipse.ui.IWorkbenchPage;
066: import org.eclipse.ui.IWorkbenchWindow;
067: import org.eclipse.ui.PartInitException;
068: import org.eclipse.ui.PlatformUI;
069:
070: /**
071: * A facade into udig to simplify operations such as getting the active map and openning a map
072: * editor.
073: *
074: * @author jeichar
075: * @since 0.9.0
076: */
077: public class ApplicationGIS {
078:
079: private static java.util.Map<Class, List<UDIGEditorInputDescriptor>> editorInputDescriptors = new HashMap<Class, List<UDIGEditorInputDescriptor>>();
080: private static IToolManager toolManager;
081:
082: /**
083: * Obtains the current project.
084: *
085: * @return The current active project
086: */
087: public static IProject getActiveProject() {
088: Project project = ProjectPlugin.getPlugin()
089: .getProjectRegistry().getCurrentProject();
090:
091: if (project != null)
092: return project;
093:
094: return ProjectPlugin.getPlugin().getProjectRegistry()
095: .getDefaultProject();
096: }
097:
098: /**
099: * Return all Projects. The list is unmodifiable.
100: *
101: * @return all Projects.
102: */
103: public static List<? extends IProject> getProjects() {
104: return Collections.unmodifiableList(ProjectPlugin.getPlugin()
105: .getProjectRegistry().getProjects());
106: }
107:
108: /**
109: * May return null if the active editor is not a Map Editor.
110: *
111: * @return the map contained by the current MapEditor or null if the active editor is not a map
112: * editor.
113: */
114: public static IMap getActiveMap() {
115: try {
116: final IEditorPart[] editor = new IEditorPart[1];
117: if (Display.getCurrent() != null) {
118: // method being called from ui thread, go ahead
119: try {
120: editor[0] = PlatformUI.getWorkbench()
121: .getActiveWorkbenchWindow().getActivePage()
122: .getActiveEditor();
123: } catch (Throwable t) {
124: // do nothing
125: }
126: } else {
127: // need to be in ui thread
128: PlatformGIS.syncInDisplayThread(new Runnable() {
129: public void run() {
130: try {
131: editor[0] = PlatformUI.getWorkbench()
132: .getActiveWorkbenchWindow()
133: .getActivePage().getActiveEditor();
134: } catch (Throwable t) {
135: // do nothing
136: }
137: }
138: });
139: }
140:
141: if (editor[0] instanceof MapEditor) {
142: return ((MapEditor) editor[0]).getMap();
143: }
144: } catch (Exception e) {
145: return null;
146: }
147:
148: return null;
149: }
150:
151: /**
152: * Returns all open maps. May return null if no Map Editors exist.
153: *
154: * @return a list of maps contained.
155: */
156: public static List<? extends IMap> getOpenMaps() {
157: try {
158:
159: // For some reason, getting the active workbench doesn't seem to work??!! So looping
160: // through all the workbenches and all their pages was the slow way to go...
161: // IEditorReference[] editors =
162: // PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
163: IWorkbenchWindow[] wWindows = PlatformUI.getWorkbench()
164: .getWorkbenchWindows();
165:
166: List<IMap> maps = new ArrayList<IMap>();
167: for (IWorkbenchWindow wWindow : wWindows) {
168: IWorkbenchPage[] wPages = wWindow.getPages();
169: for (IWorkbenchPage wPage : wPages) {
170: IEditorReference[] editors = wPage
171: .getEditorReferences();
172: for (IEditorReference editor : editors) {
173: IEditorPart editor2 = editor.getEditor(false);
174: if (editor2 instanceof MapEditor) {
175: maps.add(((MapEditor) editor2).getMap());
176: }
177: }
178: }
179: }
180: if (maps.size() == 0)
181: return maps;
182: return maps;
183: } catch (NullPointerException e) {
184: return null;
185: }
186: }
187:
188: /**
189: * Opens a Map editor for the provided map, This is a non-blocking call. Equivalent to
190: * openMap(map, false);
191: *
192: * @param map the map to open. Must be an instance of Map.
193: */
194: public static void openMap(IMap map) {
195: openMap(map, false);
196: }
197:
198: /**
199: * Opens a Map editor for the provided map.
200: *
201: * @param map the map to open. Must be an instance of Map.
202: * @param wait indicates whether to wait for the map to open before returning.
203: */
204: public static void openMap(IMap map, boolean wait) {
205: openProjectElement(map, wait);
206: }
207:
208: /**
209: * creates a map and opens an editor for the map.
210: *
211: * @param a list of IGeoResources. Each resource will be a layer in the created map.
212: */
213: public static void createAndOpenMap(List<IGeoResource> resources) {
214: CreateMapCommand command = new CreateMapCommand(null,
215: resources, null);
216: getActiveProject().sendSync(command);
217: openMap(command.getCreatedMap());
218: }
219:
220: /**
221: * creates a map and opens an editor for the map.
222: *
223: * @param a list of IGeoResources. Each resource will be a layer in the created map.
224: * @param owner the project that will contain the map. owner must be an instance of Project. If
225: * it is obtained using the framework then this will always be the case.
226: */
227: public static void createAndOpenMap(List<IGeoResource> resources,
228: IProject owner) {
229: CreateMapCommand command = new CreateMapCommand(null,
230: resources, owner);
231: getActiveProject().sendSync(command);
232: openMap(command.getCreatedMap());
233: }
234:
235: /**
236: * creates a map and opens an editor for the map.
237: *
238: * @param a list of IGeoResources. Each resource will be a layer in the created map.
239: * @param owner the project that will contain the map. owner must be an instance of Project. If
240: * it is obtained using the framework then this will always be the case.
241: * @param wait indicates whether to wait for the map to open before returning.
242: */
243: public static void createAndOpenMap(List<IGeoResource> resources,
244: IProject owner, boolean wait) {
245: CreateMapCommand command = new CreateMapCommand(null,
246: resources, owner);
247: getActiveProject().sendSync(command);
248: openMap(command.getCreatedMap(), wait);
249: }
250:
251: /**
252: * Gets a reference to a view. If the view has not been opened previously then the view will be
253: * opened.
254: *
255: * @param show whether to show the view or not.
256: * @param id the id of the view to show.
257: * @return returns the view or null if the view does not exist
258: */
259: public static IViewPart getView(boolean show, String id) {
260: IWorkbenchPage page = PlatformUI.getWorkbench()
261: .getActiveWorkbenchWindow().getActivePage();
262: IViewReference[] view = page.getViewReferences();
263: IViewReference infoRef = null;
264: for (IViewReference reference : view) {
265: if (reference.getId().equals(id)) {
266: infoRef = reference;
267: break;
268: }
269: }
270: // JONES: need to get the part and set the selection to null so that the last selected
271: // feature will not flash (because it will not be in list any more).
272: IViewPart infoView = null;
273: if (infoRef == null) {
274: try {
275: infoView = page.showView(id);
276: } catch (PartInitException e1) {
277: return null;
278: }
279: if (infoView == null) {
280: return null;
281: }
282: }
283: if (infoRef != null)
284: return (IViewPart) infoRef.getPart(show);
285:
286: return null;
287:
288: }
289:
290: /**
291: * Runs the given runnable in a protected mode. Exceptions thrown in the runnable are logged and
292: * passed to the runnable's exception handler. Such exceptions are not rethrown by this method.
293: */
294: public static void run(ISafeRunnable request) {
295: PlatformGIS.run(request);
296: }
297:
298: /**
299: * Returns an editor input for the type passed in. Processes the editorInputs extension point.
300: *
301: * @param type
302: * @return an editor input for the type passed in.
303: */
304: public static List<UDIGEditorInputDescriptor> getEditorInputs(
305: final Class<? extends IProjectElement> type) {
306: if (!editorInputDescriptors.containsKey(type)) {
307: synchronized (editorInputDescriptors) {
308: if (editorInputDescriptors.containsKey(type))
309: return editorInputDescriptors.get(type);
310:
311: final List<UDIGEditorInputDescriptor> newInputs = new ArrayList<UDIGEditorInputDescriptor>();
312:
313: IExtensionRegistry registry = Platform
314: .getExtensionRegistry();
315: IExtensionPoint extensionPoint = registry
316: .getExtensionPoint("net.refractions.udig.project.ui.editorInputs"); //$NON-NLS-1$
317: IExtension[] extensions = extensionPoint
318: .getExtensions();
319:
320: for (int i = 0; i < extensions.length; i++) {
321: IConfigurationElement[] elements = extensions[i]
322: .getConfigurationElements();
323:
324: for (int j = 0; j < elements.length; j++) {
325: try {
326: Object object = elements[j]
327: .createExecutableExtension("projectElement"); //$NON-NLS-1$
328: if (object.getClass()
329: .isAssignableFrom(type)) {
330: UDIGEditorInputDescriptor input = new UDIGEditorInputDescriptor();
331: input.setEditorID(elements[j]
332: .getAttribute("editorPartID")); //$NON-NLS-1$
333: input.setName(elements[j]
334: .getAttribute("name")); //$NON-NLS-1$
335: input.setExtensionElement(elements[j]);
336: input.setType(type);
337: newInputs.add(input);
338: }
339: } catch (CoreException e) {
340: e.printStackTrace();
341: }
342: }
343: }
344:
345: editorInputDescriptors.put(type, newInputs);
346: }
347: }
348:
349: return editorInputDescriptors.get(type);
350: }
351:
352: /**
353: * Returns the ToolManager singleton.
354: *
355: * @return the ToolManager singleton.
356: */
357: public static IToolManager getToolManager() {
358: synchronized (ToolManager.class) {
359: if (toolManager == null) {
360:
361: String prefConstant = IToolManager.P_TOOL_MANAGER;
362: String xpid = IToolManager.XPID;
363: String idField = IToolManager.ATTR_ID;
364: String classField = IToolManager.ATTR_CLASS;
365:
366: IToolManager result = (IToolManager) UiPlugin
367: .lookupConfigurationObject(IToolManager.class,
368: ProjectUIPlugin.getDefault()
369: .getPreferenceStore(),
370: ProjectUIPlugin.ID, prefConstant, xpid,
371: idField, classField);
372: if (result != null) {
373: toolManager = result;
374: } else {
375: toolManager = new ToolManager();
376: }
377: }
378: }
379: return toolManager;
380: }
381:
382: /**
383: * Returns the IEditorInput instance that wraps the element argument.
384: *
385: * @return the IEditorInput instance that wraps the element argument.
386: */
387: public static UDIGEditorInput getInput(IProjectElement element) {
388: List<UDIGEditorInputDescriptor> descriptors = getEditorInputs(element
389: .getClass());
390: for (UDIGEditorInputDescriptor descriptor : descriptors) {
391: UDIGEditorInput input = descriptor.createInput(element);
392: if (input != null) {
393: return input;
394: }
395: }
396: return null;
397: }
398:
399: /**
400: * Creates a Tools Context out of Map.
401: *
402: * @param map that the context interacts with
403: * @return a ToolContext
404: * @see ToolContext
405: */
406: public static IToolContext createContext(IMap map) {
407: if (map instanceof net.refractions.udig.project.internal.Map) {
408: ToolContext context = new ToolContextImpl();
409: context
410: .setMapInternal((net.refractions.udig.project.internal.Map) map);
411: return context;
412: }
413: return null;
414: }
415:
416: /**
417: * Make layers from the resourceList and adds the layers to the map.
418: * <p>
419: * <b>NOTE</b> map may be null. If it is then the current open map will be used (see
420: * {@link #getActiveMap()} or a new map will be created if that is null.
421: * </p>
422: *
423: * @param map the map to add the layers to. If null the current active map will be used or a new
424: * one will be created
425: * @param resourceList Resources to add to the map.
426: * @param startPosition z-position of the layers to add. if -1 it will be added to the top of the
427: * map (0 is the bottom of the map and map.getMapLayer.size() is the top of the map).
428: * @return layers that were added.
429: */
430: public static List<? extends ILayer> addLayersToMap(IMap map,
431: List<IGeoResource> resourceList, int startPosition) {
432: return addLayersToMap(map, resourceList, startPosition, null,
433: false);
434: }
435:
436: /**
437: * Make layers from the resourceList, creates a new map, adds layers to map and adds map to the
438: * project.
439: *
440: * @param project project that new map should be added to
441: * @param resourceList Resources to add to the map.
442: * @param startPosition z-position of the layers to add. if -1 it will be added to the top of the
443: * map (0 is the bottom of the map and map.getMapLayer.size() is the top of the map).
444: *
445: * @return layers that were added.
446: */
447: public static List<? extends ILayer> addLayersToMap(
448: IProject project, List<IGeoResource> resourceList) {
449: return addLayersToMap(null, resourceList, 0, project, false);
450: }
451:
452: /**
453: * Make layers from the resourceList and adds the layers to the map.
454: * <p>
455: * <b>NOTE</b> map may be null. If it is then the current open map will be used (see
456: * {@link #getActiveMap()} or a new map will be created if that is null.
457: * </p>
458: *
459: * @param map the map to add the layers to. If null the current active map will be used or a new
460: * one will be created
461: * @param resourceList Resources to add to the map.
462: * @param startPosition z-position of the layers to add. if -1 it will be added to the top of the
463: * map (0 is the bottom of the map and map.getMapLayer.size() is the top of the map).
464: * @param project project that map should be added to... Only used if there is no current map.
465: * If project is then the default project is used.
466: * @return layers that were added.
467: * @deprecated
468: */
469: public static List<? extends ILayer> addLayersToMap(IMap map,
470: List<IGeoResource> resourceList, int startPosition,
471: Project project) {
472: return addLayersToMap(map, resourceList, startPosition,
473: project, false);
474: }
475:
476: /**
477: * Make layers from the resourceList and adds the layers to the map.
478: * <p>
479: * <b>NOTE</b> map may be null. If it is then the current open map will be used (see
480: * {@link #getActiveMap()} or a new map will be created if that is null.
481: * </p>
482: *
483: * @param map the map to add the layers to. If null the current active map will be used or a new
484: * one will be created
485: * @param resourceList Resources to add to the map.
486: * @param startPosition z-position of the layers to add. if -1 it will be added to the top of the
487: * map (0 is the bottom of the map and map.getMapLayer.size() is the top of the map).
488: * @param project project that map should be added to... Only used if there is no current map.
489: * If project is then the default project is used.
490: * @param wait if true then method will block until map has been opened otherwise will return without blocking.
491: */
492: public static List<? extends ILayer> addLayersToMap(IMap map2,
493: List<IGeoResource> resourceList, int startPosition2,
494: IProject project2, boolean wait) {
495: IMap map = map2;
496: if (map == null && project2 == null)
497: map = (IMap) getActiveMap();
498: IProject project = project2;
499: if (project == null) {
500: if (map == null)
501: project = ProjectPlugin.getPlugin()
502: .getProjectRegistry().getCurrentProject();
503: else
504: project = map.getProject();
505: }
506:
507: List<? extends ILayer> layers;
508: if (map == null) {
509: CreateMapCommand cmCommand = new CreateMapCommand(null,
510: resourceList, project);
511: project.sendSync(cmCommand);
512: map = cmCommand.getCreatedMap();
513: layers = map.getMapLayers();
514: } else {
515: AddLayersCommand alCommand = new AddLayersCommand(
516: resourceList, startPosition2);
517: map.sendCommandSync(alCommand);
518: layers = alCommand.getLayers();
519: }
520:
521: if (!ApplicationGISInternal.getOpenMaps().contains(map)) {
522: openMap(map, wait);
523: }
524: return layers;
525: }
526:
527: /**
528: * Loads the project element indicated by the url and adds the map to the provided project.
529: *
530: * @param url the project element to load
531: * @param project the project to add the project element to.
532: * @return returns the loaded project element.
533: * @throws IOException thrown if there is a problem reading the project element file
534: * @throws IllegalArgumentException thrown if the file indicated by the URL is not a project
535: * element file.
536: */
537: public static IProjectElement loadProjectElement(URL url,
538: IProject project) throws IOException,
539: IllegalArgumentException {
540: URI uri = URI.createURI(url.toString());
541:
542: Resource mapResource;
543: try {
544: mapResource = ProjectRegistryImpl.getProjectRegistry()
545: .eResource().getResourceSet()
546: .getResource(uri, true);
547: } catch (Exception e) {
548: throw new IOException(Messages.ApplicationGIS_loadError
549: + uri);
550: }
551:
552: Object obj;
553: try {
554: obj = mapResource.getContents().get(0);
555: } catch (Exception e) {
556: throw new IllegalArgumentException(
557: Messages.ApplicationGIS_illegalArgumentPart1
558: + uri
559: + Messages.ApplicationGIS_illegalArgumentPart2);
560: }
561: if (!(obj instanceof ProjectElement))
562: throw new IllegalArgumentException(
563: Messages.ApplicationGIS_noProjectElement
564: + obj.getClass().getSimpleName());
565:
566: ProjectElement elem = (ProjectElement) obj;
567: ((Project) project).getElementsInternal().add(elem);
568:
569: return elem;
570: }
571:
572: /**
573: * Opens a {@link IProjectElement} for editing/viewing.
574: *
575: * @param obj object to open
576: * @param wait whether or not to perform the action asynchronously
577: */
578: public static void openProjectElement(IProjectElement obj,
579: boolean wait) {
580: OpenProjectElementCommand command = new OpenProjectElementCommand(
581: obj);
582: if (wait)
583: ApplicationGIS.getActiveProject().sendSync(command);
584: else
585: ApplicationGIS.getActiveProject().sendASync(command);
586: }
587: }
|