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