jrubyfx 0.9.2-java → 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README.md +19 -17
  2. data/bin/jrubyfx-generator +28 -11
  3. data/lib/jrubyfx.rb +8 -4
  4. data/lib/jrubyfx/{fxml_application.rb → application.rb} +0 -2
  5. data/lib/jrubyfx/controller.rb +307 -0
  6. data/lib/jrubyfx/core_ext/border_pane.rb +0 -1
  7. data/lib/jrubyfx/core_ext/duration.rb +1 -1
  8. data/lib/jrubyfx/core_ext/exts.yml +53 -0
  9. data/lib/jrubyfx/core_ext/image_view.rb +1 -0
  10. data/lib/jrubyfx/core_ext/observable_value.rb +69 -2
  11. data/lib/jrubyfx/core_ext/path.rb +0 -6
  12. data/lib/jrubyfx/core_ext/precompiled.rb +501 -0
  13. data/lib/jrubyfx/core_ext/stage.rb +12 -0
  14. data/lib/jrubyfx/core_ext/table_view.rb +0 -4
  15. data/lib/jrubyfx/core_ext/timeline.rb +3 -7
  16. data/lib/jrubyfx/dsl.rb +168 -150
  17. data/lib/jrubyfx/dsl_map.rb +267 -0
  18. data/lib/jrubyfx/imports.rb +64 -0
  19. data/lib/jrubyfx/java_fx_impl.rb +0 -1
  20. data/lib/jrubyfx/module.rb +172 -0
  21. data/lib/jrubyfx/{jfx_imports.rb → part_imports.rb} +17 -9
  22. data/lib/jrubyfx/utils.rb +13 -4
  23. data/lib/jrubyfx/utils/common_converters.rb +45 -13
  24. data/lib/jrubyfx/utils/common_utils.rb +1 -1
  25. data/lib/jrubyfx/version.rb +1 -1
  26. data/lib/jrubyfx_tasks.rb +9 -1
  27. metadata +69 -55
  28. data/lib/jrubyfx/core_ext/circle.rb +0 -26
  29. data/lib/jrubyfx/core_ext/drag_event.rb~ +0 -32
  30. data/lib/jrubyfx/core_ext/image_view.rb~ +0 -24
  31. data/lib/jrubyfx/core_ext/labeled.rb +0 -24
  32. data/lib/jrubyfx/core_ext/menu.rb +0 -25
  33. data/lib/jrubyfx/core_ext/menu.rb~ +0 -26
  34. data/lib/jrubyfx/core_ext/menu_bar.rb +0 -25
  35. data/lib/jrubyfx/core_ext/menu_bar.rb~ +0 -24
  36. data/lib/jrubyfx/core_ext/menu_item.rb +0 -22
  37. data/lib/jrubyfx/core_ext/node.rb +0 -26
  38. data/lib/jrubyfx/core_ext/parallel_transition.rb +0 -28
  39. data/lib/jrubyfx/core_ext/parent.rb +0 -28
  40. data/lib/jrubyfx/core_ext/scene.rb +0 -29
  41. data/lib/jrubyfx/core_ext/shape.rb +0 -29
  42. data/lib/jrubyfx/core_ext/stop.rb +0 -31
  43. data/lib/jrubyfx/core_ext/tree_item.rb +0 -25
  44. data/lib/jrubyfx/core_ext/tree_item.rb~ +0 -25
  45. data/lib/jrubyfx/core_ext/tree_view.rb~ +0 -33
  46. data/lib/jrubyfx/fxml_controller.rb +0 -325
  47. data/lib/jrubyfx/fxml_module.rb +0 -98
data/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  JRubyFX
2
2
  =======
3
- JRubyFX is a pure ruby wrapper for JavaFX 2.x with FXML support
3
+ JRubyFX is a pure ruby wrapper for JavaFX 2.2+ with FXML support
4
4
 
5
5
  Status
6
6
  ------
