Index: trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 11646)
+++ trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java	(revision 11647)
@@ -4,12 +4,8 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 import javax.swing.JTable;
-import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableModel;
 
@@ -96,6 +92,6 @@
     public HistoryBrowserModel() {
         versionTableModel = new VersionTableModel(this);
-        currentTagTableModel = new TagTableModel(PointInTimeType.CURRENT_POINT_IN_TIME);
-        referenceTagTableModel = new TagTableModel(PointInTimeType.REFERENCE_POINT_IN_TIME);
+        currentTagTableModel = new TagTableModel(this, PointInTimeType.CURRENT_POINT_IN_TIME);
+        referenceTagTableModel = new TagTableModel(this, PointInTimeType.REFERENCE_POINT_IN_TIME);
         referenceNodeListTableModel = new DiffTableModel();
         currentNodeListTableModel = new DiffTableModel();
@@ -482,4 +478,5 @@
      * Returns the latest {@code HistoryOsmPrimitive}.
      * @return the latest {@code HistoryOsmPrimitive}
+     * @since 11646
      */
     public HistoryOsmPrimitive getLatest() {
@@ -488,138 +485,17 @@
 
     /**
-     * The table model for the tags of the version at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}
-     * or {@link PointInTimeType#CURRENT_POINT_IN_TIME}
-     *
-     */
-    public final class TagTableModel extends AbstractTableModel {
-
-        private List<String> keys;
-        private final PointInTimeType pointInTimeType;
-
-        private TagTableModel(PointInTimeType type) {
-            pointInTimeType = type;
-            initKeyList();
-        }
-
-        private void initKeyList() {
-            Set<String> keySet = new HashSet<>();
-            if (current != null) {
-                keySet.addAll(current.getTags().keySet());
-            }
-            if (reference != null) {
-                keySet.addAll(reference.getTags().keySet());
-            }
-            keys = new ArrayList<>(keySet);
-            Collections.sort(keys);
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getRowCount() {
-            if (keys == null)
-                return 0;
-            return keys.size();
-        }
-
-        @Override
-        public Object getValueAt(int row, int column) {
-            return getKeyAt(row);
-        }
-
-        /**
-         * Get the key for the given row.
-         * @param row The row
-         * @return The key in that row.
-         * @since 10637
-         */
-        public String getKeyAt(int row) {
-            return keys.get(row);
-        }
-
-        /**
-         * Determines if a tag exists for the given key.
-         * @param key tag key
-         * @return {@code true} if a tag exists for the given key
-         */
-        public boolean hasTag(String key) {
-            HistoryOsmPrimitive primitive = getPointInTime(pointInTimeType);
-            return primitive != null && primitive.hasKey(key);
-        }
-
-        /**
-         * Returns the tag value for the given key.
-         * @param key tag key
-         * @return tag value, or null
-         */
-        public String getValue(String key) {
-            HistoryOsmPrimitive primitive = getPointInTime(pointInTimeType);
-            if (primitive == null)
-                return null;
-            return primitive.get(key);
-        }
-
-        /**
-         * Determines if a tag exists in the opposite point in time for the given key.
-         * @param key tag key
-         * @return {@code true} if a tag exists for the given key
-         */
-        public boolean oppositeHasTag(String key) {
-            PointInTimeType opposite = pointInTimeType.opposite();
-            HistoryOsmPrimitive primitive = getPointInTime(opposite);
-            return primitive != null && primitive.hasKey(key);
-        }
-
-        /**
-         * Returns the tag value in the opposite point in time for the given key.
-         * @param key tag key
-         * @return tag value, or null
-         */
-        public String getOppositeValue(String key) {
-            PointInTimeType opposite = pointInTimeType.opposite();
-            HistoryOsmPrimitive primitive = getPointInTime(opposite);
-            if (primitive == null)
-                return null;
-            return primitive.get(key);
-        }
-
-        /**
-         * Determines if the tag value is the same in the opposite point in time for the given key.
-         * @param key tag key
-         * @return {@code true} if the tag value is the same in the opposite point in time for the given key
-         */
-        public boolean hasSameValueAsOpposite(String key) {
-            String value = getValue(key);
-            String oppositeValue = getOppositeValue(key);
-            return value != null && value.equals(oppositeValue);
-        }
-
-        /**
-         * Returns the type of point in time.
-         * @return the type of point in time
-         */
-        public PointInTimeType getPointInTimeType() {
-            return pointInTimeType;
-        }
-
-        /**
-         * Determines if this is the current point in time.
-         * @return {@code true} if this is the current point in time
-         */
-        public boolean isCurrentPointInTime() {
-            return pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME);
-        }
-
-        /**
-         * Determines if this is the reference point in time.
-         * @return {@code true} if this is the reference point in time
-         */
-        public boolean isReferencePointInTime() {
-            return pointInTimeType.equals(PointInTimeType.REFERENCE_POINT_IN_TIME);
-        }
-
-        @Override
-        public int getColumnCount() {
-            return 2;
-        }
+     * Returns the key set (union of current and reference point in type key sets).
+     * @return the key set (union of current and reference point in type key sets)
+     * @since 11647
+     */
+    public Set<String> getKeySet() {
+        Set<String> keySet = new HashSet<>();
+        if (current != null) {
+            keySet.addAll(current.getTags().keySet());
+        }
+        if (reference != null) {
+            keySet.addAll(reference.getTags().keySet());
+        }
+        return keySet;
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/history/TagInfoTransferHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/TagInfoTransferHandler.java	(revision 11646)
+++ trunk/src/org/openstreetmap/josm/gui/history/TagInfoTransferHandler.java	(revision 11647)
@@ -13,5 +13,4 @@
 import org.openstreetmap.josm.gui.datatransfer.TagTransferable;
 import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData;
-import org.openstreetmap.josm.gui.history.HistoryBrowserModel.TagTableModel;
 
 /**
Index: trunk/src/org/openstreetmap/josm/gui/history/TagTableCellRenderer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/TagTableCellRenderer.java	(revision 11646)
+++ trunk/src/org/openstreetmap/josm/gui/history/TagTableCellRenderer.java	(revision 11647)
@@ -33,6 +33,5 @@
     }
 
-    protected void setBackgroundReadable(String key, HistoryBrowserModel.TagTableModel model, boolean isSelected, boolean hasFocus,
-            boolean isValue) {
+    protected void setBackgroundReadable(String key, TagTableModel model, boolean isSelected, boolean hasFocus, boolean isValue) {
         Color bgColor = UIManager.getColor("Table.background");
         if ((!model.hasTag(key) && model.isCurrentPointInTime())
@@ -64,5 +63,5 @@
 
         String key = (String) value;
-        HistoryBrowserModel.TagTableModel model = getTagTableModel(table);
+        TagTableModel model = getTagTableModel(table);
 
         String text = "";
@@ -87,6 +86,6 @@
     }
 
-    protected HistoryBrowserModel.TagTableModel getTagTableModel(JTable table) {
-        return (HistoryBrowserModel.TagTableModel) table.getModel();
+    protected TagTableModel getTagTableModel(JTable table) {
+        return (TagTableModel) table.getModel();
     }
 }
Index: trunk/src/org/openstreetmap/josm/gui/history/TagTableModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/TagTableModel.java	(revision 11647)
+++ trunk/src/org/openstreetmap/josm/gui/history/TagTableModel.java	(revision 11647)
@@ -0,0 +1,146 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.history;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
+
+/**
+ * The table model for the tags of the version
+ * at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}
+ * or {@link PointInTimeType#CURRENT_POINT_IN_TIME}
+ * @since 11647 (extracted from HistoryBrowserModel)
+ */
+public final class TagTableModel extends AbstractTableModel {
+
+    private List<String> keys;
+    private final PointInTimeType pointInTimeType;
+    private final HistoryBrowserModel model;
+
+    /**
+     * Constructs a new {@code TagTableModel}.
+     * @param historyModel parent {@code HistoryBrowserModel}
+     * @param type type of point in time
+     */
+    public TagTableModel(HistoryBrowserModel historyModel, PointInTimeType type) {
+        model = historyModel;
+        pointInTimeType = type;
+        initKeyList();
+    }
+
+    void initKeyList() {
+        keys = new ArrayList<>(model.getKeySet());
+        Collections.sort(keys);
+        fireTableDataChanged();
+    }
+
+    @Override
+    public int getRowCount() {
+        if (keys == null)
+            return 0;
+        return keys.size();
+    }
+
+    @Override
+    public Object getValueAt(int row, int column) {
+        return getKeyAt(row);
+    }
+
+    /**
+     * Get the key for the given row.
+     * @param row The row
+     * @return The key in that row.
+     * @since 10637
+     */
+    public String getKeyAt(int row) {
+        return keys.get(row);
+    }
+
+    /**
+     * Determines if a tag exists for the given key.
+     * @param key tag key
+     * @return {@code true} if a tag exists for the given key
+     */
+    public boolean hasTag(String key) {
+        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType);
+        return primitive != null && primitive.hasKey(key);
+    }
+
+    /**
+     * Returns the tag value for the given key.
+     * @param key tag key
+     * @return tag value, or null
+     */
+    public String getValue(String key) {
+        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType);
+        if (primitive == null)
+            return null;
+        return primitive.get(key);
+    }
+
+    /**
+     * Determines if a tag exists in the opposite point in time for the given key.
+     * @param key tag key
+     * @return {@code true} if a tag exists for the given key
+     */
+    public boolean oppositeHasTag(String key) {
+        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType.opposite());
+        return primitive != null && primitive.hasKey(key);
+    }
+
+    /**
+     * Returns the tag value in the opposite point in time for the given key.
+     * @param key tag key
+     * @return tag value, or null
+     */
+    public String getOppositeValue(String key) {
+        HistoryOsmPrimitive primitive = model.getPointInTime(pointInTimeType.opposite());
+        if (primitive == null)
+            return null;
+        return primitive.get(key);
+    }
+
+    /**
+     * Determines if the tag value is the same in the opposite point in time for the given key.
+     * @param key tag key
+     * @return {@code true} if the tag value is the same in the opposite point in time for the given key
+     */
+    public boolean hasSameValueAsOpposite(String key) {
+        String value = getValue(key);
+        String oppositeValue = getOppositeValue(key);
+        return value != null && value.equals(oppositeValue);
+    }
+
+    /**
+     * Returns the type of point in time.
+     * @return the type of point in time
+     */
+    public PointInTimeType getPointInTimeType() {
+        return pointInTimeType;
+    }
+
+    /**
+     * Determines if this is the current point in time.
+     * @return {@code true} if this is the current point in time
+     */
+    public boolean isCurrentPointInTime() {
+        return pointInTimeType.equals(PointInTimeType.CURRENT_POINT_IN_TIME);
+    }
+
+    /**
+     * Determines if this is the reference point in time.
+     * @return {@code true} if this is the reference point in time
+     */
+    public boolean isReferencePointInTime() {
+        return pointInTimeType.equals(PointInTimeType.REFERENCE_POINT_IN_TIME);
+    }
+
+    @Override
+    public int getColumnCount() {
+        return 2;
+    }
+}
