source: josm/trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java@ 8912

Last change on this file since 8912 was 8912, checked in by simon04, 9 years ago

fix #11151 - Not all buttons are shown in exit confirmation dialog

Use GridBagLayout to avoid disappearance of buttons.

  • Property svn:eol-style set to native
File size: 24.4 KB
RevLine 
[2512]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.Dimension;
[5003]10import java.awt.Graphics2D;
[2512]11import java.awt.GridBagConstraints;
12import java.awt.GridBagLayout;
[5003]13import java.awt.Image;
[2512]14import java.awt.event.ActionEvent;
15import java.awt.event.WindowAdapter;
16import java.awt.event.WindowEvent;
[5003]17import java.awt.image.BufferedImage;
[2512]18import java.beans.PropertyChangeEvent;
19import java.beans.PropertyChangeListener;
20import java.util.List;
21import java.util.concurrent.CancellationException;
22import java.util.concurrent.ExecutorService;
23import java.util.concurrent.Executors;
24import java.util.concurrent.Future;
25
26import javax.swing.AbstractAction;
27import javax.swing.DefaultListCellRenderer;
[5003]28import javax.swing.ImageIcon;
[6643]29import javax.swing.JButton;
[4618]30import javax.swing.JComponent;
[2512]31import javax.swing.JDialog;
32import javax.swing.JLabel;
33import javax.swing.JList;
34import javax.swing.JOptionPane;
35import javax.swing.JPanel;
36import javax.swing.JScrollPane;
[4618]37import javax.swing.KeyStroke;
[7029]38import javax.swing.ListCellRenderer;
[3441]39import javax.swing.WindowConstants;
[5003]40import javax.swing.event.TableModelEvent;
41import javax.swing.event.TableModelListener;
[2512]42
43import org.openstreetmap.josm.Main;
44import org.openstreetmap.josm.actions.UploadAction;
45import org.openstreetmap.josm.gui.ExceptionDialogUtil;
46import org.openstreetmap.josm.gui.io.SaveLayersModel.Mode;
[7402]47import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
[2512]48import org.openstreetmap.josm.gui.progress.ProgressMonitor;
49import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor;
[6965]50import org.openstreetmap.josm.gui.util.GuiHelper;
[8912]51import org.openstreetmap.josm.tools.GBC;
[2512]52import org.openstreetmap.josm.tools.ImageProvider;
[8734]53import org.openstreetmap.josm.tools.Utils;
[2512]54import org.openstreetmap.josm.tools.WindowGeometry;
55
[5003]56public class SaveLayersDialog extends JDialog implements TableModelListener {
[8836]57 public enum UserAction {
[6965]58 /** save/upload layers was successful, proceed with operation */
[2512]59 PROCEED,
[6965]60 /** save/upload of layers was not successful or user canceled operation */
[2512]61 CANCEL
62 }
63
64 private SaveLayersModel model;
65 private UserAction action = UserAction.CANCEL;
66 private UploadAndSaveProgressRenderer pnlUploadLayers;
67
68 private SaveAndProceedAction saveAndProceedAction;
69 private DiscardAndProceedAction discardAndProceedAction;
70 private CancelAction cancelAction;
[8308]71 private transient SaveAndUploadTask saveAndUploadTask;
[2512]72
73 /**
74 * builds the GUI
75 */
76 protected void build() {
[8510]77 WindowGeometry geometry = WindowGeometry.centerOnScreen(new Dimension(650, 300));
[4932]78 geometry.applySafe(this);
[2512]79 getContentPane().setLayout(new BorderLayout());
80
81 model = new SaveLayersModel();
[5003]82 SaveLayersTable table = new SaveLayersTable(model);
83 JScrollPane pane = new JScrollPane(table);
[2512]84 model.addPropertyChangeListener(table);
[5003]85 table.getModel().addTableModelListener(this);
86
[2512]87 getContentPane().add(pane, BorderLayout.CENTER);
88 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
89
90 addWindowListener(new WindowClosingAdapter());
[3441]91 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
[2512]92 }
93
[8840]94 private JButton saveAndProceedActionButton;
[5003]95
[2512]96 /**
97 * builds the button row
98 *
99 * @return the panel with the button row
100 */
101 protected JPanel buildButtonRow() {
102 JPanel pnl = new JPanel();
[8912]103 pnl.setLayout(new GridBagLayout());
[2512]104
105 saveAndProceedAction = new SaveAndProceedAction();
106 model.addPropertyChangeListener(saveAndProceedAction);
[8912]107 pnl.add(saveAndProceedActionButton = new JButton(saveAndProceedAction), GBC.std().insets(5, 5, 5, 5).fill(GBC.HORIZONTAL));
[2512]108
109 discardAndProceedAction = new DiscardAndProceedAction();
110 model.addPropertyChangeListener(discardAndProceedAction);
[8912]111 pnl.add(new JButton(discardAndProceedAction), GBC.std().insets(0, 0, 5, 0).fill(GBC.HORIZONTAL));
[2512]112
113 cancelAction = new CancelAction();
[8912]114 pnl.add(new JButton(cancelAction), GBC.std().insets(0, 0, 5, 0).fill(GBC.HORIZONTAL));
[2512]115
116 JPanel pnl2 = new JPanel();
117 pnl2.setLayout(new BorderLayout());
118 pnl2.add(pnlUploadLayers = new UploadAndSaveProgressRenderer(), BorderLayout.CENTER);
119 model.addPropertyChangeListener(pnlUploadLayers);
120 pnl2.add(pnl, BorderLayout.SOUTH);
121 return pnl2;
122 }
123
124 public void prepareForSavingAndUpdatingLayersBeforeExit() {
125 setTitle(tr("Unsaved changes - Save/Upload before exiting?"));
126 this.saveAndProceedAction.initForSaveAndExit();
127 this.discardAndProceedAction.initForDiscardAndExit();
128 }
129
130 public void prepareForSavingAndUpdatingLayersBeforeDelete() {
131 setTitle(tr("Unsaved changes - Save/Upload before deleting?"));
132 this.saveAndProceedAction.initForSaveAndDelete();
133 this.discardAndProceedAction.initForDiscardAndDelete();
134 }
135
136 public SaveLayersDialog(Component parent) {
[3501]137 super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
[2512]138 build();
139 }
140
141 public UserAction getUserAction() {
142 return this.action;
143 }
144
145 public SaveLayersModel getModel() {
146 return model;
147 }
148
149 protected void launchSafeAndUploadTask() {
150 ProgressMonitor monitor = new SwingRenderingProgressMonitor(pnlUploadLayers);
151 monitor.beginTask(tr("Uploading and saving modified layers ..."));
152 this.saveAndUploadTask = new SaveAndUploadTask(model, monitor);
[8736]153 new Thread(saveAndUploadTask, saveAndUploadTask.getClass().getName()).start();
[2512]154 }
155
156 protected void cancelSafeAndUploadTask() {
157 if (this.saveAndUploadTask != null) {
158 this.saveAndUploadTask.cancel();
159 }
160 model.setMode(Mode.EDITING_DATA);
161 }
162
163 private static class LayerListWarningMessagePanel extends JPanel {
164 private JLabel lblMessage;
[7017]165 private JList<SaveLayerInfo> lstLayers;
[2512]166
167 protected void build() {
168 setLayout(new GridBagLayout());
169 GridBagConstraints gc = new GridBagConstraints();
170 gc.gridx = 0;
171 gc.gridy = 0;
172 gc.fill = GridBagConstraints.HORIZONTAL;
173 gc.weightx = 1.0;
174 gc.weighty = 0.0;
175 add(lblMessage = new JLabel(), gc);
176 lblMessage.setHorizontalAlignment(JLabel.LEFT);
[7017]177 lstLayers = new JList<>();
[2512]178 lstLayers.setCellRenderer(
[7029]179 new ListCellRenderer<SaveLayerInfo>() {
[8285]180 private final DefaultListCellRenderer def = new DefaultListCellRenderer();
[2512]181 @Override
[7029]182 public Component getListCellRendererComponent(JList<? extends SaveLayerInfo> list, SaveLayerInfo info, int index,
[2512]183 boolean isSelected, boolean cellHasFocus) {
[7029]184 def.setIcon(info.getLayer().getIcon());
185 def.setText(info.getName());
186 return def;
[2512]187 }
188 }
189 );
190 gc.gridx = 0;
191 gc.gridy = 1;
192 gc.fill = GridBagConstraints.HORIZONTAL;
193 gc.weightx = 1.0;
194 gc.weighty = 1.0;
[8510]195 add(lstLayers, gc);
[2512]196 }
197
[8836]198 LayerListWarningMessagePanel(String msg, List<SaveLayerInfo> infos) {
[2512]199 build();
200 lblMessage.setText(msg);
[7017]201 lstLayers.setListData(infos.toArray(new SaveLayerInfo[0]));
[2512]202 }
203 }
204
205 protected void warnLayersWithConflictsAndUploadRequest(List<SaveLayerInfo> infos) {
206 String msg = trn("<html>{0} layer has unresolved conflicts.<br>"
207 + "Either resolve them first or discard the modifications.<br>"
208 + "Layer with conflicts:</html>",
209 "<html>{0} layers have unresolved conflicts.<br>"
210 + "Either resolve them first or discard the modifications.<br>"
211 + "Layers with conflicts:</html>",
212 infos.size(),
213 infos.size());
214 JOptionPane.showConfirmDialog(
215 Main.parent,
216 new LayerListWarningMessagePanel(msg, infos),
217 tr("Unsaved data and conflicts"),
218 JOptionPane.DEFAULT_OPTION,
219 JOptionPane.WARNING_MESSAGE
220 );
221 }
222
223 protected void warnLayersWithoutFilesAndSaveRequest(List<SaveLayerInfo> infos) {
224 String msg = trn("<html>{0} layer needs saving but has no associated file.<br>"
225 + "Either select a file for this layer or discard the changes.<br>"
226 + "Layer without a file:</html>",
227 "<html>{0} layers need saving but have no associated file.<br>"
228 + "Either select a file for each of them or discard the changes.<br>"
229 + "Layers without a file:</html>",
230 infos.size(),
231 infos.size());
232 JOptionPane.showConfirmDialog(
233 Main.parent,
234 new LayerListWarningMessagePanel(msg, infos),
235 tr("Unsaved data and missing associated file"),
236 JOptionPane.DEFAULT_OPTION,
237 JOptionPane.WARNING_MESSAGE
238 );
239 }
240
241 protected void warnLayersWithIllegalFilesAndSaveRequest(List<SaveLayerInfo> infos) {
242 String msg = trn("<html>{0} layer needs saving but has an associated file<br>"
[2875]243 + "which cannot be written.<br>"
[2512]244 + "Either select another file for this layer or discard the changes.<br>"
245 + "Layer with a non-writable file:</html>",
246 "<html>{0} layers need saving but have associated files<br>"
[2875]247 + "which cannot be written.<br>"
[2512]248 + "Either select another file for each of them or discard the changes.<br>"
249 + "Layers with non-writable files:</html>",
250 infos.size(),
251 infos.size());
252 JOptionPane.showConfirmDialog(
253 Main.parent,
254 new LayerListWarningMessagePanel(msg, infos),
255 tr("Unsaved data non-writable files"),
256 JOptionPane.DEFAULT_OPTION,
257 JOptionPane.WARNING_MESSAGE
258 );
259 }
260
261 protected boolean confirmSaveLayerInfosOK() {
262 List<SaveLayerInfo> layerInfos = model.getLayersWithConflictsAndUploadRequest();
263 if (!layerInfos.isEmpty()) {
264 warnLayersWithConflictsAndUploadRequest(layerInfos);
265 return false;
266 }
267
268 layerInfos = model.getLayersWithoutFilesAndSaveRequest();
269 if (!layerInfos.isEmpty()) {
270 warnLayersWithoutFilesAndSaveRequest(layerInfos);
271 return false;
272 }
273
274 layerInfos = model.getLayersWithIllegalFilesAndSaveRequest();
275 if (!layerInfos.isEmpty()) {
276 warnLayersWithIllegalFilesAndSaveRequest(layerInfos);
277 return false;
278 }
279
280 return true;
281 }
282
283 protected void setUserAction(UserAction action) {
284 this.action = action;
285 }
286
[6965]287 /**
288 * Closes this dialog and frees all native screen resources.
289 */
[3441]290 public void closeDialog() {
291 setVisible(false);
292 dispose();
293 }
294
[2512]295 class WindowClosingAdapter extends WindowAdapter {
296 @Override
297 public void windowClosing(WindowEvent e) {
298 cancelAction.cancel();
299 }
300 }
301
302 class CancelAction extends AbstractAction {
[8836]303 CancelAction() {
[2512]304 putValue(NAME, tr("Cancel"));
305 putValue(SHORT_DESCRIPTION, tr("Close this dialog and resume editing in JOSM"));
306 putValue(SMALL_ICON, ImageProvider.get("cancel"));
[4618]307 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
308 .put(KeyStroke.getKeyStroke("ESCAPE"), "ESCAPE");
309 getRootPane().getActionMap().put("ESCAPE", this);
[2512]310 }
311
312 protected void cancelWhenInEditingModel() {
313 setUserAction(UserAction.CANCEL);
[3441]314 closeDialog();
[2512]315 }
316
317 public void cancel() {
318 switch(model.getMode()) {
[2569]319 case EDITING_DATA: cancelWhenInEditingModel(); break;
320 case UPLOADING_AND_SAVING: cancelSafeAndUploadTask(); break;
[2512]321 }
322 }
323
[6084]324 @Override
[2512]325 public void actionPerformed(ActionEvent e) {
326 cancel();
327 }
328 }
329
330 class DiscardAndProceedAction extends AbstractAction implements PropertyChangeListener {
[8836]331 DiscardAndProceedAction() {
[2512]332 initForDiscardAndExit();
333 }
334
335 public void initForDiscardAndExit() {
[5003]336 putValue(NAME, tr("Exit now!"));
[2512]337 putValue(SHORT_DESCRIPTION, tr("Exit JOSM without saving. Unsaved changes are lost."));
338 putValue(SMALL_ICON, ImageProvider.get("exit"));
339 }
340
341 public void initForDiscardAndDelete() {
[5003]342 putValue(NAME, tr("Delete now!"));
[2512]343 putValue(SHORT_DESCRIPTION, tr("Delete layers without saving. Unsaved changes are lost."));
344 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
345 }
346
[6084]347 @Override
[2512]348 public void actionPerformed(ActionEvent e) {
349 setUserAction(UserAction.PROCEED);
[3441]350 closeDialog();
[2512]351 }
[8510]352
[6084]353 @Override
[2512]354 public void propertyChange(PropertyChangeEvent evt) {
355 if (evt.getPropertyName().equals(SaveLayersModel.MODE_PROP)) {
[8510]356 Mode mode = (Mode) evt.getNewValue();
[2512]357 switch(mode) {
[2569]358 case EDITING_DATA: setEnabled(true); break;
359 case UPLOADING_AND_SAVING: setEnabled(false); break;
[2512]360 }
361 }
362 }
363 }
364
[5003]365 final class SaveAndProceedAction extends AbstractAction implements PropertyChangeListener {
366 private static final int is = 24; // icon size
367 private static final String BASE_ICON = "BASE_ICON";
[8308]368 private final transient Image save = ImageProvider.get("save").getImage();
369 private final transient Image upld = ImageProvider.get("upload").getImage();
370 private final transient Image saveDis = new BufferedImage(is, is, BufferedImage.TYPE_4BYTE_ABGR);
371 private final transient Image upldDis = new BufferedImage(is, is, BufferedImage.TYPE_4BYTE_ABGR);
[5003]372
[8836]373 SaveAndProceedAction() {
[5003]374 // get disabled versions of icons
375 new JLabel(ImageProvider.get("save")).getDisabledIcon().paintIcon(new JPanel(), saveDis.getGraphics(), 0, 0);
376 new JLabel(ImageProvider.get("upload")).getDisabledIcon().paintIcon(new JPanel(), upldDis.getGraphics(), 0, 0);
[2512]377 initForSaveAndExit();
378 }
379
380 public void initForSaveAndExit() {
[5003]381 putValue(NAME, tr("Perform actions before exiting"));
[2512]382 putValue(SHORT_DESCRIPTION, tr("Exit JOSM with saving. Unsaved changes are uploaded and/or saved."));
[5003]383 putValue(BASE_ICON, ImageProvider.get("exit"));
384 redrawIcon();
[2512]385 }
386
387 public void initForSaveAndDelete() {
[5003]388 putValue(NAME, tr("Perform actions before deleting"));
[2512]389 putValue(SHORT_DESCRIPTION, tr("Save/Upload layers before deleting. Unsaved changes are not lost."));
[5003]390 putValue(BASE_ICON, ImageProvider.get("dialogs", "delete"));
391 redrawIcon();
[2512]392 }
393
[5003]394 public void redrawIcon() {
395 try { // Can fail if model is not yet setup properly
396 Image base = ((ImageIcon) getValue(BASE_ICON)).getImage();
397 BufferedImage newIco = new BufferedImage(is*3, is, BufferedImage.TYPE_4BYTE_ABGR);
398 Graphics2D g = newIco.createGraphics();
399 g.drawImage(model.getLayersToUpload().isEmpty() ? upldDis : upld, is*0, 0, is, is, null);
400 g.drawImage(model.getLayersToSave().isEmpty() ? saveDis : save, is*1, 0, is, is, null);
401 g.drawImage(base, is*2, 0, is, is, null);
402 putValue(SMALL_ICON, new ImageIcon(newIco));
[8510]403 } catch (Exception e) {
[5003]404 putValue(SMALL_ICON, getValue(BASE_ICON));
405 }
406 }
407
[6084]408 @Override
[2512]409 public void actionPerformed(ActionEvent e) {
[8444]410 if (!confirmSaveLayerInfosOK())
[2512]411 return;
412 launchSafeAndUploadTask();
413 }
414
[6084]415 @Override
[2512]416 public void propertyChange(PropertyChangeEvent evt) {
417 if (evt.getPropertyName().equals(SaveLayersModel.MODE_PROP)) {
[8510]418 SaveLayersModel.Mode mode = (SaveLayersModel.Mode) evt.getNewValue();
[2512]419 switch(mode) {
[2569]420 case EDITING_DATA: setEnabled(true); break;
421 case UPLOADING_AND_SAVING: setEnabled(false); break;
[2512]422 }
423 }
424 }
425 }
426
427 /**
428 * This is the asynchronous task which uploads modified layers to the server and
429 * saves them to files, if requested by the user.
430 *
431 */
432 protected class SaveAndUploadTask implements Runnable {
433
[8412]434 private final SaveLayersModel model;
435 private final ProgressMonitor monitor;
436 private final ExecutorService worker;
[4310]437 private boolean canceled;
[2512]438 private Future<?> currentFuture;
439 private AbstractIOTask currentTask;
440
441 public SaveAndUploadTask(SaveLayersModel model, ProgressMonitor monitor) {
442 this.model = model;
443 this.monitor = monitor;
[8734]444 this.worker = Executors.newSingleThreadExecutor(Utils.newThreadFactory(getClass() + "-%d", Thread.NORM_PRIORITY));
[2512]445 }
446
447 protected void uploadLayers(List<SaveLayerInfo> toUpload) {
448 for (final SaveLayerInfo layerInfo: toUpload) {
[7402]449 AbstractModifiableLayer layer = layerInfo.getLayer();
[4310]450 if (canceled) {
[7358]451 model.setUploadState(layer, UploadOrSaveState.CANCELED);
[2512]452 continue;
453 }
454 monitor.subTask(tr("Preparing layer ''{0}'' for upload ...", layerInfo.getName()));
455
[7358]456 if (!UploadAction.checkPreUploadConditions(layer)) {
457 model.setUploadState(layer, UploadOrSaveState.FAILED);
[2512]458 continue;
459 }
[7358]460
461 AbstractUploadDialog dialog = layer.getUploadDialog();
462 if (dialog != null) {
463 dialog.setVisible(true);
464 if (dialog.isCanceled()) {
465 model.setUploadState(layer, UploadOrSaveState.CANCELED);
466 continue;
467 }
468 dialog.rememberUserInput();
469 }
470
471 currentTask = layer.createUploadTask(monitor);
472 if (currentTask == null) {
473 model.setUploadState(layer, UploadOrSaveState.FAILED);
[2599]474 continue;
475 }
[2512]476 currentFuture = worker.submit(currentTask);
477 try {
478 // wait for the asynchronous task to complete
479 //
480 currentFuture.get();
[8510]481 } catch (CancellationException e) {
[7358]482 model.setUploadState(layer, UploadOrSaveState.CANCELED);
[8510]483 } catch (Exception e) {
[6643]484 Main.error(e);
[7358]485 model.setUploadState(layer, UploadOrSaveState.FAILED);
[2512]486 ExceptionDialogUtil.explainException(e);
487 }
[4310]488 if (currentTask.isCanceled()) {
[7358]489 model.setUploadState(layer, UploadOrSaveState.CANCELED);
[2512]490 } else if (currentTask.isFailed()) {
[6643]491 Main.error(currentTask.getLastException());
[2512]492 ExceptionDialogUtil.explainException(currentTask.getLastException());
[7358]493 model.setUploadState(layer, UploadOrSaveState.FAILED);
[2512]494 } else {
[7358]495 model.setUploadState(layer, UploadOrSaveState.OK);
[2512]496 }
497 currentTask = null;
498 currentFuture = null;
499 }
500 }
501
502 protected void saveLayers(List<SaveLayerInfo> toSave) {
503 for (final SaveLayerInfo layerInfo: toSave) {
[4310]504 if (canceled) {
505 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.CANCELED);
[2512]506 continue;
507 }
[7204]508 // Check save preconditions earlier to avoid a blocking reentring call to EDT (see #10086)
509 if (layerInfo.isDoCheckSaveConditions()) {
510 if (!layerInfo.getLayer().checkSaveConditions()) {
511 continue;
512 }
513 layerInfo.setDoCheckSaveConditions(false);
514 }
515 currentTask = new SaveLayerTask(layerInfo, monitor);
[2512]516 currentFuture = worker.submit(currentTask);
517
518 try {
519 // wait for the asynchronous task to complete
520 //
521 currentFuture.get();
[8510]522 } catch (CancellationException e) {
[4310]523 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.CANCELED);
[8510]524 } catch (Exception e) {
[6643]525 Main.error(e);
[2512]526 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.FAILED);
527 ExceptionDialogUtil.explainException(e);
528 }
[4310]529 if (currentTask.isCanceled()) {
530 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.CANCELED);
[2512]531 } else if (currentTask.isFailed()) {
532 if (currentTask.getLastException() != null) {
[6643]533 Main.error(currentTask.getLastException());
[2512]534 ExceptionDialogUtil.explainException(currentTask.getLastException());
535 }
536 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.FAILED);
537 } else {
538 model.setSaveState(layerInfo.getLayer(), UploadOrSaveState.OK);
539 }
540 this.currentTask = null;
541 this.currentFuture = null;
542 }
543 }
544
545 protected void warnBecauseOfUnsavedData() {
546 int numProblems = model.getNumCancel() + model.getNumFailed();
547 if (numProblems == 0) return;
[8474]548 Main.warn(numProblems + " problems occured during upload/save");
[2848]549 String msg = trn(
[2512]550 "<html>An upload and/or save operation of one layer with modifications<br>"
[4310]551 + "was canceled or has failed.</html>",
[2512]552 "<html>Upload and/or save operations of {0} layers with modifications<br>"
[4310]553 + "were canceled or have failed.</html>",
[2512]554 numProblems,
555 numProblems
556 );
557 JOptionPane.showMessageDialog(
558 Main.parent,
559 msg,
560 tr("Incomplete upload and/or save"),
561 JOptionPane.WARNING_MESSAGE
562 );
563 }
564
[6084]565 @Override
[2512]566 public void run() {
[6965]567 GuiHelper.runInEDTAndWait(new Runnable() {
568 @Override
569 public void run() {
570 model.setMode(SaveLayersModel.Mode.UPLOADING_AND_SAVING);
571 List<SaveLayerInfo> toUpload = model.getLayersToUpload();
572 if (!toUpload.isEmpty()) {
573 uploadLayers(toUpload);
574 }
575 List<SaveLayerInfo> toSave = model.getLayersToSave();
576 if (!toSave.isEmpty()) {
577 saveLayers(toSave);
578 }
579 model.setMode(SaveLayersModel.Mode.EDITING_DATA);
580 if (model.hasUnsavedData()) {
581 warnBecauseOfUnsavedData();
582 model.setMode(Mode.EDITING_DATA);
583 if (canceled) {
584 setUserAction(UserAction.CANCEL);
585 closeDialog();
586 }
587 } else {
588 setUserAction(UserAction.PROCEED);
589 closeDialog();
590 }
[2512]591 }
[6965]592 });
[8412]593 worker.shutdownNow();
[2512]594 }
595
596 public void cancel() {
597 if (currentTask != null) {
598 currentTask.cancel();
599 }
[8412]600 worker.shutdown();
[4310]601 canceled = true;
[2512]602 }
603 }
[5003]604
605 @Override
606 public void tableChanged(TableModelEvent arg0) {
607 boolean dis = model.getLayersToSave().isEmpty() && model.getLayersToUpload().isEmpty();
[8510]608 if (saveAndProceedActionButton != null) {
[5003]609 saveAndProceedActionButton.setEnabled(!dis);
610 }
611 saveAndProceedAction.redrawIcon();
612 }
[2512]613}
Note: See TracBrowser for help on using the repository browser.