Changeset 2048 in josm


Ignore:
Timestamp:
2009-09-04T10:49:53+02:00 (10 years ago)
Author:
Gubaer
Message:

Improved auto completion
fixed #2729: Auto completion with numbers sometimes annoying (only fixed in presets, relation editor, not in property dialog)
fixed #2320: Preset dialog for house numbers should have autocompletion (auto completion now supported in all preset dialogs)

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
11 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r2044 r2048  
    6666import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    6767import org.openstreetmap.josm.gui.SideButton;
    68 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    69 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    7068import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    7169import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
     
    7573import org.openstreetmap.josm.gui.tagging.TagEditorModel;
    7674import org.openstreetmap.josm.gui.tagging.TagTable;
     75import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     76import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    7777import org.openstreetmap.josm.io.OsmApi;
    7878import org.openstreetmap.josm.io.OsmServerObjectReader;
     
    125125        //
    126126        acCache = AutoCompletionCache.getCacheForLayer(getLayer());
    127         acCache.initFromJOSMDataset();
     127        acCache.initFromDataSet();
    128128        acList = new AutoCompletionList();
    129129
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberRoleCellEditor.java

    r2040 r2048  
    99import javax.swing.table.TableCellEditor;
    1010
    11 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    12 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionItemPritority;
    13 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    14 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionListItem;
    1511import org.openstreetmap.josm.gui.tagging.AutoCompletingTextField;
     12import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     13import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
     14import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     15import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    1616
    1717public class MemberRoleCellEditor extends AbstractCellEditor implements TableCellEditor {
  • trunk/src/org/openstreetmap/josm/gui/tagging/AutoCompletingTextField.java

    r2040 r2048  
    22package org.openstreetmap.josm.gui.tagging;
    33
     4import java.awt.Component;
    45import java.awt.event.FocusAdapter;
    56import java.awt.event.FocusEvent;
     
    89import java.util.logging.Logger;
    910
     11import javax.swing.ComboBoxEditor;
    1012import javax.swing.JTextField;
    1113import javax.swing.text.AttributeSet;
     
    1416import javax.swing.text.PlainDocument;
    1517
    16 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
     18import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    1719
    1820/**
     
    2527 *
    2628 */
    27 public class AutoCompletingTextField extends JTextField {
     29public class AutoCompletingTextField extends JTextField implements ComboBoxEditor {
    2830
    2931    static private Logger logger = Logger.getLogger(AutoCompletingTextField.class.getName());
     
    5456                return;
    5557            }
     58
    5659            String currentText = getText(0, getLength());
     60            // if the text starts with a number we don't autocomplete
     61            //
     62            try {
     63                Long.parseLong(str);
     64                if (currentText.length() == 0) {
     65                    // we don't autocomplete on numbers
     66                    super.insertString(offs, str, a);
     67                    return;
     68                }
     69                Long.parseLong(currentText);
     70                super.insertString(offs, str, a);
     71                return;
     72            } catch(NumberFormatException e) {
     73                // either the new text or the current text isn't a number. We continue with
     74                // autocompletion
     75            }
    5776            String prefix = currentText.substring(0, offs);
    5877            autoCompletionList.applyFilter(prefix+str);
     
    150169        this.autoCompletionList = autoCompletionList;
    151170    }
     171
     172    public Component getEditorComponent() {
     173        return this;
     174    }
     175
     176    public Object getItem() {
     177        return getText();
     178    }
     179
     180    public void setItem(Object anObject) {
     181        if (anObject == null) {
     182            setText("");
     183        } else {
     184            setText(anObject.toString());
     185        }
     186
     187    }
     188
     189
    152190}
  • trunk/src/org/openstreetmap/josm/gui/tagging/TagCellEditor.java

    r2040 r2048  
    99import javax.swing.table.TableCellEditor;
    1010
    11 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    12 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionItemPritority;
    13 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    14 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionListItem;
     11import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     12import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
     13import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     14import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    1515
    1616/**
  • trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorPanel.java

    r2046 r2048  
    2020import javax.swing.event.ListSelectionListener;
    2121
    22 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    23 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    2422import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     23import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     24import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    2525import org.openstreetmap.josm.tools.ImageProvider;
    2626
     
    228228        //
    229229        acCache = AutoCompletionCache.getCacheForLayer(layer);
    230         acCache.initFromJOSMDataset();
     230        acCache.initFromDataSet();
    231231        acList = new AutoCompletionList();
    232232
  • trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java

    r2040 r2048  
    3434
    3535import org.openstreetmap.josm.gui.dialogs.relation.RunnableAction;
    36 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    37 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
     36import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     37import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    3838
    3939/**
  • trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java

    r2017 r2048  
    1818import java.util.Collection;
    1919import java.util.HashMap;
    20 import java.util.HashSet;
    2120import java.util.LinkedHashMap;
    2221import java.util.LinkedList;
    2322import java.util.List;
    24 import java.util.Set;
     23import java.util.TreeSet;
    2524
    2625import javax.swing.AbstractAction;
     
    4544import org.openstreetmap.josm.gui.ExtendedDialog;
    4645import org.openstreetmap.josm.gui.QuadStateCheckBox;
     46import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     47import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     48import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
     49import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    4750import org.openstreetmap.josm.io.MirroredInputStream;
    4851import org.openstreetmap.josm.tools.GBC;
     
    6669
    6770    public static abstract class Item {
     71        protected void initAutoCompletionField(AutoCompletingTextField field, String key) {
     72            OsmDataLayer layer = Main.main.getEditLayer();
     73            if (layer == null) return;
     74            AutoCompletionCache cache = AutoCompletionCache.getCacheForLayer(layer);
     75            AutoCompletionList list = new AutoCompletionList();
     76            cache.populateWithValues(list, false /* don't append */);
     77            field.setAutoCompletionList(list);
     78        }
     79
    6880        public boolean focus = false;
    6981        abstract boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel);
     
    7385
    7486    public static class Usage {
    75         Set<String> values;
    76         Boolean hadKeys = false;
    77         Boolean hadEmpty = false;
    78         public Boolean allSimilar()
    79         {
     87        TreeSet<String> values;
     88        boolean hadKeys = false;
     89        boolean hadEmpty = false;
     90        public boolean hasUniqueValue() {
    8091            return values.size() == 1 && !hadEmpty;
    8192        }
    82         public Boolean unused()
    83         {
     93
     94        public boolean unused() {
    8495            return values.size() == 0;
    8596        }
    86         public String getFirst()
    87         {
    88             return (String)(values.toArray()[0]);
    89         }
    90         public Boolean hadKeys()
    91         {
     97        public String getFirst() {
     98            return values.first();
     99        }
     100
     101        public boolean hadKeys() {
    92102            return hadKeys;
    93103        }
     
    98108    static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
    99109        Usage returnValue = new Usage();
    100         returnValue.values = new HashSet<String>();
     110        returnValue.values = new TreeSet<String>();
    101111        for (OsmPrimitive s : sel) {
    102112            String v = s.get(key);
     
    106116                returnValue.hadEmpty = true;
    107117            }
    108             returnValue.hadKeys = returnValue.hadKeys | s.hasKeys();
     118            returnValue.hadKeys = ! returnValue.values.isEmpty() | returnValue.hadEmpty;
    109119        }
    110120        return returnValue;
     
    114124
    115125        Usage returnValue = new Usage();
    116         returnValue.values = new HashSet<String>();
     126        returnValue.values = new TreeSet<String>();
    117127        for (OsmPrimitive s : sel) {
    118128            returnValue.values.add(OsmUtils.getNamedOsmBoolean(s.get(key)));
     
    133143        private JComponent value;
    134144
     145
    135146        @Override public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
    136147
    137148            // find out if our key is already used in the selection.
    138149            Usage usage = determineTextUsage(sel, key);
    139             if (usage.unused())
    140             {
    141                 value = new JTextField();
     150            if (usage.unused()){
     151                AutoCompletingTextField textField = new AutoCompletingTextField();
     152                initAutoCompletionField(textField, key);
    142153                if (use_last_as_default && lastValue.containsKey(key)) {
    143                     ((JTextField)value).setText(lastValue.get(key));
     154                    textField.setText(lastValue.get(key));
    144155                } else {
    145                     ((JTextField)value).setText(default_);
    146                 }
     156                    textField.setText(default_);
     157                }
     158                value = textField;
    147159                originalValue = null;
    148             } else if (usage.allSimilar()) {
     160            } else if (usage.hasUniqueValue()) {
    149161                // all objects use the same value
    150                 value = new JTextField();
    151                 for (String s : usage.values) {
    152                     ((JTextField) value).setText(s);
    153                 }
    154                 originalValue = ((JTextField)value).getText();
     162                AutoCompletingTextField textField = new AutoCompletingTextField();
     163                initAutoCompletionField(textField, key);
     164                textField.setText(usage.getFirst());
     165                value = textField;
     166                originalValue = usage.getFirst();
    155167            } else {
    156168                // the objects have different values
    157                 value = new JComboBox(usage.values.toArray());
    158                 ((JComboBox)value).setEditable(true);
    159                 ((JComboBox)value).getEditor().setItem(DIFFERENT);
     169                AutoCompletingTextField textField = new AutoCompletingTextField();
     170                initAutoCompletionField(textField, key);
     171                JComboBox comboBox = new JComboBox(usage.values.toArray());
     172                comboBox.setEditable(true);
     173                comboBox.setEditor(textField);
     174                comboBox.getEditor().setItem(DIFFERENT);
     175                value=comboBox;
    160176                originalValue = DIFFERENT;
    161177            }
     
    300316
    301317            lhm = new LinkedHashMap<String,String>();
    302             if (!usage.allSimilar() && !usage.unused())
    303             {
     318            if (!usage.hasUniqueValue() && !usage.unused()){
    304319                lhm.put(DIFFERENT, DIFFERENT);
    305320            }
     
    309324                                tr(display_array[i]) : display_array[i]);
    310325            }
    311             if(!usage.unused())
    312             {
     326            if(!usage.unused()){
    313327                for (String s : usage.values) {
    314328                    if (!lhm.containsKey(s)) {
     
    326340            combo = new JComboBox(lhm.values().toArray());
    327341            combo.setEditable(editable);
    328             if (usage.allSimilar() && !usage.unused())
    329             {
     342            AutoCompletingTextField tf = new AutoCompletingTextField();
     343            initAutoCompletionField(tf, key);
     344            tf.getAutoCompletionList().add(Arrays.asList(display_array), AutoCompletionItemPritority.IS_IN_STANDARD);
     345            combo.setEditor(tf);
     346
     347            if (usage.hasUniqueValue() && !usage.unused()){
    330348                originalValue=usage.getFirst();
    331349                combo.setSelectedItem(lhm.get(originalValue));
    332350            }
    333351            // use default only in case it is a totally new entry
    334             else if(default_ != null && !usage.hadKeys())
    335             {
     352            else if(default_ != null && !usage.hadKeys()) {
    336353                combo.setSelectedItem(default_);
    337354                originalValue=DIFFERENT;
    338355            }
    339             else if(usage.unused())
    340             {
     356            else if(usage.unused()){
    341357                combo.setSelectedItem("");
    342358                originalValue="";
    343359            }
    344             else
    345             {
     360            else{
    346361                combo.setSelectedItem(DIFFERENT);
    347362                originalValue=DIFFERENT;
     
    628643        if (data == null)
    629644            return null;
     645        OsmDataLayer layer = Main.main.getEditLayer();
     646        if (layer != null) {
     647            AutoCompletionCache.getCacheForLayer(layer).initFromDataSet();
     648        }
    630649        PresetPanel p = new PresetPanel();
    631650        LinkedList<Item> l = new LinkedList<Item>();
    632         if(types != null)
    633         {
     651        if(types != null){
    634652            JPanel pp = new JPanel();
    635             for(String t : types)
    636             {
     653            for(String t : types){
    637654                JLabel la = new JLabel(ImageProvider.get("Mf_" + t));
    638655                la.setToolTipText(tr("Elements of type {0} are supported.", tr(t)));
     
    642659        }
    643660
    644         for (Item i : data)
    645         {
     661        for (Item i : data){
    646662            if(i instanceof Link) {
    647663                l.add(i);
    648             } else
    649             {
     664            } else {
    650665                if(i.addToPanel(p, selected)) {
    651666                    p.hasElements = true;
     
    683698                            true);
    684699                    contentConstraints = GBC.eol().fill().insets(5,10,5,0);
    685                     setupDialog(content, new String[] {"ok.png", "cancel.png" });
     700                    setButtonIcons(new String[] {"ok.png", "cancel.png" });
     701                    setContent(content);
     702                    setupDialog();
    686703                    buttons.get(0).setEnabled(!disableApply);
    687704                    buttons.get(0).setToolTipText(title);
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionCache.java

    r1930 r2048  
    1 package org.openstreetmap.josm.gui.dialogs.relation.ac;
     1package org.openstreetmap.josm.gui.tagging.ac;
    22
    33import java.util.ArrayList;
     
    55import java.util.Collections;
    66import java.util.HashMap;
     7import java.util.HashSet;
     8import java.util.LinkedList;
    79import java.util.List;
     10import java.util.Set;
    811import java.util.logging.Logger;
    912
     
    6770
    6871
    69     /** the cache */
    70     private HashMap<String, ArrayList<String>> cache;
    71     private  ArrayList<String> roleCache;
     72    /** the cached tags give by a tag key and a list of values for this tag*/
     73    private HashMap<String, Set<String>> tagCache;
     74    /** the cached list of member roles */
     75    private  Set<String> roleCache;
     76    /** the cache of all tag values */
     77    private  Set<String> allTagValues;
     78    /**  the layer this cache is built for */
    7279    private OsmDataLayer layer;
    7380
     81
    7482    /**
    7583     * constructor
    7684     */
    7785    public AutoCompletionCache(OsmDataLayer layer) {
    78         cache = new HashMap<String, ArrayList<String>>();
    79         roleCache = new ArrayList<String>();
     86        tagCache = new HashMap<String, Set<String>>();
     87        roleCache = new HashSet<String>();
     88        allTagValues = new HashSet<String>();
    8089        this.layer = layer;
    8190    }
     
    91100     */
    92101    protected void cacheKey(String key) {
    93         if (cache.containsKey(key))
     102        if (tagCache.containsKey(key))
    94103            return;
    95         else {
    96             cache.put(key, new ArrayList<String>());
    97         }
     104        tagCache.put(key, new HashSet<String>());
    98105    }
    99106
     
    106113    protected void cacheValue(String key, String value) {
    107114        cacheKey(key);
    108         ArrayList<String> values = cache.get(key);
    109         if (!values.contains(value)) {
    110             values.add(value);
    111         }
     115        tagCache.get(key).add(value);
     116        allTagValues.add(value);
    112117    }
    113118
     
    143148     *
    144149     */
    145     public void initFromJOSMDataset() {
    146         cache = new HashMap<String, ArrayList<String>>();
     150    public void initFromDataSet() {
     151        tagCache = new HashMap<String, Set<String>>();
    147152        if (layer == null)
    148153            return;
     
    152157        }
    153158        for (Relation relation : layer.data.relations) {
    154             if (relation.incomplete || relation.deleted) {
     159            if (relation.incomplete || relation.isDeleted()) {
    155160                continue;
    156161            }
    157162            cacheRelationMemberRoles(relation);
    158             Collections.sort(roleCache);
    159163        }
    160164    }
     
    166170     */
    167171    public List<String> getKeys() {
    168         return new ArrayList<String>(cache.keySet());
     172        return new ArrayList<String>(tagCache.keySet());
    169173    }
    170174
     
    177181     */
    178182    public List<String> getValues(String key) {
    179         if (!cache.containsKey(key))
     183        if (!tagCache.containsKey(key))
    180184            return new ArrayList<String>();
    181         return cache.get(key);
     185        return new ArrayList<String>(tagCache.get(key));
    182186    }
    183187
     
    188192     */
    189193    public List<String> getMemberRoles() {
    190         return roleCache;
     194        return new ArrayList<String>(roleCache);
    191195    }
    192196
     
    199203    public void populateWithMemberRoles(AutoCompletionList list) {
    200204        list.clear();
    201         for (String role: roleCache) {
    202             list.add(new AutoCompletionListItem(role, AutoCompletionItemPritority.IS_IN_DATASET));
    203         }
     205        list.add(roleCache, AutoCompletionItemPritority.IS_IN_DATASET);
     206    }
     207
     208    /**
     209     * Populates the an {@see AutoCompletionList} with the currently cached
     210     * values for a tag
     211     *
     212     * @param list the list to populate
     213     * @param key the tag key
     214     * @param append true to add the values to the list; false, to replace the values
     215     * in the list by the tag values
     216     */
     217    public void populateWithTagValues(AutoCompletionList list, String key, boolean append) {
     218        if (!append) {
     219            list.clear();
     220        }
     221        list.add(getValues(key), AutoCompletionItemPritority.IS_IN_DATASET);
     222    }
     223
     224    /**
     225     * Populates the an {@see AutoCompletionList} with the currently cached
     226     * tag keys
     227     *
     228     * @param list the list to populate
     229     * @param append true to add the keys to the list; false, to replace the keys
     230     * in the list by the keys in the cache
     231     */
     232    public void populateWithKeys(AutoCompletionList list, boolean append) {
     233        if (!append) {
     234            list.clear();
     235        }
     236        list.add(tagCache.keySet(), AutoCompletionItemPritority.IS_IN_DATASET);
     237    }
     238
     239
     240    /**
     241     * Populates the an {@see AutoCompletionList} with the currently cached
     242     * tag values
     243     *
     244     * @param list the list to populate
     245     * @param append true to add the keys to the list; false, to replace the keys
     246     * in the list by the keys in the cache
     247     */
     248    public void populateWithValues(AutoCompletionList list, boolean append) {
     249        if (!append) {
     250            list.clear();
     251        }
     252        list.add(this.allTagValues, AutoCompletionItemPritority.IS_IN_DATASET);
    204253    }
    205254}
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionItemPritority.java

    r1762 r2048  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.relation.ac;
     2package org.openstreetmap.josm.gui.tagging.ac;
    33
    44public enum AutoCompletionItemPritority implements Comparable<AutoCompletionItemPritority> {
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionList.java

    r1762 r2048  
    1 package org.openstreetmap.josm.gui.dialogs.relation.ac;
     1package org.openstreetmap.josm.gui.tagging.ac;
    22
    33import java.util.ArrayList;
     4import java.util.Collection;
    45import java.util.Collections;
    56import java.util.List;
     
    125126    }
    126127
     128    /**
     129     * adds a list of strings to this list. Only strings which
     130     * are not null and which do not exist yet in the list are added.
     131     *
     132     * @param value a list of strings to add
     133     * @param priority the priority to use
     134     */
     135    public void add(Collection<String> values, AutoCompletionItemPritority priority) {
     136        if (values == null) return;
     137        for (String value: values) {
     138            if (value == null) {
     139                continue;
     140            }
     141            AutoCompletionListItem item = new AutoCompletionListItem(value,priority);
     142            appendOrUpdatePriority(item);
     143
     144        }
     145        sort();
     146        filter();
     147    }
     148
    127149    protected void appendOrUpdatePriority(AutoCompletionListItem toadd) {
    128150        AutoCompletionListItem item = lookup(toadd.getValue());
  • trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionListItem.java

    r1762 r2048  
    11// License: GPL. For details, see LICENSE file.
    2 package org.openstreetmap.josm.gui.dialogs.relation.ac;
     2package org.openstreetmap.josm.gui.tagging.ac;
    33
    44/**
Note: See TracChangeset for help on using the changeset viewer.