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.internal.actions;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.util.ArrayList;
022: import java.util.HashMap;
023: import java.util.List;
024: import java.util.Map.Entry;
025:
026: import net.refractions.udig.project.ILayer;
027: import net.refractions.udig.project.IMap;
028: import net.refractions.udig.project.command.MapCommand;
029: import net.refractions.udig.project.command.UndoableMapCommand;
030: import net.refractions.udig.project.command.factory.EditCommandFactory;
031: import net.refractions.udig.project.internal.Layer;
032: import net.refractions.udig.project.internal.Project;
033: import net.refractions.udig.project.internal.ProjectElement;
034: import net.refractions.udig.project.internal.ProjectPlugin;
035: import net.refractions.udig.project.preferences.PreferenceConstants;
036: import net.refractions.udig.project.ui.ApplicationGIS;
037: import net.refractions.udig.project.ui.UDIGGenericAction;
038: import net.refractions.udig.project.ui.commands.DrawCommandFactory;
039: import net.refractions.udig.project.ui.commands.IDrawCommand;
040: import net.refractions.udig.project.ui.internal.ApplicationGISInternal;
041: import net.refractions.udig.project.ui.internal.Messages;
042: import net.refractions.udig.project.ui.internal.ProjectUIPlugin;
043: import net.refractions.udig.project.ui.internal.UDIGEditorInputDescriptor;
044: import net.refractions.udig.project.ui.render.displayAdapter.ViewportPane;
045: import net.refractions.udig.ui.PlatformGIS;
046:
047: import org.eclipse.core.runtime.IAdaptable;
048: import org.eclipse.core.runtime.Platform;
049: import org.eclipse.emf.ecore.resource.Resource;
050: import org.eclipse.emf.ecore.resource.ResourceSet;
051: import org.eclipse.jface.dialogs.MessageDialog;
052: import org.eclipse.jface.dialogs.MessageDialogWithToggle;
053: import org.eclipse.jface.window.Window;
054: import org.eclipse.swt.widgets.Display;
055: import org.eclipse.ui.IEditorPart;
056: import org.eclipse.ui.IWorkbenchPage;
057: import org.eclipse.ui.PlatformUI;
058: import org.geotools.feature.Feature;
059:
060: /**
061: * Deletes the selected elements from a project.
062: *
063: * @author jeichar
064: * @since 0.3
065: */
066: public class Delete extends UDIGGenericAction {
067:
068: /**
069: * Indicates where the user should be queried
070: */
071: private boolean headless = false;
072:
073: private boolean deleteAssumption = getDoDelete();
074:
075: /**
076: * Indicates whether to run the commands synchronously or not.
077: */
078: private boolean runSync = false;
079:
080: /**
081: * @see net.refractions.udig.project.ui.UDIGGenericAction#operate(net.refractions.udig.project.Layer)
082: */
083: protected void operate(Layer layer) {
084: if (layer == null || layer.getMap() == null)
085: return;
086:
087: UndoableMapCommand command = EditCommandFactory.getInstance()
088: .createDeleteLayers(new ILayer[] { layer });
089: // UndoableMapCommand command =
090: // EditCommandFactory.getInstance().createDeleteLayer((ILayer)layer);
091: executeCommand(command, layer.getMapInternal());
092: }
093:
094: /**
095: * @see net.refractions.udig.project.ui.UDIGGenericAction#operate(net.refractions.udig.project.internal.Layer[])
096: */
097: @Override
098: protected void operate(Layer[] layers) {
099:
100: if (layers != null && layers.length > 0) {
101: /*
102: * Layers can exist in different maps. For each map the standalone command should be
103: * used to remove only layers that are contained in this map.
104: */
105:
106: HashMap<IMap, List<Layer>> distributor = new HashMap<IMap, List<Layer>>();
107:
108: for (Layer layer : layers) {
109: IMap map = layer.getMap();
110:
111: if (distributor.containsKey(map)) {
112: distributor.get(map).add(layer);
113:
114: } else {
115: List<Layer> list = new ArrayList<Layer>();
116: list.add(layer);
117: distributor.put(map, list);
118: }
119: }
120: for (Entry<IMap, List<Layer>> entry : distributor
121: .entrySet()) {
122: IMap map = entry.getKey();
123: Layer[] removedLayers = entry.getValue().toArray(
124: new Layer[0]);
125: UndoableMapCommand command = EditCommandFactory
126: .getInstance()
127: .createDeleteLayers(removedLayers);
128: executeCommand(command, map);
129: }
130:
131: }
132: }
133:
134: void executeCommand(MapCommand command, IMap map) {
135: if (runSync) {
136: map.sendCommandSync(command);
137: } else {
138: map.sendCommandASync(command);
139: }
140: }
141:
142: /**
143: * @see net.refractions.udig.project.ui.UDIGGenericAction#operate(net.refractions.udig.project.IProjectElement)
144: */
145: protected void operate(ProjectElement element) {
146: if (element == null)
147: return;
148: boolean deleteFiles;
149: int returnCode;
150: if (headless) {
151: deleteFiles = deleteAssumption;
152: returnCode = Window.OK;
153: } else {
154:
155: MessageDialogWithToggle dialog = MessageDialogWithToggle
156: .openOkCancelConfirm(Display.getCurrent()
157: .getActiveShell(),
158: Messages.Delete_delete,
159: Messages.Delete_delete + " \"" //$NON-NLS-1$
160: + element.getName() + "\"?", //$NON-NLS-1$
161: Messages.Delete_filesystem, getDoDelete(),
162: null, null);
163: // note: we will do our own preference store persistence, since the built in one is
164: // backwards
165: deleteFiles = dialog.getToggleState();
166: returnCode = dialog.getReturnCode();
167: if (deleteFiles != getDoDelete()) {
168: setDoDelete(deleteFiles);
169: }
170: }
171: doDelete(element, deleteFiles, returnCode);
172: }
173:
174: protected final void doDelete(ProjectElement element,
175: boolean deleteFiles, int returncode) {
176: if (returncode != Window.CANCEL) {
177: for (UDIGEditorInputDescriptor desc : ApplicationGIS
178: .getEditorInputs(element.getClass())) {
179: IWorkbenchPage page = PlatformUI.getWorkbench()
180: .getActiveWorkbenchWindow().getActivePage();
181: IEditorPart editor = page.findEditor(desc
182: .createInput(element));
183: if (editor != null)
184: page.closeEditor(editor, false);
185: }
186: Project projectInternal = element.getProjectInternal();
187: if (projectInternal != null)
188: projectInternal.getElementsInternal().remove(element);
189: else {
190: Project project = findProject(element);
191: if (project != null)
192: project.getElementsInternal().remove(element);
193: }
194: Resource resource = element.eResource();
195: if (resource != null) {
196: resource.getContents().remove(element);
197: resource.unload();
198: }
199: if (deleteFiles) {
200: try {
201: String path = resource.getURI().toFileString();
202: resource.unload();
203: int lastIndexOf = path.lastIndexOf('/');
204: if (lastIndexOf == -1)
205: lastIndexOf = path.length();
206: path = path.substring(0, lastIndexOf);
207: final File file = new File(path);
208: deleteFile(file);
209: } catch (Exception e) {
210: ProjectUIPlugin.log(
211: "Error deleting project element file", e); //$NON-NLS-1$
212: }
213: }
214: }
215: }
216:
217: private Project findProject(ProjectElement element) {
218: List<? extends Project> projects = ApplicationGISInternal
219: .getProjects();
220: for (Project project : projects) {
221: if (project.getElements().contains(element))
222: return project;
223: }
224: return null;
225: }
226:
227: /**
228: * @see net.refractions.udig.project.ui.UDIGGenericAction#operate(net.refractions.udig.project.Project)
229: */
230: protected void operate(Project project) {
231: if (project == null)
232: return;
233:
234: boolean deleteProjectFiles;
235: int returnCode;
236: if (headless) {
237: deleteProjectFiles = deleteAssumption;
238: returnCode = Window.OK;
239: } else {
240:
241: MessageDialogWithToggle dialog = MessageDialogWithToggle
242: .openOkCancelConfirm(
243: Display.getCurrent().getActiveShell(),
244: Messages.Delete_deleteProject,
245: Messages.Delete_delete + " \"" //$NON-NLS-1$
246: + project.getName() + "\"?", //$NON-NLS-1$
247: Messages.Delete_filesystem, getDoDelete(),
248: null, null);
249: // note: we will do our own preference store persistence, since the built in one is
250: // backwards
251: deleteProjectFiles = dialog.getToggleState();
252: returnCode = dialog.getReturnCode();
253: if (deleteProjectFiles != getDoDelete()) {
254: setDoDelete(deleteProjectFiles);
255: }
256: }
257: doDelete(project, deleteProjectFiles, returnCode);
258: }
259:
260: protected final void doDelete(Project project,
261: boolean deleteProjectFiles, int returncode) {
262: if (returncode != Window.CANCEL) {
263: Resource resource = project.eResource();
264: if (!deleteProjectFiles) {
265: try {
266: resource.save(null);
267: resource.getContents().remove(project);
268: } catch (IOException e) {
269: ProjectUIPlugin.log(null, e);
270: }
271: }
272:
273: List<ProjectElement> toRemove = new ArrayList<ProjectElement>();
274: toRemove.addAll(project.getElementsInternal());
275: boolean oldHeadless = headless;
276: boolean oldrunSyn = runSync;
277:
278: headless = true;
279: this .runSync = true;
280: for (ProjectElement element : toRemove) {
281: operate(element);
282: }
283: headless = oldHeadless;
284: runSync = oldrunSyn;
285:
286: resource.setModified(false);
287: if (ApplicationGIS.getActiveProject() == project)
288: ProjectPlugin.getPlugin().getProjectRegistry()
289: .setCurrentProject(null);
290:
291: ProjectPlugin.getPlugin().getProjectRegistry()
292: .getProjects().remove(project);
293: resource.getContents().clear();
294: ResourceSet resourceSet = resource.getResourceSet();
295: String path = resource.getURI().toFileString();
296:
297: resource.unload();
298:
299: if (deleteProjectFiles) {
300: try {
301: resourceSet.getResources().remove(resource);
302: resource.unload();
303: int lastIndexOf = path.lastIndexOf('/');
304: if (lastIndexOf == -1)
305: lastIndexOf = path.length();
306: path = path.substring(0, lastIndexOf);
307: final File file = new File(path);
308: deleteFile(file);
309: } catch (Exception e) {
310: ProjectUIPlugin.log(
311: "Error deleting project file", e); //$NON-NLS-1$
312: }
313: }
314: }
315: }
316:
317: private void deleteFile(File file) {
318: if (!file.exists())
319: return;
320: if (file.isDirectory()) {
321: File[] files = file.listFiles();
322: for (File file2 : files) {
323: deleteFile(file2);
324: }
325: }
326:
327: file.delete();
328:
329: }
330:
331: /**
332: * @see net.refractions.udig.project.ui.UDIGGenericAction#operate(org.geotools.feature.Feature)
333: */
334: protected void operate(final Feature feature) {
335: IAdaptable adaptableFeature = null;
336: if (feature instanceof IAdaptable) {
337: adaptableFeature = (IAdaptable) feature;
338: }
339: if (adaptableFeature == null) {
340: adaptableFeature = (IAdaptable) Platform
341: .getAdapterManager().getAdapter(feature,
342: IAdaptable.class);
343: }
344: if (adaptableFeature == null)
345: return;
346:
347: final Layer layer = (Layer) adaptableFeature
348: .getAdapter(Layer.class);
349:
350: IDrawCommand command = DrawCommandFactory.getInstance()
351: .createDrawFeatureCommand(feature, layer);
352:
353: ViewportPane pane = (ViewportPane) layer.getMapInternal()
354: .getRenderManager().getMapDisplay();
355: pane.addDrawCommand(command);
356:
357: PlatformGIS.syncInDisplayThread(PlatformUI.getWorkbench()
358: .getDisplay(), new Runnable() {
359: public void run() {
360:
361: boolean result;
362: if (headless) {
363: result = getDoDelete();
364: } else {
365: result = MessageDialog.openConfirm(PlatformUI
366: .getWorkbench().getDisplay()
367: .getActiveShell(),
368: Messages.DeleteFeature_confirmation_title,
369: Messages.DeleteFeature_confirmation_text);
370: }
371:
372: if (result) {
373: UndoableMapCommand c = EditCommandFactory
374: .getInstance().createDeleteFeature(feature,
375: layer);
376: executeCommand(c, layer.getMap());
377: }
378: }
379: });
380: command.setValid(false);
381: pane.repaint();
382:
383: }
384:
385: /**
386: * Sets whether the methods should be ran headless or not. (IE whether the user should be
387: * asked).
388: *
389: * @param headless whether to query user
390: */
391: public void setRunHeadless(boolean headless) {
392: this .headless = headless;
393: }
394:
395: /**
396: * Sets whether the methods should be ran headless or not. (IE whether the user should be
397: * asked).
398: *
399: * @param headless whether to query user
400: * @param doDelete whether to delete the file if headless == true
401: */
402: public void setRunHeadless(boolean headless, boolean doDelete) {
403: this .headless = headless;
404: this .deleteAssumption = doDelete;
405: }
406:
407: /**
408: * Determines whether the command executions should happen synchronously or not.
409: *
410: * @param runSync
411: */
412: public void setRunSync(boolean runSync) {
413: this .runSync = runSync;
414: }
415:
416: private boolean getDoDelete() {
417: return ProjectPlugin.getPlugin().getPreferenceStore()
418: .getBoolean(PreferenceConstants.P_PROJECT_DELETE_FILES);
419: }
420:
421: private void setDoDelete(boolean deleteFiles) {
422: ProjectPlugin.getPlugin().getPreferenceStore()
423: .setValue(PreferenceConstants.P_PROJECT_DELETE_FILES,
424: deleteFiles);
425: }
426:
427: }
|