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

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

fix #12999 - Exception after resolving conflicts (patch by michael2402, modified) - gsoc-core

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