Module: JRubyFX::Controller

Includes:
DSL, FXImports
Defined in:
lib/jrubyfx/controller.rb

Overview

Inherit from this class for FXML controllers

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

DEFAULT_SETTINGS =
{
  width: -1,
  height: -1,
  fill: :white,
  depth_buffer: false,
  root_dir: nil,
  initialized: nil
}

Constants included from FXImports

FXImports::JFX_CLASS_HIERARCHY, FXImports::LOCAL_NAME_MAP

Constants included from DSL

DSL::NAME_TO_CLASSES, DSL::NAME_TO_CLASS_NAME

Constants included from JRubyFX

VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FXImports

#const_missing

Methods included from DSL

compile_dsl, load_dsl, #logical_lookup, #method_missing, #self_test_lookup, write_color_method_converter, write_enum_converter, write_enum_method_converter, write_event_method

Methods included from JRubyFX

#build, load_fx, #run_later, #with

Methods included from Utils::CommonUtils

#attempt_conversion, #populate_properties, #split_args_from_properties

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class JRubyFX::DSL

Instance Attribute Details

#scene=(value) ⇒ Object (writeonly)

Controllers usually need access to the stage.



74
75
76
# File 'lib/jrubyfx/controller.rb', line 74

def scene=(value)
  @scene = value
end

#stage=(value) ⇒ Object (writeonly)

Controllers usually need access to the stage.



74
75
76
# File 'lib/jrubyfx/controller.rb', line 74

def stage=(value)
  @stage = value
end

Class Method Details

.get_fxml_loader(filename, controller = nil, root_dir = nil, class_loader = JRuby.runtime.jruby_class_loader.method("get_resource")) ⇒ Object

call-seq:

get_fxml_loader(filename) => FXMLLoader
get_fxml_loader(filename, controller_instance) => FXMLLoader
get_fxml_loader(filename, controller_instance, root_dir) => FXMLLoader

Load a FXML file given a filename and a controller and return the loader root_dir is a directory that the file is relative to.

Examples

root = JRubyFX::Controller.get_fxml_loader("Demo.fxml").load

root = JRubyFX::Controller.get_fxml_loader("Demo.fxml", my_controller).load

Equivalent Java

Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));


346
347
348
349
350
351
352
# File 'lib/jrubyfx/controller.rb', line 346

def self.get_fxml_loader(filename, controller = nil, root_dir = nil, class_loader = JRuby.runtime.jruby_class_loader.method("get_resource"))
  fx = FxmlLoader.new
  fx.location = get_fxml_location(root_dir, filename, class_loader)
  # we must set this here for JFX to call our events
  fx.controller = controller
  fx
end

.get_fxml_location(root_dir, filename, class_loader) ⇒ Object



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/jrubyfx/controller.rb', line 354

def self.get_fxml_location(root_dir, filename, class_loader)
  if JRubyFX::Application.in_jar? and filename.match(/^[^.\/]/)
    # If we are in a jar file, use the class loader to get the file from the jar (like java)
    # TODO: should just be able to use URLs
    
    # According to how class loader works, the correct path for a file inside a jar is NOT "/folder/file.fxml" 
    # but "folder/file.fxml" (without starting "/" or ".", which would both make the path to be seen as a filesystem 
    # reference) so we assume that if root_dir is set to "" or to any other path not starting with "." or "/" then 
    # we want to point to a folder inside the jar, otherwise to a filesystem's one. According to this we format and 
    # feed the right path to the class loader.
    
    location = class_loader.call(File.join(root_dir, filename))
    
    # fall back if not found
    return location if location
  end
  
  root_dir ||= fxml_root
  # If we are in the normal filesystem, create a file url path relative to relative_to or this file
  URL.new "file:#{File.join root_dir, filename}"
end

.included(base) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/jrubyfx/controller.rb', line 76

