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.ui.export;
016:
017: import java.io.File;
018: import java.util.ArrayList;
019: import java.util.List;
020:
021: import net.refractions.udig.ui.internal.Messages;
022: import net.refractions.udig.ui.operations.IOp;
023:
024: import org.eclipse.core.runtime.IProgressMonitor;
025: import org.eclipse.jface.action.IStatusLineManager;
026: import org.eclipse.jface.dialogs.MessageDialog;
027: import org.eclipse.swt.SWT;
028: import org.eclipse.swt.widgets.Display;
029: import org.eclipse.swt.widgets.FileDialog;
030: import org.eclipse.ui.IEditorPart;
031: import org.eclipse.ui.IEditorSite;
032: import org.eclipse.ui.IWorkbench;
033: import org.eclipse.ui.IWorkbenchPage;
034: import org.eclipse.ui.IWorkbenchWindow;
035: import org.eclipse.ui.PlatformUI;
036:
037: /**
038: * Abstract class can be used to implement your ow "export to" opperations.
039: * <p>
040: * Based on ExportSLD by Jesse, contains ideas inspired by CIP.
041: * </p>
042: * <p>
043: * I hope this can involve into a general export tool,
044: * where the prompt
045: * @author Jesse
046: * @since 1.0.0
047: */
048: public class FileExportOperation implements IOp {
049:
050: /**
051: * Let the extention point perform any additional checks
052: * before bothering the users with a prompt.
053: * <p>
054: * The extention point lets you specify the exact interface (or class)
055: * required. This method returns <code>true</code>, but could be used
056: * to perform a more indepth check of say a Layer's Schema to pervent
057: * the export of a FeatureType with multiple Geometry attributes
058: * being exported as a Shapefile.
059: * </p>
060: * @param target Target to be considered for export
061: * @return <code>true</code> if non <code>null</code>, subclass can overrride with additional tests
062: */
063: public boolean canExport(Object target) {
064: return target != null;
065: }
066:
067: /**
068: * Subclass should override to actually do something.
069: *
070: * @param target
071: * @param file
072: * @param monitor
073: * @throws Exception
074: */
075: public void exportTo(Object target, File file,
076: IProgressMonitor monitor) throws Exception {
077: return;
078: }
079:
080: /**
081: * Prompt to use for title (example: "Export to")
082: *
083: * @param target
084: * @return Prompt (may be based on target), should be internationalized
085: */
086: public String prompt(Object target) {
087: return Messages.FileExportOperation_prompt;
088: }
089:
090: /**
091: * Defalt name for provided target.
092: * <p>
093: * Should make use of provided target's title if available.
094: * This will be combined with the first filter extention
095: * to form a valid filename.
096: * </p>
097: * @param target
098: * @return Default filename based on target, default is "new"
099: */
100: public String defaultName(Object target) {
101: return Messages.FileExportOperation_defaultName;
102: }
103:
104: /**
105: * Override as required (example "*.sld").
106: *
107: * @return filter, default "*.*"
108: */
109: public String[] getFilterExtentions() {
110: List<String> filters = new ArrayList<String>();
111: for (String extention : getExtentions()) {
112: filters.add("*." + extention); //$NON-NLS-1$
113: }
114: return filters.toArray(new String[filters.size()]);
115: }
116:
117: /**
118: * Called by getFilterExtentions (example "sld").
119: *
120: * @return filter, default "*"
121: */
122: public String[] getExtentions() {
123: return new String[] { "*" }; //$NON-NLS-1$
124: }
125:
126: /**
127: * Override as required (example "Style Layer Descriptor document").
128: * <p>
129: * Care should be taken to internationalization these.
130: * </p>
131: * @return Filter names, default "All Files"
132: */
133: public String[] getFilterNames() {
134: return new String[] { Messages.FileExportOperation_allFiles };
135: }
136:
137: /**
138: * Responsible for asking the user for a filename and calleding exporTo.
139: * <p>
140: * The following methods are used to control the process:
141: * <ul>
142: * <li>getFilterExtentions()
143: * <li>getFilterNames()
144: * <li>getPrompt(
145: */
146: protected class PromptAndExport implements Runnable {
147: Display display;
148: Object target;
149: IProgressMonitor monitor;
150:
151: // results of prompt
152: File file;
153:
154: /**
155: * @param display
156: * @param target
157: * @param monitor
158: */
159: public PromptAndExport(Display display, Object target,
160: IProgressMonitor monitor) {
161: this .display = display;
162: this .target = target;
163: this .monitor = monitor;
164: }
165:
166: /** Run with Display.asyncExec */
167: public void run() {
168: file = promptFile(display, target);
169: }
170:
171: /** @return File to export to or <code>null</code> to cancel */
172: File getFile() {
173: return file;
174: }
175: }
176:
177: /**
178: * Asks the users for a filename to export to ...
179: * <p>
180: * If the user asks for an existing filename they will be prompted to confirm that they do
181: * indeed wish to replace. If they press Yes the existing file will be removed so the
182: * opperation can repalce it, if they select false the they will be reprompted.
183: * </p>
184: * @param display Display used to prompt with
185: * @param target Target (may be used to figure out prompt)
186: * @return File or <code>null</code> to be used to export
187: */
188: public File promptFile(Display display, Object target) {
189: String name = defaultName(target);
190: String prompt = prompt(target);
191: FileDialog fileDialog = new FileDialog(
192: display.getActiveShell(), SWT.SAVE);
193:
194: fileDialog.setFilterExtensions(getFilterExtentions());
195: fileDialog.setFilterNames(getFilterNames());
196: fileDialog.setFileName(name + "." + getExtentions()[0]); //$NON-NLS-1$
197: fileDialog.setText(prompt);
198:
199: String path = fileDialog.open();
200: if (path == null) {
201: return null; // user canceled
202: }
203: File file = new File(path);
204: if (file.exists()) {
205: boolean replace = MessageDialog.openConfirm(display
206: .getActiveShell(), prompt, file.getAbsolutePath()
207: + " exists, do you want to replace?"); //$NON-NLS-1$
208: if (!replace) {
209: return null; // user canceled (we could reprompt?)
210: }
211: file.delete();
212: }
213: return file;
214: }
215:
216: /**
217: * This method is called in a non ui thread...
218: *
219: */
220: public void op(Display display, Object target,
221: IProgressMonitor monitor) throws Exception {
222: if (!canExport(target)) {
223: return; // should we log this? Or disable the op...
224: }
225: PromptAndExport prompt = new PromptAndExport(display, target,
226: monitor);
227: display.syncExec(prompt);
228: File file = prompt.getFile();
229: if (file == null) {
230: /*
231: * Means the user has canceled FileDialog
232: */
233: return;
234: }
235:
236: status(Messages.FileExportOperation_writingStatus + file);
237: exportTo(target, file, monitor);
238: status(Messages.FileExportOperation_finishStatus + file);
239: }
240:
241: /**
242: *
243: * @param msg Display msg on status bar (if possible)
244: */
245: public void status(final String msg) {
246: final IStatusLineManager statusBar = getStatusBar();
247: final Display display = Display.getCurrent();
248:
249: if (statusBar == null || display == null)
250: return;
251:
252: display.syncExec(new Runnable() {
253: public void run() {
254: statusBar.setMessage(msg);
255: }
256: });
257: }
258:
259: private IStatusLineManager getStatusBar() {
260: IEditorSite site = getEditorSite();
261: if (site == null)
262: return null;
263: return site.getActionBars().getStatusLineManager();
264: }
265:
266: private IEditorSite getEditorSite() {
267: IWorkbenchWindow window = getWindow();
268: if (window == null)
269: return null;
270: IWorkbenchPage page = window.getActivePage();
271: if (page == null)
272: return null;
273: IEditorPart part = page.getActiveEditor();
274: if (part == null)
275: return null;
276: return (IEditorSite) part.getSite();
277: }
278:
279: private IWorkbenchWindow getWindow() {
280: IWorkbench bench = PlatformUI.getWorkbench();
281: if (bench == null)
282: return null;
283: IWorkbenchWindow window = bench.getActiveWorkbenchWindow();
284: if (window == null) {
285: if (bench.getWorkbenchWindowCount() > 0)
286: window = bench.getWorkbenchWindows()[0];
287: }
288: return window;
289: }
290: }
|