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

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

update javadoc

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