JavaFX-Plus v1.beta

This commit is contained in:
billkiller
2019-06-29 01:34:10 +08:00
commit f1eb3e57ec
111 changed files with 6484 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
/**
* This is use for marking A controller as FX-Plus Controller
* @Author jack
* @Date:2019/6/25 1:34
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface FXController {
String path();
double preWidth() default 0.0;
double preHeight() default 0.0;
}

View File

@@ -0,0 +1,15 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author jack
* @Date:2019/6/25 1:35
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FXEntity {
}

View File

@@ -0,0 +1,20 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author jack
* @Date:2019/6/27 20:10
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FXField {
boolean readOnly() default false;
String setter() default "";
String add() default "";
String delete() default "";
String edit() default "";
}

View File

@@ -0,0 +1,14 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
/**
* @Author jack
* @Date:2019/6/25 13:06
*/
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.METHOD)
public @interface FXReceiver {
String name();
}

View File

@@ -0,0 +1,16 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author jack
* @Date:2019/6/25 2:55
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FXScan {
String[] base() default ".";
}

View File

@@ -0,0 +1,38 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This cn.edu.scau.biubiusuisui.annotation is used for a method which can send a signal to all consumer
* And FXSender has a name which is used for identifying different method
* It is legal to use same method which has same name because JavaFX-Plus will identify a method with its full class name
* In addition ,name is optional , default name will be the class name and method name
* you can use this cn.edu.scau.biubiusuisui.annotation as the following cn.edu.scau.biubiusuisui.example
* @FXSernder
* public class A{
* public void test(){
*
* }
* }
* name will be A.name(It will only contain base class name and this name)
* or you can use
* @FXSernder("testDemo")
* public class A{
* public void test(){
*
* }
* }
* name will be A.testDemo
*
* @Author jack
* @Date:2019/6/25 13:02
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FXSender {
String name()default "";
}

View File

@@ -0,0 +1,9 @@
package cn.edu.scau.biubiusuisui.annotation;
/**
* @Author jack
* @Date:2019/6/25 1:36
*/
public @interface FXView {
}

View File

