Changeset 7725 in josm for trunk/src


Ignore:
Timestamp:
2014-11-15T21:45:22+01:00 (10 years ago)
Author:
bastiK
Message:

autocomplete: remember user input and prefer recently entered strings

It bugged my, that in tag add dialog, JOSM always autocompletes addr:h to
addr:housename. But addr:housenumber is what I want.

Now it remembers the last tags that have been entered in a session
and gives those the highest priority in autocompletion.
More recent entries are preferred.

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java

    r7681 r7725  
    371371            if (key.equals(newkey) || value == null) {
    372372                Main.main.undoRedo.add(new ChangePropertyCommand(sel, newkey, value));
     373                AutoCompletionManager.rememberUserInput(newkey, value, true);
    373374            } else {
    374375                for (OsmPrimitive osm: sel) {
     
    401402                } else {
    402403                    commands.add(new ChangePropertyCommand(sel, newkey, value));
     404                    AutoCompletionManager.rememberUserInput(newkey, value, false);
    403405                }
    404406                Main.main.undoRedo.add(new SequenceCommand(
     
    771773            lastAddValue = value;
    772774            recentTags.put(new Tag(key, value), null);
     775            AutoCompletionManager.rememberUserInput(key, value, false);
    773776            commandCount++;
    774777            Main.main.undoRedo.add(new ChangePropertyCommand(sel, key, value));
  • trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetItems.java

    r7613 r7725  
    5454import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPriority;
    5555import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     56import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
    5657import org.openstreetmap.josm.gui.widgets.JosmComboBox;
    5758import org.openstreetmap.josm.gui.widgets.JosmTextField;
     
    767768
    768769            changedTags.add(new Tag(key, v));
     770            AutoCompletionManager.rememberUserInput(key, v, true);
    769771        }
    770772
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionItemPriority.java

    r6830 r7725  
    3737    public static final AutoCompletionItemPriority UNKNOWN = new AutoCompletionItemPriority(false, false, false);
    3838
     39    private final static int NO_USER_INPUT = Integer.MAX_VALUE;
     40
     41    private final int userInput;
    3942    private final boolean inDataSet;
    4043    private final boolean inStandard;
    4144    private final boolean selected;
     45   
    4246
    43     public AutoCompletionItemPriority(boolean inDataSet, boolean inStandard, boolean selected) {
     47    /**
     48     * Create new AutoCompletionItemPriority object.
     49     *
     50     * @param inDataSet true, if the item is found in the currently active data layer
     51     * @param inStandard true, if the item is a standard tag, e.g. from the presets.
     52     * @param selected true, if it is found on an object that is currently selected
     53     * @param userInput null, if the user hasn't entered this tag so far. A number when
     54     * the tag key / value has been entered by the user before. A lower number means
     55     * this happened more recently and beats a higher number in priority.
     56     */
     57    public AutoCompletionItemPriority(boolean inDataSet, boolean inStandard, boolean selected, Integer userInput) {
    4458        this.inDataSet = inDataSet;
    4559        this.inStandard = inStandard;
    4660        this.selected = selected;
     61        this.userInput = userInput == null ? NO_USER_INPUT : userInput;
     62    }
     63
     64    public AutoCompletionItemPriority(boolean inDataSet, boolean inStandard, boolean selected) {
     65        this(inDataSet, inStandard, selected, NO_USER_INPUT);
    4766    }
    4867
     
    5978    }
    6079
     80    public Integer getUserInput() {
     81        return userInput == NO_USER_INPUT ? null : userInput;
     82    }
     83   
    6184    /**
    6285     * Imposes an ordering on the priorities.
     
    6588    @Override
    6689    public int compareTo(AutoCompletionItemPriority other) {
     90        int ui = -Integer.compare(userInput, other.userInput);
     91        if (ui != 0) return ui;
     92
    6793        int sel = Boolean.valueOf(selected).compareTo(other.selected);
    6894        if (sel != 0) return sel;
     
    85111                inDataSet || other.inDataSet,
    86112                inStandard || other.inStandard,
    87                 selected || other.selected);
     113                selected || other.selected,
     114                Math.min(userInput, other.userInput));
    88115    }
    89116
    90117    @Override public String toString() {
    91         return String.format("<Priority; inDataSet: %b, inStandard: %b, selected: %b>", inDataSet, inStandard, selected);
     118        return String.format("<Priority; userInput: %s, inDataSet: %b, inStandard: %b, selected: %b>",
     119                userInput == NO_USER_INPUT ? "no" : Integer.toString(userInput), inDataSet, inStandard, selected);
    92120    }
    93121}
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionList.java

    r7005 r7725  
    148148        filter();
    149149    }
     150   
     151    public void addUserInput(Collection<String> values) {
     152        if (values == null) return;
     153        int i = 0;
     154        for (String value: values) {
     155            if (value == null) {
     156                continue;
     157            }
     158            AutoCompletionListItem item = new AutoCompletionListItem(value, new AutoCompletionItemPriority(false, false, false, i));
     159            appendOrUpdatePriority(item);
     160            i++;
     161        }
     162        sort();
     163        filter();
     164    }
    150165
    151166    protected void appendOrUpdatePriority(AutoCompletionListItem toAdd) {
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java

    r7556 r7725  
    77import java.util.Collections;
    88import java.util.HashSet;
     9import java.util.LinkedHashSet;
    910import java.util.List;
    1011import java.util.Map;
    1112import java.util.Map.Entry;
     13import java.util.Objects;
    1214import java.util.Set;
    1315
     
    5456public class AutoCompletionManager implements DataSetListener {
    5557
     58    /**
     59     * Data class to remember tags that the user has entered.
     60     */
     61    public static class UserInputTag {
     62        public String key;
     63        public String value;
     64        public boolean defaultKey;
     65
     66        /**
     67         * Constructor.
     68         *
     69         * @param key the tag key
     70         * @param value the tag value
     71         * @param defaultKey true, if the key was not really entered by the
     72         * user, e.g. for preset text fields.
     73         * In this case, the key will not get any higher priority, just the value.
     74         */
     75        public UserInputTag(String key, String value, boolean defaultKey) {
     76            this.key = key;
     77            this.value = value;
     78            this.defaultKey = defaultKey;
     79        }
     80
     81        @Override
     82        public int hashCode() {
     83            int hash = 7;
     84            hash = 59 * hash + Objects.hashCode(this.key);
     85            hash = 59 * hash + Objects.hashCode(this.value);
     86            hash = 59 * hash + (this.defaultKey ? 1 : 0);
     87            return hash;
     88        }
     89
     90        @Override
     91        public boolean equals(Object obj) {
     92            if (obj == null) {
     93                return false;
     94            }
     95            if (getClass() != obj.getClass()) {
     96                return false;
     97            }
     98            final UserInputTag other = (UserInputTag) obj;
     99            if (!Objects.equals(this.key, other.key)) {
     100                return false;
     101            }
     102            if (!Objects.equals(this.value, other.value)) {
     103                return false;
     104            }
     105            if (this.defaultKey != other.defaultKey) {
     106                return false;
     107            }
     108            return true;
     109        }
     110    }
     111
    56112    /** If the dirty flag is set true, a rebuild is necessary. */
    57113    protected boolean dirty;
     
    70126     */
    71127    protected static final MultiMap<String, String> presetTagCache = new MultiMap<>();
     128    /**
     129     * Cache for tags that have been entered by the user.
     130     */
     131    protected static final Set<UserInputTag> userInputTagCache = new LinkedHashSet<>();
     132   
    72133    /**
    73134     * the cached list of member roles
     
    174235        }
    175236    }
     237   
     238   
     239    public static void rememberUserInput(String key, String value, boolean defaultKey) {
     240        UserInputTag tag = new UserInputTag(key, value, defaultKey);
     241        userInputTagCache.remove(tag); // re-add, so it gets to the last position of the LinkedHashSet
     242        userInputTagCache.add(tag);
     243    }
    176244
    177245    /**
     
    187255        return new ArrayList<>(presetTagCache.keySet());
    188256    }
     257   
     258    protected Collection<String> getUserInputKeys() {
     259        List<String> keys = new ArrayList<>();
     260        for (UserInputTag tag : userInputTagCache) {
     261            if (!tag.defaultKey) {
     262                keys.add(tag.key);
     263            }
     264        }
     265        Collections.reverse(keys);
     266        return new LinkedHashSet<>(keys);
     267    }
    189268
    190269    /**
     
    201280    protected static List<String> getPresetValues(String key) {
    202281        return new ArrayList<>(presetTagCache.getValues(key));
     282    }
     283
     284    protected static Collection<String> getUserInputValues(String key) {
     285        ArrayList<String> values = new ArrayList<>();
     286        for (UserInputTag tag : userInputTagCache) {
     287            if (key.equals(tag.key)) {
     288                values.add(tag.value);
     289            }
     290        }
     291        Collections.reverse(values);
     292        return new LinkedHashSet<>(values);
    203293    }
    204294
     
    261351        list.add(new AutoCompletionListItem("source", AutoCompletionItemPriority.IS_IN_STANDARD));
    262352        list.add(getDataKeys(), AutoCompletionItemPriority.IS_IN_DATASET);
     353        list.addUserInput(getUserInputKeys());
    263354    }
    264355
     
    285376            list.add(getPresetValues(key), AutoCompletionItemPriority.IS_IN_STANDARD);
    286377            list.add(getDataValues(key), AutoCompletionItemPriority.IS_IN_DATASET);
     378            list.addUserInput(getUserInputValues(key));
    287379        }
    288380    }
Note: See TracChangeset for help on using the changeset viewer.