source: josm/trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresets.java@ 16304

Last change on this file since 16304 was 16304, checked in by simon04, 4 years ago

Preset preferences: add ellipses in name (since a dialog appears)

  • Property svn:eol-style set to native
File size: 9.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.tagging.presets;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.HashMap;
10import java.util.HashSet;
11import java.util.Map;
12import java.util.Set;
13
14import javax.swing.JMenu;
15import javax.swing.JMenuItem;
16import javax.swing.JSeparator;
17
18import org.openstreetmap.josm.actions.PreferencesAction;
19import org.openstreetmap.josm.data.osm.IPrimitive;
20import org.openstreetmap.josm.gui.MainApplication;
21import org.openstreetmap.josm.gui.MainMenu;
22import org.openstreetmap.josm.gui.MenuScroller;
23import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
24import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference;
25import org.openstreetmap.josm.gui.tagging.presets.items.CheckGroup;
26import org.openstreetmap.josm.gui.tagging.presets.items.KeyedItem;
27import org.openstreetmap.josm.gui.tagging.presets.items.Roles;
28import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role;
29import org.openstreetmap.josm.spi.preferences.Config;
30import org.openstreetmap.josm.tools.Logging;
31import org.openstreetmap.josm.tools.MultiMap;
32import org.openstreetmap.josm.tools.SubclassFilteredCollection;
33
34/**
35 * Class holding Tagging Presets and allowing to manage them.
36 * @since 7100
37 */
38public final class TaggingPresets {
39
40 /** The collection of tagging presets */
41 private static final Collection<TaggingPreset> taggingPresets = new ArrayList<>();
42
43 /** cache for key/value pairs found in the preset */
44 private static final MultiMap<String, String> PRESET_TAG_CACHE = new MultiMap<>();
45 /** cache for roles found in the preset */
46 private static final Set<String> PRESET_ROLE_CACHE = new HashSet<>();
47
48 /** The collection of listeners */
49 private static final Collection<TaggingPresetListener> listeners = new ArrayList<>();
50
51 private TaggingPresets() {
52 // Hide constructor for utility classes
53 }
54
55 /**
56 * Initializes tagging presets from preferences.
57 */
58 public static void readFromPreferences() {
59 taggingPresets.clear();
60 taggingPresets.addAll(TaggingPresetReader.readFromPreferences(false, false));
61 cachePresets(taggingPresets);
62 }
63
64 /**
65 * Initialize the tagging presets (load and may display error)
66 */
67 public static void initialize() {
68 MainMenu mainMenu = MainApplication.getMenu();
69 JMenu presetsMenu = mainMenu.presetsMenu;
70 if (presetsMenu.getComponentCount() == 0) {
71 MainMenu.add(presetsMenu, mainMenu.presetSearchAction);
72 MainMenu.add(presetsMenu, mainMenu.presetSearchPrimitiveAction);
73 MainMenu.add(presetsMenu, PreferencesAction.forPreferenceSubTab(tr("Preset preferences..."),
74 tr("Click to open the tagging presets tab in the preferences"), TaggingPresetPreference.class));
75 presetsMenu.addSeparator();
76 }
77
78 readFromPreferences();
79 for (TaggingPreset tp: taggingPresets) {
80 if (!(tp instanceof TaggingPresetSeparator)) {
81 MainApplication.getToolbar().register(tp);
82 }
83 }
84 if (taggingPresets.isEmpty()) {
85 presetsMenu.setVisible(false);
86 } else {
87 Map<TaggingPresetMenu, JMenu> submenus = new HashMap<>();
88 for (final TaggingPreset p : taggingPresets) {
89 JMenu m = p.group != null ? submenus.get(p.group) : presetsMenu;
90 if (m == null && p.group != null) {
91 Logging.error("No tagging preset submenu for " + p.group);
92 } else if (m == null) {
93 Logging.error("No tagging preset menu. Tagging preset " + p + " won't be available there");
94 } else if (p instanceof TaggingPresetSeparator) {
95 m.add(new JSeparator());
96 } else if (p instanceof TaggingPresetMenu) {
97 JMenu submenu = new JMenu(p);
98 submenu.setText(p.getLocaleName());
99 ((TaggingPresetMenu) p).menu = submenu;
100 submenus.put((TaggingPresetMenu) p, submenu);
101 m.add(submenu);
102 } else {
103 JMenuItem mi = new JMenuItem(p);
104 mi.setText(p.getLocaleName());
105 m.add(mi);
106 }
107 }
108 for (JMenu submenu : submenus.values()) {
109 if (submenu.getItemCount() >= Config.getPref().getInt("taggingpreset.min-elements-for-scroller", 15)) {
110 MenuScroller.setScrollerFor(submenu);
111 }
112 }
113 }
114 if (Config.getPref().getBoolean("taggingpreset.sortmenu")) {
115 TaggingPresetMenu.sortMenu(presetsMenu);
116 }
117 listeners.forEach(TaggingPresetListener::taggingPresetsModified);
118 }
119
120 // Cannot implement Destroyable since this is static
121 /**
122 * Call to deconstruct the TaggingPresets menus and other information so that it
123 * can be rebuilt later.
124 *
125 * @since 15582
126 */
127 public static void destroy() {
128 ToolbarPreferences toolBar = MainApplication.getToolbar();
129 taggingPresets.forEach(toolBar::unregister);
130 taggingPresets.clear();
131 PRESET_TAG_CACHE.clear();
132 PRESET_ROLE_CACHE.clear();
133 MainApplication.getMenu().presetsMenu.removeAll();
134 listeners.forEach(TaggingPresetListener::taggingPresetsModified);
135 }
136
137 /**
138 * Initialize the cache for presets. This is done only once.
139 * @param presets Tagging presets to cache
140 */
141 public static void cachePresets(Collection<TaggingPreset> presets) {
142 for (final TaggingPreset p : presets) {
143 for (TaggingPresetItem item : p.data) {
144 cachePresetItem(p, item);
145 }
146 }
147 }
148
149 private static void cachePresetItem(TaggingPreset p, TaggingPresetItem item) {
150 if (item instanceof KeyedItem) {
151 KeyedItem ki = (KeyedItem) item;
152 if (ki.key != null && ki.getValues() != null) {
153 PRESET_TAG_CACHE.putAll(ki.key, ki.getValues());
154 }
155 } else if (item instanceof Roles) {
156 Roles r = (Roles) item;
157 for (Role i : r.roles) {
158 if (i.key != null) {
159 PRESET_ROLE_CACHE.add(i.key);
160 }
161 }
162 } else if (item instanceof CheckGroup) {
163 for (KeyedItem check : ((CheckGroup) item).checks) {
164 cachePresetItem(p, check);
165 }
166 }
167 }
168
169 /**
170 * Replies a new collection containing all tagging presets.
171 * @return a new collection containing all tagging presets. Empty if presets are not initialized (never null)
172 */
173 public static Collection<TaggingPreset> getTaggingPresets() {
174 return Collections.unmodifiableCollection(taggingPresets);
175 }
176
177 /**
178 * Replies a set of all roles in the tagging presets.
179 * @return a set of all roles in the tagging presets.
180 */
181 public static Set<String> getPresetRoles() {
182 return Collections.unmodifiableSet(PRESET_ROLE_CACHE);
183 }
184
185 /**
186 * Replies a set of all keys in the tagging presets.
187 * @return a set of all keys in the tagging presets.
188 */
189 public static Set<String> getPresetKeys() {
190 return Collections.unmodifiableSet(PRESET_TAG_CACHE.keySet());
191 }
192
193 /**
194 * Return set of values for a key in the tagging presets
195 * @param key the key
196 * @return set of values for a key in the tagging presets or null if none is found
197 */
198 public static Set<String> getPresetValues(String key) {
199 Set<String> values = PRESET_TAG_CACHE.get(key);
200 if (values != null)
201 return Collections.unmodifiableSet(values);
202 return null;
203 }
204
205 /**
206 * Replies a new collection of all presets matching the parameters.
207 *
208 * @param t the preset types to include
209 * @param tags the tags to perform matching on, see {@link TaggingPresetItem#matches(Map)}
210 * @param onlyShowable whether only {@link TaggingPreset#isShowable() showable} presets should be returned
211 * @return a new collection of all presets matching the parameters.
212 * @see TaggingPreset#matches(Collection, Map, boolean)
213 * @since 9266
214 */
215 public static Collection<TaggingPreset> getMatchingPresets(final Collection<TaggingPresetType> t,
216 final Map<String, String> tags, final boolean onlyShowable) {
217 return SubclassFilteredCollection.filter(getTaggingPresets(), preset -> preset.matches(t, tags, onlyShowable));
218 }
219
220 /**
221 * Replies a new collection of all presets matching the given preset.
222 *
223 * @param primitive the primitive
224 * @return a new collection of all presets matching the given preset.
225 * @see TaggingPreset#test(IPrimitive)
226 * @since 13623 (signature)
227 */
228 public static Collection<TaggingPreset> getMatchingPresets(final IPrimitive primitive) {
229 return SubclassFilteredCollection.filter(getTaggingPresets(), preset -> preset.test(primitive));
230 }
231
232 /**
233 * Adds a list of tagging presets to the current list.
234 * @param presets The tagging presets to add
235 */
236 public static void addTaggingPresets(Collection<TaggingPreset> presets) {
237 if (presets != null && taggingPresets.addAll(presets)) {
238 listeners.forEach(TaggingPresetListener::taggingPresetsModified);
239 }
240 }
241
242 /**
243 * Adds a tagging preset listener.
244 * @param listener The listener to add
245 */
246 public static void addListener(TaggingPresetListener listener) {
247 if (listener != null) {
248 listeners.add(listener);
249 }
250 }
251
252 /**
253 * Removes a tagging preset listener.
254 * @param listener The listener to remove
255 */
256 public static void removeListener(TaggingPresetListener listener) {
257 if (listener != null) {
258 listeners.remove(listener);
259 }
260 }
261}
Note: See TracBrowser for help on using the repository browser.