source: subversion/applications/editors/josm/plugins/roadsigns/src/org/openstreetmap/josm/plugins/roadsigns/RoadSignsPlugin.java

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

update to JOSM 14153

  • Property svn:eol-style set to native
File size: 10.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins.roadsigns;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Dimension;
7import java.awt.FlowLayout;
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.io.File;
11import java.io.FileInputStream;
12import java.io.IOException;
13import java.io.InputStream;
14import java.net.MalformedURLException;
15import java.net.URL;
16import java.util.ArrayList;
17import java.util.Arrays;
18import java.util.Collection;
19import java.util.List;
20import java.util.Objects;
21
22import javax.swing.BorderFactory;
23import javax.swing.JButton;
24import javax.swing.JOptionPane;
25
26import org.openstreetmap.josm.actions.JosmAction;
27import org.openstreetmap.josm.data.StructUtils;
28import org.openstreetmap.josm.data.StructUtils.StructEntry;
29import org.openstreetmap.josm.gui.ExtendedDialog;
30import org.openstreetmap.josm.gui.MainApplication;
31import org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog;
32import org.openstreetmap.josm.io.CachedFile;
33import org.openstreetmap.josm.plugins.Plugin;
34import org.openstreetmap.josm.plugins.PluginInformation;
35import org.openstreetmap.josm.plugins.roadsigns.RoadSignInputDialog.SettingsPanel;
36import org.openstreetmap.josm.spi.preferences.Config;
37import org.openstreetmap.josm.tools.Shortcut;
38import org.openstreetmap.josm.tools.Utils;
39import org.xml.sax.SAXException;
40
41public class RoadSignsPlugin extends Plugin {
42    static PresetMetaData selectedPreset;
43    public static List<Sign> signs;
44    public static List<String> iconDirs;
45
46    public static RoadSignsPlugin plugin;
47
48    public static final PresetMetaData PRESET_BE = new PresetMetaData(
49            "BE", tr("Belgium"), "resource://data/roadsignpresetBE.xml", "resource://images/BE/");
50    public static final PresetMetaData PRESET_ES = new PresetMetaData(
51            "ES", tr("Spain"), "resource://data/roadsignpresetES.xml", "resource://images/ES/");
52    public static final PresetMetaData PRESET_DE = new PresetMetaData(
53            "DE", tr("Germany"), "resource://data/roadsignpresetDE.xml", "resource://images/DE/");
54    public static final PresetMetaData PRESET_PL = new PresetMetaData(
55            "PL", tr("Poland"), "resource://data/roadsignpresetPL.xml", "resource://images/PL/");
56    public static final PresetMetaData PRESET_SK = new PresetMetaData(
57            "SK", tr("Slovakia"), "resource://data/roadsignpresetSK.xml", "resource://images/SK/");
58    public static final Collection<PresetMetaData> DEFAULT_PRESETS = Arrays.asList(PRESET_BE, PRESET_ES, PRESET_DE, PRESET_PL, PRESET_SK);
59
60    public RoadSignsPlugin(PluginInformation info) {
61        super(info);
62        plugin = this;
63        registerAction();
64    }
65
66    public static File pluginDir() {
67        File dir = plugin.getPluginDirs().getUserDataDirectory(false);
68        if (!dir.exists()) {
69            dir.mkdirs();
70        }
71        return dir;
72    }
73
74    private void registerAction() {
75        JButton btn = new JButton(new RoadSignAction());
76        btn.setText(null);
77        btn.setBorder(BorderFactory.createEmptyBorder());
78        btn.setPreferredSize(new Dimension(18, 18));
79        PropertiesDialog.pluginHook.add(btn);
80        PropertiesDialog.pluginHook.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
81        PropertiesDialog.pluginHook.revalidate();
82    }
83
84    private static class RoadSignAction extends JosmAction {
85        RoadSignAction() {
86            super(tr("Roadsign tagging"), "pref/roadsigns-small", tr("Add tags by clicking on road signs"),
87                    Shortcut.registerShortcut("plugin:roadsigns:dialog", tr("Roadsigns plugin: open dialog"),
88                            KeyEvent.VK_Q, Shortcut.ALT_SHIFT), false);
89        }
90
91        @Override
92        public void actionPerformed(ActionEvent e) {
93            String code = Config.getPref().get("plugin.roadsigns.preset.selection", null);
94            if (code == null) {
95                ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(), tr("Settings"), new String[] {tr("Ok"), tr("Cancel")});
96                ed.setButtonIcons(new String[] {"ok", "cancel"});
97                SettingsPanel settings = new SettingsPanel(true, null);
98                ed.setContent(settings);
99                ed.showDialog();
100                if (ed.getValue() != 1) return;
101                try {
102                    settings.apply();
103                } catch (IOException ex) {
104                    return;
105                }
106            }
107            try {
108                loadSignPreset();
109            } catch (IOException ex) {
110                return;
111            }
112            RoadSignInputDialog input = new RoadSignInputDialog();
113            input.showDialog();
114        }
115
116    }
117
118    public static class PresetMetaData {
119        @StructEntry public String code;
120        @StructEntry public String display_name;
121        @StructEntry public String preset_path;
122        @StructEntry public String icon_path;
123
124        public PresetMetaData() {
125        }
126
127        public PresetMetaData(String country_code, String display_name, String preset_path, String icons_path) {
128            this.code = country_code;
129            this.display_name = display_name;
130            this.preset_path = preset_path;
131            this.icon_path = icons_path;
132        }
133
134        @Override
135        public String toString() {
136            return display_name;
137        }
138    }
139
140    public static void setSelectedPreset(PresetMetaData preset) throws IOException {
141        Config.getPref().put("plugin.roadsigns.preset.selection", preset.code);
142        loadSignPreset();
143    }
144
145    public static List<PresetMetaData> getAvailablePresetsMetaData() {
146
147        List<PresetMetaData> presetsData = StructUtils.getListOfStructs(
148                Config.getPref(), "plugin.roadsigns.presets", DEFAULT_PRESETS, PresetMetaData.class);
149
150        String customFile = Config.getPref().get("plugin.roadsigns.sources", null);
151        if (customFile == null) {
152            // for legacy reasons, try both string and collection preference type
153            List<String> customFiles = Config.getPref().getList("plugin.roadsigns.sources", null);
154            if (customFiles != null && !customFiles.isEmpty()) {
155                customFile = customFiles.iterator().next();
156            }
157        }
158
159        if (customFile != null) {
160            // first check, if custom file preference has changed. If yes,
161            // change the current preset selection to custom directly
162            String lastCustomFile = Config.getPref().get("plugin.roadsigns.sources.last", null);
163            if (!Objects.equals(customFile, lastCustomFile)) {
164                Config.getPref().put("plugin.roadsigns.sources.last", customFile);
165                Config.getPref().put("plugin.roadsigns.preset.selection", "custom");
166            }
167
168            String customIconDirsStr = Config.getPref().get("plugin.roadsigns.icon.sources", null);
169            List<String> customIconDirs = null;
170            if (customIconDirsStr != null) {
171                customIconDirs = new ArrayList<>(Arrays.asList(customIconDirsStr.split(",")));
172            } else {
173                customIconDirs = Config.getPref().getList("plugin.roadsigns.icon.sources", null);
174            }
175            if (customIconDirs != null) {
176                customIconDirs = new ArrayList<>(customIconDirs);
177            } else {
178                customIconDirs = new ArrayList<>();
179            }
180            // add icon directory relative to preset file
181            if (!customFile.startsWith("resource:")) {
182                String parentDir = null;
183                try {
184                    URL url = new URL(customFile);
185                    parentDir = url.getPath();
186                } catch (MalformedURLException ex) {
187                    File f = new File(customFile);
188                    parentDir = f.getParent();
189                }
190                if (parentDir != null && !parentDir.isEmpty()) {
191                    customIconDirs.add(parentDir);
192                }
193            }
194            if (Config.getPref().getBoolean("plugin.roadsigns.use_default_icon_source", true)) {
195                customIconDirs.add("resource://images/");
196            }
197            PresetMetaData custom = new PresetMetaData("custom", tr("custom"), customFile, Utils.join(",", customIconDirs));
198            presetsData.add(custom);
199        } else {
200            Config.getPref().put("plugin.roadsigns.sources.last", null);
201        }
202
203        return presetsData;
204    }
205
206    protected static void loadSignPreset() throws IOException {
207        List<PresetMetaData> presetsData = getAvailablePresetsMetaData();
208        String code = Config.getPref().get("plugin.roadsigns.preset.selection", null);
209
210        for (PresetMetaData data : presetsData) {
211            if (data.code.equals(code)) {
212                selectedPreset = data;
213                break;
214            }
215        }
216        if (selectedPreset == null) {
217            if (!presetsData.isEmpty()) {
218                selectedPreset = presetsData.get(0);
219            } else {
220                selectedPreset = PRESET_DE;
221            }
222        }
223        iconDirs = Arrays.asList(selectedPreset.icon_path.split(","));
224        String source = selectedPreset.preset_path;
225
226        try {
227            InputStream in = getInputStream(source);
228            RoadSignsReader reader = new RoadSignsReader(in);
229            signs = reader.parse();
230
231        } catch (IOException ex) {
232            ex.printStackTrace();
233            JOptionPane.showMessageDialog(
234                    MainApplication.getMainFrame(),
235                    tr("Could not read tagging preset source: ''{0}''", source),
236                    tr("Error"),
237                    JOptionPane.ERROR_MESSAGE
238            );
239            throw ex;
240        } catch (SAXException ex) {
241            ex.printStackTrace();
242            JOptionPane.showMessageDialog(
243                    MainApplication.getMainFrame(),
244                    tr("Error parsing tagging preset from ''{0}'':\n", source)+ex.getMessage(),
245                    tr("Error"),
246                    JOptionPane.ERROR_MESSAGE
247            );
248            throw new IOException(ex);
249        }
250    }
251
252    /**
253     * Returns an inputstream from urls, files and classloaders, depending on the name.
254     */
255    @SuppressWarnings("resource")
256    public static InputStream getInputStream(String source) throws IOException {
257        InputStream in = null;
258        if (source.startsWith("http://") || source.startsWith("https://") || source.startsWith("ftp://")) {
259            in = new CachedFile(source).getInputStream();
260        } else if (source.startsWith("file:")) {
261            in = new URL(source).openStream();
262        } else if (source.startsWith("resource://")) {
263            in = RoadSignsPlugin.class.getResourceAsStream(source.substring("resource:/".length()));
264        } else {
265            in = new FileInputStream(source);
266        }
267        return in;
268    }
269}
Note: See TracBrowser for help on using the repository browser.