Java tutorial
/* * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004, * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the Free Software * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ package net.refractions.udig.project.ui.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.refractions.udig.core.internal.ExtensionPointList; import net.refractions.udig.internal.ui.UiPlugin; import net.refractions.udig.project.internal.EditManager; import net.refractions.udig.project.internal.ProjectPackage; import net.refractions.udig.project.internal.ProjectPlugin; import net.refractions.udig.project.preferences.PreferenceConstants; import net.refractions.udig.project.ui.IUDIGDialogPage; import net.refractions.udig.project.ui.IUDIGView; import net.refractions.udig.project.ui.internal.tool.ToolContext; import net.refractions.udig.project.ui.internal.tool.impl.ToolContextImpl; import net.refractions.udig.ui.PlatformGIS; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.AdapterImpl; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.preferences.ScopedPreferenceStore; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; /** * Processes the feature editor extension points and creates the menu items. * * @author jeichar * @since 0.9.0 */ public class FeatureEditorExtensionProcessor { FeatureEditorViewpartListener partListener; Map<SimpleFeatureType, EditActionContribution> selectedEditors = new HashMap<SimpleFeatureType, EditActionContribution>(); List<FeatureEditorLoader> editorLoaders = new ArrayList<FeatureEditorLoader>(); static final String CURRENT_LOADER_ID = "FeatureEditorCurrentLoader"; //$NON-NLS-1$ private static final String FEATURE_EDITOR_ID = "net.refractions.udig.project.ui.featureEditor"; //$NON-NLS-1$ private boolean running; /** * Construct <code>FeatureEditorExtensionProcessor</code>. */ public FeatureEditorExtensionProcessor() { List<IConfigurationElement> list = ExtensionPointList.getExtensionPointList(FEATURE_EDITOR_ID); for (IConfigurationElement element : list) { FeatureEditorLoader loader = new FeatureEditorLoader(this, element); ScopedPreferenceStore preferences = ProjectPlugin.getPlugin().getPreferenceStore(); if (loader.id.equals(preferences.getString(PreferenceConstants.P_DEFAULT_FEATURE_EDITOR))) editorLoaders.add(0, loader); else editorLoaders.add(loader); } } /** * Creates the edit feature action * * @return the edit feature action */ public IContributionItem getEditFeatureAction(final ISelection selection) { if (selection.isEmpty()) return new GroupMarker("editAction"); //$NON-NLS-1$ if (!(selection instanceof IStructuredSelection)) return new GroupMarker("editAction"); //$NON-NLS-1$ IStructuredSelection structuredSelection = (IStructuredSelection) selection; if (!sameFeatureTypes(structuredSelection)) return new GroupMarker("editAction"); //$NON-NLS-1$ SimpleFeature feature = (SimpleFeature) structuredSelection.getFirstElement(); IContributionItem item = selectedEditors.get(feature.getFeatureType()); if (item != null) return item; FeatureEditorLoader loader = getClosestMatch(selection); if (loader != null) return createEditAction(loader, selection, feature); return new GroupMarker("editAction"); //$NON-NLS-1$ } /** * returns the feature editor that is customized closest for the feature(s) in the selection * * @param selection a selection that contains 1 or more features. * @return the feature editor that is customized closest for the feature(s) in the selection. */ public FeatureEditorLoader getClosestMatch(ISelection selection) { int bestValue = Integer.MAX_VALUE; FeatureEditorLoader best = null; for (FeatureEditorLoader loader : editorLoaders) { int value = loader.match(selection); if (value == -1) continue; if (value == 0) return loader; if (value < bestValue) { bestValue = value; best = loader; } } return best; } /** * Creates the edit menu item. * * @param loader * @param selection * @param feature * @return */ EditActionContribution createEditAction(final FeatureEditorLoader loader, final ISelection selection, SimpleFeature feature) { EditActionContribution item; item = new EditActionContribution(new EditAction(loader, selection)); selectedEditors.put(feature.getFeatureType(), item); return item; } static class EditAction extends Action { private ISelection selection; private final FeatureEditorLoader loader; public EditAction(FeatureEditorLoader loader, ISelection selection) { super(Messages.FeatureEditorExtensionProcessor_editMenu, loader.icon); this.selection = selection; this.loader = loader; setId(loader.id); } @Override public void runWithEvent(Event event) { loader.open(event.display, selection); } public void setSelection(ISelection selection) { this.selection = selection; } } static class EditActionContribution extends ActionContributionItem { private EditAction editAction; public EditActionContribution(IAction action) { super(action); editAction = (EditAction) action; } public void setSelection(ISelection selection) { editAction.setSelection(selection); } } boolean sameFeatureTypes(IStructuredSelection structuredSelection) { SimpleFeatureType type = null; for (Iterator iter = structuredSelection.iterator(); iter.hasNext();) { Object obj = iter.next(); if (!(obj instanceof SimpleFeature)) return false; SimpleFeature feature = (SimpleFeature) obj; if (type == null) type = feature.getFeatureType(); else if (!type.equals(feature.getFeatureType())) return false; } return true; } /** * Creates the edit/editWith menu items if the current selection is a feature. * * @return the edit/editWith menu items if the current selection is a feature. */ public IContributionItem getEditWithFeatureMenu(ISelection selection) { if (selection.isEmpty()) return new GroupMarker("editWithMenu"); //$NON-NLS-1$ MenuManager editWithMenu = new MenuManager(Messages.FeatureEditorExtensionProcessor_editWithMenu); for (FeatureEditorLoader loader : editorLoaders) { IAction editorAction = loader.getAction(selection); if (editorAction != null) editWithMenu.add(editorAction); } editWithMenu.setVisible(true); if (editWithMenu.getItems().length == 0) return new GroupMarker("editWithMenu"); //$NON-NLS-1$ return editWithMenu; } /** * Creates and registers the Workbench part listener with the workbench window. */ public void startPartListener() { if (partListener == null) { partListener = new FeatureEditorViewpartListener(); } try { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().addPartListener(partListener); running = true; } catch (Exception e) { ProjectUIPlugin.log(null, e); } } /** * De-registers the Workbench part listener with the workbench window. */ public void stopPartListener() { try { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().addPartListener(partListener); } catch (Exception e) { // do nothing } running = false; } static class FeatureEditorViewpartListener extends AdapterImpl implements IPartListener2 { ToolContext currentContext; private List<IUDIGView> views = new ArrayList<IUDIGView>(); FeatureEditorViewpartListener() { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewReference[] refs = page.getViewReferences(); for (IViewReference reference : refs) { IWorkbenchPart part = reference.getPart(false); if (page.isPartVisible(part) && part instanceof IUDIGView) views.add((IUDIGView) part); } } /** * @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference) */ public void partActivated(IWorkbenchPartReference partRef) { partVisible(partRef); } /** * @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference) */ public void partBroughtToTop(IWorkbenchPartReference partRef) { partVisible(partRef); } /** * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference) */ public void partClosed(IWorkbenchPartReference partRef) { if (partRef.getPart(false) instanceof IUDIGView) { views.remove(partRef.getPart(false)); } else if (partRef.getPart(false) instanceof MapPart) { MapPart editor = (MapPart) partRef.getPart(false); synchronized (this) { if (currentContext == null || currentContext.getMapInternal() != editor.getMap()) return; currentContext.getEditManagerInternal().eAdapters().remove(this); currentContext = null; } for (IUDIGView view : views) { view.setContext(null); } } } /** * @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference) */ public void partDeactivated(IWorkbenchPartReference partRef) { // do nothing } /** * @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference) */ public synchronized void partOpened(IWorkbenchPartReference partRef) { partVisible(partRef); } /** * @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference) */ public void partHidden(IWorkbenchPartReference partRef) { // do nothing } /** * @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference) */ @SuppressWarnings("unchecked") public void partVisible(IWorkbenchPartReference partRef) { if (partRef.getPart(false) instanceof IUDIGView) { IUDIGView udigview = (IUDIGView) partRef.getPart(false); if (!views.contains(udigview)) views.add(udigview); SimpleFeature editFeature; ToolContext copy; synchronized (this) { if (!validateContext(currentContext)) return; copy = currentContext.copy(); editFeature = currentContext.getEditManager().getEditFeature(); } try { udigview.setContext(copy); if (editFeature != null) udigview.editFeatureChanged(editFeature); } catch (Throwable e) { UiPlugin.log(udigview + " threw an exception", e); //$NON-NLS-1$ } } else if (partRef.getPart(false) instanceof MapPart) { MapPart editor = (MapPart) partRef.getPart(false); synchronized (this) { if (currentContext != null && currentContext.getMapInternal() == editor.getMap()) return; if (currentContext != null) currentContext.getEditManagerInternal().eAdapters().remove(this); currentContext = new ToolContextImpl(); currentContext.setMapInternal(editor.getMap()); currentContext.setRenderManagerInternal(editor.getMap().getRenderManagerInternal()); currentContext.getEditManagerInternal().eAdapters().add(this); for (IUDIGView view : views) { try { view.setContext(currentContext); } catch (Throwable e) { UiPlugin.log(view + " threw an exception", e); //$NON-NLS-1$ } } } } } private boolean validateContext(ToolContext currentContext2) { if (currentContext2 == null) return false; if (currentContext2.getMap() == null) return false; if (currentContext2.getViewportModel() == null) return false; if (currentContext2.getRenderManager() == null) return false; if (currentContext2.getDisplay() == null) return false; if (currentContext2.getEditManager() == null) return false; return true; } /** * @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference) */ public void partInputChanged(IWorkbenchPartReference partRef) { // do nothing } /** * @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification) */ public void notifyChanged(final Notification msg) { if (msg.getNotifier() instanceof EditManager) { if (msg.getFeatureID(EditManager.class) == ProjectPackage.EDIT_MANAGER__EDIT_FEATURE) { PlatformGIS.syncInDisplayThread(new Runnable() { public void run() { updateEditFeatureViews(msg); } }); } } } private void updateEditFeatureViews(Notification msg) { SimpleFeature newFeature = (SimpleFeature) msg.getNewValue(); for (IUDIGView view : views) { try { view.editFeatureChanged(newFeature); } catch (Throwable e) { UiPlugin.log(view + " threw an exception", e); //$NON-NLS-1$ } } } } static class EditorDialog extends Dialog { private IUDIGDialogPage page; /** * Construct <code>EditorDialog</code>. * * @param parentShell */ protected EditorDialog(Shell parentShell, IUDIGDialogPage page) { super(parentShell); this.page = page; } /** * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); page.createControl(composite); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); composite.setLayoutData(data); page.getControl().setLayoutData(data); return composite; } } /** * Indicates whether the listener has been added to the workbench * * @return */ public boolean isRunning() { return running; } public FeatureEditorLoader[] getEditorLoaders() { return editorLoaders.toArray(new FeatureEditorLoader[0]); } }