001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.history; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.marktr; 006import static org.openstreetmap.josm.tools.I18n.tr; 007 008import java.awt.BorderLayout; 009import java.awt.FlowLayout; 010import java.awt.event.ActionEvent; 011import java.awt.event.WindowAdapter; 012import java.awt.event.WindowEvent; 013 014import javax.swing.AbstractAction; 015import javax.swing.JButton; 016import javax.swing.JDialog; 017import javax.swing.JLabel; 018import javax.swing.JPanel; 019 020import org.openstreetmap.josm.Main; 021import org.openstreetmap.josm.data.osm.PrimitiveId; 022import org.openstreetmap.josm.data.osm.history.History; 023import org.openstreetmap.josm.data.osm.history.HistoryDataSet; 024import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener; 025import org.openstreetmap.josm.gui.MainApplication; 026import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction; 027import org.openstreetmap.josm.gui.help.HelpUtil; 028import org.openstreetmap.josm.gui.util.GuiHelper; 029import org.openstreetmap.josm.tools.ImageProvider; 030import org.openstreetmap.josm.tools.InputMapUtils; 031 032/** 033 * This is non-modal dialog, always showing on top, which displays history information 034 * about a given {@link org.openstreetmap.josm.data.osm.OsmPrimitive}. 035 * @since 1709 036 */ 037public class HistoryBrowserDialog extends JDialog implements HistoryDataSetListener { 038 039 /** the embedded browser */ 040 private final HistoryBrowser browser = new HistoryBrowser(); 041 private final CloseAction closeAction = new CloseAction(); 042 private final JLabel titleLabel = new JLabel("", JLabel.CENTER); 043 044 /** 045 * Constructs a new {@code HistoryBrowserDialog}. 046 * 047 * @param history the history to be displayed 048 */ 049 public HistoryBrowserDialog(History history) { 050 super(GuiHelper.getFrameForComponent(Main.parent), false); 051 build(); 052 setHistory(history); 053 setTitle(buildTitle(history)); 054 pack(); 055 if (getInsets().top > 0) { 056 titleLabel.setVisible(false); 057 } 058 HistoryDataSet.getInstance().addHistoryDataSetListener(this); 059 addWindowListener(new WindowClosingAdapter()); 060 } 061 062 /** 063 * Constructs the title for this dialog 064 * 065 * @param h the current history 066 * @return the title for this dialog 067 */ 068 static String buildTitle(History h) { 069 String title; 070 switch (h.getEarliest().getType()) { 071 case NODE: title = marktr("History for node {0}"); 072 break; 073 case WAY: title = marktr("History for way {0}"); 074 break; 075 case RELATION: title = marktr("History for relation {0}"); 076 break; 077 default: title = ""; 078 } 079 return tr(title, Long.toString(h.getId())); 080 } 081 082 @Override 083 public void setTitle(String title) { 084 super.setTitle(title); 085 if (titleLabel != null) { 086 titleLabel.setText(title); 087 } 088 } 089 090 /** 091 * builds the GUI 092 */ 093 protected void build() { 094 setLayout(new BorderLayout()); 095 096 add(titleLabel, BorderLayout.NORTH); 097 098 add(browser, BorderLayout.CENTER); 099 100 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); 101 102 JButton btn = new JButton(new ReloadAction()); 103 btn.setName("btn.reload"); 104 pnl.add(btn); 105 106 btn = new JButton(closeAction); 107 btn.setName("btn.close"); 108 pnl.add(btn); 109 InputMapUtils.addEscapeAction(getRootPane(), closeAction); 110 111 btn = new JButton(new ContextSensitiveHelpAction(ht("/Action/ObjectHistory"))); 112 btn.setName("btn.help"); 113 pnl.add(btn); 114 add(pnl, BorderLayout.SOUTH); 115 116 HelpUtil.setHelpContext(getRootPane(), ht("/Action/ObjectHistory")); 117 } 118 119 /** 120 * Sets the current history. 121 * @param history current history 122 */ 123 protected void setHistory(History history) { 124 browser.populate(history); 125 } 126 127 /** 128 * Removes this history browser model as listener for data change and layer change events. 129 */ 130 public void unlinkAsListener() { 131 getHistoryBrowser().getModel().unlinkAsListener(); 132 } 133 134 /* ---------------------------------------------------------------------------------- */ 135 /* interface HistoryDataSetListener */ 136 /* ---------------------------------------------------------------------------------- */ 137 138 @Override 139 public void historyUpdated(HistoryDataSet source, PrimitiveId primitiveId) { 140 if (primitiveId == null || primitiveId.equals(browser.getHistory().getPrimitiveId())) { 141 History history = source.getHistory(browser.getHistory().getPrimitiveId()); 142 if (history != null) { 143 browser.populate(history); 144 } 145 } 146 } 147 148 @Override 149 public void historyDataSetCleared(HistoryDataSet source) { 150 if (isVisible()) { 151 closeAction.run(); 152 } 153 } 154 155 class CloseAction extends AbstractAction { 156 CloseAction() { 157 putValue(NAME, tr("Close")); 158 putValue(SHORT_DESCRIPTION, tr("Close the dialog")); 159 new ImageProvider("ok").getResource().attachImageIcon(this); 160 } 161 162 void run() { 163 getHistoryBrowser().getModel().unlinkAsListener(); 164 HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this); 165 HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this); 166 } 167 168 @Override 169 public void actionPerformed(ActionEvent e) { 170 run(); 171 } 172 } 173 174 class ReloadAction extends AbstractAction { 175 ReloadAction() { 176 putValue(NAME, tr("Reload")); 177 putValue(SHORT_DESCRIPTION, tr("Reload the history from the server")); 178 new ImageProvider("dialogs", "refresh").getResource().attachImageIcon(this); 179 } 180 181 @Override 182 public void actionPerformed(ActionEvent e) { 183 HistoryLoadTask task = new HistoryLoadTask(); 184 task.add(browser.getHistory()); 185 MainApplication.worker.submit(task); 186 } 187 } 188 189 class WindowClosingAdapter extends WindowAdapter { 190 @Override 191 public void windowClosing(WindowEvent e) { 192 if (isVisible()) { 193 closeAction.run(); 194 } 195 } 196 } 197 198 /** 199 * Replies the history browser. 200 * @return the history browser 201 */ 202 public HistoryBrowser getHistoryBrowser() { 203 return browser; 204 } 205}