source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java @ 5241

Revision 5200, 11.8 KB checked in by akks, 5 weeks ago (diff)

see #7626, fix #7463: keys Ctrl-Shift-Up/Down, Enter, Spacebar work better in toggle dialogs
Enter and Spacebar = useful actions for list items (select, toggle, etc.)

  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.awt.event.MouseAdapter;
10import java.awt.event.MouseEvent;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.List;
16
17import javax.swing.AbstractAction;
18import javax.swing.Action;
19import javax.swing.DefaultListSelectionModel;
20import javax.swing.JComponent;
21import javax.swing.JLabel;
22import javax.swing.JTable;
23import javax.swing.ListSelectionModel;
24import javax.swing.event.ListSelectionEvent;
25import javax.swing.event.ListSelectionListener;
26import javax.swing.table.DefaultTableCellRenderer;
27import javax.swing.table.DefaultTableColumnModel;
28import javax.swing.table.DefaultTableModel;
29import javax.swing.table.TableCellRenderer;
30import javax.swing.table.TableColumn;
31
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.data.SelectionChangedListener;
34import org.openstreetmap.josm.data.osm.DataSet;
35import org.openstreetmap.josm.data.osm.OsmPrimitive;
36import org.openstreetmap.josm.data.osm.PrimitiveId;
37import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
38import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
39import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
40import org.openstreetmap.josm.gui.SideButton;
41import org.openstreetmap.josm.gui.help.HelpUtil;
42import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
43import org.openstreetmap.josm.gui.history.HistoryLoadTask;
44import org.openstreetmap.josm.tools.ImageProvider;
45import org.openstreetmap.josm.tools.InputMapUtils;
46import org.openstreetmap.josm.tools.Shortcut;
47
48/**
49 * HistoryDialog displays a list of the currently selected primitives and provides
50 * two actions for (1) (re)loading the history of the selected primitives and (2)
51 * for launching a history browser for each selected primitive.
52 *
53 */
54public class HistoryDialog extends ToggleDialog implements HistoryDataSetListener {
55
56    /** the table model */
57    protected HistoryItemTableModel model;
58    /** the table with the history items */
59    protected JTable historyTable;
60
61    protected ShowHistoryAction showHistoryAction;
62    protected ReloadAction reloadAction;
63
64    public HistoryDialog() {
65        super(tr("History"), "history", tr("Display the history of all selected items."),
66                Shortcut.registerShortcut("subwindow:history", tr("Toggle: {0}", tr("History")), KeyEvent.VK_H,
67                        Shortcut.ALT_SHIFT), 150);
68        build();
69        HelpUtil.setHelpContext(this, HelpUtil.ht("/Dialog/History"));
70    }
71
72    /**
73     * builds the GUI
74     */
75    protected void build() {
76        DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
77        historyTable = new JTable(
78                model = new HistoryItemTableModel(selectionModel),
79                new HistoryTableColumnModel(),
80                selectionModel
81        );
82        historyTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
83        final TableCellRenderer oldRenderer = historyTable.getTableHeader().getDefaultRenderer();
84        historyTable.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer(){
85            @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
86                JComponent c = (JComponent)oldRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
87                if (!"".equals(value))
88                    return c;
89                JLabel l = new JLabel(ImageProvider.get("misc","showhide"));
90                l.setForeground(c.getForeground());
91                l.setBackground(c.getBackground());
92                l.setFont(c.getFont());
93                l.setBorder(c.getBorder());
94                l.setOpaque(true);
95                return l;
96            }
97        });
98        historyTable.addMouseListener(new ShowHistoryMouseAdapter());
99        historyTable.setTableHeader(null);
100
101        createLayout(historyTable, true, Arrays.asList(new SideButton[] {
102            new SideButton(reloadAction = new ReloadAction()),
103            new SideButton(showHistoryAction = new ShowHistoryAction())
104        }));
105
106        // wire actions
107        //
108        historyTable.getSelectionModel().addListSelectionListener(showHistoryAction);
109        historyTable.getSelectionModel().addListSelectionListener(reloadAction);
110       
111        // Show history dialog on Enter/Spacebar
112        InputMapUtils.addEnterAction(historyTable, showHistoryAction);
113        InputMapUtils.addSpacebarAction(historyTable, showHistoryAction);
114    }
115
116    @Override
117    public void showNotify() {
118        HistoryDataSet.getInstance().addHistoryDataSetListener(this);
119        DataSet.addSelectionListener(model);
120        if (Main.main.getCurrentDataSet() == null) {
121            model.selectionChanged(null);
122        } else {
123            model.selectionChanged(Main.main.getCurrentDataSet().getSelected());
124        }
125    }
126
127    @Override
128    public void hideNotify() {
129        HistoryDataSet.getInstance().removeHistoryDataSetListener(this);
130        DataSet.removeSelectionListener(model);
131    }
132
133    /* ----------------------------------------------------------------------------- */
134    /* interface HistoryDataSetListener                                              */
135    /* ----------------------------------------------------------------------------- */
136    public void historyUpdated(HistoryDataSet source, PrimitiveId primitiveId) {
137        model.refresh();
138    }
139
140    public void historyDataSetCleared(HistoryDataSet source) {
141        model.refresh();
142    }
143
144    /**
145     * The table model with the history items
146     *
147     */
148    static class HistoryItemTableModel extends DefaultTableModel implements SelectionChangedListener{
149        private ArrayList<OsmPrimitive> data;
150        private DefaultListSelectionModel selectionModel;
151
152        public HistoryItemTableModel(DefaultListSelectionModel selectionModel) {
153            data = new ArrayList<OsmPrimitive>();
154            this.selectionModel = selectionModel;
155        }
156
157        @Override
158        public int getRowCount() {
159            if (data == null)
160                return 0;
161            return data.size();
162        }
163
164        @Override
165        public Object getValueAt(int row, int column) {
166            return data.get(row);
167        }
168
169        @Override
170        public boolean isCellEditable(int row, int column) {
171            return false;
172        }
173
174        protected List<OsmPrimitive> getSelectedPrimitives() {
175            ArrayList<OsmPrimitive> ret = new ArrayList<OsmPrimitive>();
176            for (int i=0; i< data.size(); i++) {
177                if (selectionModel.isSelectedIndex(i)) {
178                    ret.add(data.get(i));
179                }
180            }
181            return ret;
182        }
183
184        protected void selectPrimitives(Collection<OsmPrimitive> primitives) {
185            for (OsmPrimitive p: primitives) {
186                int idx = data.indexOf(p);
187                if (idx < 0) {
188                    continue;
189                }
190                selectionModel.addSelectionInterval(idx, idx);
191            }
192        }
193
194        public void refresh() {
195            List<OsmPrimitive> selectedPrimitives = getSelectedPrimitives();
196            data.clear();
197            if (Main.main.getCurrentDataSet() == null)
198                return;
199            for (OsmPrimitive primitive: Main.main.getCurrentDataSet().getSelected()) {
200                if (primitive.isNew()) {
201                    continue;
202                }
203                data.add(primitive);
204            }
205            fireTableDataChanged();
206            selectPrimitives(selectedPrimitives);
207        }
208
209        public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
210            data.clear();
211            selectionModel.clearSelection();
212            if (newSelection != null && !newSelection.isEmpty()) {
213                for (OsmPrimitive primitive: newSelection) {
214                    if (primitive.isNew()) {
215                        continue;
216                    }
217                    data.add(primitive);
218                }
219            }
220            fireTableDataChanged();
221            selectionModel.addSelectionInterval(0, data.size()-1);
222        }
223
224        public List<OsmPrimitive> getPrimitives(int [] rows) {
225            if (rows == null || rows.length == 0) return Collections.emptyList();
226            ArrayList<OsmPrimitive> ret = new ArrayList<OsmPrimitive>(rows.length);
227            for (int row: rows) {
228                ret.add(data.get(row));
229            }
230            return ret;
231        }
232
233        public OsmPrimitive getPrimitive(int row) {
234            return data.get(row);
235        }
236    }
237
238    /**
239     * The column model
240     */
241    static class HistoryTableColumnModel extends DefaultTableColumnModel {
242        protected void createColumns() {
243            TableColumn col = null;
244            OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
245            // column 0 - History item
246            col = new TableColumn(0);
247            col.setHeaderValue(tr("Object with history"));
248            col.setCellRenderer(renderer);
249            addColumn(col);
250        }
251
252        public HistoryTableColumnModel() {
253            createColumns();
254        }
255    }
256
257    /**
258     * The action for reloading history information of the currently selected primitives.
259     *
260     */
261    class ReloadAction extends AbstractAction implements ListSelectionListener {
262
263        public ReloadAction() {
264            putValue(Action.SMALL_ICON, ImageProvider.get("dialogs","refresh"));
265            putValue(Action.NAME, tr("Reload"));
266            putValue(Action.SHORT_DESCRIPTION, tr("Reload all currently selected objects and refresh the list."));
267            updateEnabledState();
268        }
269
270        public void actionPerformed(ActionEvent e) {
271            int [] rows = historyTable.getSelectedRows();
272            if (rows == null || rows.length == 0) return;
273
274            List<OsmPrimitive> selectedItems = model.getPrimitives(rows);
275            HistoryLoadTask task = new HistoryLoadTask();
276            task.add(selectedItems);
277            Main.worker.execute(task);
278        }
279
280        protected void updateEnabledState() {
281            setEnabled(historyTable.getSelectedRowCount() > 0);
282        }
283
284        public void valueChanged(ListSelectionEvent e) {
285            updateEnabledState();
286        }
287    }
288
289    class ShowHistoryMouseAdapter extends MouseAdapter {
290        @Override
291        public void mouseClicked(MouseEvent e) {
292            if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
293                int row = historyTable.rowAtPoint(e.getPoint());
294                HistoryBrowserDialogManager.getInstance().showHistory(Collections.singletonList(model.getPrimitive(row)));
295            }
296        }
297    }
298
299    /**
300     * The action for showing history information of the current history item.
301     */
302    class ShowHistoryAction extends AbstractAction implements ListSelectionListener {
303        public ShowHistoryAction() {
304            putValue(Action.SMALL_ICON, ImageProvider.get("dialogs","history"));
305            putValue(Action.NAME, tr("Show"));
306            putValue(Action.SHORT_DESCRIPTION, tr("Display the history of the selected objects."));
307            updateEnabledState();
308        }
309
310        public void actionPerformed(ActionEvent e) {
311            int [] rows = historyTable.getSelectedRows();
312            if (rows == null || rows.length == 0) return;
313            HistoryBrowserDialogManager.getInstance().showHistory(model.getPrimitives(rows));
314        }
315
316        protected void updateEnabledState() {
317            setEnabled(historyTable.getSelectedRowCount() > 0);
318        }
319
320        public void valueChanged(ListSelectionEvent e) {
321            updateEnabledState();
322        }
323    }
324}
Note: See TracBrowser for help on using the repository browser.