001: package net.suberic.util.gui.propedit;
002:
003: import javax.swing.*;
004: import net.suberic.util.*;
005: import java.awt.FlowLayout;
006: import java.awt.event.*;
007: import java.util.*;
008:
009: /**
010: * An EditorPane which allows a user to select from a list of choices.
011: */
012: public class ListEditorPane extends SwingPropertyEditor {
013: protected int originalIndex;
014: protected String mOriginalValue;
015: protected JLabel label;
016: protected JComboBox inputField;
017: JButton addButton;
018: protected HashMap labelToValueMap = new HashMap();
019: protected int currentIndex = -1;
020:
021: /**
022: * @param propertyName The property to be edited.
023: * @param template The property that will define the layout of the
024: * editor.
025: * @param manager The PropertyEditorManager that will manage the
026: * changes.
027: * @param isEnabled Whether or not this editor is enabled by default.
028: */
029: public void configureEditor(String propertyName, String template,
030: PropertyEditorManager newManager, boolean isEnabled) {
031: property = propertyName;
032: manager = newManager;
033: editorTemplate = template;
034:
035: label = createLabel();
036:
037: inputField = createComboBox();
038:
039: Box inputBox = new Box(BoxLayout.X_AXIS);
040: inputField.setPreferredSize(inputField.getMinimumSize());
041: inputField.setMaximumSize(inputField.getMinimumSize());
042: inputBox.add(inputField);
043: inputBox.add(Box.createGlue());
044: if (manager.getProperty(editorTemplate + "._includeAddButton",
045: "false").equalsIgnoreCase("true")) {
046: addButton = createAddButton();
047: inputBox.add(addButton);
048: }
049:
050: this .add(label);
051: this .add(inputBox);
052: this .setEnabled(isEnabled);
053:
054: labelComponent = label;
055: valueComponent = inputBox;
056: //valueComponent.setLayout(new FlowLayout(FlowLayout.LEFT));
057: //valueComponent.add(inputField);
058: manager.registerPropertyEditor(property, this );
059:
060: // if we're showing something other than the actually configured
061: // value, fire an event.
062: if (isChanged()) {
063: String newValue = (String) labelToValueMap.get(inputField
064: .getSelectedItem());
065: try {
066: firePropertyChangingEvent(newValue);
067: firePropertyChangedEvent(newValue);
068: } catch (PropertyValueVetoException pvve) {
069: manager.getFactory().showError(
070: inputField,
071: "Error changing value " + label.getText()
072: + " to " + newValue + ": "
073: + pvve.getReason());
074: inputField.setSelectedIndex(currentIndex);
075: }
076: }
077: }
078:
079: /**
080: * Creates the JComboBox with the appropriate options.
081: */
082: protected JComboBox createComboBox() {
083: String originalValue = manager.getProperty(property, "");
084: // we set this to the real original value, rather than the default
085: // value if none is set.
086: mOriginalValue = originalValue;
087: // now we get the default value.
088: if (originalValue.equalsIgnoreCase(""))
089: originalValue = manager.getProperty(editorTemplate, "");
090: String currentItem;
091: originalIndex = -1;
092: Vector items = new Vector();
093: StringTokenizer tokens;
094:
095: String allowedValuesString = manager.getProperty(editorTemplate
096: + ".allowedValues", "");
097: if (manager.getProperty(allowedValuesString, "") != "") {
098: tokens = new StringTokenizer(manager.getProperty(
099: allowedValuesString, ""), ":");
100: manager.addPropertyEditorListener(allowedValuesString,
101: new ListEditorListener());
102: } else {
103: tokens = new StringTokenizer(manager.getProperty(
104: editorTemplate + ".allowedValues", ""), ":");
105: }
106:
107: for (int i = 0; tokens.hasMoreTokens(); i++) {
108: currentItem = tokens.nextToken();
109:
110: String itemLabel = manager.getProperty(editorTemplate
111: + ".listMapping." + currentItem.toString()
112: + ".label", "");
113: if (itemLabel.equals(""))
114: itemLabel = currentItem.toString();
115:
116: String itemValue = manager.getProperty(editorTemplate
117: + ".listMapping." + currentItem.toString()
118: + ".value", "");
119: if (itemValue.equals(""))
120: itemValue = currentItem.toString();
121:
122: if (itemValue.equals(originalValue)) {
123: originalIndex = i;
124: currentIndex = i;
125: }
126: items.add(itemLabel);
127: labelToValueMap.put(itemLabel, itemValue);
128: }
129:
130: if (originalIndex == -1) {
131: items.add(originalValue);
132: labelToValueMap.put(originalValue, originalValue);
133: originalIndex = items.size() - 1;
134: }
135:
136: JComboBox jcb = new JComboBox(items);
137: jcb.setSelectedIndex(originalIndex);
138:
139: jcb.addItemListener(new ItemListener() {
140: public void itemStateChanged(ItemEvent e) {
141: int newIndex = inputField.getSelectedIndex();
142: if (newIndex != currentIndex) {
143: String newValue = (String) labelToValueMap
144: .get(inputField.getSelectedItem());
145: try {
146: firePropertyChangingEvent(newValue);
147: firePropertyChangedEvent(newValue);
148: currentIndex = newIndex;
149: } catch (PropertyValueVetoException pvve) {
150: manager.getFactory().showError(
151: inputField,
152: "Error changing value "
153: + label.getText() + " to "
154: + newValue + ": "
155: + pvve.getReason());
156: inputField.setSelectedIndex(currentIndex);
157: }
158: }
159: }
160: });
161:
162: return jcb;
163: }
164:
165: /**
166: * Updates the combo box with the new value(s).
167: */
168: private void updateComboBox(String newValue) {
169: Vector items = new Vector();
170: StringTokenizer tokens = new StringTokenizer(newValue, ":");
171: String currentValue = (String) inputField.getSelectedItem();
172:
173: String currentItem;
174: for (int i = 0; tokens.hasMoreTokens(); i++) {
175: currentItem = tokens.nextToken();
176:
177: String itemLabel = manager.getProperty(editorTemplate
178: + ".listMapping." + currentItem.toString()
179: + ".label", "");
180: if (itemLabel.equals(""))
181: itemLabel = currentItem.toString();
182:
183: String itemValue = manager.getProperty(editorTemplate
184: + ".listMapping." + currentItem.toString()
185: + ".value", "");
186: if (itemValue.equals(""))
187: itemValue = currentItem.toString();
188:
189: if (itemValue.equals(originalValue)) {
190: originalIndex = i;
191: }
192: if (itemValue.equals(currentValue)) {
193: currentIndex = i;
194: }
195: items.add(itemLabel);
196: labelToValueMap.put(itemLabel, itemValue);
197: }
198:
199: ComboBoxModel newModel = new DefaultComboBoxModel(items);
200: newModel.setSelectedItem(currentValue);
201: inputField.setModel(newModel);
202:
203: }
204:
205: /**
206: * Creates a button to add a new value to the List.
207: */
208: public JButton createAddButton() {
209: JButton returnValue = new JButton("Add");
210: returnValue.addActionListener(new AbstractAction() {
211: public void actionPerformed(ActionEvent e) {
212: addNewEntry();
213: }
214: });
215:
216: return returnValue;
217: }
218:
219: /**
220: * Opens up an editor to add a new Item to the List.
221: */
222: public void addNewEntry() {
223: String editedProperty = manager.getProperty(editorTemplate
224: + ".allowedValues", "");
225: Vector v = new Vector();
226: v.add(editedProperty);
227: manager.getFactory().showNewEditorWindow("Add property", v, v,
228: manager);
229: }
230:
231: // as defined in net.suberic.util.gui.PropertyEditorUI
232:
233: /**
234: * This writes the currently configured value in the PropertyEditorUI
235: * to the source VariableBundle.
236: */
237: public void setValue() {
238: int newIndex = inputField.getSelectedIndex();
239: String currentValue = (String) labelToValueMap.get(inputField
240: .getSelectedItem());
241: try {
242: if (newIndex != currentIndex) {
243: firePropertyChangingEvent(currentValue);
244: firePropertyChangedEvent(currentValue);
245: currentIndex = newIndex;
246: }
247:
248: if (isEnabled() && isChanged()) {
249: manager.setProperty(property, currentValue);
250: }
251: } catch (PropertyValueVetoException pvve) {
252: manager.getFactory().showError(
253: inputField,
254: "Error changing value " + label.getText() + " to "
255: + currentValue + ": " + pvve.getReason());
256: inputField.setSelectedIndex(currentIndex);
257: }
258: }
259:
260: /**
261: * Returns the current values of the edited properties as a
262: * java.util.Properties object.
263: */
264: public java.util.Properties getValue() {
265: java.util.Properties retProps = new java.util.Properties();
266:
267: retProps.setProperty(property, (String) labelToValueMap
268: .get(inputField.getSelectedItem()));
269:
270: return retProps;
271: }
272:
273: /**
274: * This resets the editor to the original (or latest set, if setValue()
275: * has been called) value of the edited property.
276: */
277: public void resetDefaultValue() {
278: // this will be handled by the ItemListener we have on the inputField,
279: // so we don't have to notify listeners here.
280:
281: inputField.setSelectedIndex(originalIndex);
282: }
283:
284: /**
285: * Returns whether or not the current list selection has changed from
286: * the last save.
287: */
288: public boolean isChanged() {
289: if (mOriginalValue == null)
290: return (mOriginalValue != (String) labelToValueMap
291: .get(inputField.getSelectedItem()));
292: else
293: return (!mOriginalValue.equals((String) labelToValueMap
294: .get(inputField.getSelectedItem())));
295:
296: }
297:
298: /**
299: * Sets the enabled property of the PropertyEditorUI. Disabled
300: * editors should not be able to do setValue() calls.
301: */
302: public void setEnabled(boolean newValue) {
303: if (inputField != null) {
304: inputField.setEnabled(newValue);
305: }
306: if (addButton != null) {
307: addButton.setEnabled(newValue);
308: }
309: enabled = newValue;
310: }
311:
312: /**
313: * This listens to the property that it currently providing the list
314: * of allowed values for this List. If it changes, then the allowed
315: * values list also is updated.
316: */
317: public class ListEditorListener extends PropertyEditorAdapter {
318:
319: /**
320: * Called after a property changes.
321: */
322: public void propertyChanged(PropertyEditorUI ui,
323: String property, String newValue) {
324: updateComboBox(newValue);
325: }
326:
327: }
328: }
|