diff --git a/data/defaultpresets.xml b/data/defaultpresets.xml
index d798bac..c9b9477 100755
|
a
|
b
|
role: type to specify possible roles in relations
|
| 88 | 88 | requisite: optional/required (default is "optional") |
| 89 | 89 | count: how often can the role occur (if not given unlimited number is assumed) |
| 90 | 90 | type: the data types - way,node,relation,closedway (separated by comma) |
| | 91 | member_expression: an expression (cf. search dialog) for objects of this role |
| 91 | 92 | |
| 92 | 93 | presets: For external files <presets> should have following attributes: |
| 93 | 94 | author: the author of the preset |
| … |
… |
Note that for a match, at least one positive and no negative is required.
|
| 2425 | 2426 | </optional> |
| 2426 | 2427 | <roles> |
| 2427 | 2428 | <role key="" text="route segment" requisite="required" type="way" /> |
| 2428 | | <role key="stop" text="stop position" requisite="optional" type="node" /> |
| 2429 | | <role key="stop_exit_only" text="stop position (exit only)" requisite="optional" type="node" /> |
| 2430 | | <role key="stop_entry_only" text="stop position (entry only)" requisite="optional" type="node" /> |
| 2431 | | <role key="platform" text="platform" requisite="optional" type="node,way,closedway" /> |
| 2432 | | <role key="platform_exit_only" text="platform (exit only)" requisite="optional" type="node,way,closedway" /> |
| 2433 | | <role key="platform_entry_only" text="platform (entry only)" requisite="optional" type="node,way,closedway" /> |
| | 2429 | <role key="stop" text="stop position" requisite="optional" type="node" member_expression="public_transport=stop_position" /> |
| | 2430 | <role key="stop_exit_only" text="stop position (exit only)" requisite="optional" type="node" member_expression="public_transport=stop_position" /> |
| | 2431 | <role key="stop_entry_only" text="stop position (entry only)" requisite="optional" type="node" member_expression="public_transport=stop_position" /> |
| | 2432 | <role key="platform" text="platform" requisite="optional" type="node,way,closedway" member_expression="public_transport=platform" /> |
| | 2433 | <role key="platform_exit_only" text="platform (exit only)" requisite="optional" type="node,way,closedway" member_expression="public_transport=platform" /> |
| | 2434 | <role key="platform_entry_only" text="platform (entry only)" requisite="optional" type="node,way,closedway" member_expression="public_transport=platform" /> |
| 2434 | 2435 | </roles> |
| 2435 | 2436 | </item> |
| 2436 | 2437 | <item name="Route master" icon="presets/path.png" type="relation"> |
| … |
… |
Note that for a match, at least one positive and no negative is required.
|
| 2446 | 2447 | <combo key="colour" text="Color (HTML name or hexadecimal code)" values_context="color" values="black,brown,green,red,blue,gray,white,#CD853F" /> |
| 2447 | 2448 | </optional> |
| 2448 | 2449 | <roles> |
| 2449 | | <role key="" text="route variant/direction (at least 2)" requisite="required" type="relation"/> <!-- FIXME: at least 2 members are required --> |
| | 2450 | <role key="" text="route variant/direction (at least 2)" requisite="required" type="relation" member_expression="type=route"/> <!-- FIXME: at least 2 members are required --> |
| 2450 | 2451 | </roles> |
| 2451 | 2452 | </item> |
| 2452 | 2453 | <item name="Stop Area" type="relation" icon="presets/interpolation.png"> |
| … |
… |
Note that for a match, at least one positive and no negative is required.
|
| 2463 | 2464 | <text key="network" text="Network"/> |
| 2464 | 2465 | </optional> |
| 2465 | 2466 | <roles> |
| 2466 | | <role key="stop" text="Stop Position" requisite="optional" type="node"/> |
| 2467 | | <role key="platform" text="Platform" requisite="optional" type="node,way,closedway"/> |
| 2468 | | <role key="" text="Station or amenities" requisite="optional" type="node,way,closedway"/> |
| | 2467 | <role key="stop" text="Stop Position" requisite="optional" type="node" member_expression="public_transport=stop_position"/> |
| | 2468 | <role key="platform" text="Platform" requisite="optional" type="node,way,closedway" member_expression="public_transport=platform"/> |
| | 2469 | <role key="" text="Station or amenities" requisite="optional" type="node,way,closedway" member_expression="amenity|public_transport=station"/> |
| 2469 | 2470 | </roles> |
| 2470 | 2471 | </item> |
| 2471 | 2472 | <separator/> |
| … |
… |
Note that for a match, at least one positive and no negative is required.
|
| 5905 | 5906 | <key key="type" value="associatedStreet" /> |
| 5906 | 5907 | <text key="name" text="Street name" /> |
| 5907 | 5908 | <roles> |
| 5908 | | <role key="street" text="street" requisite="required" type="way" /> |
| 5909 | | <role key="house" text="house" requisite="required" type="node,way,closedway,relation" /> |
| | 5909 | <role key="street" text="street" requisite="required" type="way" member_expression="highway "addr:street"" /> |
| | 5910 | <role key="house" text="house" requisite="required" type="node,way,closedway,relation" member_expression=""addr:housenumber"" /> |
| 5910 | 5911 | </roles> |
| 5911 | 5912 | </item> |
| 5912 | 5913 | <item name="Street" type="relation"> |
| … |
… |
Note that for a match, at least one positive and no negative is required.
|
| 5962 | 5963 | <text key="wikipedia" text="Wikipedia" /> |
| 5963 | 5964 | </optional> |
| 5964 | 5965 | <roles> |
| 5965 | | <role key="" text="waterways (no riverbank)" requisite="optional" type="way" /> |
| 5966 | | <role key="main_stream" text="waterways (no riverbank)" requisite="optional" type="way" /> |
| 5967 | | <role key="side_stream" text="branch waterways (no riverbank)" requisite="optional" type="way" /> |
| | 5966 | <role key="" text="waterways (no riverbank)" requisite="optional" type="way" member_expression="waterway -waterway:riverbank" /> |
| | 5967 | <role key="main_stream" text="waterways (no riverbank)" requisite="optional" type="way" member_expression="waterway -waterway:riverbank" /> |
| | 5968 | <role key="side_stream" text="branch waterways (no riverbank)" requisite="optional" type="way" member_expression="waterway -waterway:riverbank"/> |
| 5968 | 5969 | <role key="spring" text="spring of waterway" requisite="optional" type="node" /> |
| 5969 | 5970 | </roles> |
| 5970 | 5971 | </item> |
diff --git a/data/tagging-preset.xsd b/data/tagging-preset.xsd
index 72f84e4..183f296 100644
|
a
|
b
|
|
| 231 | 231 | <attribute name="requisite" type="tns:role_requisite" /> |
| 232 | 232 | <attribute name="type" type="string" /> |
| 233 | 233 | <attribute name="count" type="integer" /> |
| | 234 | <attribute name="member_expression" type="string" /> |
| 234 | 235 | </complexType> |
| 235 | 236 | |
| 236 | 237 | <simpleType name="role_requisite"> |
diff --git a/src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java b/src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java
index f52e70c..cebd1fe 100644
|
a
|
b
|
import javax.swing.JPanel;
|
| 20 | 20 | |
| 21 | 21 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| 22 | 22 | import org.openstreetmap.josm.data.osm.Tag; |
| 23 | | import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference; |
| 24 | 23 | import org.openstreetmap.josm.gui.tagging.TaggingPreset; |
| 25 | 24 | import org.openstreetmap.josm.gui.tagging.TaggingPreset.PresetType; |
| 26 | 25 | import org.openstreetmap.josm.tools.GBC; |
| … |
… |
public class PresetListPanel extends JPanel {
|
| 85 | 84 | return; |
| 86 | 85 | } |
| 87 | 86 | |
| 88 | | for (TaggingPreset t : TaggingPresetPreference.taggingPresets) { |
| 89 | | if (!t.matches(types, tags, true)) { |
| 90 | | continue; |
| 91 | | } |
| 92 | | |
| | 87 | for (TaggingPreset t : TaggingPreset.getMatchingPresets(types, tags, true)) { |
| 93 | 88 | JLabel lbl = new JLabel(t.getName() + " …"); |
| 94 | 89 | lbl.setIcon((Icon) t.getValue(Action.SMALL_ICON)); |
| 95 | 90 | lbl.addMouseListener(new PresetLabelML(lbl, t, presetHandler)); |
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java b/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
index abba54b..5205c52 100644
|
a
|
b
|
import org.openstreetmap.josm.gui.HelpAwareOptionPane;
|
| 61 | 61 | import org.openstreetmap.josm.gui.MainMenu; |
| 62 | 62 | import org.openstreetmap.josm.gui.SideButton; |
| 63 | 63 | import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; |
| | 64 | import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel; |
| 64 | 65 | import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel.PresetHandler; |
| 65 | 66 | import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction; |
| 66 | 67 | import org.openstreetmap.josm.gui.help.HelpUtil; |
| … |
… |
public class GenericRelationEditor extends RelationEditor {
|
| 114 | 115 | setRememberWindowGeometry(getClass().getName() + ".geometry", |
| 115 | 116 | WindowGeometry.centerInWindow(Main.parent, new Dimension(700, 650))); |
| 116 | 117 | |
| 117 | | // init the various models |
| 118 | | // |
| 119 | | memberTableModel = new MemberTableModel(getLayer()); |
| 120 | | memberTableModel.register(); |
| 121 | | selectionTableModel = new SelectionTableModel(getLayer()); |
| 122 | | selectionTableModel.register(); |
| 123 | | referrerModel = new ReferringRelationsBrowserModel(relation); |
| 124 | | |
| 125 | | tagEditorPanel = new TagEditorPanel(new PresetHandler() { |
| | 118 | final PresetHandler presetHandler = new PresetHandler() { |
| 126 | 119 | |
| 127 | 120 | @Override |
| 128 | 121 | public void updateTags(List<Tag> tags) { |
| … |
… |
public class GenericRelationEditor extends RelationEditor {
|
| 135 | 128 | tagEditorPanel.getModel().applyToPrimitive(relation); |
| 136 | 129 | return Collections.<OsmPrimitive>singletonList(relation); |
| 137 | 130 | } |
| 138 | | }); |
| | 131 | }; |
| | 132 | |
| | 133 | // init the various models |
| | 134 | // |
| | 135 | memberTableModel = new MemberTableModel(getLayer(), presetHandler); |
| | 136 | memberTableModel.register(); |
| | 137 | selectionTableModel = new SelectionTableModel(getLayer()); |
| | 138 | selectionTableModel.register(); |
| | 139 | referrerModel = new ReferringRelationsBrowserModel(relation); |
| | 140 | |
| | 141 | tagEditorPanel = new TagEditorPanel(presetHandler); |
| 139 | 142 | |
| 140 | 143 | // populate the models |
| 141 | 144 | // |
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java b/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java
index 8908626..2b37958 100644
|
a
|
b
|
import java.util.Arrays;
|
| 12 | 12 | import java.util.Collection; |
| 13 | 13 | import java.util.Collections; |
| 14 | 14 | import java.util.Comparator; |
| | 15 | import java.util.EnumSet; |
| 15 | 16 | import java.util.HashMap; |
| 16 | 17 | import java.util.HashSet; |
| 17 | 18 | import java.util.Iterator; |
| … |
… |
import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
|
| 45 | 46 | import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent; |
| 46 | 47 | import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; |
| 47 | 48 | import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; |
| | 49 | import org.openstreetmap.josm.gui.dialogs.properties.PresetListPanel; |
| 48 | 50 | import org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction; |
| 49 | 51 | import org.openstreetmap.josm.gui.layer.OsmDataLayer; |
| | 52 | import org.openstreetmap.josm.gui.tagging.TaggingPreset; |
| 50 | 53 | import org.openstreetmap.josm.gui.widgets.OsmPrimitivesTableModel; |
| 51 | 54 | |
| 52 | 55 | public class MemberTableModel extends AbstractTableModel implements TableModelListener, SelectionChangedListener, DataSetListener, OsmPrimitivesTableModel { |
| … |
… |
public class MemberTableModel extends AbstractTableModel implements TableModelLi
|
| 58 | 61 | private List<WayConnectionType> connectionType = null; |
| 59 | 62 | |
| 60 | 63 | private DefaultListSelectionModel listSelectionModel; |
| 61 | | private CopyOnWriteArrayList<IMemberModelListener> listeners; |
| 62 | | private OsmDataLayer layer; |
| | 64 | private final CopyOnWriteArrayList<IMemberModelListener> listeners; |
| | 65 | private final OsmDataLayer layer; |
| | 66 | private final PresetListPanel.PresetHandler presetHandler; |
| 63 | 67 | |
| 64 | 68 | private final int UNCONNECTED = Integer.MIN_VALUE; |
| 65 | 69 | |
| … |
… |
public class MemberTableModel extends AbstractTableModel implements TableModelLi
|
| 72 | 76 | /** |
| 73 | 77 | * constructor |
| 74 | 78 | */ |
| 75 | | public MemberTableModel(OsmDataLayer layer) { |
| | 79 | public MemberTableModel(OsmDataLayer layer, PresetListPanel.PresetHandler presetHandler) { |
| 76 | 80 | members = new ArrayList<RelationMember>(); |
| 77 | 81 | listeners = new CopyOnWriteArrayList<IMemberModelListener>(); |
| 78 | 82 | this.layer = layer; |
| | 83 | this.presetHandler = presetHandler; |
| 79 | 84 | addTableModelListener(this); |
| 80 | 85 | } |
| 81 | 86 | |
| … |
… |
public class MemberTableModel extends AbstractTableModel implements TableModelLi
|
| 394 | 399 | } |
| 395 | 400 | |
| 396 | 401 | private void addMembersAtIndex(List<? extends OsmPrimitive> primitives, int index) { |
| | 402 | final Collection<TaggingPreset> presets = TaggingPreset.getMatchingPresets(EnumSet.of(TaggingPreset.PresetType.RELATION), presetHandler.getSelection().iterator().next().getKeys(), false); |
| 397 | 403 | if (primitives == null) |
| 398 | 404 | return; |
| 399 | 405 | int idx = index; |
| 400 | 406 | for (OsmPrimitive primitive : primitives) { |
| 401 | | RelationMember member = new RelationMember("", primitive); |
| | 407 | final String role = presets.isEmpty() ? null : presets.iterator().next().suggestRoleForOsmPrimitive(primitive); |
| | 408 | RelationMember member = new RelationMember(role == null ? "" : role, primitive); |
| 402 | 409 | members.add(idx++, member); |
| 403 | 410 | } |
| 404 | 411 | fireTableDataChanged(); |
diff --git a/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java b/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java
index a68b4c6..cb971f7 100644
|
a
|
b
|
import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
|
| 66 | 66 | import org.openstreetmap.josm.gui.layer.Layer; |
| 67 | 67 | import org.openstreetmap.josm.gui.layer.OsmDataLayer; |
| 68 | 68 | import org.openstreetmap.josm.gui.preferences.SourceEntry; |
| | 69 | import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference; |
| 69 | 70 | import org.openstreetmap.josm.gui.preferences.map.TaggingPresetPreference.PresetPrefHelper; |
| 70 | 71 | import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField; |
| 71 | 72 | import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority; |
| … |
… |
import org.openstreetmap.josm.gui.widgets.JosmComboBox;
|
| 75 | 76 | import org.openstreetmap.josm.io.MirroredInputStream; |
| 76 | 77 | import org.openstreetmap.josm.tools.GBC; |
| 77 | 78 | import org.openstreetmap.josm.tools.ImageProvider; |
| | 79 | import org.openstreetmap.josm.tools.Predicate; |
| 78 | 80 | import org.openstreetmap.josm.tools.UrlLabel; |
| 79 | 81 | import org.openstreetmap.josm.tools.Utils; |
| 80 | 82 | import org.openstreetmap.josm.tools.XmlObjectParser; |
| … |
… |
public class TaggingPreset extends AbstractAction implements MapView.LayerChange
|
| 1093 | 1095 | public String text; |
| 1094 | 1096 | public String text_context; |
| 1095 | 1097 | public String locale_text; |
| | 1098 | public Match memberExpression; |
| 1096 | 1099 | |
| 1097 | 1100 | public boolean required = false; |
| 1098 | 1101 | public long count = 0; |
| … |
… |
public class TaggingPreset extends AbstractAction implements MapView.LayerChange
|
| 1108 | 1111 | throw new SAXException(tr("Unknown requisite: {0}", str)); |
| 1109 | 1112 | } |
| 1110 | 1113 | |
| | 1114 | public void setMember_expression(String member_expression) throws SAXException { |
| | 1115 | try { |
| | 1116 | this.memberExpression = SearchCompiler.compile(member_expression, true, true); |
| | 1117 | } catch (SearchCompiler.ParseError ex) { |
| | 1118 | throw new SAXException(tr("Illegal member expression: {0}", ex.getMessage()), ex); |
| | 1119 | } |
| | 1120 | } |
| | 1121 | |
| 1111 | 1122 | /* return either argument, the highest possible value or the lowest |
| 1112 | 1123 | allowed value */ |
| 1113 | 1124 | public long getValidCount(long c) |
| … |
… |
public class TaggingPreset extends AbstractAction implements MapView.LayerChange
|
| 1571 | 1582 | return false; |
| 1572 | 1583 | } |
| 1573 | 1584 | |
| | 1585 | public String suggestRoleForOsmPrimitive(OsmPrimitive osm) { |
| | 1586 | final List<Role> roles = new ArrayList<Role>(); |
| | 1587 | for (Item i : data) { |
| | 1588 | if (i instanceof Roles) { |
| | 1589 | roles.addAll(((Roles) i).roles); |
| | 1590 | } |
| | 1591 | } |
| | 1592 | for (Role i : roles) { |
| | 1593 | if (i.memberExpression != null && i.memberExpression.match(osm)) { |
| | 1594 | return i.key; |
| | 1595 | } |
| | 1596 | } |
| | 1597 | return null; |
| | 1598 | } |
| | 1599 | |
| 1574 | 1600 | public void actionPerformed(ActionEvent e) { |
| 1575 | 1601 | if (Main.main == null) return; |
| 1576 | 1602 | if (Main.main.getCurrentDataSet() == null) return; |
| … |
… |
public class TaggingPreset extends AbstractAction implements MapView.LayerChange
|
| 1589 | 1615 | for(Tag t : getChangedTags()) { |
| 1590 | 1616 | r.put(t.getKey(), t.getValue()); |
| 1591 | 1617 | } |
| 1592 | | for(OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { |
| 1593 | | RelationMember rm = new RelationMember("", osm); |
| | 1618 | for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { |
| | 1619 | String role = suggestRoleForOsmPrimitive(osm); |
| | 1620 | RelationMember rm = new RelationMember(role == null ? "" : role, osm); |
| 1594 | 1621 | r.addMember(rm); |
| 1595 | 1622 | members.add(rm); |
| 1596 | 1623 | } |
| … |
… |
public class TaggingPreset extends AbstractAction implements MapView.LayerChange
|
| 1772 | 1799 | } |
| 1773 | 1800 | return atLeastOnePositiveMatch; |
| 1774 | 1801 | } |
| | 1802 | |
| | 1803 | public static Collection<TaggingPreset> getMatchingPresets(final Collection<PresetType> t, final Map<String, String> tags, final boolean onlyShowable) { |
| | 1804 | return Utils.filter(TaggingPresetPreference.taggingPresets, new Predicate<TaggingPreset>() { |
| | 1805 | @Override |
| | 1806 | public boolean evaluate(TaggingPreset object) { |
| | 1807 | return object.matches(t, tags, onlyShowable); |
| | 1808 | } |
| | 1809 | }); |
| | 1810 | } |
| 1775 | 1811 | } |