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.util.List;
018: import java.util.Set;
019:
020: import net.refractions.udig.core.internal.ExtensionPointList;
021: import net.refractions.udig.project.command.UndoableMapCommand;
022: import net.refractions.udig.project.ui.ApplicationGIS;
023: import net.refractions.udig.project.ui.internal.tool.display.CursorProxy;
024: import net.refractions.udig.project.ui.internal.tool.display.ToolManager;
025: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent;
026: import net.refractions.udig.project.ui.render.displayAdapter.MapMouseWheelEvent;
027: import net.refractions.udig.project.ui.tool.IToolContext;
028: import net.refractions.udig.project.ui.tool.IToolManager;
029: import net.refractions.udig.project.ui.tool.SimpleTool;
030: import net.refractions.udig.project.ui.tool.Tool;
031: import net.refractions.udig.tools.edit.behaviour.RefreshLayersBehaviour;
032: import net.refractions.udig.tools.edit.support.EditUtils;
033:
034: import org.eclipse.core.runtime.IConfigurationElement;
035: import org.eclipse.jface.resource.ImageDescriptor;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.graphics.Cursor;
038: import org.eclipse.swt.graphics.Image;
039: import org.eclipse.swt.widgets.Display;
040: import org.eclipse.ui.plugin.AbstractUIPlugin;
041:
042: /**
043: * Super class for edit tools. This class delegates to the EditToolHandler which must be initialized by
044: * the subclass during construction.
045: *
046: * @author jones
047: * @since 1.1.0
048: */
049: public abstract class AbstractEditTool extends SimpleTool {
050:
051: protected EditToolHandler handler;
052:
053: public AbstractEditTool() {
054: super (MOUSE | WHEEL | MOTION);
055: Cursor editCursor = null;
056: IToolManager toolManager = ApplicationGIS.getToolManager();
057:
058: List<IConfigurationElement> list = ExtensionPointList
059: .getExtensionPointList(Tool.EXTENSION_ID);
060:
061: /*
062: * Vitalus: The modern tool cursor approach is used - the order of finding the
063: * default cursor:
064: * 1) Try to find default cursor from "toolCursorId" attribute
065: * 2) Try to find child configuration element "cursor"
066: * 3) Set default system arrow cursor
067: */
068: for (IConfigurationElement element : list) {
069: if (element.getAttribute("id").equals(getExtensionID())) { //$NON-NLS-1$
070: String cursorId = element.getAttribute("toolCursorId");
071: if (cursorId != null) {
072: editCursor = toolManager.findToolCursor(cursorId);
073: }
074: if (editCursor == null) {
075: IConfigurationElement[] cursorElement = element
076: .getChildren("cursor"); //$NON-NLS-1$
077: editCursor = new CursorProxy(cursorElement[0])
078: .getCursor();
079: }
080: break;
081: }
082: }
083: if (editCursor == null) {
084: editCursor = Display.getDefault().getSystemCursor(
085: SWT.CURSOR_ARROW);
086: }
087:
088: //Must be configured in "net.refractions.udig.tool.default" plugin
089: Cursor selectionCursor = toolManager
090: .findToolCursor("boxSelectionCursor");
091: handler = new EditToolHandler(selectionCursor, editCursor);
092: initActivators(handler.getActivators());
093: EditToolConfigurationHelper editToolConfigurationHelper = new EditToolConfigurationHelper(
094: getHandler().getBehaviours());
095: initEventBehaviours(editToolConfigurationHelper);
096: initEnablementBehaviours(handler.getEnablementBehaviours());
097: initAcceptBehaviours(handler.getAcceptBehaviours());
098: // make sure that the layer cache is cleaned up to prevent memory leaks.
099: handler.getAcceptBehaviours().add(new Behaviour() {
100:
101: public UndoableMapCommand getCommand(EditToolHandler handler) {
102: EditUtils.instance.clearLayerStateShapeCache(handler
103: .getContext().getMapLayers());
104: return null;
105: }
106:
107: public void handleError(EditToolHandler handler,
108: Throwable error, UndoableMapCommand command) {
109: EditPlugin.log("", error); //$NON-NLS-1$
110: }
111:
112: public boolean isValid(EditToolHandler handler) {
113: return true;
114: }
115:
116: });
117:
118: initCancelBehaviours(handler.getCancelBehaviours());
119: handler.setTool(this );
120:
121: if (!editToolConfigurationHelper.isDone())
122: throw new IllegalStateException(
123: "configurator's done method was not called."); //$NON-NLS-1$
124: }
125:
126: /**
127: * Initializes the list of Activators that are ran when the tool is activated and deactivated.
128: *
129: * @param activators an empty list.
130: */
131: protected abstract void initActivators(Set<Activator> activators);
132:
133: /**
134: * Initializes the list of Behaviours to run when the current edit has been accepted.
135: * Acceptance is signalled by a double click or the Enter key
136: *
137: * @param acceptBehaviours an empty list
138: */
139: protected abstract void initAcceptBehaviours(
140: List<Behaviour> acceptBehaviours);
141:
142: /**
143: * Initializes the behaviours that are ran when a cancel signal is received (the ESC key).
144: *
145: * @param cancelBehaviours an empty list
146: */
147: protected abstract void initCancelBehaviours(
148: List<Behaviour> cancelBehaviours);
149:
150: /**
151: * Initializes the Event Behaviours that are run when an event occurs. Since this can be complex a helper
152: * class is provided to build the complex datastructure of Behaviours.
153: *
154: * @see EditToolConfigurationHelper
155: *
156: * @param helper a helper for constructing the complicated structure of EventBehaviours.
157: */
158: protected abstract void initEventBehaviours(
159: EditToolConfigurationHelper helper);
160:
161: /**
162: * Initializes the list of {@link EnablementBehaviour}s that are ran to determine if the tool is enabled given an
163: * event. For example if the mouse cursor is outside the valid bounds of a CRS for a layer an EnablementBehaviour might
164: * signal that editing is illegal and provide a message for the user indicating why.
165: *
166: * @param enablementBehaviours an empty list
167: */
168: protected abstract void initEnablementBehaviours(
169: List<EnablementBehaviour> enablementBehaviours);
170:
171: /**
172: * Called only by unit tests. Has no effect on state of tool.
173: */
174: public void testinitActivators(Set<Activator> activators) {
175: initActivators(activators);
176: }
177:
178: /**
179: * Called only by unit tests. Has no effect on state of tool.
180: */
181: public void testinitAcceptBehaviours(
182: List<Behaviour> acceptBehaviours) {
183: initAcceptBehaviours(acceptBehaviours);
184: }
185:
186: /**
187: * Called only by unit tests. Has no effect on state of tool.
188: */
189: public void testinitCancelBehaviours(
190: List<Behaviour> cancelBehaviours) {
191: initCancelBehaviours(cancelBehaviours);
192: }
193:
194: /**
195: * Called only by unit tests. Has no effect on state of tool.
196: */
197: public void testinitEventBehaviours(
198: EditToolConfigurationHelper helper) {
199: initEventBehaviours(helper);
200: }
201:
202: /**
203: * Returns the ID of the tool as declared in the plugin.xml. The plugin's id must be appended to the
204: * id. For example if the id of the tool is "polygon" and the id of the containing plugin is "net.refractions.udig.tool"
205: * then the id this method will return is "net.refractions.udig.tool.polygon"
206: *
207: * @return the ID of the tool as declared in the plugin.xml
208: */
209: protected abstract String getExtensionID();
210:
211: @Override
212: public void setContext(IToolContext context) {
213: if (getContext() != null
214: && getContext().getViewportPane() != null)
215: getContext().getViewportPane().repaint();
216: super .setContext(context);
217: handler.setContext(context);
218: if (isActive()) {
219: handler.basicDisablement();
220: handler.basicEnablement();
221: }
222: handler.repaint();
223: }
224:
225: @Override
226: public void setActive(boolean active) {
227: super .setActive(active);
228: handler.setActive(active);
229: }
230:
231: @Override
232: protected void onMouseDoubleClicked(MapMouseEvent e) {
233: handler.handleEvent(e, EventType.DOUBLE_CLICK);
234: }
235:
236: @Override
237: protected void onMouseDragged(MapMouseEvent e) {
238: handler.handleEvent(e, EventType.DRAGGED);
239: }
240:
241: @Override
242: protected void onMouseEntered(MapMouseEvent e) {
243: handler.handleEvent(e, EventType.ENTERED);
244: }
245:
246: @Override
247: protected void onMouseExited(MapMouseEvent e) {
248: handler.handleEvent(e, EventType.EXITED);
249: }
250:
251: @Override
252: protected void onMouseMoved(MapMouseEvent e) {
253: handler.handleEvent(e, EventType.MOVED);
254: }
255:
256: @Override
257: protected void onMousePressed(MapMouseEvent e) {
258: handler.handleEvent(e, EventType.PRESSED);
259: }
260:
261: @Override
262: protected void onMouseReleased(MapMouseEvent e) {
263: handler.handleEvent(e, EventType.RELEASED);
264: }
265:
266: @Override
267: protected void onMouseWheelMoved(MapMouseWheelEvent e) {
268: handler.handleEvent(e, EventType.WHEEL);
269: }
270:
271: @Override
272: protected void onMouseHovered(MapMouseEvent e) {
273: handler.handleEvent(e, EventType.HOVERED);
274: }
275:
276: /**
277: * @return Returns the handler.
278: */
279: public EditToolHandler getHandler() {
280: return handler;
281: }
282:
283: /**
284: * @param handler The handler to set.
285: */
286: public void setHandler(EditToolHandler handler) {
287: this.handler = handler;
288: }
289:
290: }
|