blob: e507afeb7749219f92d43c5a15f6ad05aa224978 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.openide.explorer.propertysheet;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GraphicsEnvironment;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
/** Tests that PropertyPanel honors Escape and Enter keys when
* in a dialog */
public class PropertyPanelInDialogTest extends NbTestCase {
public static Test suite() {
return GraphicsEnvironment.isHeadless() ? new TestSuite() : new TestSuite(PropertyPanelInDialogTest.class);
}
static {
ComboTest.registerPropertyEditors();
}
public PropertyPanelInDialogTest(String name) {
super(name);
}
/*
* This test creates a Property, Editor and Node. First test checks if initialized
* editor contains the same value as property. The second checks if the property
* value is changed if the same change will be done in the editor.
*/
PropertyPanel basicRen;
PropertyPanel tagsRen1;
PropertyPanel tagsRen2;
PropertyPanel tagsRen3;
PropertyPanel boolRen;
PropertyPanel custRen;
PropertyPanel custRen2;
PropertyPanel exRen;
PropertyPanel numRen;
PropertyPanel edRen;
private TNode tn;
private BasicProperty basicProp;
private TagsProperty tags1;
private TagsProperty tags2;
private TagsProperty tags3;
private BooleanProperty booleanProp;
private EditorCustom ec;
private CustomProperty customProp;
private CustomProperty customProp2;
private BasicEditor te;
private boolean setup=false;
private JFrame jf=null;
private JPanel jp=null;
private int SLEEP_LENGTH=200;
PropertyPanel[] renderers;
JButton launcher;
protected void tearDown() {
if (jf != null) {
jf.hide();
jf.dispose();
}
}
protected void setUp() throws Exception {
// UIManager.setLookAndFeel(new com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
// UIManager.setLookAndFeel(new com.sun.java.swing.plaf.gtk.GTKLookAndFeel());
if (setup) return;
// Create new TesBasicProperty
basicProp= new BasicProperty("basicProp", true);
tags1 = new TagsProperty("tags1", true, new String[] {"What","is","the","meaning","of","life"});
tags2 = new TagsProperty("tags2", true, new String[] {"NetBeans","can be ","really","cool"});
tags3 = new TagsProperty("tags3", true, new String[] {"Behold","the","power","of","cheese"});
booleanProp = new BooleanProperty("booleanProp", true);
customProp = new CustomProperty("CustomProp", true);
customProp2 = new CustomProperty("CustomProp2", true);
ExceptionProperty exProp = new ExceptionProperty("Exception prop", true);
NumProperty numProp = new NumProperty("Int prop", true);
EditableNumProperty edProp = new EditableNumProperty("Editable", true);
// Create new BasicEditor
te = new BasicEditor();
ec = new EditorCustom();
// Create new TNode
tn = new TNode();
jf = new JFrame();
jf.getContentPane().setLayout(new BorderLayout());
jp = new JPanel();
jp.setLayout(new FlowLayout());
jf.getContentPane().add(jp, BorderLayout.CENTER);
jf.setLocation(20,20);
jf.setSize(600, 200);
basicRen = new PropertyPanel(basicProp);
tagsRen1 = new PropertyPanel(tags1);
tagsRen2 = new PropertyPanel(tags2);
tagsRen3 = new PropertyPanel(tags3);
boolRen = new PropertyPanel(booleanProp);
custRen = new PropertyPanel(customProp);
custRen2 = new PropertyPanel(customProp2);
exRen = new PropertyPanel(exProp);
numRen = new PropertyPanel(numProp);
edRen = new PropertyPanel(edProp);
tagsRen2.putClientProperty("radioButtonMax", new Integer(10));
renderers = new PropertyPanel[] {
basicRen, tagsRen1, tagsRen2, boolRen, custRen, edRen, numRen
};
launcher = new JButton("Invoke dialog");
launcher.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
invokeDlg();
}
});
jf.getContentPane().add(launcher);
new WaitWindow(jf); //block until window open
jf.toFront();
ExtTestCase.requestFocus(launcher);
sleep();
Thread.currentThread().sleep(300);
sleep();
currRen = basicRen;
setup = true;
}
public void testBooleanEditor() throws Exception {
currRen = boolRen;
checkOneRenderer();
}
public void testStringEditor() throws Exception {
currRen = basicRen;
checkOneRenderer();
}
public void testComboEditor() throws Exception {
currRen = tagsRen1;
checkOneRenderer();
}
public void testEditableCombo() throws Exception {
currRen = edRen;
checkOneRenderer();
}
public void testRadioEditor() throws Exception {
currRen = tagsRen2;
checkOneRenderer();
}
PropertyPanel currRen=null;
NotifyDescriptor not = null;
Object notifyResult=null;
private void invokeDlg() {
NotifyDescriptor not = new NotifyDescriptor(currRen, "Boo!", NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE,
new Object[] {NotifyDescriptor.OK_OPTION, NotifyDescriptor.CANCEL_OPTION}, null);
notifyResult = DialogDisplayer.getDefault().notify(not);
try {
Thread.currentThread().sleep(300);
} catch (Exception e){}
ExtTestCase.waitForDialog();
}
static Boolean functioning = null;
private static final boolean canBeRun() {
if (functioning == null) {
functioning = ExtTestCase.canSafelyRunFocusTests() ? Boolean.TRUE : Boolean.FALSE;
if (Boolean.FALSE.equals(functioning)) {
System.err.println("Platform focus behavior not sane. Not " +
"running PropertyPanelInDialogTest");
}
}
return functioning.booleanValue();
}
public void checkOneRenderer() throws Exception {
if (!canBeRun()) {
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
invokeDlg();
}
});
sleep();
sleep();
ExtTestCase.waitForDialog();
while (!currRen.isVisible()) {
System.currentTimeMillis();
}
if (currRen.getProperty() != tags2) {
currRen.requestFocus();
} else {
clickOn(currRen, 80, 25);
}
if (currRen == boolRen) {
clickOn(currRen, 40, 13);
}
sleep();
ExtTestCase.waitForComponentOrChildToGetFocus(currRen);
Component focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
assertTrue("After showing dialog, focus owner should be child of renderer, but it is " + focus, currRen == focus || currRen.isAncestorOf(focus));
Container anc = null;
if (focus instanceof JComponent) {
JComponent jcp = (JComponent) focus;
anc = jcp.getTopLevelAncestor();
}
assertTrue(anc != null);
pressKey(currRen, KeyEvent.VK_ESCAPE);
releaseKey(currRen, KeyEvent.VK_ESCAPE);
typeKey(currRen, KeyEvent.VK_ESCAPE);
if (focus instanceof JComboBox) {
//do a second set, the first should just close the popup
pressKey(currRen, KeyEvent.VK_ESCAPE);
releaseKey(currRen, KeyEvent.VK_ESCAPE);
typeKey(currRen, KeyEvent.VK_ESCAPE);
}
int ct = 0;
//#47044
while (anc.isShowing()) {
System.err.println("Iter");
sleep();
if (ct++ > 1000) {
return;
}
}
sleep();
sleep();
sleep();
ExtTestCase.waitForAnythingToGetFocus();
sleep();
focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
assertTrue("After closing dialog, focus should not be null.", focus != null);
ExtTestCase.waitForFrame();
assertTrue("After closing dialog, focus should be on the button in the main frame - perhaps the dialog did not close?" + focus,
focus == launcher);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
invokeDlg();
}
});
while (!currRen.isVisible()) {
System.err.println("Waiting");
}
//clickOn(currRen);
if (currRen.getProperty() != tags2) {
clickOn(currRen);
} else {
clickOn(currRen, 80, 25);
}
if (currRen == boolRen) {
clickOn(currRen, 40, 13);
}
sleep();
sleep();
ExtTestCase.waitForComponentOrChildToGetFocus(currRen);
focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
assertTrue("After showing dialog, focus owner should be child of renderer, but it is " + focus, currRen == focus || currRen.isAncestorOf(focus));
anc = null;
if (focus instanceof JComponent) {
JComponent jcp = (JComponent) focus;
anc = jcp.getTopLevelAncestor();
}
assertTrue(anc != null);
pressKey(currRen, KeyEvent.VK_ENTER);
releaseKey(currRen, KeyEvent.VK_ENTER);
typeKey(currRen, KeyEvent.VK_ENTER);
if (focus instanceof JComboBox) {
//do a second set, the first should just close the popup
pressKey(currRen, KeyEvent.VK_ENTER);
releaseKey(currRen, KeyEvent.VK_ENTER);
typeKey(currRen, KeyEvent.VK_ENTER);
}
ct = 0;
//#47044
while (anc.isShowing()) {
System.err.println("Iter2");
sleep();
if (ct++ > 1000) {
return;
}
}
sleep();
ExtTestCase.waitForAnythingToGetFocus();
focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
assertTrue("After closing dialog, focus should not be null.", focus != null);
ExtTestCase.waitForFrame();
focus = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
assertTrue("After closing dialog, focus should be on the button in the main frame - perhaps the dialog did not close?" + focus,
focus == launcher);
}
private class FL implements FocusListener {
private FocusEvent gainedEvent=null;
private FocusEvent lostEvent=null;
private int gainedCount=0;
private int lostCount=0;
public void assertGained() {
assertNotNull("No focus gained received after clicking on an editable renderer", gainedEvent);
assertTrue("Received wrong number of focus gained events for a single click on a renderer " + gainedCount, gainedCount == 1);
}
public void assertLost() {
assertNotNull("No focus lost event received after clicking away from a focused, editable renderer", lostEvent);
assertTrue("Received wrong number of focus lost events for a single click away from a focused renderer" + lostCount, lostCount == 1);
}
public void focusGained(FocusEvent e) {
gainedEvent = e;
gainedCount++;
}
public void focusLost(FocusEvent e) {
lostEvent = e;
lostCount++;
}
}
private class CL implements ChangeListener {
private ChangeEvent e;
public void assertEvent(String msg) {
sleep(); //give the event time to happen
assertNotNull(msg, e);
e = null;
}
public void assertNoEvent(String msg) {
sleep();
assertNull(e);
e = null;
}
public void stateChanged(ChangeEvent e) {
this.e = e;
}
}
private static class TestGCVal extends Object {
public String toString() {
return "TestGCVal";
}
}
private static class WaitWindow extends WindowAdapter {
boolean shown=false;
public WaitWindow(JFrame f) {
f.addWindowListener(this);
f.show();
if (!shown) {
synchronized(this) {
try {
//System.err.println("Waiting for window");
wait(5000);
} catch (Exception e) {}
}
}
}
public void windowOpened(WindowEvent e) {
shown = true;
synchronized(this) {
//System.err.println("window opened");
notifyAll();
((JFrame) e.getSource()).removeWindowListener(this);
}
}
}
private void sleep() {
//useful when running interactively
try {
Thread.currentThread().sleep(SLEEP_LENGTH);
} catch (InterruptedException ie) {
//go away
}
//runs faster -uncomment for production use
try {
//jf.getTreeLock().wait();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.currentTimeMillis();
}
});
//jf.getTreeLock().wait();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.currentTimeMillis();
}
});
} catch (Exception e) {
}
}
private void changeProperty(PropertyPanel ren, Node.Property newProp) {
ren.setProperty(newProp);
}
private void clickOn(final PropertyPanel ren, final int fromRight, final int fromTop) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
Point toClick = new Point(ren.getWidth() - fromRight, fromTop);
Component target=ren.getComponentAt(toClick);
if (target == null) {
target = ren;
}
toClick = SwingUtilities.convertPoint(ren, toClick, target);
// System.err.println("Target component is " + target.getClass().getName() + " - " + target + " clicking at " + toClick);
MouseEvent me = new MouseEvent(target, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false);
target.dispatchEvent(me);
me = new MouseEvent(target, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false);
target.dispatchEvent(me);
me = new MouseEvent(target, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false);
}
});
sleep();
}
private void clickOn(final PropertyPanel ren) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
Point toClick = new Point(5,5);
Component target=ren.getComponentAt(toClick);
MouseEvent me = new MouseEvent(target, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false);
target.dispatchEvent(me);
}
});
sleep();
}
private void releaseKey(final Component target, final int key) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
KeyEvent ke = new KeyEvent(target, KeyEvent.KEY_RELEASED, System.currentTimeMillis(), 0, key, (char) key);
target.dispatchEvent(ke);
}
});
sleep();
}
private void pressKey(final Component target, final int key) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
KeyEvent ke = new KeyEvent(target, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, key, (char) key);
target.dispatchEvent(ke);
}
});
sleep();
}
private void shiftPressKey(final Component target, final int key) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
KeyEvent ke = new KeyEvent(target, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), KeyEvent.SHIFT_MASK, key, (char) key);
target.dispatchEvent(ke);
}
});
sleep();
}
private void typeKey(final Component target, final int key) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
KeyEvent ke = new KeyEvent(target, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, (char) key);
System.err.println("Typing key to " + target);
target.dispatchEvent(ke);
}
});
sleep();
}
//Node definition
public class TNode extends AbstractNode {
//create Node
public TNode() {
super(Children.LEAF);
setName("TNode"); // or, super.setName if needed
setDisplayName("TNode");
createSheet();
}
//clone existing Node
public Node cloneNode() {
return new TNode();
}
public void addProp(Node.Property p) {
props.put(p);
this.firePropertyChange(PROP_PROPERTY_SETS, null, null);
this.firePropertySetsChange(null, null);
}
Sheet sheet=null;
Sheet.Set props=null;
// Create a property sheet:
protected Sheet createSheet() {
sheet = super.createSheet();
// Make sure there is a "Properties" set:
props = sheet.get(Sheet.PROPERTIES);
if (props == null) {
props = Sheet.createPropertiesSet();
sheet.put(props);
}
props.put(basicProp);
props.put(tags1);
props.put(tags2);
props.put(tags3);
props.put(booleanProp);
props.put(customProp);
return sheet;
}
// Method firing changes
public void fireMethod(String s, Object o1, Object o2) {
firePropertyChange(s,o1,o2);
}
}
// Property definition
public class BasicProperty extends PropertySupport {
private Object myValue = "Value";
// Create new Property
public BasicProperty(String name, boolean isWriteable) {
super(name, Object.class, name, "", true, isWriteable);
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
Object oldVal = myValue;
myValue = value;
tn.fireMethod(getName(), oldVal, myValue);
}
// get the property editor
public PropertyEditor getPropertyEditor() {
return te;
}
}
// Editor definition
public class BasicEditor extends PropertyEditorSupport implements ExPropertyEditor {
PropertyEnv env;
// Create new BasicEditor
public BasicEditor() {
}
/*
* This method is called by the IDE to pass
* the environment to the property editor.
*/
public void attachEnv(PropertyEnv env) {
this.env = env;
}
// Set that this Editor doesn't support custom Editor
public boolean supportsCustomEditor() {
return false;
}
// Set the Property value threw the Editor
public void setValue(Object newValue) {
super.setValue(newValue);
}
public String getAsText() {
return getValue() == null ? "null" : getValue().toString();
}
}
public class TagsEditor extends PropertyEditorSupport implements ExPropertyEditor {
PropertyEnv env;
String[] tags;
public TagsEditor(String[] tags) {
this.tags = tags;
}
public String[] getTags() {
return tags;
}
public void attachEnv(PropertyEnv env) {
this.env = env;
}
public boolean supportsCustomEditor() {
return false;
}
public void setValue(Object newValue) {
super.setValue(newValue);
}
}
// Property definition
public class TagsProperty extends PropertySupport {
private Object myValue = "Value";
private String[] tags;
// Create new Property
public TagsProperty(String name, boolean isWriteable, String[] tags) {
super(name, Object.class, name, "", true, isWriteable);
this.tags = tags;
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
Object oldVal = myValue;
myValue = value;
tn.fireMethod(getName(), oldVal, myValue);
}
// get the property editor
public PropertyEditor getPropertyEditor() {
return new TagsEditor(tags);
}
public String getShortDescription() {
return "I have tags!";
}
}
// Property definition
public class BooleanProperty extends PropertySupport {
private Boolean myValue = Boolean.FALSE;
// Create new Property
public BooleanProperty(String name, boolean isWriteable) {
super(name, Boolean.class, name, "", true, isWriteable);
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
Object oldVal = myValue;
myValue = (Boolean) value;
tn.fireMethod(getName(), oldVal, myValue);
}
}
public class CustomProperty extends PropertySupport {
private Object myValue = "Value";
// Create new Property
public CustomProperty(String name, boolean isWriteable) {
super(name, Object.class, name, "", true, isWriteable);
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
Object oldVal = myValue;
myValue = value;
tn.fireMethod(getName(), oldVal, myValue);
}
// get the property editor
public PropertyEditor getPropertyEditor() {
return ec;
}
}
public class ExceptionProperty extends PropertySupport {
private Object myValue = "Value";
// Create new Property
public ExceptionProperty(String name, boolean isWriteable) {
super(name, Object.class, name, "", true, isWriteable);
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
Object oldVal = myValue;
myValue = value;
tn.fireMethod(getName(), oldVal, myValue);
}
// get the property editor
public PropertyEditor getPropertyEditor() {
return exed;
}
}
private ExEditor exed = new ExEditor();
public static class ExEditor extends PropertyEditorSupport {
private Object myVal="Value";
public ExEditor() {}
public void setAsText(String val) {
//System.err.println("SetAsText");
if (val.equals("Value")) {
myVal = val;
} else {
IllegalArgumentException iae = new IllegalArgumentException("No!");
Exceptions.attachLocalizedMessage(iae, "Localized message");
throw iae;
}
}
public void setValue(Object newValue) {
myVal = newValue;
firePropertyChange();
}
public Object getValue() {
return "Value";
}
}
// Editor definition
public class EditorCustom extends PropertyEditorSupport implements ExPropertyEditor {
PropertyEnv env;
// Create new BasicEditor
public EditorCustom() {
}
/*
* This method is called by the IDE to pass
* the environment to the property editor.
*/
public void attachEnv(PropertyEnv env) {
this.env = env;
}
// Set that this Editor doesn't support custom Editor
public boolean supportsCustomEditor() {
return true;
}
// Set the Property value threw the Editor
public void setValue(Object newValue) {
super.setValue(newValue);
}
public String getAsText() {
return getValue() == null ? "null" : getValue().toString();
}
public Component getCustomEditor() {
return new JPanel();
}
}
public class NumProperty extends PropertySupport {
private Integer myValue = new Integer(4);
// Create new Property
public NumProperty(String name, boolean isWriteable) {
super(name, Integer.class, name, "", true, isWriteable);
}
// get property value
public Object getValue() {
return myValue;
}
// set property value
public void setValue(Object value) throws IllegalArgumentException,IllegalAccessException, InvocationTargetException {
if (!(value instanceof Integer)) {
throw new IllegalArgumentException("Not an integer - " + value);
}
Object oldVal = myValue;
myValue = (Integer) value;
tn.fireMethod(getName(), oldVal, myValue);
}
// get the property editor
public PropertyEditor getPropertyEditor() {
return new NumberedTagsEditor();
}
public Object getValue(String key) {
if ("canEditAsText".equals(key)) {
return Boolean.TRUE;
} else {
return super.getValue(key);
}
}
}
public class EditableNumProperty extends TagsProperty {
public EditableNumProperty(String name, boolean isWriteable) {
super(name, isWriteable, new String[]{"boo"});
}
public PropertyEditor getPropertyEditor() {
return new PropertyPanelInDialogTest.EditableTagsEditor();
}
}
// Combo must display text, not numbers
public class NumberedTagsEditor extends PropertyEditorSupport {
private int val=3;
// Create new BasicEditor
public NumberedTagsEditor() {
}
public String[] getTags() {
return new String[] {"zero","one","two","three","four","five","six","seven"};
}
// Set the Property value threw the Editor
public void setValue(Object newValue) {
val = ((Integer) newValue).intValue();
firePropertyChange();
}
public String getAsText() {
return getTags()[((Integer) getValue()).intValue()];
}
public void setAsText(String txt) {
String[] t = getTags();
for (int i=0; i < t.length; i++) {
if (txt.trim().equals(t[i])) {
setValue(new Integer(i));
return;
}
}
IllegalArgumentException iae = new IllegalArgumentException(txt);
Exceptions.attachLocalizedMessage(iae, txt + " is not a valid value");
}
public Object getValue() {
return new Integer(val);
}
public Component getCustomEditor() {
return new JPanel();
}
}
public class EditableTagsEditor extends TagsEditor implements ExPropertyEditor {
private Object val="woof";
public EditableTagsEditor() {
super(new String[] {"miaou","woof","moo","quack"});
}
public void attachEnv(PropertyEnv env) {
env.getFeatureDescriptor().setValue("canEditAsText", Boolean.TRUE);
}
public void setAsText(String s) {
setValue(s);
}
public void setValue(Object val) {
this.val = val;
}
public Object getValue() {
return val;
}
public String getAsText() {
return val.toString();
}
}
}