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

Last change on this file since 2239 was 2239, checked in by Gubaer, 15 years ago

see #3626: Show history for any object in history dialog (partially fixed)
fixed #3515: The history dialog is confusing unless you know how it works

  • Property svn:eol-style set to native
File size: 12.4 KB
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.BorderLayout;
7import java.awt.Component;
8import java.awt.GridLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.KeyEvent;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13import java.util.ArrayList;
14import java.util.Collection;
15import java.util.Collections;
16import java.util.List;
17
18import javax.swing.AbstractAction;
19import javax.swing.Action;
20import javax.swing.DefaultListSelectionModel;
21import javax.swing.JComponent;
22import javax.swing.JLabel;
23import javax.swing.JPanel;
24import javax.swing.JScrollPane;
25import javax.swing.JTable;
26import javax.swing.ListSelectionModel;
27import javax.swing.event.ListSelectionEvent;
28import javax.swing.event.ListSelectionListener;
29import javax.swing.table.DefaultTableCellRenderer;
30import javax.swing.table.DefaultTableColumnModel;
31import javax.swing.table.DefaultTableModel;
32import javax.swing.table.TableCellRenderer;
33import javax.swing.table.TableColumn;
34
35import org.openstreetmap.josm.Main;
36import org.openstreetmap.josm.data.SelectionChangedListener;
37import org.openstreetmap.josm.data.osm.DataSet;
38import org.openstreetmap.josm.data.osm.OsmPrimitive;
39import org.openstreetmap.josm.data.osm.history.History;
40import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
41import org.openstreetmap.josm.data.osm.history.HistoryDataSetListener;
42import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
43import org.openstreetmap.josm.gui.SideButton;
44import org.openstreetmap.josm.gui.history.HistoryBrowserDialog;
45import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
46import org.openstreetmap.josm.gui.history.HistoryLoadTask;
47import org.openstreetmap.josm.tools.ImageProvider;
48import org.openstreetmap.josm.tools.Shortcut;
49
50/**
51 * HistoryDialog displays a list of the currently selected primitives and provides
52 * two actions for (1) (re)loading the history of the selected primitives and (2)
53 * for launching a history browser for each selected primitive.
54 *
55 */
56public class HistoryDialog extends ToggleDialog implements HistoryDataSetListener {
57
58 /** the table model */
59 protected HistoryItemTableModel model;
60 /** the table with the history items */
61 protected JTable historyTable;
62
63 protected ShowHistoryAction showHistoryAction;
64 protected ReloadAction reloadAction;
65
66 /**
67 * builds the row with the command buttons
68 *
69 * @return the rows with the command buttons
70 */
71 protected JPanel buildButtonRow() {
72 JPanel buttons = new JPanel(new GridLayout(1,2));
73
74 SideButton btn = new SideButton(reloadAction = new ReloadAction());
75 btn.setName("btn.reload");
76 buttons.add(btn);
77
78 btn = new SideButton(showHistoryAction = new ShowHistoryAction());
79 btn.setName("btn.showhistory");
80 buttons.add(btn);
81
82 return buttons;
83 }
84
85 /**
86 * builds the GUI
87 */
88 protected void build() {
89 DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
90 historyTable = new JTable(
91 model = new HistoryItemTableModel(selectionModel),
92 new HistoryTableColumnModel(),
93 selectionModel
94 );
95 historyTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
96 historyTable.setName("table.historyitems");
97 final TableCellRenderer oldRenderer = historyTable.getTableHeader().getDefaultRenderer();
98 historyTable.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer(){
99 @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
100 JComponent c = (JComponent)oldRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
101 if (!value.equals(""))
102 return c;
103 JLabel l = new JLabel(ImageProvider.get("misc","showhide"));
104 l.setForeground(c.getForeground());
105 l.setBackground(c.getBackground());
106 l.setFont(c.getFont());
107 l.setBorder(c.getBorder());
108 l.setOpaque(true);
109 return l;
110 }
111 });
112
113 JScrollPane pane = new JScrollPane(historyTable);
114 pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
115 pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
116 historyTable.setTableHeader(null);
117 pane.setColumnHeaderView(null);
118 add(pane, BorderLayout.CENTER);
119
120 add(buildButtonRow(), BorderLayout.SOUTH);
121
122 // wire actions
123 //
124 historyTable.getSelectionModel().addListSelectionListener(showHistoryAction);
125 historyTable.getSelectionModel().addListSelectionListener(reloadAction);
126 }
127
128 public HistoryDialog() {
129 super(tr("History"), "history", tr("Display the history of all selected items."),
130 Shortcut.registerShortcut("subwindow:history", tr("Toggle: {0}", tr("History")), KeyEvent.VK_H,
131 Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150);
132 build();
133 DataSet.selListeners.add(model);
134 HistoryDataSet.getInstance().addHistoryDataSetListener(this);
135 }
136
137 public void historyUpdated(HistoryDataSet source, long primitiveId) {
138 model.refresh();
139 }
140
141 /**
142 * shows the {@see HistoryBrowserDialog} for a given {@see History}
143 *
144 * @param h the history. Must not be null.
145 * @exception IllegalArgumentException thrown, if h is null
146 */
147 protected void showHistory(History h) throws IllegalArgumentException {
148 if (h == null)
149 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null.", "h"));
150 if (HistoryBrowserDialogManager.getInstance().existsDialog(h.getId())) {
151 HistoryBrowserDialogManager.getInstance().show(h.getId());
152 } else {
153 HistoryBrowserDialog dialog = new HistoryBrowserDialog(h);
154 HistoryBrowserDialogManager.getInstance().show(h.getId(), dialog);
155 }
156 }
157
158
159 /**
160 * The table model with the history items
161 *
162 */
163 class HistoryItemTableModel extends DefaultTableModel implements SelectionChangedListener{
164 private ArrayList<OsmPrimitive> data;
165 private DefaultListSelectionModel selectionModel;
166
167 public HistoryItemTableModel(DefaultListSelectionModel selectionModel) {
168 data = new ArrayList<OsmPrimitive>();
169 this.selectionModel = selectionModel;
170 }
171
172 @Override
173 public int getRowCount() {
174 if (data == null)
175 return 0;
176 return data.size();
177 }
178
179 @Override
180 public Object getValueAt(int row, int column) {
181 return data.get(row);
182 }
183
184 @Override
185 public boolean isCellEditable(int row, int column) {
186 return false;
187 }
188
189 protected List<OsmPrimitive> getSelectedPrimitives() {
190 ArrayList<OsmPrimitive> ret = new ArrayList<OsmPrimitive>();
191 for (int i=0; i< data.size(); i++) {
192 if (selectionModel.isSelectedIndex(i)) {
193 ret.add(data.get(i));
194 }
195 }
196 return ret;
197 }
198
199 protected void selectPrimitives(Collection<OsmPrimitive> primitives) {
200 for (OsmPrimitive p: primitives) {
201 int idx = data.indexOf(p);
202 if (idx < 0) {
203 continue;
204 }
205 selectionModel.addSelectionInterval(idx, idx);
206 }
207 }
208
209 public void refresh() {
210 List<OsmPrimitive> selectedPrimitives = getSelectedPrimitives();
211 data.clear();
212 if (Main.main.getCurrentDataSet() == null)
213 return;
214 for (OsmPrimitive primitive: Main.main.getCurrentDataSet().getSelected()) {
215 if (primitive.getId() == 0) {
216 continue;
217 }
218 data.add(primitive);
219 }
220 fireTableDataChanged();
221 selectPrimitives(selectedPrimitives);
222 }
223
224 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
225 refresh();
226 }
227
228 public List<OsmPrimitive> getPrimitives(int [] rows) {
229 if (rows == null || rows.length == 0) return Collections.emptyList();
230 ArrayList<OsmPrimitive> ret = new ArrayList<OsmPrimitive>(rows.length);
231 for (int row: rows) {
232 ret.add(data.get(row));
233 }
234 return ret;
235 }
236 }
237
238 /**
239 * The column model
240 */
241 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 public ReloadAction() {
263 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs","refresh"));
264 putValue(Action.NAME, tr("Reload"));
265 putValue(Action.SHORT_DESCRIPTION, tr("Reload all currently selected objects and refresh the list."));
266 updateEnabledState();
267 }
268
269 public void actionPerformed(ActionEvent e) {
270 int [] rows = historyTable.getSelectedRows();
271 if (rows == null || rows.length == 0) return;
272
273 List<OsmPrimitive> selectedItems = model.getPrimitives(rows);
274 HistoryLoadTask task = new HistoryLoadTask();
275 task.add(selectedItems);
276 Main.worker.execute(task);
277 }
278
279 protected void updateEnabledState() {
280 setEnabled(historyTable.getSelectedRowCount() > 0);
281 }
282
283 public void valueChanged(ListSelectionEvent e) {
284 updateEnabledState();
285 }
286 }
287
288 /**
289 * The action for showing history information of the current history item.
290 */
291 class ShowHistoryAction extends AbstractAction implements ListSelectionListener {
292 public ShowHistoryAction() {
293 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs","history"));
294 putValue(Action.NAME, tr("Show"));
295 putValue(Action.SHORT_DESCRIPTION, tr("Display the history of the selected objects."));
296 updateEnabledState();
297 }
298
299 protected List<OsmPrimitive> filterPrimitivesWithUnloadedHistory(Collection<OsmPrimitive> primitives) {
300 ArrayList<OsmPrimitive> ret = new ArrayList<OsmPrimitive>(primitives.size());
301 for (OsmPrimitive p: primitives) {
302 if (HistoryDataSet.getInstance().getHistory(p.getId()) == null) {
303 ret.add(p);
304 }
305 }
306 return ret;
307 }
308
309 public void actionPerformed(ActionEvent e) {
310 int [] rows = historyTable.getSelectedRows();
311 if (rows == null || rows.length == 0) return;
312
313 final List<OsmPrimitive> selectedItems = model.getPrimitives(rows);
314 List<OsmPrimitive> toLoad = filterPrimitivesWithUnloadedHistory(selectedItems);
315 if (!toLoad.isEmpty()) {
316 HistoryLoadTask task = new HistoryLoadTask();
317 task.add(selectedItems);
318 Main.worker.submit(task);
319 }
320
321 Runnable r = new Runnable() {
322 public void run() {
323 for (OsmPrimitive p : selectedItems) {
324 History h = HistoryDataSet.getInstance().getHistory(p.getId());
325 if (h == null) {
326 continue;
327 }
328 showHistory(h);
329 }
330 }
331 };
332 Main.worker.submit(r);
333 }
334
335 protected void updateEnabledState() {
336 setEnabled(historyTable.getSelectedRowCount() > 0);
337 }
338
339 public void valueChanged(ListSelectionEvent e) {
340 updateEnabledState();
341 }
342 }
343}
Note: See TracBrowser for help on using the repository browser.