001: /* uDig - User Friendly Desktop Internet GIS client
002: * http://udig.refractions.net
003: * (C) 2004, Refractions Research Inc.
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation;
008: * version 2.1 of the License.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: */
015: package net.refractions.udig.tools.edit;
016:
017: import java.awt.geom.AffineTransform;
018: import java.io.IOException;
019: import java.text.MessageFormat;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.concurrent.TimeUnit;
027: import java.util.concurrent.locks.Condition;
028: import java.util.concurrent.locks.Lock;
029: import java.util.concurrent.locks.ReentrantLock;
030:
031: import net.refractions.udig.project.ILayer;
032: import net.refractions.udig.project.ILayerListener;
033: import net.refractions.udig.project.IMap;
034: import net.refractions.udig.project.LayerEvent;
035: import net.refractions.udig.project.command.UndoableComposite;
036: import net.refractions.udig.project.command.UndoableMapCommand;
037: import net.refractions.udig.project.internal.EditManager;
038: import net.refractions.udig.project.internal.Layer;
039: import net.refractions.udig.project.internal.impl.EditManagerImpl;
040: import net.refractions.udig.project.internal.render.RenderPackage;
041: import net.refractions.udig.project.internal.render.ViewportModel;
042: import net.refractions.udig.project.render.displayAdapter.IMapDisplayListener;
043: import net.refractions.udig.project.render.displayAdapter.MapDisplayEvent;
044: import net.refractions.udig.project.ui.ApplicationGIS;
045: import net.refractions.udig.project.ui.tool.IToolContext;
046: import net.refractions.udig.project.ui.tool.Tool;
047: import net.refractions.udig.tool.edit.internal.Messages;
048: import net.refractions.udig.tools.edit.support.EditBlackboard;
049: import net.refractions.udig.tools.edit.support.EditGeom;
050: import net.refractions.udig.tools.edit.support.PrimitiveShape;
051: import net.refractions.udig.ui.PlatformGIS;
052:
053: import org.eclipse.core.commands.AbstractHandler;
054: import org.eclipse.core.commands.Command;
055: import org.eclipse.core.commands.CommandEvent;
056: import org.eclipse.core.commands.ExecutionEvent;
057: import org.eclipse.core.commands.ExecutionException;
058: import org.eclipse.core.commands.ICommandListener;
059: import org.eclipse.core.commands.IHandler;
060: import org.eclipse.core.runtime.IProgressMonitor;
061: import org.eclipse.core.runtime.NullProgressMonitor;
062: import org.eclipse.emf.common.notify.Notification;
063: import org.eclipse.emf.common.notify.impl.AdapterImpl;
064: import org.eclipse.jface.dialogs.Dialog;
065: import org.eclipse.jface.dialogs.MessageDialog;
066: import org.eclipse.jface.dialogs.ProgressMonitorDialog;
067: import org.eclipse.jface.operation.IRunnableWithProgress;
068: import org.eclipse.swt.SWT;
069: import org.eclipse.swt.layout.GridData;
070: import org.eclipse.swt.layout.GridLayout;
071: import org.eclipse.swt.widgets.Composite;
072: import org.eclipse.swt.widgets.Control;
073: import org.eclipse.swt.widgets.Display;
074: import org.eclipse.swt.widgets.Label;
075: import org.eclipse.swt.widgets.Text;
076: import org.eclipse.ui.PlatformUI;
077: import org.eclipse.ui.commands.ICommandService;
078: import org.geotools.data.FeatureEvent;
079: import org.geotools.data.FeatureSource;
080: import org.geotools.data.FeatureStore;
081: import org.geotools.feature.Feature;
082: import org.geotools.feature.FeatureCollection;
083: import org.geotools.feature.FeatureIterator;
084: import org.geotools.filter.FidFilter;
085: import org.geotools.filter.Filter;
086: import org.geotools.filter.FilterFactory;
087: import org.geotools.filter.FilterFactoryFinder;
088: import org.geotools.referencing.CRS;
089: import org.geotools.referencing.crs.DefaultGeographicCRS;
090: import org.opengis.referencing.FactoryException;
091: import org.opengis.referencing.operation.MathTransform;
092:
093: import com.vividsolutions.jts.geom.Envelope;
094: import com.vividsolutions.jts.geom.Geometry;
095:
096: /**
097: * To delete soon EditManager will have an editblackboard.
098: *
099: * @author jones
100: * @since 1.1.0
101: */
102: public class EditBlackboardUtil {
103: private static final MathTransform IDENTITY;
104: static {
105: MathTransform tmp = null;
106: try {
107: tmp = CRS.findMathTransform(DefaultGeographicCRS.WGS84,
108: DefaultGeographicCRS.WGS84);
109: } catch (FactoryException e) {
110: // can't happen
111: }
112:
113: IDENTITY = tmp;
114: }
115:
116: private volatile static ViewportModelListener listener;
117:
118: public static final EditBlackboard EMPTY_BLACKBOARD = new EditBlackboard(
119: 0, 0, AffineTransform.getTranslateInstance(0, 0), IDENTITY);
120:
121: public static final String EDIT_BLACKBOARD_KEY = "EDIT_BLACKBOARD_KEY_839834"; //$NON-NLS-1$
122:
123: private static Lock blackboardLock = new ReentrantLock();
124:
125: public static EditBlackboard getEditBlackboard(
126: IToolContext context, ILayer layer2) {
127: if (layer2 == null
128: || !ApplicationGIS.getOpenMaps().contains(
129: layer2.getMap()))
130: return EMPTY_BLACKBOARD;
131: ILayer layer = layer2;
132:
133: EditBlackboard editBlackBoard;
134: blackboardLock.lock();
135: try {
136:
137: EditManager editManager = ((EditManager) context
138: .getEditManager());
139: if (editManager.getEditLayer() != null
140: && editManager.isEditLayerLocked()) {
141: layer = context.getEditManager().getEditLayer();
142: }
143:
144: editBlackBoard = getEditBlackBoardFromLayer(layer);
145:
146: if (editBlackBoard == null) {
147:
148: MathTransform layerToMapTransform;
149: try {
150: layerToMapTransform = layer.layerToMapTransform();
151: } catch (IOException e) {
152: EditPlugin.log("", e); //$NON-NLS-1$
153: layerToMapTransform = IDENTITY;
154: }
155: editBlackBoard = new EditBlackboard(context
156: .getMapDisplay().getWidth(), context
157: .getMapDisplay().getHeight(), context
158: .worldToScreenTransform(), layerToMapTransform);
159:
160: final EditBlackboard bb = editBlackBoard;
161:
162: context.getViewportPane().addPaneListener(
163: new IMapDisplayListener() {
164:
165: public void sizeChanged(
166: MapDisplayEvent event) {
167: if (event.getOldSize() != null
168: && event.getOldSize().width != event
169: .getSize().width)
170: bb.setWidth(event.getSize().width);
171: if (event.getOldSize() != null
172: && event.getOldSize().height != event
173: .getSize().height)
174: bb
175: .setHeight(event.getSize().height);
176: }
177:
178: });
179:
180: layer.getBlackboard().put(EDIT_BLACKBOARD_KEY,
181: editBlackBoard);
182:
183: }
184: enableViewportListener((ViewportModel) context
185: .getViewportModel());
186:
187: //Vitalus: moved to EditToolHandler.enableListeners().
188: // enableClearBlackboardCommand(context);
189:
190: // disabled until I fix the events
191: // enableLayerChangeEventListener(layer, editBlackBoard);
192: } finally {
193: blackboardLock.unlock();
194: }
195:
196: if (dirtyAreas.get(layer) != null) {
197: openDataChangedDialog(layer, dirtyAreas.get(layer));
198: }
199: editBlackBoard.setToScreenTransform(context
200: .worldToScreenTransform());
201: return editBlackBoard;
202:
203: }
204:
205: private static Map<ILayer, ILayerListener> layerListenerMap = new HashMap<ILayer, ILayerListener>();
206: private static Map<ILayer, Envelope> dirtyAreas = new HashMap<ILayer, Envelope>();
207:
208: /**
209: * Adds a listener so that the editblackboards can be notified when the data in the feature
210: * store are modified.
211: */
212: private static synchronized void enableLayerChangeEventListener(
213: final ILayer layer, final EditBlackboard editBlackboard) {
214: ILayerListener listener = layerListenerMap.get(layer);
215: if (listener == null) {
216: listener = new ILayerListener() {
217: public void refresh(LayerEvent event) {
218: if (event.getSource() != layer) {
219: layer.removeListener(this );
220: return;
221: }
222: if (event.getType() != LayerEvent.EventType.EDIT_EVENT)
223: return;
224:
225: EditManager editManager = (EditManager) layer
226: .getMap().getEditManager();
227: ILayer editlayer = editManager.getSelectedLayer();
228: if (editManager.getEditLayer() != null
229: && editManager.isEditLayerLocked()) {
230: editlayer = editManager.getEditLayer();
231: }
232: EditState currentEditState = (EditState) layer
233: .getMap().getBlackboard().get(
234: EditToolHandler.EDITSTATE);
235: if (editlayer == layer
236: && (currentEditState == EditState.COMMITTING || EditManagerListener.committing == editManager))
237: return;
238:
239: FeatureEvent editEvent = (FeatureEvent) event
240: .getNewValue();
241:
242: if (editEvent == null)
243: return;
244:
245: Envelope dirtyArea = dirtyAreas.get(editlayer);
246: if (dirtyArea == null) {
247: dirtyArea = editEvent.getBounds();
248: } else {
249: dirtyArea
250: .expandToInclude(editEvent.getBounds());
251: }
252:
253: dirtyAreas.put(editlayer, dirtyArea);
254:
255: if (editlayer == layer
256: && layer.getMap() == ApplicationGIS
257: .getActiveMap()) {
258: openDataChangedDialog(editlayer, dirtyArea);
259: }
260: }
261: };
262: layerListenerMap.put(layer, listener);
263: }
264:
265: layer.addListener(listener);
266:
267: }
268:
269: static volatile Dialog dialog;
270:
271: public static void openDataChangedDialog(final ILayer layer,
272: final Envelope dirtyArea) {
273: Display d = Display.getCurrent();
274: if (d == null)
275: d = Display.getDefault();
276:
277: Condition condition = blackboardLock.newCondition();
278: try {
279: blackboardLock.lock();
280: if (dialog != null) {
281: // we're in the display thread, which means that the viewport is repainting since the dialog has any other input blocked.
282: // so just return
283: if (Display.getCurrent() != null)
284: return;
285: // the issue is being resolved we should wait for it to be resolved.
286: while (dialog != null) {
287: try {
288: condition.await(500, TimeUnit.MILLISECONDS);
289: } catch (InterruptedException e) {
290: return;
291: }
292: }
293: return;
294: }
295: } finally {
296: blackboardLock.unlock();
297: }
298:
299: PlatformGIS.syncInDisplayThread(d, new Runnable() {
300: public void run() {
301: try {
302: blackboardLock.lock();
303: if (dirtyAreas.get(layer) == null)
304: return;
305:
306: dialog = new Dialog(Display.getCurrent()
307: .getActiveShell()) {
308: private final int UPDATE = 1;
309: private final int CLEAR = 2;
310: private final int IGNORE = 3;
311:
312: public Control createDialogArea(Composite parent) {
313: Composite comp = new Composite(parent,
314: SWT.NONE);
315: comp.setLayout(new GridLayout(2, false));
316: Display display = Display.getCurrent();
317: Label label = new Label(comp, SWT.NONE);
318: label
319: .setBackground(display
320: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
321: label
322: .setForeground(display
323: .getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
324: label.setImage(Dialog
325: .getImage(Dialog.DLG_IMG_WARNING));
326: label.setLayoutData(new GridData(SWT.FILL,
327: SWT.NONE, true, false));
328: Text text = new Text(comp, SWT.WRAP
329: | SWT.READ_ONLY);
330: text.setLayoutData(new GridData(SWT.FILL,
331: SWT.FILL, true, true));
332: text
333: .setBackground(display
334: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
335: text
336: .setForeground(display
337: .getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
338: text
339: .setText(Messages.EditBlackboardUtil_data_changed);
340: return comp;
341: }
342:
343: public void createButtonsForButtonBar(
344: Composite composite) {
345: createButton(composite, UPDATE,
346: Messages.EditBlackboardUtil_update,
347: false);
348: createButton(composite, CLEAR,
349: Messages.EditBlackboardUtil_clear,
350: true);
351: createButton(composite, IGNORE,
352: Messages.EditBlackboardUtil_ignore,
353: false);
354: }
355:
356: public void buttonPressed(int button) {
357: switch (button) {
358: case UPDATE: {
359: boolean ok = MessageDialog
360: .openConfirm(
361: getParentShell(),
362: Messages.EditBlackboardUtil_Update_Selection,
363: Messages.EditBlackboardUtil_update_selection_confirmation);
364: if (ok) {
365: try {
366: ProgressMonitorDialog d = new ProgressMonitorDialog(
367: this .getParentShell());
368:
369: blackboardLock.unlock();
370: d
371: .run(
372: false,
373: false,
374: new IRunnableWithProgress() {
375: public void run(
376: IProgressMonitor monitor) {
377: updateFeatures(
378: layer,
379: monitor,
380: dirtyArea);
381: }
382: });
383: okPressed();
384: } catch (Exception e) {
385: EditPlugin.log("", e); //$NON-NLS-1$
386: }
387: }
388: break;
389: }
390: case CLEAR: {
391: boolean ok = MessageDialog
392: .openConfirm(
393: getParentShell(),
394: Messages.EditBlackboardUtil_clear_selection,
395: Messages.EditBlackboardUtil_changes_will_be_lost);
396: if (ok) {
397: blackboardLock.unlock();
398: (getEditBlackBoardFromLayer(layer))
399: .clear();
400: layer
401: .getMap()
402: .getBlackboard()
403: .put(
404: EditToolHandler.CURRENT_SHAPE,
405: null);
406: ((EditManager) layer.getMap()
407: .getEditManager())
408: .setEditFeature(null, null);
409: okPressed();
410: }
411: break;
412: }
413: case IGNORE:
414: boolean ok = MessageDialog
415: .openConfirm(
416: getParentShell(),
417: Messages.EditBlackboardUtil_ignore_change,
418: Messages.EditBlackboardUtil_changes_will_be_overwritten);
419: if (ok) {
420: okPressed();
421: }
422: break;
423:
424: default:
425: cancelPressed();
426: break;
427: }
428: }
429:
430: public void okPressed() {
431: dirtyAreas.remove(layer);
432: super .okPressed();
433: }
434: };
435: dialog.setBlockOnOpen(true);
436: dialog.open();
437: } finally {
438: blackboardLock.unlock();
439: dialog = null;
440: }
441:
442: }
443: });
444: }
445:
446: /**
447: * Updates the features in the "dirty Area" so that the {@link EditGeom}s reflect the actual state of the stored features.
448: * Any changes to the {@link EditGeom} will be lost.
449: *
450: * @param layer that needs to be updated.
451: * @param monitor progress monitor
452: * @param dirtyArea area that needs to be updated.
453: */
454: public static void updateFeatures(ILayer layer,
455: IProgressMonitor monitor, Envelope dirtyArea) {
456: EditBlackboard bb = getEditBlackBoardFromLayer(layer);
457: List<EditGeom> geoms = bb.getGeoms();
458: monitor.beginTask(
459: Messages.EditBlackboardUtil_updating_selected_features,
460: geoms.size());
461:
462: PrimitiveShape shape = (PrimitiveShape) layer.getMap()
463: .getBlackboard().get(EditToolHandler.CURRENT_SHAPE);
464: EditManager editManager = (EditManager) layer.getMap()
465: .getEditManager();
466:
467: FilterFactory factory = FilterFactoryFinder
468: .createFilterFactory();
469: FidFilter fidFilter = factory.createFidFilter();
470: for (EditGeom geom : geoms) {
471: fidFilter.addFid(geom.getFeatureIDRef().get());
472: }
473: Filter filter = fidFilter.and(layer.createBBoxFilter(dirtyArea,
474: new NullProgressMonitor()));
475: try {
476: FeatureSource fs = layer.getResource(FeatureSource.class,
477: monitor);
478: FeatureCollection results = fs.getFeatures(filter);
479: FeatureIterator reader = results.features();
480: try {
481: int read = 0;
482: boolean selectedFound = false;
483: List<EditGeom> toRemove = new ArrayList<EditGeom>();
484: while (reader.hasNext()) {
485: int count = geoms.size() - read;
486: monitor
487: .setTaskName(MessageFormat
488: .format(
489: Messages.EditBlackboardUtil_count_remaining,
490: new Object[] { count }));
491: read++;
492: Feature feature = reader.next();
493:
494: for (EditGeom geom : geoms) {
495: if (feature.getID().equals(
496: geom.getFeatureIDRef().get())) {
497: toRemove.add(geom);
498: }
499: }
500:
501: Map<Geometry, EditGeom> mapping = bb.addGeometry(
502: feature.getDefaultGeometry(), feature
503: .getID());
504: if (feature.getID()
505: .equals(
506: shape.getEditGeom()
507: .getFeatureIDRef().get())) {
508: editManager.setEditFeature(feature,
509: (Layer) layer);
510: layer.getMap().getBlackboard().put(
511: EditToolHandler.CURRENT_SHAPE,
512: mapping.values().iterator().next()
513: .getShell());
514: selectedFound = true;
515: }
516: monitor.worked(1);
517: }
518: if (!selectedFound) {
519: layer.getMap().getBlackboard().put(
520: EditToolHandler.CURRENT_SHAPE, null);
521: editManager.setEditFeature(null, null);
522: }
523: bb.removeGeometries(toRemove);
524: } finally {
525: reader.close();
526: monitor.done();
527: }
528: } catch (IOException e) {
529: EditPlugin.log("", e); //$NON-NLS-1$
530: }
531: }
532:
533: /**
534: * Returns the Editblackboard from the layer if it is on the layer or null if it hasn't been created yet.
535: * {@link #getEditBlackboard(IToolContext, ILayer)} will create and initialize the blackbaord
536: *
537: * @param layer
538: * @return
539: */
540: private static EditBlackboard getEditBlackBoardFromLayer(
541: ILayer layer) {
542: blackboardLock.lock();
543: try {
544: return (EditBlackboard) layer.getBlackboard().get(
545: EDIT_BLACKBOARD_KEY);
546: } finally {
547: blackboardLock.unlock();
548: }
549: }
550:
551: /**
552: * Command handler for the command "net.refractions.udig.tool.edit.clearAction"
553: * to clear EditBlackboard.
554: */
555: static IHandler clearEditBlackboardHandler;
556:
557: /**
558: * Listener for "net.refractions.udig.tool.edit.clearAction" command.
559: */
560: static ICommandListener clearEditBlackboardCommandListener;
561:
562: /**
563: * Sets the command handler for the "ESC" button. The handler clears current edit blackboard.
564: * <p>
565: * Called from <code>EditToolHandler.enableListeners()</code>.
566: *
567: * @param context
568: */
569: static synchronized void enableClearBlackboardCommand(
570: final IToolContext context) {
571: if (clearEditBlackboardHandler == null) {
572: clearEditBlackboardHandler = new AbstractHandler() {
573:
574: public Object execute(ExecutionEvent event)
575: throws ExecutionException {
576: Tool tool = ApplicationGIS.getToolManager()
577: .getActiveTool();
578:
579: if (tool instanceof AbstractEditTool) {
580: EditToolHandler editToolHandler = ((AbstractEditTool) tool)
581: .getHandler();
582: List<Behaviour> behaviours = editToolHandler
583: .getCancelBehaviours();
584: UndoableComposite compositeCommand = new UndoableComposite();
585: for (Behaviour behaviour : behaviours) {
586: if (behaviour.isValid(editToolHandler)) {
587: UndoableMapCommand command = behaviour
588: .getCommand(editToolHandler);
589: if (command != null)
590: compositeCommand.getCommands().add(
591: command);
592: }
593: }
594: if (!compositeCommand.getCommands().isEmpty())
595: editToolHandler.getContext()
596: .sendASyncCommand(compositeCommand);
597: }
598:
599: return null;
600: }
601: };
602:
603: }
604: ICommandService service = (ICommandService) PlatformUI
605: .getWorkbench().getAdapter(ICommandService.class);
606:
607: Command command = service
608: .getCommand("net.refractions.udig.tool.edit.clearAction"); //$NON-NLS-1$
609: command.setHandler(clearEditBlackboardHandler);
610:
611: if (clearEditBlackboardCommandListener == null) {
612: clearEditBlackboardCommandListener = new ICommandListener() {
613:
614: public void commandChanged(CommandEvent commandEvent) {
615: if (commandEvent.isHandledChanged()) {
616: commandEvent.getCommand()
617: .removeCommandListener(this );
618: clearEditBlackboardCommandListener = null;
619:
620: IMap map = ApplicationGIS.getActiveMap();
621: resetBlackboards(map);
622: }
623: }
624:
625: };
626: command
627: .addCommandListener(clearEditBlackboardCommandListener);
628: }
629: }
630:
631: /**
632: * Removes a command handler for the "ESC" button.
633: * <p>
634: * Called from <code>EditToolHandler.disableListeners()</code>.
635: */
636: static synchronized void disableClearBlackboardCommand() {
637: ICommandService service = (ICommandService) PlatformUI
638: .getWorkbench().getAdapter(ICommandService.class);
639: Command command = service
640: .getCommand("net.refractions.udig.tool.edit.clearAction"); //$NON-NLS-1$
641: command.setHandler(null);
642:
643: if (clearEditBlackboardCommandListener != null) {
644: command
645: .removeCommandListener(clearEditBlackboardCommandListener);
646: clearEditBlackboardCommandListener = null;
647: }
648: }
649:
650: /**
651: * Disables listeners so that they will not get events.
652: * Should be called when tool is disabled or when a blackboard is no longer required.
653: *
654: * @see #getEditBlackboard(IToolContext, ILayer) (it enables listeners).
655: */
656: public static void doneListening() {
657: disableViewportListener();
658: // disableLayerEvents();
659: }
660:
661: /**
662: * Disables the listeners listening to layers for edit events.
663: * @see #enableLayerChangeEventListener(ILayer, EditBlackboard)
664: */
665: public static synchronized void disableLayerEvents() {
666: Collection<Map.Entry<ILayer, ILayerListener>> entries = layerListenerMap
667: .entrySet();
668: for (Map.Entry<ILayer, ILayerListener> entry : entries) {
669: entry.getKey().removeListener(entry.getValue());
670: }
671: layerListenerMap.clear();
672: }
673:
674: /**
675: * Returns the selectedLayer or if it is not editable or not visible then the edit layer will be
676: *
677: * @return
678: */
679: public static ILayer findEditLayer(IToolContext context) {
680: ILayer layer = null;
681: IMap map = context.getMap();
682: // The selected layer will become the edit layer! If it's a featureStore and editable of
683: // course.
684: ILayer selectedLayer = ((EditManagerImpl) map.getEditManager())
685: .getSelectedLayer();
686: if (isEditable(selectedLayer)) {
687: return selectedLayer;
688: }
689: // Otherwise we'll fall back to the current editLayer
690: if (isEditable(map.getEditManager().getEditLayer()))
691: return map.getEditManager().getEditLayer();
692: // If all else fails we'll iterate through the layer and find the first layer eligable for
693: // editing.
694: // We should really never get here though.
695: for (Iterator<ILayer> iter = map.getMapLayers().iterator(); iter
696: .hasNext();) {
697: layer = iter.next();
698: if (isEditable(layer))
699: break;
700: }
701: return layer;
702: }
703:
704: /**
705: * Checks that a layer has a FeatureStore, is editable and is visible.
706: */
707: private static boolean isEditable(ILayer layer) {
708: return layer != null && layer.hasResource(FeatureStore.class)
709: && layer.isApplicable("editing") && layer.isVisible(); //$NON-NLS-1$
710: }
711:
712: @SuppressWarnings("unchecked")
713: private synchronized static void enableViewportListener(
714: ViewportModel model) {
715: disableViewportListener();
716: listener = new ViewportModelListener(model);
717:
718: listener.model.eAdapters().add(listener);
719:
720: }
721:
722: private synchronized static void disableViewportListener() {
723: if (listener != null)
724: listener.model.eAdapters().remove(listener);
725: listener = null;
726: }
727:
728: /**
729: * Listens for changes to the viewport model and transforms the edit blackboards to the new CRS or bounds
730: *
731: */
732: static class ViewportModelListener extends AdapterImpl {
733: ViewportModel model;
734: private ILayer layer;
735:
736: ViewportModelListener(ViewportModel model) {
737: this .model = model;
738: this .layer = model.getMap().getEditManager()
739: .getSelectedLayer();
740: }
741:
742: @Override
743: public void notifyChanged(Notification msg) {
744: if (listener == null) {
745: model.eAdapters().remove(listener);
746: listener = this ;
747: return;
748: }
749: switch (msg.getFeatureID(ViewportModel.class)) {
750: case RenderPackage.VIEWPORT_MODEL__BOUNDS: {
751: getEditBlackBoardFromLayer(layer).setToScreenTransform(
752: model.worldToScreenTransform());
753: break;
754: }
755: case RenderPackage.VIEWPORT_MODEL__CRS: {
756: try {
757: getEditBlackBoardFromLayer(layer)
758: .setMapLayerTransform(
759: layer.mapToLayerTransform());
760: } catch (IOException e) {
761: EditPlugin.log("", e); //$NON-NLS-1$
762: }
763: getEditBlackBoardFromLayer(layer).setToScreenTransform(
764: model.worldToScreenTransform());
765: break;
766: }
767: }
768: }
769:
770: }
771:
772: /**
773: * clears edit blackboard for all layers in a given map... Critical to prevent memory leaks
774: */
775: public static void resetBlackboards(IMap map) {
776: if (map != null) {
777: blackboardLock.lock();
778: try {
779: List<ILayer> layers = map.getMapLayers();
780: for (ILayer layer : layers) {
781: EditBlackboard blackboard = getEditBlackBoardFromLayer(layer);
782: if (blackboard != null) {
783: blackboard.clear();
784: layer.getBlackboard().put(EDIT_BLACKBOARD_KEY,
785: null);
786: }
787: }
788: } finally {
789: blackboardLock.unlock();
790: }
791: }
792: }
793:
794: }
|