/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * 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.configure; import java.awt.Color; import java.awt.Component; import java.awt.Image; import java.awt.Window; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.KeyStroke; import VASSAL.build.AutoConfigurable; import VASSAL.build.Configurable; import VASSAL.build.GameModule; import VASSAL.tools.NamedKeyStroke; import VASSAL.tools.ReflectionUtils; /** * A Configurer for configuring Configurable components * (Is that as redundant as it sounds?) * Automatically builds a property editor with controls for setting all * of the attributes of the target Configurable component */ public class AutoConfigurer extends Configurer implements PropertyChangeListener { protected JPanel p; protected AutoConfigurable target; protected List<Configurer> configurers = new ArrayList<Configurer>(); protected Map<String,VisibilityCondition> conditions; public AutoConfigurer(AutoConfigurable c) { super(null, c.getConfigureName()); target = c; setValue(target); target.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(final PropertyChangeEvent evt) { if (Configurable.NAME_PROPERTY.equals(evt.getPropertyName())) { setName((String) evt.getNewValue()); } } }); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); String[] name = c.getAttributeNames(); String[] prompt = c.getAttributeDescriptions(); Class<?>[] type = c.getAttributeTypes(); int n = Math.min(name.length, Math.min(prompt.length, type.length)); for (int i = 0; i < n; ++i) { if (type[i] == null) { continue; } Configurer config; config = createConfigurer(type[i], name[i], prompt[i], target); if (config != null) { config.addPropertyChangeListener(this); config.setValue(target.getAttributeValueString(name[i])); Box box = Box.createHorizontalBox(); box.add(config.getControls()); box.add(Box.createHorizontalGlue()); p.add(box); configurers.add(config); } setVisibility(name[i],c.getAttributeVisibility(name[i])); } } public static Configurer createConfigurer(Class<?> type, String key, String prompt, AutoConfigurable target) { Configurer config = null; if (String.class.isAssignableFrom(type)) { config = new StringConfigurer(key, prompt); } else if (Integer.class.isAssignableFrom(type)) { config = new IntConfigurer(key, prompt); } else if (Double.class.isAssignableFrom(type)) { config = new DoubleConfigurer(key, prompt); } else if (Boolean.class.isAssignableFrom(type)) { config = new BooleanConfigurer(key, prompt); } else if (Image.class.isAssignableFrom(type)) { config = new ImageConfigurer(key, prompt, GameModule.getGameModule().getArchiveWriter()); } else if (Color.class.isAssignableFrom(type)) { config = new ColorConfigurer(key, prompt); } else if (KeyStroke.class.isAssignableFrom(type)) { config = new HotKeyConfigurer(key, prompt); } else if (NamedKeyStroke.class.isAssignableFrom(type)) { config = new NamedHotKeyConfigurer(key, prompt); } else if (File.class.isAssignableFrom(type)) { config = new FileConfigurer(key, prompt, GameModule.getGameModule().getArchiveWriter()); } else if (String[].class.isAssignableFrom(type)) { config = new StringArrayConfigurer(key, prompt); } else if (Icon.class.isAssignableFrom(type)) { config = new IconConfigurer(key,prompt,null); } else if (PropertyExpression.class.isAssignableFrom(type)) { config = new PropertyExpressionConfigurer(key, prompt); } else if (StringEnum.class.isAssignableFrom(type)) { StringEnum se = null; try { se = (StringEnum) type.getConstructor().newInstance(); } catch (Throwable t) { ReflectionUtils.handleNewInstanceFailure(t, type); config = new StringConfigurer(key, prompt); } if (se != null) { final String[] validValues = se.getValidValues(target); config = new StringEnumConfigurer(key, prompt, validValues); } } else if (ConfigurerFactory.class.isAssignableFrom(type)) { ConfigurerFactory cf = null; try { cf = (ConfigurerFactory) type.getConstructor().newInstance(); } catch (Throwable t) { ReflectionUtils.handleNewInstanceFailure(t, type); } if (cf != null) { config = cf.getConfigurer(target, key, prompt); } } else { throw new IllegalArgumentException("Invalid class " + type.getName()); } return config; } public void reset() { String[] s = target.getAttributeNames(); for (int i = 0; i < s.length; ++i) { Configurer config = getConfigurer(s[i]); if (config != null) { config.setValue(target.getAttributeValueString(s[i])); } } } public String getValueString() { return target.getConfigureName(); } public void setValue(String s) { throw new UnsupportedOperationException( "Can't set Configurable from String"); } public Component getControls() { return p; } public void propertyChange(final PropertyChangeEvent evt) { target.setAttribute(evt.getPropertyName(), evt.getNewValue()); checkVisibility(); } public void setVisibility(String attribute, VisibilityCondition c) { if (c != null) { if (conditions == null) { conditions = new HashMap<String,VisibilityCondition>(); } conditions.put(attribute, c); checkVisibility(); } } protected void checkVisibility() { boolean visChanged = false; if (conditions != null) { for (Configurer c : configurers) { VisibilityCondition cond = conditions.get(c.getKey()); if (cond != null) { if (c.getControls().isVisible() != cond.shouldBeVisible()) { visChanged = true; c.getControls().setVisible(cond.shouldBeVisible()); } } } // Only repack the configurer if an item visiblity has changed. if (visChanged && p.getTopLevelAncestor() instanceof Window) { ((Window) p.getTopLevelAncestor()).pack(); } } } public Configurer getConfigurer(String attribute) { for (Configurer c : configurers) { if (attribute.equals(c.getKey())) { return c; } } return null; } }