001 // License: GPL. See LICENSE file for details.
002 package org.openstreetmap.josm.gui.preferences.advanced;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.awt.Dimension;
007 import java.awt.GridBagLayout;
008 import java.awt.event.ActionEvent;
009 import java.util.ArrayList;
010 import java.util.Collections;
011 import java.util.List;
012
013 import javax.swing.AbstractAction;
014 import javax.swing.AbstractListModel;
015 import javax.swing.DefaultCellEditor;
016 import javax.swing.JLabel;
017 import javax.swing.JList;
018 import javax.swing.JPanel;
019 import javax.swing.JScrollPane;
020 import javax.swing.JTable;
021 import javax.swing.JTextField;
022 import javax.swing.JToolBar;
023 import javax.swing.event.ListSelectionEvent;
024 import javax.swing.event.ListSelectionListener;
025 import javax.swing.table.TableCellEditor;
026 import javax.swing.table.AbstractTableModel;
027
028 import org.openstreetmap.josm.data.Preferences.ListListSetting;
029 import org.openstreetmap.josm.gui.ExtendedDialog;
030 import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
031 import org.openstreetmap.josm.gui.preferences.advanced.AdvancedPreference.PrefEntry;
032 import org.openstreetmap.josm.tools.GBC;
033 import org.openstreetmap.josm.tools.ImageProvider;
034 import org.openstreetmap.josm.tools.WindowGeometry;
035
036 public class ListListEditor extends ExtendedDialog {
037
038 EntryListModel entryModel;
039 List<List<String>> data;
040 PrefEntry entry;
041
042 JList entryList;
043 Integer entryIdx;
044 JTable table;
045
046 ListTableModel tableModel;
047
048 public ListListEditor(final PreferenceTabbedPane gui, PrefEntry entry, ListListSetting setting) {
049 super(gui, tr("Change list of lists setting"), new String[] {tr("OK"), tr("Cancel")});
050 this.entry = entry;
051 List<List<String>> orig = setting.getValue();
052 data = new ArrayList<List<String>>();
053 if (orig != null) {
054 for (List<String> l : orig) {
055 data.add(new ArrayList<String>(l));
056 }
057 }
058 setButtonIcons(new String[] {"ok.png", "cancel.png"});
059 setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(gui, new Dimension(500, 350)));
060 setContent(build(), false);
061 }
062
063 public List<List<String>> getData() {
064 return data;
065 }
066
067 protected JPanel build() {
068 JPanel p = new JPanel(new GridBagLayout());
069 p.add(new JLabel(tr("Key: {0}", entry.getKey())), GBC.std(0,0).span(2).weight(1, 0).insets(0,0,5,10));
070
071 JPanel left = new JPanel(new GridBagLayout());
072
073 entryModel = new EntryListModel();
074 entryList = new JList(entryModel);
075 entryList.getSelectionModel().addListSelectionListener(new EntryListener());
076 JScrollPane scroll = new JScrollPane(entryList);
077 left.add(scroll, GBC.eol().fill());
078
079 JToolBar sideButtonTB = new JToolBar(JToolBar.HORIZONTAL);
080 sideButtonTB.setBorderPainted(false);
081 sideButtonTB.setOpaque(false);
082 sideButtonTB.add(new NewEntryAction());
083 RemoveEntryAction removeEntryAction = new RemoveEntryAction();
084 entryList.getSelectionModel().addListSelectionListener(removeEntryAction);
085 sideButtonTB.add(removeEntryAction);
086 left.add(sideButtonTB, GBC.eol());
087
088 left.setPreferredSize(new Dimension(80, 0));
089
090 p.add(left, GBC.std(0,1).fill().weight(0.3, 1.0));
091
092 tableModel = new ListTableModel();
093 table = new JTable(tableModel);
094 table.putClientProperty("terminateEditOnFocusLost", true);
095 table.setTableHeader(null);
096
097 DefaultCellEditor editor = new DefaultCellEditor(new JTextField());
098 editor.setClickCountToStart(1);
099 table.setDefaultEditor(table.getColumnClass(0), editor);
100
101 JScrollPane pane = new JScrollPane(table);
102 pane.setPreferredSize(new Dimension(140, 0));
103 p.add(pane, GBC.std(1,1).insets(5,0,0,0).fill().weight(0.7, 1.0));
104 return p;
105 }
106
107 class EntryListModel extends AbstractListModel {
108 public Object getElementAt(int index) {
109 return (index+1) + ": " + data.get(index).toString();
110 }
111
112 public int getSize() {
113 return data.size();
114 }
115
116 public void add(List<String> l) {
117 data.add(l);
118 fireIntervalAdded(this, data.size() - 1, data.size() - 1);
119 }
120
121 public void remove(int idx) {
122 data.remove(idx);
123 fireIntervalRemoved(this, idx, idx);
124 }
125 }
126
127 class NewEntryAction extends AbstractAction {
128 public NewEntryAction() {
129 putValue(NAME, tr("New"));
130 putValue(SHORT_DESCRIPTION, tr("add entry"));
131 putValue(SMALL_ICON, ImageProvider.get("dialogs", "add"));
132 }
133
134 public void actionPerformed(ActionEvent evt) {
135 entryModel.add(new ArrayList<String>());
136 }
137 }
138
139 class RemoveEntryAction extends AbstractAction implements ListSelectionListener {
140 public RemoveEntryAction() {
141 putValue(NAME, tr("Remove"));
142 putValue(SHORT_DESCRIPTION, tr("Remove the selected entry"));
143 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
144 updateEnabledState();
145 }
146
147 protected void updateEnabledState() {
148 setEnabled(entryList.getSelectedIndices().length == 1);
149 }
150
151 public void valueChanged(ListSelectionEvent e) {
152 updateEnabledState();
153 }
154
155 public void actionPerformed(ActionEvent e) {
156 int idx = entryList.getSelectedIndices()[0];
157 entryModel.remove(idx);
158 }
159 }
160
161 class EntryListener implements ListSelectionListener {
162 public void valueChanged(ListSelectionEvent e) {
163 TableCellEditor editor = table.getCellEditor();
164 if (editor != null) {
165 ((DefaultCellEditor) editor).stopCellEditing();
166 }
167 if (entryList.getSelectedIndices().length != 1) {
168 entryIdx = null;
169 table.setEnabled(false);
170 } else {
171 entryIdx = entryList.getSelectedIndices()[0];
172 table.setEnabled(true);
173 }
174 tableModel.fireTableStructureChanged();
175 }
176 }
177
178 class ListTableModel extends AbstractTableModel {
179
180 private List<String> data() {
181 if (entryIdx == null) return Collections.emptyList();
182 return data.get(entryIdx);
183 }
184
185 @Override
186 public int getRowCount() {
187 return entryIdx == null ? 0 : data().size() + 1;
188 }
189
190 @Override
191 public int getColumnCount() {
192 return 1;
193 }
194
195 @Override
196 public Object getValueAt(int row, int column) {
197 return data().size() == row ? "" : data().get(row);
198 }
199
200 @Override
201 public void setValueAt(Object o, int row, int column) {
202 String s = (String)o;
203 if (row == data().size()) {
204 data().add(s);
205 fireTableRowsInserted(row+1, row+1);
206 } else {
207 data().set(row, s);
208 }
209 fireTableCellUpdated(row, column);
210 }
211
212 @Override
213 public boolean isCellEditable(int row, int column) {
214 return true;
215 }
216 }
217
218 }