source: subversion/applications/editors/josm/plugins/imagery_offset_db/src/org/openstreetmap/josm/plugins/imagery_offset_db/GetImageryOffsetAction.java

Last change on this file was 34596, checked in by donvip, 8 months ago

rename package, fix warnings

File size: 6.6 KB
Line 
1// License: WTFPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins.imagery_offset_db;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.event.KeyEvent;
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.UnsupportedEncodingException;
11import java.net.URLEncoder;
12import java.util.List;
13
14import javax.swing.Action;
15import javax.swing.Icon;
16import javax.swing.JOptionPane;
17
18import org.openstreetmap.josm.actions.JosmAction;
19import org.openstreetmap.josm.data.coor.LatLon;
20import org.openstreetmap.josm.data.coor.conversion.DecimalDegreesCoordinateFormat;
21import org.openstreetmap.josm.data.projection.Projection;
22import org.openstreetmap.josm.gui.MainApplication;
23import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
24import org.openstreetmap.josm.spi.preferences.Config;
25import org.openstreetmap.josm.tools.ImageProvider;
26import org.openstreetmap.josm.tools.Shortcut;
27import org.xml.sax.SAXException;
28
29/**
30 * Download a list of imagery offsets for the current position, let user choose which one to use.
31 *
32 * @author Zverik
33 * @license WTFPL
34 */
35public class GetImageryOffsetAction extends JosmAction implements ImageryOffsetWatcher.OffsetStateListener {
36    private Icon iconOffsetOk;
37    private Icon iconOffsetBad;
38
39    /**
40     * Initialize the action. Sets "Ctrl+Alt+I" shortcut: the only shortcut in this plugin.
41     * Also registers itself with {@link ImageryOffsetWatcher}.
42     */
43    public GetImageryOffsetAction() {
44        super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"),
45                Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")),
46                        KeyEvent.VK_I, Shortcut.ALT_CTRL), true);
47        iconOffsetOk = new ImageProvider("getoffset").setSize(ImageProvider.ImageSizes.MENU).get();
48        iconOffsetBad = new ImageProvider("getoffsetnow").setSize(ImageProvider.ImageSizes.MENU).get();
49        ImageryOffsetWatcher.getInstance().register(this);
50    }
51
52    /**
53     * The action just executes {@link DownloadOffsetsTask}.
54     */
55    @Override
56    public void actionPerformed(ActionEvent e) {
57        if (!MainApplication.isDisplayingMapView() || !MainApplication.getMap().isVisible())
58            return;
59        Projection proj = MainApplication.getMap().mapView.getProjection();
60        LatLon center = proj.eastNorth2latlon(MainApplication.getMap().mapView.getCenter());
61        AbstractTileSourceLayer<?> layer = ImageryOffsetTools.getTopImageryLayer();
62        String imagery = ImageryOffsetTools.getImageryID(layer);
63        if (imagery == null)
64            return;
65
66        DownloadOffsetsTask download = new DownloadOffsetsTask(center, layer, imagery);
67        MainApplication.worker.submit(download);
68    }
69
70    /**
71     * This action is enabled when there's a map, mapView and one of the layers
72     * is an imagery layer.
73     */
74    @Override
75    protected void updateEnabledState() {
76        boolean state = true;
77        if (!MainApplication.isDisplayingMapView() || !MainApplication.getMap().isVisible())
78            state = false;
79        AbstractTileSourceLayer<?> layer = ImageryOffsetTools.getTopImageryLayer();
80        if (ImageryOffsetTools.getImageryID(layer) == null)
81            state = false;
82        setEnabled(state);
83    }
84
85    /**
86     * Display a dialog for choosing between offsets. If there are no offsets in
87     * the list, displays the relevant message instead.
88     * @param offsets List of offset objects to choose from.
89     */
90    private void showOffsetDialog(List<ImageryOffsetBase> offsets) {
91        if (offsets.isEmpty()) {
92            JOptionPane.showMessageDialog(MainApplication.getMainFrame(),
93                    tr("No data for this region. Please adjust imagery layer and upload an offset."),
94                    ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE);
95            return;
96        }
97        OffsetDialog offsetDialog = new OffsetDialog(offsets);
98        if (offsetDialog.showDialog() != null)
99            offsetDialog.applyOffset();
100    }
101
102    /**
103     * Update action icon based on an offset state.
104     */
105    @Override
106    public void offsetStateChanged(boolean isOffsetGood) {
107        putValue(Action.SMALL_ICON, isOffsetGood ? iconOffsetOk : iconOffsetBad);
108    }
109
110    /**
111     * Remove offset listener.
112     */
113    @Override
114    public void destroy() {
115        ImageryOffsetWatcher.getInstance().unregister(this);
116        super.destroy();
117    }
118
119    /**
120     * A task that downloads offsets for a given position and imagery layer,
121     * then parses resulting XML and calls
122     * {@link #showOffsetDialog(java.util.List)} on success.
123     */
124    private class DownloadOffsetsTask extends SimpleOffsetQueryTask {
125        private List<ImageryOffsetBase> offsets;
126
127        /**
128         * Initializes query object from the parameters.
129         * @param center A center point of a map view.
130         * @param layer The topmost imagery layer.
131         * @param imagery Imagery ID for the layer.
132         */
133        DownloadOffsetsTask(LatLon center, AbstractTileSourceLayer<?> layer, String imagery) {
134            super(null, tr("Loading imagery offsets..."));
135            try {
136                String query = "get?lat=" + DecimalDegreesCoordinateFormat.INSTANCE.latToString(center)
137                + "&lon=" + DecimalDegreesCoordinateFormat.INSTANCE.lonToString(center)
138                + "&imagery=" + URLEncoder.encode(imagery, "UTF8");
139                int radius = Config.getPref().getInt("iodb.radius", -1);
140                if (radius > 0)
141                    query = query + "&radius=" + radius;
142                setQuery(query);
143            } catch (UnsupportedEncodingException e) {
144                throw new IllegalArgumentException(e);
145            }
146        }
147
148        /**
149         * Displays offset dialog on success.
150         */
151        @Override
152        protected void afterFinish() {
153            if (!cancelled && offsets != null)
154                showOffsetDialog(offsets);
155        }
156
157        /**
158         * Parses the response with {@link IODBReader}.
159         * @param inp Response input stream.
160         * @throws org.openstreetmap.josm.plugins.imagery_offset_db.SimpleOffsetQueryTask.UploadException Thrown on XML parsing error.
161         */
162        @Override
163        protected void processResponse(InputStream inp) throws UploadException {
164            offsets = null;
165            try {
166                offsets = new IODBReader(inp).parse();
167            } catch (IOException | SAXException e) {
168                throw new UploadException(tr("Error processing XML response: {0}", e.getMessage()));
169            }
170        }
171    }
172}
Note: See TracBrowser for help on using the repository browser.