source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java@ 8863

Last change on this file since 8863 was 8863, checked in by Don-vip, 9 years ago

major code cleanup/refactoring of tagging presets: slay the monster TaggingPresetItems (60 Kb, 1600 lines) and extract all its internal classes to a new package gui.tagging.presets.items

  • Property svn:eol-style set to native
File size: 13.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.map;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.GridBagLayout;
8import java.io.IOException;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.HashMap;
13import java.util.List;
14import java.util.Map;
15
16import javax.swing.BorderFactory;
17import javax.swing.JCheckBox;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.gui.ExtendedDialog;
24import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
25import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
26import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
27import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.ValidationListener;
28import org.openstreetmap.josm.gui.preferences.SourceEditor;
29import org.openstreetmap.josm.gui.preferences.SourceEditor.ExtendedSourceEntry;
30import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetReader;
31import org.openstreetmap.josm.gui.preferences.SourceEntry;
32import org.openstreetmap.josm.gui.preferences.SourceProvider;
33import org.openstreetmap.josm.gui.preferences.SourceType;
34import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
35import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
36import org.openstreetmap.josm.tools.GBC;
37import org.xml.sax.SAXException;
38import org.xml.sax.SAXParseException;
39
40/**
41 * Preference settings for tagging presets.
42 */
43public final class TaggingPresetPreference implements SubPreferenceSetting {
44
45 private final class TaggingPresetValidationListener implements ValidationListener {
46 @Override
47 public boolean validatePreferences() {
48 if (sources.hasActiveSourcesChanged()) {
49 List<Integer> sourcesToRemove = new ArrayList<>();
50 int i = -1;
51 SOURCES:
52 for (SourceEntry source: sources.getActiveSources()) {
53 i++;
54 boolean canLoad = false;
55 try {
56 TaggingPresetReader.readAll(source.url, false);
57 canLoad = true;
58 } catch (IOException e) {
59 Main.warn(tr("Could not read tagging preset source: {0}", source));
60 ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Error"),
61 new String[] {tr("Yes"), tr("No"), tr("Cancel")});
62 ed.setContent(tr("Could not read tagging preset source: {0}\nDo you want to keep it?", source));
63 switch (ed.showDialog().getValue()) {
64 case 1:
65 continue SOURCES;
66 case 2:
67 sourcesToRemove.add(i);
68 continue SOURCES;
69 default:
70 return false;
71 }
72 } catch (SAXException e) {
73 // We will handle this in step with validation
74 if (Main.isTraceEnabled()) {
75 Main.trace(e.getMessage());
76 }
77 }
78
79 String errorMessage = null;
80
81 try {
82 TaggingPresetReader.readAll(source.url, true);
83 } catch (IOException e) {
84 // Should not happen, but at least show message
85 String msg = tr("Could not read tagging preset source {0}", source);
86 Main.error(msg);
87 JOptionPane.showMessageDialog(Main.parent, msg);
88 return false;
89 } catch (SAXParseException e) {
90 if (canLoad) {
91 errorMessage = tr("<html>Tagging preset source {0} can be loaded but it contains errors. " +
92 "Do you really want to use it?<br><br><table width=600>Error is: [{1}:{2}] {3}</table></html>",
93 source, e.getLineNumber(), e.getColumnNumber(), e.getMessage());
94 } else {
95 errorMessage = tr("<html>Unable to parse tagging preset source: {0}. " +
96 "Do you really want to use it?<br><br><table width=400>Error is: [{1}:{2}] {3}</table></html>",
97 source, e.getLineNumber(), e.getColumnNumber(), e.getMessage());
98 }
99 } catch (SAXException e) {
100 if (canLoad) {
101 errorMessage = tr("<html>Tagging preset source {0} can be loaded but it contains errors. " +
102 "Do you really want to use it?<br><br><table width=600>Error is: {1}</table></html>",
103 source, e.getMessage());
104 } else {
105 errorMessage = tr("<html>Unable to parse tagging preset source: {0}. " +
106 "Do you really want to use it?<br><br><table width=600>Error is: {1}</table></html>",
107 source, e.getMessage());
108 }
109 }
110
111 if (errorMessage != null) {
112 Main.error(errorMessage);
113 int result = JOptionPane.showConfirmDialog(Main.parent, new JLabel(errorMessage), tr("Error"),
114 JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE);
115
116 switch (result) {
117 case JOptionPane.YES_OPTION:
118 continue SOURCES;
119 case JOptionPane.NO_OPTION:
120 sourcesToRemove.add(i);
121 continue SOURCES;
122 default:
123 return false;
124 }
125 }
126 }
127 sources.removeSources(sourcesToRemove);
128 return true;
129 } else {
130 return true;
131 }
132 }
133 }
134
135 /**
136 * Factory used to create a new {@code TaggingPresetPreference}.
137 */
138 public static class Factory implements PreferenceSettingFactory {
139 @Override
140 public PreferenceSetting createPreferenceSetting() {
141 return new TaggingPresetPreference();
142 }
143 }
144
145 private TaggingPresetPreference() {
146 super();
147 }
148
149 private static final List<SourceProvider> presetSourceProviders = new ArrayList<>();
150
151 private SourceEditor sources;
152 private JCheckBox sortMenu;
153
154 /**
155 * Registers a new additional preset source provider.
156 * @param provider The preset source provider
157 * @return {@code true}, if the provider has been added, {@code false} otherwise
158 */
159 public static boolean registerSourceProvider(SourceProvider provider) {
160 if (provider != null)
161 return presetSourceProviders.add(provider);
162 return false;
163 }
164
165 private final ValidationListener validationListener = new TaggingPresetValidationListener();
166
167 @Override
168 public void addGui(PreferenceTabbedPane gui) {
169 sortMenu = new JCheckBox(tr("Sort presets menu"),
170 Main.pref.getBoolean("taggingpreset.sortmenu", false));
171
172 final JPanel panel = new JPanel(new GridBagLayout());
173 panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
174 panel.add(sortMenu, GBC.eol().insets(5, 5, 5, 0));
175 sources = new TaggingPresetSourceEditor();
176 panel.add(sources, GBC.eol().fill(GBC.BOTH));
177 final MapPreference mapPref = gui.getMapPreference();
178 mapPref.addSubTab(this, tr("Tagging Presets"), panel);
179 sources.deferLoading(mapPref, panel);
180 gui.addValidationListener(validationListener);
181 }
182
183 static class TaggingPresetSourceEditor extends SourceEditor {
184
185 private static final String iconpref = "taggingpreset.icon.sources";
186
187 TaggingPresetSourceEditor() {
188 super(SourceType.TAGGING_PRESET, Main.getJOSMWebsite()+"/presets", presetSourceProviders, true);
189 }
190
191 @Override
192 public Collection<? extends SourceEntry> getInitialSourcesList() {
193 return PresetPrefHelper.INSTANCE.get();
194 }
195
196 @Override
197 public boolean finish() {
198 List<SourceEntry> activeStyles = activeSourcesModel.getSources();
199
200 boolean changed = PresetPrefHelper.INSTANCE.put(activeStyles);
201
202 if (tblIconPaths != null) {
203 List<String> iconPaths = iconPathsModel.getIconPaths();
204
205 if (!iconPaths.isEmpty()) {
206 if (Main.pref.putCollection(iconpref, iconPaths)) {
207 changed = true;
208 }
209 } else if (Main.pref.putCollection(iconpref, null)) {
210 changed = true;
211 }
212 }
213 return changed;
214 }
215
216 @Override
217 public Collection<ExtendedSourceEntry> getDefault() {
218 return PresetPrefHelper.INSTANCE.getDefault();
219 }
220
221 @Override
222 public Collection<String> getInitialIconPathsList() {
223 return Main.pref.getCollection(iconpref, null);
224 }
225
226 @Override
227 public String getStr(I18nString ident) {
228 switch (ident) {
229 case AVAILABLE_SOURCES:
230 return tr("Available presets:");
231 case ACTIVE_SOURCES:
232 return tr("Active presets:");
233 case NEW_SOURCE_ENTRY_TOOLTIP:
234 return tr("Add a new preset by entering filename or URL");
235 case NEW_SOURCE_ENTRY:
236 return tr("New preset entry:");
237 case REMOVE_SOURCE_TOOLTIP:
238 return tr("Remove the selected presets from the list of active presets");
239 case EDIT_SOURCE_TOOLTIP:
240 return tr("Edit the filename or URL for the selected active preset");
241 case ACTIVATE_TOOLTIP:
242 return tr("Add the selected available presets to the list of active presets");
243 case RELOAD_ALL_AVAILABLE:
244 return marktr("Reloads the list of available presets from ''{0}''");
245 case LOADING_SOURCES_FROM:
246 return marktr("Loading preset sources from ''{0}''");
247 case FAILED_TO_LOAD_SOURCES_FROM:
248 return marktr("<html>Failed to load the list of preset sources from<br>"
249 + "''{0}''.<br>"
250 + "<br>"
251 + "Details (untranslated):<br>{1}</html>");
252 case FAILED_TO_LOAD_SOURCES_FROM_HELP_TOPIC:
253 return "/Preferences/Presets#FailedToLoadPresetSources";
254 case ILLEGAL_FORMAT_OF_ENTRY:
255 return marktr("Warning: illegal format of entry in preset list ''{0}''. Got ''{1}''");
256 default: throw new AssertionError();
257 }
258 }
259 }
260
261 @Override
262 public boolean ok() {
263 boolean restart = Main.pref.put("taggingpreset.sortmenu", sortMenu.getSelectedObjects() != null);
264 restart |= sources.finish();
265
266 return restart;
267 }
268
269 /**
270 * Helper class for tagging presets preferences.
271 */
272 public static class PresetPrefHelper extends SourceEditor.SourcePrefHelper {
273
274 /**
275 * The unique instance.
276 */
277 public static final PresetPrefHelper INSTANCE = new PresetPrefHelper();
278
279 /**
280 * Constructs a new {@code PresetPrefHelper}.
281 */
282 public PresetPrefHelper() {
283 super("taggingpreset.entries");
284 }
285
286 @Override
287 public Collection<ExtendedSourceEntry> getDefault() {
288 ExtendedSourceEntry i = new ExtendedSourceEntry("defaultpresets.xml", "resource://data/defaultpresets.xml");
289 i.title = tr("Internal Preset");
290 i.description = tr("The default preset for JOSM");
291 return Collections.singletonList(i);
292 }
293
294 @Override
295 public Map<String, String> serialize(SourceEntry entry) {
296 Map<String, String> res = new HashMap<>();
297 res.put("url", entry.url);
298 res.put("title", entry.title == null ? "" : entry.title);
299 return res;
300 }
301
302 @Override
303 public SourceEntry deserialize(Map<String, String> s) {
304 return new SourceEntry(s.get("url"), null, s.get("title"), true);
305 }
306 }
307
308 @Override
309 public boolean isExpert() {
310 return false;
311 }
312
313 @Override
314 public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
315 return gui.getMapPreference();
316 }
317}
Note: See TracBrowser for help on using the repository browser.