@@ -0,0 +1,16 @@
package cn.edu.scau.biubiusuisui.annotation;
import java.lang.annotation.*;
/**
* @Author jack
* @Date:2019/6/25 1:36
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface FXWindow {
double preWidth() default 0.0;
double preHeight()default 0.0;
String title () ;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
package cn.edu.scau.biubiusuisui.config;
import cn.edu.scau.biubiusuisui.annotation.FXScan;
import cn.edu.scau.biubiusuisui.factory.FXFactory;
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
import java.util.List;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
/**
* @Author jack
* @Date:2019/6/25 2:54
*/
public class FXPlusApplication {
public static void start(Class clazz){
Annotation []annotations = clazz.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(FXScan.class.equals(annotation.annotationType())){
String []dirs = ((FXScan)annotation).base();
Set<String> sets = new HashSet<>();
for(String dir : dirs){
sets.add(dir);
}
Set<String> classNames = new HashSet<>();
for(String dir:sets){
ClassUtils classUtils = new ClassUtils();
List<String> temps = classUtils.scanAllClassName(dir);
for(String className:temps){
try {
loadFXPlusClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
private static void loadFXPlusClass(String className) throws ClassNotFoundException {
Class clazz = Class.forName(className);
FXFactory.loadFXController(clazz);
}
}

View File

@@ -0,0 +1,97 @@
package cn.edu.scau.biubiusuisui.entity;
import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus;
import javafx.fxml.Initializable;
import javafx.scene.layout.Pane;
import cn.edu.scau.biubiusuisui.utils.StringUtils;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @Author jack
* @Date:2019/6/25 5:51
*/
/**
* In JavaFX-Plus Framework Controller
* We use MVC model
* V means view which stand for fxml
* C means controller which stand for FXBaseController instance
* M means model which is base cn.edu.scau.biubiusuisui.entity in your program
* Every BaseController has a name which is used for identifying different <strong>instance</strong>
*
*/
public class FXBaseController extends Pane {
protected String name = "";
private boolean isController = false;
private boolean isWindows = false;
public FXBaseController(String name){
this.name = name;
}
public FXBaseController(){
FXController fxController = null;
Annotation[] annotations = getClass().getAnnotations();
// Find FXController cn.edu.scau.biubiusuisui.annotation
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(FXController.class)) {
fxController = (FXController) annotation;
isController = true;
}
}
//load fxml file to show panel in scene builder
if(isController) {
FXMLLoaderPlus fxmlLoader = new FXMLLoaderPlus(getClass().getClassLoader().getResource(fxController.path()));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void initialize() {
}
public String getName() {
if("".equals(name)){
return StringUtils.getBaseClassName(getClass().getSimpleName());
}else{
return StringUtils.getBaseClassName(getClass().getSimpleName()) +"#"+name;
}
}
public void doInit(){}
public void setName(String name) {
this.name = name;
}
public boolean isController() {
return isController;
}
public void setController(boolean controller) {
isController = controller;
}
public boolean isWindows() {
return isWindows;
}
public void setWindows(boolean windows) {
isWindows = windows;
}
}

View File

@@ -0,0 +1,38 @@
package cn.edu.scau.biubiusuisui.entity;
import java.lang.reflect.Method;
/**
* @Author jack
* @Date:2019/6/28 10:03
*/
public class FXFieldMethodMapping {
private Method setMethod ;
private Method addMethod ;
private Method delMethod;
public Method getSetMethod() {
return setMethod;
}
public void setSetMethod(Method setMethod) {
this.setMethod = setMethod;
}
public Method getAddMethod() {
return addMethod;
}
public void setAddMethod(Method addMethod) {
this.addMethod = addMethod;
}
public Method getDelMethod() {
return delMethod;
}
public void setDelMethod(Method delMethod) {
this.delMethod = delMethod;
}
}

View File

@@ -0,0 +1,38 @@
package cn.edu.scau.biubiusuisui.entity;
import java.lang.reflect.Method;
/**
* This class is base cn.edu.scau.biubiusuisui.entity for queue message(or signal)
* you mush save the instance and method which means who will run this method
* @Author jack
* @Date:2019/6/26 15:39
*/
public class FXMethodEntity {
private FXBaseController fxBaseController;
private Method method;
public FXMethodEntity(FXBaseController fxBaseController, Method method) {
this.fxBaseController = fxBaseController;
this.method = method;
}
public FXBaseController getFxBaseController() {
return fxBaseController;
}
public void setFxBaseController(FXBaseController fxBaseController) {
this.fxBaseController = fxBaseController;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
}

View File

@@ -0,0 +1,52 @@
package cn.edu.scau.biubiusuisui.entity;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXEntityProxy;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* Context is use for storing Controller
* In addition,you can store an instance into Session to use it everywhere
*
* @Author jack
* @Date:2019/6/26 12:28
*/
public class FXPlusContext {
private FXPlusContext(){}
private static Map<String, List<FXBaseController>> controllerContext = new ConcurrentHashMap<>();
private static Map<Object, FXEntityProxy> beanProxyMap = new ConcurrentHashMap<>();
public static void addController(FXBaseController fxBaseController){
List<FXBaseController> controllers = controllerContext.get(fxBaseController.getName());
if(controllers == null){
controllers = new LinkedList<>();
}
controllers.add(fxBaseController);
}
public static List<FXBaseController> getControllers(String key){
return controllerContext.get(key);
}
public static FXEntityProxy getProryByBeanObject(Object object){
return beanProxyMap.get(object);
}
public static void setProxyByBeanObject(Object object,FXEntityProxy fxEntityProxy){
beanProxyMap.put(object,fxEntityProxy);
}
public static Map<Object, FXEntityProxy> getBeanProxyMap() {
return beanProxyMap;
}
public static void setBeanProxyMap(Map<Object, FXEntityProxy> beanProxyMap) {
FXPlusContext.beanProxyMap = beanProxyMap;
}
}

View File

@@ -0,0 +1,18 @@
package cn.edu.scau.biubiusuisui.example;
import cn.edu.scau.biubiusuisui.annotation.FXScan;
import cn.edu.scau.biubiusuisui.config.FXPlusApplication;
import javafx.application.Application;
import javafx.stage.Stage;
/**
* @Author jack
* @Date:2019/6/25 7:05
*/
@FXScan(base = {"cn.edu.scau.biubiusuisui.example"})
public class Demo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
FXPlusApplication.start(Demo.class);
}
}

View File

@@ -0,0 +1,55 @@
package cn.edu.scau.biubiusuisui.example;
import cn.edu.scau.biubiusuisui.annotation.*;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.factory.FXEntityFactory;
import cn.edu.scau.biubiusuisui.factory.FXFactory;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXEntityProxy;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import java.net.URL;
import java.util.ResourceBundle;
/**
* @Author jack
* @Date:2019/6/25 1:47
*/
@FXController(path = "Main.fxml")
@FXWindow(title = "demo1")
public class MainController extends FXBaseController{
@FXML
Button btn;
@FXML
Label label;
Student student;
int count = 1;
@Override
public void initialize() {
student = (Student) FXEntityFactory.getInstance().createJavaBeanProxy(Student.class); //工厂产生一个学生
student.setName("Jack"); //设置学生姓名
FXEntityProxy fxEntityProxy = FXPlusContext.getProryByBeanObject(student); //获取学生代理
Property nameProperty = fxEntityProxy.getPropertyByFieldName("name"); //获取Bean对应的Property
label.textProperty().bind(nameProperty); //属性绑定
}
@FXML
@FXSender
public String send(){
student.setName("Jack :" + count);
count++;
return "sending msg";
}
}

View File

@@ -0,0 +1,53 @@
package cn.edu.scau.biubiusuisui.example;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.annotation.FXField;
/**
* @Author jack
* @Date:2019/6/27 20:02
*/
@FXEntity
public class Student {
@FXField
private String name;
private int age;
private String gender;
private String code;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@@ -0,0 +1,11 @@
package cn.edu.scau.biubiusuisui.exception;
/**
* @Author jack
* @Date:2019/6/25 7:23
*/
public class ProtocolNotSupport extends Exception{
public ProtocolNotSupport(){
super("protocolNotSupport");
}
}

View File

@@ -0,0 +1,186 @@
package cn.edu.scau.biubiusuisui.factory;
import cn.edu.scau.biubiusuisui.annotation.FXField;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.function.DefaultEventFunction;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXEntityProxy;
import cn.edu.scau.biubiusuisui.utils.ClassUtils;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @Author jack
* @Date:2019/6/28 1:12
*/
public class FXEntityFactory {
private FXEntityFactory(){}
private static FXEntityFactory instance = null;
ChangeListener propertyChangeEvent = new DefaultEventFunction();
public synchronized static FXEntityFactory getInstance() {
if(instance == null){
instance = new FXEntityFactory();
}
return instance;
}
public Object createJavaBeanProxy(Class clazz) {
Object object = null;
try {
object = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return createJavaBeanProxy(object);
}
public Object createJavaBeanProxy(Object object){
FXEntityProxy fxEntityProxy = new FXEntityProxy();
Object objectProxy = null;
try {
objectProxy = fxEntityProxy.getInstance(object);
Map<String, Property> stringPropertyMap = FXEntityFactory.getInstance().getEntityProperty(object,objectProxy);
fxEntityProxy.setStringPropertyMap(stringPropertyMap);
FXPlusContext.setProxyByBeanObject(objectProxy, fxEntityProxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return objectProxy;
}
public Map<String, Property> getEntityProperty(Object entity,Object proxy) throws IllegalAccessException {
Map<String, Property> stringPropertyMap = new HashMap<>();
Field []fields = entity.getClass().getDeclaredFields();
for(Field field:fields){
Annotation annotation = ClassUtils.getAnnotationInList( FXField.class,field.getDeclaredAnnotations());
if(annotation != null){
Property property;
field.setAccessible(true);
FXField fxField = (FXField)annotation;
if(field.get(entity) == null){
if(fxField.readOnly()){
property = getReadOnlyFieldDefalutProperty(field);
}else{
property = getFieldDefalutProperty(field);
}
}else{
if(fxField.readOnly()){
property = getReadOnlyProperty(entity,field);
}else{
property = getFieldProperty(entity, field);
}
}
if(property !=null) {
//添加时间;
property.addListener((object,oldVal,newVal)->{
try {
field.set(proxy, newVal);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
stringPropertyMap.put(field.getName(), property);
}
}
}
return stringPropertyMap;
}
private static Property getFieldProperty(Object object,Field field) throws IllegalAccessException {
Class type = field.getType();
Object value = field.get(object);
Property property = null;
if(Boolean.class.equals(type)){
property = new SimpleBooleanProperty((Boolean) value);
}else if(Double.class.equals(type)){
property = new SimpleDoubleProperty((Double) value);
}else if (Float.class.equals(type)){
property = new SimpleFloatProperty((Float) value);
}else if(Integer.class.equals(type)){
property = new SimpleIntegerProperty((Integer) value);
}else if(Long.class.equals(type)){
property = new SimpleLongProperty((Long) value);
}else if(String.class.equals(type)){
property = new SimpleStringProperty((String) value);
}
return property;
}
private static Property getFieldDefalutProperty(Field field) throws IllegalAccessException{
Class type = field.getType();
Property property = null;
if(Boolean.class.equals(type)){
property = new SimpleBooleanProperty();
}else if(Double.class.equals(type)){
property = new SimpleDoubleProperty();
}else if (Float.class.equals(type)){
property = new SimpleFloatProperty();
}else if(Integer.class.equals(type)){
property = new SimpleIntegerProperty();
}else if(Long.class.equals(type)){
property = new SimpleLongProperty();
}else if(String.class.equals(type)){
property = new SimpleStringProperty();
}
return property;
}
private static Property getReadOnlyFieldDefalutProperty(Field field) throws IllegalAccessException{
Class type = field.getType();
Property property = null;
if(Boolean.class.equals(type)){
property = new ReadOnlyBooleanWrapper();
}else if(Double.class.equals(type)){
property = new ReadOnlyDoubleWrapper();
}else if (Float.class.equals(type)){
property = new ReadOnlyFloatWrapper();
}else if(Integer.class.equals(type)){
property = new ReadOnlyIntegerWrapper();
}else if(Long.class.equals(type)){
property = new ReadOnlyLongWrapper();
}else if(String.class.equals(type)){
property = new ReadOnlyStringWrapper();
}
return property;
}
private static Property getReadOnlyProperty(Object object,Field field) throws IllegalAccessException {
Class type = field.getType();
Object value = field.get(object);
Property property = null;
if(Boolean.class.equals(type)){
property = new ReadOnlyBooleanWrapper((Boolean) value);
}else if(Double.class.equals(type)){
property = new ReadOnlyDoubleWrapper((Double) value);
}else if (Float.class.equals(type)){
property = new ReadOnlyFloatWrapper((Float) value);
}else if(Integer.class.equals(type)){
property = new ReadOnlyIntegerWrapper((Integer) value);
}else if(Long.class.equals(type)){
property = new ReadOnlyLongWrapper((Long) value);
}else if(String.class.equals(type)){
property = new ReadOnlyStringWrapper((String) value);
}
return property;
}
private static Method getFieldMethodMapping(Object object ,Field field){
Class clazz = object.getClass();
return null;
}
}

View File

@@ -0,0 +1,117 @@
package cn.edu.scau.biubiusuisui.factory;
import cn.edu.scau.biubiusuisui.annotation.FXController;
import cn.edu.scau.biubiusuisui.annotation.FXWindow;
import cn.edu.scau.biubiusuisui.config.FXMLLoaderPlus;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue;
import cn.edu.scau.biubiusuisui.proxy.classProxy.FXControllerProxy;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
/**
* @Author jack
* @Date:2019/6/25 8:12
*/
public class FXFactory {
private FXFactory() {
}
public static void loadFXController(Class clazz) {
getFXController(clazz, "");
}
public static FXBaseController getFXController(Class clazz) {
FXBaseController fxBaseController = getFXController(clazz, "");
return fxBaseController;
}
public static FXBaseController getFXController(Class clazz, String controllerName) {
FXBaseController fxBaseController = getFxBaseController(clazz, controllerName);
return fxBaseController;
}
private static void register(FXBaseController fxBaseController, FXBaseController fxBaseControllerProxy) {
FXPlusContext.addController(fxBaseController);
MessageQueue.getInstance().registerCosumer(fxBaseController, fxBaseControllerProxy);
}
/**
*
* @param clazz instance that extends by FXBaseController
* @param controllerName
* @return
*/
private static FXBaseController getFxBaseController(Class clazz, String controllerName) {
Annotation[] annotations = clazz.getAnnotations();
Boolean isController = false;
URL fxmlPath;
Boolean isWindow = false;
FXWindow fxWindow = null;
FXController fxController = null;
//reflect and get FXController cn.edu.scau.biubiusuisui.annotation
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(FXController.class)) {
fxController = (FXController) annotation;
isController = true;
} else if (annotation.annotationType().equals(FXWindow.class)) {
fxWindow = (FXWindow) annotation;
isWindow = true;
}
}
Pane parent = null;
FXBaseController fxControllerProxy = null;
FXBaseController fxBaseController = null;
if (isController) {
String name = fxController.path();
fxmlPath = clazz.getClassLoader().getResource(name);
FXMLLoaderPlus fxmlLoader = new FXMLLoaderPlus(fxmlPath);
try {
// create a cn.edu.scau.biubiusuisui.proxy for monitoring methods
fxBaseController = (FXBaseController) clazz.newInstance();
FXControllerProxy controllerProxy = new FXControllerProxy();
fxControllerProxy = (FXBaseController) controllerProxy.getInstance(fxBaseController);
fxControllerProxy.setName(controllerName);
fxBaseController.setName(controllerName);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
fxmlLoader.setRoot(fxControllerProxy);
fxmlLoader.setController(fxControllerProxy);
try {
parent = fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}else{
return null;
}
//register
register(fxBaseController, fxControllerProxy);
if (isWindow) {
Stage stage = new Stage();
double preWidth = fxWindow.preWidth() == 0 ? parent.getPrefWidth() : fxWindow.preWidth();
double preHeight = fxWindow.preHeight() == 0 ? parent.getPrefWidth() : fxWindow.preHeight();
Scene scene = new Scene(fxControllerProxy, preWidth, preHeight);
stage.setScene(scene);
stage.setTitle(fxWindow.title());
stage.show();
}
return fxControllerProxy;
}
}

View File

@@ -0,0 +1,19 @@
package cn.edu.scau.biubiusuisui.function;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
/**
* @Author jack
* @Date:2019/6/28 15:57
*/
public class DefaultEventFunction implements ChangeListener {
public DefaultEventFunction() {}
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
}
}

View File

@@ -0,0 +1,82 @@
package cn.edu.scau.biubiusuisui.messageQueue;
import cn.edu.scau.biubiusuisui.annotation.FXReceiver;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.entity.FXMethodEntity;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author jack
* @Date:2019/6/25 12:24
*/
public class MessageQueue {
private static Map<String, List<FXMethodEntity>> receivers = new ConcurrentHashMap<>();
private static MessageQueue messageQueue = null;
private MessageQueue(){ }
public static synchronized MessageQueue getInstance(){
if(messageQueue == null){
messageQueue = new MessageQueue();
}
return messageQueue;
}
public void registerCosumer(FXBaseController fxBaseController,FXBaseController fxBaseControllerProxy){
Class clazz = fxBaseController.getClass();
Method [] methods = clazz.getDeclaredMethods();
for(Method method : methods){
Annotation[]annotations = method.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(FXReceiver.class.equals(annotation.annotationType())){
FXReceiver receiver = (FXReceiver)annotation;
FXMethodEntity fxMethodEntity = new FXMethodEntity(fxBaseControllerProxy,method);
List<FXMethodEntity> fxMethodEntities = receivers.get(receiver.name());
if(fxMethodEntities == null){
fxMethodEntities = new ArrayList<>();
}
fxMethodEntities.add(fxMethodEntity);
receivers.put(receiver.name(), fxMethodEntities);
}
}
}
}
public void sendMsg(String id,Object msg) {
List<FXMethodEntity> lists = receivers.get(id);
if (lists != null) {
for (FXMethodEntity fxMethodEntity : lists) {
Method method = fxMethodEntity.getMethod();
FXBaseController fxBaseController = fxMethodEntity.getFxBaseController();
if (method.getParameterCount() == 0) {
try {
method.invoke(fxBaseController);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
try {
method.invoke(fxBaseController, msg);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}

View File

@@ -0,0 +1,54 @@
package cn.edu.scau.biubiusuisui.proxy.classProxy;
import cn.edu.scau.biubiusuisui.annotation.FXSender;
import cn.edu.scau.biubiusuisui.entity.FXBaseController;
import cn.edu.scau.biubiusuisui.messageQueue.MessageQueue;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
*
* This proxy class intercept Methods that has special annotation such as
* FXSender which is a mark for message queue
*
* @Author jack
* @Date:2019/6/25 2:03
*/
public class FXControllerProxy implements MethodInterceptor {
FXBaseController target;
public Object getInstance(FXBaseController target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object o1 = methodProxy.invokeSuper(o, objects);
Annotation []annotations = method.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(FXSender.class.equals(annotation.annotationType())){
FXSender fxSender = (FXSender)annotation;
String name = target.getName() +":";
if("".equals(fxSender.name())){
name += method.getName();
}else{
name += fxSender.name();
}
MessageQueue.getInstance().sendMsg(name,o1);
}
}
return o1;
}
}

View File

@@ -0,0 +1,86 @@
package cn.edu.scau.biubiusuisui.proxy.classProxy;
import cn.edu.scau.biubiusuisui.entity.FXFieldMethodMapping;
import cn.edu.scau.biubiusuisui.utils.StringUtils;
import javafx.beans.property.ListProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @Author jack
* @Date:2019/6/27 18:47
*/
public class FXEntityProxy implements MethodInterceptor {
Object target;
private Map<String, Property> stringPropertyMap;
private Map<String, FXFieldMethodMapping> stringFXFieldMethodMappingMap;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
/**
* intercept get and set method and
*
* @param o
* @param method
* @param objects
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object o1 = methodProxy.invokeSuper(o, objects);
String methodName = method.getName();
String fieldName = null;
if (methodName.length() >= 3) {
fieldName = StringUtils.toInstanceName(methodName.substring(3));
} else {
return o1;
}
SimpleStringProperty property = (SimpleStringProperty) stringPropertyMap.get(fieldName);
if (methodName.startsWith("set")) {
property.set((String) objects[0]);
}
//修改
return o1;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Property getPropertyByFieldName(String name) {
return stringPropertyMap.get(name);
}
public Map<String, Property> getStringPropertyMap() {
return stringPropertyMap;
}
public void setStringPropertyMap(Map<String, Property> stringPropertyMap) {
this.stringPropertyMap = stringPropertyMap;
}
}

View File

@@ -0,0 +1,100 @@
package cn.edu.scau.biubiusuisui.utils;
import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* @Author jack
* @Date:2019/6/25 5:20
*/
public class ClassUtils {
private ClassLoader cl;
public ClassUtils() {
cl = getClass().getClassLoader();
}
private List<String> getAllFXControllerClassName(String base, List<String> nameList) {
String splashPath = StringUtils.dotToSplash(base);
URL url = cl.getResource(splashPath);
String filePath = StringUtils.getRootPath(url);
List<String> names = null;
names = readFromDirectory(filePath);
for (String name : names) {
if (isClassFile(name)) {
nameList.add(toFullyQualifiedName(name, base));
} else if (isDirectory(name)){
nameList = getAllFXControllerClassName(base + "." + name, nameList);
}
}
return nameList;
}
public List<String> scanAllClassName(String base) {
return getAllFXControllerClassName(base, new LinkedList<>());
}
private static String toFullyQualifiedName(String shortName, String basePackage) {
StringBuilder sb = new StringBuilder(basePackage);
sb.append('.');
sb.append(StringUtils.trimExtension(shortName));
return sb.toString();
}
private static boolean isClassFile(String name) {
return name.endsWith(".class");
}
private static boolean isDirectory(String name){
return !name.contains(".");
}
private static List<String> readFromDirectory(String path) {
File file = new File(path);
String[] names = file.list();
if (null == names) {
return null;
} else {
return Arrays.asList(names);
}
}
public static boolean hasDeclaredAnnotation(Class clazz, Class annotation){
if(annotation == null){
return false;
}
if (hasAnnotationInList(annotation, clazz.getDeclaredAnnotations())) return true;
return false;
}
public static boolean hasAnnotation(Class clazz, Class annotation) {
if(annotation == null){
return false;
}
if (hasAnnotationInList(annotation, clazz.getAnnotations())) return true;
return false;
}
public static boolean hasAnnotationInList(Class annotation, Annotation[] annotations2) {
if(getAnnotationInList(annotation,annotations2) == null){
return false;
}else{
return true;
}
}
public static Annotation getAnnotationInList(Class annotation,Annotation[]annotations){
if(annotations == null || annotation == null){
return null;
}
for (Annotation annotation1 : annotations) {
if (annotation1.annotationType().equals(annotation)) {
return annotation1;
}
}
return null;
}
}

View File

@@ -0,0 +1,17 @@
package cn.edu.scau.biubiusuisui.utils;
import cn.edu.scau.biubiusuisui.exception.ProtocolNotSupport;
import java.net.URL;
/**
* @Author jack
* @Date:2019/6/25 7:01
*/
public class FileUtils {
public URL getFXMLFile(String fxmlFilePath) throws ProtocolNotSupport {
return this.getClass().getClassLoader().getResource(fxmlFilePath);
}
}

View File

@@ -0,0 +1,82 @@
package cn.edu.scau.biubiusuisui.utils;
/**
* @Author jack
* @Date:2019/6/25 3:46
*/
import java.net.URL;
public class StringUtils {
private StringUtils() {
}
/**
* "file:/home/whf/cn/fh" -> "/home/whf/cn/fh"
* "jar:file:/home/whf/foo.jar!cn/fh" -> "/home/whf/foo.jar"
*/
public static String getRootPath(URL url) {
String fileUrl = url.getFile();
int pos = fileUrl.indexOf('!');
if (-1 == pos) {
return fileUrl;
}
return fileUrl.substring(5, pos);
}
/**
* "cn.fh.lightning" -> "cn/fh/lightning"
*
* @param name
* @return
*/
public static String dotToSplash(String name) {
return name.replaceAll("\\.", "/");
}
/**
* "Apple.class" -> "Apple"
*/
public static String trimExtension(String name) {
int pos = name.indexOf('.');
if (-1 != pos) {
return name.substring(0, pos);
}
return name;
}
/**
* /application/home -> /home
*
* @param uri
* @return
*/
public static String trimURI(String uri) {
String trimmed = uri.substring(1);
int splashIndex = trimmed.indexOf('/');
return trimmed.substring(splashIndex);
}
public static String getBaseClassName(String name){
int index = name.indexOf("$");
if(index == -1){
return name;
}
return name.substring(0,index);
}
public static String toInstanceName(String name){
String result = name.substring(0, 1).toLowerCase().concat(name.substring(1));
return result;
}
public static String toClassName(String name){
String result = name.substring(0, 1).toUpperCase().concat(name.substring(1));
return result;
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<fx:root prefHeight="400.0" prefWidth="600.0" type="Pane" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cn.edu.scau.biubiusuisui.example.MainController">
<children>
<Button fx:id="btn" layoutX="366.0" layoutY="159.0" mnemonicParsing="false" text="Button" onAction="#send"/>
<Label fx:id="label" layoutX="130.0" layoutY="159.0" prefHeight="30.0" prefWidth="184.0" text="JavaFX Plus is awesome!" />
</children>
</fx:root>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>
<fx:root prefHeight="400.0" prefWidth="600.0" type="Pane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cn.edu.scau.biubiusuisui.example.MainController">
<children>
<Button fx:id="btn" layoutX="266.0" layoutY="179.0" mnemonicParsing="false" text="Button" />
</children>
</fx:root>

View File

@@ -0,0 +1 @@
console.log('123123');

View File

@@ -0,0 +1,14 @@
import cn.edu.scau.biubiusuisui.example.Student;
import cn.edu.scau.biubiusuisui.factory.FXEntityFactory;
import org.junit.Test;
/**
* @Author jack
* @Date:2019/6/25 2:11
*/
public class MainTest {
@Test
public void test(){
FXEntityFactory fxEntityFactory = FXEntityFactory.getInstance();
}
}

View File

@@ -0,0 +1,59 @@
package cn.edu.scau.biubiusuisui.factory;
import cn.edu.scau.biubiusuisui.annotation.FXEntity;
import cn.edu.scau.biubiusuisui.entity.FXPlusContext;
import cn.edu.scau.biubiusuisui.example.Student;
import javafx.beans.property.Property;
import org.junit.Test;
import java.util.Map;
import java.util.function.Predicate;
import static org.junit.Assert.*;
/**
* @Author jack
* @Date:2019/6/28 1:32
*/
public class FXEntityFactoryTest {
@Test
public void getClassProperty() {
FXEntityFactory fxEntityFactory =FXEntityFactory.getInstance();
Student student = new Student();
student.setName("Jack");
try {
Map<String, Property> entityProperty = fxEntityFactory.getEntityProperty(student,null);
entityProperty.forEach((k,v)->{
System.out.println("key" + k +" v" + v);
});
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Test
public void getInstance() {
}
@Test
public void createJavaBeanProxy() {
Student student = new Student();
student.setName("NAME");
}
@Test
public void createJavaBeanProxy2() throws InstantiationException, IllegalAccessException {
Student student1 = (Student) FXEntityFactory.getInstance().createJavaBeanProxy(Student.class);
System.out.println(student1);
FXPlusContext.getProryByBeanObject(student1).getStringPropertyMap().forEach((k,v)->{
System.out.println("k " +k +"v" + v);
});
student1.setName("Jack");
}
@Test
public void getEntityProperty() {
}
}