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("/Dialog/HistoryBrowser"))); 100 btn.setName("btn.help"); 101 pnl.add(btn); 102 add(pnl, BorderLayout.SOUTH); 103 104 HelpUtil.setHelpContext(getRootPane(), ht("/Dialog/HistoryBrowser")); 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 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 156 class CloseAction extends AbstractAction { 157 public CloseAction() { 158 putValue(NAME, tr("Close")); 159 putValue(SHORT_DESCRIPTION, tr("Close the dialog")); 160 putValue(SMALL_ICON, ImageProvider.get("ok")); 161 } 162 163 public void run() { 164 getHistoryBrowser().getModel().unlinkAsListener(); 165 HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this); 166 HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this); 167 } 168 169 @Override 170 public void actionPerformed(ActionEvent e) { 171 run(); 172 } 173 } 174 175 class ReloadAction extends AbstractAction { 176 public ReloadAction() { 177 putValue(NAME, tr("Reload")); 178 putValue(SHORT_DESCRIPTION, tr("Reload the history from the server")); 179 putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh")); 180 } 181 182 @Override 183 public void actionPerformed(ActionEvent e) { 184 HistoryLoadTask task = new HistoryLoadTask(); 185 task.add(browser.getHistory()); 186 Main.worker.submit(task); 187 } 188 } 189 190 class WindowClosingAdapter extends WindowAdapter { 191 @Override 192 public void windowClosing(WindowEvent e) { 193 closeAction.run(); 194 } 195 } 196 197 /** 198 * Replies the history browser. 199 * @return the history browser 200 */ 201 public HistoryBrowser getHistoryBrowser() { 202 return browser; 203 } 204}