001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.history; 003 004import java.awt.event.FocusEvent; 005import java.awt.event.FocusListener; 006import java.util.Arrays; 007import java.util.Collection; 008import java.util.HashMap; 009import java.util.Map; 010import java.util.function.IntFunction; 011import java.util.function.Supplier; 012 013import javax.swing.JPopupMenu; 014import javax.swing.JTable; 015import javax.swing.ListSelectionModel; 016 017import org.openstreetmap.josm.data.osm.Tagged; 018import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 019import org.openstreetmap.josm.gui.dialogs.properties.CopyAllKeyValueAction; 020import org.openstreetmap.josm.gui.dialogs.properties.CopyKeyValueAction; 021import org.openstreetmap.josm.gui.dialogs.properties.CopyValueAction; 022import org.openstreetmap.josm.gui.dialogs.properties.HelpAction; 023import org.openstreetmap.josm.gui.dialogs.properties.TaginfoAction; 024import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher; 025 026/** 027 * TagInfoViewer is a UI component which displays the list of tags of two 028 * version of a {@link org.openstreetmap.josm.data.osm.OsmPrimitive} in a {@link org.openstreetmap.josm.data.osm.history.History}. 029 * 030 * <ul> 031 * <li>on the left, it displays the list of tags for the version at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}</li> 032 * <li>on the right, it displays the list of tags for the version at {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li> 033 * </ul> 034 * @since 1709 035 */ 036public class TagInfoViewer extends HistoryViewerPanel { 037 private static final class RepaintOnFocusChange implements FocusListener { 038 @Override 039 public void focusLost(FocusEvent e) { 040 repaintSelected(e); 041 } 042 043 @Override 044 public void focusGained(FocusEvent e) { 045 repaintSelected(e); 046 } 047 048 private static void repaintSelected(FocusEvent e) { 049 // we would only need the selected rows, but this is easier: 050 e.getComponent().repaint(); 051 } 052 } 053 054 /** 055 * Constructs a new {@code TagInfoViewer}. 056 * @param model The history browsing model 057 */ 058 public TagInfoViewer(HistoryBrowserModel model) { 059 super(model); 060 } 061 062 @Override 063 protected JTable buildReferenceTable() { 064 return buildTable(PointInTimeType.REFERENCE_POINT_IN_TIME, "table.referencetagtable", model::getReferencePointInTime); 065 } 066 067 @Override 068 protected JTable buildCurrentTable() { 069 return buildTable(PointInTimeType.CURRENT_POINT_IN_TIME, "table.currenttagtable", model::getCurrentPointInTime); 070 } 071 072 private JTable buildTable(PointInTimeType pointInTime, String name, Supplier<HistoryOsmPrimitive> histoSp) { 073 TagTableModel tagTableModel = model.getTagTableModel(pointInTime); 074 JTable table = new JTable(tagTableModel, new TagTableColumnModel()); 075 table.setName(name); 076 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 077 selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel()); 078 table.setTransferHandler(new TagInfoTransferHandler()); 079 table.addFocusListener(new RepaintOnFocusChange()); 080 JPopupMenu tagMenu = new JPopupMenu(); 081 082 IntFunction<String> tagKeyFn = x -> (String) table.getValueAt(x, 0); 083 IntFunction<Map<String, Integer>> tagValuesFn = x -> { 084 Map<String, Integer> map = new HashMap<>(); 085 String key = tagTableModel.getValue((String) table.getValueAt(x, 0)); 086 if (key != null) { 087 map.put(key, 1); 088 } 089 return map; 090 }; 091 Supplier<Collection<? extends Tagged>> objectSp = () -> Arrays.asList(histoSp.get()); 092 093 tagMenu.add(new CopyValueAction(table, tagKeyFn, objectSp)); 094 tagMenu.add(new CopyKeyValueAction(table, tagKeyFn, objectSp)); 095 tagMenu.add(new CopyAllKeyValueAction(table, tagKeyFn, objectSp)); 096 tagMenu.addSeparator(); 097 tagMenu.add(new HelpAction(table, tagKeyFn, tagValuesFn, null, null)); 098 tagMenu.add(new TaginfoAction(table, tagKeyFn, tagValuesFn, null, null)); 099 100 table.addMouseListener(new PopupMenuLauncher(tagMenu)); 101 return table; 102 } 103}