~ubuntu-branches/ubuntu/utopic/gpsprune/utopic

« back to all changes in this revision

Viewing changes to tim/prune/save/BaseImageConfigDialog.java

  • Committer: Package Import Robot
  • Author(s): Mònica Ramírez Arceda
  • Date: 2013-05-15 10:26:51 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130515102651-130bcw88wox3u0q0
Tags: 15-1
* New upstream version
  - "nautical mile" is added to unit selector (Closes: #639503)
* debian/control:
  - Add myself as an uploader
  - Standards-Version bump to 3.9.4, no changes needed
* debian/copyright:
  - Add required Copyright field to tim/prune/function/srtm/gen/ files
  - Update years
* debian/scripts/gpsprune:
  - Fix sed commands, when there is no host/port, proxyhost/proxyport
    variables must be empty.
    Thanks to Simó Albert i Beltran <sim6@probeta.net> and to
    <debian@activityworkshop.net> for the patch!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package tim.prune.save;
 
2
 
 
3
import java.awt.BorderLayout;
 
4
import java.awt.Color;
 
5
import java.awt.Component;
 
6
import java.awt.FlowLayout;
 
7
import java.awt.GridLayout;
 
8
import java.awt.event.ActionEvent;
 
9
import java.awt.event.ActionListener;
 
10
import java.awt.event.KeyAdapter;
 
11
import java.awt.event.KeyEvent;
 
12
import java.io.File;
 
13
 
 
14
import javax.swing.BorderFactory;
 
15
import javax.swing.JButton;
 
16
import javax.swing.JCheckBox;
 
17
import javax.swing.JComboBox;
 
18
import javax.swing.JDialog;
 
19
import javax.swing.JLabel;
 
20
import javax.swing.JPanel;
 
21
 
 
22
import tim.prune.DataSubscriber;
 
23
import tim.prune.I18nManager;
 
24
import tim.prune.config.Config;
 
25
import tim.prune.data.Track;
 
26
import tim.prune.gui.map.MapSource;
 
27
import tim.prune.gui.map.MapSourceLibrary;
 
28
 
 
29
/**
 
30
 * Dialog to let you choose the parameters for a base image
 
31
 * (source and zoom)
 
32
 */
 
33
public class BaseImageConfigDialog implements Runnable
 
34
{
 
35
        /** Parent to notify */
 
36
        private DataSubscriber _parent = null;
 
37
        /** Parent dialog for position */
 
38
        private JDialog _parentDialog = null;
 
39
        /** Track to use for preview image */
 
40
        private Track _track = null;
 
41
        /** Dialog to show */
 
42
        private JDialog _dialog = null;
 
43
        /** Checkbox for using an image or not */
 
44
        private JCheckBox _useImageCheckbox = null;
 
45
        /** Panel to hold the other controls */
 
46
        private JPanel _mainPanel = null;
 
47
        /** Dropdown for map source */
 
48
        private JComboBox _mapSourceDropdown = null;
 
49
        /** Dropdown for zoom levels */
 
50
        private JComboBox _zoomDropdown = null;
 
51
        /** Warning label that image is incomplete */
 
52
        private JLabel _imageIncompleteLabel = null;
 
53
        /** Label for number of tiles found */
 
54
        private JLabel _tilesFoundLabel = null;
 
55
        /** Label for image size in pixels */
 
56
        private JLabel _imageSizeLabel = null;
 
57
        /** Image preview panel */
 
58
        private ImagePreviewPanel _previewPanel = null;
 
59
        /** OK button, needs to be enabled/disabled */
 
60
        private JButton _okButton = null;
 
61
        /** Flag for rebuilding dialog, don't bother refreshing and recalculating */
 
62
        private boolean _rebuilding = false;
 
63
        /** Cached values to allow cancellation of dialog */
 
64
        private boolean        _useImage = false;
 
65
        private int            _sourceIndex = 0;
 
66
        private int            _zoomLevel = 0;
 
67
 
 
68
 
 
69
        /**
 
70
         * Constructor
 
71
         * @param inParent parent object to notify on completion of dialog
 
72
         * @param inParentDialog parent dialog
 
73
         * @param inTrack track object
 
74
         */
 
75
        public BaseImageConfigDialog(DataSubscriber inParent, JDialog inParentDialog, Track inTrack)
 
76
        {
 
77
                _parent = inParent;
 
78
                _parentDialog = inParentDialog;
 
79
                _dialog = new JDialog(inParentDialog, I18nManager.getText("dialog.baseimage.title"), true);
 
80
                _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
 
81
                _dialog.getContentPane().add(makeDialogComponents());
 
82
                _dialog.pack();
 
83
                _track = inTrack;
 
84
        }
 
85
 
 
86
        /**
 
87
         * Begin the function
 
88
         */
 
89
        public void begin()
 
90
        {
 
91
                initDialog();
 
92
                _dialog.setLocationRelativeTo(_parentDialog);
 
93
                _dialog.setVisible(true);
 
94
        }
 
95
 
 
96
        /**
 
97
         * Begin the function with a default of using an image
 
98
         */
 
99
        public void beginWithImageYes()
 
100
        {
 
101
                initDialog();
 
102
                _useImageCheckbox.setSelected(true);
 
103
                refreshDialog();
 
104
                _dialog.setVisible(true);
 
105
        }
 
106
 
 
107
        /**
 
108
         * Initialise the dialog from the cached values
 
109
         */
 
110
        private void initDialog()
 
111
        {
 
112
                _rebuilding = true;
 
113
                _useImageCheckbox.setSelected(_useImage);
 
114
                // Populate the dropdown of map sources from the library in case it has changed
 
115
                _mapSourceDropdown.removeAllItems();
 
116
                for (int i=0; i<MapSourceLibrary.getNumSources(); i++)
 
117
                {
 
118
                        _mapSourceDropdown.addItem(MapSourceLibrary.getSource(i).getName());
 
119
                }
 
120
                if (_sourceIndex < 0 || _sourceIndex >= _mapSourceDropdown.getItemCount()) {
 
121
                        _sourceIndex = 0;
 
122
                }
 
123
                _mapSourceDropdown.setSelectedIndex(_sourceIndex);
 
124
 
 
125
                // Zoom level
 
126
                if (_useImage)
 
127
                {
 
128
                        for (int i=0; i<_zoomDropdown.getItemCount(); i++)
 
129
                        {
 
130
                                String item = _zoomDropdown.getItemAt(i).toString();
 
131
                                try {
 
132
                                        if (Integer.parseInt(item) == _zoomLevel) {
 
133
                                                _zoomDropdown.setSelectedIndex(i);
 
134
                                                break;
 
135
                                        }
 
136
                                }
 
137
                                catch (NumberFormatException nfe) {}
 
138
                        }
 
139
                }
 
140
                _rebuilding = false;
 
141
                refreshDialog();
 
142
        }
 
143
 
 
144
        /**
 
145
         * Update the visibility of the controls, and update the zoom dropdown based on the selected map source
 
146
         */
 
147
        private void refreshDialog()
 
148
        {
 
149
                _mainPanel.setVisible(_useImageCheckbox.isSelected());
 
150
                // Exit if we're in the middle of something
 
151
                if (_rebuilding) {return;}
 
152
                int currentZoom = 0;
 
153
                try {
 
154
                        currentZoom = Integer.parseInt(_zoomDropdown.getSelectedItem().toString());
 
155
                }
 
156
                catch (Exception nfe) {}
 
157
                // Get the extent of the track so we can work out how big the images are going to be for each zoom level
 
158
                // System.out.println("Ranges are: x=" + _track.getXRange().getRange() + ", y=" +  _track.getYRange().getRange());
 
159
                final double xyExtent = Math.max(_track.getXRange().getRange(), _track.getYRange().getRange());
 
160
                int zoomToSelect = -1;
 
161
 
 
162
                _rebuilding = true;
 
163
                _zoomDropdown.removeAllItems();
 
164
                if (_useImageCheckbox.isSelected() && _mapSourceDropdown.getItemCount() > 0)
 
165
                {
 
166
                        int currentSource = _mapSourceDropdown.getSelectedIndex();
 
167
                        for (int i=5; i<18; i++)
 
168
                        {
 
169
                                // How many pixels does this give?
 
170
                                final int zoomFactor = 1 << i;
 
171
                                final int pixCount = (int) (xyExtent * zoomFactor * 256);
 
172
                                if (pixCount > 100      // less than this isn't worth it
 
173
                                        && pixCount < 4000  // don't want to run out of memory
 
174
                                        && isZoomAvailable(i, MapSourceLibrary.getSource(currentSource)))
 
175
                                {
 
176
                                        _zoomDropdown.addItem("" + i);
 
177
                                        if (i == currentZoom) {
 
178
                                                zoomToSelect = _zoomDropdown.getItemCount() - 1;
 
179
                                        }
 
180
                                }
 
181
                                // else System.out.println("Not using zoom " + i + " because pixCount=" + pixCount + " and xyExtent=" + xyExtent);
 
182
                        }
 
183
                }
 
184
                _zoomDropdown.setSelectedIndex(zoomToSelect);
 
185
                _rebuilding = false;
 
186
 
 
187
                _okButton.setEnabled(!_useImageCheckbox.isSelected() ||
 
188
                        (_zoomDropdown.getItemCount() > 0 && _zoomDropdown.getSelectedIndex() >= 0));
 
189
                updateImagePreview();
 
190
        }
 
191
 
 
192
        /**
 
193
         * @return true if it should be possible to use an image, false if no disk cache or cache empty
 
194
         */
 
195
        public static boolean isImagePossible()
 
196
        {
 
197
                String path = Config.getConfigString(Config.KEY_DISK_CACHE);
 
198
                if (path != null && !path.equals(""))
 
199
                {
 
200
                        File cacheDir = new File(path);
 
201
                        if (cacheDir.exists() && cacheDir.isDirectory())
 
202
                        {
 
203
                                // Check if there are any directories in the cache
 
204
                                for (File subdir : cacheDir.listFiles())
 
205
                                {
 
206
                                        if (subdir.exists() && subdir.isDirectory()) {
 
207
                                                return true;
 
208
                                        }
 
209
                                }
 
210
                        }
 
211
                }
 
212
                return false;
 
213
        }
 
214
 
 
215
        /**
 
216
         * See if the requested zoom level is available
 
217
         * @param inZoom zoom level
 
218
         * @param inSource selected map source
 
219
         * @return true if there is a zoom directory for each of the source's layers
 
220
         */
 
221
        private static boolean isZoomAvailable(int inZoom, MapSource inSource)
 
222
        {
 
223
                if (inSource == null) {return false;}
 
224
                String path = Config.getConfigString(Config.KEY_DISK_CACHE);
 
225
                if (path == null || path.equals("")) {
 
226
                        return false;
 
227
                }
 
228
                File cacheDir = new File(path);
 
229
                if (!cacheDir.exists() || !cacheDir.isDirectory()) {
 
230
                        return false;
 
231
                }
 
232
                // First layer
 
233
                File layer0 = new File(cacheDir, inSource.getSiteName(0) + inZoom);
 
234
                if (!layer0.exists() || !layer0.isDirectory() || !layer0.canRead()) {
 
235
                        return false;
 
236
                }
 
237
                // Second layer, if any
 
238
                if (inSource.getNumLayers() > 1)
 
239
                {
 
240
                        File layer1 = new File(cacheDir, inSource.getSiteName(1) + inZoom);
 
241
                        if (!layer1.exists() || !layer1.isDirectory() || !layer1.canRead()) {
 
242
                                return false;
 
243
                        }
 
244
                }
 
245
                // must be ok
 
246
                return true;
 
247
        }
 
248
 
 
249
 
 
250
        /**
 
251
         * @return true if image has been selected
 
252
         */
 
253
        public boolean useImage() {
 
254
                return _useImage;
 
255
        }
 
256
 
 
257
        /**
 
258
         * @return index of selected image source
 
259
         */
 
260
        public int getSourceIndex() {
 
261
                return _sourceIndex;
 
262
        }
 
263
 
 
264
        /**
 
265
         * @return selected zoom level
 
266
         */
 
267
        public int getZoomLevel() {
 
268
                return _zoomLevel;
 
269
        }
 
270
 
 
271
        /**
 
272
         * Make the dialog components to select the options
 
273
         * @return Component holding gui elements
 
274
         */
 
275
        private Component makeDialogComponents()
 
276
        {
 
277
                JPanel panel = new JPanel();
 
278
                panel.setLayout(new BorderLayout());
 
279
                _useImageCheckbox = new JCheckBox(I18nManager.getText("dialog.baseimage.useimage"));
 
280
                _useImageCheckbox.setBorder(BorderFactory.createEmptyBorder(4, 4, 6, 4));
 
281
                _useImageCheckbox.setHorizontalAlignment(JLabel.CENTER);
 
282
                _useImageCheckbox.addActionListener(new ActionListener() {
 
283
                        public void actionPerformed(ActionEvent arg0) {
 
284
                                refreshDialog();
 
285
                        }
 
286
                });
 
287
                panel.add(_useImageCheckbox, BorderLayout.NORTH);
 
288
 
 
289
                // Outer panel with the grid and the map preview
 
290
                _mainPanel = new JPanel();
 
291
                _mainPanel.setLayout(new BorderLayout(1, 10));
 
292
                // Central stuff with labels and dropdowns
 
293
                JPanel controlsPanel = new JPanel();
 
294
                controlsPanel.setLayout(new GridLayout(0, 2, 10, 4));
 
295
                // map source
 
296
                JLabel sourceLabel = new JLabel(I18nManager.getText("dialog.baseimage.mapsource") + ": ");
 
297
                sourceLabel.setHorizontalAlignment(JLabel.RIGHT);
 
298
                controlsPanel.add(sourceLabel);
 
299
                _mapSourceDropdown = new JComboBox();
 
300
                _mapSourceDropdown.addItem("name of map source");
 
301
                // Add listener to dropdown to change zoom levels
 
302
                _mapSourceDropdown.addActionListener(new ActionListener() {
 
303
                        public void actionPerformed(ActionEvent arg0) {
 
304
                                refreshDialog();
 
305
                        }
 
306
                });
 
307
                controlsPanel.add(_mapSourceDropdown);
 
308
                // zoom level
 
309
                JLabel zoomLabel = new JLabel(I18nManager.getText("dialog.baseimage.zoom") + ": ");
 
310
                zoomLabel.setHorizontalAlignment(JLabel.RIGHT);
 
311
                controlsPanel.add(zoomLabel);
 
312
                _zoomDropdown = new JComboBox();
 
313
                // Add action listener to enable ok button when zoom changed
 
314
                _zoomDropdown.addActionListener(new ActionListener() {
 
315
                        public void actionPerformed(ActionEvent arg0) {
 
316
                                if (_zoomDropdown.getSelectedIndex() >= 0) {
 
317
                                        _okButton.setEnabled(true);
 
318
                                        updateImagePreview();
 
319
                                }
 
320
                        }
 
321
                });
 
322
                controlsPanel.add(_zoomDropdown);
 
323
                _mainPanel.add(controlsPanel, BorderLayout.NORTH);
 
324
 
 
325
                JPanel imagePanel = new JPanel();
 
326
                imagePanel.setLayout(new BorderLayout(10, 1));
 
327
                // image preview
 
328
                _previewPanel = new ImagePreviewPanel();
 
329
                imagePanel.add(_previewPanel, BorderLayout.CENTER);
 
330
 
 
331
                // Label panel on right
 
332
                JPanel labelPanel = new JPanel();
 
333
                labelPanel.setLayout(new BorderLayout());
 
334
                _imageIncompleteLabel = new JLabel(I18nManager.getText("dialog.baseimage.incomplete"));
 
335
                _imageIncompleteLabel.setForeground(Color.RED);
 
336
                _imageIncompleteLabel.setVisible(false);
 
337
                labelPanel.add(_imageIncompleteLabel, BorderLayout.NORTH);
 
338
                JPanel labelGridPanel = new JPanel();
 
339
                labelGridPanel.setLayout(new GridLayout(0, 2, 10, 4));
 
340
                labelGridPanel.add(new JLabel(I18nManager.getText("dialog.baseimage.tiles") + ": "));
 
341
                _tilesFoundLabel = new JLabel("11 / 11");
 
342
                labelGridPanel.add(_tilesFoundLabel);
 
343
                labelGridPanel.add(new JLabel(I18nManager.getText("dialog.baseimage.size") + ": "));
 
344
                _imageSizeLabel = new JLabel("1430");
 
345
                labelGridPanel.add(_imageSizeLabel);
 
346
                labelGridPanel.add(new JLabel(" ")); // just for spacing
 
347
                labelPanel.add(labelGridPanel, BorderLayout.SOUTH);
 
348
                imagePanel.add(labelPanel, BorderLayout.EAST);
 
349
 
 
350
                _mainPanel.add(imagePanel, BorderLayout.CENTER);
 
351
                panel.add(_mainPanel, BorderLayout.CENTER);
 
352
 
 
353
                // OK, Cancel buttons
 
354
                JPanel buttonPanel = new JPanel();
 
355
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
 
356
                _okButton = new JButton(I18nManager.getText("button.ok"));
 
357
                _okButton.addActionListener(new ActionListener() {
 
358
                        public void actionPerformed(ActionEvent e)
 
359
                        {
 
360
                                // Check values, maybe don't want to exit
 
361
                                if (!_useImageCheckbox.isSelected()
 
362
                                        || (_mapSourceDropdown.getSelectedIndex() >= 0 && _zoomDropdown.getSelectedIndex() >= 0))
 
363
                                {
 
364
                                        storeValues();
 
365
                                        _dialog.dispose();
 
366
                                }
 
367
                        }
 
368
                });
 
369
                buttonPanel.add(_okButton);
 
370
                JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
 
371
                cancelButton.addActionListener(new ActionListener() {
 
372
                        public void actionPerformed(ActionEvent e)
 
373
                        {
 
374
                                _dialog.dispose();
 
375
                        }
 
376
                });
 
377
                buttonPanel.add(cancelButton);
 
378
                panel.add(buttonPanel, BorderLayout.SOUTH);
 
379
 
 
380
                // Listener to close dialog if escape pressed
 
381
                KeyAdapter closer = new KeyAdapter() {
 
382
                        public void keyReleased(KeyEvent e)
 
383
                        {
 
384
                                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
 
385
                                        _dialog.dispose();
 
386
                                }
 
387
                        }
 
388
                };
 
389
                _useImageCheckbox.addKeyListener(closer);
 
390
                _mapSourceDropdown.addKeyListener(closer);
 
391
                _zoomDropdown.addKeyListener(closer);
 
392
                _okButton.addKeyListener(closer);
 
393
                cancelButton.addKeyListener(closer);
 
394
 
 
395
                return panel;
 
396
        }
 
397
 
 
398
        /**
 
399
         * Use the selected settings to make a preview image and (asynchronously) update the preview panel
 
400
         */
 
401
        private void updateImagePreview()
 
402
        {
 
403
                // Clear labels
 
404
                _imageIncompleteLabel.setVisible(false);
 
405
                _tilesFoundLabel.setText("");
 
406
                _imageSizeLabel.setText("");
 
407
                if (_useImageCheckbox.isSelected() && _mapSourceDropdown.getSelectedIndex() >= 0
 
408
                        && _zoomDropdown.getItemCount() > 0 && _zoomDropdown.getSelectedIndex() >= 0)
 
409
                {
 
410
                        _previewPanel.startLoading();
 
411
                        // Launch a separate thread to create an image and pass it to the preview panel
 
412
                        new Thread(this).start();
 
413
                }
 
414
                else {
 
415
                        // clear preview
 
416
                        _previewPanel.setImage(null);
 
417
                }
 
418
        }
 
419
 
 
420
        /**
 
421
         * Store the selected details in the variables
 
422
         */
 
423
        private void storeValues()
 
424
        {
 
425
                // Store values of controls in variables
 
426
                _useImage = _useImageCheckbox.isSelected();
 
427
                _sourceIndex = _mapSourceDropdown.getSelectedIndex();
 
428
                try {
 
429
                        String zoomStr = _zoomDropdown.getSelectedItem().toString();
 
430
                        _zoomLevel = Integer.parseInt(zoomStr);
 
431
                }
 
432
                catch (Exception nfe) {
 
433
                        _zoomLevel = 0;
 
434
                }
 
435
                // Call parent to retrieve values
 
436
                _parent.dataUpdated(DataSubscriber.ALL);
 
437
        }
 
438
 
 
439
        /**
 
440
         * Run method for separate thread.  Uses the current dialog parameters
 
441
         * to trigger a call to the Grouter, and pass the image to the preview panel
 
442
         */
 
443
        public void run()
 
444
        {
 
445
                // Remember the current dropdown indices, so we know whether they've changed or not
 
446
                final int mapIndex = _mapSourceDropdown.getSelectedIndex();
 
447
                final int zoomIndex = _zoomDropdown.getSelectedIndex();
 
448
                if (!_useImageCheckbox.isSelected() || mapIndex < 0 || zoomIndex < 0) {return;}
 
449
 
 
450
                // Get the map source and zoom level
 
451
                MapSource mapSource = MapSourceLibrary.getSource(mapIndex);
 
452
                int zoomLevel = 0;
 
453
                try {
 
454
                        zoomLevel = Integer.parseInt(_zoomDropdown.getSelectedItem().toString());
 
455
                }
 
456
                catch (Exception e) {}
 
457
 
 
458
                // Use the Grouter to create an image (slow, blocks thread)
 
459
                GroutedImage groutedImage = MapGrouter.createMapImage(_track, mapSource, zoomLevel);
 
460
 
 
461
                // If the dialog hasn't changed, pass the generated image to the preview panel
 
462
                if (_useImageCheckbox.isSelected()
 
463
                        && _mapSourceDropdown.getSelectedIndex() == mapIndex
 
464
                        && _zoomDropdown.getSelectedIndex() == zoomIndex
 
465
                        && groutedImage != null)
 
466
                {
 
467
                        _previewPanel.setImage(groutedImage);
 
468
                        // Set values of labels
 
469
                        _imageIncompleteLabel.setVisible(!groutedImage.isComplete());
 
470
                        _tilesFoundLabel.setText(groutedImage.getNumTilesUsed() + " / " + groutedImage.getNumTilesTotal());
 
471
                        if (groutedImage.getImageSize() > 0) {
 
472
                                _imageSizeLabel.setText("" + groutedImage.getImageSize());
 
473
                        }
 
474
                        else {
 
475
                                _imageSizeLabel.setText("");
 
476
                        }
 
477
                }
 
478
                else
 
479
                {
 
480
                        _previewPanel.setImage(null);
 
481
                        // Clear labels
 
482
                        _imageIncompleteLabel.setVisible(false);
 
483
                        _tilesFoundLabel.setText("");
 
484
                        _imageSizeLabel.setText("");
 
485
                }
 
486
        }
 
487
 
 
488
        /**
 
489
         * @return true if any map data has been found for the image
 
490
         */
 
491
        public boolean getFoundData()
 
492
        {
 
493
                return _useImage && _zoomLevel > 0 && _previewPanel != null && _previewPanel.getTilesFound();
 
494
        }
 
495
}