Class: JRubyFX::Controller

Inherits:
Object
  • Object
show all
Extended by:
FXImports
Includes:
JRubyFX, DSL
Defined in:
lib/jrubyfx/fxml_controller.rb

Overview

Inherit from this class for FXML controllers

Constant Summary collapse

@@fxml_linked_args =

FXML linked variable names by subclass

{}

Constants included from FXImports

FXImports::JFX_CLASS_HIERARCHY

Constants included from DSL

DSL::ENUM_OVERRIDES, DSL::NAME_TO_CLASSES

Constants included from JRubyFX

VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DSL

included, inject_enum_method_converter, inject_symbol_converter, load_dsl, load_enum_converter, #method_missing

Methods included from JRubyFX

#build, #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

#stageObject

Controllers usually need access to the stage.



28
29
30
# File 'lib/jrubyfx/fxml_controller.rb', line 28

def stage
  @stage
end

Class Method Details

.fx_handler(names, type = ActionEvent, &block) ⇒ Object

call-seq:

fx_handler(callback) { |event_info| block } => Method
fx_handler(callback, EventType) { |event_info| block } => Method
fx_type_handler(callback) { |event_info| block } => Method

Registers a function of name name for a FXML defined event with the body in the block Note: there are overrides for most of the default types, so you should never need to manually specify the type argument unless you have custom events. The overrides are in the format fx_*_handler where * is the event type (ex: fx_key_handler for KeyEvent).

Overloads

  • fx_key_handler is for KeyEvent

  • fx_mouse_handler is for MouseEvent

  • fx_touch_handler is for TouchEvent

  • fx_gesture_handler is for GestureEvent

  • fx_context_handler is for ContextMenuEvent

  • fx_context_menu_handler is for ContextMenuEvent

  • fx_drag_handler is for DragEvent

  • fx_ime_handler is for InputMethodEvent

  • fx_input_method_handler is for InputMethodEvent

  • fx_window_handler is for WindowEvent

  • fx_action_handler is for ActionEvent

  • fx_generic_handler is for Event

Examples

fx_handler :click do
  puts "button clicked"
end

fx_mouse_handler :moved do |event|
  puts "Mouse Moved"
  p event
end

fx_key_handler :keypress do
  puts "Key Pressed"
end

Equivalent Java

@FXML
private void click(ActionEvent event) {
  System.out.println("button clicked");
}

@FXML
private void moved(MouseEvent event) {
  System.out.println("Mouse Moved");
}

@FXML
private void keypress(KeyEvent event) {
  System.out.println("Key Pressed");
}


85
86
87
88
89
90
91
92
93
94
# File 'lib/jrubyfx/fxml_controller.rb', line 85

def self.fx_handler(names, type=ActionEvent, &block)
  [names].flatten.each do |name|
    class_eval do
      #must define this way so block executes in class scope, not static scope
      define_method(name, block)
      #the first arg is the return type, the rest are params
      add_method_signature name, [Void::TYPE, type]
    end
  end
end

.fx_id(*name) ⇒ Object

call-seq:

fx_id :name, ...

Register one or more variable names to bind to a fx:id in the FXML file.

Example

fx_id :myVar

Equivalent Java

@FXML
private ClassName myVar;


138
139
140
141
# File 'lib/jrubyfx/fxml_controller.rb', line 138

def self.fx_id(*name)
  # we must distinguish between subclasses, hence self.
  (@@fxml_linked_args[self] ||= []).concat(name)
end

.fx_id_optional(*names) ⇒ Object

call-seq:

fx_id_optional :name, ...

Register one or more variable name to bind to a fx:id in the FXML file if it exists. If the name cannot be found, don’t complain.

Example

fx_id_optional :myVar

Equivalent Java

@FXML
private ClassName myVar;


156
157
158
# File 'lib/jrubyfx/fxml_controller.rb', line 156

def self.fx_id_optional(*names)
  fx_id *names.map {|i| {i => :quiet} }
end

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

Load given fxml file onto the given stage. settings is an optional hash of:

  • :initialize => [array of arguments to pass to the initialize function]

  • :width => Default width of the Scene

  • :height => Default height of the Scene

  • :fill => Fill color of the Scene’s background

  • :depth_buffer => JavaFX Scene DepthBuffer argument (look it up)

  • :relative_to => number of calls back, or filename. filename is evaluated as being relative to this. Default is relative to caller (1)

