Changeset 18439 in josm for trunk/src/org


Ignore:
Timestamp:
2022-05-04T21:08:02+02:00 (3 years ago)
Author:
taylor.smock
Message:

Fix #17906, #21889, see #12617 for the original issue

This fixes an issue where a relation member could be deleted accidentally
when a user moved the relation member to its current position. This also
affected multiple members when multiple members were selected. The user
just had to move the selected members to another selected member position.

This patch also improves relation move performance when large numbers of
relation members are moved.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java

    r18401 r18439  
    308308        final ListSelectionModel selectionModel = getSelectionModel();
    309309        selectionModel.setValueIsAdjusting(true);
    310         for (int row : selectedRows) {
    311             row -= offset;
    312             if (members.size() > row) {
    313                 members.remove(row);
    314                 selectionModel.removeIndexInterval(row, row);
    315                 offset++;
     310        for (int[] row : groupRows(selectedRows)) {
     311            if (members.size() > row[0] - offset) {
     312                // Remove (inclusive)
     313                members.subList(row[0] - offset, row[1] - offset + 1).clear();
     314                selectionModel.removeIndexInterval(row[0] - offset, row[1] - offset);
     315                offset += row[1] - row[0] + 1;
    316316            }
    317317        }
    318318        selectionModel.setValueIsAdjusting(false);
    319319        fireTableDataChanged();
     320    }
     321
     322    /**
     323     * Group rows for use in changing selection intervals, to avoid many small calls on large selections
     324     * @param rows The rows to group
     325     * @return A list of grouped rows, [lower, higher] (inclusive)
     326     */
     327    private static List<int[]> groupRows(int... rows) {
     328        if (rows.length == 0) {
     329            return Collections.emptyList();
     330        }
     331        List<int[]> groups = new ArrayList<>();
     332        int[] current = {Integer.MIN_VALUE, Integer.MIN_VALUE};
     333        groups.add(current);
     334        for (int row : rows) {
     335            if (current[0] == Integer.MIN_VALUE) {
     336                current[0] = row;
     337                current[1] = row;
     338                continue;
     339            }
     340            if (current[1] == row - 1) {
     341                current[1] = row;
     342            } else {
     343                current = new int[] {row, row};
     344                groups.add(current);
     345            }
     346        }
     347        return Collections.unmodifiableList(groups);
    320348    }
    321349
     
    445473    void addMembersAtIndexKeepingOldSelection(final Iterable<RelationMember> newMembers, final int index) {
    446474        int idx = index;
     475        // Avoid having the inserted rows from being part of the selection. See JOSM #12617, #17906, #21889.
     476        int[] originalSelection = null;
     477        if (selectedIndices().anyMatch(selectedRow -> selectedRow == index)) {
     478            originalSelection = getSelectedIndices();
     479        }
    447480        for (RelationMember member : newMembers) {
    448481            members.add(idx++, member);
     
    450483        invalidateConnectionType();
    451484        fireTableRowsInserted(index, idx - 1);
     485        if (originalSelection != null) {
     486            final DefaultListSelectionModel model = this.getSelectionModel();
     487            model.setValueIsAdjusting(true);
     488            model.clearSelection();
     489            final int tIdx = idx;
     490            // Avoiding many addSelectionInterval calls is critical for performance.
     491            for (int[] row : groupRows(IntStream.of(originalSelection).map(i -> i < index ? i : i + tIdx - index).toArray())) {
     492                model.addSelectionInterval(row[0], row[1]);
     493            }
     494            model.setValueIsAdjusting(false);
     495        }
    452496    }
    453497
Note: See TracChangeset for help on using the changeset viewer.