jrubyfx-openjfx.patch 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +202 -0
  3. data/README.md +121 -0
  4. data/bin/jrubyfx-compile +32 -0
  5. data/bin/jrubyfx-generator +98 -0
  6. data/bin/jrubyfx-jarify +115 -0
  7. data/lib/jrubyfx.rb +41 -0
  8. data/lib/jrubyfx/application.rb +42 -0
  9. data/lib/jrubyfx/compiler_app.rb +51 -0
  10. data/lib/jrubyfx/controller.rb +375 -0
  11. data/lib/jrubyfx/core_ext/border_pane.rb +30 -0
  12. data/lib/jrubyfx/core_ext/column_constraints.rb +43 -0
  13. data/lib/jrubyfx/core_ext/drag_event.rb +32 -0
  14. data/lib/jrubyfx/core_ext/duration.rb +30 -0
  15. data/lib/jrubyfx/core_ext/effects.rb +32 -0
  16. data/lib/jrubyfx/core_ext/exts.yml +57 -0
  17. data/lib/jrubyfx/core_ext/file_chooser.rb +63 -0
  18. data/lib/jrubyfx/core_ext/geometry.rb +27 -0
  19. data/lib/jrubyfx/core_ext/grid_pane.rb +30 -0
  20. data/lib/jrubyfx/core_ext/image_view.rb +25 -0
  21. data/lib/jrubyfx/core_ext/media_player.rb +25 -0
  22. data/lib/jrubyfx/core_ext/observable_value.rb +158 -0
  23. data/lib/jrubyfx/core_ext/pagination.rb +28 -0
  24. data/lib/jrubyfx/core_ext/path.rb +37 -0
  25. data/lib/jrubyfx/core_ext/precompiled.rb +1883 -0
  26. data/lib/jrubyfx/core_ext/progress_indicator.rb +41 -0
  27. data/lib/jrubyfx/core_ext/radial_gradient.rb +37 -0
  28. data/lib/jrubyfx/core_ext/region.rb +42 -0
  29. data/lib/jrubyfx/core_ext/rotate.rb +39 -0
  30. data/lib/jrubyfx/core_ext/stage.rb +89 -0
  31. data/lib/jrubyfx/core_ext/table_view.rb +31 -0
  32. data/lib/jrubyfx/core_ext/timeline.rb +56 -0
  33. data/lib/jrubyfx/core_ext/transition.rb +26 -0
  34. data/lib/jrubyfx/core_ext/tree_view.rb +40 -0
  35. data/lib/jrubyfx/core_ext/xy_chart.rb +53 -0
  36. data/lib/jrubyfx/dsl.rb +330 -0
  37. data/lib/jrubyfx/dsl_control.rb +28 -0
  38. data/lib/jrubyfx/dsl_map.rb +273 -0
  39. data/lib/jrubyfx/imports.rb +324 -0
  40. data/lib/jrubyfx/java_fx_impl.rb +144 -0
  41. data/lib/jrubyfx/module.rb +178 -0
  42. data/lib/jrubyfx/part_imports.rb +141 -0
  43. data/lib/jrubyfx/utils.rb +86 -0
  44. data/lib/jrubyfx/utils/__ignore_java_stupid_rdoc.rb +30 -0
  45. data/lib/jrubyfx/utils/common_converters.rb +223 -0
  46. data/lib/jrubyfx/utils/common_utils.rb +72 -0
  47. data/lib/jrubyfx/utils/string_utils.rb +48 -0
  48. data/lib/jrubyfx/version.rb +4 -0
  49. data/lib/jrubyfx_tasks.rb +183 -0
  50. metadata +145 -0
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env jruby
2
+ =begin
3
+ JRubyFX - Write JavaFX and FXML in Ruby
4
+ Copyright (C) 2013 The JRubyFX Team
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License");
7
+ you may not use this file except in compliance with the License.
8
+ You may obtain a copy of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS,
14
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ See the License for the specific language governing permissions and
16
+ limitations under the License.
17
+ =end
18
+
19
+ require 'jrubyfx_tasks'
20
+
21
+ def usage
22
+ puts "#{$0} {options} project-folder [output.jar]"
23
+ puts <<THEOPTIONS
24
+ project-folder should contain rb files and supporting files
25
+
26
+ -m|--main FILE ruby script to launch when the jar is executed.
27
+ Defaults to jar-bootstrap.rb or main.rb
28
+ -j|--include-jars Include jars in the jar. (off by default to prevent including
29
+ the jar you are building)
30
+ --native Create native application packages and installers. (Requires JDK8)
31
+ -v|--verbose Turns on the native packagers verbose mode. Useful for
32
+ customizing icons, licenses, etc.
33
+ --name STRING Name for your native package.
34
+ THEOPTIONS
35
+ exit -1
36
+ end
37
+
38
+ if ARGV.length < 1
39
+ usage
40
+ end
41
+
42
+ main = ["jar-bootstrap.rb", "main.rb"]
43
+ include_jars = false
44
+ native_bundle = false
45
+ app_name = ""
46
+ verbose = false
47
+ nargs = []
48
+ default_on_next = on_next = ->(arg){true}
49
+
50
+ # split the args manually
51
+ ARGV.each do |arg|
52
+ # some args have multiple parts. this is a cheap way to do that (lambdas)
53
+ next unless on_next.call(arg)
54
+ case arg
55
+ when "-m", "--main"
56
+ on_next = ->(arg){
57
+ main = [arg]
58
+ on_next = default_on_next
59
+ false
60
+ }
61
+ next
62
+ when "-j", "--include-jars"
63
+ include_jars = true
64
+ next
65
+ when "--native"
66
+ native_bundle = true
67
+ next
68
+ when "--name"
69
+ on_next = ->(arg){
70
+ app_name = [arg]
71
+ on_next = default_on_next
72
+ false
73
+ }
74
+ next
75
+ when "-v", "--verbose"
76
+ verbose = true
77
+ when "-h", "--help"
78
+ usage
79
+ exit 0
80
+ when /^-/
81
+ puts "ERROR! Unrecognized option '#{arg}'!"
82
+ exit -2
83
+ end
84
+ # no flag? must be positional arg
85
+ nargs << arg
86
+ end
87
+ # set jar default if none passed in
88
+ if nargs.length <= 1
89
+ nargs << File.basename(nargs[0]) + ".jar"
90
+ end
91
+ # set positional args
92
+ project_folder, output_jar = nargs
93
+
94
+ # Download the current running JRuby version
95
+ JRubyFX::Tasks::download_jruby(JRUBY_VERSION)
96
+
97
+ # set the main script to the first (must be passed in), or tries to find
98
+ # a file that does exists. Silently fails if it fails.
99
+ main_script = main[0]
100
+ if main.length > 1
101
+ main.each do |scrpt|
102
+ ps = project_folder + "/" + scrpt
103
+ if File.exists? ps
104
+ main_script = ps
105
+ break
106
+ end
107
+ end
108
+ end
109
+
110
+ # Jarify!
111
+ JRubyFX::Tasks::jarify_jrubyfx(project_folder + "/*", main_script, nil, output_jar, :file_filter => ->(filename){!filename.end_with?(".jar") or include_jars})
112
+
113
+ if native_bundle
114
+ JRubyFX::Tasks::native_bundles(Dir.pwd, output_jar, verbose, app_name[0])
115
+ end
@@ -0,0 +1,41 @@
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
+ if RUBY_VERSION.include? "1.8" or !JRUBY_VERSION
19
+ puts "JRubyFX requires JRuby to be in 1.9 mode"
20
+ exit -2
21
+ end
22
+ if Gem::Version.new(JRUBY_VERSION) < Gem::Version.new("1.7.4")
23
+ puts "Warning: JRuby 1.7.3 and prior have bugs that can cause strange errors. Do not submit any bug reports. Please use JRuby 1.7.4 or later."
24
+ end
25
+
26
+ require 'java' # for java_import
27
+ require 'jruby/core_ext' # for the become_java!
28
+
29
+ unless File.size? "#{File.dirname(__FILE__)}/jrubyfx/imports.rb"
30
+ puts "Please run `rake reflect` to generate the imports"
31
+ exit -1
32
+ end
33
+ # JRubyFX includes
34
+ require_relative 'jrubyfx/imports'
35
+ require_relative 'jrubyfx/module'
36
+ require_relative 'jrubyfx/dsl'
37
+ require_relative 'jrubyfx/dsl_control'
38
+ JRubyFX::DSL.load_dsl # load it after we require the dsl package to not loop around
39
+ require_relative 'jrubyfx/application'
40
+ require_relative 'jrubyfx/controller'
41
+ require_relative 'jrubyfx/java_fx_impl'
@@ -0,0 +1,42 @@
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
+ ##
19
+ # Inherit from this class for FXML Applications. You must use this class for both
20
+ # raw JavaFX and FXML as it contains the launch method.
21
+ class JRubyFX::Application < Java.javafx.application.Application
22
+ include JRubyFX
23
+ include JRubyFX::DSL
24
+
25
+ ##
26
+ # Are we packaged in a jar? This does some comparison, and may get false positives
27
+ # and, if jruby changes, false negatives. If you are using this, it might be a
28
+ # very bad idea... (though it is handy)
29
+ def self.in_jar?()
30
+ $LOAD_PATH.inject(false) { |res,i| res || i.include?("/META-INF/jruby.home/lib/ruby/")}
31
+ end
32
+
33
+ ##
34
+ # call-seq:
35
+ # launch()
36
+ #
37
+ # When called on a subclass, this is effectively our main method.
38
+ def self.launch(*args)
39
+ #call our custom launcher to avoid a java shim
40
+ JavaFXImpl::Launcher.launch_app(self, *args)
41
+ end
42
+ end
@@ -0,0 +1,51 @@
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
+ require 'jrubyfx'
18
+
19
+ # This class is used by the rake task to compile fxml files
20
+ class CompilerApp < JRubyFX::Application
21
+ def start(stage)
22
+ begin
23
+ args = parameters.raw.to_a
24
+ if args.include? "--"
25
+ ar, requires = split(args, "--")
26
+ requires.each {|x| require x}
27
+ ar
28
+ else
29
+ args
30
+ end.each do |arg|
31
+ loader = FxmlLoader.new
32
+ loader.location = URL.new "file:#{arg}"
33
+ loader.controller = Object.new
34
+ puts "Compiling #{arg}..."
35
+ loader.load(jruby_ext: {jit: 0, dont_load: true, jit_opts: {force: true}})
36
+ end
37
+ puts "done"
38
+ rescue java.lang.Throwable, Exception => e
39
+ $JRUBYFX_AOT_ERROR = e
40
+ ensure
41
+ Platform.exit
42
+ end
43
+ end
44
+
45
+ def split(arr, delim)
46
+ index = arr.index(delim)
47
+ first = arr[0...index]
48
+ second = arr[(index+1)..-1]
49
+ return first, second
50
+ end
51
+ end
@@ -0,0 +1,375 @@
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/utils/string_utils'
19
+ # If fxmlloader is installed, require it here
20
+ begin
21
+ require 'jrubyfx-fxmlloader'
22
+ rescue LoadError
23
+ # no fxmlloader, ignore it
24
+ end
25
+
26
+ # Special methods for fxml loading
27
+ module Kernel
28
+ @@jrubyfx_res_dir = {}
29
+ @@jrubyfx_fxml_res_cl = nil
30
+ def fxml_root(value=nil, jar_value=nil, class_loader = nil)
31
+ @@jrubyfx_fxml_res_cl = class_loader if class_loader
32
+ if value or jar_value
33
+ @@jrubyfx_fxml_dir = (JRubyFX::Application.in_jar? and jar_value) ? jar_value : File.expand_path(value)
34
+ else
35
+ @@jrubyfx_fxml_dir
36
+ end
37
+ end
38
+ def resource_root(res_name, value=nil, jar_value=nil)
39
+ if value or jar_value
40
+ @@jrubyfx_res_dir[res_name.to_sym] = (JRubyFX::Application.in_jar? and jar_value) ? jar_value : File.expand_path(value)
41
+ else
42
+ @@jrubyfx_res_dir[res_name.to_sym]
43
+ end
44
+ end
45
+ def get_fxml_resource_class_loader
46
+ @@jrubyfx_fxml_res_cl || JRuby.runtime.jruby_class_loader.method("get_resource")
47
+ end
48
+ def resource_url(type, relative_path)
49
+ if JRubyFX::Application.in_jar?
50
+ get_fxml_resource_class_loader.call("#{resource_root(type)}/#{relative_path}")
51
+ else
52
+ java.net.URL.new("file:" + File.join(resource_root(type), relative_path))
53
+ end
54
+ end
55
+ end
56
+
57
+ # Inherit from this class for FXML controllers
58
+ module JRubyFX::Controller
59
+ include JRubyFX::DSL
60
+ include JRubyFX::FXImports
61
+
62
+ java_import 'java.net.URL'
63
+
64
+ DEFAULT_SETTINGS = {
65
+ width: -1,
66
+ height: -1,
67
+ fill: :white,
68
+ depth_buffer: false,
69
+ root_dir: nil,
70
+ initialized: nil
71
+ }
72
+
73
+ # Controllers usually need access to the stage.
74
+ attr_writer :stage, :scene
75
+
76
+ def self.included(base)
77
+ base.extend(ClassMethods)
78
+ base.extend(JRubyFX::FXMLClassUtils) if defined? JRubyFX::FXMLClassUtils
79
+ base.extend(JRubyFX::FXImports)
80
+ # register ourselves as a control. overridable with custom_fxml_control
81
+ register_type base if base.is_a? Class
82
+ end
83
+
84
+ # class methods for FXML controllers
85
+ module ClassMethods
86
+ include JRubyFX::DSL
87
+
88
+ #nested including, TODO: don't duplicate this
89
+ def included(base)
90
+ base.extend(JRubyFX::Controller::ClassMethods)
91
+ # register ourselves as a control. overridable with custom_fxml_control
92
+ JRubyFX::DSL::ClassUtils.register_type base if base.is_a? Class
93
+ end
94
+
95
+ # Load given fxml file onto the given stage. `settings` is an optional hash of:
96
+ # * :initialize => [array of arguments to pass to the initialize function]
97
+ # * :width => Default width of the Scene
98
+ # * :height => Default height of the Scene
99
+ # * :fill => Fill color of the Scene's background
100
+ # * :depth_buffer => JavaFX Scene DepthBuffer argument (look it up)
101
+ # * :root_dir => filename search for fxml realtive to this file
102
+ #
103
+ # === Examples
104
+ #
105
+ # controller = MyFXController.new "Demo.fxml", stage
106
+ #
107
+ # === Equivalent Java
108
+ # Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
109
+ # Scene scene = new Scene(root);
110
+ # stage.setScene(scene);
111
+ # controller = root.getController();
112
+
113
+ def load_into(stage, settings={})
114
+ # Inherit from default settings
115
+ settings = DEFAULT_SETTINGS.merge({root_dir: (self.instance_variable_get("@fxml_root_dir") || fxml_root),
116
+ class_loader: (get_fxml_resource_class_loader),
117
+ filename: self.instance_variable_get("@filename")}).merge settings
118
+
119
+ # Custom controls don't always need to be pure java, but oh well...
120
+ become_java!
121
+
122
+ # like new, without initialize
123
+ ctrl = allocate
124
+
125
+ # Set the stage so we can reference it if needed later
126
+ ctrl.stage = stage
127
+
128
+ # load the FXML file
129
+ root = Controller.get_fxml_loader(settings[:filename], ctrl, settings[:root_dir], settings[:class_loader]).load
130
+
131
+ # Unless the FXML root node is a scene, wrap that node in a scene
132
+ if root.is_a? Scene
133
+ scene = root
134
+ else
135
+ scene = Scene.new root, settings[:width], settings[:height], settings[:depth_buffer]
136
+ scene.fill = settings[:fill]
137
+ end
138
+
139
+ # set the controller and stage scene
140
+ ctrl.scene = stage.scene = scene
141
+
142
+ ctrl.finish_initialization *settings[:initialize].to_a
143
+ end
144
+
145
+ # This is the default override for custom controls
146
+ # Normal FXML controllers will use Control#new
147
+ def new(*args, &block)
148
+ if @preparsed && @preparsed.length > 0
149
+ return @preparsed.pop.finish_initialization(*args, &block)
150
+ end
151
+ # Custom controls don't always need to be pure java, but oh well...
152
+ become_java! if @filename
153
+
154
+ # like new, without initialize
155
+ ctrl = allocate
156
+
157
+ ctrl.initialize_controller(DEFAULT_SETTINGS.merge({root_dir: @fxml_root_dir || fxml_root,
158
+ filename: @filename}),
159
+ *args, &block) if @filename
160
+
161
+ # return the controller
162
+ ctrl
163
+ end
164
+
165
+ def preparse_new(num=3)
166
+ become_java! if @filename
167
+ @preparsed ||= []
168
+ num.times do
169
+ ctrl = allocate
170
+ ctrl.pre_initialize_controller(DEFAULT_SETTINGS.merge({root_dir: @fxml_root_dir || fxml_root,
171
+ filename: @filename})) if @filename
172
+ @preparsed << ctrl
173
+ end
174
+ end
175
+
176
+ #decorator to force becoming java class
177
+ def become_java
178
+ @force_java = true
179
+ end
180
+
181
+ # Set the filename of the fxml this control is part of
182
+ def fxml(fxml=nil, name = nil, root_dir = nil)
183
+ @filename = fxml
184
+ # snag the filename from the caller
185
+ @fxml_root_dir = root_dir
186
+ register_type(self, name) if name
187
+ end
188
+
189
+ ##
190
+ # Event Handlers
191
+ ##
192
+
193
+ ##
194
+ # call-seq:
195
+ # on(callback, ...) { |event_info| block } => Method
196
+ #
197
+ # Registers a function of name `name` for a FXML defined event with the body in the block.
198
+ # Note you can also just use normal methods
199
+ #
200
+ # === Examples
201
+ # on :click do
202
+ # puts "button clicked"
203
+ # end
204
+ #
205
+ # on :moved, :pressed do |event|
206
+ # puts "Mouse Moved or Key Pressed"
207
+ # p event
208
+ # end
209
+ #
210
+ # === Equivalent Java
211
+ # @FXML
212
+ # private void click(ActionEvent event) {
213
+ # System.out.println("button clicked");
214
+ # }
215
+ #
216
+ # @FXML
217
+ # private void moved(MouseEvent event) {
218
+ # System.out.println("Mouse Moved or Key Pressed");
219
+ # }
220
+ #
221
+ # @FXML
222
+ # private void keypress(KeyEvent event) {
223
+ # System.out.println("Key Pressed or Key Pressed");
224
+ # }
225
+ #
226
+ def on(names, &block)
227
+ [names].flatten.each do |name|
228
+ class_eval do
229
+ # must define this way so block executes in class scope, not static scope
230
+ define_method name, block
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ #default java ctor, override for arguments
237
+ def java_ctor(ctor, initialize_arguments)
238
+ ctor.call
239
+ end
240
+
241
+ # Initialize all controllers
242
+ def initialize_controller(options={}, *args, &block)
243
+
244
+ # JRuby complains loudly (probably broken behavior) if we don't call the ctor
245
+ java_ctor self.class.superclass.instance_method(:initialize).bind(self), args
246
+
247
+ # load the FXML file with the current control as the root
248
+ load_fxml options[:filename], options[:root_dir]
249
+
250
+ finish_initialization *args, &block
251
+ end
252
+
253
+ # Initialize all controllers
254
+ def pre_initialize_controller(options={})
255
+
256
+ # JRuby complains loudly (probably broken behavior) if we don't call the ctor
257
+ java_ctor self.class.superclass.instance_method(:initialize).bind(self), [] #TODO: do we need to call this now with []?
258
+
259
+ # load the FXML file with the current control as the root
260
+ load_fxml options[:filename], options[:root_dir]
261
+ end
262
+
263
+ def load_fxml(filename, root_dir=nil)
264
+ fx = Controller.get_fxml_loader(filename, self, root_dir || @fxml_root_dir || fxml_root, get_fxml_resource_class_loader)
265
+ fx.root = self
266
+ fx.load
267
+ end
268
+
269
+ def finish_initialization(*args, &block)
270
+ @nodes_by_id = {}
271
+
272
+ # custom controls are their own scene
273
+ self.scene = self unless @scene
274
+
275
+ # Everything is ready, call initialize
276
+ if private_methods.include? :initialize
277
+ self.send :initialize, *args, &block
278
+ end
279
+
280
+ #return ourself
281
+ self
282
+ end
283
+
284
+ ##
285
+ # Node Lookup Methods
286
+ ##
287
+
288
+ # return first matched node or nil
289
+ def find(css_selector)
290
+ @scene.lookup(css_selector)
291
+ end
292
+
293
+ # Return first matched node or throw exception
294
+ def find!(css_selector)
295
+ res = find(css_selector)
296
+ raise "Selector(#{css_selector}) returned no results!" unless res
297
+ res
298
+ end
299
+
300
+ # return an array of matched nodes
301
+ def css(css_selector)
302
+ @scene.get_root.lookup_all(css_selector).to_a
303
+ end
304
+
305
+ # Loads a controller-less file
306
+ def self.load_fxml_only(filename, stage, settings={})
307
+ # Inherit from default settings
308
+ settings = DEFAULT_SETTINGS.merge({root_dir: fxml_root,
309
+ class_loader: get_fxml_resource_class_loader,
310
+ filename: filename}).merge settings
311
+
312
+ # load the FXML file
313
+ root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir], settings[:class_loader]).load
314
+
315
+ # TODO: de-duplicate this code
316
+
317
+ # Unless the FXML root node is a scene, wrap that node in a scene
318
+ if root.is_a? Scene
319
+ scene = root
320
+ else
321
+ scene = Scene.new root, settings[:width], settings[:height], settings[:depth_buffer]
322
+ scene.fill = settings[:fill]
323
+ end
324
+
325
+ # set the controller and stage scene
326
+ stage.scene = scene
327
+ end
328
+
329
+
330
+ ##
331
+ # call-seq:
332
+ # get_fxml_loader(filename) => FXMLLoader
333
+ # get_fxml_loader(filename, controller_instance) => FXMLLoader
334
+ # get_fxml_loader(filename, controller_instance, root_dir) => FXMLLoader
335
+ #
336
+ # Load a FXML file given a filename and a controller and return the loader
337
+ # root_dir is a directory that the file is relative to.
338
+ # === Examples
339
+ # root = JRubyFX::Controller.get_fxml_loader("Demo.fxml").load
340
+ #
341
+ # root = JRubyFX::Controller.get_fxml_loader("Demo.fxml", my_controller).load
342
+ #
343
+ # === Equivalent Java
344
+ # Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
345
+ #
346
+ def self.get_fxml_loader(filename, controller = nil, root_dir = nil, class_loader = JRuby.runtime.jruby_class_loader.method("get_resource"))
347
+ fx = FxmlLoader.new
348
+ fx.location = get_fxml_location(root_dir, filename, class_loader)
349
+ # we must set this here for JFX to call our events
350
+ fx.controller = controller
351
+ fx
352
+ end
353
+
354
+ def self.get_fxml_location(root_dir, filename, class_loader)
355
+ if JRubyFX::Application.in_jar? and filename.match(/^[^.\/]/)
356
+ # If we are in a jar file, use the class loader to get the file from the jar (like java)
357
+ # TODO: should just be able to use URLs
358
+
359
+ # According to how class loader works, the correct path for a file inside a jar is NOT "/folder/file.fxml"
360
+ # but "folder/file.fxml" (without starting "/" or ".", which would both make the path to be seen as a filesystem
361
+ # reference) so we assume that if root_dir is set to "" or to any other path not starting with "." or "/" then
362
+ # we want to point to a folder inside the jar, otherwise to a filesystem's one. According to this we format and
363
+ # feed the right path to the class loader.
364
+
365
+ location = class_loader.call(File.join(root_dir, filename))
366
+
367
+ # fall back if not found
368
+ return location if location
369
+ end
370
+
371
+ root_dir ||= fxml_root
372
+ # If we are in the normal filesystem, create a file url path relative to relative_to or this file
373
+ URL.new "file:#{File.join root_dir, filename}"
374
+ end
375
+ end