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

Last change on this file since 2871 was 2871, checked in by jttt, 14 years ago

Partially fix situation after last layer removal - most objects still stay in memory but at least there are less references and forgotten listeners

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