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