1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package it.tidalwave.ui.javafx;
27
28 import javax.annotation.Nonnull;
29 import java.io.IOException;
30 import javafx.fxml.FXMLLoader;
31 import javafx.scene.Node;
32 import javafx.application.Platform;
33 import it.tidalwave.util.ReflectionUtils;
34 import lombok.Getter;
35 import lombok.RequiredArgsConstructor;
36 import lombok.extern.slf4j.Slf4j;
37 import static lombok.AccessLevel.PRIVATE;
38
39
40
41
42
43
44 @RequiredArgsConstructor(access = PRIVATE) @Getter @Slf4j
45 public final class NodeAndDelegate<T>
46 {
47 @Nonnull
48 private final Node node;
49
50 @Nonnull
51 private final T delegate;
52
53 @Nonnull
54 public static <T> NodeAndDelegate<T> load (@Nonnull final Class<T> clazz, @Nonnull final String resource)
55 throws IOException
56 {
57 log.debug("NodeAndDelegate({}, {})", clazz, resource);
58 assert Platform.isFxApplicationThread() : "Not in JavaFX UI Thread";
59 final var loader = new FXMLLoader(clazz.getResource(resource), null, null,
60 type -> ReflectionUtils.instantiateWithDependencies(type, JavaFXSafeProxyCreator.BEANS));
61 final Node node = loader.load();
62 final T jfxController = loader.getController();
63 ReflectionUtils.injectDependencies(jfxController, JavaFXSafeProxyCreator.BEANS);
64 final var interfaces = jfxController.getClass().getInterfaces();
65
66 if (interfaces.length == 0)
67 {
68 log.warn("{} has no interface: not creating safe proxy", jfxController.getClass());
69 log.debug(">>>> load({}, {}) completed", clazz, resource);
70 return new NodeAndDelegate<>(node, jfxController);
71 }
72 else
73 {
74 final var interfaceClass = (Class<T>)interfaces[0];
75 final var safeDelegate = JavaFXSafeProxyCreator.createSafeProxy(jfxController, interfaceClass);
76 log.debug(">>>> load({}, {}) completed", clazz, resource);
77 return new NodeAndDelegate<>(node, safeDelegate);
78 }
79 }
80 }