7
- JRubyFX should be usable in its current form and able to run FXML apps if used properly (see Issues).
8
- The syntax of the FXML side of JRubyFX should be fairly stable, but the JavaFX DSL may change.
9
- At this point in time, no custom ruby controls are supported from FXML, though you
10
- can certainly create them in code.
7
+ JRubyFX master should be usable in its current form and able to run simple FXML apps if used properly (see Issues).
8
+ FXML syntax in master/1.0 is very different from 0.9 series. Please see the [JRubyFX github wiki](https://github.com/jruby/jrubyfx/wiki/) for more details.
11
9
 
12
10
  Install
13
11
  -----
@@ -17,9 +15,10 @@ gem install jrubyfx
17
15
 
18
16
  Manual Build and Install
19
17
  -----
20
- Build is done using rake/gem/bundler/rdoc. You obviously need JRuby, Java 1.7 (with JavaFX) also.
18
+ Build is done using rake/gem/bundler/rdoc. You need JRuby >1.7.4 (in 1.9 mode), Java >1.6 with JavaFX 2.2, but Java 7 is recommended. Building native application packages requires JDK 8.
21
19
 
22
20
  ```text
21
+ gem install jrubyfx-fxmlloader
23
22
  rake install
24
23
  ```
25
24
  Once the gem is installed, just run a ruby file that uses it normally.
@@ -27,6 +26,8 @@ Once the gem is installed, just run a ruby file that uses it normally.
27
26
  **NOTE:** If you don't have JRuby installed as the `ruby` command, use `jruby -S rake` instead of `rake`. If
28
27
  you are using RVM, this does not apply to you (though make sure you `rvm use jruby`).
29
28
 
29
+ **If you are reporting bugs or encountering fxml issues:** please install [master jrubyfx-fxmlloader](https://github.com/byteit101/JRubyFX-FXMLLoader/) instead of from rubygems
30
+
30
31
  Creating a Jar
31
32
  --------------
32
33
  If you want to distribute your application, you can create a jar with embedded JRuby.
@@ -55,7 +56,9 @@ Example: If my project directory is `Hello`, all my files are in `src`, I have a
55
56
  jrubyfx-jarify src --main src/HelloWorldApp.rb dist/HelloWorldApp.jar --native --name "Hello World App" -v
56
57
  ```
57
58
 
58
- Sample
59
+ Also note that you can do this in code, see samples/fxml/Demo.rb for the rake task usage.
60
+
61
+ Samples
59
62
  -------
60
63
 
61
64
  To run sample:
@@ -73,9 +76,11 @@ rake run main_script=samples/fxml/Demo.rb
73
76
  To run all samples (a nice quick way to make sure you didn't break anything), run:
74
77
 
75
78
  ```text
76
- jruby samples/test_all_the_samples.rb
79
+ jruby -I lib samples/test_all_the_samples.rb
77
80
  ```
78
81
 
82
+ Several other files that can be used as examples are in the tests/ folder
83
+
79
84
  Creating Application and Controller
80
85
  -----------------------------------
81
86
 
@@ -83,19 +88,16 @@ Require the 'jrubyfx' file/gem, and subclass JRubyFX::Application (and JRubyFX::
83
88
  At the bottom of the file, call _yourFXApplicationClass_.launch().
84
89
  Override start(stage) in the application. See samples/fxml/Demo.rb for commented FXML example,
85
90
  or the fils in samples/javafx for non-FXML (programatic JavaFX, but you should really
86
- look into FXML, its better) or see the Getting Started Guide and the Notes.
91
+ look into FXML, its better) or see the [Getting Started Guide](https://github.com/jruby/jrubyfx/wiki/Getting-Started) and the Syntax Notes on the [JRubyFX github wiki](https://github.com/jruby/jrubyfx/wiki/)
87
92
 
88
- If you want rdoc, run `rake rdoc`.
93
+ If you want rdoc, run `rake rdoc`. Please note that there are lots of generated methods and conventions that are not in the RDoc. Please read the Getting Started Guide or the tutorials.
89
94
 
90
95
  Issues
91
96
  ------
92
- * You must NOT set fx:controller in the FXML files. At the moment, due to JRuby bugs, Java is unable
93
- to initialize Ruby objects in this way. See Demo.rb for proper way to set the controller (passing it
94
- in to load_fxml())
95
- * You must use the provided JavaFXImpl::Launcher to launch the app (aka: call _yourFXApplicationClass_.launch()). This is due to the same JRuby bugs
96
- as above.
97
- * Errors loading jfxrt.jar are bugs. Please report if you encounter this issue, tell us your platform,
98
- OS, and version of JRuby
97
+ * Use JRubyFX-FxmlLoader's FxmlLoader instead of javafx.fxml.FXMLLoader for maximum Ruby support.
98
+ * FXML support in master for very complex documents is untested. Report bugs against JRubyFX-FxmlLoader with the FXML file if it fails.
99
+ * You must use the provided JavaFXImpl::Launcher to launch the app (aka: call _yourFXApplicationClass_.launch())
100
+ * Errors loading JavaFX are bugs. Please report if you encounter this issue, tell us your platform, OS, and version of JRuby
99
101
  * Jarify command needs the `jar` executable in your path.
100
102
  * Any other difficulties are bugs. Please report them
101
103
 
@@ -18,6 +18,7 @@ limitations under the License.
18
18
 
19
19
  require 'date'
20
20
  require 'jrubyfx/utils'
21
+ require 'pathname'
21
22
 
22
23
  if ARGV.length < 1
23
24
  puts "Please specify the fxml file to parse"
@@ -34,39 +35,54 @@ name_guess = ARGV[2] if ARGV.length > 2
34
35
  print "Generating JRubyFX template for #{fxml} into #{rb}... "
35
36
 
36
37
  File.open(rb, "w") do |output|
37
-
38
+
39
+ fx_diff_root = ("/" + Pathname.new(File.dirname fxml).relative_path_from(Pathname.new(File.dirname rb)).to_s).inspect
40
+ fx_diff_root = if fx_diff_root == '"/."'
41
+ ""
42
+ else
43
+ " + #{fx_diff_root}"
44
+ end
38
45
  output << <<END
39
46
  # This file was auto-generated by jrubyfx-generator at #{DateTime.now.to_s}
40
47
 
41
48
  require 'jrubyfx'
49
+ fxml_root File.dirname(__FILE__)#{fx_diff_root}
42
50
 
43
51
  class #{name_guess}Application < JRubyFX::Application
44
52
  def start(stage)
45
- with(stage, title: "#{name_guess}", width: 600, height: 400)
46
- #{name_guess}Controller.load_fxml("#{File.basename(fxml)}", stage)
47
- stage.show()
53
+ with(stage, title: "#{name_guess}") do
54
+ fxml #{name_guess}Controller
55
+ show
56
+ end
48
57
  end
49
58
  end
50
59
 
51
- class #{name_guess}Controller < JRubyFX::Controller
60
+ class #{name_guess}Controller
61
+ include JRubyFX::Controller
62
+ fxml "#{File.basename(fxml)}"
52
63
  END
53
64
 
65
+ fx_ids = []
54
66
  File.open(fxml, "r") do |fx|
55
67
  handlers = "\n"
68
+
56
69
  fx.each_line do |line|
57
- line.scan(/fx:id="([^ "':]+)"/) do |match|
58
- output << " fx_id :#{match[0]}\n"
70
+ line.scan(/fx:id="([^ "':]+)"/) do |match|
71
+ fx_ids << match[0]
59
72
  end
60
73
  # TODO: may not work with funky non-latin characters
61
74
  # Yes, I used regex, yes its xml, yes I now have two problems.
62
- line.scan(/on((([A-Z]*[a-z]*)*?)[A-Z]+[a-z]+)="#([^ "':]+)"/) do |match|
63
- handlers << " fx_#{match[1].snake_case}#{(match[1].length >0 ? "_" : "")}handler :#{match[3]} do |event|\n # TODO: Auto-generated event handler\n"
75
+ line.scan(/on((([A-Z]*[a-z]*)*?)[A-Z]+[a-z]+)="#([^ "':]+)"/) do |match|
76
+ handlers << " def #{match[3]}(event)\n"
77
+ handlers << " # TODO: Auto-generated event handler\n"
64
78
  handlers << " puts \"#{match[0]} event '#{match[3]}' called\"\n end\n\n"
65
79
  end
66
80
  end
81
+ output << "\n # nodes with ruby method-like fx:ids may be accessed directly"
82
+ output << "\n def initialize\n#{fx_ids.map{|x|" puts \"fx:id=\\\"#{x}\\\" was not injected: check your FXML file '#{File.basename(fxml)}'.\" unless @#{x}"}.join "\n"}\n end\n"
67
83
  output << handlers
68
84
  end
69
-
85
+
70
86
  output << <<END
71
87
  end
72
88
 
@@ -76,6 +92,7 @@ END
76
92
  end
77
93
 
78
94
  puts "Done!"
95
+
79
96
  puts "Launching 'jruby #{rb}' ..."
80
97
 
81
- require rb
98
+ require rb
data/lib/jrubyfx.rb CHANGED
@@ -17,11 +17,15 @@ limitations under the License.
17
17
  require 'java' # for java_import
18
18
  require 'jruby/core_ext' # for the become_java!
19
19
 
20
+ unless File.size? "#{File.dirname(__FILE__)}/jrubyfx/imports.rb"
21
+ puts "Please run `rake reflect` to generate the imports"
22
+ exit -1
23
+ end
20
24
  # JRubyFX includes
21
- require_relative 'jrubyfx/jfx_imports'
22
- require_relative 'jrubyfx/fxml_module'
25
+ require_relative 'jrubyfx/imports'
26
+ require_relative 'jrubyfx/module'
23
27
  require_relative 'jrubyfx/dsl'
24
28
  JRubyFX::DSL.load_dsl # load it after we require the dsl package to not loop around
25
- require_relative 'jrubyfx/fxml_application'
26
- require_relative 'jrubyfx/fxml_controller'
29
+ require_relative 'jrubyfx/application'
30
+ require_relative 'jrubyfx/controller'
27
31
  require_relative 'jrubyfx/java_fx_impl'
@@ -15,8 +15,6 @@ See the License for the specific language governing permissions and
15
15
  limitations under the License.
16
16
  =end
17
17
 
18
- require 'jrubyfx'
19
-
20
18
  ##
21
19
  # Inherit from this class for FXML Applications. You must use this class for both
22
20
  # raw JavaFX and FXML as it contains the launch method.
@@ -0,0 +1,307 @@
1
+ =begin
2
+ JRubyFX - Write JavaFX and FXML in Ruby
3
+ Copyright (C) 2013 The JRubyFX Team
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ =end
17
+
18
+ require 'jrubyfx-fxmlloader'
19
+
20
+ # Special methods for fxml loading
21
+ module Kernel
22
+ def fxml_root(value=nil)
23
+ if value
24
+ @@jrubyfx_fxml_dir = File.expand_path(value)
25
+ else
26
+ @@jrubyfx_fxml_dir
27
+ end
28
+ end
29
+ end
30
+
31
+ # Inherit from this class for FXML controllers
32
+ module JRubyFX::Controller
33
+ include JRubyFX::DSL
34
+ java_import 'java.net.URL'
35
+
36
+ DEFAULT_SETTINGS = {
37
+ width: -1,
38
+ height: -1,
39
+ fill: :white,
40
+ depth_buffer: false,
41
+ root_dir: nil,
42
+ initialized: nil
43
+ }
44
+
45
+ # Controllers usually need access to the stage.
46
+ attr_writer :stage, :scene
47
+
48
+ def self.included(base)
49
+ base.extend(ClassMethods)
50
+ base.extend(JRubyFX::FXMLClassUtils)
51
+ # register ourselves as a control. overridable with custom_fxml_control
52
+ register_type base if base.is_a? Class
53
+ end
54
+
55
+ # class methods for FXML controllers
56
+ module ClassMethods
57
+ include JRubyFX::DSL
58
+
59
+ #nested including, TODO: don't duplicate this
60
+ def included(base)
61
+ base.extend(JRubyFX::Controller::ClassMethods)
62
+ # register ourselves as a control. overridable with custom_fxml_control
63
+ JRubyFX::DSL::ClassUtils.register_type base if base.is_a? Class
64
+ end
65
+
66
+ # Load given fxml file onto the given stage. `settings` is an optional hash of:
67
+ # * :initialize => [array of arguments to pass to the initialize function]
68
+ # * :width => Default width of the Scene
69
+ # * :height => Default height of the Scene
70
+ # * :fill => Fill color of the Scene's background
71
+ # * :depth_buffer => JavaFX Scene DepthBuffer argument (look it up)
72
+ # * :root_dir => filename search for fxml realtive to this file
73
+ #
74
+ # === Examples
75
+ #
76
+ # controller = MyFXController.new "Demo.fxml", stage
77
+ #
78
+ # === Equivalent Java
79
+ # Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
80
+ # Scene scene = new Scene(root);
81
+ # stage.setScene(scene);
82
+ # controller = root.getController();
83
+
84
+ def load_into(stage, settings={})
85
+ # Inherit from default settings
86
+ settings = DEFAULT_SETTINGS.merge({root_dir: (self.instance_variable_get("@fxml_root_dir") || fxml_root),
87
+ filename: self.instance_variable_get("@filename")}).merge settings
88
+
89
+ # Custom controls don't always need to be pure java, but oh well...
90
+ become_java!
91
+
92
+ # like new, without initialize
93
+ ctrl = allocate
94
+
95
+ # Set the stage so we can reference it if needed later
96
+ ctrl.stage = stage
97
+
98
+ # load the FXML file
99
+ root = Controller.get_fxml_loader(settings[:filename], ctrl, settings[:root_dir]).load
100
+
101
+ # Unless the FXML root node is a scene, wrap that node in a scene
102
+ if root.is_a? Scene
103
+ scene = root
104
+ else
105
+ scene = Scene.new root, settings[:width], settings[:height], settings[:depth_buffer]
106
+ scene.fill = settings[:fill]
107
+ end
108
+
109
+ # set the controller and stage scene
110
+ ctrl.scene = stage.scene = scene
111
+
112
+ ctrl.finish_initialization *settings[:initialize].to_a
113
+ end
114
+
115
+ # This is the default override for custom controls
116
+ # Normal FXML controllers will use Control#new
117
+ def new(*args, &block)
118
+ # Custom controls don't always need to be pure java, but oh well...
119
+ become_java! if @filename
120
+
121
+ # like new, without initialize
122
+ ctrl = allocate
123
+
124
+ ctrl.initialize_controller(DEFAULT_SETTINGS.merge({root_dir: @fxml_root_dir || fxml_root,
125
+ filename: @filename}),
126
+ *args, &block) if @filename
127
+
128
+ # return the controller
129
+ ctrl
130
+ end
131
+
132
+ #decorator to force becoming java class
133
+ def become_java
134
+ @force_java = true
135
+ end
136
+
137
+ # Set the filename of the fxml this control is part of
138
+ def fxml(fxml=nil, name = nil, root_dir = nil)
139
+ @filename = fxml
140
+ # snag the filename from the caller
141
+ @fxml_root_dir = root_dir
142
+ register_type(self, name) if name
143
+ end
144
+
145
+ ##
146
+ # Event Handlers
147
+ ##
148
+
149
+ ##
150
+ # call-seq:
151
+ # on(callback, ...) { |event_info| block } => Method
152
+ #
153
+ # Registers a function of name `name` for a FXML defined event with the body in the block.
154
+ # Note you can also just use normal methods
155
+ #
156
+ # === Examples
157
+ # on :click do
158
+ # puts "button clicked"
159
+ # end
160
+ #
161
+ # on :moved, :pressed do |event|
162
+ # puts "Mouse Moved or Key Pressed"
163
+ # p event
164
+ # end
165
+ #
166
+ # === Equivalent Java
167
+ # @FXML
168
+ # private void click(ActionEvent event) {
169
+ # System.out.println("button clicked");
170
+ # }
171
+ #
172
+ # @FXML
173
+ # private void moved(MouseEvent event) {
174
+ # System.out.println("Mouse Moved or Key Pressed");
175
+ # }
176
+ #
177
+ # @FXML
178
+ # private void keypress(KeyEvent event) {
179
+ # System.out.println("Key Pressed or Key Pressed");
180
+ # }
181
+ #
182
+ def on(names, &block)
183
+ [names].flatten.each do |name|
184
+ class_eval do
185
+ # must define this way so block executes in class scope, not static scope
186
+ define_method name, block
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ #default java ctor, override for arguments
193
+ def java_ctor(ctor, initialize_arguments)
194
+ ctor.call
195
+ end
196
+
197
+ # Initialize all controllers
198
+ def initialize_controller(options={}, *args, &block)
199
+
200
+ # JRuby complains loudly (probably broken behavior) if we don't call the ctor
201
+ java_ctor self.class.superclass.instance_method(:initialize).bind(self), args
202
+
203
+ # load the FXML file with the current control as the root
204
+ load_fxml options[:filename], options[:root_dir]
205
+
206
+ finish_initialization *args, &block
207
+ end
208
+
209
+ def load_fxml(filename, root_dir=nil)
210
+ fx = Controller.get_fxml_loader(filename, self, root_dir)
211
+ fx.root = self
212
+ fx.load
213
+ end
214
+
215
+ def finish_initialization(*args, &block)
216
+ @nodes_by_id = {}
217
+
218
+ # custom controls are their own scene
219
+ self.scene = self unless @scene
220
+
221
+ # Everything is ready, call initialize
222
+ if private_methods.include? :initialize
223
+ self.send :initialize, *args, &block
224
+ end
225
+
226
+ #return ourself
227
+ self
228
+ end
229
+
230
+ ##
231
+ # Node Lookup Methods
232
+ ##
233
+
234
+ # return first matched node or nil
235
+ def find(css_selector)
236
+ @scene.lookup(css_selector)
237
+ end
238
+
239
+ # Return first matched node or throw exception
240
+ def find!(css_selector)
241
+ res = find(css_selector)
242
+ raise "Selector(#{css_selector}) returned no results!" unless res
243
+ res
244
+ end
245
+
246
+ # return an array of matched nodes
247
+ def css(css_selector)
248
+ @scene.get_root.lookup_all(css_selector).to_a
249
+ end
250
+
251
+ # Loads a controller-less file
252
+ def self.load_fxml_only(filename, stage, settings={})
253
+ # Inherit from default settings
254
+ settings = DEFAULT_SETTINGS.merge({root_dir: fxml_root,
255
+ filename: filename}).merge settings
256
+
257
+ # load the FXML file
258
+ root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir]).load
259
+
260
+ # TODO: de-duplicate this code
261
+
262
+ # Unless the FXML root node is a scene, wrap that node in a scene
263
+ if root.is_a? Scene
264
+ scene = root
265
+ else
266
+ scene = Scene.new root, settings[:width], settings[:height], settings[:depth_buffer]
267
+ scene.fill = settings[:fill]
268
+ end
269
+
270
+ # set the controller and stage scene
271
+ stage.scene = scene
272
+ end
273
+
274
+
275
+ ##
276
+ # call-seq:
277
+ # get_fxml_loader(filename) => FXMLLoader
278
+ # get_fxml_loader(filename, controller_instance) => FXMLLoader
279
+ # get_fxml_loader(filename, controller_instance, root_dir) => FXMLLoader
280
+ #
281
+ # Load a FXML file given a filename and a controller and return the loader
282
+ # root_dir is a directory that the file is relative to.
283
+ # === Examples
284
+ # root = JRubyFX::Controller.get_fxml_loader("Demo.fxml").load
285
+ #
286
+ # root = JRubyFX::Controller.get_fxml_loader("Demo.fxml", my_controller).load
287
+ #
288
+ # === Equivalent Java
289
+ # Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
290
+ #
291
+ def self.get_fxml_loader(filename, controller = nil, root_dir = nil)
292
+ fx = FxmlLoader.new
293
+ fx.location =
294
+ if JRubyFX::Application.in_jar?
295
+ # If we are in a jar file, use the class loader to get the file from the jar (like java)
296
+ # TODO: should just be able to use URLs
297
+ JRuby.runtime.jruby_class_loader.get_resource filename
298
+ else
299
+ root_dir ||= fxml_root
300
+ # If we are in the normal filesystem, create a file url path relative to relative_to or this file
301
+ URL.new "file:#{File.join root_dir, filename}"
302
+ end
303
+ # we must set this here for JFX to call our events
304
+ fx.controller = controller
305
+ fx
306
+ end
307
+ end