def self.included(base)
  base.extend(ClassMethods)
  base.extend(JRubyFX::FXMLClassUtils) if defined? JRubyFX::FXMLClassUtils
  base.extend(JRubyFX::FXImports)
  # register ourselves as a control. overridable with custom_fxml_control
  register_type base if base.is_a? Class
end

.load_fxml_only(filename, stage, settings = {}) ⇒ Object

Loads a controller-less file



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/jrubyfx/controller.rb', line 306

def self.load_fxml_only(filename, stage, settings={})
  # Inherit from default settings
  settings = DEFAULT_SETTINGS.merge({root_dir: fxml_root,
  	class_loader: get_fxml_resource_class_loader,
      filename: filename}).merge settings

  # load the FXML file
  root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir], settings[:class_loader]).load

  # TODO: de-duplicate this code

  # Unless the FXML root node is a scene, wrap that node in a scene
  if root.is_a? Scene
    scene = root
  else
    scene = Scene.new root, settings[:width], settings[:height], settings[:depth_buffer]
    scene.fill = settings[:fill]
  end

  # set the controller and stage scene
  stage.scene = scene
end

Instance Method Details

#css(css_selector) ⇒ Object

return an array of matched nodes



301
302
303
# File 'lib/jrubyfx/controller.rb', line 301

def css(css_selector)
  @scene.get_root.lookup_all(css_selector).to_a
end

#find(css_selector) ⇒ Object

return first matched node or nil



289
290
291
# File 'lib/jrubyfx/controller.rb', line 289

def find(css_selector)
  @scene.lookup(css_selector)
end

#find!(css_selector) ⇒ Object

Return first matched node or throw exception



294
295
296
297
298
# File 'lib/jrubyfx/controller.rb', line 294

def find!(css_selector)
  res = find(css_selector)
  raise "Selector(#{css_selector}) returned no results!" unless res
  res
end

#finish_initialization(*args, &block) ⇒ Object



269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/jrubyfx/controller.rb', line 269

def finish_initialization(*args, &block)
  @nodes_by_id = {}

  # custom controls are their own scene
  self.scene = self unless @scene

  # Everything is ready, call initialize
  if private_methods.include? :initialize
    self.send :initialize, *args, &block
  end

  #return ourself
  self
end

#initialize_controller(options = {}, *args, &block) ⇒ Object

Initialize all controllers



242
243
244
245
246
247
248
249
250
251
# File 'lib/jrubyfx/controller.rb', line 242

def initialize_controller(options={}, *args, &block)

  # JRuby complains loudly (probably broken behavior) if we don't call the ctor
  java_ctor self.class.superclass.instance_method(:initialize).bind(self), args

  # load the FXML file with the current control as the root
  load_fxml options[:filename], options[:root_dir]

  finish_initialization *args, &block
end

#java_ctor(ctor, initialize_arguments) ⇒ Object

default java ctor, override for arguments



237
238
239
# File 'lib/jrubyfx/controller.rb', line 237

def java_ctor(ctor, initialize_arguments)
  ctor.call
end

#load_fxml(filename, root_dir = nil) ⇒ Object



263
264
265
266
267
# File 'lib/jrubyfx/controller.rb', line 263

def load_fxml(filename, root_dir=nil)
  fx = Controller.get_fxml_loader(filename, self, root_dir || @fxml_root_dir || fxml_root, get_fxml_resource_class_loader)
  fx.root = self
  fx.load
end

#pre_initialize_controller(options = {}) ⇒ Object

Initialize all controllers



254
255
256
257
258
259
260
261
# File 'lib/jrubyfx/controller.rb', line 254

def pre_initialize_controller(options={})

  # JRuby complains loudly (probably broken behavior) if we don't call the ctor
  java_ctor self.class.superclass.instance_method(:initialize).bind(self), [] #TODO: do we need to call this now with []?

  # load the FXML file with the current control as the root
  load_fxml options[:filename], options[:root_dir]
end