24
24
import javafx .scene .layout .AnchorPane ;
25
25
26
26
/**
27
- * This class is derived from Adam Bien's <a href="http://afterburner.adam-bien.com/">afterburner.fx</a> project.
27
+ * This class is derived from Adam Bien's
28
+ * <a href="http://afterburner.adam-bien.com/">afterburner.fx</a> project.
28
29
* <p>
29
30
* {@link AbstractFxmlView} is a stripped down version of <a href=
30
31
* "https://github.com/AdamBien/afterburner.fx/blob/02f25fdde9629fcce50ea8ace5dec4f802958c8d/src/main/java/com/airhacks/afterburner/views/FXMLView.java"
31
32
* >FXMLView</a> that provides DI for Java FX Controllers via Spring.
32
33
*
33
- * Felix Roske <[email protected] > changed this, so it always expects fxml Files by default in FXML_PATH .
34
+ * Felix Roske <[email protected] > changed this to use annotation for fxml path .
34
35
*
35
36
* @author Thomas Darimont
36
37
*/
37
38
public abstract class AbstractFxmlView implements ApplicationContextAware {
38
39
39
40
private static String FXML_PATH = "/fxml/" ;
40
-
41
+
41
42
protected ObjectProperty <Object > presenterProperty ;
42
43
protected FXMLLoader fxmlLoader ;
43
44
protected ResourceBundle bundle ;
@@ -56,31 +57,45 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
56
57
57
58
this .applicationContext = applicationContext ;
58
59
}
59
-
60
+
60
61
public AbstractFxmlView () {
61
62
this (FXML_PATH );
62
63
}
63
-
64
+
64
65
public AbstractFxmlView (String path ) {
65
66
setFxmlRootPath (path );
67
+
68
+ // TODO refactor me!
69
+ FXMLView annotation = getFXMLAnnotation ();
70
+ if (annotation != null && !annotation .value ().equals ("" )) {
71
+ this .resource = getClass ().getResource (annotation .value ());
72
+ } else {
73
+ this .resource = getClass ().getResource (getFxmlPath ());
74
+ }
75
+
66
76
this .presenterProperty = new SimpleObjectProperty <>();
67
- this .resource = getClass ().getResource (getFxmlPath ());
77
+ // this.resource = getClass().getResource(getFxmlPath());
68
78
this .bundle = getResourceBundle (getBundleName ());
69
79
}
70
80
81
+ private FXMLView getFXMLAnnotation () {
82
+ Class <? extends AbstractFxmlView > theClass = this .getClass ();
83
+ FXMLView annotation = theClass .getAnnotation (FXMLView .class );
84
+ return annotation ;
85
+ }
86
+
71
87
private Object createControllerForType (Class <?> type ) {
72
88
return this .applicationContext .getBean (type );
73
89
}
74
90
75
91
private void setFxmlRootPath (String path ) {
76
- if (path .endsWith ("/" )) {
92
+ if (path .endsWith ("/" )) {
77
93
this .fxmlRoot = path ;
78
- }
79
- else {
94
+ } else {
80
95
this .fxmlRoot = path + "/" ;
81
96
}
82
97
}
83
-
98
+
84
99
FXMLLoader loadSynchronously (URL resource , ResourceBundle bundle ) throws IllegalStateException {
85
100
86
101
FXMLLoader loader = new FXMLLoader (resource , bundle );
@@ -106,8 +121,8 @@ void ensureFxmlLoaderInitialized() {
106
121
}
107
122
108
123
/**
109
- * Initializes the view by loading the FXML (if not happened yet) and returns the top Node (parent) specified in the
110
- * FXML file.
124
+ * Initializes the view by loading the FXML (if not happened yet) and
125
+ * returns the top Node (parent) specified in the FXML file.
111
126
*
112
127
* @return
113
128
*/
@@ -121,17 +136,21 @@ public Parent getView() {
121
136
}
122
137
123
138
/**
124
- * Initializes the view synchronously and invokes the consumer with the created parent Node within the FX UI thread.
139
+ * Initializes the view synchronously and invokes the consumer with the
140
+ * created parent Node within the FX UI thread.
125
141
*
126
- * @param consumer - an object interested in received the {@link Parent} as callback
142
+ * @param consumer
143
+ * - an object interested in received the {@link Parent} as
144
+ * callback
127
145
*/
128
146
public void getView (Consumer <Parent > consumer ) {
129
147
CompletableFuture .supplyAsync (this ::getView , Platform ::runLater ).thenAccept (consumer );
130
148
}
131
149
132
150
/**
133
- * Scene Builder creates for each FXML document a root container. This method omits the root container (e.g.
134
- * {@link AnchorPane}) and gives you the access to its first child.
151
+ * Scene Builder creates for each FXML document a root container. This
152
+ * method omits the root container (e.g. {@link AnchorPane}) and gives you
153
+ * the access to its first child.
135
154
*
136
155
* @return the first child of the {@link AnchorPane}
137
156
*/
@@ -146,7 +165,18 @@ public Node getViewWithoutRootContainer() {
146
165
}
147
166
148
167
void addCSSIfAvailable (Parent parent ) {
149
-
168
+
169
+ // TODO refactor me!
170
+ FXMLView annotation = getFXMLAnnotation ();
171
+ if (annotation != null && annotation .css ().length > 0 ) {
172
+ for (String cssFile : annotation .css ()) {
173
+ URL uri = getClass ().getResource (cssFile );
174
+ String uriToCss = uri .toExternalForm ();
175
+ parent .getStylesheets ().add (uriToCss );
176
+ }
177
+ return ;
178
+ }
179
+
150
180
URL uri = getClass ().getResource (getStyleSheetName ());
151
181
if (uri == null ) {
152
182
return ;
@@ -161,10 +191,13 @@ String getStyleSheetName() {
161
191
}
162
192
163
193
/**
164
- * In case the view was not initialized yet, the conventional fxml (airhacks.fxml for the AirhacksView and
165
- * AirhacksPresenter) are loaded and the specified presenter / controller is going to be constructed and returned.
194
+ * In case the view was not initialized yet, the conventional fxml
195
+ * (airhacks.fxml for the AirhacksView and AirhacksPresenter) are loaded and
196
+ * the specified presenter / controller is going to be constructed and
197
+ * returned.
166
198
*
167
- * @return the corresponding controller / presenter (usually for a AirhacksView the AirhacksPresenter)
199
+ * @return the corresponding controller / presenter (usually for a
200
+ * AirhacksView the AirhacksPresenter)
168
201
*/
169
202
public Object getPresenter () {
170
203
@@ -174,10 +207,12 @@ public Object getPresenter() {
174
207
}
175
208
176
209
/**
177
- * Does not initialize the view. Only registers the Consumer and waits until the the view is going to be created / the
178
- * method FXMLView#getView or FXMLView#getViewAsync invoked.
210
+ * Does not initialize the view. Only registers the Consumer and waits until
211
+ * the the view is going to be created / the method FXMLView#getView or
212
+ * FXMLView#getViewAsync invoked.
179
213
*
180
- * @param presenterConsumer listener for the presenter construction
214
+ * @param presenterConsumer
215
+ * listener for the presenter construction
181
216
*/
182
217
public void getPresenter (Consumer <Object > presenterConsumer ) {
183
218
@@ -187,16 +222,17 @@ public void getPresenter(Consumer<Object> presenterConsumer) {
187
222
}
188
223
189
224
/**
190
- * @param ending the suffix to append
225
+ * @param ending
226
+ * the suffix to append
191
227
* @return the conventional name with stripped ending
192
228
*/
193
229
protected String getConventionalName (String ending ) {
194
230
return getConventionalName () + ending ;
195
231
}
196
232
197
233
/**
198
- * @return the name of the view without the "View" prefix in lowerCase. For AirhacksView just airhacks is going to be
199
- * returned.
234
+ * @return the name of the view without the "View" prefix in lowerCase. For
235
+ * AirhacksView just airhacks is going to be returned.
200
236
*/
201
237
protected String getConventionalName () {
202
238
return stripEnding (getClass ().getSimpleName ().toLowerCase ());
@@ -216,14 +252,15 @@ static String stripEnding(String clazz) {
216
252
}
217
253
218
254
/**
219
- * @return the relative path to the fxml file derived from the FXML view. e.g. The name for the AirhacksView is going to be
255
+ * @return the relative path to the fxml file derived from the FXML view.
256
+ * e.g. The name for the AirhacksView is going to be
220
257
* <PATH>/airhacks.fxml.
221
258
*/
222
259
223
260
final String getFxmlPath () {
224
261
return fxmlRoot + getConventionalName (".fxml" );
225
262
}
226
-
263
+
227
264
private ResourceBundle getResourceBundle (String name ) {
228
265
try {
229
266
return getBundle (name );
@@ -239,4 +276,3 @@ public ResourceBundle getResourceBundle() {
239
276
return this .bundle ;
240
277
}
241
278
}
242
-
0 commit comments