Class: JRubyFX::Controller
- Inherits:
-
Object
- Object
- JRubyFX::Controller
- Extended by:
- FXImports
- 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
Instance Attribute Summary collapse
-
#stage ⇒ Object
Controllers usually need access to the stage.
Class Method Summary collapse
-
.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.
-
.fx_id(*name) ⇒ Object
call-seq: fx_id :name, …
-
.fx_id_optional(*names) ⇒ Object
call-seq: fx_id_optional :name, …
-
.load_fxml(filename, stage, settings = {}) ⇒ Object
Load given fxml file onto the given stage.
-
.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.
-
.method_added(name) ⇒ Object
When initialize is defined, rename it to initialized, and restore initialize to default so java does not double call us.
-
.new(*args, &block) ⇒ Object
When FXMLLoader detects a method called initialze taking 0 args, then it calls it We don’t want this, as ruby new calls initialize Override new to avoid calling initialize.
-
.new_java(*args) ⇒ Object
Magic self-java-ifying new call.
Instance Method Summary collapse
-
#initialize ⇒ Controller
(also: #initialize_orig)
constructor
this is the default initialize that the FXML loader will call.
-
#initialize_fxml(*args) ⇒ Object
this is the default initialized method so we can always call it.
-
#scene ⇒ Object
Return the scene object (getter).
-
#scene=(s) ⇒ Object
Set scene object (setter), and update fxml-injected values.
Methods included from DSL
included, inject_enum_method_converter, inject_symbol_converter, load_dsl, load_enum_converter, #method_missing
Methods included from JRubyFX
Methods included from Utils::CommonUtils
#attempt_conversion, #populate_properties, #split_args_from_properties
Constructor Details
#initialize ⇒ Controller Also known as: initialize_orig
this is the default initialize that the FXML loader will call
133 134 |
# File 'lib/jrubyfx/fxml_controller.rb', line 133 def initialize() end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class JRubyFX::DSL
Instance Attribute Details
#stage ⇒ Object
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;
191 192 193 194 |
# File 'lib/jrubyfx/fxml_controller.rb', line 191 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;
209 210 211 |
# File 'lib/jrubyfx/fxml_controller.rb', line 209 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.
filenameis 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();
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/jrubyfx/fxml_controller.rb', line 267 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_ruby].to_a # 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 # instead of using the initializable interface, roll our own so we don't have to deal with java. ctrl.initialize_fxml(*settings[:initialize_fxml].to_a) # 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"));
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/jrubyfx/fxml_controller.rb', line 306 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 |
.method_added(name) ⇒ Object
When initialize is defined, rename it to initialized, and restore initialize to default so java does not double call us
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/jrubyfx/fxml_controller.rb', line 143 def self.method_added(name) if name == :initialize && !@in_alias puts <<WARNIT ***************************************************************************** ***************************************************************************** ** WARNING! WARNING! WARNING! WARNING! ** ** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! ** ** WARNING! WARNING! WARNING! WARNING! ** ***************************************************************************** ** ** ** You probably meant to define `initialize_fxml` instead of `initialize` ** ** `initialize` is ambiguous in JavaFX controllers as FXMLLoader will call ** ** it if it has 0 arguments in addition to it being ruby's constructor. ** ** If you need access to FXML elements (defined with `fx_id :myEltId`), ** ** then use `initialize_fxml`. If you need the ruby constructor, which ** ** does not have access to FXML yet, use `initialize_ruby` instead ** ** ** ** Assuming you wanted `initialize_fxml` for this run ** ** ** ***************************************************************************** ** WARNING! WARNING! WARNING! WARNING! ** ** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! ** ** WARNING! WARNING! WARNING! WARNING! ** ***************************************************************************** ***************************************************************************** WARNIT @in_alias = true alias_method :initialize_fxml_warn, :initialize alias_method :initialize, :initialize_orig @in_alias = false end end |
.new(*args, &block) ⇒ Object
When FXMLLoader detects a method called initialze taking 0 args, then it calls it We don’t want this, as ruby new calls initialize Override new to avoid calling initialize
126 127 128 129 130 |
# File 'lib/jrubyfx/fxml_controller.rb', line 126 def self.new(*args, &block) obj = self.allocate obj.send(:initialize_ruby, *args, &block) if defined? obj.initialize_ruby obj end |
.new_java(*args) ⇒ Object
Magic self-java-ifying new call. (Creates a Java instance)
242 243 244 245 |
# File 'lib/jrubyfx/fxml_controller.rb', line 242 def self.new_java(*args) self.become_java! self.new(*args) end |
Instance Method Details
#initialize_fxml(*args) ⇒ Object
this is the default initialized method so we can always call it
136 137 138 |
# File 'lib/jrubyfx/fxml_controller.rb', line 136 def initialize_fxml(*args) self.send(:initialize_fxml_warn, *args) if defined? initialize_fxml_warn end |
#scene ⇒ Object
Return the scene object (getter)
236 237 238 |
# File 'lib/jrubyfx/fxml_controller.rb', line 236 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.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/jrubyfx/fxml_controller.rb', line 216 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 |