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.JOptionPane;
019import javax.swing.JPanel;
020import javax.swing.KeyStroke;
021
022import org.openstreetmap.josm.Main;
023import org.openstreetmap.josm.data.osm.PrimitiveId;
024import org.openstreetmap.josm.data.osm.history.History;
025import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
026import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
027import org.openstreetmap.josm.gui.SideButton;
028import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
029import org.openstreetmap.josm.gui.help.HelpUtil;
030import org.openstreetmap.josm.tools.ImageProvider;
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 *
036 */
037public class HistoryBrowserDialog extends JDialog implements HistoryDataSetListener{
038
039    /** the embedded browser */
040    private HistoryBrowser browser;
041    private CloseAction closeAction;
042
043    /**
044     * displays the title for this dialog
045     *
046     * @param h the current history
047     */
048    protected void renderTitle(History h) {
049        String title = "";
050        switch(h.getEarliest().getType()) {
051        case NODE:  title = marktr("History for node {0}"); break;
052        case WAY: title = marktr("History for way {0}"); break;
053        case RELATION:  title = marktr("History for relation {0}"); break;
054        }
055        setTitle(tr(
056                title,
057                Long.toString(h.getId())
058        ));
059    }
060
061    /**
062     * builds the GUI
063     *
064     */
065    protected void build() {
066        setLayout(new BorderLayout());
067        browser = new HistoryBrowser();
068        add(browser, BorderLayout.CENTER);
069
070        JPanel pnl = new JPanel();
071        pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
072
073        SideButton btn = new SideButton(new ReloadAction());
074        btn.setName("btn.reload");
075        pnl.add(btn);
076
077        btn = new SideButton(closeAction = new CloseAction());
078        final String closeHistoryBrowserDialogKey = "CloseHistoryBrowserDialog";
079        KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
080        getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(escapeKey, closeHistoryBrowserDialogKey);
081        getRootPane().getActionMap().put(closeHistoryBrowserDialogKey, closeAction);
082        btn.setName("btn.close");
083        pnl.add(btn);
084
085        btn = new SideButton(new ContextSensitiveHelpAction(ht("/Dialog/HistoryBrowser")));
086        btn.setName("btn.help");
087        pnl.add(btn);
088        add(pnl, BorderLayout.SOUTH);
089
090        HelpUtil.setHelpContext(getRootPane(), ht("/Dialog/HistoryBrowser"));
091
092        setSize(800, 500);
093    }
094
095    /**
096     * constructor
097     *
098     * @param history  the history to be displayed
099     */
100    public HistoryBrowserDialog(History history) {
101        super(JOptionPane.getFrameForComponent(Main.parent), false);
102        build();
103        setHistory(history);
104        renderTitle(history);
105        HistoryDataSet.getInstance().addHistoryDataSetListener(this);
106        addWindowListener(new WindowClosingAdapter());
107    }
108
109    /**
110     * sets the current history
111     * @param history
112     */
113    protected void setHistory(History history) {
114        browser.populate(history);
115    }
116
117    public void unlinkAsListener() {
118        getHistoryBrowser().getModel().unlinkAsListener();
119    }
120
121    /* ---------------------------------------------------------------------------------- */
122    /* interface HistoryDataSetListener                                                   */
123    /* ---------------------------------------------------------------------------------- */
124    @Override
125    public void historyUpdated(HistoryDataSet source, PrimitiveId primitiveId) {
126        if (primitiveId == null || primitiveId.equals(browser.getHistory().getPrimitiveId())) {
127            browser.populate(source.getHistory(browser.getHistory().getPrimitiveId()));
128        }
129    }
130
131    @Override
132    public void historyDataSetCleared(HistoryDataSet source) {
133        closeAction.run();
134    }
135
136
137    class CloseAction extends AbstractAction {
138        public CloseAction() {
139            putValue(NAME, tr("Close"));
140            putValue(SHORT_DESCRIPTION, tr("Close the dialog"));
141            putValue(SMALL_ICON, ImageProvider.get("ok"));
142        }
143
144        public void run() {
145            getHistoryBrowser().getModel().unlinkAsListener();
146            HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
147            HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this);
148        }
149
150        @Override
151        public void actionPerformed(ActionEvent e) {
152            run();
153        }
154    }
155
156    class ReloadAction extends AbstractAction {
157        public ReloadAction() {
158            putValue(NAME, tr("Reload"));
159            putValue(SHORT_DESCRIPTION, tr("Reload the history from the server"));
160            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
161        }
162
163        @Override
164        public void actionPerformed(ActionEvent e) {
165            HistoryLoadTask task = new HistoryLoadTask();
166            task.add(browser.getHistory());
167            Main.worker.submit(task);
168        }
169    }
170
171    class WindowClosingAdapter extends WindowAdapter {
172        @Override
173        public void windowClosing(WindowEvent e) {
174            closeAction.run();
175        }
176    }
177
178    public HistoryBrowser getHistoryBrowser() {
179        return browser;
180    }
181}