001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.changeset; 003 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.Comparator; 007import java.util.Iterator; 008import java.util.List; 009import java.util.Set; 010import java.util.stream.Collectors; 011 012import javax.swing.DefaultListSelectionModel; 013import javax.swing.JTable; 014import javax.swing.table.AbstractTableModel; 015 016import org.openstreetmap.josm.data.osm.ChangesetDataSet; 017import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetDataSetEntry; 018import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType; 019import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 020 021/** 022 * This is the table model for the content of a changeset. 023 * @since 2689 024 */ 025public class ChangesetContentTableModel extends AbstractTableModel { 026 027 private final transient List<ChangesetContentEntry> data = new ArrayList<>(); 028 private final DefaultListSelectionModel selectionModel; 029 030 /** 031 * Constructs a new {@code ChangesetContentTableModel}. 032 * @param selectionModel selection model 033 */ 034 public ChangesetContentTableModel(DefaultListSelectionModel selectionModel) { 035 this.selectionModel = selectionModel; 036 } 037 038 /** 039 * Replies true if there is at least one selected primitive in the table model 040 * 041 * @return true if there is at least one selected primitive in the table model 042 */ 043 public boolean hasSelectedPrimitives() { 044 return selectionModel.getMinSelectionIndex() >= 0; 045 } 046 047 /** 048 * Selects a single item by its index. 049 * @param row index 050 */ 051 public void setSelectedByIdx(int row) { 052 selectionModel.setSelectionInterval(row, row); 053 } 054 055 /** 056 * Replies the selection model 057 * @return the selection model 058 */ 059 public DefaultListSelectionModel getSelectionModel() { 060 return selectionModel; 061 } 062 063 /** 064 * Returns the selected history primitives. 065 * @param table the JTable used with this model 066 * @return the selected history primitives 067 */ 068 public Set<HistoryOsmPrimitive> getSelectedPrimitives(JTable table) { 069 int[] selection = table.getSelectedRows(); 070 return Arrays.stream(selection) 071 .mapToObj(i -> data.get(table.convertRowIndexToModel(i)).getPrimitive()) 072 .collect(Collectors.toSet()); 073 } 074 075 /** 076 * Populates the model with the content of a changeset. If ds is null, the table is cleared. 077 * 078 * @param ds the changeset content. 079 */ 080 public void populate(ChangesetDataSet ds) { 081 this.data.clear(); 082 if (ds == null) { 083 fireTableDataChanged(); 084 return; 085 } 086 for (Iterator<ChangesetDataSetEntry> it = ds.iterator(); it.hasNext();) { 087 data.add(new ChangesetContentEntry(it.next())); 088 } 089 sort(); 090 fireTableDataChanged(); 091 } 092 093 /** 094 * Sort data. 095 */ 096 protected void sort() { 097 data.sort(Comparator.comparing(ChangesetContentEntry::getModificationType).thenComparingLong(c -> c.getPrimitive().getId()) 098 ); 099 } 100 101 /* -------------------------------------------------------------- */ 102 /* interface TableModel */ 103 /* -------------------------------------------------------------- */ 104 @Override 105 public int getColumnCount() { 106 return 3; 107 } 108 109 @Override 110 public int getRowCount() { 111 return data.size(); 112 } 113 114 @Override 115 public Object getValueAt(int row, int col) { 116 switch(col) { 117 case 0: return data.get(row).getModificationType(); 118 default: return data.get(row).getPrimitive(); 119 } 120 } 121 122 /** 123 * The type used internally to keep information about {@link HistoryOsmPrimitive} 124 * with their {@link ChangesetModificationType}. 125 */ 126 private static class ChangesetContentEntry implements ChangesetDataSetEntry { 127 private final ChangesetModificationType modificationType; 128 private final HistoryOsmPrimitive primitive; 129 130 ChangesetContentEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) { 131 this.modificationType = modificationType; 132 this.primitive = primitive; 133 } 134 135 ChangesetContentEntry(ChangesetDataSetEntry entry) { 136 this(entry.getModificationType(), entry.getPrimitive()); 137 } 138 139 @Override 140 public ChangesetModificationType getModificationType() { 141 return modificationType; 142 } 143 144 @Override 145 public HistoryOsmPrimitive getPrimitive() { 146 return primitive; 147 } 148 } 149}