source: josm/trunk/src/org/openstreetmap/josm/io/GpxExporter.java@ 8426

Last change on this file since 8426 was 8426, checked in by Don-vip, 9 years ago

Accessibility - global use of JLabel.setLabelFor() + various fixes (javadoc, code style)

  • Property svn:eol-style set to native
File size: 13.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener;
9import java.awt.event.KeyAdapter;
10import java.awt.event.KeyEvent;
11import java.io.File;
12import java.io.IOException;
13import java.io.OutputStream;
14import java.text.MessageFormat;
15import java.util.Calendar;
16
17import javax.swing.JButton;
18import javax.swing.JCheckBox;
19import javax.swing.JLabel;
20import javax.swing.JList;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
23import javax.swing.JScrollPane;
24import javax.swing.ListSelectionModel;
25
26import org.openstreetmap.josm.Main;
27import org.openstreetmap.josm.data.gpx.GpxConstants;
28import org.openstreetmap.josm.data.gpx.GpxData;
29import org.openstreetmap.josm.data.osm.DataSet;
30import org.openstreetmap.josm.gui.ExtendedDialog;
31import org.openstreetmap.josm.gui.layer.GpxLayer;
32import org.openstreetmap.josm.gui.layer.Layer;
33import org.openstreetmap.josm.gui.layer.OsmDataLayer;
34import org.openstreetmap.josm.gui.widgets.JosmTextArea;
35import org.openstreetmap.josm.gui.widgets.JosmTextField;
36import org.openstreetmap.josm.tools.CheckParameterUtil;
37import org.openstreetmap.josm.tools.GBC;
38
39/**
40 * Exports data to a .gpx file. Data may be native GPX or OSM data which will be converted.
41 * @since 1949
42 */
43public class GpxExporter extends FileExporter implements GpxConstants {
44
45 private static final String GPL_WARNING = "<html><font color='red' size='-2'>"
46 + tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.") + "</html>";
47
48 /**
49 * Constructs a new {@code GpxExporter}.
50 */
51 public GpxExporter() {
52 super(GpxImporter.FILE_FILTER);
53 }
54
55 @Override
56 public boolean acceptFile(File pathname, Layer layer) {
57 if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
58 return false;
59 return super.acceptFile(pathname, layer);
60 }
61
62 @Override
63 public void exportData(File file, Layer layer) throws IOException {
64 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
65 if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
66 throw new IllegalArgumentException(MessageFormat.format("Expected instance of OsmDataLayer or GpxLayer. Got ''{0}''.", layer
67 .getClass().getName()));
68 CheckParameterUtil.ensureParameterNotNull(file, "file");
69
70 String fn = file.getPath();
71 if (fn.indexOf('.') == -1) {
72 fn += ".gpx";
73 file = new File(fn);
74 }
75
76 // open the dialog asking for options
77 JPanel p = new JPanel(new GridBagLayout());
78
79 GpxData gpxData;
80 // At this moment, we only need to know the attributes of the GpxData,
81 // conversion of OsmDataLayer (if needed) will be done after the dialog is closed.
82 if (layer instanceof GpxLayer) {
83 gpxData = ((GpxLayer) layer).data;
84 } else {
85 gpxData = new GpxData();
86 }
87
88 p.add(new JLabel(tr("GPS track description")), GBC.eol());
89 JosmTextArea desc = new JosmTextArea(3, 40);
90 desc.setWrapStyleWord(true);
91 desc.setLineWrap(true);
92 desc.setText(gpxData.getString(META_DESC));
93 p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
94
95 JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
96 p.add(author, GBC.eol());
97
98 JLabel nameLabel = new JLabel(tr("Real name"));
99 p.add(nameLabel, GBC.std().insets(10, 0, 5, 0));
100 JosmTextField authorName = new JosmTextField();
101 p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
102 nameLabel.setLabelFor(authorName);
103
104 JLabel emailLabel = new JLabel(tr("E-Mail"));
105 p.add(emailLabel, GBC.std().insets(10, 0, 5, 0));
106 JosmTextField email = new JosmTextField();
107 p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
108 emailLabel.setLabelFor(email);
109
110 JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
111 p.add(copyrightLabel, GBC.std().insets(10, 0, 5, 0));
112 JosmTextField copyright = new JosmTextField();
113 p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
114 copyrightLabel.setLabelFor(copyright);
115
116 JButton predefined = new JButton(tr("Predefined"));
117 p.add(predefined, GBC.eol().insets(5, 0, 0, 0));
118
119 JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
120 p.add(copyrightYearLabel, GBC.std().insets(10, 0, 5, 5));
121 JosmTextField copyrightYear = new JosmTextField("");
122 p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
123 copyrightYearLabel.setLabelFor(copyrightYear);
124
125 JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
126 p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15, 0, 0, 0));
127 addDependencies(gpxData, author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel,
128 copyrightLabel, copyrightYearLabel, warning);
129
130 p.add(new JLabel(tr("Keywords")), GBC.eol());
131 JosmTextField keywords = new JosmTextField();
132 keywords.setText(gpxData.getString(META_KEYWORDS));
133 p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
134
135 ExtendedDialog ed = new ExtendedDialog(Main.parent,
136 tr("Export options"),
137 new String[] { tr("Export and Save"), tr("Cancel") });
138 ed.setButtonIcons(new String[] { "exportgpx", "cancel" });
139 ed.setContent(p);
140 ed.showDialog();
141
142 if (ed.getValue() != 1) {
143 setCanceled(true);
144 return;
145 }
146 setCanceled(false);
147
148 Main.pref.put("lastAddAuthor", author.isSelected());
149 if (authorName.getText().length() != 0) {
150 Main.pref.put("lastAuthorName", authorName.getText());
151 }
152 if (copyright.getText().length() != 0) {
153 Main.pref.put("lastCopyright", copyright.getText());
154 }
155
156 if (layer instanceof OsmDataLayer) {
157 gpxData = ((OsmDataLayer) layer).toGpxData();
158 } else if (layer instanceof GpxLayer) {
159 gpxData = ((GpxLayer) layer).data;
160 } else {
161 gpxData = OsmDataLayer.toGpxData(getCurrentDataSet(), file);
162 }
163
164 // add author and copyright details to the gpx data
165 if (author.isSelected()) {
166 if (authorName.getText().length() > 0) {
167 gpxData.put(META_AUTHOR_NAME, authorName.getText());
168 gpxData.put(META_COPYRIGHT_AUTHOR, authorName.getText());
169 }
170 if (email.getText().length() > 0) {
171 gpxData.put(META_AUTHOR_EMAIL, email.getText());
172 }
173 if (copyright.getText().length() > 0) {
174 gpxData.put(META_COPYRIGHT_LICENSE, copyright.getText());
175 }
176 if (copyrightYear.getText().length() > 0) {
177 gpxData.put(META_COPYRIGHT_YEAR, copyrightYear.getText());
178 }
179 }
180
181 // add the description to the gpx data
182 if (desc.getText().length() > 0) {
183 gpxData.put(META_DESC, desc.getText());
184 }
185
186 // add keywords to the gpx data
187 if (keywords.getText().length() > 0) {
188 gpxData.put(META_KEYWORDS, keywords.getText());
189 }
190
191 try (OutputStream fo = Compression.getCompressedFileOutputStream(file)) {
192 new GpxWriter(fo).write(gpxData);
193 fo.flush();
194 } catch (IOException x) {
195 Main.error(x);
196 JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn, x.getMessage()),
197 tr("Error"), JOptionPane.ERROR_MESSAGE);
198 }
199 }
200
201 private static void enableCopyright(final GpxData data, final JosmTextField copyright, final JButton predefined,
202 final JosmTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel,
203 final JLabel warning, boolean enable) {
204 copyright.setEnabled(enable);
205 predefined.setEnabled(enable);
206 copyrightYear.setEnabled(enable);
207 copyrightLabel.setEnabled(enable);
208 copyrightYearLabel.setEnabled(enable);
209 warning.setText(enable ? GPL_WARNING : "<html><font size='-2'>&nbsp;</html");
210
211 if (enable) {
212 if (copyrightYear.getText().isEmpty()) {
213 String sCopyrightYear = data.getString(META_COPYRIGHT_YEAR);
214 if (sCopyrightYear == null) {
215 sCopyrightYear = Integer.toString(Calendar.getInstance().get(Calendar.YEAR));
216 }
217 copyrightYear.setText(sCopyrightYear);
218 }
219 if (copyright.getText().isEmpty()) {
220 String sCopyright = data.getString(META_COPYRIGHT_LICENSE);
221 if (sCopyright == null) {
222 sCopyright = Main.pref.get("lastCopyright", "https://creativecommons.org/licenses/by-sa/2.5");
223 }
224 copyright.setText(sCopyright);
225 copyright.setCaretPosition(0);
226 }
227 } else {
228 copyrightYear.setText("");
229 copyright.setText("");
230 }
231 }
232
233 /**
234 * Add all those listeners to handle the enable state of the fields.
235 */
236 private static void addDependencies(
237 final GpxData data,
238 final JCheckBox author,
239 final JosmTextField authorName,
240 final JosmTextField email,
241 final JosmTextField copyright,
242 final JButton predefined,
243 final JosmTextField copyrightYear,
244 final JLabel nameLabel,
245 final JLabel emailLabel,
246 final JLabel copyrightLabel,
247 final JLabel copyrightYearLabel,
248 final JLabel warning) {
249
250 ActionListener authorActionListener = new ActionListener(){
251 @Override
252 public void actionPerformed(ActionEvent e) {
253 boolean b = author.isSelected();
254 authorName.setEnabled(b);
255 email.setEnabled(b);
256 nameLabel.setEnabled(b);
257 emailLabel.setEnabled(b);
258 if (b) {
259 String sAuthorName = data.getString(META_AUTHOR_NAME);
260 if (sAuthorName == null) {
261 sAuthorName = Main.pref.get("lastAuthorName");
262 }
263 authorName.setText(sAuthorName);
264 String sEmail = data.getString(META_AUTHOR_EMAIL);
265 if (sEmail == null) {
266 sEmail = Main.pref.get("lastAuthorEmail");
267 }
268 email.setText(sEmail);
269 } else {
270 authorName.setText("");
271 email.setText("");
272 }
273 boolean isAuthorSet = authorName.getText().length() != 0;
274 GpxExporter.enableCopyright(data, copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && isAuthorSet);
275 }
276 };
277 author.addActionListener(authorActionListener);
278
279 KeyAdapter authorNameListener = new KeyAdapter(){
280 @Override public void keyReleased(KeyEvent e) {
281 boolean b = authorName.getText().length()!=0 && author.isSelected();
282 GpxExporter.enableCopyright(data, copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
283 }
284 };
285 authorName.addKeyListener(authorNameListener);
286
287 predefined.addActionListener(new ActionListener(){
288 @Override
289 public void actionPerformed(ActionEvent e) {
290 final String[] licenses = {
291 "Creative Commons By-SA",
292 "Open Database License (ODbL)",
293 "public domain",
294 "GNU Lesser Public License (LGPL)",
295 "BSD License (MIT/X11)"};
296 JList<String> l = new JList<>(licenses);
297 l.setVisibleRowCount(licenses.length);
298 l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
299 int answer = JOptionPane.showConfirmDialog(
300 Main.parent,
301 new JScrollPane(l),
302 tr("Choose a predefined license"),
303 JOptionPane.OK_CANCEL_OPTION,
304 JOptionPane.QUESTION_MESSAGE
305 );
306 if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
307 return;
308 final String[] urls = {
309 "https://creativecommons.org/licenses/by-sa/3.0",
310 "http://opendatacommons.org/licenses/odbl/1.0",
311 "public domain",
312 "https://www.gnu.org/copyleft/lesser.html",
313 "http://www.opensource.org/licenses/bsd-license.php"};
314 String license = "";
315 for (int i : l.getSelectedIndices()) {
316 if (i == 2) {
317 license = "public domain";
318 break;
319 }
320 license += license.isEmpty() ? urls[i] : ", "+urls[i];
321 }
322 copyright.setText(license);
323 copyright.setCaretPosition(0);
324 }
325 });
326
327 authorActionListener.actionPerformed(null);
328 authorNameListener.keyReleased(null);
329 }
330
331 /**
332 * Replies the current dataset
333 *
334 * @return the current dataset. null, if no current dataset exists
335 */
336 private DataSet getCurrentDataSet() {
337 return Main.main.getCurrentDataSet();
338 }
339}
Note: See TracBrowser for help on using the repository browser.