Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionCache.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionCache.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionCache.java	(revision 14324)
@@ -0,0 +1,116 @@
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ * AutoCompletionCache temporarily holds a cache of keys with a list of
+ * possible auto completion values for each key.
+ * 
+ * The cache can initialize itself from the current JOSM data set such that
+ * <ol>
+ *   <li>any key used in a tag in the data set is part of the key list in the cache</li>
+ *   <li>any value used in a tag for a specific key is part of the autocompletion list of
+ *     this key</li>
+ * </ol>  
+ * 
+ * Building up auto completion lists should not
+ * slow down tabbing from input field to input field. Looping through the complete
+ * data set in order to build up the auto completion list for a specific input
+ * field is not efficient enough, hence this cache.   
+ *
+ */
+public class AutoCompletionCache {
+	
+	/** the cache */
+	private HashMap<String, ArrayList<String>> cache;
+	
+	/**
+	 * constructor 
+	 */
+	public AutoCompletionCache() {
+		cache = new HashMap<String, ArrayList<String>>();
+	}
+
+	/**
+	 * make sure, <code>key</code> is in the cache 
+	 * 
+	 * @param key  the key 
+	 */
+	protected void cacheKey(String key) {
+		if (cache.containsKey(key)) {
+			return;
+		} else {
+			cache.put(key, new ArrayList<String>());
+		}
+	}
+	
+	/**
+	 * make sure, value is one of the auto completion values allowed for key 
+	 * 
+	 * @param key the key 
+	 * @param value the value 
+	 */
+	protected void cacheValue(String key, String value) {
+		cacheKey(key);
+		ArrayList<String> values = cache.get(key);
+		if (!values.contains(value)) {
+			values.add(value);
+		}
+	}
+	
+	/**
+	 * make sure, the keys and values of all tags held by primitive are
+	 * in the auto completion cache 
+	 *  
+	 * @param primitive an OSM primitive 
+	 */
+	protected void cachePrimitive(OsmPrimitive primitive) {
+		for (String key: primitive.keySet()) {
+			String value = primitive.get(key);
+			cacheValue(key, value);
+		}
+	}
+	
+	/**
+	 * initializes the cache from the current JOSM dataset {@link OsmPrimitive}s.
+	 * 
+	 */
+	public void initFromJOSMDataset() {
+		cache = new HashMap<String, ArrayList<String>>();
+		Collection<OsmPrimitive> ds = Main.ds.allNonDeletedPrimitives();
+		for (OsmPrimitive primitive : ds) {
+			cachePrimitive(primitive);
+		}
+	}
+	
+	/**
+	 * replies the keys held by the cache
+	 *  
+	 * @return the list of keys held by the cache 
+	 */
+	public List<String> getKeys() {
+		return new ArrayList<String>(cache.keySet());
+	}
+	
+	
+	/**
+	 * replies the auto completion values allowed for a specific key. Replies
+	 * an empty list if key is null or if key is not in {@link #getKeys()}.
+	 * 
+	 * @param key 
+	 * @return the list of auto completion values  
+	 */
+	public List<String> getValues(String key) {
+		if (!cache.containsKey(key)) {
+			return new ArrayList<String>();
+		} else {
+			return cache.get(key);
+		}
+	}
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionContext.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionContext.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionContext.java	(revision 14324)
@@ -0,0 +1,54 @@
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+import org.openstreetmap.josm.Main;
+
+public class AutoCompletionContext {
+	
+	private boolean selectionIncludesNodes = false;
+	private boolean selectionIncludesWays = false;
+	private boolean selectionIncludesRelations = false;
+	private boolean selectionEmpty = false; 
+	
+	public AutoCompletionContext(){
+	}
+
+	public void initFromJOSMSelection() {
+		selectionIncludesNodes = ! Main.ds.getSelectedNodes().isEmpty();
+		selectionIncludesWays = !Main.ds.getSelectedWays().isEmpty();
+		selectionIncludesRelations = !Main.ds.getSelectedRelations().isEmpty();
+		selectionEmpty = (Main.ds.getSelected().size() == 0);
+	}
+	
+	
+	public boolean isSelectionEmpty() {
+		return selectionEmpty;
+	}
+
+	public boolean isSelectionIncludesNodes() {
+		return selectionIncludesNodes;
+	}
+
+	public void setSelectionIncludesNodes(boolean selectionIncludesNodes) {
+		this.selectionIncludesNodes = selectionIncludesNodes;
+	}
+
+	public boolean isSelectionIncludesWays() {
+		return selectionIncludesWays;
+	}
+
+	public void setSelectionIncludesWays(boolean selectionIncludesWays) {
+		this.selectionIncludesWays = selectionIncludesWays;
+	}
+
+	public boolean isSelectionIncludesRelations() {
+		return selectionIncludesRelations;
+	}
+
+	public void setSelectionIncludesRelations(boolean selectionIncludesRelations) {
+		this.selectionIncludesRelations = selectionIncludesRelations;
+	}
+	
+	
+	
+
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionItemPritority.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionItemPritority.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionItemPritority.java	(revision 14324)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+public enum AutoCompletionItemPritority implements Comparable<AutoCompletionItemPritority> {
+
+	/** indicates that a value is in the current selection */
+	IS_IN_SELECTION,
+
+	/** indicates that this is a standard value, i.e. a standard tag name 
+	 *  or a standard value for a given tag name 
+	 */
+	IS_IN_STANDARD,
+	
+	
+	/**
+	 * indicates that this is an arbitrary value from the data set, i.e. 
+	 * the value of a tag name=xxx
+	 */
+	IS_IN_DATASET,
+	
+	/** unknown priority. This is the lowest priority. */
+	UNKNOWN
+	
+	
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionList.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionList.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionList.java	(revision 14324)
@@ -0,0 +1,296 @@
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+/**
+ * AutoCompletionList manages a list of {@see AutoCompletionListItem}s.
+ * 
+ * The list is sorted, items with higher priority first, then according to lexicographic order 
+ * on the value of the {@see AutoCompletionListItem}. 
+ * 
+ * AutoCompletionList maintains two views on the list of {@see AutoCompletionListItem}s.
+ * <ol>
+ *   <li>the bare, unfiltered view which includes all items</li>
+ *   <li>a filtered view, which includes only items which match a current filter expression</li>   
+ * </ol>
+ * 
+ * AutoCompletionList is an {@link AbstractTableModel} which serves the list of filtered
+ * items to a {@link JTable}.
+ * 
+ * @author gubaer
+ */
+public class AutoCompletionList extends AbstractTableModel {
+
+	/** the bare list of AutoCompletionItems */
+	private ArrayList<AutoCompletionListItem> list = null;	
+	/**  the filtered list of AutoCompletionItems */ 
+	private ArrayList<AutoCompletionListItem> filtered = null;	
+	/** the filter expression */ 
+	private String filter = null; 
+
+	/**
+	 * constructor 
+	 */
+	public AutoCompletionList() {
+		list = new ArrayList<AutoCompletionListItem>();
+		filtered = new ArrayList<AutoCompletionListItem>();
+	}
+	
+	
+	/**
+	 * applies a filter expression to the list of {@see AutoCompletionListItem}s.
+	 * 
+	 * The matching criterion is a case insensitive substring match. 
+	 * 
+	 * @param filter  the filter expression; must not be null
+	 * 
+	 * @exception IllegalArgumentException thrown, if filter is null
+	 */
+	public void applyFilter(String filter) {
+		if (filter == null) {
+			throw new IllegalArgumentException("argument 'filter' must not be null");
+		}
+		this.filter = filter;
+		filter();
+	}
+	
+	/**
+	 * clears the current filter 
+	 * 
+	 */
+	public void clearFilter() {
+		filter = null;
+		filter();
+	}
+	
+	/**
+	 * @return the current filter expression; null, if no filter expression is set 
+	 */
+	public String getFilter() {
+		return filter; 
+	}
+	
+	
+	/** 
+	 * adds an AutoCompletionListItem to the list. Only adds the item if it
+	 * is not null and if not in the list yet. 
+	 *  
+	 * @param item the item 
+	 */
+	public void add(AutoCompletionListItem item) {
+		if (item == null) {
+			return; 
+		}
+		appendOrUpdatePriority(item);
+		sort();
+		filter();
+	}
+	
+	
+	/**
+	 * adds another AutoCompletionList to this list. An item is only
+	 * added it is not null and if it does not exist in the list yet. 
+	 * 
+	 * @param other another auto completion list; must not be null
+	 * @exception IllegalArgumentException thrown, if other is null 
+	 */
+	public void add(AutoCompletionList other) {
+		if (other == null) {
+			throw new IllegalArgumentException("argument 'other' must not be null");
+		}
+		for (AutoCompletionListItem item : other.list) {
+			appendOrUpdatePriority(item);
+		}
+		sort();
+		filter();
+	}
+	
+	
+	/**
+	 * adds a list of AutoCompletionListItem to this list. Only items which
+	 * are not null and which do not exist yet in the list are added. 
+	 * 
+	 * @param other a list of AutoCompletionListItem; must not be null
+	 * @exception IllegalArgumentException thrown, if other is null 
+	 */
+	public void add(List<AutoCompletionListItem> other) {
+		if (other == null)	{
+			throw new IllegalArgumentException("argument 'other' must not be null");
+		}
+		for (AutoCompletionListItem toadd : other) {
+			appendOrUpdatePriority(toadd);
+		}
+		sort();
+		filter();
+	}
+
+	protected void appendOrUpdatePriority(AutoCompletionListItem toadd) {
+		AutoCompletionListItem item = lookup(toadd.getValue());
+		if (item == null) {
+			// new item does not exist yet. Add it to the list
+			//
+			list.add(toadd);
+		} else {
+			// new item already exists. Update priority if necessary
+			//
+			if (toadd.getPriority().compareTo(item.getPriority()) < 0) {
+				item.setPriority(toadd.getPriority());
+			}
+		}
+	}
+	
+	/**
+	 * checks whether a specific item is already in the list. Matches for the 
+	 * the value <strong>and</strong> the priority of the item 
+	 * 
+	 * @param item the item to check
+	 * @return true, if item is in the list; false, otherwise 
+	 */
+	public boolean contains(AutoCompletionListItem item) {
+		if (item == null) {
+			return false; 
+		}
+		return list.contains(item);
+	}
+	
+	/**
+	 * checks whether an item with the given value is already in the list. Ignores
+	 * priority of the items.
+	 * 
+	 * @param value the value of an auto completion item 
+	 * @return true, if value is in the list; false, otherwise  
+	 */
+	public boolean contains(String value) {
+		if (value == null) {
+			return false; 
+		}
+		for (AutoCompletionListItem item: list) {
+			if (item.getValue().equals(value)) {
+				return true; 
+			}
+		}
+		return false; 
+	}
+	
+	/**
+	 * 
+	 * @param value a specific value 
+	 * @return  the auto completion item for this value; null, if there is no
+	 *   such auto completion item 
+	 */
+	public AutoCompletionListItem lookup(String value) {
+		if (value == null) {
+			return null;
+		}
+		for (AutoCompletionListItem item : list) {
+			if (item.getValue().equals(value)) {
+				return item;
+			}
+		}
+		return null;
+	}
+	
+	
+	/**
+	 * removes the auto completion item with key <code>key</code>
+	 * @param key  the key; 
+	 */
+	public void remove(String key) {
+		if (key == null) {
+			return; 
+		}
+		for (int i=0;i< list.size();i++) {
+			AutoCompletionListItem item = list.get(i);
+			if (item.getValue().equals(key)) {
+				list.remove(i);
+				return; 
+			}
+		}		
+	}
+	
+	
+	
+	/**
+	 * sorts the list 
+	 */
+	protected void sort() {
+		Collections.sort(list);		
+	}
+	
+	protected void filter() {
+		filtered.clear();
+		if (filter == null) {
+			// Collections.copy throws an exception "Source does not fit in dest"
+			// Collections.copy(filtered, list);
+			filtered.ensureCapacity(list.size());
+			for (AutoCompletionListItem item: list) {
+				filtered.add(item);
+			}			
+			return;
+		}
+		
+		// apply the pattern to list of possible values. If it matches, add the
+		// value to the list of filtered values 
+		// 
+		for (AutoCompletionListItem item : list) {
+			if (item.getValue().startsWith(filter)) {
+				filtered.add(item);
+			}
+		}
+		
+		fireTableDataChanged();
+	}
+	
+	/**
+	 * replies the number of filtered items 
+	 *   
+	 * @return the number of filtered items 
+	 */
+	public int getFilteredSize() {
+		return this.filtered.size();
+	}
+	
+	/**
+	 * replies the idx-th item from the list of filtered items 
+	 * @param idx the index; must be in the range 0<= idx < {@see #getFilteredSize()}
+	 * @return the item
+	 * 
+	 * @exception IndexOutOfBoundsException thrown, if idx is out of bounds
+	 */
+	public AutoCompletionListItem getFilteredItem(int idx) {
+		if (idx < 0 || idx >= getFilteredSize()) {
+			throw new IndexOutOfBoundsException("idx out of bounds. idx=" + idx);
+		}
+		return filtered.get(idx);
+	}
+	
+	
+	/**
+	 * removes all elements from the auto completion list
+	 * 
+	 */
+	public void clear() {
+		list.clear();
+		fireTableDataChanged();
+	}
+	
+	
+	@Override public int getColumnCount() {
+		return 1;
+	}
+
+	@Override public int getRowCount() {
+	
+	    return list == null ? 0 : getFilteredSize();
+    }
+
+	@Override public Object getValueAt(int rowIndex, int columnIndex) {
+		return list == null ? null : getFilteredItem(rowIndex);
+    }
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListItem.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListItem.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListItem.java	(revision 14324)
@@ -0,0 +1,131 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+/**
+ * Represents an entry in the list of auto completion values.
+ * 
+ *  An AutoCompletionListItem has a <em>priority</em> and a <em>value</em>. 
+ *  
+ *  The priority helps to sort the auto completion items according to their importance. For instance,
+ *  in an auto completion list for tag names, standard tag names would be assigned a higher
+ *  priority than arbitrary tag names present in the current data set. There are three priority levels,
+ *  {@see AutoCompletionItemPritority}.
+ *
+ * The value is a string which will be displayed in the auto completion list.    
+ * 
+ * @author gubaer
+ *
+ */
+public class AutoCompletionListItem implements Comparable<AutoCompletionListItem>{
+
+	/** the pritority of this item */ 
+	private  AutoCompletionItemPritority priority;
+	/** the value of this item */ 
+	private String value;
+	
+	/**
+	 * constructor 
+	 */
+	public AutoCompletionListItem() {
+		value = "";
+		priority = AutoCompletionItemPritority.UNKNOWN;
+	}
+	
+	public AutoCompletionListItem(String value, AutoCompletionItemPritority priority) {
+		this.value = value;
+		this.priority = priority;
+	}
+
+	/**
+	 * 
+	 * @return the priority 
+	 */
+	public AutoCompletionItemPritority getPriority() {
+    	return priority;
+    }
+
+	/**
+	 * sets the priority 
+	 * @param priority  the priority 
+	 */
+	public void setPriority(AutoCompletionItemPritority priority) {
+    	this.priority = priority;
+    }
+
+	/**
+	 * 
+	 * @return the value 
+	 */
+	public String getValue() {
+    	return value;
+    }
+
+	/**
+	 * sets the value 
+	 * @param value the value; must not be null
+	 * @exception IllegalArgumentException thrown, if value if null
+	 */
+	public void setValue(String value) {
+		if (value == null)	{
+			throw new IllegalArgumentException("argument 'value' must not be null");
+		}
+    	this.value = value;
+    }
+
+	@Override public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("<AutoCompletionItemPritority: ");
+		sb.append("value='");
+		sb.append(value);
+		sb.append("',");
+		sb.append("priority='");
+		sb.append(priority.toString());
+		sb.append("'>");
+		return sb.toString();
+	}
+
+	@Override public int hashCode() {
+	    final int prime = 31;
+	    int result = 1;
+	    result = prime * result
+	            + ((priority == null) ? 0 : priority.hashCode());
+	    result = prime * result + ((value == null) ? 0 : value.hashCode());
+	    return result;
+    }
+
+	@Override public boolean equals(Object obj) {
+	    if (this == obj)
+		    return true;
+	    if (obj == null)
+		    return false;
+	    if (getClass() != obj.getClass())
+		    return false;
+	    final AutoCompletionListItem other = (AutoCompletionListItem)obj;
+	    if (priority == null) {
+		    if (other.priority != null)
+			    return false;
+	    } else if (!priority.equals(other.priority))
+		    return false;
+	    if (value == null) {
+		    if (other.value != null)
+			    return false;
+	    } else if (!value.equals(other.value))
+		    return false;
+	    return true;
+    }
+	
+
+	@Override public int compareTo(AutoCompletionListItem other) {
+		int ret = this.priority.compareTo(other.priority);
+		if (ret != 0) {
+			return ret;
+		} else {
+			return this.value.compareTo(other.value);
+		}
+	}
+
+	
+	
+	
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListRenderer.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListRenderer.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListRenderer.java	(revision 14324)
@@ -0,0 +1,137 @@
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+/**
+ * This is the table cell renderer for the list of auto completion list items.
+ * 
+ * It uses an instance of {@Link JLabel} to render an {@link AutoCompletionListItem}.  
+ * 
+ *
+ */
+public class AutoCompletionListRenderer implements TableCellRenderer {
+
+
+	static public final String RES_OSM_ICON = "/resources/osm.gif";
+	static public final String RES_SELECTION_ICON = "/resources/selection.gif";
+	public static final Color BG_COLOR_SELECTED = new Color(143,170,255);
+	
+	/** the renderer component */
+	private JLabel renderer;
+	
+	/** the icon used to decorate items of priority
+	 *  {@link AutoCompletionItemPritority#IS_IN_STANDARD} 
+	 */
+	private Icon iconStandard;
+	
+	/** the icon used to decorate items of priority 
+	 *  {@link AutoCompletionItemPritority#IS_IN_SELECTION}
+	 */
+	private Icon iconSelection;
+	
+	/**
+	 * constructor 
+	 */
+	public AutoCompletionListRenderer() {
+		renderer = new JLabel();
+		renderer.setOpaque(true);
+		
+		loadIcons();
+	}
+	
+	/**
+	 * loads the icons 
+	 */
+	protected void loadIcons() {
+		java.net.URL imgURL = getClass().getResource(RES_OSM_ICON);
+	    if (imgURL != null) {
+	    	iconStandard = new ImageIcon(imgURL);
+	    } else {
+	        System.err.println("Could not load icon: " + RES_OSM_ICON);
+	        iconStandard = null;
+	    }
+	    
+		imgURL = getClass().getResource(RES_SELECTION_ICON);
+	    if (imgURL != null) {
+	    	iconSelection = new ImageIcon(imgURL);
+	    } else {
+	        System.err.println("Could not load icon: " + RES_SELECTION_ICON);
+	        iconSelection = null;
+	    }
+	}
+	
+	
+	/**
+	 * prepares the renderer for rendering a specific icon 
+	 * 
+	 * @param item the item to be rendered 
+	 */
+	protected void prepareRendererIcon(AutoCompletionListItem item) {
+		if (item.getPriority().equals(AutoCompletionItemPritority.IS_IN_STANDARD)) {
+			if (iconStandard != null) {
+				renderer.setIcon(iconStandard);
+			}
+		} else if (item.getPriority().equals(AutoCompletionItemPritority.IS_IN_SELECTION)) {
+			if (iconSelection != null) {
+				renderer.setIcon(iconSelection);
+			}
+		}
+	}
+	
+	/**
+	 * resets the renderer 
+	 */
+	protected void resetRenderer() {
+		renderer.setIcon(null);
+		renderer.setText("");
+		renderer.setOpaque(true);
+		renderer.setBackground(Color.WHITE);
+		renderer.setForeground(Color.BLACK);
+	}
+	
+	/**
+	 * prepares background and text colors for a selected item 
+	 */
+	protected void renderSelected() {
+		renderer.setBackground(BG_COLOR_SELECTED);
+		renderer.setForeground(Color.WHITE);
+	}
+	
+	@Override
+	public Component getTableCellRendererComponent(JTable table, Object value,
+			boolean isSelected, boolean hasFocus, int row, int column) {
+		
+		resetRenderer();
+		// set icon and text 
+		//
+		if (value instanceof AutoCompletionListItem) {
+			AutoCompletionListItem item = (AutoCompletionListItem)value;
+			prepareRendererIcon(item);
+			renderer.setText(item.getValue());
+		} else if (value != null) {
+			renderer.setText(value.toString());
+		} else {
+			renderer.setText("<null>");
+		}
+		
+		// prepare background and foreground for a selected item 
+		//
+		if (isSelected) {
+			renderSelected();
+		}
+		
+		
+		return renderer;
+	
+	}
+
+	
+	
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListViewer.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListViewer.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/AutoCompletionListViewer.java	(revision 14324)
@@ -0,0 +1,210 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.logging.Logger;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.KeyStroke;
+import javax.swing.ListSelectionModel;
+import javax.swing.table.DefaultTableModel;
+
+/**
+ * 
+ * 
+ *
+ */
+@SuppressWarnings("serial")
+public class AutoCompletionListViewer extends JPanel {
+	
+	static private Logger logger = Logger.getLogger(AutoCompletionListViewer.class.getName());
+
+	/** the table showing the auto completion list entries */
+	private JTable table = null;
+	
+	/** the auto completion list to be displayed */
+	private AutoCompletionList autoCompletionList = null;
+	
+	/** the listeners */
+	private ArrayList<IAutoCompletionListListener> listener = null;
+	
+	
+	/**
+	 * creates the GUI 
+	 */
+	protected void createGUI() {
+		setBackground(Color.WHITE);
+		setLayout(new BorderLayout());
+	
+		
+		table = new JTable();
+		
+		// the table model
+		//
+		if (autoCompletionList == null) {
+			logger.info("setting model to default model");
+			table.setModel(new DefaultTableModel());
+		} else {
+			logger.info("setting model to " + autoCompletionList);
+			table.setModel(autoCompletionList);
+		}
+		
+		// no table header required 
+		table.setTableHeader(null);
+		
+		// set cell renderer 
+		//
+		table.setDefaultRenderer(Object.class, new AutoCompletionListRenderer());
+		
+		// embed in a scroll pane 
+		JScrollPane p  = new JScrollPane(table);
+		p.setBackground(Color.WHITE);
+		add(p, BorderLayout.CENTER);
+		
+		// only single selection allowed
+		//
+		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		
+		// fire item change event on double click
+		//
+		table.addMouseListener(
+				new MouseAdapter() {
+					@Override
+					public void mouseClicked(MouseEvent e) {
+						if (e.getClickCount() == 2) {
+							int row = table.getSelectedRow();
+							String item = autoCompletionList.getFilteredItem(row).getValue();
+							fireAutoCompletionListItemSelected(item);
+						}
+					}					
+				}
+		);
+
+
+	}
+	
+	
+	/**
+	 * constructor 
+	 * 
+	 * @param list the auto completion list to be rendered. If null, the list is empty.
+	 *  
+	 */
+	public AutoCompletionListViewer(AutoCompletionList list) {		
+		this.autoCompletionList = list;
+		createGUI();
+		listener = new ArrayList<IAutoCompletionListListener>();
+	}
+	
+	
+	/**
+	 * constructor 
+	 */
+	public AutoCompletionListViewer() {
+		this.autoCompletionList = null;
+		createGUI();
+		listener = new ArrayList<IAutoCompletionListListener>();
+	}
+
+
+	/**
+	 * 
+	 */
+	@Override public Dimension getMaximumSize() {	    
+	    Dimension d = super.getMaximumSize();
+	    d.width = 100;
+	    return d;
+    }
+	
+	/**
+	 * 
+	 */
+	@Override public Dimension getPreferredSize() {	    
+	    Dimension d = super.getMaximumSize();
+	    d.width = 150;
+	    return d;
+    }
+
+
+	/**
+	 * replies the auto completion list this viewer renders
+	 * 
+	 * @return the auto completion list; may be null 
+	 */
+	public AutoCompletionList getAutoCompletionList() {
+    	return autoCompletionList;
+    }
+
+
+	/**
+	 * sets the auto completion list this viewer renders 
+	 * 
+	 * @param autoCompletionList  the auto completion list; may be null
+	 */
+	public void setAutoCompletionList(AutoCompletionList autoCompletionList) {
+    	this.autoCompletionList = autoCompletionList;
+    	if (autoCompletionList == null) {
+    		table.setModel(new DefaultTableModel());
+    	} else {
+    		table.setModel(autoCompletionList);
+    	}
+    }
+
+
+	
+	/**
+	 * add an {@link IAutoCompletionListListener}
+	 * 
+	 * @param listener  the listener 
+	 */
+	public void addAutoCompletionListListener(IAutoCompletionListListener listener) {
+		if (listener != null && !this.listener.contains(listener)) {
+			synchronized(this.listener) {
+				this.listener.add(listener);
+			}
+		}
+	}
+	
+	/**
+	 * removes a {@link IAutoCompletionListListener} 
+	 * 
+	 * @param listener the listener 
+	 */
+	public void removeAutoCompletionListListener(IAutoCompletionListListener listener) {
+		if (listener != null && this.listener.contains(listener)) {
+			synchronized(this.listener) {
+				this.listener.remove(listener);
+			}
+		}
+	}
+	
+	
+	/**
+	 * notifies listeners about a selected item in the auto completion list  
+	 */
+	protected void fireAutoCompletionListItemSelected(String item) {
+		synchronized(this.listener) {
+			for (IAutoCompletionListListener target: listener) {
+				target.autoCompletionItemSelected(item);
+			}			
+		}
+	}	
+	
+	
+	public void installKeyAction(Action a) {
+		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put((KeyStroke)a.getValue(AbstractAction.ACCELERATOR_KEY), a.getValue(AbstractAction.NAME));
+		getActionMap().put(a.getValue(AbstractAction.NAME), a);
+
+	}
+}
Index: /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/IAutoCompletionListListener.java
===================================================================
--- /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/IAutoCompletionListListener.java	(revision 14324)
+++ /applications/editors/josm/plugins/tageditor/src/org/openstreetmap/josm/plugins/tageditor/ac/IAutoCompletionListListener.java	(revision 14324)
@@ -0,0 +1,5 @@
+package org.openstreetmap.josm.plugins.tageditor.ac;
+
+public interface IAutoCompletionListListener {
+	public void autoCompletionItemSelected(String item);
+}
