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

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

javadoc update

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