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