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

Last change on this file since 4153 was 3770, checked in by stoecker, 13 years ago

fix help

  • Property svn:eol-style set to native
File size: 18.9 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;
6
7import java.awt.BorderLayout;
8import java.awt.Dimension;
9import java.awt.FlowLayout;
10import java.awt.Image;
11import java.awt.event.ActionEvent;
12import java.awt.event.KeyEvent;
13import java.awt.event.WindowAdapter;
14import java.awt.event.WindowEvent;
15import java.beans.PropertyChangeEvent;
16import java.beans.PropertyChangeListener;
17import java.util.Collections;
18import java.util.List;
19import java.util.Map;
20import java.util.logging.Logger;
21
22import javax.swing.AbstractAction;
23import javax.swing.BorderFactory;
24import javax.swing.Icon;
25import javax.swing.ImageIcon;
26import javax.swing.InputMap;
27import javax.swing.JButton;
28import javax.swing.JComponent;
29import javax.swing.JDialog;
30import javax.swing.JOptionPane;
31import javax.swing.JPanel;
32import javax.swing.JTabbedPane;
33import javax.swing.KeyStroke;
34
35import org.openstreetmap.josm.Main;
36import org.openstreetmap.josm.data.APIDataSet;
37import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
38import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
39import org.openstreetmap.josm.data.osm.Changeset;
40import org.openstreetmap.josm.data.osm.OsmPrimitive;
41import org.openstreetmap.josm.gui.ExtendedDialog;
42import org.openstreetmap.josm.gui.HelpAwareOptionPane;
43import org.openstreetmap.josm.gui.SideButton;
44import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
45import org.openstreetmap.josm.gui.help.HelpUtil;
46import org.openstreetmap.josm.io.OsmApi;
47import org.openstreetmap.josm.tools.ImageProvider;
48import org.openstreetmap.josm.tools.WindowGeometry;
49
50/**
51 * This is a dialog for entering upload options like the parameters for
52 * the upload changeset and the strategy for opening/closing a changeset.
53 *
54 */
55public class UploadDialog extends JDialog implements PropertyChangeListener, PreferenceChangedListener{
56 protected static final Logger logger = Logger.getLogger(UploadDialog.class.getName());
57
58 /** the unique instance of the upload dialog */
59 static private UploadDialog uploadDialog;
60
61 /**
62 * Replies the unique instance of the upload dialog
63 *
64 * @return the unique instance of the upload dialog
65 */
66 static public UploadDialog getUploadDialog() {
67 if (uploadDialog == null) {
68 uploadDialog = new UploadDialog();
69 }
70 return uploadDialog;
71 }
72
73 /** the panel with the objects to upload */
74 private UploadedObjectsSummaryPanel pnlUploadedObjects;
75 /** the panel to select the changeset used */
76 private ChangesetManagementPanel pnlChangesetManagement;
77
78 private BasicUploadSettingsPanel pnlBasicUploadSettings;
79
80 private UploadStrategySelectionPanel pnlUploadStrategySelectionPanel;
81
82 /** checkbox for selecting whether an atomic upload is to be used */
83 private TagSettingsPanel pnlTagSettings;
84 /** the tabbed pane used below of the list of primitives */
85 private JTabbedPane tpConfigPanels;
86 /** the upload button */
87 private JButton btnUpload;
88 private boolean canceled = false;
89
90 /** the changeset comment model keeping the state of the changeset comment */
91 private ChangesetCommentModel changesetCommentModel;
92
93 /**
94 * builds the content panel for the upload dialog
95 *
96 * @return the content panel
97 */
98 protected JPanel buildContentPanel() {
99 JPanel pnl = new JPanel();
100 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
101 pnl.setLayout(new BorderLayout());
102
103 // the panel with the list of uploaded objects
104 //
105 pnl.add(pnlUploadedObjects = new UploadedObjectsSummaryPanel(), BorderLayout.CENTER);
106
107 // a tabbed pane with two configuration panels in the
108 // lower half
109 //
110 tpConfigPanels = new JTabbedPane() {
111 @Override
112 public Dimension getPreferredSize() {
113 // make sure the tabbed pane never grabs more space than necessary
114 //
115 return super.getMinimumSize();
116 }
117 };
118 tpConfigPanels.add(new JPanel());
119 tpConfigPanels.add(new JPanel());
120 tpConfigPanels.add(new JPanel());
121 tpConfigPanels.add(new JPanel());
122
123 changesetCommentModel = new ChangesetCommentModel();
124
125 tpConfigPanels.setComponentAt(0, pnlBasicUploadSettings = new BasicUploadSettingsPanel(changesetCommentModel));
126 tpConfigPanels.setTitleAt(0, tr("Settings"));
127 tpConfigPanels.setToolTipTextAt(0, tr("Decide how to upload the data and which changeset to use"));
128
129 tpConfigPanels.setComponentAt(1,pnlTagSettings = new TagSettingsPanel(changesetCommentModel));
130 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
131 tpConfigPanels.setToolTipTextAt(1, tr("Apply tags to the changeset data is uploaded to"));
132
133 tpConfigPanels.setComponentAt(2,pnlChangesetManagement = new ChangesetManagementPanel(changesetCommentModel));
134 tpConfigPanels.setTitleAt(2, tr("Changesets"));
135 tpConfigPanels.setToolTipTextAt(2, tr("Manage open changesets and select a changeset to upload to"));
136
137 tpConfigPanels.setComponentAt(3, pnlUploadStrategySelectionPanel = new UploadStrategySelectionPanel());
138 tpConfigPanels.setTitleAt(3, tr("Advanced"));
139 tpConfigPanels.setToolTipTextAt(3, tr("Configure advanced settings"));
140
141 pnl.add(tpConfigPanels, BorderLayout.SOUTH);
142 return pnl;
143 }
144
145 /**
146 * builds the panel with the OK and CANCEL buttons
147 *
148 * @return
149 */
150 protected JPanel buildActionPanel() {
151 JPanel pnl = new JPanel();
152 pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
153 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
154
155 // -- upload button
156 UploadAction uploadAction = new UploadAction();
157 pnl.add(btnUpload = new SideButton(uploadAction));
158 btnUpload.setFocusable(true);
159 InputMap inputMap = btnUpload.getInputMap();
160 inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "doUpload");
161 btnUpload.getActionMap().put("doUpload", uploadAction);
162
163 // -- cancel button
164 CancelAction cancelAction = new CancelAction();
165 pnl.add(new SideButton(cancelAction));
166 getRootPane().registerKeyboardAction(
167 cancelAction,
168 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),
169 JComponent.WHEN_IN_FOCUSED_WINDOW
170 );
171 pnl.add(new SideButton(new ContextSensitiveHelpAction(ht("/Dialog/Upload"))));
172 HelpUtil.setHelpContext(getRootPane(),ht("/Dialog/Upload"));
173 return pnl;
174 }
175
176 /**
177 * builds the gui
178 */
179 protected void build() {
180 setTitle(tr("Upload to ''{0}''", OsmApi.getOsmApi().getBaseUrl()));
181 getContentPane().setLayout(new BorderLayout());
182 getContentPane().add(buildContentPanel(), BorderLayout.CENTER);
183 getContentPane().add(buildActionPanel(), BorderLayout.SOUTH);
184
185 addWindowListener(new WindowEventHandler());
186
187
188 // make sure the the configuration panels listen to each other
189 // changes
190 //
191 pnlChangesetManagement.addPropertyChangeListener(
192 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
193 );
194 pnlChangesetManagement.addPropertyChangeListener(this);
195 pnlUploadedObjects.addPropertyChangeListener(
196 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
197 );
198 pnlUploadedObjects.addPropertyChangeListener(pnlUploadStrategySelectionPanel);
199 pnlUploadStrategySelectionPanel.addPropertyChangeListener(
200 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
201 );
202
203
204 // users can click on either of two links in the upload parameter
205 // summary handler. This installs the handler for these two events.
206 // We simply select the appropriate tab in the tabbed pane with the
207 // configuration dialogs.
208 //
209 pnlBasicUploadSettings.getUploadParameterSummaryPanel().setConfigurationParameterRequestListener(
210 new ConfigurationParameterRequestHandler() {
211 public void handleUploadStrategyConfigurationRequest() {
212 tpConfigPanels.setSelectedIndex(3);
213 }
214 public void handleChangesetConfigurationRequest() {
215 tpConfigPanels.setSelectedIndex(2);
216 }
217 }
218 );
219
220 pnlBasicUploadSettings.setUploadCommentDownFocusTraversalHandler(
221 new AbstractAction() {
222 public void actionPerformed(ActionEvent e) {
223 btnUpload.requestFocusInWindow();
224 }
225 }
226 );
227
228 Main.pref.addPreferenceChangeListener(this);
229 }
230
231 /**
232 * constructor
233 */
234 public UploadDialog() {
235 super(JOptionPane.getFrameForComponent(Main.parent), ModalityType.DOCUMENT_MODAL);
236 build();
237 }
238
239 /**
240 * Sets the collection of primitives to upload
241 *
242 * @param toUpload the dataset with the objects to upload. If null, assumes the empty
243 * set of objects to upload
244 *
245 */
246 public void setUploadedPrimitives(APIDataSet toUpload) {
247 if (toUpload == null) {
248 List<OsmPrimitive> emptyList = Collections.emptyList();
249 pnlUploadedObjects.setUploadedPrimitives(emptyList, emptyList, emptyList);
250 return;
251 }
252 pnlUploadedObjects.setUploadedPrimitives(
253 toUpload.getPrimitivesToAdd(),
254 toUpload.getPrimitivesToUpdate(),
255 toUpload.getPrimitivesToDelete()
256 );
257 }
258
259 /**
260 * Remembers the user input in the preference settings
261 */
262 public void rememberUserInput() {
263 pnlBasicUploadSettings.rememberUserInput();
264 pnlUploadStrategySelectionPanel.rememberUserInput();
265 }
266
267 /**
268 * Initializes the panel for user input
269 */
270 public void startUserInput() {
271 tpConfigPanels.setSelectedIndex(0);
272 pnlBasicUploadSettings.startUserInput();
273 pnlTagSettings.startUserInput();
274 pnlTagSettings.initFromChangeset(pnlChangesetManagement.getSelectedChangeset());
275 pnlUploadStrategySelectionPanel.initFromPreferences();
276 UploadParameterSummaryPanel pnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
277 pnl.setUploadStrategySpecification(pnlUploadStrategySelectionPanel.getUploadStrategySpecification());
278 pnl.setCloseChangesetAfterNextUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
279 pnl.setNumObjects(pnlUploadedObjects.getNumObjectsToUpload());
280 }
281
282 /**
283 * Replies the current changeset
284 *
285 * @return the current changeset
286 */
287 public Changeset getChangeset() {
288 Changeset cs = pnlChangesetManagement.getSelectedChangeset();
289 if (cs == null) {
290 cs = new Changeset();
291 }
292 cs.setKeys(pnlTagSettings.getTags());
293 return cs;
294 }
295
296 public void setSelectedChangesetForNextUpload(Changeset cs) {
297 pnlChangesetManagement.setSelectedChangesetForNextUpload(cs);
298 }
299
300 public Map<String, String> getDefaultChangesetTags() {
301 return pnlTagSettings.getDefaultTags();
302 }
303
304 public void setDefaultChangesetTags(Map<String, String> tags) {
305 pnlTagSettings.setDefaultTags(tags);
306 }
307
308 /**
309 * Replies the {@see UploadStrategySpecification} the user entered in the dialog.
310 *
311 * @return the {@see UploadStrategySpecification} the user entered in the dialog.
312 */
313 public UploadStrategySpecification getUploadStrategySpecification() {
314 UploadStrategySpecification spec = pnlUploadStrategySelectionPanel.getUploadStrategySpecification();
315 spec.setCloseChangesetAfterUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
316 return spec;
317 }
318
319 /**
320 * Returns the current value for the upload comment
321 *
322 * @return the current value for the upload comment
323 */
324 protected String getUploadComment() {
325 return changesetCommentModel.getComment();
326 }
327
328 /**
329 * Returns true if the dialog was canceled
330 *
331 * @return true if the dialog was canceled
332 */
333 public boolean isCanceled() {
334 return canceled;
335 }
336
337 /**
338 * Sets whether the dialog was canceled
339 *
340 * @param canceled true if the dialog is canceled
341 */
342 protected void setCanceled(boolean canceled) {
343 this.canceled = canceled;
344 }
345
346 @Override
347 public void setVisible(boolean visible) {
348 if (visible) {
349 new WindowGeometry(
350 getClass().getName() + ".geometry",
351 WindowGeometry.centerInWindow(
352 Main.parent,
353 new Dimension(400,600)
354 )
355 ).applySafe(this);
356 startUserInput();
357 } else if (!visible && isShowing()){
358 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
359 }
360 super.setVisible(visible);
361 }
362
363 /**
364 * Handles an upload
365 *
366 */
367 class UploadAction extends AbstractAction {
368 public UploadAction() {
369 putValue(NAME, tr("Upload Changes"));
370 putValue(SMALL_ICON, ImageProvider.get("upload"));
371 putValue(SHORT_DESCRIPTION, tr("Upload the changed primitives"));
372 }
373
374 /**
375 * returns true if the user wants to revisit, false if they
376 * want to continue
377 */
378 protected boolean warnUploadComment() {
379 ExtendedDialog dlg = new ExtendedDialog(UploadDialog.this,
380 tr("Please revise upload comment"),
381 new String[] {tr("Revise"), tr("Cancel"), tr("Continue as is")});
382 dlg.setContent("<html>" +
383 tr("Your upload comment is <i>empty</i>, or <i>very short</i>.<br /><br />" +
384 "This is technically allowed, but please consider that many users who are<br />" +
385 "watching changes in their area depend on meaningful changeset comments<br />" +
386 "to understand what is going on!<br /><br />" +
387 "If you spend a minute now to explain your change, you will make life<br />" +
388 "easier for many other mappers.") +
389 "</html>");
390 dlg.setButtonIcons(new Icon[] {
391 ImageProvider.get("ok"),
392 ImageProvider.get("cancel"),
393 ImageProvider.overlay(
394 ImageProvider.get("upload"),
395 new ImageIcon(ImageProvider.get("warning-small").getImage().getScaledInstance(10 , 10, Image.SCALE_SMOOTH)),
396 ImageProvider.OverlayPosition.SOUTHEAST)});
397 dlg.setToolTipTexts(new String[] {
398 tr("Return to the previous dialog to enter a more descriptive comment"),
399 tr("Cancel and return to the previous dialog"),
400 tr("Ignore this hint and upload anyway")});
401 dlg.setIcon(JOptionPane.WARNING_MESSAGE);
402 dlg.toggleEnable("upload_comment_is_empty_or_very_short");
403 dlg.setToggleCheckboxText(tr("Do not show this message again"));
404 dlg.setCancelButton(1, 2);
405 return dlg.showDialog().getValue() != 3;
406 }
407
408 protected void warnIllegalChunkSize() {
409 HelpAwareOptionPane.showOptionDialog(
410 UploadDialog.this,
411 tr("Please enter a valid chunk size first"),
412 tr("Illegal chunk size"),
413 JOptionPane.ERROR_MESSAGE,
414 ht("/Dialog/Upload#IllegalChunkSize")
415 );
416 }
417
418 public void actionPerformed(ActionEvent e) {
419 if (getUploadComment().trim().length() < 10) {
420 if (warnUploadComment())
421 {
422 tpConfigPanels.setSelectedIndex(0);
423 pnlBasicUploadSettings.initEditingOfUploadComment();
424 return;
425 }
426 }
427 UploadStrategySpecification strategy = getUploadStrategySpecification();
428 if (strategy.getStrategy().equals(UploadStrategy.CHUNKED_DATASET_STRATEGY)) {
429 if (strategy.getChunkSize() == UploadStrategySpecification.UNSPECIFIED_CHUNK_SIZE) {
430 warnIllegalChunkSize();
431 tpConfigPanels.setSelectedIndex(0);
432 return;
433 }
434 }
435 setCanceled(false);
436 setVisible(false);
437 }
438 }
439
440 /**
441 * Action for canceling the dialog
442 *
443 */
444 class CancelAction extends AbstractAction {
445 public CancelAction() {
446 putValue(NAME, tr("Cancel"));
447 putValue(SMALL_ICON, ImageProvider.get("cancel"));
448 putValue(SHORT_DESCRIPTION, tr("Cancel the upload and resume editing"));
449 }
450
451 public void actionPerformed(ActionEvent e) {
452 setCanceled(true);
453 setVisible(false);
454 }
455 }
456
457 /**
458 * Listens to window closing events and processes them as cancel events.
459 * Listens to window open events and initializes user input
460 *
461 */
462 class WindowEventHandler extends WindowAdapter {
463 @Override
464 public void windowClosing(WindowEvent e) {
465 setCanceled(true);
466 }
467
468 @Override
469 public void windowOpened(WindowEvent e) {
470 //startUserInput();
471 }
472
473 @Override
474 public void windowActivated(WindowEvent arg0) {
475 if (tpConfigPanels.getSelectedIndex() == 0) {
476 pnlBasicUploadSettings.initEditingOfUploadComment();
477 }
478 }
479 }
480
481 /* -------------------------------------------------------------------------- */
482 /* Interface PropertyChangeListener */
483 /* -------------------------------------------------------------------------- */
484 public void propertyChange(PropertyChangeEvent evt) {
485 if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
486 Changeset cs = (Changeset)evt.getNewValue();
487 if (cs == null) {
488 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
489 } else {
490 tpConfigPanels.setTitleAt(1, tr("Tags of changeset {0}", cs.getId()));
491 }
492 }
493 }
494
495 /* -------------------------------------------------------------------------- */
496 /* Interface PreferenceChangedListener */
497 /* -------------------------------------------------------------------------- */
498 public void preferenceChanged(PreferenceChangeEvent e) {
499 if (e.getKey() == null || ! e.getKey().equals("osm-server.url"))
500 return;
501 if (e.getNewValue() == null) {
502 setTitle(tr("Upload"));
503 } else {
504 setTitle(tr("Upload to ''{0}''", e.getNewValue()));
505 }
506 }
507}
Note: See TracBrowser for help on using the repository browser.