001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences.advanced; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.util.ArrayList; 007import java.util.Arrays; 008import java.util.Collections; 009import java.util.LinkedHashMap; 010import java.util.List; 011import java.util.Map; 012import java.util.Map.Entry; 013 014import javax.swing.JComponent; 015import javax.swing.JPanel; 016import javax.swing.table.AbstractTableModel; 017 018import org.openstreetmap.josm.data.preferences.MapListSetting; 019 020/** 021 * Editor for List of Maps preference entries. 022 * @since 4634 023 */ 024public class MapListEditor extends AbstractTableListEditor<Map<String, String>> { 025 026 private final transient List<List<String>> dataKeys; 027 private final transient List<List<String>> dataValues; 028 029 /** 030 * Constructs a new {@code MapListEditor}. 031 * @param gui The parent component 032 * @param entry preference entry 033 * @param setting list of maps setting 034 */ 035 public MapListEditor(JComponent gui, PrefEntry entry, MapListSetting setting) { 036 super(gui, tr("Change list of maps setting"), entry); 037 List<Map<String, String>> orig = setting.getValue(); 038 039 dataKeys = new ArrayList<>(); 040 dataValues = new ArrayList<>(); 041 if (orig != null) { 042 for (Map<String, String> m : orig) { 043 List<String> keys = new ArrayList<>(); 044 List<String> values = new ArrayList<>(); 045 for (Entry<String, String> e : m.entrySet()) { 046 keys.add(e.getKey()); 047 values.add(e.getValue()); 048 } 049 dataKeys.add(keys); 050 dataValues.add(values); 051 } 052 } 053 } 054 055 @Override 056 public List<Map<String, String>> getData() { 057 List<Map<String, String>> data = new ArrayList<>(); 058 for (int i = 0; i < dataKeys.size(); ++i) { 059 Map<String, String> m = new LinkedHashMap<>(); 060 for (int j = 0; j < dataKeys.get(i).size(); ++j) { 061 m.put(dataKeys.get(i).get(j), dataValues.get(i).get(j)); 062 } 063 data.add(m); 064 } 065 return data; 066 } 067 068 @Override 069 protected final JPanel build() { 070 table.getTableHeader().getColumnModel().getColumn(0).setHeaderValue(tr("Key")); 071 table.getTableHeader().getColumnModel().getColumn(1).setHeaderValue(tr("Value")); 072 return super.build(); 073 } 074 075 private class EntryListModel extends AbstractEntryListModel { 076 077 @Override 078 public String getElementAt(int index) { 079 return tr("Entry {0}", index+1); 080 } 081 082 @Override 083 public int getSize() { 084 return dataKeys.size(); 085 } 086 087 @Override 088 public void add() { 089 dataKeys.add(new ArrayList<String>()); 090 dataValues.add(new ArrayList<String>()); 091 fireIntervalAdded(this, getSize() - 1, getSize() - 1); 092 } 093 094 @Override 095 public void remove(int idx) { 096 dataKeys.remove(idx); 097 dataValues.remove(idx); 098 fireIntervalRemoved(this, idx, idx); 099 } 100 } 101 102 private class MapTableModel extends AbstractTableModel { 103 104 private List<List<String>> data() { 105 return entryIdx == null ? Collections.<List<String>>emptyList() : Arrays.asList(dataKeys.get(entryIdx), dataValues.get(entryIdx)); 106 } 107 108 private int size() { 109 return entryIdx == null ? 0 : dataKeys.get(entryIdx).size(); 110 } 111 112 @Override 113 public int getRowCount() { 114 return entryIdx == null ? 0 : size() + 1; 115 } 116 117 @Override 118 public int getColumnCount() { 119 return 2; 120 } 121 122 @Override 123 public String getColumnName(int column) { 124 return column == 0 ? tr("Key") : tr("Value"); 125 } 126 127 @Override 128 public Object getValueAt(int row, int column) { 129 return size() == row ? "" : data().get(column).get(row); 130 } 131 132 @Override 133 public void setValueAt(Object o, int row, int column) { 134 String s = (String) o; 135 if (row == size()) { 136 data().get(0).add(""); 137 data().get(1).add(""); 138 data().get(column).set(row, s); 139 fireTableRowsInserted(row+1, row+1); 140 } else { 141 data().get(column).set(row, s); 142 fireTableCellUpdated(row, column); 143 } 144 } 145 146 @Override 147 public boolean isCellEditable(int row, int column) { 148 return true; 149 } 150 } 151 152 @Override 153 protected final AbstractEntryListModel newEntryListModel() { 154 return new EntryListModel(); 155 } 156 157 @Override 158 protected final AbstractTableModel newTableModel() { 159 return new MapTableModel(); 160 } 161}