001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.history;
003    
004    import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005    import static org.openstreetmap.josm.tools.I18n.marktr;
006    import static org.openstreetmap.josm.tools.I18n.tr;
007    
008    import java.awt.BorderLayout;
009    import java.awt.FlowLayout;
010    import java.awt.event.ActionEvent;
011    import java.awt.event.KeyEvent;
012    import java.awt.event.WindowAdapter;
013    import java.awt.event.WindowEvent;
014    
015    import javax.swing.AbstractAction;
016    import javax.swing.JComponent;
017    import javax.swing.JDialog;
018    import javax.swing.JOptionPane;
019    import javax.swing.JPanel;
020    import javax.swing.KeyStroke;
021    
022    import org.openstreetmap.josm.Main;
023    import org.openstreetmap.josm.data.osm.PrimitiveId;
024    import org.openstreetmap.josm.data.osm.history.History;
025    import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
026    import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
027    import org.openstreetmap.josm.gui.SideButton;
028    import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
029    import org.openstreetmap.josm.gui.help.HelpUtil;
030    import 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 OsmPrimitive}.
035     *
036     */
037    public 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        public void historyUpdated(HistoryDataSet source, PrimitiveId primitiveId) {
125            if (primitiveId == null || primitiveId.equals(browser.getHistory().getPrimitiveId())) {
126                browser.populate(source.getHistory(browser.getHistory().getPrimitiveId()));
127            }
128        }
129    
130        public void historyDataSetCleared(HistoryDataSet source) {
131            closeAction.run();
132        }
133    
134    
135        class CloseAction extends AbstractAction {
136            public CloseAction() {
137                putValue(NAME, tr("Close"));
138                putValue(SHORT_DESCRIPTION, tr("Close the dialog"));
139                putValue(SMALL_ICON, ImageProvider.get("ok"));
140            }
141    
142            public void run() {
143                getHistoryBrowser().getModel().unlinkAsListener();
144                HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
145                HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this);
146            }
147    
148            public void actionPerformed(ActionEvent e) {
149                run();
150            }
151        }
152    
153        class ReloadAction extends AbstractAction {
154            public ReloadAction() {
155                putValue(NAME, tr("Reload"));
156                putValue(SHORT_DESCRIPTION, tr("Reload the history from the server"));
157                putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
158            }
159    
160            public void actionPerformed(ActionEvent e) {
161                HistoryLoadTask task = new HistoryLoadTask();
162                task.add(browser.getHistory());
163                Main.worker.submit(task);
164            }
165        }
166    
167        class WindowClosingAdapter extends WindowAdapter {
168            @Override
169            public void windowClosing(WindowEvent e) {
170                closeAction.run();
171            }
172        }
173    
174        public HistoryBrowser getHistoryBrowser() {
175            return browser;
176        }
177    }