/*
* GeoExportGUI.java
*
* Created on March 22, 2007, 12:10 PM
*
*/
package ika.gui;
import ika.geo.GeoMap;
import ika.geo.GeoObject;
import ika.geo.GeoSet;
import ika.geoexport.*;
import ika.geoexport.VectorGraphicsExporter;
import ika.table.TableLink;
import ika.table.TableLinkExporter;
import ika.utils.ErrorDialog;
import ika.utils.FileUtils;
import java.awt.Component;
import java.awt.Frame;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
/**
* Utility class that handles the GUI for a GeoSetExporter.
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich.
*/
public class GeoExportGUI {
private GeoExportGUI() {
}
/**
* Exports map features to a file. The user is asked to select a file path to a
* new file. This is designed for vector data.
*
* @param exporter The GeoSetExporter to export the exporterMap. If null, the
* user is asked to select a GeoSetExporter from a list.
* @param geoSet The GeoSet to export.
* @param fileName A default file name without extension. If null, the name
* of the GeoSet is used.
* @param frame The Frame for which the dialog for selecting a file
* is displayed.
* @param pageFormat The page format for exporting to vector graphics formats
* (not georeferenced formats). If null and the exporter is a
* VectorGraphicsExporter, the page format of the exporter is used. If this
* is also null, a default page format is used that includes the whole GeoSet
* to export.
* @param askScale If true and if exporting to a vector graphics format (not
* a georeferenced GIS format), the user is asked for a scale that is
* applied to the data prior to export.
*/
public static void export(GeoSetExporter exporter,
GeoSet geoSet,
String fileName,
Frame frame,
PageFormat pageFormat,
boolean askScale) {
GeoExportGUI.export(exporter, geoSet, fileName, frame, pageFormat,
askScale, null, null, null, null, null, null);
}
/**
* Exports map features to a file. The user is asked to select a file path to a
* new file. This is designed for vector data.
*
* @param exporter The GeoSetExporter to export the exporterMap. If null, the
* user is asked to select a GeoSetExporter from a list.
* @param geoSet The GeoSet to export.
* @param fileName A default file name without extension. If null, the name
* of the GeoSet is used.
* @param frame The Frame for which the dialog for selecting a file
* is displayed.
* @param pageFormat The page format for exporting to vector graphics formats
* (not georeferenced formats). If null and the exporter is a
* VectorGraphicsExporter, the page format of the exporter is used. If this
* is also null, a default page format is used that includes the whole GeoSet
* to export.
* @param askScale If true and if exporting to a vector graphics format (not
* a georeferenced GIS format), the user is asked for a scale that is
* applied to the data prior to export.
*/
public static void export(GeoSetExporter exporter,
GeoSet geoSet,
String fileName,
Frame frame,
PageFormat pageFormat,
boolean askScale,
String applicationName,
String documentName,
String documentAuthor,
String documentSubject,
String documentKeyWords,
ProgressIndicator progressIndicator) {
try {
if (exporter == null) {
exporter = GeoExportGUI.askExporter(frame);
}
if (exporter == null) {
return; // user cancelled
}
// construct a message for the file selection dialog
exporter.setApplicationName(applicationName);
exporter.setDocumentName(documentName);
exporter.setDocumentAuthor(documentAuthor);
exporter.setDocumentSubject(documentSubject);
exporter.setDocumentKeyWords(documentKeyWords);
String msg = "Save " + exporter.getFileFormatName() + " File";
// construct a file name
if (fileName == null) {
fileName = geoSet.getName();
}
String ext = exporter.getFileExtension();
fileName = FileUtils.forceFileNameExtension(fileName, ext);
// ask the user for a file.
String filePath = FileUtils.askFile(frame, msg, fileName, false, ext);
if (filePath == null) {
return; // user canceled
}
// ask the user for a scale for graphics file formats if the exporter
// does not have a valid page format. Don't do this for georeferenced
// GIS export formats.
if (exporter instanceof VectorGraphicsExporter) {
VectorGraphicsExporter gExporter = (VectorGraphicsExporter) exporter;
if (pageFormat == null) {
pageFormat = gExporter.getPageFormat();
}
if (pageFormat == null) {
pageFormat = new PageFormat();
pageFormat.setAutomatic(true);
Rectangle2D box = geoSet.getBounds2D(GeoObject.UNDEFINED_SCALE);
pageFormat.setPageWorldCoordinates(box);
}
if (askScale) {
if (!GeoExportGUI.askScale(exporter, pageFormat, geoSet, frame)) {
return;
}
} else {
gExporter.setPageFormat(pageFormat);
}
} else if (exporter instanceof RasterImageExporter) {
String rasterSizeMsg = "Please enter the width of the image in pixels:";
String rasterTitle = "Image Width";
String widthStr = (String) JOptionPane.showInputDialog(frame, rasterSizeMsg, rasterTitle, JOptionPane.QUESTION_MESSAGE, null, null, new Integer(1000));
if (widthStr == null) {
return; // user canceled
}
try {
int width = (int) Double.parseDouble(widthStr);
((RasterImageExporter) exporter).setImageWidth(width);
} catch (NumberFormatException exc) {
ErrorDialog.showErrorDialog("Please enter a valid number for the image width.");
return;
}
}
if (progressIndicator == null) {
GeoExportGUI.export(exporter, geoSet, filePath, null);
} else {
new GeoExportTask(exporter, geoSet, filePath, progressIndicator).execute();
}
} catch (Exception e) {
// show an error message.
String msg = "The data could not be exported.";
ika.utils.ErrorDialog.showErrorDialog(msg, "Export Error", e, frame);
e.printStackTrace();
}
}
private static void export(GeoSetExporter exporter,
GeoSet geoSet,
String filePath,
ProgressIndicator progressIndicator) throws IOException {
// export the GeoSet to the file
if (progressIndicator != null) {
exporter.setProgressIndicator(progressIndicator);
progressIndicator.start();
}
exporter.export(geoSet, filePath);
// FIXME this is an ugly hack !!! ???
if (exporter instanceof TableLinkExporter) {
TableLinkExporter tableLinkExporter = (TableLinkExporter) exporter;
TableLink tableLink = null;
if (geoSet instanceof GeoMap && ((GeoMap) geoSet).tableLinkGetNumber() > 0) {
tableLink = ((GeoMap) geoSet).tableLinkGet(0); // !!! ???
} else {
ika.table.Table table = new ika.table.Table("US-ASCII");
table.setName("table");
table.addColumn("ID");
final int rowCount = tableLinkExporter.getFeatureCount();
for (int i = 0; i < rowCount; i++) {
table.addRow(new Object[]{new Double(i)});
}
tableLink = new TableLink(table, geoSet);
}
tableLinkExporter.exportTableForGeometry(filePath, tableLink);
}
}
/**
* Ask the user to select a scale for graphics file formats (not
* georeferenced GIS formats).
* @param exporter The export that will receive the selected scale.
* @param pageFormat A page format with the size, position and scale of the map.
* @param geoSet The data to export.
* @param frame The parent frame.
* @return False if the user cancels or if the passed exporter is not an
* instance of a VectorGraphicsExporter; true otherwise.
*/
public static boolean askScale(GeoSetExporter exporter, PageFormat pageFormat,
GeoSet geoSet, Frame frame) {
// only for graphics file formats
if (exporter instanceof VectorGraphicsExporter == false) {
return false;
}
SimplePageFormatDialog dlg = new SimplePageFormatDialog(frame, true, pageFormat);
//dlg.setMapObjectsBoundingBox(geoSet.getBounds2D(GeoObject.UNDEFINED_SCALE));
pageFormat = dlg.showDialog();
if (pageFormat == null) {
return false; // user cancelled
}
VectorGraphicsExporter vectorExporter = (VectorGraphicsExporter) exporter;
vectorExporter.setPageFormat(pageFormat);
return true;
}
private static final HashMap<String, Class> exporterMap;
private static final String[] orderedExporterNames;
private static final String[] exporterNames = {"SVG", "Illustrator", "PDF", "Shape", "DXF", "Ungenerate", "PNG", "JPEG"};
static {
exporterMap = new HashMap<String, Class>();
for (String exporterClassName : exporterNames) {
try {
Class exporterClass = Class.forName("ika.geoexport." + exporterClassName + "Exporter");
GeoExporter exporter = (GeoExporter) exporterClass.newInstance();
String exporterName = exporter.getFileFormatName();
exporterMap.put(exporterName, exporterClass);
} catch (Exception ex) {
Logger.getLogger(GeoExportGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
orderedExporterNames = exporterMap.keySet().toArray(new String[]{});
Arrays.sort(orderedExporterNames);
}
/**
* Ask the user to select an export file format.
* @return A GeoSetExporter selected by the user, or null if the user cancels.
*/
public static GeoSetExporter askExporter(Component parent) {
String exporterName = (String) JOptionPane.showInputDialog(parent,
"Export File Format",
"",
JOptionPane.QUESTION_MESSAGE, null,
orderedExporterNames, null);
if (exporterName == null) {
return null; // user canceled
}
Class cls = (Class) exporterMap.get(exporterName);
if (cls != null) {
try {
return (GeoSetExporter) cls.newInstance();
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
}
return null;
}
private static class GeoExportTask extends SwingWorker<GeoSet, Void>
implements PropertyChangeListener {
private ProgressIndicator progressIndicator;
private GeoSetExporter exporter;
private GeoSet geoSet;
private String filePath;
protected GeoExportTask(GeoSetExporter exporter,
GeoSet geoSet,
String filePath,
ProgressIndicator progressIndicator) {
this.progressIndicator = progressIndicator;
this.exporter = exporter;
this.geoSet = geoSet;
this.filePath = filePath;
this.addPropertyChangeListener(this);
}
/**
* Invoked when task's progress property changes. Update the value displayed
* by the progress monitor dialog and inform the task if the user presses
* the cancel button. This is called in the event dispatching thread.
*/
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = ((Integer) evt.getNewValue()).intValue();
System.out.println(progress);
this.progressIndicator.progress(progress);
if (this.progressIndicator.isAborted()) {
this.cancel(true);
}
}
}
protected GeoSet doInBackground() throws Exception {
try {
progressIndicator.start();
this.setProgress(0);
GeoExportGUI.export(exporter, geoSet, filePath, progressIndicator);
return null;
} catch (Exception e) {
e.printStackTrace();
// this will be executed in the event dispatching thread.
ika.utils.ErrorDialog.showErrorDialog("The file could not be exported.", e);
throw e;
} finally {
progressIndicator.complete();
}
}
}
}