source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/AdvancedPreference.java@ 4392

Last change on this file since 4392 was 4392, checked in by simon04, 13 years ago

fix #6361 - case insensitive search in advanced preference

  • Property svn:eol-style set to native
File size: 11.7 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.preferences;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Dimension;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13import java.util.Arrays;
14import java.util.ArrayList;
15import java.util.Map;
16import java.util.TreeMap;
17import java.util.TreeSet;
18import java.util.Map.Entry;
19
20import javax.swing.Box;
21import javax.swing.JButton;
22import javax.swing.JLabel;
23import javax.swing.JOptionPane;
24import javax.swing.JPanel;
25import javax.swing.JScrollPane;
26import javax.swing.JTable;
27import javax.swing.JTextField;
28import javax.swing.event.DocumentEvent;
29import javax.swing.event.DocumentListener;
30import javax.swing.table.DefaultTableCellRenderer;
31import javax.swing.table.DefaultTableModel;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.gui.ExtendedDialog;
35import org.openstreetmap.josm.tools.GBC;
36
37public class AdvancedPreference implements PreferenceSetting {
38
39 public static class Factory implements PreferenceSettingFactory {
40 public PreferenceSetting createPreferenceSetting() {
41 return new AdvancedPreference();
42 }
43 }
44
45 private Map<String,String> orig;
46 private Map<String,String> defaults;
47 private DefaultTableModel model;
48 protected Map<String, String> data;
49 protected JTextField txtFilter;
50
51 public void addGui(final PreferenceTabbedPane gui) {
52 JPanel p = gui.createPreferenceTab("advanced", tr("Advanced Preferences"),
53 tr("Setting Preference entries directly. Use with caution!"), false);
54
55 txtFilter = new JTextField();
56 JLabel lbFilter = new JLabel(tr("Search: "));
57 lbFilter.setLabelFor(txtFilter);
58 p.add(lbFilter);
59 p.add(txtFilter, GBC.eol().fill(GBC.HORIZONTAL));
60 txtFilter.getDocument().addDocumentListener(new DocumentListener(){
61 public void changedUpdate(DocumentEvent e) {
62 action();
63 }
64
65 public void insertUpdate(DocumentEvent e) {
66 action();
67 }
68
69 public void removeUpdate(DocumentEvent e) {
70 action();
71 }
72
73 private void action() {
74 dataToModel();
75 }
76 });
77
78 model = new DefaultTableModel(new String[]{tr("Key"), tr("Value")},0) {
79 @Override public boolean isCellEditable(int row, int column) {
80 return column != 0;
81 }
82 @Override public void fireTableCellUpdated(int row, int column)
83 {
84 super.fireTableCellUpdated(row, column);
85 if(column == 1)
86 {
87 data.put((String) model.getValueAt(row, 0),
88 (String) model.getValueAt(row, 1));
89 }
90 }
91
92 };
93 DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(){
94 @Override
95 public Component getTableCellRendererComponent(JTable table, Object value,
96 boolean isSelected, boolean hasFocus, int row, int column)
97 {
98 JLabel label=new JLabel();
99 String s = defaults.get(value);
100 if(s != null)
101 {
102 if(s.equals(model.getValueAt(row, 1))) {
103 label.setToolTipText(tr("Current value is default."));
104 } else {
105 label.setToolTipText(tr("Default value is ''{0}''.", s));
106 }
107 } else {
108 label.setToolTipText(tr("Default value currently unknown (setting has not been used yet)."));
109 }
110 label.setText((String)value);
111 return label;
112 }
113 };
114 final JTable list = new JTable(model);
115 list.putClientProperty("terminateEditOnFocusLost", true);
116 list.getColumn(tr("Key")).setCellRenderer(renderer);
117 JScrollPane scroll = new JScrollPane(list);
118 p.add(scroll, GBC.eol().fill(GBC.BOTH));
119 scroll.setPreferredSize(new Dimension(400,200));
120
121 orig = Main.pref.getAllPrefix("");
122 defaults = Main.pref.getDefaults();
123 orig.remove("osm-server.password");
124 defaults.remove("osm-server.password");
125 prepareData();
126 dataToModel();
127
128 JButton add = new JButton(tr("Add"));
129 p.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
130 p.add(add, GBC.std().insets(0,5,0,0));
131 add.addActionListener(new ActionListener(){
132 public void actionPerformed(ActionEvent e) {
133 addPreference(gui);
134 }
135 });
136
137 JButton edit = new JButton(tr("Edit"));
138 p.add(edit, GBC.std().insets(5,5,5,0));
139 edit.addActionListener(new ActionListener(){
140 public void actionPerformed(ActionEvent e) {
141 editPreference(gui, list);
142 }
143 });
144
145 JButton delete = new JButton(tr("Delete"));
146 p.add(delete, GBC.std().insets(0,5,0,0));
147 delete.addActionListener(new ActionListener(){
148 public void actionPerformed(ActionEvent e) {
149 removePreference(gui, list);
150 }
151 });
152
153 list.addMouseListener(new MouseAdapter(){
154 @Override public void mouseClicked(MouseEvent e) {
155 if (e.getClickCount() == 2) {
156 editPreference(gui, list);
157 }
158 }
159 });
160 }
161
162 private void prepareData() {
163 TreeSet<String> ts = new TreeSet<String>(orig.keySet());
164 for (String s : defaults.keySet())
165 {
166 if(!ts.contains(s)) {
167 ts.add(s);
168 }
169 }
170 data = new TreeMap<String, String>();
171 for (String s : ts)
172 {
173 String val = Main.pref.get(s);
174 if(val == null) {
175 val = "";
176 }
177 data.put(s, val);
178 }
179 }
180
181 private void dataToModel() {
182 while (model.getRowCount() > 0) {
183 model.removeRow(0);
184 }
185 for (String prefKey : data.keySet()) {
186 String prefValue = data.get(prefKey);
187 String input[] = txtFilter.getText().split("\\s+");
188 boolean canHas = true;
189
190 // Make 'wmsplugin cache' search for e.g. 'cache.wmsplugin'
191 final String prefKeyLower = prefKey.toLowerCase();
192 final String prefValueLower = prefValue.toLowerCase();
193 for (String bit : input) {
194 bit = bit.toLowerCase();
195 if (!prefKeyLower.contains(bit) && !prefValueLower.contains(bit)) {
196 canHas = false;
197 }
198 }
199
200 if (canHas) {
201 model.addRow(new String[] {prefKey, prefValue});
202 }
203 }
204 }
205
206 public boolean ok() {
207 for (String key : data.keySet()) {
208 String value = data.get(key);
209 if(value.length() != 0)
210 {
211 String origValue = orig.get(key);
212 if (origValue == null || !origValue.equals(value)) {
213 Main.pref.put(key, value);
214 }
215 orig.remove(key); // processed.
216 }
217 }
218 for (Entry<String, String> e : orig.entrySet()) {
219 Main.pref.put(e.getKey(), null);
220 }
221 return false;
222 }
223
224 private void removePreference(final PreferenceTabbedPane gui, final JTable list) {
225 if (list.getSelectedRowCount() == 0) {
226 JOptionPane.showMessageDialog(
227 gui,
228 tr("Please select the row to delete."),
229 tr("Warning"),
230 JOptionPane.WARNING_MESSAGE
231 );
232 return;
233 }
234 for(int row: list.getSelectedRows()) {
235 data.put((String) model.getValueAt(row, 0), "");
236 model.setValueAt("", row, 1);
237 }
238 }
239
240 private void addPreference(final PreferenceTabbedPane gui) {
241 String s[] = showEditDialog(gui, tr("Enter a new key/value pair"),
242 "", "");
243 if(s != null && !s[0].isEmpty() && !s[1].isEmpty()) {
244 data.put(s[0], s[1]);
245 dataToModel();
246 }
247 }
248
249 private void editPreference(final PreferenceTabbedPane gui, final JTable list) {
250 if (list.getSelectedRowCount() != 1) {
251 JOptionPane.showMessageDialog(
252 gui,
253 tr("Please select the row to edit."),
254 tr("Warning"),
255 JOptionPane.WARNING_MESSAGE
256 );
257 return;
258 }
259 String key = (String)model.getValueAt(list.getSelectedRow(), 0);
260 String value = data.get(key);
261 if(value.isEmpty())
262 value = defaults.get(key);
263 String s[] = showEditDialog(gui, tr("Change a key/value pair"),
264 key, value);
265 if(s != null && !s[0].isEmpty()) {
266 data.put(s[0], s[1]);
267 if(!s[0].equals(key))
268 data.put(key,"");
269 dataToModel();
270 }
271 }
272
273 private String[] showEditDialog(final PreferenceTabbedPane gui, String title,
274 String key, String value) {
275 JPanel p = new JPanel(new GridBagLayout());
276 p.add(new JLabel(tr("Key")), GBC.std().insets(0,0,5,0));
277 JTextField tkey = new JTextField(key, 50);
278 JTextField tvalue = new JTextField(value, 50);
279 p.add(tkey, GBC.eop().insets(5,0,0,0).fill(GBC.HORIZONTAL));
280 PrefValueTableModel model = new PrefValueTableModel(value);
281 p.add(new JLabel(tr("Values")), GBC.std().insets(0,0,5,0));
282 JTable table = new JTable(model);
283 table.putClientProperty("terminateEditOnFocusLost", true);
284 table.getTableHeader().setVisible(false);
285 JScrollPane pane = new JScrollPane(table);
286 Dimension d = pane.getPreferredSize();
287 d.height = (d.height/20)*(model.getRowCount()+4);
288 pane.setPreferredSize(d);
289 p.add(pane, GBC.eol().insets(5,10,0,0).fill(GBC.HORIZONTAL));
290 ExtendedDialog ed = new ExtendedDialog(gui, title,
291 new String[] {tr("OK"), tr("Cancel")});
292 ed.setButtonIcons(new String[] {"ok.png", "cancel.png"});
293 ed.setContent(p);
294 ed.showDialog();
295 if(ed.getValue() == 1) {
296 return new String[]{tkey.getText(), model.getText()};
297 }
298 return null;
299 }
300 class PrefValueTableModel extends DefaultTableModel {
301 private final ArrayList<String> data = new ArrayList<String>();
302 public PrefValueTableModel(String val) {
303 data.addAll(Arrays.asList(val.split("\u001e")));
304 setColumnIdentifiers(new String[]{""});
305 }
306
307 public String getText() {
308 String s = null;
309 for(String a : data)
310 {
311 if(s == null) {
312 s = a;
313 } else {
314 s += "\u001e" + a;
315 }
316 }
317 return s == null ? "" : s;
318 }
319
320 @Override
321 public int getRowCount() {
322 return data == null ? 1 : data.size()+1;
323 }
324
325 @Override
326 public Object getValueAt(int row, int column) {
327 return data.size() == row ? "" : data.get(row);
328 }
329
330 @Override
331 public void setValueAt(Object o, int row, int column) {
332 String s = (String)o;
333 if(row == data.size()) {
334 data.add(s);
335 fireTableRowsInserted(row+1, row+1);
336 } else {
337 data.set(row, s);
338 }
339 fireTableCellUpdated(row, column);
340 }
341
342 @Override
343 public boolean isCellEditable(int row, int column) {
344 return true;
345 }
346 }
347}
Note: See TracBrowser for help on using the repository browser.