001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.util; 003 004import java.util.Arrays; 005import java.util.stream.IntStream; 006 007import javax.swing.JList; 008import javax.swing.JTable; 009import javax.swing.ListModel; 010import javax.swing.ListSelectionModel; 011import javax.swing.table.TableModel; 012 013import org.openstreetmap.josm.data.ReorderableModel; 014 015/** 016 * Defines a list/table model that can be reordered. 017 * @param <T> item type 018 * @since 15226 019 */ 020public interface ReorderableTableModel<T> extends ReorderableModel<T> { 021 022 /** 023 * Returns the selection model. 024 * @return the selection model (never null) 025 * @see JList#getSelectionModel() 026 * @see JTable#getSelectionModel() 027 */ 028 ListSelectionModel getSelectionModel(); 029 030 /** 031 * Returns the number of rows in the list/table. 032 * @return the number of rows in the list/table 033 * @see ListModel#getSize() 034 * @see TableModel#getRowCount() 035 */ 036 int getRowCount(); 037 038 /** 039 * Returns an array of all of the selected indices in the selection model, in increasing order. 040 * @return an array of all of the selected indices in the selection model, in increasing order 041 * @see #selectedIndices() 042 */ 043 default int[] getSelectedIndices() { 044 return TableHelper.getSelectedIndices(getSelectionModel()); 045 } 046 047 /** 048 * Returns a stream of all of the selected indices in the selection model, in increasing order. 049 * @return a stream of all of the selected indices in the selection model, in increasing order 050 * @since 17773 051 */ 052 default IntStream selectedIndices() { 053 return TableHelper.selectedIndices(getSelectionModel()); 054 } 055 056 /** 057 * Checks that the currently selected range of rows can be moved by a number of positions. 058 * @param delta negative or positive delta 059 * @return {@code true} if rows can be moved 060 */ 061 default boolean canMove(int delta) { 062 return canMove(delta, this::getRowCount, getSelectedIndices()); 063 } 064 065 /** 066 * Checks that the currently selected range of rows can be moved up. 067 * @return {@code true} if rows can be moved up 068 */ 069 default boolean canMoveUp() { 070 return canMoveUp(getSelectedIndices()); 071 } 072 073 /** 074 * Checks that a range of rows can be moved up. 075 * @param rows indexes of rows to move up 076 * @return {@code true} if rows can be moved up 077 */ 078 default boolean canMoveUp(int... rows) { 079 return canMoveUp(this::getRowCount, rows); 080 } 081 082 /** 083 * Checks that the currently selected range of rows can be moved down. 084 * @return {@code true} if rows can be moved down 085 */ 086 default boolean canMoveDown() { 087 return canMoveDown(getSelectedIndices()); 088 } 089 090 /** 091 * Checks that a range of rows can be moved down. 092 * @param rows indexes of rows to move down 093 * @return {@code true} if rows can be moved down 094 */ 095 default boolean canMoveDown(int... rows) { 096 return canMoveDown(this::getRowCount, rows); 097 } 098 099 /** 100 * Move up selected rows, if possible. 101 * @return {@code true} if the move was performed 102 * @see #canMoveUp 103 */ 104 default boolean moveUp() { 105 return moveUp(getSelectedIndices()); 106 } 107 108 /** 109 * Move up selected rows, if possible. 110 * @param selectedRows rows to move up 111 * @return {@code true} if the move was performed 112 * @see #canMoveUp 113 */ 114 default boolean moveUp(int... selectedRows) { 115 return move(-1, selectedRows); 116 } 117 118 /** 119 * Move down selected rows, if possible. 120 * @return {@code true} if the move was performed 121 * @see #canMoveDown 122 */ 123 default boolean moveDown() { 124 return moveDown(getSelectedIndices()); 125 } 126 127 /** 128 * Move down selected rows by 1 position, if possible. 129 * @param selectedRows rows to move down 130 * @return {@code true} if the move was performed 131 * @see #canMoveDown 132 */ 133 default boolean moveDown(int... selectedRows) { 134 return move(1, selectedRows); 135 } 136 137 /** 138 * Move selected rows by any number of positions, if possible. 139 * @param delta negative or positive delta 140 * @param selectedRows rows to move 141 * @return {@code true} if the move was performed 142 * @see #canMove 143 */ 144 default boolean move(int delta, int... selectedRows) { 145 if (!canMove(delta, this::getRowCount, selectedRows)) 146 return false; 147 if (!doMove(delta, selectedRows)) 148 return false; 149 final ListSelectionModel selectionModel = getSelectionModel(); 150 TableHelper.setSelectedIndices(selectionModel, Arrays.stream(selectedRows).map(i -> i + delta)); 151 return true; 152 } 153}