source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTable.java@ 10070

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

refactor duplicated code

  • Property svn:eol-style set to native
File size: 9.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Dimension;
7import java.awt.GraphicsEnvironment;
8import java.awt.event.ActionEvent;
9import java.util.ArrayList;
10import java.util.Arrays;
11import java.util.Collection;
12import java.util.List;
13
14import javax.swing.AbstractAction;
15import javax.swing.DropMode;
16import javax.swing.JPopupMenu;
17import javax.swing.JTable;
18import javax.swing.ListSelectionModel;
19import javax.swing.SwingUtilities;
20import javax.swing.event.ListSelectionEvent;
21import javax.swing.event.ListSelectionListener;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.actions.AutoScaleAction;
25import org.openstreetmap.josm.actions.ZoomToAction;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.data.osm.Relation;
28import org.openstreetmap.josm.data.osm.RelationMember;
29import org.openstreetmap.josm.data.osm.Way;
30import org.openstreetmap.josm.gui.MapView;
31import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
32import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType;
33import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType.Direction;
34import org.openstreetmap.josm.gui.layer.Layer;
35import org.openstreetmap.josm.gui.layer.OsmDataLayer;
36import org.openstreetmap.josm.gui.util.HighlightHelper;
37import org.openstreetmap.josm.gui.widgets.OsmPrimitivesTable;
38
39public class MemberTable extends OsmPrimitivesTable implements IMemberModelListener {
40
41 /** the additional actions in popup menu */
42 private ZoomToGapAction zoomToGap;
43 private final transient HighlightHelper highlightHelper = new HighlightHelper();
44 private boolean highlightEnabled;
45
46 /**
47 * constructor for relation member table
48 *
49 * @param layer the data layer of the relation. Must not be null
50 * @param relation the relation. Can be null
51 * @param model the table model
52 */
53 public MemberTable(OsmDataLayer layer, Relation relation, MemberTableModel model) {
54 super(model, new MemberTableColumnModel(layer.data, relation), model.getSelectionModel());
55 setLayer(layer);
56 model.addMemberModelListener(this);
57
58 MemberRoleCellEditor ce = (MemberRoleCellEditor) getColumnModel().getColumn(0).getCellEditor();
59 setRowHeight(ce.getEditor().getPreferredSize().height);
60 setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
61 setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
62 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
63
64 installCustomNavigation(0);
65 initHighlighting();
66
67 if (!GraphicsEnvironment.isHeadless()) {
68 setTransferHandler(new MemberTransferHandler());
69 setFillsViewportHeight(true); // allow drop on empty table
70 setDragEnabled(true);
71 setDropMode(DropMode.INSERT_ROWS);
72 }
73 }
74
75 @Override
76 protected ZoomToAction buildZoomToAction() {
77 return new ZoomToAction(this);
78 }
79
80 @Override
81 protected JPopupMenu buildPopupMenu() {
82 JPopupMenu menu = super.buildPopupMenu();
83 zoomToGap = new ZoomToGapAction();
84 MapView.addLayerChangeListener(zoomToGap);
85 getSelectionModel().addListSelectionListener(zoomToGap);
86 menu.add(zoomToGap);
87 menu.addSeparator();
88 menu.add(new SelectPreviousGapAction());
89 menu.add(new SelectNextGapAction());
90 return menu;
91 }
92
93 @Override
94 public Dimension getPreferredSize() {
95 return getPreferredFullWidthSize();
96 }
97
98 @Override
99 public void makeMemberVisible(int index) {
100 scrollRectToVisible(getCellRect(index, 0, true));
101 }
102
103 private transient ListSelectionListener highlighterListener = new ListSelectionListener() {
104 @Override
105 public void valueChanged(ListSelectionEvent lse) {
106 if (Main.isDisplayingMapView()) {
107 Collection<RelationMember> sel = getMemberTableModel().getSelectedMembers();
108 final List<OsmPrimitive> toHighlight = new ArrayList<>();
109 for (RelationMember r: sel) {
110 if (r.getMember().isUsable()) {
111 toHighlight.add(r.getMember());
112 }
113 }
114 SwingUtilities.invokeLater(new Runnable() {
115 @Override
116 public void run() {
117 if (Main.isDisplayingMapView() && highlightHelper.highlightOnly(toHighlight)) {
118 Main.map.mapView.repaint();
119 }
120 }
121 });
122 }
123 }
124 };
125
126 private void initHighlighting() {
127 highlightEnabled = Main.pref.getBoolean("draw.target-highlight", true);
128 if (!highlightEnabled) return;
129 getMemberTableModel().getSelectionModel().addListSelectionListener(highlighterListener);
130 if (Main.isDisplayingMapView()) {
131 HighlightHelper.clearAllHighlighted();
132 Main.map.mapView.repaint();
133 }
134 }
135
136 @Override
137 public void unlinkAsListener() {
138 super.unlinkAsListener();
139 MapView.removeLayerChangeListener(zoomToGap);
140 }
141
142 public void stopHighlighting() {
143 if (highlighterListener == null) return;
144 if (!highlightEnabled) return;
145 getMemberTableModel().getSelectionModel().removeListSelectionListener(highlighterListener);
146 highlighterListener = null;
147 if (Main.isDisplayingMapView()) {
148 HighlightHelper.clearAllHighlighted();
149 Main.map.mapView.repaint();
150 }
151 }
152
153 private class SelectPreviousGapAction extends AbstractAction {
154
155 SelectPreviousGapAction() {
156 putValue(NAME, tr("Select previous Gap"));
157 putValue(SHORT_DESCRIPTION, tr("Select the previous relation member which gives rise to a gap"));
158 }
159
160 @Override
161 public void actionPerformed(ActionEvent e) {
162 int i = getSelectedRow() - 1;
163 while (i >= 0 && getMemberTableModel().getWayConnection(i).linkPrev) {
164 i--;
165 }
166 if (i >= 0) {
167 getSelectionModel().setSelectionInterval(i, i);
168 }
169 }
170 }
171
172 private class SelectNextGapAction extends AbstractAction {
173
174 SelectNextGapAction() {
175 putValue(NAME, tr("Select next Gap"));
176 putValue(SHORT_DESCRIPTION, tr("Select the next relation member which gives rise to a gap"));
177 }
178
179 @Override
180 public void actionPerformed(ActionEvent e) {
181 int i = getSelectedRow() + 1;
182 while (i < getRowCount() && getMemberTableModel().getWayConnection(i).linkNext) {
183 i++;
184 }
185 if (i < getRowCount()) {
186 getSelectionModel().setSelectionInterval(i, i);
187 }
188 }
189 }
190
191 private class ZoomToGapAction extends AbstractAction implements LayerChangeListener, ListSelectionListener {
192
193 /**
194 * Constructs a new {@code ZoomToGapAction}.
195 */
196 ZoomToGapAction() {
197 putValue(NAME, tr("Zoom to Gap"));
198 putValue(SHORT_DESCRIPTION, tr("Zoom to the gap in the way sequence"));
199 updateEnabledState();
200 }
201
202 private WayConnectionType getConnectionType() {
203 return getMemberTableModel().getWayConnection(getSelectedRows()[0]);
204 }
205
206 private final Collection<Direction> connectionTypesOfInterest = Arrays.asList(
207 WayConnectionType.Direction.FORWARD, WayConnectionType.Direction.BACKWARD);
208
209 private boolean hasGap() {
210 WayConnectionType connectionType = getConnectionType();
211 return connectionTypesOfInterest.contains(connectionType.direction)
212 && !(connectionType.linkNext && connectionType.linkPrev);
213 }
214
215 @Override
216 public void actionPerformed(ActionEvent e) {
217 WayConnectionType connectionType = getConnectionType();
218 Way way = (Way) getMemberTableModel().getReferredPrimitive(getSelectedRows()[0]);
219 if (!connectionType.linkPrev) {
220 getLayer().data.setSelected(WayConnectionType.Direction.FORWARD.equals(connectionType.direction)
221 ? way.firstNode() : way.lastNode());
222 AutoScaleAction.autoScale("selection");
223 } else if (!connectionType.linkNext) {
224 getLayer().data.setSelected(WayConnectionType.Direction.FORWARD.equals(connectionType.direction)
225 ? way.lastNode() : way.firstNode());
226 AutoScaleAction.autoScale("selection");
227 }
228 }
229
230 private void updateEnabledState() {
231 setEnabled(Main.main != null
232 && Main.main.getEditLayer() == getLayer()
233 && getSelectedRowCount() == 1
234 && hasGap());
235 }
236
237 @Override
238 public void valueChanged(ListSelectionEvent e) {
239 updateEnabledState();
240 }
241
242 @Override
243 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
244 updateEnabledState();
245 }
246
247 @Override
248 public void layerAdded(Layer newLayer) {
249 updateEnabledState();
250 }
251
252 @Override
253 public void layerRemoved(Layer oldLayer) {
254 updateEnabledState();
255 }
256 }
257
258 protected MemberTableModel getMemberTableModel() {
259 return (MemberTableModel) getModel();
260 }
261}
Note: See TracBrowser for help on using the repository browser.