source: josm/trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java@ 9543

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

refactoring - global simplification of use of setLayout method - simply pass layout to JPanel constructor

  • Property svn:eol-style set to native
File size: 26.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.BorderLayout;
9import java.awt.Component;
10import java.awt.Dimension;
11import java.awt.FlowLayout;
12import java.awt.GridBagLayout;
13import java.awt.event.ActionEvent;
14import java.awt.event.KeyEvent;
15import java.awt.event.WindowAdapter;
16import java.awt.event.WindowEvent;
17import java.beans.PropertyChangeEvent;
18import java.beans.PropertyChangeListener;
19import java.util.ArrayList;
20import java.util.Collection;
21import java.util.Collections;
22import java.util.HashMap;
23import java.util.Iterator;
24import java.util.List;
25import java.util.Map;
26import java.util.Map.Entry;
27
28import javax.swing.AbstractAction;
29import javax.swing.BorderFactory;
30import javax.swing.Icon;
31import javax.swing.JButton;
32import javax.swing.JComponent;
33import javax.swing.JOptionPane;
34import javax.swing.JPanel;
35import javax.swing.JTabbedPane;
36import javax.swing.KeyStroke;
37
38import org.openstreetmap.josm.Main;
39import org.openstreetmap.josm.data.APIDataSet;
40import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
41import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
42import org.openstreetmap.josm.data.Preferences.Setting;
43import org.openstreetmap.josm.data.Version;
44import org.openstreetmap.josm.data.osm.Changeset;
45import org.openstreetmap.josm.data.osm.DataSet;
46import org.openstreetmap.josm.data.osm.OsmPrimitive;
47import org.openstreetmap.josm.gui.ExtendedDialog;
48import org.openstreetmap.josm.gui.HelpAwareOptionPane;
49import org.openstreetmap.josm.gui.SideButton;
50import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
51import org.openstreetmap.josm.gui.help.HelpUtil;
52import org.openstreetmap.josm.io.OsmApi;
53import org.openstreetmap.josm.tools.GBC;
54import org.openstreetmap.josm.tools.ImageOverlay;
55import org.openstreetmap.josm.tools.ImageProvider;
56import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
57import org.openstreetmap.josm.tools.InputMapUtils;
58import org.openstreetmap.josm.tools.Utils;
59import org.openstreetmap.josm.tools.WindowGeometry;
60
61/**
62 * This is a dialog for entering upload options like the parameters for
63 * the upload changeset and the strategy for opening/closing a changeset.
64 * @since 2025
65 */
66public class UploadDialog extends AbstractUploadDialog implements PropertyChangeListener, PreferenceChangedListener {
67 /** the unique instance of the upload dialog */
68 private static UploadDialog uploadDialog;
69
70 /** list of custom components that can be added by plugins at JOSM startup */
71 private static final Collection<Component> customComponents = new ArrayList<>();
72
73 /** the "created_by" changeset OSM key */
74 private static final String CREATED_BY = "created_by";
75
76 /** the panel with the objects to upload */
77 private UploadedObjectsSummaryPanel pnlUploadedObjects;
78 /** the panel to select the changeset used */
79 private ChangesetManagementPanel pnlChangesetManagement;
80
81 private BasicUploadSettingsPanel pnlBasicUploadSettings;
82
83 private UploadStrategySelectionPanel pnlUploadStrategySelectionPanel;
84
85 /** checkbox for selecting whether an atomic upload is to be used */
86 private TagSettingsPanel pnlTagSettings;
87 /** the tabbed pane used below of the list of primitives */
88 private JTabbedPane tpConfigPanels;
89 /** the upload button */
90 private JButton btnUpload;
91
92 /** the changeset comment model keeping the state of the changeset comment */
93 private final transient ChangesetCommentModel changesetCommentModel = new ChangesetCommentModel();
94 private final transient ChangesetCommentModel changesetSourceModel = new ChangesetCommentModel();
95
96 private transient DataSet dataSet;
97
98 /**
99 * Constructs a new {@code UploadDialog}.
100 */
101 public UploadDialog() {
102 super(JOptionPane.getFrameForComponent(Main.parent), ModalityType.DOCUMENT_MODAL);
103 build();
104 }
105
106 /**
107 * Replies the unique instance of the upload dialog
108 *
109 * @return the unique instance of the upload dialog
110 */
111 public static synchronized UploadDialog getUploadDialog() {
112 if (uploadDialog == null) {
113 uploadDialog = new UploadDialog();
114 }
115 return uploadDialog;
116 }
117
118 /**
119 * builds the content panel for the upload dialog
120 *
121 * @return the content panel
122 */
123 protected JPanel buildContentPanel() {
124 JPanel pnl = new JPanel(new GridBagLayout());
125 pnl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
126
127 // the panel with the list of uploaded objects
128 pnlUploadedObjects = new UploadedObjectsSummaryPanel();
129 pnl.add(pnlUploadedObjects, GBC.eol().fill(GBC.BOTH));
130
131 // Custom components
132 for (Component c : customComponents) {
133 pnl.add(c, GBC.eol().fill(GBC.HORIZONTAL));
134 }
135
136 // a tabbed pane with configuration panels in the lower half
137 tpConfigPanels = new JTabbedPane() {
138 @Override
139 public Dimension getPreferredSize() {
140 // make sure the tabbed pane never grabs more space than necessary
141 return super.getMinimumSize();
142 }
143 };
144
145 pnlBasicUploadSettings = new BasicUploadSettingsPanel(changesetCommentModel, changesetSourceModel);
146 tpConfigPanels.add(pnlBasicUploadSettings);
147 tpConfigPanels.setTitleAt(0, tr("Settings"));
148 tpConfigPanels.setToolTipTextAt(0, tr("Decide how to upload the data and which changeset to use"));
149
150 pnlTagSettings = new TagSettingsPanel(changesetCommentModel, changesetSourceModel);
151 tpConfigPanels.add(pnlTagSettings);
152 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
153 tpConfigPanels.setToolTipTextAt(1, tr("Apply tags to the changeset data is uploaded to"));
154
155 pnlChangesetManagement = new ChangesetManagementPanel(changesetCommentModel);
156 tpConfigPanels.add(pnlChangesetManagement);
157 tpConfigPanels.setTitleAt(2, tr("Changesets"));
158 tpConfigPanels.setToolTipTextAt(2, tr("Manage open changesets and select a changeset to upload to"));
159
160 pnlUploadStrategySelectionPanel = new UploadStrategySelectionPanel();
161 tpConfigPanels.add(pnlUploadStrategySelectionPanel);
162 tpConfigPanels.setTitleAt(3, tr("Advanced"));
163 tpConfigPanels.setToolTipTextAt(3, tr("Configure advanced settings"));
164
165 pnl.add(tpConfigPanels, GBC.eol().fill(GBC.HORIZONTAL));
166 return pnl;
167 }
168
169 /**
170 * builds the panel with the OK and CANCEL buttons
171 *
172 * @return The panel with the OK and CANCEL buttons
173 */
174 protected JPanel buildActionPanel() {
175 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
176 pnl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
177
178 // -- upload button
179 btnUpload = new SideButton(new UploadAction());
180 pnl.add(btnUpload);
181 btnUpload.setFocusable(true);
182 InputMapUtils.enableEnter(btnUpload);
183
184 // -- cancel button
185 CancelAction cancelAction = new CancelAction();
186 pnl.add(new SideButton(cancelAction));
187 getRootPane().registerKeyboardAction(
188 cancelAction,
189 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
190 JComponent.WHEN_IN_FOCUSED_WINDOW
191 );
192 pnl.add(new SideButton(new ContextSensitiveHelpAction(ht("/Dialog/Upload"))));
193 HelpUtil.setHelpContext(getRootPane(), ht("/Dialog/Upload"));
194 return pnl;
195 }
196
197 /**
198 * builds the gui
199 */
200 protected void build() {
201 setTitle(tr("Upload to ''{0}''", OsmApi.getOsmApi().getBaseUrl()));
202 getContentPane().setLayout(new BorderLayout());
203 getContentPane().add(buildContentPanel(), BorderLayout.CENTER);
204 getContentPane().add(buildActionPanel(), BorderLayout.SOUTH);
205
206 addWindowListener(new WindowEventHandler());
207
208
209 // make sure the configuration panels listen to each other
210 // changes
211 //
212 pnlChangesetManagement.addPropertyChangeListener(this);
213 pnlChangesetManagement.addPropertyChangeListener(
214 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
215 );
216 pnlChangesetManagement.addPropertyChangeListener(this);
217 pnlUploadedObjects.addPropertyChangeListener(
218 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
219 );
220 pnlUploadedObjects.addPropertyChangeListener(pnlUploadStrategySelectionPanel);
221 pnlUploadStrategySelectionPanel.addPropertyChangeListener(
222 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
223 );
224
225
226 // users can click on either of two links in the upload parameter
227 // summary handler. This installs the handler for these two events.
228 // We simply select the appropriate tab in the tabbed pane with the configuration dialogs.
229 //
230 pnlBasicUploadSettings.getUploadParameterSummaryPanel().setConfigurationParameterRequestListener(
231 new ConfigurationParameterRequestHandler() {
232 @Override
233 public void handleUploadStrategyConfigurationRequest() {
234 tpConfigPanels.setSelectedIndex(3);
235 }
236
237 @Override
238 public void handleChangesetConfigurationRequest() {
239 tpConfigPanels.setSelectedIndex(2);
240 }
241 }
242 );
243
244 pnlBasicUploadSettings.setUploadTagDownFocusTraversalHandlers(
245 new AbstractAction() {
246 @Override
247 public void actionPerformed(ActionEvent e) {
248 btnUpload.requestFocusInWindow();
249 }
250 }
251 );
252
253 setMinimumSize(new Dimension(300, 350));
254
255 Main.pref.addPreferenceChangeListener(this);
256 }
257
258 /**
259 * Sets the collection of primitives to upload
260 *
261 * @param toUpload the dataset with the objects to upload. If null, assumes the empty
262 * set of objects to upload
263 *
264 */
265 public void setUploadedPrimitives(APIDataSet toUpload) {
266 if (toUpload == null) {
267 List<OsmPrimitive> emptyList = Collections.emptyList();
268 pnlUploadedObjects.setUploadedPrimitives(emptyList, emptyList, emptyList);
269 return;
270 }
271 pnlUploadedObjects.setUploadedPrimitives(
272 toUpload.getPrimitivesToAdd(),
273 toUpload.getPrimitivesToUpdate(),
274 toUpload.getPrimitivesToDelete()
275 );
276 }
277
278 /**
279 * Sets the tags for this upload based on (later items overwrite earlier ones):
280 * <ul>
281 * <li>previous "source" and "comment" input</li>
282 * <li>the tags set in the dataset (see {@link DataSet#getChangeSetTags()})</li>
283 * <li>the tags from the selected open changeset</li>
284 * <li>the JOSM user agent (see {@link Version#getAgentString(boolean)})</li>
285 * </ul>
286 *
287 * @param dataSet to obtain the tags set in the dataset
288 */
289 public void setChangesetTags(DataSet dataSet) {
290 final Map<String, String> tags = new HashMap<>();
291
292 // obtain from previous input
293 tags.put("source", getLastChangesetSourceFromHistory());
294 tags.put("comment", getLastChangesetCommentFromHistory());
295
296 // obtain from dataset
297 if (dataSet != null) {
298 tags.putAll(dataSet.getChangeSetTags());
299 }
300 this.dataSet = dataSet;
301
302 // obtain from selected open changeset
303 if (pnlChangesetManagement.getSelectedChangeset() != null) {
304 tags.putAll(pnlChangesetManagement.getSelectedChangeset().getKeys());
305 }
306
307 // set/adapt created_by
308 final String agent = Version.getInstance().getAgentString(false);
309 final String createdBy = tags.get(CREATED_BY);
310 if (createdBy == null || createdBy.isEmpty()) {
311 tags.put(CREATED_BY, agent);
312 } else if (!createdBy.contains(agent)) {
313 tags.put(CREATED_BY, createdBy + ';' + agent);
314 }
315
316 // remove empty values
317 final Iterator<String> it = tags.keySet().iterator();
318 while (it.hasNext()) {
319 final String v = tags.get(it.next());
320 if (v == null || v.isEmpty()) {
321 it.remove();
322 }
323 }
324
325 pnlTagSettings.initFromTags(tags);
326 pnlTagSettings.tableChanged(null);
327 }
328
329 @Override
330 public void rememberUserInput() {
331 pnlBasicUploadSettings.rememberUserInput();
332 pnlUploadStrategySelectionPanel.rememberUserInput();
333 }
334
335 /**
336 * Initializes the panel for user input
337 */
338 public void startUserInput() {
339 tpConfigPanels.setSelectedIndex(0);
340 pnlBasicUploadSettings.startUserInput();
341 pnlTagSettings.startUserInput();
342 pnlUploadStrategySelectionPanel.initFromPreferences();
343 UploadParameterSummaryPanel pnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
344 pnl.setUploadStrategySpecification(pnlUploadStrategySelectionPanel.getUploadStrategySpecification());
345 pnl.setCloseChangesetAfterNextUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
346 pnl.setNumObjects(pnlUploadedObjects.getNumObjectsToUpload());
347 }
348
349 /**
350 * Replies the current changeset
351 *
352 * @return the current changeset
353 */
354 public Changeset getChangeset() {
355 Changeset cs = pnlChangesetManagement.getSelectedChangeset();
356 if (cs == null) {
357 cs = new Changeset();
358 }
359 cs.setKeys(pnlTagSettings.getTags(false));
360 return cs;
361 }
362
363 /**
364 * Sets the changeset to be used in the next upload
365 *
366 * @param cs the changeset
367 */
368 public void setSelectedChangesetForNextUpload(Changeset cs) {
369 pnlChangesetManagement.setSelectedChangesetForNextUpload(cs);
370 }
371
372 /**
373 * @deprecated No longer supported, does nothing;
374 * @return empty map
375 */
376 @Deprecated
377 public Map<String, String> getDefaultChangesetTags() {
378 return pnlTagSettings.getDefaultTags();
379 }
380
381 /**
382 * @param tags ignored
383 * @deprecated No longer supported, does nothing; use {@link #setChangesetTags(DataSet)} instead!
384 */
385 @Deprecated
386 public void setDefaultChangesetTags(Map<String, String> tags) {
387 // Deprecated
388 }
389
390 /**
391 * Replies the {@link UploadStrategySpecification} the user entered in the dialog.
392 *
393 * @return the {@link UploadStrategySpecification} the user entered in the dialog.
394 */
395 public UploadStrategySpecification getUploadStrategySpecification() {
396 UploadStrategySpecification spec = pnlUploadStrategySelectionPanel.getUploadStrategySpecification();
397 spec.setCloseChangesetAfterUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
398 return spec;
399 }
400
401 /**
402 * Returns the current value for the upload comment
403 *
404 * @return the current value for the upload comment
405 */
406 protected String getUploadComment() {
407 return changesetCommentModel.getComment();
408 }
409
410 /**
411 * Returns the current value for the changeset source
412 *
413 * @return the current value for the changeset source
414 */
415 protected String getUploadSource() {
416 return changesetSourceModel.getComment();
417 }
418
419 @Override
420 public void setVisible(boolean visible) {
421 if (visible) {
422 new WindowGeometry(
423 getClass().getName() + ".geometry",
424 WindowGeometry.centerInWindow(
425 Main.parent,
426 new Dimension(400, 600)
427 )
428 ).applySafe(this);
429 startUserInput();
430 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
431 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
432 }
433 super.setVisible(visible);
434 }
435
436 /**
437 * Adds a custom component to this dialog.
438 * Custom components added at JOSM startup are displayed between the objects list and the properties tab pane.
439 * @param c The custom component to add. If {@code null}, this method does nothing.
440 * @return {@code true} if the collection of custom components changed as a result of the call
441 * @since 5842
442 */
443 public static boolean addCustomComponent(Component c) {
444 if (c != null) {
445 return customComponents.add(c);
446 }
447 return false;
448 }
449
450 /**
451 * Handles an upload
452 *
453 */
454 class UploadAction extends AbstractAction {
455 UploadAction() {
456 putValue(NAME, tr("Upload Changes"));
457 putValue(SMALL_ICON, ImageProvider.get("upload"));
458 putValue(SHORT_DESCRIPTION, tr("Upload the changed primitives"));
459 }
460
461 /**
462 * Displays a warning message indicating that the upload comment is empty/short.
463 * @return true if the user wants to revisit, false if they want to continue
464 */
465 protected boolean warnUploadComment() {
466 return warnUploadTag(
467 tr("Please revise upload comment"),
468 tr("Your upload comment is <i>empty</i>, or <i>very short</i>.<br /><br />" +
469 "This is technically allowed, but please consider that many users who are<br />" +
470 "watching changes in their area depend on meaningful changeset comments<br />" +
471 "to understand what is going on!<br /><br />" +
472 "If you spend a minute now to explain your change, you will make life<br />" +
473 "easier for many other mappers."),
474 "upload_comment_is_empty_or_very_short"
475 );
476 }
477
478 /**
479 * Displays a warning message indicating that no changeset source is given.
480 * @return true if the user wants to revisit, false if they want to continue
481 */
482 protected boolean warnUploadSource() {
483 return warnUploadTag(
484 tr("Please specify a changeset source"),
485 tr("You did not specify a source for your changes.<br />" +
486 "It is technically allowed, but this information helps<br />" +
487 "other users to understand the origins of the data.<br /><br />" +
488 "If you spend a minute now to explain your change, you will make life<br />" +
489 "easier for many other mappers."),
490 "upload_source_is_empty"
491 );
492 }
493
494 protected boolean warnUploadTag(final String title, final String message, final String togglePref) {
495 ExtendedDialog dlg = new ExtendedDialog(UploadDialog.this,
496 title,
497 new String[] {tr("Revise"), tr("Cancel"), tr("Continue as is")});
498 dlg.setContent("<html>" + message + "</html>");
499 dlg.setButtonIcons(new Icon[] {
500 new ImageProvider("ok").setMaxSize(ImageSizes.LARGEICON).get(),
501 new ImageProvider("cancel").setMaxSize(ImageSizes.LARGEICON).get(),
502 new ImageProvider("upload").setMaxSize(ImageSizes.LARGEICON).addOverlay(
503 new ImageOverlay(new ImageProvider("warning-small"), 0.5, 0.5, 1.0, 1.0)).get()});
504 dlg.setToolTipTexts(new String[] {
505 tr("Return to the previous dialog to enter a more descriptive comment"),
506 tr("Cancel and return to the previous dialog"),
507 tr("Ignore this hint and upload anyway")});
508 dlg.setIcon(JOptionPane.WARNING_MESSAGE);
509 dlg.toggleEnable(togglePref);
510 dlg.setCancelButton(1, 2);
511 return dlg.showDialog().getValue() != 3;
512 }
513
514 protected void warnIllegalChunkSize() {
515 HelpAwareOptionPane.showOptionDialog(
516 UploadDialog.this,
517 tr("Please enter a valid chunk size first"),
518 tr("Illegal chunk size"),
519 JOptionPane.ERROR_MESSAGE,
520 ht("/Dialog/Upload#IllegalChunkSize")
521 );
522 }
523
524 @Override
525 public void actionPerformed(ActionEvent e) {
526 if ((getUploadComment().trim().length() < 10 && warnUploadComment()) /* abort for missing comment */
527 || (getUploadSource().trim().isEmpty() && warnUploadSource()) /* abort for missing changeset source */
528 ) {
529 tpConfigPanels.setSelectedIndex(0);
530 pnlBasicUploadSettings.initEditingOfUploadComment();
531 return;
532 }
533
534 /* test for empty tags in the changeset metadata and proceed only after user's confirmation.
535 * though, accept if key and value are empty (cf. xor). */
536 List<String> emptyChangesetTags = new ArrayList<>();
537 for (final Entry<String, String> i : pnlTagSettings.getTags(true).entrySet()) {
538 final boolean isKeyEmpty = i.getKey() == null || i.getKey().trim().isEmpty();
539 final boolean isValueEmpty = i.getValue() == null || i.getValue().trim().isEmpty();
540 final boolean ignoreKey = "comment".equals(i.getKey()) || "source".equals(i.getKey());
541 if ((isKeyEmpty ^ isValueEmpty) && !ignoreKey) {
542 emptyChangesetTags.add(tr("{0}={1}", i.getKey(), i.getValue()));
543 }
544 }
545 if (!emptyChangesetTags.isEmpty() && JOptionPane.OK_OPTION != JOptionPane.showConfirmDialog(
546 Main.parent,
547 trn(
548 "<html>The following changeset tag contains an empty key/value:<br>{0}<br>Continue?</html>",
549 "<html>The following changeset tags contain an empty key/value:<br>{0}<br>Continue?</html>",
550 emptyChangesetTags.size(), Utils.joinAsHtmlUnorderedList(emptyChangesetTags)),
551 tr("Empty metadata"),
552 JOptionPane.OK_CANCEL_OPTION,
553 JOptionPane.WARNING_MESSAGE
554 )) {
555 tpConfigPanels.setSelectedIndex(0);
556 pnlBasicUploadSettings.initEditingOfUploadComment();
557 return;
558 }
559
560 UploadStrategySpecification strategy = getUploadStrategySpecification();
561 if (strategy.getStrategy().equals(UploadStrategy.CHUNKED_DATASET_STRATEGY)
562 && strategy.getChunkSize() == UploadStrategySpecification.UNSPECIFIED_CHUNK_SIZE) {
563 warnIllegalChunkSize();
564 tpConfigPanels.setSelectedIndex(0);
565 return;
566 }
567 setCanceled(false);
568 setVisible(false);
569 }
570 }
571
572 /**
573 * Action for canceling the dialog
574 *
575 */
576 class CancelAction extends AbstractAction {
577 CancelAction() {
578 putValue(NAME, tr("Cancel"));
579 putValue(SMALL_ICON, ImageProvider.get("cancel"));
580 putValue(SHORT_DESCRIPTION, tr("Cancel the upload and resume editing"));
581 }
582
583 @Override
584 public void actionPerformed(ActionEvent e) {
585 setCanceled(true);
586 setVisible(false);
587 }
588 }
589
590 /**
591 * Listens to window closing events and processes them as cancel events.
592 * Listens to window open events and initializes user input
593 *
594 */
595 class WindowEventHandler extends WindowAdapter {
596 @Override
597 public void windowClosing(WindowEvent e) {
598 setCanceled(true);
599 }
600
601 @Override
602 public void windowActivated(WindowEvent arg0) {
603 if (tpConfigPanels.getSelectedIndex() == 0) {
604 pnlBasicUploadSettings.initEditingOfUploadComment();
605 }
606 }
607 }
608
609 /* -------------------------------------------------------------------------- */
610 /* Interface PropertyChangeListener */
611 /* -------------------------------------------------------------------------- */
612 @Override
613 public void propertyChange(PropertyChangeEvent evt) {
614 if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
615 Changeset cs = (Changeset) evt.getNewValue();
616 setChangesetTags(dataSet);
617 if (cs == null) {
618 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
619 } else {
620 tpConfigPanels.setTitleAt(1, tr("Tags of changeset {0}", cs.getId()));
621 }
622 }
623 }
624
625 /* -------------------------------------------------------------------------- */
626 /* Interface PreferenceChangedListener */
627 /* -------------------------------------------------------------------------- */
628 @Override
629 public void preferenceChanged(PreferenceChangeEvent e) {
630 if (e.getKey() == null || !"osm-server.url".equals(e.getKey()))
631 return;
632 final Setting<?> newValue = e.getNewValue();
633 final String url;
634 if (newValue == null || newValue.getValue() == null) {
635 url = OsmApi.getOsmApi().getBaseUrl();
636 } else {
637 url = newValue.getValue().toString();
638 }
639 setTitle(tr("Upload to ''{0}''", url));
640 }
641
642 private static String getLastChangesetTagFromHistory(String historyKey, List<String> def) {
643 Collection<String> history = Main.pref.getCollection(historyKey, def);
644 int age = (int) (System.currentTimeMillis() / 1000 - Main.pref.getInteger(BasicUploadSettingsPanel.HISTORY_LAST_USED_KEY, 0));
645 if (age < Main.pref.getInteger(BasicUploadSettingsPanel.HISTORY_MAX_AGE_KEY, 4 * 3600 * 1000) && history != null && !history.isEmpty()) {
646 return history.iterator().next();
647 } else {
648 return null;
649 }
650 }
651
652 /**
653 * Returns the last changeset comment from history.
654 * @return the last changeset comment from history
655 */
656 public String getLastChangesetCommentFromHistory() {
657 return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.HISTORY_KEY, new ArrayList<String>());
658 }
659
660 /**
661 * Returns the last changeset source from history.
662 * @return the last changeset source from history
663 */
664 public String getLastChangesetSourceFromHistory() {
665 return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.SOURCE_HISTORY_KEY, BasicUploadSettingsPanel.getDefaultSources());
666 }
667}
Note: See TracBrowser for help on using the repository browser.