Changeset 17610 in josm


Ignore:
Timestamp:
2021-03-20T23:07:04+01:00 (4 years ago)
Author:
simon04
Message:

see #18949 - Tagging presets: value_template="..." for <text>

Use value_template to generate the value automatically based on other <text> values of this preset. For instance, "Bus {ref}: {from} → {to}" can be used to generate the name of a bus route relation.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/resources/data/tagging-preset.xsd

    r17605 r17610  
    332332            <annotation>
    333333                <documentation><![CDATA[
    334                     A comma separated list of alternative keys to use for auto completion of <text<.
     334                    A comma separated list of alternative keys to use for auto completion of <text>.
     335                ]]></documentation>
     336            </annotation>
     337        </attribute>
     338        <attribute name="value_template" type="string">
     339            <annotation>
     340                <documentation><![CDATA[
     341                    A template to generate the value automatically based on other <text> values of this preset.
     342                    For instance, "Bus {ref}: {from} → {to}" can be used to generate the name of a bus route relation.
    335343                ]]></documentation>
    336344            </annotation>
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java

    r17609 r17610  
    329329
    330330        boolean presetInitiallyMatches = !selected.isEmpty() && selected.stream().allMatch(this);
    331         final TaggingPresetItemGuiSupport itemGuiSupport = TaggingPresetItemGuiSupport.create(presetInitiallyMatches, selected);
     331        final TaggingPresetItemGuiSupport itemGuiSupport = TaggingPresetItemGuiSupport.create(
     332                presetInitiallyMatches, selected, this::getChangedTags);
    332333        JPanel items = new JPanel(new GridBagLayout());
    333334        TaggingPresetItem previous = null;
     
    363364        tb.setFocusable(false);
    364365        p.add(tb, GBC.std(1, 0).anchor(GBC.LINE_END));
     366
     367        // Trigger initial updates
     368        itemGuiSupport.fireItemValueModified(null, null, null);
    365369        return p;
    366370    }
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItemGuiSupport.java

    r17609 r17610  
    33
    44import org.openstreetmap.josm.data.osm.OsmPrimitive;
     5import org.openstreetmap.josm.data.osm.Tag;
     6import org.openstreetmap.josm.data.osm.search.SearchCompiler;
     7import org.openstreetmap.josm.gui.tagging.presets.items.KeyedItem;
     8import org.openstreetmap.josm.tools.ListenerList;
     9import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider;
    510
    611import java.util.Arrays;
    712import java.util.Collection;
     13import java.util.Collections;
     14import java.util.function.Supplier;
     15import java.util.stream.Collectors;
    816
    917/**
     
    1220 * @since xxx
    1321 */
    14 public class TaggingPresetItemGuiSupport {
     22public final class TaggingPresetItemGuiSupport implements TemplateEngineDataProvider {
    1523
    1624    private final Collection<OsmPrimitive> selected;
    1725    private final boolean presetInitiallyMatches;
     26    private final Supplier<Collection<Tag>> changedTagsSupplier;
     27    private final ListenerList<ChangeListener> listeners = ListenerList.create();
    1828
    19     private TaggingPresetItemGuiSupport(boolean presetInitiallyMatches, Collection<OsmPrimitive> selected) {
     29    /**
     30     * Interface to notify listeners that a preset item input as changed.
     31     * @since xxx
     32     */
     33    public interface ChangeListener {
     34        /**
     35         * Notifies this listener that a preset item input as changed.
     36         * @param source the source of this event
     37         * @param key the tag key
     38         * @param newValue the new tag value
     39         */
     40        void itemValueModified(TaggingPresetItem source, String key, String newValue);
     41    }
     42
     43    private TaggingPresetItemGuiSupport(
     44            boolean presetInitiallyMatches, Collection<OsmPrimitive> selected, Supplier<Collection<Tag>> changedTagsSupplier) {
    2045        this.selected = selected;
    2146        this.presetInitiallyMatches = presetInitiallyMatches;
     47        this.changedTagsSupplier = changedTagsSupplier;
    2248    }
    2349
     
    4773     * @return the new {@code TaggingPresetItemGuiSupport}
    4874     */
    49     public static TaggingPresetItemGuiSupport create(boolean presetInitiallyMatches, Collection<OsmPrimitive> selected) {
    50         return new TaggingPresetItemGuiSupport(presetInitiallyMatches, selected);
     75    public static TaggingPresetItemGuiSupport create(
     76            boolean presetInitiallyMatches, Collection<OsmPrimitive> selected, Supplier<Collection<Tag>> changedTagsSupplier) {
     77        return new TaggingPresetItemGuiSupport(presetInitiallyMatches, selected, changedTagsSupplier);
    5178    }
    5279
     
    5885     * @return the new {@code TaggingPresetItemGuiSupport}
    5986     */
    60     public static TaggingPresetItemGuiSupport create(boolean presetInitiallyMatches, OsmPrimitive... selected) {
    61         return new TaggingPresetItemGuiSupport(presetInitiallyMatches, Arrays.asList(selected));
     87    public static TaggingPresetItemGuiSupport create(
     88            boolean presetInitiallyMatches, OsmPrimitive... selected) {
     89        return new TaggingPresetItemGuiSupport(presetInitiallyMatches, Arrays.asList(selected), Collections::emptyList);
     90    }
     91
     92    @Override
     93    public Collection<String> getTemplateKeys() {
     94        return changedTagsSupplier.get().stream().map(Tag::getKey).collect(Collectors.toList());
     95    }
     96
     97    @Override
     98    public Object getTemplateValue(String key, boolean special) {
     99        return changedTagsSupplier.get().stream()
     100                .filter(tag -> key.equals(tag.getKey()))
     101                .findFirst().map(Tag::getValue).orElseGet(() -> {
     102                    KeyedItem.Usage usage = KeyedItem.determineTextUsage(getSelected(), key);
     103                    return usage.hasUniqueValue() ? usage.getFirst() : null;
     104                });
     105    }
     106
     107    @Override
     108    public boolean evaluateCondition(SearchCompiler.Match condition) {
     109        throw new UnsupportedOperationException();
     110    }
     111
     112    /**
     113     * Adds a new change listener
     114     * @param listener the listener to add
     115     */
     116    public void addListener(ChangeListener listener) {
     117        listeners.addListener(listener);
     118    }
     119
     120    /**
     121     * Notifies all listeners that a preset item input as changed.
     122     * @param source the source of this event
     123     * @param key the tag key
     124     * @param newValue the new tag value
     125     */
     126    public void fireItemValueModified(TaggingPresetItem source, String key, String newValue) {
     127        listeners.fireEvent(e -> e.itemValueModified(source, key, newValue));
    62128    }
    63129}
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/KeyedItem.java

    r16596 r17610  
    9696    /**
    9797     * Usage information on a key
    98      */
    99     protected static class Usage {
     98     *
     99     * TODO merge with {@link org.openstreetmap.josm.data.osm.TagCollection}
     100     */
     101    public static class Usage {
    100102        /**
    101103         * A set of values that were used for this key.
     
    139141    }
    140142
    141     protected static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
     143    /**
     144     * Computes the tag usage for the given key from the given primitives
     145     * @param sel the primitives
     146     * @param key the key
     147     * @return the tag usage
     148     */
     149    public static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
    142150        Usage returnValue = new Usage();
    143151        for (OsmPrimitive s : sel) {
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java

    r17609 r17610  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.Color;
    67import java.awt.Component;
    78import java.awt.GridBagLayout;
     
    2122import javax.swing.JPanel;
    2223import javax.swing.JToggleButton;
     24import javax.swing.event.DocumentEvent;
     25import javax.swing.event.DocumentListener;
    2326
    2427import org.openstreetmap.josm.data.osm.Tag;
     
    3235import org.openstreetmap.josm.tools.Logging;
    3336import org.openstreetmap.josm.tools.Utils;
     37import org.openstreetmap.josm.tools.template_engine.ParseError;
     38import org.openstreetmap.josm.tools.template_engine.TemplateEntry;
     39import org.openstreetmap.josm.tools.template_engine.TemplateParser;
     40import org.xml.sax.SAXException;
    3441
    3542/**
     
    5966
    6067    private JComponent value;
     68    private transient TemplateEntry valueTemplate;
    6169
    6270    @Override
     
    114122        }
    115123        initializeLocaleText(null);
     124
     125        setupListeners(textField, support);
    116126
    117127        // if there's an auto_increment setting, then wrap the text field
     
    229239        return Collections.singleton(default_);
    230240    }
     241
     242    public void setValue_template(String pattern) throws SAXException {
     243        try {
     244            this.valueTemplate = new TemplateParser(pattern).parse();
     245        } catch (ParseError e) {
     246            Logging.error("Error while parsing " + pattern + ": " + e.getMessage());
     247            throw new SAXException(e);
     248        }
     249    }
     250
     251    private void setupListeners(AutoCompletingTextField textField, TaggingPresetItemGuiSupport support) {
     252        textField.getDocument().addDocumentListener(new DocumentListener() {
     253            @Override
     254            public void insertUpdate(DocumentEvent e) {
     255                support.fireItemValueModified(Text.this, key, textField.getText());
     256            }
     257
     258            @Override
     259            public void removeUpdate(DocumentEvent e) {
     260                support.fireItemValueModified(Text.this, key, textField.getText());
     261            }
     262
     263            @Override
     264            public void changedUpdate(DocumentEvent e) {
     265                support.fireItemValueModified(Text.this, key, textField.getText());
     266            }
     267        });
     268
     269        if (valueTemplate != null) {
     270            textField.setForeground(Color.BLUE);
     271            support.addListener((source, key, newValue) -> {
     272                if (source != this) {
     273                    textField.setItem(valueTemplate.getText(support));
     274                }
     275            });
     276        }
     277    }
    231278}
  • trunk/src/org/openstreetmap/josm/tools/template_engine/TemplateEntry.java

    r13003 r17610  
    1010 */
    1111public interface TemplateEntry {
     12
     13    /**
     14     * Execute this template by generating text for a given data provider.
     15     * @param dataProvider the data provider from which information should be compiled to a string
     16     * @return the generated text
     17     */
     18    default String getText(TemplateEngineDataProvider dataProvider) {
     19        StringBuilder sb = new StringBuilder();
     20        appendText(sb, dataProvider);
     21        return sb.toString();
     22    }
     23
    1224    /**
    1325     * Execute this template by generating text for a given data provider.
Note: See TracChangeset for help on using the changeset viewer.