From 2041d6564531fe794072ddfe345773de1cab60a3 Mon Sep 17 00:00:00 2001 From: Reino Ruusu Date: Mon, 25 Nov 2019 13:50:14 +0200 Subject: [PATCH] Reflection-based handling of Enum property editing. gitlab #57 Change-Id: Ifab41fbf38d1e56b36fc561763ce9200cd18c358 --- .../property/ComboPropertyManipulator.java | 38 ++++++++++++++++--- .../DefaultPropertyManipulatorFactory.java | 2 + .../property/MethodComboValueProvider.java | 32 +++++++++++++++- .../g3d/property/MethodValueProvider.java | 6 +++ .../property/MethodWithMapValueProvider.java | 10 +++++ .../simantics/g3d/property/ValueProvider.java | 2 +- 6 files changed, 81 insertions(+), 9 deletions(-) diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/ComboPropertyManipulator.java b/org.simantics.g3d/src/org/simantics/g3d/property/ComboPropertyManipulator.java index 45a3b99a..a1ea44c3 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/ComboPropertyManipulator.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/ComboPropertyManipulator.java @@ -2,6 +2,8 @@ package org.simantics.g3d.property; import java.util.List; +import org.simantics.utils.datastructures.Arrays; + public class ComboPropertyManipulator implements PropertyManipulator{ ComboValueProvider provider; @@ -29,9 +31,20 @@ public class ComboPropertyManipulator implements PropertyManipulator{ @Override public String getValue(int i) { try { - Integer value = (Integer)provider.getValue(input); - if (value == null) return null; - return getItems()[value]; + Object rawValue = provider.getValue(input); + if (rawValue == null) { + return null; + } + else if (rawValue instanceof Integer) { + Integer value = (Integer)rawValue; + return getItems()[value]; + } + else if (rawValue instanceof Enum) { + return rawValue.toString(); + } + else { + return null; + } } catch (Exception e) { return null; } @@ -40,7 +53,14 @@ public class ComboPropertyManipulator implements PropertyManipulator{ @Override public String setValue(String value, int i) { try { - provider.setValue(input, Integer.parseInt(value)); + int intValue = Integer.parseInt(value); + Class valueType = provider.getValueType(); + if (Enum.class.isAssignableFrom(valueType)) { + provider.setValue(input, valueType.getEnumConstants()[intValue]); + } + else { + provider.setValue(input, intValue); + } } catch (Exception e) { return e.getMessage(); } @@ -72,8 +92,14 @@ public class ComboPropertyManipulator implements PropertyManipulator{ public Integer getValueIndex() { try { - Integer value = (Integer)provider.getValue(input); - return value; + Object value = provider.getValue(input); + Class valueType = provider.getValueType(); + if (valueType.isEnum()) { + return Arrays.indexOf(valueType.getEnumConstants(), value); + } + else { + return (Integer) value; + } } catch (Exception e) { return null; } diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/DefaultPropertyManipulatorFactory.java b/org.simantics.g3d/src/org/simantics/g3d/property/DefaultPropertyManipulatorFactory.java index 1ad89945..5d7e121d 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/DefaultPropertyManipulatorFactory.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/DefaultPropertyManipulatorFactory.java @@ -45,6 +45,8 @@ public class DefaultPropertyManipulatorFactory implements PropertyManipulatorFac return BooleanPropertyManipulator.class; if (double[].class.equals(returnValue)) return DoubleArrayPropertyManipulator.class; + if (returnValue.isEnum()) + return ComboPropertyManipulator.class; throw new RuntimeException("Cannot handle value " + returnValue.getName() + " for method " + get); } diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/MethodComboValueProvider.java b/org.simantics.g3d/src/org/simantics/g3d/property/MethodComboValueProvider.java index c1e21e07..0408235f 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/MethodComboValueProvider.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/MethodComboValueProvider.java @@ -12,8 +12,11 @@ package org.simantics.g3d.property; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.List; +import org.simantics.utils.datastructures.Arrays; + public class MethodComboValueProvider implements ComboValueProvider { Method getter; @@ -28,14 +31,39 @@ public class MethodComboValueProvider implements ComboValueProvider { @Override public Object getValue(Object obj) throws Exception{ - return getter.invoke(obj); + if (getValueType().isEnum()) { + Object value = getter.invoke(obj); + Object[] vs = getValueType().getEnumConstants(); + return (Integer) Arrays.indexOf(vs, value); + } + else { + return getter.invoke(obj); + } } @Override public void setValue(Object obj, Object value) throws Exception { setter.invoke(obj,value); } + @SuppressWarnings("unchecked") public List getValues(Object obj) throws Exception { - return (List)values.invoke(obj); + if (values != null) { + return (List)values.invoke(obj); + } + else if (getValueType().isEnum()) { + Object[] enumConstants = getValueType().getEnumConstants(); + List result = new ArrayList<>(enumConstants.length); + for (Object c : enumConstants) + result.add(c); + return result; + } + else { + throw new IllegalStateException("No value list defined for " + getter.toString()); + } + } + + @Override + public Class getValueType() { + return getter.getReturnType(); } } diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/MethodValueProvider.java b/org.simantics.g3d/src/org/simantics/g3d/property/MethodValueProvider.java index 016e1fe3..212ff36b 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/MethodValueProvider.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/MethodValueProvider.java @@ -27,8 +27,14 @@ public class MethodValueProvider implements ValueProvider { public Object getValue(Object obj) throws Exception{ return getter.invoke(obj); } + @Override public void setValue(Object obj, Object value) throws Exception { setter.invoke(obj,value); } + + @Override + public Class getValueType() { + return getter.getReturnType(); + } } diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/MethodWithMapValueProvider.java b/org.simantics.g3d/src/org/simantics/g3d/property/MethodWithMapValueProvider.java index eeae0dc8..8fad8897 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/MethodWithMapValueProvider.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/MethodWithMapValueProvider.java @@ -12,6 +12,8 @@ package org.simantics.g3d.property; import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; @@ -33,6 +35,7 @@ public class MethodWithMapValueProvider implements ValueProvider { Map map = (Map)getter.invoke(obj); return map.get(key); } + @SuppressWarnings("unchecked") @Override public void setValue(Object obj, Object value) throws Exception { @@ -41,4 +44,11 @@ public class MethodWithMapValueProvider implements ValueProvider { map.put(key, value); setter.invoke(obj,map); } + + @Override + public Class getValueType() { + // The return type of the getter should be a java.util.Map. + Type[] typeArguments = ((ParameterizedType)getter.getGenericReturnType()).getActualTypeArguments(); + return (Class) typeArguments[1]; + } } diff --git a/org.simantics.g3d/src/org/simantics/g3d/property/ValueProvider.java b/org.simantics.g3d/src/org/simantics/g3d/property/ValueProvider.java index 94169617..2471d5f3 100644 --- a/org.simantics.g3d/src/org/simantics/g3d/property/ValueProvider.java +++ b/org.simantics.g3d/src/org/simantics/g3d/property/ValueProvider.java @@ -16,5 +16,5 @@ public interface ValueProvider { Object getValue(Object obj) throws Exception; void setValue(Object obj, Object value) throws Exception; - + Class getValueType(); } -- 2.47.0