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

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

major code cleanup/refactoring of tagging presets: slay the monster TaggingPresetItems (60 Kb, 1600 lines) and extract all its internal classes to a new package gui.tagging.presets.items

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