source: josm/trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java@ 8836

Last change on this file since 8836 was 8836, checked in by Don-vip, 9 years ago

fix Checkstyle issues

  • Property svn:eol-style set to native
File size: 12.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Dimension;
8import java.awt.Point;
9import java.awt.Rectangle;
10import java.awt.event.ActionEvent;
11import java.awt.event.ItemEvent;
12import java.awt.event.ItemListener;
13import java.awt.event.KeyAdapter;
14import java.awt.event.KeyEvent;
15import java.awt.event.MouseEvent;
16import java.util.Observable;
17import java.util.Observer;
18
19import javax.swing.DefaultCellEditor;
20import javax.swing.JCheckBox;
21import javax.swing.JLabel;
22import javax.swing.JPopupMenu;
23import javax.swing.JRadioButton;
24import javax.swing.JTable;
25import javax.swing.SwingConstants;
26import javax.swing.UIManager;
27import javax.swing.event.TableModelEvent;
28import javax.swing.event.TableModelListener;
29import javax.swing.table.TableCellRenderer;
30
31import org.openstreetmap.josm.Main;
32import org.openstreetmap.josm.actions.AbstractInfoAction;
33import org.openstreetmap.josm.data.osm.User;
34import org.openstreetmap.josm.data.osm.history.History;
35import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
36import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
37import org.openstreetmap.josm.io.XmlWriter;
38import org.openstreetmap.josm.tools.ImageProvider;
39import org.openstreetmap.josm.tools.OpenBrowser;
40
41/**
42 * VersionTable shows a list of version in a {@link org.openstreetmap.josm.data.osm.history.History}
43 * of an {@link org.openstreetmap.josm.data.osm.OsmPrimitive}.
44 * @since 1709
45 */
46public class VersionTable extends JTable implements Observer{
47 private VersionTablePopupMenu popupMenu;
48 private final transient HistoryBrowserModel model;
49
50 protected void build() {
51 getTableHeader().setFont(getTableHeader().getFont().deriveFont(9f));
52 setRowSelectionAllowed(false);
53 setShowGrid(false);
54 setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
55 setBackground(UIManager.getColor("Button.background"));
56 setIntercellSpacing(new Dimension(6, 0));
57 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
58 popupMenu = new VersionTablePopupMenu();
59 addMouseListener(new MouseListener());
60 addKeyListener(new KeyAdapter() {
61 @Override
62 public void keyReleased(KeyEvent e) {
63 // navigate history down/up using the corresponding arrow keys.
64 long ref = model.getReferencePointInTime().getVersion();
65 long cur = model.getCurrentPointInTime().getVersion();
66 if (e.getKeyCode() == KeyEvent.VK_DOWN) {
67 History refNext = model.getHistory().from(ref);
68 History curNext = model.getHistory().from(cur);
69 if (refNext.getNumVersions() > 1 && curNext.getNumVersions() > 1) {
70 model.setReferencePointInTime(refNext.sortAscending().get(1));
71 model.setCurrentPointInTime(curNext.sortAscending().get(1));
72 }
73 } else if (e.getKeyCode() == KeyEvent.VK_UP) {
74 History refNext = model.getHistory().until(ref);
75 History curNext = model.getHistory().until(cur);
76 if (refNext.getNumVersions() > 1 && curNext.getNumVersions() > 1) {
77 model.setReferencePointInTime(refNext.sortDescending().get(1));
78 model.setCurrentPointInTime(curNext.sortDescending().get(1));
79 }
80 }
81 }
82 });
83 getModel().addTableModelListener(new TableModelListener() {
84 @Override
85 public void tableChanged(TableModelEvent e) {
86 adjustColumnWidth(VersionTable.this, 0, 0);
87 adjustColumnWidth(VersionTable.this, 1, -8);
88 adjustColumnWidth(VersionTable.this, 2, -8);
89 adjustColumnWidth(VersionTable.this, 3, 0);
90 adjustColumnWidth(VersionTable.this, 4, 0);
91 }
92 });
93 }
94
95 /**
96 * Constructs a new {@code VersionTable}.
97 * @param model model used by the history browser
98 */
99 public VersionTable(HistoryBrowserModel model) {
100 super(model.getVersionTableModel(), new VersionTableColumnModel());
101 model.addObserver(this);
102 build();
103 this.model = model;
104 }
105
106 // some kind of hack to prevent the table from scrolling to the
107 // right when clicking on the cells
108 @Override
109 public void scrollRectToVisible(Rectangle aRect) {
110 super.scrollRectToVisible(new Rectangle(0, aRect.y, aRect.width, aRect.height));
111 }
112
113 protected HistoryBrowserModel.VersionTableModel getVersionTableModel() {
114 return (HistoryBrowserModel.VersionTableModel) getModel();
115 }
116
117 @Override
118 public void update(Observable o, Object arg) {
119 repaint();
120 }
121
122 final class MouseListener extends PopupMenuLauncher {
123 private MouseListener() {
124 super(popupMenu);
125 }
126
127 @Override
128 public void mousePressed(MouseEvent e) {
129 super.mousePressed(e);
130 if (!e.isPopupTrigger() && e.getButton() == MouseEvent.BUTTON1) {
131 int row = rowAtPoint(e.getPoint());
132 int col = columnAtPoint(e.getPoint());
133 if (row >= 0 && (col == VersionTableColumnModel.COL_DATE || col == VersionTableColumnModel.COL_USER)) {
134 model.getVersionTableModel().setCurrentPointInTime(row);
135 model.getVersionTableModel().setReferencePointInTime(Math.max(0, row - 1));
136 }
137 }
138 }
139
140 @Override
141 protected int checkTableSelection(JTable table, Point p) {
142 HistoryBrowserModel.VersionTableModel model = getVersionTableModel();
143 int row = rowAtPoint(p);
144 if (row > -1 && !model.isLatest(row)) {
145 popupMenu.prepare(model.getPrimitive(row));
146 }
147 return row;
148 }
149 }
150
151 static class ChangesetInfoAction extends AbstractInfoAction {
152 private transient HistoryOsmPrimitive primitive;
153
154 /**
155 * Constructs a new {@code ChangesetInfoAction}.
156 */
157 ChangesetInfoAction() {
158 super(true);
159 putValue(NAME, tr("Changeset info"));
160 putValue(SHORT_DESCRIPTION, tr("Launch browser with information about the changeset"));
161 putValue(SMALL_ICON, ImageProvider.get("data/changeset"));
162 }
163
164 @Override
165 protected String createInfoUrl(Object infoObject) {
166 if (infoObject instanceof HistoryOsmPrimitive) {
167 HistoryOsmPrimitive prim = (HistoryOsmPrimitive) infoObject;
168 return Main.getBaseBrowseUrl() + "/changeset/" + prim.getChangesetId();
169 } else {
170 return null;
171 }
172 }
173
174 @Override
175 public void actionPerformed(ActionEvent e) {
176 if (!isEnabled())
177 return;
178 String url = createInfoUrl(primitive);
179 OpenBrowser.displayUrl(url);
180 }
181
182 public void prepare(HistoryOsmPrimitive primitive) {
183 putValue(NAME, tr("Show changeset {0}", primitive.getChangesetId()));
184 this.primitive = primitive;
185 }
186 }
187
188 static class UserInfoAction extends AbstractInfoAction {
189 private transient HistoryOsmPrimitive primitive;
190
191 /**
192 * Constructs a new {@code UserInfoAction}.
193 */
194 UserInfoAction() {
195 super(true);
196 putValue(NAME, tr("User info"));
197 putValue(SHORT_DESCRIPTION, tr("Launch browser with information about the user"));
198 putValue(SMALL_ICON, ImageProvider.get("data/user"));
199 }
200
201 @Override
202 protected String createInfoUrl(Object infoObject) {
203 if (infoObject instanceof HistoryOsmPrimitive) {
204 HistoryOsmPrimitive hp = (HistoryOsmPrimitive) infoObject;
205 return hp.getUser() == null ? null : Main.getBaseUserUrl() + "/" + hp.getUser().getName();
206 } else {
207 return null;
208 }
209 }
210
211 @Override
212 public void actionPerformed(ActionEvent e) {
213 if (!isEnabled())
214 return;
215 String url = createInfoUrl(primitive);
216 OpenBrowser.displayUrl(url);
217 }
218
219 public void prepare(HistoryOsmPrimitive primitive) {
220 final User user = primitive.getUser();
221 putValue(NAME, "<html>" + tr("Show user {0}", user == null ? "?" :
222 XmlWriter.encode(user.getName(), true) + " <font color=gray>(" + user.getId() + ")</font>") + "</html>");
223 this.primitive = primitive;
224 }
225 }
226
227 static class VersionTablePopupMenu extends JPopupMenu {
228
229 private ChangesetInfoAction changesetInfoAction;
230 private UserInfoAction userInfoAction;
231
232 /**
233 * Constructs a new {@code VersionTablePopupMenu}.
234 */
235 VersionTablePopupMenu() {
236 super();
237 build();
238 }
239
240 protected void build() {
241 changesetInfoAction = new ChangesetInfoAction();
242 add(changesetInfoAction);
243 userInfoAction = new UserInfoAction();
244 add(userInfoAction);
245 }
246
247 public void prepare(HistoryOsmPrimitive primitive) {
248 changesetInfoAction.prepare(primitive);
249 userInfoAction.prepare(primitive);
250 invalidate();
251 }
252 }
253
254 public static class RadioButtonRenderer extends JRadioButton implements TableCellRenderer {
255
256 @Override
257 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
258 int row, int column) {
259 setSelected(value != null && (Boolean) value);
260 setHorizontalAlignment(SwingConstants.CENTER);
261 return this;
262 }
263 }
264
265 public static class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
266
267 private JRadioButton btn;
268
269 /**
270 * Constructs a new {@code RadioButtonEditor}.
271 */
272 public RadioButtonEditor() {
273 super(new JCheckBox());
274 btn = new JRadioButton();
275 btn.setHorizontalAlignment(SwingConstants.CENTER);
276 }
277
278 @Override
279 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
280 if (value == null) return null;
281 boolean val = (Boolean) value;
282 btn.setSelected(val);
283 btn.addItemListener(this);
284 return btn;
285 }
286
287 @Override
288 public Object getCellEditorValue() {
289 btn.removeItemListener(this);
290 return btn.isSelected();
291 }
292
293 @Override
294 public void itemStateChanged(ItemEvent e) {
295 fireEditingStopped();
296 }
297 }
298
299 public static class AlignedRenderer extends JLabel implements TableCellRenderer {
300
301 /**
302 * Constructs a new {@code AlignedRenderer}.
303 * @param hAlignment Horizontal alignement. One of the following constants defined in SwingConstants:
304 * LEFT, CENTER (the default for image-only labels), RIGHT, LEADING (the default for text-only labels) or TRAILING
305 */
306 public AlignedRenderer(int hAlignment) {
307 setHorizontalAlignment(hAlignment);
308 }
309
310 @Override
311 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
312 int row, int column) {
313 String v = value.toString();
314 setText(v);
315 return this;
316 }
317 }
318
319 private static void adjustColumnWidth(JTable tbl, int col, int cellInset) {
320 int maxwidth = 0;
321
322 for (int row = 0; row < tbl.getRowCount(); row++) {
323 TableCellRenderer tcr = tbl.getCellRenderer(row, col);
324 Object val = tbl.getValueAt(row, col);
325 Component comp = tcr.getTableCellRendererComponent(tbl, val, false, false, row, col);
326 maxwidth = Math.max(comp.getPreferredSize().width + cellInset, maxwidth);
327 }
328 TableCellRenderer tcr = tbl.getTableHeader().getDefaultRenderer();
329 Object val = tbl.getColumnModel().getColumn(col).getHeaderValue();
330 Component comp = tcr.getTableCellRendererComponent(tbl, val, false, false, -1, col);
331 maxwidth = Math.max(comp.getPreferredSize().width + Main.pref.getInteger("table.header-inset", 0), maxwidth);
332
333 int spacing = tbl.getIntercellSpacing().width;
334 tbl.getColumnModel().getColumn(col).setPreferredWidth(maxwidth + spacing);
335 }
336}
Note: See TracBrowser for help on using the repository browser.