001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.workbench.plugin;
034:
035: import java.awt.event.ActionEvent;
036: import java.awt.event.ActionListener;
037:
038: import org.apache.log4j.Logger;
039:
040: import com.vividsolutions.jump.I18N;
041: import com.vividsolutions.jump.util.StringUtil;
042: import com.vividsolutions.jump.workbench.WorkbenchContext;
043: import com.vividsolutions.jump.workbench.model.LayerManagerProxy;
044: import com.vividsolutions.jump.workbench.model.UndoableCommand;
045: import com.vividsolutions.jump.workbench.model.UndoableEditReceiver;
046: import com.vividsolutions.jump.workbench.ui.EditTransaction;
047: import com.vividsolutions.jump.workbench.ui.task.TaskMonitorManager;
048:
049: /**
050: * Default implementation of PlugIn, with useful functions for auto-generating
051: * a name, converting a PlugIn into an ActionListener (for use with JButtons,
052: * for example), and supporting undo.
053: */
054: public abstract class AbstractPlugIn implements PlugIn {
055: private static Logger LOG = Logger.getLogger(AbstractPlugIn.class);
056:
057: protected void execute(UndoableCommand command,
058: PlugInContext context) {
059: execute(command, context.getLayerViewPanel());
060: }
061:
062: public AbstractPlugIn() {
063: }
064:
065: public AbstractPlugIn(String name) {
066: this .name = name;
067: }
068:
069: public void initialize(PlugInContext context) throws Exception {
070: }
071:
072: public boolean execute(PlugInContext context) throws Exception {
073: return true;
074: }
075:
076: /**
077: * @return the class name, minus "PlugIn", with
078: * spaces inserted at the appropriate point before each
079: * uppercase+lowercase and lowercase+uppercase combination.
080: */
081: public String getName() {
082: return name == null ? createName(getClass()) : name;
083: }
084:
085: private String name;
086:
087: public static String createName(Class plugInClass) {
088: try {
089: return I18N.get(plugInClass.getName());
090: } catch (java.util.MissingResourceException e) {
091: // No I18N for the PlugIn so log it, but don't stop
092: LOG.error(e.getMessage() + " " + plugInClass.getName());
093: return StringUtil.toFriendlyName(plugInClass.getName(),
094: "PlugIn");
095: }
096: }
097:
098: /**
099: * @param taskMonitorManager can be null if you do not wish to use the
100: * Task Monitor progress-reporting framework
101: */
102:
103: public static ActionListener toActionListener(final PlugIn plugIn,
104: final WorkbenchContext workbenchContext,
105: final TaskMonitorManager taskMonitorManager) {
106: return new ActionListener() {
107: public void actionPerformed(ActionEvent e) {
108: try {
109: if (workbenchContext.getWorkbench() != null) {
110: workbenchContext.getWorkbench().getFrame()
111: .setStatusMessage("");
112: workbenchContext
113: .getWorkbench()
114: .getFrame()
115: .log(
116: I18N
117: .get("plugin.AbstractPlugIn.executing")
118: + " "
119: + plugIn.getName());
120:
121: }
122:
123: PlugInContext plugInContext = workbenchContext
124: .createPlugInContext();
125: //Cache the UndoableEditReceiver, because the "topmost"
126: //layer manager before the edit may be different from the
127: //topmost layer manager after (e.g. NewTaskPlugIn). [Jon Aquino]
128:
129: UndoableEditReceiver undoableEditReceiver = workbenchContext
130: .getLayerManager() != null ? workbenchContext
131: .getLayerManager()
132: .getUndoableEditReceiver()
133: : null;
134: if (undoableEditReceiver != null) {
135: undoableEditReceiver.startReceiving();
136: }
137:
138: try {
139: boolean executeComplete = plugIn
140: .execute(plugInContext);
141:
142: if (plugIn instanceof ThreadedPlugIn
143: && executeComplete) {
144: taskMonitorManager.execute(
145: (ThreadedPlugIn) plugIn,
146: plugInContext);
147: }
148: } finally {
149: if (undoableEditReceiver != null) {
150: undoableEditReceiver.stopReceiving();
151: }
152: }
153:
154: if (workbenchContext.getWorkbench() != null) {
155: workbenchContext
156: .getWorkbench()
157: .getFrame()
158: .log(
159: I18N
160: .get("plugin.AbstractPlugIn.done-current-committed-memory")
161: + workbenchContext
162: .getWorkbench()
163: .getFrame()
164: .getMBCommittedMemory()
165: + " MB");
166: }
167: } catch (Throwable t) {
168: workbenchContext.getErrorHandler().handleThrowable(
169: t);
170: }
171: }
172: };
173: }
174:
175: public static void execute(UndoableCommand command,
176: LayerManagerProxy layerManagerProxy) {
177: //Used to do nothing if command or panel were null, but that seems to me now
178: //like a dangerous thing to do. So I've taken it out, and hopefully will receive
179: //a complaint from someone about a NullPointerException. When I find out
180: //why, I'll be sure to document the reason! [Jon Aquino]
181: boolean exceptionOccurred = true;
182: try {
183: command.execute();
184: exceptionOccurred = false;
185: } finally {
186: //Funny logic because I want to avoid adding a throws clause to this method,
187: //so that existing code will not break [Jon Aquino 12/5/2003]
188: if (exceptionOccurred) {
189: layerManagerProxy.getLayerManager()
190: .getUndoableEditReceiver().getUndoManager()
191: .discardAllEdits();
192: }
193: }
194: layerManagerProxy.getLayerManager().getUndoableEditReceiver()
195: .receive(command.toUndoableEdit());
196: }
197:
198: public String toString() {
199: return getName();
200: }
201:
202: /**
203: * Indicates that this plug-in either (1) is undoable but hasn't modified
204: * the system yet or (2) does not modify the system. In either case, the
205: * undo history will be preserved. If this method is not called, then this
206: * plug-in will be assumed to be non-undoable, and the undo history will be
207: * truncated.
208: */
209: protected void reportNothingToUndoYet(PlugInContext context) {
210: //The LayerManager can be null if for example there are no TaskFrames
211: // and
212: //the user selects File / New Task. When we get to this point,
213: // LayerManager
214: //will be null. [Jon Aquino]
215: if (context.getLayerManager() == null) {
216: return;
217: }
218: context.getLayerManager().getUndoableEditReceiver()
219: .reportNothingToUndoYet();
220: }
221:
222: protected boolean isRollingBackInvalidEdits(PlugInContext context) {
223: return context.getWorkbenchContext().getWorkbench()
224: .getBlackboard().get(
225: EditTransaction.ROLLING_BACK_INVALID_EDITS_KEY,
226: false);
227: }
228: }
|