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.tool;
018:
019: import java.util.EventListener;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import org.eclipse.swt.widgets.Display;
026: import org.eclipse.ui.IEditorPart;
027: import org.eclipse.ui.IEditorReference;
028: import org.eclipse.ui.IWorkbenchPage;
029: import org.eclipse.ui.IWorkbenchWindow;
030: import org.eclipse.ui.PlatformUI;
031:
032: import net.refractions.udig.project.ui.internal.ApplicationGISInternal;
033: import net.refractions.udig.project.ui.internal.MapEditor;
034: import net.refractions.udig.project.ui.internal.ProjectUIPlugin;
035: import net.refractions.udig.project.ui.internal.Trace;
036: import net.refractions.udig.project.ui.internal.tool.ToolContext;
037: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
038: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener;
039: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseMotionListener;
040: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelEvent;
041: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelListener;
042: import net.refractions.udig.ui.PlatformGIS;
043:
044: /**
045: * The Abstract base class for items. Provides support for enabling and disabling modal items.
046: * <p>
047: * Tool developers that extend this class override the event notification methods. This class
048: * handles registering the tool with the current map display.
049: * </p>
050: * <p>
051: * Note: subclasses must have a single public parameterless constructor that calls the super
052: * constructor with a number indicating which event they want to listen for.
053: * </p>
054: * <p>
055: * Example:
056: *
057: * <pre><code>
058: * super( MOUSE|MOTION ) indicates that the items will be receive all mouse and mouse motion commands.
059: * </code></pre>
060: *
061: * @author Jesse Eichar
062: * @version $Revision: 1.9 $
063: * @see Tool
064: * @see MapMouseListener
065: * @see MapMouseMotionListener
066: * @see MapMouseWheelListener
067: * @see EventListener
068: */
069: public abstract class AbstractTool implements Tool, MapMouseListener,
070: MapMouseMotionListener, MapMouseWheelListener, EventListener {
071:
072: /** Flag indicating that the tool does not listen for events from the ViewportPane */
073: public final static int NONE = 0;
074:
075: /** Flag indicating the tool is a {@linkplain MapMouseListener} */
076: public final static int MOUSE = 1;
077:
078: /** Flag indicating the tool is a {@linkplain MapMouseMotionListener} */
079: public final static int MOTION = 2;
080:
081: /** Flag indicating the tool is a {@linkplain MapMouseWheelListener} */
082: public final static int WHEEL = 4;
083: /** Flag indicating that the tool can drag from the Map Editor. (drag in terms of drag-drop) */
084: public final static int DRAG_DROP = 8;
085:
086: /** The items to use for tool actions */
087: protected IToolContext context;
088:
089: private int targets;
090:
091: private Map<String, Object> properties = new HashMap<String, Object>();
092:
093: /**
094: *
095: */
096: private IMapEditorSelectionProvider selectionProvider;
097:
098: /**
099: *
100: * Tool's lifecycle listeners.
101: */
102: private Set<ToolLifecycleListener> listeners = new HashSet<ToolLifecycleListener>();
103:
104: /**
105: * Enablement of the tool.
106: */
107: protected boolean enabled = true;
108:
109: private boolean isNotify = true;
110:
111: /**
112: * Assigns renderManager to field and registers as a listener with source. The target field is
113: * used to determine which type of listeners to register as.
114: *
115: * @param targets Used to determine which listeners to register as. The following choices from
116: * the following list can be combined using | and this tool will be registered as both
117: * types of listeners:
118: * <ul>
119: * <li>{@link #MOUSE}- Register as a {@link MapMouseListener} </li>
120: * <li>{@link #MOTION}- Register as a (@link MapMouseMotionListener}</li>
121: * <li>{@link #WHEEL}- Register as a (@link MapMouseWheelListener} </li>
122: * </ul>
123: */
124: public AbstractTool(int targets) {
125: if ((targets & (MOUSE | MOTION | WHEEL | DRAG_DROP)) != targets)
126: throw new RuntimeException(
127: "Argument targets indicated that the" //$NON-NLS-1$
128: + " items was not to be registered with any component.\n" //$NON-NLS-1$
129: + "Argument targets = " + targets); //$NON-NLS-1$
130:
131: this .targets = targets;
132: }
133:
134: /**
135: * Registers this object as a listener.
136: * <p>
137: * The events this object listens for are indicated by the targets parameter in the constructor.
138: * This method is called by setActive() and only needs to be called by client code if setActive
139: * is overridden and not called with super().
140: * </p>
141: * This method does not need to be overridden by subclasses normally.
142: */
143: protected final void registerMouseListeners() {
144: if (context == null || context.getViewportPane() == null)
145: return;
146:
147: if ((targets & MOUSE) != 0)
148: context.getViewportPane().addMouseListener(this );
149: if ((targets & MOTION) != 0)
150: context.getViewportPane().addMouseMotionListener(this );
151: if ((targets & WHEEL) != 0)
152: context.getViewportPane().addMouseWheelListener(this );
153: if ((targets & DRAG_DROP) != 0) {
154: // yes I do want to do this in async even if I am in the display thread
155: // because if I try to get the editor now, the editor may not be open yet.
156: Display display = Display.getCurrent();
157: if (display == null) {
158: display = Display.getDefault();
159: }
160: final IToolContext context = this .context;
161: display.asyncExec(new Runnable() {
162: public void run() {
163: MapEditor editor = ApplicationGISInternal
164: .findMapEditor(context.getMap());
165: if (editor != null && !editor.isDragging()) {
166: editor.setDragging(true);
167: }
168:
169: }
170: });
171: }
172:
173: }
174:
175: /**
176: * Deregisters this object as a listener.
177: * <p>
178: * The events this object listens for are indicated by the targets parameter in the constructor.
179: * This method is called by setActive() and only needs to be called by client code if setActive
180: * is overridden and not called with super().
181: * </p>
182: * This method does not need to be overridden by subclasses normally.
183: */
184: protected final void deregisterMouseListeners() {
185: if (context == null || context.getViewportPane() == null)
186: return;
187:
188: context.getViewportPane().removeMouseListener(this );
189: context.getViewportPane().removeMouseMotionListener(this );
190: context.getViewportPane().removeMouseWheelListener(this );
191: if ((targets & DRAG_DROP) != 0) {
192: // yes I do want to do this in async even if I am in the display thread
193: // because if I try to get the editor now, the editor may not be open yet.
194: Display display = Display.getCurrent();
195: if (display == null) {
196: display = Display.getDefault();
197: }
198: final IToolContext context = this .context;
199: display.asyncExec(new Runnable() {
200: public void run() {
201: MapEditor editor = ApplicationGISInternal
202: .findMapEditor(context.getMap());
203: if (editor != null && editor.isDragging()) {
204: editor.setDragging(false);
205: }
206:
207: }
208: });
209: }
210: }
211:
212: /**
213: * Called each time an eclipse editor is activated. The RenderManager and ViewportPane are those
214: * that are associated with the newly actived Eclipse view. Intended to be used if something
215: * other just changing the current state happens. if false the tool is set as inactive and
216: * deregistered with the component. This method does not need to be overridden by subclasses
217: * normally.
218: *
219: * @param items The items that the tool can use in its operations
220: * @see IToolContext
221: */
222: public void setContext(IToolContext tools) {
223: deregisterMouseListeners();
224:
225: this .context = tools;
226:
227: registerMouseListeners();
228: }
229:
230: /**
231: * This method does not need to be overridden by subclasses normally.
232: *
233: * @see net.refractions.udig.project.ui.tool.Tool#getContext()
234: * @see IToolContext
235: */
236: public IToolContext getContext() {
237: return context;
238: }
239:
240: /**
241: * @see net.refractions.udig.project.ui.tool.Tool#dispose()
242: */
243: public void dispose() {
244: deregisterMouseListeners();
245: }
246:
247: /**
248: * @see net.refractions.udig.project.ui.tool.Tool#getProperty()
249: */
250: public Object getProperty(String key) {
251: return properties.get(key);
252:
253: }
254:
255: /**
256: * (non-Javadoc)
257: * @see net.refractions.udig.project.ui.tool.Tool#isEnabled()
258: */
259: public boolean isEnabled() {
260: return enabled;
261: }
262:
263: /** (non-Javadoc)
264: * @see net.refractions.udig.project.ui.tool.Tool#setEnabled(boolean)
265: */
266: public void setEnabled(boolean enabled) {
267: boolean oldValue = enabled;
268: this .enabled = enabled;
269:
270: if (isNotify && oldValue != enabled) {
271: ToolLifecycleEvent event = new ToolLifecycleEvent(this ,
272: ToolLifecycleEvent.Type.ENABLE, enabled, oldValue);
273: fireEvent(event);
274: }
275: }
276:
277: /**
278: * @see net.refractions.udig.project.ui.tool.Tool#setProperty()
279: */
280: public void setProperty(String key, Object value) {
281: properties.put(key, value);
282: }
283:
284: /* (non-Javadoc)
285: * @see net.refractions.udig.project.ui.tool.Tool#getSelectionProvider()
286: */
287: public IMapEditorSelectionProvider getSelectionProvider() {
288: return selectionProvider;
289: }
290:
291: /* (non-Javadoc)
292: * @see net.refractions.udig.project.ui.tool.Tool#setSelectionProvider(net.refractions.udig.project.ui.tool.IMapEditorSelectionProvider)
293: */
294: public void setSelectionProvider(
295: IMapEditorSelectionProvider selectionProvider) {
296: this .selectionProvider = selectionProvider;
297: }
298:
299: /** (non-Javadoc)
300: * @see net.refractions.udig.project.ui.tool.Tool#addListener(net.refractions.udig.project.ui.tool.ToolLifecycleListener)
301: */
302: public void addListener(ToolLifecycleListener listener) {
303: listeners.add(listener);
304: }
305:
306: /** (non-Javadoc)
307: * @see net.refractions.udig.project.ui.tool.Tool#removeListener(net.refractions.udig.project.ui.tool.ToolLifecycleListener)
308: */
309: public void removeListener(ToolLifecycleListener listener) {
310: listeners.remove(listener);
311: }
312:
313: protected void setNotifyListeners(boolean isNotify) {
314: this .isNotify = isNotify;
315: }
316:
317: /**
318: * @return
319: */
320: protected boolean isNotifyListeners() {
321: return isNotify;
322: }
323:
324: /**
325: * @param event
326: */
327: protected void fireEvent(ToolLifecycleEvent event) {
328: for (ToolLifecycleListener listener : listeners) {
329: listener.changed(event);
330: }
331: }
332:
333: /**
334: * This method may be overridden by subclasses
335: *
336: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener#mouseEntered(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
337: * @see MapMouseEvent
338: */
339: public void mouseEntered(MapMouseEvent e) { // do nothing
340: }
341:
342: /**
343: * This method may be overridden by subclasses
344: *
345: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener#mouseExited(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
346: * @see MapMouseEvent
347: */
348: public void mouseExited(MapMouseEvent e) { // do nothing
349: }
350:
351: /**
352: * This method may be overridden by subclasses
353: *
354: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener#mousePressed(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
355: * @see MapMouseEvent
356: */
357: public void mousePressed(MapMouseEvent e) { // do nothing
358: }
359:
360: /**
361: * This method may be overridden by subclasses
362: *
363: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener#mouseReleased(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
364: * @see MapMouseEvent
365: */
366: public void mouseReleased(MapMouseEvent e) { // do nothing
367: }
368:
369: /**
370: * This method may be overridden by subclasses
371: *
372: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseMotionListener#mouseDragged(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
373: * @see MapMouseEvent
374: */
375: public void mouseDragged(MapMouseEvent e) { // do nothing
376: }
377:
378: /**
379: * This method may be overridden by subclasses
380: *
381: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseMotionListener#mouseMoved(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
382: */
383: public void mouseMoved(MapMouseEvent e) { // do nothing
384: }
385:
386: /**
387: * This method may be overridden by subclasses
388: *
389: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseMotionListener#mouseHovered(MapMouseEvent)
390: */
391: public void mouseHovered(MapMouseEvent e) { // do nothing
392: }
393:
394: /**
395: * This method may be overridden by subclasses
396: *
397: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelListener#mouseWheelMoved(net.refractions.udig.project.render.displayAdapter.MapMouseWheelEvent)
398: * @see MapMouseEvent
399: */
400: public void mouseWheelMoved(MapMouseWheelEvent e) { // do nothing
401: }
402:
403: /**
404: * This method may be overridden by subclasses
405: *
406: * @see net.refractions.udig.project.ui.render.displayAdapter.MapMouseListener#mouseDoubleClicked(net.refractions.udig.project.render.displayAdapter.MapMouseEvent)
407: * @see MapMouseEvent
408: */
409: public void mouseDoubleClicked(MapMouseEvent event) { // do nothing
410: }
411: }
|