source: josm/trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java@ 12620

Last change on this file since 12620 was 12620, checked in by Don-vip, 7 years ago

see #15182 - deprecate all Main logging methods and introduce suitable replacements in Logging for most of them

File size: 9.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.tagging.presets.items;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.GridBagLayout;
8import java.awt.Insets;
9import java.text.NumberFormat;
10import java.text.ParseException;
11import java.util.Collection;
12import java.util.Collections;
13import java.util.List;
14
15import javax.swing.AbstractButton;
16import javax.swing.BorderFactory;
17import javax.swing.ButtonGroup;
18import javax.swing.JButton;
19import javax.swing.JComponent;
20import javax.swing.JLabel;
21import javax.swing.JPanel;
22import javax.swing.JToggleButton;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.data.osm.OsmPrimitive;
26import org.openstreetmap.josm.data.osm.Tag;
27import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
28import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
29import org.openstreetmap.josm.gui.widgets.JosmComboBox;
30import org.openstreetmap.josm.gui.widgets.JosmTextField;
31import org.openstreetmap.josm.tools.GBC;
32import org.openstreetmap.josm.tools.Logging;
33
34/**
35 * Text field type.
36 */
37public class Text extends KeyedItem {
38
39 private static int auto_increment_selected; // NOSONAR
40
41 /** The localized version of {@link #text}. */
42 public String locale_text; // NOSONAR
43 /** The default value for the item. If not specified, the current value of the key is chosen as default (if applicable). Defaults to "". */
44 public String default_; // NOSONAR
45 /** The original value */
46 public String originalValue; // NOSONAR
47 /** whether the last value is used as default. Using "force" enforces this behaviour also for already tagged objects. Default is "false".*/
48 public String use_last_as_default = "false"; // NOSONAR
49 /**
50 * May contain a comma separated list of integer increments or decrements, e.g. "-2,-1,+1,+2".
51 * A button will be shown next to the text field for each value, allowing the user to select auto-increment with the given stepping.
52 * Auto-increment only happens if the user selects it. There is also a button to deselect auto-increment.
53 * Default is no auto-increment. Mutually exclusive with {@link #use_last_as_default}.
54 */
55 public String auto_increment; // NOSONAR
56 /** The length of the text box (number of characters allowed). */
57 public String length; // NOSONAR
58 /** A comma separated list of alternative keys to use for autocompletion. */
59 public String alternative_autocomplete_keys; // NOSONAR
60
61 private JComponent value;
62
63 @Override
64 public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) {
65
66 // find out if our key is already used in the selection.
67 Usage usage = determineTextUsage(sel, key);
68 AutoCompletingTextField textField = new AutoCompletingTextField();
69 if (alternative_autocomplete_keys != null) {
70 initAutoCompletionField(textField, (key + ',' + alternative_autocomplete_keys).split(","));
71 } else {
72 initAutoCompletionField(textField, key);
73 }
74 if (Main.pref.getBoolean("taggingpreset.display-keys-as-hint", true)) {
75 textField.setHint(key);
76 }
77 if (length != null && !length.isEmpty()) {
78 textField.setMaxChars(Integer.valueOf(length));
79 }
80 if (usage.unused()) {
81 if (auto_increment_selected != 0 && auto_increment != null) {
82 try {
83 textField.setText(Integer.toString(Integer.parseInt(
84 LAST_VALUES.get(key)) + auto_increment_selected));
85 } catch (NumberFormatException ex) {
86 // Ignore - cannot auto-increment if last was non-numeric
87 Logging.trace(ex);
88 }
89 } else if (!usage.hadKeys() || PROP_FILL_DEFAULT.get() || "force".equals(use_last_as_default)) {
90 // selected osm primitives are untagged or filling default values feature is enabled
91 if (!presetInitiallyMatches && !"false".equals(use_last_as_default) && LAST_VALUES.containsKey(key)) {
92 textField.setText(LAST_VALUES.get(key));
93 } else {
94 textField.setText(default_);
95 }
96 } else {
97 // selected osm primitives are tagged and filling default values feature is disabled
98 textField.setText("");
99 }
100 value = textField;
101 originalValue = null;
102 } else if (usage.hasUniqueValue()) {
103 // all objects use the same value
104 textField.setText(usage.getFirst());
105 value = textField;
106 originalValue = usage.getFirst();
107 } else {
108 // the objects have different values
109 JosmComboBox<String> comboBox = new JosmComboBox<>(usage.values.toArray(new String[usage.values.size()]));
110 comboBox.setEditable(true);
111 comboBox.setEditor(textField);
112 comboBox.getEditor().setItem(DIFFERENT);
113 value = comboBox;
114 originalValue = DIFFERENT;
115 }
116 if (locale_text == null) {
117 locale_text = getLocaleText(text, text_context, null);
118 }
119
120 // if there's an auto_increment setting, then wrap the text field
121 // into a panel, appending a number of buttons.
122 // auto_increment has a format like -2,-1,1,2
123 // the text box being the first component in the panel is relied
124 // on in a rather ugly fashion further down.
125 if (auto_increment != null) {
126 ButtonGroup bg = new ButtonGroup();
127 JPanel pnl = new JPanel(new GridBagLayout());
128 pnl.add(value, GBC.std().fill(GBC.HORIZONTAL));
129
130 // first, one button for each auto_increment value
131 for (final String ai : auto_increment.split(",")) {
132 JToggleButton aibutton = new JToggleButton(ai);
133 aibutton.setToolTipText(tr("Select auto-increment of {0} for this field", ai));
134 aibutton.setMargin(new Insets(0, 0, 0, 0));
135 aibutton.setFocusable(false);
136 saveHorizontalSpace(aibutton);
137 bg.add(aibutton);
138 try {
139 // TODO there must be a better way to parse a number like "+3" than this.
140 final int buttonvalue = (NumberFormat.getIntegerInstance().parse(ai.replace("+", ""))).intValue();
141 if (auto_increment_selected == buttonvalue) aibutton.setSelected(true);
142 aibutton.addActionListener(e -> auto_increment_selected = buttonvalue);
143 pnl.add(aibutton, GBC.std());
144 } catch (ParseException ex) {
145 Logging.error("Cannot parse auto-increment value of '" + ai + "' into an integer");
146 }
147 }
148
149 // an invisible toggle button for "release" of the button group
150 final JToggleButton clearbutton = new JToggleButton("X");
151 clearbutton.setVisible(false);
152 clearbutton.setFocusable(false);
153 bg.add(clearbutton);
154 // and its visible counterpart. - this mechanism allows us to
155 // have *no* button selected after the X is clicked, instead
156 // of the X remaining selected
157 JButton releasebutton = new JButton("X");
158 releasebutton.setToolTipText(tr("Cancel auto-increment for this field"));
159 releasebutton.setMargin(new Insets(0, 0, 0, 0));
160 releasebutton.setFocusable(false);
161 releasebutton.addActionListener(e -> {
162 auto_increment_selected = 0;
163 clearbutton.setSelected(true);
164 });
165 saveHorizontalSpace(releasebutton);
166 pnl.add(releasebutton, GBC.eol());
167 value = pnl;
168 }
169 final JLabel label = new JLabel(locale_text + ':');
170 label.setToolTipText(getKeyTooltipText());
171 label.setLabelFor(value);
172 p.add(label, GBC.std().insets(0, 0, 10, 0));
173 p.add(value, GBC.eol().fill(GBC.HORIZONTAL));
174 value.setToolTipText(getKeyTooltipText());
175 return true;
176 }
177
178 private static void saveHorizontalSpace(AbstractButton button) {
179 Insets insets = button.getBorder().getBorderInsets(button);
180 // Ensure the current look&feel does not waste horizontal space (as seen in Nimbus & Aqua)
181 if (insets != null && insets.left+insets.right > insets.top+insets.bottom) {
182 int min = Math.min(insets.top, insets.bottom);
183 button.setBorder(BorderFactory.createEmptyBorder(insets.top, min, insets.bottom, min));
184 }
185 }
186
187 private static String getValue(Component comp) {
188 if (comp instanceof JosmComboBox) {
189 return ((JosmComboBox<?>) comp).getEditor().getItem().toString();
190 } else if (comp instanceof JosmTextField) {
191 return ((JosmTextField) comp).getText();
192 } else if (comp instanceof JPanel) {
193 return getValue(((JPanel) comp).getComponent(0));
194 } else {
195 return null;
196 }
197 }
198
199 @Override
200 public void addCommands(List<Tag> changedTags) {
201
202 // return if unchanged
203 String v = getValue(value);
204 if (v == null) {
205 Logging.error("No 'last value' support for component " + value);
206 return;
207 }
208
209 v = Tag.removeWhiteSpaces(v);
210
211 if (!"false".equals(use_last_as_default) || auto_increment != null) {
212 LAST_VALUES.put(key, v);
213 }
214 if (v.equals(originalValue) || (originalValue == null && v.isEmpty()))
215 return;
216
217 changedTags.add(new Tag(key, v));
218 AutoCompletionManager.rememberUserInput(key, v, true);
219 }
220
221 @Override
222 public MatchType getDefaultMatch() {
223 return MatchType.NONE;
224 }
225
226 @Override
227 public Collection<String> getValues() {
228 if (default_ == null || default_.isEmpty())
229 return Collections.emptyList();
230 return Collections.singleton(default_);
231 }
232}
Note: See TracBrowser for help on using the repository browser.