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, K> extends BaseConverter { @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 serialize(Object t); Object deserialize(String data); } public static final PropertyConverter 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 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 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 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 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 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, String> COLOR = new BaseConverter<>() { @Override protected String serialize(Field field, ObjectProperty property) { if (property.getValue() == null) { return null; } return TimiFX.toHexString(property.getValue()); } @Override protected ObjectProperty deserialize(Field field, String data) { SimpleObjectProperty property = new SimpleObjectProperty<>(); if (data != null) { property.set(TimiFX.fromHexString(data)); } return property; } }; /** 颜色配置转换 */ public static final BaseConverter, String> PAINT = new BaseConverter<>() { @Override protected String serialize(Field field, ObjectProperty 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 deserialize(Field field, String data) { SimpleObjectProperty property = new SimpleObjectProperty<>(); if (data != null) { property.set(Paint.valueOf(data)); } return property; } }; /** 基本填充背景颜色配置转换 */ public static final BaseConverter, String> BG_FILL = new BaseConverter<>() { @Override protected String serialize(Field field, ObjectProperty 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 deserialize(Field field, String data) { SimpleObjectProperty property = new SimpleObjectProperty<>(); if (data != null) { property.set(new BgFill(data).build()); } return property; } }; public static final BaseConverter, 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 property = new SimpleObjectProperty<>(); property.set(Ref.toType((Class>) propertyGenericClass, data)); return property; } if (OBJECT_CONVERTER_MAP.containsKey(propertyGenericClass)) { SimpleObjectProperty 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, 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, 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, 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, ObjectPropertyConverter> OBJECT_CONVERTER_MAP = new HashMap<>(); public static ConfigLoader build(String path, Class clazz) { return build(path, path, clazz); } public static ConfigLoader build(String srcPath, String distPath, Class clazz) { ConfigLoader loader = new ConfigLoader<>(srcPath, distPath, clazz); addAllFXConverter(loader); return loader; } public static void addAllFXConverter(ConfigLoader loader) { for (Map.Entry, 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); } }