001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.history; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.BorderLayout; 007import java.awt.Dimension; 008 009import javax.swing.JPanel; 010import javax.swing.JScrollPane; 011import javax.swing.JSplitPane; 012import javax.swing.JTabbedPane; 013 014import org.openstreetmap.josm.data.osm.OsmPrimitive; 015import org.openstreetmap.josm.data.osm.OsmPrimitiveType; 016import org.openstreetmap.josm.data.osm.history.History; 017import org.openstreetmap.josm.tools.Destroyable; 018 019/** 020 * HistoryBrowser is an UI component which displays history information about an {@link OsmPrimitive}. 021 * 022 * @since 1709 023 */ 024public class HistoryBrowser extends JPanel implements Destroyable { 025 026 /** the model */ 027 private transient HistoryBrowserModel model; 028 private TagInfoViewer tagInfoViewer; 029 private NodeListViewer nodeListViewer; 030 private RelationMemberListViewer relationMemberListViewer; 031 private CoordinateInfoViewer coordinateInfoViewer; 032 private JTabbedPane tpViewers; 033 034 /** 035 * Constructs a new {@code HistoryBrowser}. 036 */ 037 public HistoryBrowser() { 038 model = new HistoryBrowserModel(); 039 build(); 040 } 041 042 /** 043 * Constructs a new {@code HistoryBrowser}. 044 * @param history the history of an {@link OsmPrimitive} 045 */ 046 public HistoryBrowser(History history) { 047 this(); 048 populate(history); 049 } 050 051 /** 052 * creates the table which shows the list of versions 053 * 054 * @return the panel with the version table 055 */ 056 protected JPanel createVersionTablePanel() { 057 JPanel pnl = new JPanel(new BorderLayout()); 058 pnl.add(new JScrollPane(new VersionTable(model)), BorderLayout.CENTER); 059 return pnl; 060 } 061 062 /** 063 * creates the panel which shows information about two different versions 064 * of the same {@link OsmPrimitive}. 065 * 066 * @return the panel 067 */ 068 protected JPanel createVersionComparePanel() { 069 tpViewers = new JTabbedPane(); 070 071 // create the viewers, but don't add them yet. 072 // see populate() 073 // 074 tagInfoViewer = new TagInfoViewer(model); 075 nodeListViewer = new NodeListViewer(model); 076 relationMemberListViewer = new RelationMemberListViewer(model); 077 coordinateInfoViewer = new CoordinateInfoViewer(model); 078 JPanel pnl = new JPanel(new BorderLayout()); 079 pnl.add(tpViewers, BorderLayout.CENTER); 080 081 tpViewers.addChangeListener(e -> { 082 if (tpViewers.getSelectedComponent() == coordinateInfoViewer) { 083 // while building the component size is not yet known, thus panning does not give reasonable results 084 coordinateInfoViewer.setDisplayToFitMapMarkers(); 085 } 086 }); 087 088 return pnl; 089 } 090 091 /** 092 * builds the GUI 093 */ 094 protected void build() { 095 JPanel left = createVersionTablePanel(); 096 JPanel right = createVersionComparePanel(); 097 setLayout(new BorderLayout()); 098 JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right); 099 add(pane, BorderLayout.CENTER); 100 101 pane.setOneTouchExpandable(true); 102 pane.setDividerLocation(300); 103 104 Dimension minimumSize = new Dimension(100, 50); 105 left.setMinimumSize(minimumSize); 106 right.setMinimumSize(minimumSize); 107 } 108 109 /** 110 * populates the browser with the history of a specific {@link OsmPrimitive} 111 * 112 * @param history the history 113 */ 114 public void populate(History history) { 115 model.setHistory(history); 116 117 tpViewers.removeAll(); 118 119 tpViewers.add(tagInfoViewer); 120 tpViewers.setTitleAt(0, tr("Tags")); 121 122 if (history.getEarliest().getType() == OsmPrimitiveType.NODE) { 123 tpViewers.add(coordinateInfoViewer); 124 tpViewers.setTitleAt(1, tr("Coordinates")); 125 } else if (history.getEarliest().getType() == OsmPrimitiveType.WAY) { 126 tpViewers.add(nodeListViewer); 127 tpViewers.setTitleAt(1, tr("Nodes")); 128 } else if (history.getEarliest().getType() == OsmPrimitiveType.RELATION) { 129 tpViewers.add(relationMemberListViewer); 130 tpViewers.setTitleAt(1, tr("Members")); 131 } 132 revalidate(); 133 } 134 135 /** 136 * replies the {@link History} currently displayed by this browser 137 * 138 * @return the current history 139 */ 140 public History getHistory() { 141 return model.getHistory(); 142 } 143 144 /** 145 * replies the model used by this browser 146 * @return the model 147 */ 148 public HistoryBrowserModel getModel() { 149 return model; 150 } 151 152 @Override 153 public void destroy() { 154 model.unlinkAsListener(); 155 for (Destroyable component : new Destroyable[] { 156 tagInfoViewer, nodeListViewer, relationMemberListViewer, coordinateInfoViewer}) { 157 component.destroy(); 158 } 159 } 160}