// License: GPL. For details, see LICENSE file.
package pdfimport;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Properties;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.gui.SideButton;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.preferences.projection.ProjectionChoice;
import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.gui.progress.ProgressRenderer;
import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor;
import org.openstreetmap.josm.io.OsmExporter;
import org.openstreetmap.josm.tools.ImageProvider;
import org.openstreetmap.josm.tools.WindowGeometry;
import pdfimport.pdfbox.PdfBoxParser;
public class LoadPdfDialog extends JFrame {
class LoadProgressRenderer implements ProgressRenderer {
private final JProgressBar pBar;
private String title = "";
LoadProgressRenderer(JProgressBar pb) {
this.pBar = pb;
this.pBar.setMinimum(0);
this.pBar.setValue(0);
this.pBar.setMaximum(1);
this.pBar.setString("");
this.pBar.setStringPainted(true);
}
@Override
public void setCustomText(String message) {
this.pBar.setString(this.title + message);
}
@Override
public void setIndeterminate(boolean indeterminate) {
this.pBar.setIndeterminate(indeterminate);
}
@Override
public void setMaximum(int maximum) {
this.pBar.setMaximum(maximum);
}
@Override
public void setTaskTitle(String taskTitle) {
this.title = taskTitle;
this.pBar.setString(this.title);
}
@Override
public void setValue(int value) {
this.pBar.setValue(value);
}
public void finish() {
this.pBar.setString(tr("Finished"));
this.pBar.setValue(this.pBar.getMaximum());
}
}
private File fileName;
private PathOptimizer data;
private OsmDataLayer layer;
/**
* Combobox with all projections available
*/
private JComboBox<ProjectionChoice> projectionCombo;
private JButton projectionPreferencesButton;
private JTextField minXField;
private JTextField minYField;
private JTextField minEastField;
private JTextField minNorthField;
private JButton getMinButton;
private JButton okButton;
private JButton cancelButton;
private JButton getMaxButton;
private JTextField maxNorthField;
private JTextField maxEastField;
private JTextField maxYField;
private JTextField maxXField;
private JButton loadFileButton;
private JButton showButton;
private JButton saveButton;
private JCheckBox debugModeCheck;
private JCheckBox mergeCloseNodesCheck;
private JTextField mergeCloseNodesTolerance;
private JCheckBox removeSmallObjectsCheck;
private JTextField removeSmallObjectsSize;
private JTextField colorFilterColor;
private JCheckBox colorFilterCheck;
private JCheckBox removeParallelSegmentsCheck;
private JTextField removeParallelSegmentsTolerance;
private JCheckBox removeLargeObjectsCheck;
private JTextField removeLargeObjectsSize;
private JProgressBar loadProgress;
protected OsmDataLayer newLayer;
private LoadProgressRenderer progressRenderer;
private JCheckBox limitPathCountCheck;
private JTextField limitPathCount;
private JCheckBox splitOnColorChangeCheck;
private JCheckBox splitOnShapeClosedCheck;
private JCheckBox splitOnSingleSegmentCheck;
private JCheckBox splitOnOrthogonalCheck;
public LoadPdfDialog() {
this.buildGUI();
FilePlacement pl = new FilePlacement();
this.setPlacement(pl);
this.addListeners();
this.removeLayer();
}
private void addListeners() {
this.projectionCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateProjectionPrefButton();
}
});
this.projectionPreferencesButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showProjectionPreferences();
}
});
this.loadFileButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loadFilePressed();
}
});
this.okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
okPressed();
}
});
this.saveButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
savePressed();
}
});
this.showButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showPressed();
}
});
this.cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cancelPressed();
}
});
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
cancelPressed();
}
});
this.getMinButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getMinPressed();
}
});
this.getMaxButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getMaxPressed();
}
});
}
private void buildGUI() {
GridBagConstraints c = new GridBagConstraints();
c.gridheight = 1; c.gridwidth = 1; c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.BOTH;
this.projectionCombo = new JComboBox<>();
for (ProjectionChoice p: ProjectionPreference.getProjectionChoices()) {
this.projectionCombo.addItem(p);
}
this.projectionPreferencesButton = new JButton(tr("Prefs"));
updateProjectionPrefButton();
this.loadFileButton = new JButton(tr("Load file..."));
this.okButton = new JButton(tr("Place"));
this.saveButton = new JButton(tr("Save"));
this.showButton = new JButton(tr("Show target"));
this.cancelButton = new JButton(tr("Discard"));
this.loadProgress = new JProgressBar();
this.progressRenderer = new LoadProgressRenderer(this.loadProgress);
this.minXField = new JTextField("");
this.minYField = new JTextField("");
this.minEastField = new JTextField("");
this.minNorthField = new JTextField("");
this.getMinButton = new JButton(tr("Take X and Y from selected node"));
this.maxXField = new JTextField("");
this.maxYField = new JTextField("");
this.maxEastField = new JTextField("");
this.maxNorthField = new JTextField("");
this.getMaxButton = new JButton(tr("Take X and Y from selected node"));
this.debugModeCheck = new JCheckBox(tr("Debug info"));
this.mergeCloseNodesCheck = new JCheckBox(tr("Merge close nodes"));
this.mergeCloseNodesTolerance = new JTextField("1e-3");
this.removeSmallObjectsCheck = new JCheckBox(tr("Remove objects smaller than"));
this.removeSmallObjectsSize = new JTextField("1");
this.removeLargeObjectsCheck = new JCheckBox(tr("Remove objects larger than"));
this.removeLargeObjectsSize = new JTextField("10");
this.colorFilterCheck = new JCheckBox(tr("Only this color"));
this.colorFilterColor = new JTextField("#000000");
this.removeParallelSegmentsCheck = new JCheckBox(tr("Remove parallel lines"));
this.removeParallelSegmentsTolerance = new JTextField("3");
this.limitPathCountCheck = new JCheckBox(tr("Take only first X paths"));
this.limitPathCount = new JTextField("10000");
this.splitOnColorChangeCheck = new JCheckBox(tr("Color/width change"));
this.splitOnShapeClosedCheck = new JCheckBox(tr("Shape closed"));
this.splitOnSingleSegmentCheck = new JCheckBox(tr("Single segments"));
this.splitOnOrthogonalCheck = new JCheckBox(tr("Orthogonal shapes"));
JPanel configPanel = new JPanel(new GridBagLayout());
configPanel.setBorder(BorderFactory.createTitledBorder(tr("Import settings")));
c.gridx = 0; c.gridy = 0; c.gridwidth = 1;
configPanel.add(this.mergeCloseNodesCheck, c);
c.gridx = 1; c.gridy = 0; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHEAST;
configPanel.add(new JLabel("Tolerance :"), c);
c.gridx = 2; c.gridy = 0; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHWEST;
configPanel.add(this.mergeCloseNodesTolerance, c);
c.gridx = 0; c.gridy = 1; c.gridwidth = 1;
configPanel.add(this.removeSmallObjectsCheck, c);
c.gridx = 1; c.gridy = 1; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHEAST;
configPanel.add(new JLabel("Tolerance :"), c);
c.gridx = 2; c.gridy = 1; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHWEST;
configPanel.add(this.removeSmallObjectsSize, c);
c.gridx = 0; c.gridy = 2; c.gridwidth = 1;
configPanel.add(this.removeLargeObjectsCheck, c);
c.gridx = 1; c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHEAST;
configPanel.add(new JLabel("Tolerance :"), c);
c.gridx = 2; c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHWEST;
configPanel.add(this.removeLargeObjectsSize, c);
c.gridx = 0; c.gridy = 3; c.gridwidth = 1;
configPanel.add(this.removeParallelSegmentsCheck, c);
c.gridx = 1; c.gridy = 3; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHEAST;
configPanel.add(new JLabel("Max distance :"), c);
c.gridx = 2; c.gridy = 3; c.gridwidth = 1; c.anchor = GridBagConstraints.NORTHWEST;
configPanel.add(this.removeParallelSegmentsTolerance, c);
c.gridx = 0; c.gridy = 4; c.gridwidth = 2;
configPanel.add(this.limitPathCountCheck, c);
c.gridx = 2; c.gridy = 4; c.gridwidth = 1;
configPanel.add(this.limitPathCount, c);
c.gridx = 0; c.gridy = 5; c.gridwidth = 1;
configPanel.add(this.colorFilterCheck, c);
c.gridx = 2; c.gridy = 5; c.gridwidth = 1;
configPanel.add(this.colorFilterColor, c);
c.gridx = 0; c.gridy = 6; c.gridwidth = 2;
configPanel.add(this.debugModeCheck, c);
c.gridx = 0; c.gridy = 7; c.gridwidth = 1;
configPanel.add(new JLabel(tr("Introduce separate layers for:")), c);
c.gridx = 1; c.gridy = 7; c.gridwidth = 1;
configPanel.add(this.splitOnShapeClosedCheck, c);
c.gridx = 2; c.gridy = 7; c.gridwidth = 1;
configPanel.add(this.splitOnSingleSegmentCheck, c);
c.gridx = 1; c.gridy = 8; c.gridwidth = 1;
configPanel.add(this.splitOnColorChangeCheck, c);
c.gridx = 2; c.gridy = 8; c.gridwidth = 1;
configPanel.add(this.splitOnOrthogonalCheck, c);
JPanel projectionPanel = new JPanel(new GridBagLayout());
projectionPanel.setBorder(BorderFactory.createTitledBorder(tr("Bind to coordinates")));
JPanel projectionSubPanel = new JPanel();
projectionSubPanel.setLayout(new BoxLayout(projectionSubPanel, BoxLayout.X_AXIS));
projectionSubPanel.add(new JLabel(tr("Projection:")));
projectionSubPanel.add(this.projectionCombo);
projectionSubPanel.add(this.projectionPreferencesButton);
c.gridx = 0; c.gridy = 0; c.gridwidth = 3;
projectionPanel.add(projectionSubPanel, c);
c.gridx = 0; c.gridy = 1; c.gridwidth = 2;
projectionPanel.add(new JLabel(tr("Bottom left (min) corner:")), c);
c.gridx = 0; c.gridy = 2; c.gridwidth = 1;
projectionPanel.add(new JLabel(tr("PDF X and Y")), c);
c.gridx = 1; c.gridy = 2; c.gridwidth = 1;
projectionPanel.add(new JLabel(tr("East and North")), c);
c.gridx = 0; c.gridy = 3; c.gridwidth = 1;
projectionPanel.add(this.minXField, c);
c.gridx = 0; c.gridy = 4; c.gridwidth = 1;
projectionPanel.add(this.minYField, c);
c.gridx = 1; c.gridy = 3; c.gridwidth = 1;
projectionPanel.add(this.minEastField, c);
c.gridx = 1; c.gridy = 4; c.gridwidth = 1;
projectionPanel.add(this.minNorthField, c);
c.gridx = 0; c.gridy = 5; c.gridwidth = 1;
projectionPanel.add(this.getMinButton, c);
c.gridx = 0; c.gridy = 6; c.gridwidth = 2;
projectionPanel.add(new JLabel(tr("Top right (max) corner:")), c);
c.gridx = 0; c.gridy = 7; c.gridwidth = 1;
projectionPanel.add(new JLabel(tr("PDF X and Y")), c);
c.gridx = 1; c.gridy = 7; c.gridwidth = 1;
projectionPanel.add(new JLabel(tr("East and North")), c);
c.gridx = 0; c.gridy = 8; c.gridwidth = 1;
projectionPanel.add(this.maxXField, c);
c.gridx = 0; c.gridy = 9; c.gridwidth = 1;
projectionPanel.add(this.maxYField, c);
c.gridx = 1; c.gridy = 8; c.gridwidth = 1;
projectionPanel.add(this.maxEastField, c);
c.gridx = 1; c.gridy = 9; c.gridwidth = 1;
projectionPanel.add(this.maxNorthField, c);
c.gridx = 0; c.gridy = 10; c.gridwidth = 1;
projectionPanel.add(this.getMaxButton, c);
JPanel okCancelPanel = new JPanel(new GridLayout(1, 3));
okCancelPanel.add(this.cancelButton);
okCancelPanel.add(this.showButton);
okCancelPanel.add(this.okButton);
okCancelPanel.add(this.saveButton);
JPanel panel = new JPanel(new GridBagLayout());
c.gridx = 0; c.gridy = 0; c.gridwidth = 1;
panel.add(configPanel, c);
c.gridx = 0; c.gridy = 1; c.gridwidth = 1;
panel.add(loadFileButton, c);
c.gridx = 0; c.gridy = 2; c.gridwidth = 1;
panel.add(projectionPanel, c);
c.gridx = 0; c.gridy = 3; c.gridwidth = 1;
panel.add(okCancelPanel, c);
c.gridx = 0; c.gridy = 4; c.gridwidth = 1;
panel.add(this.loadProgress, c);
this.setSize(450, 550);
this.setContentPane(panel);
}
private class ProjectionSubPrefsDialog extends JDialog {
private final ProjectionChoice projPref;
private OKAction actOK;
private CancelAction actCancel;
private JPanel projPrefPanel;
ProjectionSubPrefsDialog(Component parent, ProjectionChoice pr) {
super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
projPref = pr;
setTitle(tr("Projection Preferences"));
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
build();
}
protected void makeButtonRespondToEnter(SideButton btn) {
btn.setFocusable(true);
btn.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter");
btn.getActionMap().put("enter", btn.getAction());
}
protected JPanel buildInputForm() {
return projPref.getPreferencePanel(null);
}
protected JPanel buildButtonRow() {
JPanel pnl = new JPanel(new FlowLayout());
actOK = new OKAction();
actCancel = new CancelAction();
SideButton btn;
pnl.add(btn = new SideButton(actOK));
makeButtonRespondToEnter(btn);
pnl.add(btn = new SideButton(actCancel));
makeButtonRespondToEnter(btn);
return pnl;
}
protected void build() {
projPrefPanel = buildInputForm();
getContentPane().setLayout(new BorderLayout());
getContentPane().add(projPrefPanel, BorderLayout.CENTER);
getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
pack();
// make dialog respond to ESCAPE
getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
getRootPane().getActionMap().put("escape", actCancel);
}
class OKAction extends AbstractAction {
OKAction() {
putValue(NAME, tr("OK"));
putValue(SHORT_DESCRIPTION, tr("Close the dialog and apply projection preferences"));
putValue(SMALL_ICON, ImageProvider.get("ok"));
}
@Override
public void actionPerformed(ActionEvent e) {
projPref.setPreferences(projPref.getPreferences(projPrefPanel));
setVisible(false);
}
}
class CancelAction extends AbstractAction {
CancelAction() {
putValue(NAME, tr("Cancel"));
putValue(SHORT_DESCRIPTION, tr("Close the dialog, discard projection preference changes"));
putValue(SMALL_ICON, ImageProvider.get("cancel"));
}
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
}
@Override
public void setVisible(boolean visible) {
if (visible) {
new WindowGeometry(
getClass().getName() + ".geometry",
WindowGeometry.centerOnScreen(new Dimension(400, 300))).applySafe(this);
} else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
new WindowGeometry(this).remember(getClass().getName() + ".geometry");
}
super.setVisible(visible);
}
}
private void updateProjectionPrefButton() {
// ProjectionChoice proj = (ProjectionChoice) projectionCombo.getSelectedItem();
//TODO
// Enable/disable pref button
// if(!(proj instanceof ProjectionSubPrefs)) {
// projectionPreferencesButton.setEnabled(false);
// } else {
projectionPreferencesButton.setEnabled(true);
// }
}
private void showProjectionPreferences() {
ProjectionChoice proj = (ProjectionChoice) projectionCombo.getSelectedItem();
ProjectionSubPrefsDialog dlg = new ProjectionSubPrefsDialog(this, proj);
dlg.setVisible(true);
}
private void loadFilePressed() {
final File newFileName = this.chooseFile();
if (newFileName == null) {
return;
}
this.removeLayer();
this.loadFileButton.setEnabled(false);
this.loadFileButton.setText(tr("Loading..."));
this.runAsBackgroundTask(
new Runnable() {
@Override
public void run() {
//async part
SwingRenderingProgressMonitor monitor = new SwingRenderingProgressMonitor(progressRenderer);
monitor.beginTask("Loading file", 1000);
data = loadPDF(newFileName, monitor.createSubTaskMonitor(500, false));
OsmBuilder.Mode mode = LoadPdfDialog.this.debugModeCheck.isSelected() ? OsmBuilder.Mode.Debug : OsmBuilder.Mode.Draft;
if (data != null) {
LoadPdfDialog.this.newLayer = LoadPdfDialog.this.makeLayer(
tr("PDF file preview"), new FilePlacement(), mode, monitor.createSubTaskMonitor(500, false));
}
monitor.finishTask();
progressRenderer.finish();
}
},
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//sync part
if (data != null) {
LoadPdfDialog.this.placeLayer(newLayer, new FilePlacement());
fileName = newFileName;
newLayer = null;
LoadPdfDialog.this.loadFileButton.setText(tr("Loaded"));
LoadPdfDialog.this.loadFileButton.setEnabled(true);
FilePlacement placement = LoadPdfDialog.this.loadPlacement();
LoadPdfDialog.this.setPlacement(placement);
}
}
});
}
private FilePlacement preparePlacement() {
FilePlacement placement = this.parsePlacement();
if (placement == null) {
return null;
}
String transformError = placement.prepareTransform();
if (transformError != null) {
JOptionPane.showMessageDialog(Main.parent, transformError);
return null;
}
this.savePlacement(placement);
return placement;
}
private void okPressed() {
final FilePlacement placement = preparePlacement();
if (placement == null) {
return;
}
this.removeLayer();
this.runAsBackgroundTask(
new Runnable() {
@Override
public void run() {
//async part
SwingRenderingProgressMonitor monitor = new SwingRenderingProgressMonitor(progressRenderer);
LoadPdfDialog.this.newLayer = LoadPdfDialog.this.makeLayer(
tr("Imported PDF: ") + fileName, placement, OsmBuilder.Mode.Final, monitor);
progressRenderer.finish();
}
},
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//sync part
//rebuild layer with latest projection
LoadPdfDialog.this.placeLayer(newLayer, placement);
LoadPdfDialog.this.setVisible(false);
}
});
}
private void savePressed() {
final FilePlacement placement = preparePlacement();
if (placement == null) {
return;
}
final java.io.File file = this.chooseSaveFile();
if (file == null) {
return;
}
this.removeLayer();
this.runAsBackgroundTask(
new Runnable() {
@Override
public void run() {
//async part
SwingRenderingProgressMonitor monitor = new SwingRenderingProgressMonitor(progressRenderer);
LoadPdfDialog.this.saveLayer(file, placement, monitor);
progressRenderer.finish();
}
},
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//sync part
LoadPdfDialog.this.setVisible(false);
}
});
}
private void showPressed() {
FilePlacement placement = preparePlacement();
if (placement == null) {
return;
}
//zoom to new location
Main.map.mapView.zoomTo(placement.getWorldBounds(this.data));
Main.map.repaint();
}
private void cancelPressed() {
this.removeLayer();
this.setVisible(false);
}
private void getMinPressed() {
EastNorth en = this.getSelectedCoor();
if (en != null) {
this.minXField.setText(Double.toString(en.east()));
this.minYField.setText(Double.toString(en.north()));
}
}
private void getMaxPressed() {
EastNorth en = this.getSelectedCoor();
if (en != null) {
this.maxXField.setText(Double.toString(en.east()));
this.maxYField.setText(Double.toString(en.north()));
}
}
// Implementation methods
private EastNorth getSelectedCoor() {
Collection<OsmPrimitive> selected = Main.getLayerManager().getEditDataSet().getSelected();
if (selected.size() != 1 || !(selected.iterator().next() instanceof Node)) {
JOptionPane.showMessageDialog(Main.parent, tr("Please select exactly one node."));
return null;
}
LatLon ll = ((Node) selected.iterator().next()).getCoor();
FilePlacement pl = new FilePlacement();
return pl.reverseTransform(ll);
}
private java.io.File chooseFile() {
//get file name
JFileChooser fc = new JFileChooser();
fc.setAcceptAllFileFilterUsed(false);
fc.setMultiSelectionEnabled(false);
fc.setSelectedFile(this.fileName);
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(java.io.File pathname) {
return pathname.isDirectory() || pathname.getName().endsWith(".pdf");
}
@Override
public String getDescription() {
return tr("PDF files");
}
});
int result = fc.showOpenDialog(Main.parent);
if (result != JFileChooser.APPROVE_OPTION) {
return null;
} else {
return fc.getSelectedFile();
}
}
private java.io.File chooseSaveFile() {
//get file name
JFileChooser fc = new JFileChooser();
fc.setAcceptAllFileFilterUsed(true);
fc.setMultiSelectionEnabled(false);
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(java.io.File pathname) {
return pathname.isDirectory() || pathname.getName().endsWith(".osm");
}
@Override
public String getDescription() {
return tr("OSM files");
}
});
int result = fc.showOpenDialog(Main.parent);
if (result != JFileChooser.APPROVE_OPTION) {
return null;
} else {
return fc.getSelectedFile();
}
}
private void runAsBackgroundTask(final Runnable task, final ActionListener after) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Thread t = new Thread(new Runnable() {
@Override
public void run() {
task.run();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
after.actionPerformed(null);
}
});
}
});
t.start();
}
private PathOptimizer loadPDF(File fileName, ProgressMonitor monitor) {
monitor.beginTask("", 100);
monitor.setTicks(0);
monitor.setCustomText(tr("Preparing"));
double nodesTolerance = 0.0;
Color color = null;
int maxPaths = Integer.MAX_VALUE;
if (this.mergeCloseNodesCheck.isSelected()) {
try {
nodesTolerance = Double.parseDouble(this.mergeCloseNodesTolerance.getText());
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Tolerance is not a number"));
return null;
}
}
if (this.colorFilterCheck.isSelected()) {
try {
String colString = this.colorFilterColor.getText().replace("#", "");
color = new Color(Integer.parseInt(colString, 16));
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Could not parse color"));
return null;
}
}
if (this.limitPathCountCheck.isSelected()) {
try {
maxPaths = Integer.parseInt(this.limitPathCount.getText());
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Could not parse max path count"));
return null;
}
}
monitor.setTicks(10);
monitor.setCustomText(tr("Parsing file"));
PathOptimizer data = new PathOptimizer(nodesTolerance, color, this.splitOnColorChangeCheck.isSelected());
try {
PdfBoxParser parser = new PdfBoxParser(data);
parser.parse(fileName, maxPaths, monitor.createSubTaskMonitor(80, false));
} catch (FileNotFoundException e1) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("File not found."));
return null;
} catch (Exception e) {
e.printStackTrace();
JOptionPane
.showMessageDialog(
Main.parent,
tr("Error while parsing: {0}", e.getMessage()));
return null;
}
monitor.setTicks(80);
if (this.removeParallelSegmentsCheck.isSelected()) {
try {
double tolerance = Double.parseDouble(this.removeParallelSegmentsTolerance.getText());
monitor.setCustomText(tr("Removing parallel segments"));
data.removeParallelLines(tolerance);
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Max distance is not a number"));
return null;
}
}
if (nodesTolerance > 0.0) {
monitor.setTicks(83);
monitor.setCustomText(tr("Joining nodes"));
data.mergeNodes();
}
monitor.setTicks(85);
monitor.setCustomText(tr("Joining adjacent segments"));
data.mergeSegments();
if (this.removeSmallObjectsCheck.isSelected()) {
try {
double tolerance = Double.parseDouble(this.removeSmallObjectsSize.getText());
monitor.setTicks(90);
monitor.setCustomText(tr("Removing small objects"));
data.removeSmallObjects(tolerance);
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Tolerance is not a number"));
return null;
}
}
if (this.removeLargeObjectsCheck.isSelected()) {
try {
double tolerance = Double.parseDouble(this.removeLargeObjectsSize.getText());
monitor.setTicks(90);
monitor.setCustomText(tr("Removing large objects"));
data.removeLargeObjects(tolerance);
} catch (Exception e) {
JOptionPane
.showMessageDialog(
Main.parent,
tr("Tolerance is not a number"));
return null;
}
}
monitor.setTicks(95);
monitor.setCustomText(tr("Finalizing layers"));
data.splitLayersByPathKind(
this.splitOnShapeClosedCheck.isSelected(),
this.splitOnSingleSegmentCheck.isSelected(),
this.splitOnOrthogonalCheck.isSelected());
data.finish();
monitor.finishTask();
return data;
}
private FilePlacement parsePlacement() {
ProjectionChoice selectedProjection = (ProjectionChoice) this.projectionCombo.getSelectedItem();
if (selectedProjection == null) {
JOptionPane.showMessageDialog(Main.parent, tr("Please set a projection."));
return null;
}
FilePlacement placement = new FilePlacement();
placement.projection = selectedProjection.getProjection();
try {
placement.setPdfBounds(
Double.parseDouble(this.minXField.getText()),
Double.parseDouble(this.minYField.getText()),
Double.parseDouble(this.maxXField.getText()),
Double.parseDouble(this.maxYField.getText()));
placement.setEastNorthBounds(
Double.parseDouble(this.minEastField.getText()),
Double.parseDouble(this.minNorthField.getText()),
Double.parseDouble(this.maxEastField.getText()),
Double.parseDouble(this.maxNorthField.getText()));
} catch (Exception e) {
JOptionPane.showMessageDialog(Main.parent, tr("Could not parse numbers. Please check."));
return null;
}
return placement;
}
private void setPlacement(FilePlacement placement) {
if (placement == null) {
//use default values.
placement = new FilePlacement();
}
if (placement.projection != null) {
String projectionCode = placement.projection.toCode();
BIG_LOOP:
for (ProjectionChoice projectionChoice: ProjectionPreference.getProjectionChoices()) {
for (String code: projectionChoice.allCodes()) {
if (code.equals(projectionCode)) {
projectionChoice.getPreferencesFromCode(projectionCode);
this.projectionCombo.setSelectedItem(projectionChoice);
break BIG_LOOP;
}
}
}
}
this.minXField.setText(Double.toString(placement.minX));
this.maxXField.setText(Double.toString(placement.maxX));
this.minYField.setText(Double.toString(placement.minY));
this.maxYField.setText(Double.toString(placement.maxY));
this.minEastField.setText(Double.toString(placement.minEast));
this.maxEastField.setText(Double.toString(placement.maxEast));
this.minNorthField.setText(Double.toString(placement.minNorth));
this.maxNorthField.setText(Double.toString(placement.maxNorth));
}
private FilePlacement loadPlacement() {
FilePlacement pl = null;
//load saved transformation
File propertiesFile = new File(fileName.getAbsoluteFile()+ ".placement");
try {
if (propertiesFile.exists()) {
pl = new FilePlacement();
Properties p = new Properties();
p.load(new FileInputStream(propertiesFile));
pl.fromProperties(p);
}
} catch (Exception e) {
pl = null;
e.printStackTrace();
}
return pl;
}
private void savePlacement(FilePlacement pl) {
//load saved transformation
File propertiesFile = new File(fileName.getAbsoluteFile()+ ".placement");
try {
Properties p = pl.toProperties();
p.store(new FileOutputStream(propertiesFile), "PDF file placement on OSM");
} catch (Exception e) {
e.printStackTrace();
}
}
private OsmDataLayer makeLayer(String name, FilePlacement placement, OsmBuilder.Mode mode, ProgressMonitor monitor) {
monitor.beginTask(tr("Building JOSM layer"), 100);
OsmBuilder builder = new OsmBuilder(placement);
DataSet data = builder.build(this.data.getLayers(), mode, monitor.createSubTaskMonitor(50, false));
monitor.setTicks(50);
monitor.setCustomText(tr("Postprocessing layer"));
OsmDataLayer result = new OsmDataLayer(data, name, null);
result.onPostLoadFromFile();
monitor.finishTask();
return result;
}
private void placeLayer(OsmDataLayer _layer, FilePlacement placement) {
this.removeLayer();
this.layer = _layer;
Main.getLayerManager().addLayer(this.layer);
Main.map.mapView.zoomTo(placement.getWorldBounds(this.data));
}
private void removeLayer() {
if (this.layer != null) {
Main.getLayerManager().removeLayer(this.layer);
this.layer.data.clear(); //saves memory
this.layer = null;
}
}
private void saveLayer(java.io.File file, FilePlacement placement, ProgressMonitor monitor) {
monitor.beginTask(tr("Saving to file."), 1000);
OsmBuilder builder = new OsmBuilder(placement);
DataSet data = builder.build(this.data.getLayers(), OsmBuilder.Mode.Final, monitor.createSubTaskMonitor(500, false));
OsmDataLayer layer = new OsmDataLayer(data, file.getName(), file);
monitor.setCustomText(tr(" Writing to file"));
monitor.setTicks(500);
OsmExporter exporter = new OsmExporter();
try {
exporter.exportData(file, layer);
} catch (IOException e) {
Main.error(e);
}
monitor.finishTask();
}
}