source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java@ 8840

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

sonar - squid:S3052 - Fields should not be initialized to default values

  • Property svn:eol-style set to native
File size: 26.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.Collection;
7import java.util.Collections;
8import java.util.EnumSet;
9import java.util.HashSet;
10import java.util.Iterator;
11import java.util.List;
12import java.util.Set;
13import java.util.TreeSet;
14import java.util.concurrent.CopyOnWriteArrayList;
15
16import javax.swing.DefaultListSelectionModel;
17import javax.swing.ListSelectionModel;
18import javax.swing.event.TableModelEvent;
19import javax.swing.event.TableModelListener;
20import javax.swing.table.AbstractTableModel;
21
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.data.SelectionChangedListener;
24import org.openstreetmap.josm.data.osm.DataSet;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.Relation;
27import org.openstreetmap.josm.data.osm.RelationMember;
28import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
29import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
30import org.openstreetmap.josm.data.osm.event.DataSetListener;
31import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
32import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
33import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
34import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
35import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
36import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
37import org.openstreetmap.josm.gui.dialogs.relation.sort.RelationSorter;
38import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType;
39import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionTypeCalculator;
40import org.openstreetmap.josm.gui.layer.OsmDataLayer;
41import org.openstreetmap.josm.gui.tagging.PresetHandler;
42import org.openstreetmap.josm.gui.tagging.TaggingPreset;
43import org.openstreetmap.josm.gui.tagging.TaggingPresetType;
44import org.openstreetmap.josm.gui.widgets.OsmPrimitivesTableModel;
45
46public class MemberTableModel extends AbstractTableModel
47implements TableModelListener, SelectionChangedListener, DataSetListener, OsmPrimitivesTableModel {
48
49 /**
50 * data of the table model: The list of members and the cached WayConnectionType of each member.
51 **/
52 private transient List<RelationMember> members;
53 private transient List<WayConnectionType> connectionType;
54
55 private DefaultListSelectionModel listSelectionModel;
56 private final CopyOnWriteArrayList<IMemberModelListener> listeners;
57 private final transient OsmDataLayer layer;
58 private final transient PresetHandler presetHandler;
59
60 private final transient WayConnectionTypeCalculator wayConnectionTypeCalculator = new WayConnectionTypeCalculator();
61 private final transient RelationSorter relationSorter = new RelationSorter();
62
63 /**
64 * constructor
65 */
66 public MemberTableModel(OsmDataLayer layer, PresetHandler presetHandler) {
67 members = new ArrayList<>();
68 listeners = new CopyOnWriteArrayList<>();
69 this.layer = layer;
70 this.presetHandler = presetHandler;
71 addTableModelListener(this);
72 }
73
74 public OsmDataLayer getLayer() {
75 return layer;
76 }
77
78 public void register() {
79 DataSet.addSelectionListener(this);
80 getLayer().data.addDataSetListener(this);
81 }
82
83 public void unregister() {
84 DataSet.removeSelectionListener(this);
85 getLayer().data.removeDataSetListener(this);
86 }
87
88 /* --------------------------------------------------------------------------- */
89 /* Interface SelectionChangedListener */
90 /* --------------------------------------------------------------------------- */
91 @Override
92 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
93 if (Main.main.getEditLayer() != this.layer) return;
94 // just trigger a repaint
95 Collection<RelationMember> sel = getSelectedMembers();
96 fireTableDataChanged();
97 setSelectedMembers(sel);
98 }
99
100 /* --------------------------------------------------------------------------- */
101 /* Interface DataSetListener */
102 /* --------------------------------------------------------------------------- */
103 @Override
104 public void dataChanged(DataChangedEvent event) {
105 // just trigger a repaint - the display name of the relation members may have changed
106 Collection<RelationMember> sel = getSelectedMembers();
107 fireTableDataChanged();
108 setSelectedMembers(sel);
109 }
110
111 @Override
112 public void nodeMoved(NodeMovedEvent event) {
113 // ignore
114 }
115
116 @Override
117 public void primitivesAdded(PrimitivesAddedEvent event) {
118 // ignore
119 }
120
121 @Override
122 public void primitivesRemoved(PrimitivesRemovedEvent event) {
123 // ignore - the relation in the editor might become out of sync with the relation
124 // in the dataset. We will deal with it when the relation editor is closed or
125 // when the changes in the editor are applied.
126 }
127
128 @Override
129 public void relationMembersChanged(RelationMembersChangedEvent event) {
130 // ignore - the relation in the editor might become out of sync with the relation
131 // in the dataset. We will deal with it when the relation editor is closed or
132 // when the changes in the editor are applied.
133 }
134
135 @Override
136 public void tagsChanged(TagsChangedEvent event) {
137 // just refresh the respective table cells
138 //
139 Collection<RelationMember> sel = getSelectedMembers();
140 for (int i = 0; i < members.size(); i++) {
141 if (members.get(i).getMember() == event.getPrimitive()) {
142 fireTableCellUpdated(i, 1 /* the column with the primitive name */);
143 }
144 }
145 setSelectedMembers(sel);
146 }
147
148 @Override
149 public void wayNodesChanged(WayNodesChangedEvent event) {
150 // ignore
151 }
152
153 @Override
154 public void otherDatasetChange(AbstractDatasetChangedEvent event) {
155 // ignore
156 }
157
158 /* --------------------------------------------------------------------------- */
159
160 public void addMemberModelListener(IMemberModelListener listener) {
161 if (listener != null) {
162 listeners.addIfAbsent(listener);
163 }
164 }
165
166 public void removeMemberModelListener(IMemberModelListener listener) {
167 listeners.remove(listener);
168 }
169
170 protected void fireMakeMemberVisible(int index) {
171 for (IMemberModelListener listener : listeners) {
172 listener.makeMemberVisible(index);
173 }
174 }
175
176 public void populate(Relation relation) {
177 members.clear();
178 if (relation != null) {
179 // make sure we work with clones of the relation members in the model.
180 members.addAll(new Relation(relation).getMembers());
181 }
182 fireTableDataChanged();
183 }
184
185 @Override
186 public int getColumnCount() {
187 return 3;
188 }
189
190 @Override
191 public int getRowCount() {
192 return members.size();
193 }
194
195 @Override
196 public Object getValueAt(int rowIndex, int columnIndex) {
197 switch (columnIndex) {
198 case 0:
199 return members.get(rowIndex).getRole();
200 case 1:
201 return members.get(rowIndex).getMember();
202 case 2:
203 return getWayConnection(rowIndex);
204 }
205 // should not happen
206 return null;
207 }
208
209 @Override
210 public boolean isCellEditable(int rowIndex, int columnIndex) {
211 return columnIndex == 0;
212 }
213
214 @Override
215 public void setValueAt(Object value, int rowIndex, int columnIndex) {
216 // fix #10524 - IndexOutOfBoundsException: Index: 2, Size: 2
217 if (rowIndex >= members.size()) {
218 return;
219 }
220 RelationMember member = members.get(rowIndex);
221 RelationMember newMember = new RelationMember(value.toString(), member.getMember());
222 members.remove(rowIndex);
223 members.add(rowIndex, newMember);
224 }
225
226 @Override
227 public OsmPrimitive getReferredPrimitive(int idx) {
228 return members.get(idx).getMember();
229 }
230
231 public void moveUp(int[] selectedRows) {
232 if (!canMoveUp(selectedRows))
233 return;
234
235 for (int row : selectedRows) {
236 RelationMember member1 = members.get(row);
237 RelationMember member2 = members.get(row - 1);
238 members.set(row, member2);
239 members.set(row - 1, member1);
240 }
241 fireTableDataChanged();
242 getSelectionModel().setValueIsAdjusting(true);
243 getSelectionModel().clearSelection();
244 for (int row : selectedRows) {
245 row--;
246 getSelectionModel().addSelectionInterval(row, row);
247 }
248 getSelectionModel().setValueIsAdjusting(false);
249 fireMakeMemberVisible(selectedRows[0] - 1);
250 }
251
252 public void moveDown(int[] selectedRows) {
253 if (!canMoveDown(selectedRows))
254 return;
255
256 for (int i = selectedRows.length - 1; i >= 0; i--) {
257 int row = selectedRows[i];
258 RelationMember member1 = members.get(row);
259 RelationMember member2 = members.get(row + 1);
260 members.set(row, member2);
261 members.set(row + 1, member1);
262 }
263 fireTableDataChanged();
264 getSelectionModel();
265 getSelectionModel().setValueIsAdjusting(true);
266 getSelectionModel().clearSelection();
267 for (int row : selectedRows) {
268 row++;
269 getSelectionModel().addSelectionInterval(row, row);
270 }
271 getSelectionModel().setValueIsAdjusting(false);
272 fireMakeMemberVisible(selectedRows[0] + 1);
273 }
274
275 public void remove(int[] selectedRows) {
276 if (!canRemove(selectedRows))
277 return;
278 int offset = 0;
279 for (int row : selectedRows) {
280 row -= offset;
281 if (members.size() > row) {
282 members.remove(row);
283 offset++;
284 }
285 }
286 fireTableDataChanged();
287 }
288
289 public boolean canMoveUp(int[] rows) {
290 if (rows == null || rows.length == 0)
291 return false;
292 Arrays.sort(rows);
293 return rows[0] > 0 && !members.isEmpty();
294 }
295
296 public boolean canMoveDown(int[] rows) {
297 if (rows == null || rows.length == 0)
298 return false;
299 Arrays.sort(rows);
300 return !members.isEmpty() && rows[rows.length - 1] < members.size() - 1;
301 }
302
303 public boolean canRemove(int[] rows) {
304 if (rows == null || rows.length == 0)
305 return false;
306 return true;
307 }
308
309 public DefaultListSelectionModel getSelectionModel() {
310 if (listSelectionModel == null) {
311 listSelectionModel = new DefaultListSelectionModel();
312 listSelectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
313 }
314 return listSelectionModel;
315 }
316
317 public void removeMembersReferringTo(List<? extends OsmPrimitive> primitives) {
318 if (primitives == null)
319 return;
320 Iterator<RelationMember> it = members.iterator();
321 while (it.hasNext()) {
322 RelationMember member = it.next();
323 if (primitives.contains(member.getMember())) {
324 it.remove();
325 }
326 }
327 fireTableDataChanged();
328 }
329
330 public void applyToRelation(Relation relation) {
331 relation.setMembers(members);
332 }
333
334 public boolean hasSameMembersAs(Relation relation) {
335 if (relation == null)
336 return false;
337 if (relation.getMembersCount() != members.size())
338 return false;
339 for (int i = 0; i < relation.getMembersCount(); i++) {
340 if (!relation.getMember(i).equals(members.get(i)))
341 return false;
342 }
343 return true;
344 }
345
346 /**
347 * Replies the set of incomplete primitives
348 *
349 * @return the set of incomplete primitives
350 */
351 public Set<OsmPrimitive> getIncompleteMemberPrimitives() {
352 Set<OsmPrimitive> ret = new HashSet<>();
353 for (RelationMember member : members) {
354 if (member.getMember().isIncomplete()) {
355 ret.add(member.getMember());
356 }
357 }
358 return ret;
359 }
360
361 /**
362 * Replies the set of selected incomplete primitives
363 *
364 * @return the set of selected incomplete primitives
365 */
366 public Set<OsmPrimitive> getSelectedIncompleteMemberPrimitives() {
367 Set<OsmPrimitive> ret = new HashSet<>();
368 for (RelationMember member : getSelectedMembers()) {
369 if (member.getMember().isIncomplete()) {
370 ret.add(member.getMember());
371 }
372 }
373 return ret;
374 }
375
376 /**
377 * Replies true if at least one the relation members is incomplete
378 *
379 * @return true if at least one the relation members is incomplete
380 */
381 public boolean hasIncompleteMembers() {
382 for (RelationMember member : members) {
383 if (member.getMember().isIncomplete())
384 return true;
385 }
386 return false;
387 }
388
389 /**
390 * Replies true if at least one of the selected members is incomplete
391 *
392 * @return true if at least one of the selected members is incomplete
393 */
394 public boolean hasIncompleteSelectedMembers() {
395 for (RelationMember member : getSelectedMembers()) {
396 if (member.getMember().isIncomplete())
397 return true;
398 }
399 return false;
400 }
401
402 protected List<Integer> getSelectedIndices() {
403 List<Integer> selectedIndices = new ArrayList<>();
404 for (int i = 0; i < members.size(); i++) {
405 if (getSelectionModel().isSelectedIndex(i)) {
406 selectedIndices.add(i);
407 }
408 }
409 return selectedIndices;
410 }
411
412 private void addMembersAtIndex(List<? extends OsmPrimitive> primitives, int index) {
413 final Collection<TaggingPreset> presets = TaggingPreset.getMatchingPresets(EnumSet.of(TaggingPresetType.RELATION),
414 presetHandler.getSelection().iterator().next().getKeys(), false);
415 if (primitives == null)
416 return;
417 int idx = index;
418 for (OsmPrimitive primitive : primitives) {
419 Set<String> potentialRoles = new TreeSet<>();
420 for (TaggingPreset tp : presets) {
421 String suggestedRole = tp.suggestRoleForOsmPrimitive(primitive);
422 if (suggestedRole != null) {
423 potentialRoles.add(suggestedRole);
424 }
425 }
426 // TODO: propose user to choose role among potential ones instead of picking first one
427 final String role = potentialRoles.isEmpty() ? null : potentialRoles.iterator().next();
428 RelationMember member = new RelationMember(role == null ? "" : role, primitive);
429 members.add(idx++, member);
430 }
431 fireTableDataChanged();
432 getSelectionModel().clearSelection();
433 getSelectionModel().addSelectionInterval(index, index + primitives.size() - 1);
434 fireMakeMemberVisible(index);
435 }
436
437 public void addMembersAtBeginning(List<? extends OsmPrimitive> primitives) {
438 addMembersAtIndex(primitives, 0);
439 }
440
441 public void addMembersAtEnd(List<? extends OsmPrimitive> primitives) {
442 addMembersAtIndex(primitives, members.size());
443 }
444
445 public void addMembersBeforeIdx(List<? extends OsmPrimitive> primitives, int idx) {
446 addMembersAtIndex(primitives, idx);
447 }
448
449 public void addMembersAfterIdx(List<? extends OsmPrimitive> primitives, int idx) {
450 addMembersAtIndex(primitives, idx + 1);
451 }
452
453 /**
454 * Replies the number of members which refer to a particular primitive
455 *
456 * @param primitive the primitive
457 * @return the number of members which refer to a particular primitive
458 */
459 public int getNumMembersWithPrimitive(OsmPrimitive primitive) {
460 int count = 0;
461 for (RelationMember member : members) {
462 if (member.getMember().equals(primitive)) {
463 count++;
464 }
465 }
466 return count;
467 }
468
469 /**
470 * updates the role of the members given by the indices in <code>idx</code>
471 *
472 * @param idx the array of indices
473 * @param role the new role
474 */
475 public void updateRole(int[] idx, String role) {
476 if (idx == null || idx.length == 0)
477 return;
478 for (int row : idx) {
479 // fix #7885 - IndexOutOfBoundsException: Index: 39, Size: 39
480 if (row >= members.size()) {
481 continue;
482 }
483 RelationMember oldMember = members.get(row);
484 RelationMember newMember = new RelationMember(role, oldMember.getMember());
485 members.remove(row);
486 members.add(row, newMember);
487 }
488 fireTableDataChanged();
489 for (int row : idx) {
490 getSelectionModel().addSelectionInterval(row, row);
491 }
492 }
493
494 /**
495 * Get the currently selected relation members
496 *
497 * @return a collection with the currently selected relation members
498 */
499 public Collection<RelationMember> getSelectedMembers() {
500 List<RelationMember> selectedMembers = new ArrayList<>();
501 for (int i : getSelectedIndices()) {
502 selectedMembers.add(members.get(i));
503 }
504 return selectedMembers;
505 }
506
507 /**
508 * Replies the set of selected referers. Never null, but may be empty.
509 *
510 * @return the set of selected referers
511 */
512 public Collection<OsmPrimitive> getSelectedChildPrimitives() {
513 Collection<OsmPrimitive> ret = new ArrayList<>();
514 for (RelationMember m: getSelectedMembers()) {
515 ret.add(m.getMember());
516 }
517 return ret;
518 }
519
520 /**
521 * Replies the set of selected referers. Never null, but may be empty.
522 *
523 * @return the set of selected referers
524 */
525 public Set<OsmPrimitive> getChildPrimitives(Collection<? extends OsmPrimitive> referenceSet) {
526 Set<OsmPrimitive> ret = new HashSet<>();
527 if (referenceSet == null) return null;
528 for (RelationMember m: members) {
529 if (referenceSet.contains(m.getMember())) {
530 ret.add(m.getMember());
531 }
532 }
533 return ret;
534 }
535
536 /**
537 * Selects the members in the collection selectedMembers
538 *
539 * @param selectedMembers the collection of selected members
540 */
541 public void setSelectedMembers(Collection<RelationMember> selectedMembers) {
542 if (selectedMembers == null || selectedMembers.isEmpty()) {
543 getSelectionModel().clearSelection();
544 return;
545 }
546
547 // lookup the indices for the respective members
548 //
549 Set<Integer> selectedIndices = new HashSet<>();
550 for (RelationMember member : selectedMembers) {
551 for (int idx = 0; idx < members.size(); ++idx) {
552 if (member.equals(members.get(idx))) {
553 selectedIndices.add(idx);
554 }
555 }
556 }
557 setSelectedMembersIdx(selectedIndices);
558 }
559
560 /**
561 * Selects the members in the collection selectedIndices
562 *
563 * @param selectedIndices the collection of selected member indices
564 */
565 public void setSelectedMembersIdx(Collection<Integer> selectedIndices) {
566 if (selectedIndices == null || selectedIndices.isEmpty()) {
567 getSelectionModel().clearSelection();
568 return;
569 }
570 // select the members
571 //
572 getSelectionModel().setValueIsAdjusting(true);
573 getSelectionModel().clearSelection();
574 for (int row : selectedIndices) {
575 getSelectionModel().addSelectionInterval(row, row);
576 }
577 getSelectionModel().setValueIsAdjusting(false);
578 // make the first selected member visible
579 //
580 if (!selectedIndices.isEmpty()) {
581 fireMakeMemberVisible(Collections.min(selectedIndices));
582 }
583 }
584
585 /**
586 * Replies true if the index-th relation members referrs
587 * to an editable relation, i.e. a relation which is not
588 * incomplete.
589 *
590 * @param index the index
591 * @return true, if the index-th relation members referrs
592 * to an editable relation, i.e. a relation which is not
593 * incomplete
594 */
595 public boolean isEditableRelation(int index) {
596 if (index < 0 || index >= members.size())
597 return false;
598 RelationMember member = members.get(index);
599 if (!member.isRelation())
600 return false;
601 Relation r = member.getRelation();
602 return !r.isIncomplete();
603 }
604
605 /**
606 * Replies true if there is at least one relation member given as {@code members}
607 * which refers to at least on the primitives in {@code primitives}.
608 *
609 * @param members the members
610 * @param primitives the collection of primitives
611 * @return true if there is at least one relation member in this model
612 * which refers to at least on the primitives in <code>primitives</code>; false
613 * otherwise
614 */
615 public static boolean hasMembersReferringTo(Collection<RelationMember> members, Collection<OsmPrimitive> primitives) {
616 if (primitives == null || primitives.isEmpty())
617 return false;
618 Set<OsmPrimitive> referrers = new HashSet<>();
619 for (RelationMember member : members) {
620 referrers.add(member.getMember());
621 }
622 for (OsmPrimitive referred : primitives) {
623 if (referrers.contains(referred))
624 return true;
625 }
626 return false;
627 }
628
629 /**
630 * Replies true if there is at least one relation member in this model
631 * which refers to at least on the primitives in <code>primitives</code>.
632 *
633 * @param primitives the collection of primitives
634 * @return true if there is at least one relation member in this model
635 * which refers to at least on the primitives in <code>primitives</code>; false
636 * otherwise
637 */
638 public boolean hasMembersReferringTo(Collection<OsmPrimitive> primitives) {
639 return hasMembersReferringTo(members, primitives);
640 }
641
642 /**
643 * Selects all mebers which refer to {@link OsmPrimitive}s in the collections
644 * <code>primitmives</code>. Does nothing is primitives is null.
645 *
646 * @param primitives the collection of primitives
647 */
648 public void selectMembersReferringTo(Collection<? extends OsmPrimitive> primitives) {
649 if (primitives == null) return;
650 getSelectionModel().setValueIsAdjusting(true);
651 getSelectionModel().clearSelection();
652 for (int i = 0; i < members.size(); i++) {
653 RelationMember m = members.get(i);
654 if (primitives.contains(m.getMember())) {
655 this.getSelectionModel().addSelectionInterval(i, i);
656 }
657 }
658 getSelectionModel().setValueIsAdjusting(false);
659 if (!getSelectedIndices().isEmpty()) {
660 fireMakeMemberVisible(getSelectedIndices().get(0));
661 }
662 }
663
664 /**
665 * Replies true if <code>primitive</code> is currently selected in the layer this
666 * model is attached to
667 *
668 * @param primitive the primitive
669 * @return true if <code>primitive</code> is currently selected in the layer this
670 * model is attached to, false otherwise
671 */
672 public boolean isInJosmSelection(OsmPrimitive primitive) {
673 return layer.data.isSelected(primitive);
674 }
675
676 /**
677 * Replies true if the layer this model belongs to is equal to the active
678 * layer
679 *
680 * @return true if the layer this model belongs to is equal to the active
681 * layer
682 */
683 protected boolean isActiveLayer() {
684 if (!Main.isDisplayingMapView()) return false;
685 return Main.map.mapView.getActiveLayer() == layer;
686 }
687
688 /**
689 * Sort the selected relation members by the way they are linked.
690 */
691 void sort() {
692 List<RelationMember> selectedMembers = new ArrayList<>(getSelectedMembers());
693 List<RelationMember> sortedMembers = null;
694 List<RelationMember> newMembers;
695 if (selectedMembers.size() <= 1) {
696 newMembers = relationSorter.sortMembers(members);
697 sortedMembers = newMembers;
698 } else {
699 sortedMembers = relationSorter.sortMembers(selectedMembers);
700 List<Integer> selectedIndices = getSelectedIndices();
701 newMembers = new ArrayList<>();
702 boolean inserted = false;
703 for (int i = 0; i < members.size(); i++) {
704 if (selectedIndices.contains(i)) {
705 if (!inserted) {
706 newMembers.addAll(sortedMembers);
707 inserted = true;
708 }
709 } else {
710 newMembers.add(members.get(i));
711 }
712 }
713 }
714
715 if (members.size() != newMembers.size()) throw new AssertionError();
716
717 members.clear();
718 members.addAll(newMembers);
719 fireTableDataChanged();
720 setSelectedMembers(sortedMembers);
721 }
722
723 /**
724 * Sort the selected relation members and all members below by the way they are linked.
725 */
726 void sortBelow() {
727 final List<RelationMember> subList = members.subList(getSelectionModel().getMinSelectionIndex(), members.size());
728 final List<RelationMember> sorted = relationSorter.sortMembers(subList);
729 subList.clear();
730 subList.addAll(sorted);
731 fireTableDataChanged();
732 setSelectedMembers(sorted);
733 }
734
735 WayConnectionType getWayConnection(int i) {
736 if (connectionType == null) {
737 connectionType = wayConnectionTypeCalculator.updateLinks(members);
738 }
739 return connectionType.get(i);
740 }
741
742 @Override
743 public void tableChanged(TableModelEvent e) {
744 connectionType = null;
745 }
746
747 /**
748 * Reverse the relation members.
749 */
750 void reverse() {
751 List<Integer> selectedIndices = getSelectedIndices();
752 List<Integer> selectedIndicesReversed = getSelectedIndices();
753
754 if (selectedIndices.size() <= 1) {
755 Collections.reverse(members);
756 fireTableDataChanged();
757 setSelectedMembers(members);
758 } else {
759 Collections.reverse(selectedIndicesReversed);
760
761 List<RelationMember> newMembers = new ArrayList<>(members);
762
763 for (int i = 0; i < selectedIndices.size(); i++) {
764 newMembers.set(selectedIndices.get(i), members.get(selectedIndicesReversed.get(i)));
765 }
766
767 if (members.size() != newMembers.size()) throw new AssertionError();
768 members.clear();
769 members.addAll(newMembers);
770 fireTableDataChanged();
771 setSelectedMembersIdx(selectedIndices);
772 }
773 }
774}
Note: See TracBrowser for help on using the repository browser.