source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/advanced/PreferencesTable.java

Last change on this file was 16960, checked in by simon04, 4 years ago

see #8334 - Add advanced option to scale the table font

Advanced preference keys gui.scale.table.*

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.advanced;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Color;
8import java.awt.Component;
9import java.awt.Font;
10import java.awt.GridBagLayout;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13import java.util.Arrays;
14import java.util.List;
15import java.util.Map;
16import java.util.Objects;
17import java.util.stream.Collectors;
18
19import javax.swing.ButtonGroup;
20import javax.swing.DefaultCellEditor;
21import javax.swing.JComponent;
22import javax.swing.JLabel;
23import javax.swing.JPanel;
24import javax.swing.JRadioButton;
25import javax.swing.JTable;
26import javax.swing.UIManager;
27import javax.swing.table.DefaultTableCellRenderer;
28import javax.swing.table.DefaultTableModel;
29
30import org.openstreetmap.josm.data.preferences.NamedColorProperty;
31import org.openstreetmap.josm.gui.ExtendedDialog;
32import org.openstreetmap.josm.gui.util.GuiHelper;
33import org.openstreetmap.josm.gui.util.TableHelper;
34import org.openstreetmap.josm.gui.widgets.JosmTextField;
35import org.openstreetmap.josm.spi.preferences.ListListSetting;
36import org.openstreetmap.josm.spi.preferences.ListSetting;
37import org.openstreetmap.josm.spi.preferences.MapListSetting;
38import org.openstreetmap.josm.spi.preferences.Setting;
39import org.openstreetmap.josm.spi.preferences.StringSetting;
40import org.openstreetmap.josm.tools.GBC;
41
42/**
43 * Component for editing list of preferences as a table.
44 * @since 6021
45 */
46public class PreferencesTable extends JTable {
47 private final AllSettingsTableModel model;
48 private final transient List<PrefEntry> displayData;
49
50 /**
51 * Constructs a new {@code PreferencesTable}.
52 * @param displayData The list of preferences entries to display
53 */
54 public PreferencesTable(List<PrefEntry> displayData) {
55 this.displayData = displayData;
56 model = new AllSettingsTableModel();
57 setModel(model);
58 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
59 getColumnModel().getColumn(1).setCellRenderer(new SettingCellRenderer());
60 getColumnModel().getColumn(1).setCellEditor(new SettingCellEditor());
61
62 TableHelper.setFont(this, getClass());
63 addMouseListener(new MouseAdapter() {
64 @Override public void mouseClicked(MouseEvent e) {
65 if (e.getClickCount() == 2) {
66 editPreference(PreferencesTable.this);
67 }
68 }
69 });
70 }
71
72 /**
73 * This method should be called when displayed data was changed form external code
74 */
75 public void fireDataChanged() {
76 model.fireTableDataChanged();
77 }
78
79 /**
80 * The list of currently selected rows
81 * @return newly created list of PrefEntry
82 */
83 public List<PrefEntry> getSelectedItems() {
84 return Arrays.stream(getSelectedRows())
85 .mapToObj(row -> (PrefEntry) model.getValueAt(row, -1))
86 .collect(Collectors.toList());
87 }
88
89 /**
90 * Call this to edit selected row in preferences table
91 * @param gui - parent component for messagebox
92 * @return true if editing was actually performed during this call
93 */
94 public boolean editPreference(final JComponent gui) {
95 if (getSelectedRowCount() != 1) {
96 return false;
97 }
98 final PrefEntry e = (PrefEntry) model.getValueAt(getSelectedRow(), 1);
99 Setting<?> stg = e.getValue();
100 boolean ok = false;
101 if (stg instanceof StringSetting) {
102 editCellAt(getSelectedRow(), 1);
103 Component editor = getEditorComponent();
104 if (editor != null) {
105 editor.requestFocus();
106 }
107 } else if (stg instanceof ListSetting) {
108 ok = doAddEditList(gui, e, (ListSetting) stg);
109 } else if (stg instanceof ListListSetting) {
110 ok = doAddEditListList(gui, e, (ListListSetting) stg);
111 } else if (stg instanceof MapListSetting) {
112 ok = doAddEditMapList(gui, e, (MapListSetting) stg);
113 }
114 return ok;
115 }
116
117 /**
118 * Add new preference to the table
119 * @param gui - parent component for asking dialogs
120 * @return newly created entry or null if adding was cancelled
121 */
122 public PrefEntry addPreference(final JComponent gui) {
123 JPanel p = new JPanel(new GridBagLayout());
124 p.add(new JLabel(tr("Key")), GBC.std().insets(0, 0, 5, 0));
125 JosmTextField tkey = new JosmTextField("", 50);
126 p.add(tkey, GBC.eop().insets(5, 0, 0, 0).fill(GBC.HORIZONTAL));
127
128 p.add(new JLabel(tr("Select Setting Type:")), GBC.eol().insets(5, 15, 5, 0));
129
130 JRadioButton rbString = new JRadioButton(tr("Simple"));
131 JRadioButton rbList = new JRadioButton(tr("List"));
132 JRadioButton rbListList = new JRadioButton(tr("List of lists"));
133 JRadioButton rbMapList = new JRadioButton(tr("List of maps"));
134
135 ButtonGroup group = new ButtonGroup();
136 group.add(rbString);
137 group.add(rbList);
138 group.add(rbListList);
139 group.add(rbMapList);
140
141 p.add(rbString, GBC.eol());
142 p.add(rbList, GBC.eol());
143 p.add(rbListList, GBC.eol());
144 p.add(rbMapList, GBC.eol());
145
146 rbString.setSelected(true);
147
148 PrefEntry pe = null;
149 boolean ok = false;
150 if (askAddSetting(gui, p)) {
151 if (rbString.isSelected()) {
152 StringSetting sSetting = new StringSetting(null);
153 pe = new PrefEntry(tkey.getText(), sSetting, sSetting, false);
154 ok = doAddSimple(gui, pe, sSetting);
155 } else if (rbList.isSelected()) {
156 ListSetting lSetting = new ListSetting(null);
157 pe = new PrefEntry(tkey.getText(), lSetting, lSetting, false);
158 ok = doAddEditList(gui, pe, lSetting);
159 } else if (rbListList.isSelected()) {
160 ListListSetting llSetting = new ListListSetting(null);
161 pe = new PrefEntry(tkey.getText(), llSetting, llSetting, false);
162 ok = doAddEditListList(gui, pe, llSetting);
163 } else if (rbMapList.isSelected()) {
164 MapListSetting mlSetting = new MapListSetting(null);
165 pe = new PrefEntry(tkey.getText(), mlSetting, mlSetting, false);
166 ok = doAddEditMapList(gui, pe, mlSetting);
167 }
168 }
169 return ok ? pe : null;
170 }
171
172 private static boolean askAddSetting(JComponent gui, JPanel p) {
173 return new ExtendedDialog(gui, tr("Add setting"), tr("OK"), tr("Cancel"))
174 .setContent(p).setButtonIcons("ok", "cancel").showDialog().getValue() == 1;
175 }
176
177 private static boolean doAddSimple(final JComponent gui, PrefEntry pe, StringSetting sSetting) {
178 StringEditor sEditor = new StringEditor(gui, pe, sSetting);
179 sEditor.showDialog();
180 if (sEditor.getValue() == 1) {
181 String data = sEditor.getData();
182 if (!Objects.equals(sSetting.getValue(), data)) {
183 pe.setValue(new StringSetting(data));
184 return true;
185 }
186 }
187 return false;
188 }
189
190 private static boolean doAddEditList(final JComponent gui, PrefEntry pe, ListSetting lSetting) {
191 ListEditor lEditor = new ListEditor(gui, pe, lSetting);
192 lEditor.showDialog();
193 if (lEditor.getValue() == 1) {
194 List<String> data = lEditor.getData();
195 if (!lSetting.equalVal(data)) {
196 pe.setValue(new ListSetting(data));
197 return true;
198 }
199 }
200 return false;
201 }
202
203 private static boolean doAddEditListList(final JComponent gui, PrefEntry pe, ListListSetting llSetting) {
204 ListListEditor llEditor = new ListListEditor(gui, pe, llSetting);
205 llEditor.showDialog();
206 if (llEditor.getValue() == 1) {
207 List<List<String>> data = llEditor.getData();
208 if (!llSetting.equalVal(data)) {
209 pe.setValue(new ListListSetting(data));
210 return true;
211 }
212 }
213 return false;
214 }
215
216 private static boolean doAddEditMapList(final JComponent gui, PrefEntry pe, MapListSetting mlSetting) {
217 MapListEditor mlEditor = new MapListEditor(gui, pe, mlSetting);
218 mlEditor.showDialog();
219 if (mlEditor.getValue() == 1) {
220 List<Map<String, String>> data = mlEditor.getData();
221 if (!mlSetting.equalVal(data)) {
222 pe.setValue(new MapListSetting(data));
223 return true;
224 }
225 }
226 return false;
227 }
228
229 /**
230 * Reset selected preferences to their default values
231 * @param gui - parent component to display warning messages
232 */
233 public void resetPreferences(final JComponent gui) {
234 if (getSelectedRowCount() == 0) {
235 return;
236 }
237 for (int row : getSelectedRows()) {
238 PrefEntry e = displayData.get(row);
239 e.reset();
240 }
241 fireDataChanged();
242 }
243
244 final class AllSettingsTableModel extends DefaultTableModel {
245
246 AllSettingsTableModel() {
247 setColumnIdentifiers(new String[]{tr("Key"), tr("Value")});
248 }
249
250 @Override
251 public boolean isCellEditable(int row, int column) {
252 return column == 1 && (displayData.get(row).getValue() instanceof StringSetting);
253 }
254
255 @Override
256 public int getRowCount() {
257 return displayData.size();
258 }
259
260 @Override
261 public Object getValueAt(int row, int column) {
262 if (column == 0)
263 return displayData.get(row).getKey();
264 else
265 return displayData.get(row);
266 }
267
268 @Override
269 public void setValueAt(Object o, int row, int column) {
270 PrefEntry pe = displayData.get(row);
271 String s = (String) o;
272 if (!s.equals(pe.getValue().getValue())) {
273 pe.setValue(new StringSetting(s));
274 fireTableCellUpdated(row, column);
275 }
276 }
277 }
278
279 static final class SettingCellRenderer extends DefaultTableCellRenderer {
280 private final Color backgroundColor = UIManager.getColor("Table.background");
281 private final Color changedColor = new NamedColorProperty(
282 marktr("Advanced Background: Changed"),
283 new Color(200, 255, 200)).get();
284 private final Color nonDefaultColor = new NamedColorProperty(
285 marktr("Advanced Background: NonDefault"),
286 new Color(255, 255, 200)).get();
287
288 @Override
289 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
290 if (value == null)
291 return this;
292 PrefEntry pe = (PrefEntry) value;
293 Setting<?> setting = pe.getValue();
294 Object val = setting.getValue();
295 String display = val != null ? val.toString() : "<html><i>&lt;"+tr("unset")+"&gt;</i></html>";
296
297 JLabel label = (JLabel) super.getTableCellRendererComponent(table,
298 display, isSelected, hasFocus, row, column);
299
300 GuiHelper.setBackgroundReadable(label, backgroundColor);
301 if (pe.isChanged()) {
302 GuiHelper.setBackgroundReadable(label, changedColor);
303 } else if (!pe.isDefault()) {
304 GuiHelper.setBackgroundReadable(label, nonDefaultColor);
305 }
306
307 if (!pe.isDefault()) {
308 label.setFont(label.getFont().deriveFont(Font.BOLD));
309 }
310 val = pe.getDefaultValue().getValue();
311 if (val != null) {
312 if (pe.isDefault()) {
313 label.setToolTipText(tr("Current value is default."));
314 } else {
315 label.setToolTipText(tr("Default value is ''{0}''.", val));
316 }
317 } else {
318 label.setToolTipText(tr("Default value currently unknown (setting has not been used yet)."));
319 }
320 return label;
321 }
322 }
323
324 static final class SettingCellEditor extends DefaultCellEditor {
325 SettingCellEditor() {
326 super(new JosmTextField());
327 }
328
329 @Override
330 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
331 PrefEntry pe = (PrefEntry) value;
332 StringSetting stg = (StringSetting) pe.getValue();
333 String s = stg.getValue() == null ? "" : stg.getValue();
334 return super.getTableCellEditorComponent(table, s, isSelected, row, column);
335 }
336 }
337}
Note: See TracBrowser for help on using the repository browser.