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

Last change on this file since 3133 was 3133, checked in by Gubaer, 14 years ago

fixed #4371: Changeset comment reverts to previous when switching options

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