001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.tagging.presets; 003 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.HashMap; 007import java.util.Map; 008 009import javax.swing.JMenu; 010import javax.swing.JMenuItem; 011import javax.swing.JSeparator; 012 013import org.openstreetmap.josm.Main; 014import org.openstreetmap.josm.data.osm.OsmPrimitive; 015import org.openstreetmap.josm.gui.MenuScroller; 016import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager; 017import org.openstreetmap.josm.tools.SubclassFilteredCollection; 018 019/** 020 * Class holding Tagging Presets and allowing to manage them. 021 * @since 7100 022 */ 023public final class TaggingPresets { 024 025 /** The collection of tagging presets */ 026 private static final Collection<TaggingPreset> taggingPresets = new ArrayList<>(); 027 028 /** The collection of listeners */ 029 private static final Collection<TaggingPresetListener> listeners = new ArrayList<>(); 030 031 private TaggingPresets() { 032 // Hide constructor for utility classes 033 } 034 035 /** 036 * Initializes tagging presets from preferences. 037 */ 038 public static void readFromPreferences() { 039 taggingPresets.clear(); 040 taggingPresets.addAll(TaggingPresetReader.readFromPreferences(false, false)); 041 } 042 043 /** 044 * Initialize the tagging presets (load and may display error) 045 */ 046 public static void initialize() { 047 readFromPreferences(); 048 for (TaggingPreset tp: taggingPresets) { 049 if (!(tp instanceof TaggingPresetSeparator)) { 050 Main.toolbar.register(tp); 051 } 052 } 053 if (taggingPresets.isEmpty()) { 054 Main.main.menu.presetsMenu.setVisible(false); 055 } else { 056 AutoCompletionManager.cachePresets(taggingPresets); 057 Map<TaggingPresetMenu, JMenu> submenus = new HashMap<>(); 058 for (final TaggingPreset p : taggingPresets) { 059 JMenu m = p.group != null ? submenus.get(p.group) : Main.main.menu.presetsMenu; 060 if (m == null && p.group != null) { 061 Main.error("No tagging preset submenu for " + p.group); 062 } else if (m == null) { 063 Main.error("No tagging preset menu. Tagging preset " + p + " won't be available there"); 064 } else if (p instanceof TaggingPresetSeparator) { 065 m.add(new JSeparator()); 066 } else if (p instanceof TaggingPresetMenu) { 067 JMenu submenu = new JMenu(p); 068 submenu.setText(p.getLocaleName()); 069 ((TaggingPresetMenu) p).menu = submenu; 070 submenus.put((TaggingPresetMenu) p, submenu); 071 m.add(submenu); 072 } else { 073 JMenuItem mi = new JMenuItem(p); 074 mi.setText(p.getLocaleName()); 075 m.add(mi); 076 } 077 } 078 for (JMenu submenu : submenus.values()) { 079 if (submenu.getItemCount() >= Main.pref.getInteger("taggingpreset.min-elements-for-scroller", 15)) { 080 MenuScroller.setScrollerFor(submenu); 081 } 082 } 083 } 084 if (Main.pref.getBoolean("taggingpreset.sortmenu")) { 085 TaggingPresetMenu.sortMenu(Main.main.menu.presetsMenu); 086 } 087 } 088 089 /** 090 * Replies a new collection containing all tagging presets. 091 * @return a new collection containing all tagging presets. Empty if presets are not initialized (never null) 092 */ 093 public static Collection<TaggingPreset> getTaggingPresets() { 094 return new ArrayList<>(taggingPresets); 095 } 096 097 /** 098 * Replies a new collection of all presets matching the parameters. 099 * 100 * @param t the preset types to include 101 * @param tags the tags to perform matching on, see {@link TaggingPresetItem#matches(Map)} 102 * @param onlyShowable whether only {@link TaggingPreset#isShowable() showable} presets should be returned 103 * @return a new collection of all presets matching the parameters. 104 * @see TaggingPreset#matches(Collection, Map, boolean) 105 * @since 9266 106 */ 107 public static Collection<TaggingPreset> getMatchingPresets(final Collection<TaggingPresetType> t, 108 final Map<String, String> tags, final boolean onlyShowable) { 109 return SubclassFilteredCollection.filter(getTaggingPresets(), preset -> preset.matches(t, tags, onlyShowable)); 110 } 111 112 /** 113 * Replies a new collection of all presets matching the given preset. 114 * 115 * @param primitive the primitive 116 * @return a new collection of all presets matching the given preset. 117 * @see TaggingPreset#test(OsmPrimitive) 118 * @since 9265 119 */ 120 public static Collection<TaggingPreset> getMatchingPresets(final OsmPrimitive primitive) { 121 return SubclassFilteredCollection.filter(getTaggingPresets(), preset -> preset.test(primitive)); 122 } 123 124 /** 125 * Adds a list of tagging presets to the current list. 126 * @param presets The tagging presets to add 127 */ 128 public static void addTaggingPresets(Collection<TaggingPreset> presets) { 129 if (presets != null) { 130 if (taggingPresets.addAll(presets)) { 131 for (TaggingPresetListener listener : listeners) { 132 listener.taggingPresetsModified(); 133 } 134 } 135 } 136 } 137 138 /** 139 * Adds a tagging preset listener. 140 * @param listener The listener to add 141 */ 142 public static void addListener(TaggingPresetListener listener) { 143 if (listener != null) { 144 listeners.add(listener); 145 } 146 } 147 148 /** 149 * Removes a tagging preset listener. 150 * @param listener The listener to remove 151 */ 152 public static void removeListener(TaggingPresetListener listener) { 153 if (listener != null) { 154 listeners.remove(listener); 155 } 156 } 157}