331 lines
9.9 KiB
Java
331 lines
9.9 KiB
Java
package com.imyeyu.fx.config;
|
|
|
|
import javafx.beans.property.BooleanProperty;
|
|
import javafx.beans.property.DoubleProperty;
|
|
import javafx.beans.property.FloatProperty;
|
|
import javafx.beans.property.IntegerProperty;
|
|
import javafx.beans.property.LongProperty;
|
|
import javafx.beans.property.ObjectProperty;
|
|
import javafx.beans.property.Property;
|
|
import javafx.beans.property.SimpleBooleanProperty;
|
|
import javafx.beans.property.SimpleDoubleProperty;
|
|
import javafx.beans.property.SimpleFloatProperty;
|
|
import javafx.beans.property.SimpleIntegerProperty;
|
|
import javafx.beans.property.SimpleLongProperty;
|
|
import javafx.beans.property.SimpleObjectProperty;
|
|
import javafx.beans.property.SimpleStringProperty;
|
|
import javafx.beans.property.StringProperty;
|
|
import javafx.collections.FXCollections;
|
|
import javafx.collections.ObservableList;
|
|
import javafx.collections.ObservableSet;
|
|
import javafx.scene.layout.Background;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.scene.paint.Paint;
|
|
import com.imyeyu.config.BaseConverter;
|
|
import com.imyeyu.config.ConfigLoader;
|
|
import com.imyeyu.fx.TimiFX;
|
|
import com.imyeyu.fx.utils.BgFill;
|
|
import com.imyeyu.java.ref.Ref;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.ParameterizedType;
|
|
import java.lang.reflect.Type;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* 配置绑定
|
|
*
|
|
* @author 夜雨
|
|
* @since 2021-10-26 10:27
|
|
*/
|
|
public final class BindingsConfig {
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @author 夜雨
|
|
* @version 2024-04-14 09:30
|
|
*/
|
|
public abstract static class PropertyConverter<T extends Property<?>, K> extends BaseConverter<T, Object> {
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
protected K serialize(Field field, T t) {
|
|
if (t.getValue() == null) {
|
|
return null;
|
|
}
|
|
return (K) t.getValue();
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @author 夜雨
|
|
* @version 2024-04-28 15:23
|
|
*/
|
|
public interface ObjectPropertyConverter<T> {
|
|
|
|
T serialize(Object t);
|
|
|
|
Object deserialize(String data);
|
|
}
|
|
|
|
public static final PropertyConverter<StringProperty, String> STRING = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected StringProperty deserialize(Field field, Object data) {
|
|
SimpleStringProperty property = new SimpleStringProperty();
|
|
if (data != null) {
|
|
property.set(data.toString());
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final PropertyConverter<IntegerProperty, Integer> INTEGER = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected IntegerProperty deserialize(Field field, Object data) {
|
|
SimpleIntegerProperty property = new SimpleIntegerProperty();
|
|
if (data != null) {
|
|
property.set(Integer.parseInt(data.toString()));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final PropertyConverter<LongProperty, Long> LONG = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected LongProperty deserialize(Field field, Object data) {
|
|
SimpleLongProperty property = new SimpleLongProperty();
|
|
if (data != null) {
|
|
property.set(Long.parseLong(data.toString()));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final PropertyConverter<DoubleProperty, Double> DOUBLE = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected DoubleProperty deserialize(Field field, Object data) {
|
|
SimpleDoubleProperty property = new SimpleDoubleProperty();
|
|
if (data != null) {
|
|
property.set(Double.parseDouble(data.toString()));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final PropertyConverter<FloatProperty, Float> FLOAT = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected FloatProperty deserialize(Field field, Object data) {
|
|
SimpleFloatProperty property = new SimpleFloatProperty();
|
|
if (data != null) {
|
|
property.set(Float.parseFloat(data.toString()));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final PropertyConverter<BooleanProperty, Boolean> BOOLEAN = new PropertyConverter<>() {
|
|
|
|
@Override
|
|
protected BooleanProperty deserialize(Field field, Object data) {
|
|
SimpleBooleanProperty property = new SimpleBooleanProperty();
|
|
if (data != null) {
|
|
property.set(Boolean.parseBoolean(data.toString()));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
|
|
/** 颜色转换,配置值格式为 0x11223344 */
|
|
public static final BaseConverter<ObjectProperty<Color>, String> COLOR = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected String serialize(Field field, ObjectProperty<Color> property) {
|
|
if (property.getValue() == null) {
|
|
return null;
|
|
}
|
|
return TimiFX.toHexString(property.getValue());
|
|
}
|
|
|
|
@Override
|
|
protected ObjectProperty<Color> deserialize(Field field, String data) {
|
|
SimpleObjectProperty<Color> property = new SimpleObjectProperty<>();
|
|
if (data != null) {
|
|
property.set(TimiFX.fromHexString(data));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
/** 颜色配置转换 */
|
|
public static final BaseConverter<ObjectProperty<Paint>, String> PAINT = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected String serialize(Field field, ObjectProperty<Paint> property) {
|
|
Paint paint = property.getValue();
|
|
if (paint == null) {
|
|
return null;
|
|
}
|
|
if (paint instanceof Color color) {
|
|
return TimiFX.toHexString(color);
|
|
}
|
|
return paint.toString();
|
|
}
|
|
|
|
@Override
|
|
protected ObjectProperty<Paint> deserialize(Field field, String data) {
|
|
SimpleObjectProperty<Paint> property = new SimpleObjectProperty<>();
|
|
if (data != null) {
|
|
property.set(Paint.valueOf(data));
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
/** 基本填充背景颜色配置转换 */
|
|
public static final BaseConverter<ObjectProperty<Background>, String> BG_FILL = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected String serialize(Field field, ObjectProperty<Background> property) {
|
|
if (property.getValue() == null || property.getValue().getFills().isEmpty()) {
|
|
return null;
|
|
}
|
|
return TimiFX.toHexString(Color.valueOf(property.getValue().getFills().getFirst().getFill().toString()));
|
|
}
|
|
|
|
@Override
|
|
protected ObjectProperty<Background> deserialize(Field field, String data) {
|
|
SimpleObjectProperty<Background> property = new SimpleObjectProperty<>();
|
|
if (data != null) {
|
|
property.set(new BgFill(data).build());
|
|
}
|
|
return property;
|
|
}
|
|
};
|
|
|
|
public static final BaseConverter<ObjectProperty<?>, String> OBJECT = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected String serialize(Field field, ObjectProperty<?> property) {
|
|
Type genericType = field.getGenericType();
|
|
if (genericType instanceof ParameterizedType pt) {
|
|
try {
|
|
Class<?> propertyGenericClass = Class.forName(pt.getActualTypeArguments()[0].getTypeName());
|
|
if (Enum.class.isAssignableFrom(propertyGenericClass)) {
|
|
if (property.get() == null) {
|
|
return null;
|
|
}
|
|
return property.get().toString();
|
|
}
|
|
if (OBJECT_CONVERTER_MAP.containsKey(propertyGenericClass)) {
|
|
return OBJECT_CONVERTER_MAP.get(propertyGenericClass).serialize(property.get()).toString();
|
|
}
|
|
} catch (ClassNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
throw new RuntimeException("未找到 " + field.getType() + " 属性转换器");
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
protected ObjectProperty<?> deserialize(Field field, String data) {
|
|
Type genericType = field.getGenericType();
|
|
if (genericType instanceof ParameterizedType pt) {
|
|
try {
|
|
Class<?> propertyGenericClass = Class.forName(pt.getActualTypeArguments()[0].getTypeName());
|
|
if (Enum.class.isAssignableFrom(propertyGenericClass)) {
|
|
SimpleObjectProperty<Object> property = new SimpleObjectProperty<>();
|
|
property.set(Ref.toType((Class<Enum<?>>) propertyGenericClass, data));
|
|
return property;
|
|
}
|
|
if (OBJECT_CONVERTER_MAP.containsKey(propertyGenericClass)) {
|
|
SimpleObjectProperty<Object> property = new SimpleObjectProperty<>();
|
|
property.set(OBJECT_CONVERTER_MAP.get(propertyGenericClass).deserialize(data));
|
|
return property;
|
|
}
|
|
} catch (ClassNotFoundException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
throw new RuntimeException("未找到 " + genericType + " 属性转换器");
|
|
}
|
|
};
|
|
|
|
public static final BaseConverter<ObservableList<?>, List<?>> OBS_LIST = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected List<?> serialize(Field field, ObservableList<?> obsList) {
|
|
return new ArrayList<>(obsList);
|
|
}
|
|
|
|
@Override
|
|
protected ObservableList<?> deserialize(Field field, List<?> list) {
|
|
if (list == null) {
|
|
list = new ArrayList<>();
|
|
}
|
|
return FXCollections.observableList(list);
|
|
}
|
|
};
|
|
|
|
public static final BaseConverter<ObservableSet<?>, Set<?>> OBS_SET = new BaseConverter<>() {
|
|
|
|
@Override
|
|
protected Set<?> serialize(Field field, ObservableSet<?> obsSet) {
|
|
return new HashSet<>(obsSet);
|
|
}
|
|
|
|
@Override
|
|
protected ObservableSet<?> deserialize(Field field, Set<?> set) {
|
|
if (set == null) {
|
|
set = new HashSet<>();
|
|
}
|
|
return FXCollections.observableSet(set);
|
|
}
|
|
};
|
|
|
|
public static final Map<Class<?>, PropertyConverter<?, ?>> DEFAULT_CONVERTER_MAP = Collections.unmodifiableMap(new HashMap<>() {{
|
|
put(StringProperty.class, STRING);
|
|
put(IntegerProperty.class, INTEGER);
|
|
put(LongProperty.class, LONG);
|
|
put(DoubleProperty.class, DOUBLE);
|
|
put(FloatProperty.class, FLOAT);
|
|
put(BooleanProperty.class, BOOLEAN);
|
|
}});
|
|
|
|
public static final Map<Class<?>, ObjectPropertyConverter<?>> OBJECT_CONVERTER_MAP = new HashMap<>();
|
|
|
|
public static <T> ConfigLoader<T> build(String path, Class<T> clazz) {
|
|
return build(path, path, clazz);
|
|
}
|
|
|
|
public static <T> ConfigLoader<T> build(String srcPath, String distPath, Class<T> clazz) {
|
|
ConfigLoader<T> loader = new ConfigLoader<>(srcPath, distPath, clazz);
|
|
addAllFXConverter(loader);
|
|
return loader;
|
|
}
|
|
|
|
public static void addAllFXConverter(ConfigLoader<?> loader) {
|
|
for (Map.Entry<Class<?>, BindingsConfig.PropertyConverter<?, ?>> item : BindingsConfig.DEFAULT_CONVERTER_MAP.entrySet()) {
|
|
loader.addConverter(item.getKey(), item.getValue());
|
|
}
|
|
loader.addConverter(ObjectProperty.class, BindingsConfig.OBJECT);
|
|
loader.addConverter(ObservableSet.class, BindingsConfig.OBS_SET);
|
|
loader.addConverter(ObservableList.class, BindingsConfig.OBS_LIST);
|
|
}
|
|
}
|