/* * $Id$ * * Copyright (c) 2006-2012 by Rodney Kinney, Brent Easton * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.build.module.properties; import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import javax.swing.BoxLayout; import javax.swing.JPanel; import VASSAL.build.module.gamepieceimage.StringEnumConfigurer; import VASSAL.configure.Configurer; import VASSAL.configure.FormattedExpressionConfigurer; import VASSAL.configure.FormattedStringArrayConfigurer; import VASSAL.configure.StringArrayConfigurer; import VASSAL.configure.StringConfigurer; import VASSAL.tools.SequenceEncoder; /** * Configurer instance that allows a module editor to specify a * PropertyChanger, i.e. the way in which a dynamic property will be * updated by a player during a game * * @author rkinney * */ public class PropertyChangerConfigurer extends Configurer { protected static final String PLAIN_TYPE = "Set value directly"; protected static final String INCREMENT_TYPE = "Increment numeric value"; protected static final String PROMPT_TYPE = "Prompt user"; protected static final String SELECT_TYPE = "Prompt user to select from list"; protected static final char PLAIN_CODE = 'P'; protected static final char PROMPT_CODE = 'R'; protected static final char ENUM_CODE = 'E'; protected static final char INCR_CODE = 'I'; protected static final Map<Class<? extends PropertyChanger>,Character> typeToCode = new HashMap<Class<? extends PropertyChanger>,Character>(); protected static final Map<Class<? extends PropertyChanger>,String> typeToDescription = new HashMap<Class<? extends PropertyChanger>,String>(); protected static final Map<String,Character> descriptionToCode = new HashMap<String,Character>(); static { typeToCode.put(PropertySetter.class, PLAIN_CODE); typeToCode.put(PropertyPrompt.class, PROMPT_CODE); typeToCode.put(NumericPropertyPrompt.class, PROMPT_CODE); typeToCode.put(IncrementProperty.class, INCR_CODE); typeToCode.put(EnumeratedPropertyPrompt.class, ENUM_CODE); typeToDescription.put(PropertySetter.class, PLAIN_TYPE); typeToDescription.put(PropertyPrompt.class, PROMPT_TYPE); typeToDescription.put(NumericPropertyPrompt.class, PROMPT_TYPE); typeToDescription.put(IncrementProperty.class, INCREMENT_TYPE); typeToDescription.put(EnumeratedPropertyPrompt.class, SELECT_TYPE); descriptionToCode.put(PLAIN_TYPE, PLAIN_CODE); descriptionToCode.put(INCREMENT_TYPE, INCR_CODE); descriptionToCode.put(PROMPT_TYPE, PROMPT_CODE); descriptionToCode.put(SELECT_TYPE, ENUM_CODE); } protected Constraints constraints; protected JPanel controls; protected StringEnumConfigurer typeConfig; protected FormattedExpressionConfigurer valueConfig; protected StringConfigurer promptConfig; protected FormattedExpressionConfigurer incrConfig; protected StringArrayConfigurer validValuesConfig; public PropertyChangerConfigurer(String key, String name, Constraints constraints) { super(key, name); this.constraints = constraints; setValue(new PropertySetter("", null)); } public Component getControls() { if (controls == null) { PropertyChangeListener l = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { updateValue(); updateControls(); } }; controls = new JPanel(); controls.setLayout(new BoxLayout(controls, BoxLayout.X_AXIS)); typeConfig = new StringEnumConfigurer(null, "Type: ", new String[]{PLAIN_TYPE, INCREMENT_TYPE, PROMPT_TYPE, SELECT_TYPE}); typeConfig.addPropertyChangeListener(l); valueConfig = new FormattedExpressionConfigurer(null, "New Value: ", "", constraints); valueConfig.addPropertyChangeListener(l); promptConfig = new StringConfigurer(null, "Prompt: "); promptConfig.addPropertyChangeListener(l); incrConfig = new FormattedExpressionConfigurer(null, "Increment by: ", "", constraints); incrConfig.addPropertyChangeListener(l); validValuesConfig = new FormattedStringArrayConfigurer(null, "Valid Values", constraints); validValuesConfig.addPropertyChangeListener(l); controls.add(typeConfig.getControls()); controls.add(valueConfig.getControls()); controls.add(promptConfig.getControls()); controls.add(incrConfig.getControls()); controls.add(validValuesConfig.getControls()); updateControls(); } return controls; } protected void updateControls() { PropertyChanger pc = getPropertyChanger(); typeConfig.setValue(typeToDescription.get(pc.getClass())); if (pc instanceof PropertySetter) { valueConfig.setValue(((PropertySetter) pc).getRawValue()); valueConfig.getControls().setVisible(true); } else { valueConfig.getControls().setVisible(false); } if (pc instanceof IncrementProperty) { incrConfig.setValue(String.valueOf(((IncrementProperty) pc).getIncrement())); incrConfig.getControls().setVisible(true); } else { incrConfig.getControls().setVisible(false); } if (pc instanceof PropertyPrompt) { promptConfig.setValue(((PropertyPrompt) pc).getPrompt()); promptConfig.getControls().setVisible(true); } else { promptConfig.getControls().setVisible(false); } if (pc instanceof EnumeratedPropertyPrompt) { validValuesConfig.setValue(((EnumeratedPropertyPrompt) pc).getValidValues()); validValuesConfig.getControls().setVisible(true); } else { validValuesConfig.getControls().setVisible(false); } } protected void updateValue() { PropertyChanger p; switch (descriptionToCode.get(typeConfig.getValueString()).charValue()) { case PROMPT_CODE: p = new PropertyPrompt(constraints, promptConfig.getValueString()); break; case INCR_CODE: p = new IncrementProperty(this, incrConfig.getValueString(), constraints); break; case ENUM_CODE: p = new EnumeratedPropertyPrompt( constraints, promptConfig.getValueString(), validValuesConfig.getStringArray(), constraints ); break; case PLAIN_CODE: default: p = new PropertySetter(valueConfig.getValueString(), constraints); } setValue(p); } public String getValueString() { PropertyChanger propChanger = getPropertyChanger(); SequenceEncoder se = new SequenceEncoder(','); if (propChanger != null) { switch (typeToCode.get(propChanger.getClass()).charValue()) { case PROMPT_CODE: se.append(PROMPT_CODE) .append(((PropertyPrompt) propChanger).getPrompt()); break; case INCR_CODE: se.append(INCR_CODE) .append(((IncrementProperty) propChanger).getIncrement()); break; case ENUM_CODE: se.append(ENUM_CODE) .append(((PropertyPrompt) propChanger).getPrompt()) .append(((EnumeratedPropertyPrompt) propChanger).getValidValues()); break; case PLAIN_CODE: se.append(PLAIN_CODE) .append(((PropertySetter) propChanger).getRawValue()); } } return se.getValue(); } public PropertyChanger getPropertyChanger() { return (PropertyChanger) getValue(); } public void setValue(String s) { PropertyChanger p; if (s == null || s.length() == 0) { s = Character.toString(PLAIN_CODE); } SequenceEncoder.Decoder sd = new SequenceEncoder.Decoder(s, ','); switch (sd.nextChar(PLAIN_CODE)) { case PROMPT_CODE: p = new PropertyPrompt(constraints, sd.nextToken("Enter new value")); break; case INCR_CODE: p = new IncrementProperty(this, sd.nextToken("1"), constraints); break; case ENUM_CODE: p = new EnumeratedPropertyPrompt(constraints, sd.nextToken("Select new value"), sd.nextStringArray(0), constraints); break; case PLAIN_CODE: default: p = new PropertySetter(sd.nextToken("new value"), constraints); } setValue(p); } public static interface Constraints extends PropertyPrompt.Constraints, IncrementProperty.Constraints, PropertySource { } }