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, get_resources = JRuby.runtime.jruby_class_loader.method("get_resource"), fxml_class_loader = nil) ⇒ 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"));


377
378
379
380
381
382
383
# File 'lib/jrubyfx/controller.rb', line 377

def self.get_fxml_loader(filename, controller = nil, root_dir = nil, get_resources = JRuby.runtime.jruby_class_loader.method("get_resource"), fxml_class_loader=nil)
  fx = javafx.fxml.FXMLLoader.new(get_fxml_location(root_dir, filename, get_resources))
	fx.class_loader = fxml_class_loader unless fxml_class_loader.nil?
  # we must set this here for JFX to call our events
  fx.controller = controller
  fx
end

.get_fxml_location(root_dir, filename, get_resources) ⇒ Object



385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/jrubyfx/controller.rb', line 385

def self.get_fxml_location(root_dir, filename, get_resources)
  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 = get_resources.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
83
84
85
86
# 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)
  base.configure_java_class ctor_name: "java_ctor" do
    dispatch :initialize, :fx_initialize # we want to load our code before calling user code
    # un-exclude "initialize"
  end
  # 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



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/jrubyfx/controller.rb', line 334

def self.load_fxml_only(filename, stage, settings={})
  # Inherit from default settings
  settings = DEFAULT_SETTINGS.merge({root_dir: fxml_root,
  	get_resources: get_fxml_resource_class_loader,
      fxml_class_loader: get_fxml_classes_class_loader,
      filename: filename}).merge settings
        
  raise "JRubyFX 1.x style class loader argument passed into 'load_fxml_only'. Replace 'class_loader' with either 'get_resources' (likely) or 'fxml_class_loader' (less likely)" if settings.has_key? :class_loader
  
  # load the FXML file
  root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir], settings[:get_resources], settings[:fxml_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



329
330
331
# File 'lib/jrubyfx/controller.rb', line 329

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

#find(css_selector) ⇒ Object

return first matched node or nil



317
318
319
# File 'lib/jrubyfx/controller.rb', line 317

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

#find!(css_selector) ⇒ Object

Return first matched node or throw exception



322
323
324
325
326
# File 'lib/jrubyfx/controller.rb', line 322

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

#finish_initialization(*args, &block) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/jrubyfx/controller.rb', line 297

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 or methods.include? :initialize
    self.send :initialize, *args, &block
  end

  #return ourself
  self
end

#fx_initializeObject

java initialize is redirected to here



260
261
262
# File 'lib/jrubyfx/controller.rb', line 260

def fx_initialize()
  # Do nothing, as we already control initialization
end

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

Initialize all controllers



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

def initialize_controller(options={}, *args, &block)
  
  # JRuby complains loudly (probably broken behavior) if we don't call the ctor
  __jallocate!() # TODO: args? TODO: non-java controllers?*args) # TODO: remove

  # 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(*initialize_arguments) ⇒ Object

default java ctor, override for arguments



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

def java_ctor(*initialize_arguments)
  super()
end

#load_fxml(filename, root_dir = nil) ⇒ Object



291
292
293
294
295
# File 'lib/jrubyfx/controller.rb', line 291

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, get_fxml_classes_class_loader)
  fx.root = self
  fx.load
end

#pre_initialize_controller(options = {}) ⇒ Object

Initialize all controllers



282
283
284
285
286
287
288
289
# File 'lib/jrubyfx/controller.rb', line 282

def pre_initialize_controller(options={})

  # JRuby complains loudly (probably broken behavior) if we don't call the ctor
  java_ctor self.class.instance_method(:__jallocate!).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