Returns a scene, either a new one, or the FXML root if its a Scene.

Examples

controller = MyFXController.load_fxml("Demo.fxml", stage)

Equivalent Java

Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
controller = root.getController();


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/jrubyfx/fxml_controller.rb', line 214

def self.load_fxml(filename, stage, settings={})
  # Create our class as a java class with any arguments it wants
  ctrl = self.new_java *(settings[:initialize] || [])
  # save the stage so we can reference it if needed later
  ctrl.stage = stage
  # load the FXML file
  parent = load_fxml_resource(filename, ctrl, settings[:relative_to] || 1)
  # set the controller and stage scene, so that all the fx_id variables are hooked up
  ctrl.scene = stage.scene = if parent.is_a? Scene
    parent
  elsif settings.has_key? :fill
    Scene.new(parent, settings[:width] || -1, settings[:height] || -1, settings[:fill] || Color::WHITE)
  else
    Scene.new(parent, settings[:width] || -1, settings[:height] || -1, settings[:depth_buffer] || settings[:depthBuffer] || false)
  end
  # return the controller. If they want the new scene, they can call the scene() method on it
  return ctrl
end

.load_fxml_resource(filename, ctrlr = nil, relative_to = 0) ⇒ Object

call-seq:

load_fxml_resource(filename) => Parent
load_fxml_resource(filename, controller_instance) => Parent
load_fxml_resource(filename, controller_instance, relative_to) => Parent

Load a FXML file given a filename and a controller and return the root element relative_to can be a file that this should be relative to, or an index of the caller number. If you are calling this from a function, pass 0 as you are the immediate caller of this function.

Examples

root = JRubyFX::Controller.load_fxml_resource("Demo.fxml")

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

Equivalent Java

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


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/jrubyfx/fxml_controller.rb', line 251

def self.load_fxml_resource(filename, ctrlr=nil, relative_to=0)
  fx = FXMLLoader.new()
  fx.location = if JRubyFX::Application.in_jar?
    # If we are in a jar file, use the class loader to get the file from the jar (like java)
    JRuby.runtime.jruby_class_loader.get_resource(filename)
  else
    if relative_to.is_a? Fixnum or relative_to == nil
      # caller[0] returns a string like so:
      # "/home/user/.rvm/rubies/jruby-1.7.1/lib/ruby/1.9/irb/workspace.rb:80:in `eval'"
      # and then we use a regex to filter out the filename
      relative_to = caller[relative_to||0][/(.*):[0-9]+:in /, 1] # the 1 is the first match, aka everything up to the :
    end
    # If we are in the normal filesystem, create a normal file url path relative to the main file
    URL.new(URL.new("file:"), "#{File.dirname(relative_to)}/#{filename}")
  end
  # we must set this here for JFX to call our events
  fx.controller = ctrlr
  return fx.load()
end

.new_java(*args) ⇒ Object

Magic self-java-ifying new call. (Creates a Java instance)



189
190
191
192
# File 'lib/jrubyfx/fxml_controller.rb', line 189

def self.new_java(*args)
  self.become_java!
  self.new(*args)
end

Instance Method Details

#sceneObject

Return the scene object (getter)



183
184
185
# File 'lib/jrubyfx/fxml_controller.rb', line 183

def scene()
  @scene
end

#scene=(s) ⇒ Object

Set scene object (setter), and update fxml-injected values. If you are manually loading FXML, you MUST call this to link fx_id specified names.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/jrubyfx/fxml_controller.rb', line 163

def scene=(s)
  @scene = s
  (@@fxml_linked_args[self.class] ||= []).each do |name|
    quiet = false
    # you can specify name => [quiet/verbose], so we need to check for that
    if name.is_a? Hash
      quiet = name.values[0] == :quiet
      name = name.keys[0]
    end
    # set each instance variable from the lookup on the scene
    val = s.lookup("##{name}")
    if val == nil && !quiet
      puts "[WARNING] fx_id not found: #{name}. Is id set to a different value than fx:id? (if this is expected, use fx_id_optional)"
    end
    instance_variable_set("@#{name}".to_sym, val)
  end
end