package tools.map.making;
import java.awt.Color;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.JFrame;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.data.properties.AEditableProperty;
import games.strategy.engine.data.properties.BooleanProperty;
import games.strategy.engine.data.properties.CollectionProperty;
import games.strategy.engine.data.properties.ColorProperty;
import games.strategy.engine.data.properties.ComboProperty;
import games.strategy.engine.data.properties.DoubleProperty;
import games.strategy.engine.data.properties.FileProperty;
import games.strategy.engine.data.properties.IEditableProperty;
import games.strategy.engine.data.properties.MapProperty;
import games.strategy.engine.data.properties.NumberProperty;
import games.strategy.engine.data.properties.PropertiesUI;
import games.strategy.engine.data.properties.StringProperty;
import games.strategy.util.PropertyUtil;
import games.strategy.util.Tuple;
/**
* This will take ANY object, and then look at every method that begins with 'set[name]' and if there also exists a
* method 'get[name]'
* and a field '[name]' which is public, then it will take these and create an editable UI component
* for each of these based on the games.strategy.engine.data.properties classes.
*
* @param <T>
* parameters can be: Boolean, String, Integer, Double, Color, File, Collection, Map
*/
@SuppressWarnings("unchecked")
public class MapPropertyWrapper<T> extends AEditableProperty {
private static final long serialVersionUID = 6406798101396215624L;
private IEditableProperty property;
// private final Class m_clazz;
// private final T m_defaultValue;
private final Method setter;
private final Method getter;
public MapPropertyWrapper(final String name, final String description, final T defaultValue, final Method setter,
final Method getter) {
super(name, description);
// m_clazz = clazz;
this.setter = setter;
this.getter = getter;
// m_defaultValue = defaultValue;
if (defaultValue instanceof Boolean) {
property = new BooleanProperty(name, description, ((Boolean) defaultValue));
} else if (defaultValue instanceof Color) {
property = new ColorProperty(name, description, ((Color) defaultValue));
} else if (defaultValue instanceof File) {
property = new FileProperty(name, description, ((File) defaultValue));
} else if (defaultValue instanceof String) {
property = new StringProperty(name, description, ((String) defaultValue));
} else if (defaultValue instanceof Collection || defaultValue instanceof List || defaultValue instanceof Set) {
property = new CollectionProperty<>(name, description, ((Collection<?>) defaultValue));
} else if (defaultValue instanceof Map || defaultValue instanceof HashMap) {
property = new MapProperty<>(name, description, ((Map<?, ?>) defaultValue));
} else if (defaultValue instanceof Integer) {
property =
new NumberProperty(name, description, Integer.MAX_VALUE, Integer.MIN_VALUE, ((Integer) defaultValue));
} else if (defaultValue instanceof Double) {
property =
new DoubleProperty(name, description, Double.MAX_VALUE, Double.MIN_VALUE, ((Double) defaultValue), 5);
} else {
throw new IllegalArgumentException(
"Cannot instantiate PropertyWrapper with: " + defaultValue.getClass().getCanonicalName());
}
}
public MapPropertyWrapper(final String name, final String description, final T defaultValue,
final Collection<T> possibleValues, final Method setter, final Method getter) {
super(name, description);
// m_clazz = clazz;
this.setter = setter;
this.getter = getter;
// m_defaultValue = defaultValue;
if (defaultValue instanceof Collection) {
property = new ComboProperty<>(name, description, defaultValue, possibleValues);
} else {
throw new IllegalArgumentException(
"Cannot instantiate PropertyWrapper with: " + defaultValue.getClass().getCanonicalName());
}
}
public MapPropertyWrapper(final String name, final String description, final int max, final int min,
final int defaultValue, final Method setter, final Method getter) {
super(name, description);
// m_clazz = clazz;
this.setter = setter;
this.getter = getter;
// m_defaultValue = defaultValue;
property = new NumberProperty(name, description, max, min, defaultValue);
}
public MapPropertyWrapper(final String name, final String description, final double max, final double min,
final double defaultValue, final int places, final Method setter, final Method getter) {
super(name, description);
// m_clazz = clazz;
this.setter = setter;
this.getter = getter;
// m_defaultValue = defaultValue;
property = new DoubleProperty(name, description, max, min, defaultValue, places);
}
public MapPropertyWrapper(final String name, final String description, final File defaultValue,
final String[] acceptableSuffixes, final Method setter, final Method getter) {
super(name, description);
// m_clazz = clazz;
this.setter = setter;
this.getter = getter;
// m_defaultValue = defaultValue;
property = new FileProperty(name, description, defaultValue, acceptableSuffixes);
}
@Override
public int getRowsNeeded() {
return property.getRowsNeeded();
}
@Override
public Object getValue() {
return property.getValue();
}
public T getValueT() {
return (T) property.getValue();
}
@Override
public void setValue(final Object value) throws ClassCastException {
property.setValue(value);
}
public void setValueT(final T value) {
property.setValue(value);
}
@Override
public JComponent getEditorComponent() {
return property.getEditorComponent();
}
public T getFromObject(final Object object) {
try {
return (T) getter.invoke(object);
} catch (final IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
ClientLogger.logQuietly(e);
}
return null;
}
public void setToObject(final Object object) {
final Object value = getValue();
final Object[] args = {value};
try {
System.out.println(setter + " to " + value);
setter.invoke(object, args);
} catch (final IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
ClientLogger.logQuietly(e);
}
}
private static List<MapPropertyWrapper<?>> createProperties(final Object object) {
final List<MapPropertyWrapper<?>> properties = new ArrayList<>();
for (final Method setter : object.getClass().getMethods()) {
final boolean startsWithSet = setter.getName().startsWith("set");
if (!startsWithSet) {
continue;
}
final String propertyName =
setter.getName().substring(Math.min(3, setter.getName().length()), setter.getName().length());
final Method getter;
try {
getter = object.getClass().getMethod("get" + propertyName);
} catch (final SecurityException e) {
ClientLogger.logQuietly(e);
continue;
} catch (final NoSuchMethodException e) {
ClientLogger.logQuietly(e);
continue;
}
final String fieldName = Introspector.decapitalize(propertyName);
final Field field = PropertyUtil.getFieldIncludingFromSuperClasses(object.getClass(), fieldName, false);
final Object currentValue;
try {
currentValue = field.get(object);
} catch (final IllegalArgumentException e) {
ClientLogger.logQuietly(e);
continue;
} catch (final IllegalAccessException e) {
ClientLogger.logQuietly(e);
continue;
}
try {
final MapPropertyWrapper<?> wrapper =
new MapPropertyWrapper<>(propertyName, null, currentValue, setter, getter);
properties.add(wrapper);
} catch (final Exception e) {
ClientLogger.logQuietly(e);
}
}
properties.sort((o1, o2) -> o1.getName().compareTo(o2.getName()));
return properties;
}
public static void writePropertiesToObject(final Object object, final List<MapPropertyWrapper<?>> properties) {
for (final MapPropertyWrapper<?> p : properties) {
p.setToObject(object);
}
}
public static PropertiesUI createPropertiesUI(final List<? extends IEditableProperty> properties,
final boolean editable) {
return new PropertiesUI(properties, editable);
}
public static Tuple<PropertiesUI, List<MapPropertyWrapper<?>>> createPropertiesUI(final Object object,
final boolean editable) {
final List<MapPropertyWrapper<?>> properties = createProperties(object);
final PropertiesUI ui = new PropertiesUI(properties, editable);
return Tuple.of(ui, properties);
}
@Override
public boolean validate(final Object value) {
return property.validate(value);
}
public static void main(final String[] args) {
final MapProperties mapProperties = new MapProperties();
final List<MapPropertyWrapper<?>> properties = createProperties(mapProperties);
final PropertiesUI ui = createPropertiesUI(properties, true);
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(ui);
frame.pack();
frame.setVisible(true);
}
}