jrubyfx 0.9.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +202 -0
- data/README.md +97 -0
- data/bin/jrubyfx-jarify +90 -0
- data/bin/rubyfx-generator +81 -0
- data/lib/jrubyfx.rb +27 -0
- data/lib/jrubyfx/core_ext/border_pane.rb +29 -0
- data/lib/jrubyfx/core_ext/circle.rb +26 -0
- data/lib/jrubyfx/core_ext/column_constraints.rb +41 -0
- data/lib/jrubyfx/core_ext/duration.rb +28 -0
- data/lib/jrubyfx/core_ext/effects.rb +30 -0
- data/lib/jrubyfx/core_ext/file_chooser.rb +60 -0
- data/lib/jrubyfx/core_ext/labeled.rb +24 -0
- data/lib/jrubyfx/core_ext/media_player.rb +23 -0
- data/lib/jrubyfx/core_ext/node.rb +24 -0
- data/lib/jrubyfx/core_ext/observable_value.rb +36 -0
- data/lib/jrubyfx/core_ext/pagination.rb +26 -0
- data/lib/jrubyfx/core_ext/parallel_transition.rb +28 -0
- data/lib/jrubyfx/core_ext/parent.rb +28 -0
- data/lib/jrubyfx/core_ext/path.rb +41 -0
- data/lib/jrubyfx/core_ext/progress_indicator.rb +38 -0
- data/lib/jrubyfx/core_ext/radial_gradient.rb +37 -0
- data/lib/jrubyfx/core_ext/region.rb +39 -0
- data/lib/jrubyfx/core_ext/rotate.rb +37 -0
- data/lib/jrubyfx/core_ext/scene.rb +29 -0
- data/lib/jrubyfx/core_ext/shape.rb +27 -0
- data/lib/jrubyfx/core_ext/stage.rb +77 -0
- data/lib/jrubyfx/core_ext/stop.rb +29 -0
- data/lib/jrubyfx/core_ext/table_view.rb +35 -0
- data/lib/jrubyfx/core_ext/timeline.rb +47 -0
- data/lib/jrubyfx/core_ext/transition.rb +25 -0
- data/lib/jrubyfx/core_ext/xy_chart.rb +53 -0
- data/lib/jrubyfx/dsl.rb +217 -0
- data/lib/jrubyfx/fxml_application.rb +44 -0
- data/lib/jrubyfx/fxml_controller.rb +270 -0
- data/lib/jrubyfx/fxml_module.rb +98 -0
- data/lib/jrubyfx/java_fx_impl.rb +139 -0
- data/lib/jrubyfx/jfx_imports.rb +107 -0
- data/lib/jrubyfx/utils.rb +56 -0
- data/lib/jrubyfx/utils/__ignore_java_stupid_rdoc.rb +24 -0
- data/lib/jrubyfx/utils/common_converters.rb +140 -0
- data/lib/jrubyfx/utils/common_utils.rb +72 -0
- data/lib/jrubyfx/version.rb +4 -0
- data/lib/jrubyfx_tasks.rb +110 -0
- metadata +116 -0
@@ -0,0 +1,25 @@
|
|
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
|
+
{:Rotate => :angle, :Scale => [:x, :y, :z], :Translate => [:x, :y, :z],
|
19
|
+
:Fade => :value, :Fill => :value, :Stroke => :value}.each do |clas, anim_props|
|
20
|
+
JavaUtilities.get_proxy_class("javafx.animation.#{clas}Transition").class_eval do
|
21
|
+
extend JRubyFX::Utils::CommonConverters
|
22
|
+
|
23
|
+
animation_converter_for *anim_props
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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/dsl'
|
18
|
+
|
19
|
+
# JRubyFX DSL extensions for JavaFX XYCharts
|
20
|
+
class Java::javafx::scene::chart::XYChart
|
21
|
+
include JRubyFX::DSL
|
22
|
+
|
23
|
+
##
|
24
|
+
# This will defer to node to construct proper object, but will
|
25
|
+
# optionally add paths primary child automatically if it is a
|
26
|
+
# PathElement.
|
27
|
+
def method_missing(name, *args, &block)
|
28
|
+
super.tap do |obj|
|
29
|
+
data.add(obj) if obj.kind_of? XYChart::Series
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# JRubyFX DSL extensions for JavaFX XYChart Series
|
35
|
+
class Java::javafx::scene::chart::XYChart::Series
|
36
|
+
include JRubyFX::DSL
|
37
|
+
|
38
|
+
##
|
39
|
+
# This will defer to node to construct proper object, but will
|
40
|
+
# optionally add paths primary child automatically if it is a
|
41
|
+
# PathElement.
|
42
|
+
def method_missing(name, *args, &block)
|
43
|
+
super.tap do |obj|
|
44
|
+
data.add(obj) if obj.kind_of? XYChart::Data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# JRubyFX DSL extensions for JavaFX XYChart Data
|
51
|
+
class Java::javafx::scene::chart::XYChart::Data
|
52
|
+
include JRubyFX::DSL
|
53
|
+
end
|
data/lib/jrubyfx/dsl.rb
ADDED
@@ -0,0 +1,217 @@
|
|
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 'java'
|
18
|
+
require 'jrubyfx'
|
19
|
+
|
20
|
+
module JRubyFX
|
21
|
+
# Defines a nice DSL for building JavaFX applications. Include it in a class for
|
22
|
+
# access to the DSL. JRubyFX::Application and JRubyFX::Controller include it already.
|
23
|
+
module DSL
|
24
|
+
include JRubyFX
|
25
|
+
|
26
|
+
# Contains methods to be defined inside all classes that include JRubyFX
|
27
|
+
module ClassUtils
|
28
|
+
include JRubyFX::FXImports
|
29
|
+
|
30
|
+
# Make sure we are added to the mapping. FIXME: is this ever used?
|
31
|
+
def register_type(name, type)
|
32
|
+
JRubyFX::DSL::NAME_TO_CLASSES[name.to_s] = type
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lots of DSL extensions use these methods, so define them here so multiple classes can use them
|
36
|
+
|
37
|
+
##
|
38
|
+
# call-seq:
|
39
|
+
# include_add
|
40
|
+
# include_add :child_getter
|
41
|
+
#
|
42
|
+
# Include a function to add to child list (optional argument) without need
|
43
|
+
# to ask for children
|
44
|
+
# include_add
|
45
|
+
# include_add :elements
|
46
|
+
#
|
47
|
+
def include_add(adder = :get_children)
|
48
|
+
self.class_eval do
|
49
|
+
define_method :add do |value|
|
50
|
+
self.send(adder) << value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Adds a function to the class that Adds rotate to transform (manually
|
57
|
+
# added ebcause there is a getRotate on Node already. Use get_rotate
|
58
|
+
# to get property
|
59
|
+
def include_rotate
|
60
|
+
self.class_eval do
|
61
|
+
def rotate(*args) #:nodoc:
|
62
|
+
transforms << build(Rotate, *args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Adds a method_missing that automatically calls add if the DSL builds it
|
69
|
+
# as the given type.
|
70
|
+
# This will defer to node to construct proper object, but will
|
71
|
+
# optionally add paths primary child automatically if it is a
|
72
|
+
# PathElement.
|
73
|
+
def include_method_missing(type)
|
74
|
+
self.class_eval do
|
75
|
+
define_method :method_missing do |name, *args, &block|
|
76
|
+
# we must manually call super otherwise it will call super(type)
|
77
|
+
super(name, *args, &block).tap do |obj|
|
78
|
+
add(obj) if obj.kind_of? type
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# When a class includes JRubyFX, extend (add to the metaclass) ClassUtils
|
86
|
+
def self.included(mod)
|
87
|
+
mod.extend(JRubyFX::DSL::ClassUtils)
|
88
|
+
end
|
89
|
+
|
90
|
+
#--
|
91
|
+
# FIXME: This should be broken up with nice override for each type of
|
92
|
+
# fx object so we can manually create static overrides.
|
93
|
+
#++
|
94
|
+
# The list of snake_case names mapped to full java classes to use for DSL mapping.
|
95
|
+
# This list is dynamically generated using JRubyFX::FXImports::JFX_CLASS_HIERARCHY and
|
96
|
+
# Hash.flat_tree_inject.
|
97
|
+
NAME_TO_CLASSES = {
|
98
|
+
# observable structs
|
99
|
+
'observable_array_list' => proc { |*args| FXCollections.observable_array_list(*args) },
|
100
|
+
'double_property' => SimpleDoubleProperty,
|
101
|
+
'xy_chart_series' => Java::javafx.scene.chart.XYChart::Series,
|
102
|
+
'xy_chart_data' => Java::javafx.scene.chart.XYChart::Data,
|
103
|
+
}.merge(JFX_CLASS_HIERARCHY.flat_tree_inject(Hash) do |res, name, values|
|
104
|
+
# Merge in auto-generated list of classes from all the imported classes
|
105
|
+
unless values.is_a? Hash
|
106
|
+
values.map do |i|
|
107
|
+
# this regexp does snake_casing
|
108
|
+
# TODO: Anybody got a better way to get the java class instead of evaling its name?
|
109
|
+
res.merge!({i.snake_case.gsub(/(h|v)_(line|box)/, '\1\2') => eval(i)})
|
110
|
+
end
|
111
|
+
res
|
112
|
+
else
|
113
|
+
# we are not at a leaf node anymore, merge in previous work
|
114
|
+
res.merge!(values)
|
115
|
+
end
|
116
|
+
end)
|
117
|
+
|
118
|
+
# List of known overrides for enums.
|
119
|
+
ENUM_OVERRIDES = {PathTransition::OrientationType => {:orthogonal_to_tangent => :orthogonal},
|
120
|
+
BlendMode => {:src_over => :over, :src_atop => :atop, :color_dodge => :dodge, :color_burn => :burn},
|
121
|
+
ContentDisplay => {:graphic_only => :graphic, :text_only => :text},
|
122
|
+
BlurType => {:one_pass_box => [:one, :one_pass], :two_pass_box => [:two, :two_pass], :three_pass_box => [:three, :three_pass]},
|
123
|
+
Modality => {:window_modal => :window, :application_modal => [:application, :app]}}
|
124
|
+
|
125
|
+
# This is the heart of the DSL. When a method is missing and the name of the
|
126
|
+
# method is in the NAME_TO_CLASSES mapping, it calls JRubyFX.build with the
|
127
|
+
# Java class. This means that instead of saying
|
128
|
+
# build(JavaClass, hash) { ... }
|
129
|
+
# you can say
|
130
|
+
# java_class(hash) { ... }
|
131
|
+
#
|
132
|
+
def method_missing(name, *args, &block)
|
133
|
+
clazz = NAME_TO_CLASSES[name.to_s]
|
134
|
+
super unless clazz
|
135
|
+
|
136
|
+
build(clazz, *args, &block)
|
137
|
+
end
|
138
|
+
|
139
|
+
alias :node_method_missing :method_missing
|
140
|
+
|
141
|
+
# Loads the special symbol to enum converter functions into all methods
|
142
|
+
# and enums
|
143
|
+
def self.load_enum_converter
|
144
|
+
# load overrides
|
145
|
+
ENUM_OVERRIDES.each do |cls, overrides|
|
146
|
+
JRubyFX::Utils::CommonConverters.set_overrides_for cls, overrides
|
147
|
+
end
|
148
|
+
|
149
|
+
# use reflection to load all enums into all_enums and methods that use them
|
150
|
+
# into enum_methods
|
151
|
+
mod_list = {
|
152
|
+
:methods => [],
|
153
|
+
:all => []
|
154
|
+
}
|
155
|
+
JRubyFX::DSL::NAME_TO_CLASSES.each do |n,cls|
|
156
|
+
cls.java_class.java_instance_methods.each do |method|
|
157
|
+
args = method.argument_types.find_all(&:enum?).tap {|i| mod_list[:all] << i }
|
158
|
+
|
159
|
+
# one and only, must be a setter style
|
160
|
+
if method.argument_types.length == 1 and (args.length == method.argument_types.length)
|
161
|
+
mod_list[:methods] << [method.name, cls]
|
162
|
+
end
|
163
|
+
end if cls.respond_to? :ancestors and cls.ancestors.include? JavaProxy # some are not java classes. ignore those
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get the proper class (only need them once)
|
167
|
+
mod_list[:all] = mod_list[:all].flatten.uniq.map {|i| JavaUtilities.get_proxy_class(i) }
|
168
|
+
|
169
|
+
# Inject our converter into each enum/class
|
170
|
+
mod_list[:all].each do |enum|
|
171
|
+
inject_symbol_converter enum
|
172
|
+
end
|
173
|
+
|
174
|
+
# finally, "override" each method
|
175
|
+
mod_list[:methods].each do |method|
|
176
|
+
inject_enum_method_converter *method
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Adds `parse_ruby_symbols` method to given enum/class to enable symbol conversion
|
181
|
+
def self.inject_symbol_converter(jclass)
|
182
|
+
# inject!
|
183
|
+
class << jclass
|
184
|
+
define_method :parse_ruby_symbols do |const|
|
185
|
+
# cache it. It could be expensive
|
186
|
+
@map = JRubyFX::Utils::CommonConverters.map_enums(self) if @map == nil
|
187
|
+
@map[const.to_s] || const
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# "overrides" given function name in given class to parse ruby symbols into
|
193
|
+
# proper enums. Rewrites method name as `my_method=` from `setMyMethod`
|
194
|
+
def self.inject_enum_method_converter(jfunc, in_class)
|
195
|
+
jclass = in_class.java_class.java_instance_methods.find_all {|i| i.name == jfunc.to_s}[0].argument_types[0]
|
196
|
+
jclass = JavaUtilities.get_proxy_class(jclass)
|
197
|
+
|
198
|
+
# Define the conversion function as the snake cased assignment, calling parse_ruby
|
199
|
+
in_class.class_eval do
|
200
|
+
define_method "#{jfunc.to_s.gsub(/^set/i,'').snake_case}=" do |rbenum|
|
201
|
+
java_send jfunc, [jclass], jclass.parse_ruby_symbols(rbenum)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# This loads the entire DSL. Call this immediately after requiring
|
207
|
+
# this file, but not inside this file, or it requires itself twice.
|
208
|
+
def self.load_dsl
|
209
|
+
rt = "#{File.dirname(__FILE__)}/core_ext/"
|
210
|
+
Dir.foreach rt do |file|
|
211
|
+
require_relative "core_ext/#{file}" unless [".", ".."].include? file
|
212
|
+
end
|
213
|
+
|
214
|
+
JRubyFX::DSL.load_enum_converter()
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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'
|
19
|
+
|
20
|
+
##
|
21
|
+
# Inherit from this class for FXML Applications. You must use this class for both
|
22
|
+
# raw JavaFX and FXML as it contains the launch method.
|
23
|
+
class JRubyFX::Application < Java.javafx.application.Application
|
24
|
+
include JRubyFX
|
25
|
+
include JRubyFX::DSL
|
26
|
+
|
27
|
+
##
|
28
|
+
# Are we packaged in a jar? This does some comparison, and may get false positives
|
29
|
+
# and, if jruby changes, false negatives. If you are using this, it might be a
|
30
|
+
# very bad idea... (though it is handy)
|
31
|
+
def self.in_jar?()
|
32
|
+
$LOAD_PATH.inject(false) { |res,i| res || i.include?(".jar!/META-INF/jruby.home/lib/ruby/")}
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# call-seq:
|
37
|
+
# launch()
|
38
|
+
#
|
39
|
+
# When called on a subclass, this is effectively our main method.
|
40
|
+
def self.launch(*args)
|
41
|
+
#call our custom launcher to avoid a java shim
|
42
|
+
JavaFXImpl::Launcher.launch_app(self, *args)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,270 @@
|
|
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'
|
19
|
+
|
20
|
+
# Inherit from this class for FXML controllers
|
21
|
+
class JRubyFX::Controller
|
22
|
+
include JRubyFX
|
23
|
+
include JRubyFX::DSL
|
24
|
+
java_import 'java.net.URL'
|
25
|
+
java_import 'javafx.fxml.FXMLLoader'
|
26
|
+
|
27
|
+
# Controllers usually need access to the stage.
|
28
|
+
attr_accessor :stage
|
29
|
+
|
30
|
+
##
|
31
|
+
# call-seq:
|
32
|
+
# fx_handler(callback) { |event_info| block } => Method
|
33
|
+
# fx_handler(callback, EventType) { |event_info| block } => Method
|
34
|
+
# fx_type_handler(callback) { |event_info| block } => Method
|
35
|
+
#
|
36
|
+
# Registers a function of name `name` for a FXML defined event with the body in the block
|
37
|
+
# Note: there are overrides for most of the default types, so you should never
|
38
|
+
# need to manually specify the `type` argument unless you have custom events.
|
39
|
+
# The overrides are in the format fx_*_handler where * is the event type (ex:
|
40
|
+
# fx_key_handler for KeyEvent).
|
41
|
+
# === Overloads
|
42
|
+
# * fx_key_handler is for KeyEvent
|
43
|
+
# * fx_mouse_handler is for MouseEvent
|
44
|
+
# * fx_touch_handler is for TouchEvent
|
45
|
+
# * fx_gesture_handler is for GestureEvent
|
46
|
+
# * fx_context_handler is for ContextMenuEvent
|
47
|
+
# * fx_context_menu_handler is for ContextMenuEvent
|
48
|
+
# * fx_drag_handler is for DragEvent
|
49
|
+
# * fx_ime_handler is for InputMethodEvent
|
50
|
+
# * fx_input_method_handler is for InputMethodEvent
|
51
|
+
# * fx_window_handler is for WindowEvent
|
52
|
+
# * fx_action_handler is for ActionEvent
|
53
|
+
# * fx_generic_handler is for Event
|
54
|
+
#
|
55
|
+
# === Examples
|
56
|
+
# fx_handler :click do
|
57
|
+
# puts "button clicked"
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# fx_mouse_handler :moved do |event|
|
61
|
+
# puts "Mouse Moved"
|
62
|
+
# p event
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# fx_key_handler :keypress do
|
66
|
+
# puts "Key Pressed"
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# === Equivalent Java
|
70
|
+
# @FXML
|
71
|
+
# private void click(ActionEvent event) {
|
72
|
+
# System.out.println("button clicked");
|
73
|
+
# }
|
74
|
+
#
|
75
|
+
# @FXML
|
76
|
+
# private void moved(MouseEvent event) {
|
77
|
+
# System.out.println("Mouse Moved");
|
78
|
+
# }
|
79
|
+
#
|
80
|
+
# @FXML
|
81
|
+
# private void keypress(KeyEvent event) {
|
82
|
+
# System.out.println("Key Pressed");
|
83
|
+
# }
|
84
|
+
#
|
85
|
+
def self.fx_handler(names, type=ActionEvent, &block)
|
86
|
+
[names].flatten.each do |name|
|
87
|
+
class_eval do
|
88
|
+
#must define this way so block executes in class scope, not static scope
|
89
|
+
define_method(name, block)
|
90
|
+
#the first arg is the return type, the rest are params
|
91
|
+
add_method_signature name, [Void::TYPE, type]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Get the singleton class, and add special overloads as fx_EVENT_handler
|
97
|
+
# This funky syntax allows us to define methods on self (like define_method("self.method"),
|
98
|
+
# except that does not work)
|
99
|
+
class << self
|
100
|
+
include JRubyFX::FXImports
|
101
|
+
{:key => KeyEvent,
|
102
|
+
:mouse => MouseEvent,
|
103
|
+
:touch => TouchEvent,
|
104
|
+
:gesture => GestureEvent,
|
105
|
+
:context => ContextMenuEvent,
|
106
|
+
:context_menu => ContextMenuEvent,
|
107
|
+
:drag => DragEvent,
|
108
|
+
:ime => InputMethodEvent,
|
109
|
+
:input_method => InputMethodEvent,
|
110
|
+
:window => WindowEvent,
|
111
|
+
:action => ActionEvent,
|
112
|
+
:generic => Event}.each do |method, klass|
|
113
|
+
#instance_eval on the self instance so that these are defined as class methods
|
114
|
+
self.instance_eval do
|
115
|
+
# define the handy overloads that just pass our arguments in
|
116
|
+
define_method("fx_#{method}_handler") do |name, &block|
|
117
|
+
fx_handler(name, klass, &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# FXML linked variable names by subclass
|
124
|
+
@@fxml_linked_args = {}
|
125
|
+
|
126
|
+
##
|
127
|
+
# call-seq:
|
128
|
+
# fx_id :name, ...
|
129
|
+
#
|
130
|
+
# Register one or more variable names to bind to a fx:id in the FXML file.
|
131
|
+
# === Example
|
132
|
+
# fx_id :myVar
|
133
|
+
#
|
134
|
+
# === Equivalent Java
|
135
|
+
# @FXML
|
136
|
+
# private ClassName myVar;
|
137
|
+
#
|
138
|
+
def self.fx_id(*name)
|
139
|
+
# we must distinguish between subclasses, hence self.
|
140
|
+
(@@fxml_linked_args[self] ||= []).concat(name)
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# call-seq:
|
145
|
+
# fx_id_optional :name, ...
|
146
|
+
#
|
147
|
+
# Register one or more variable name to bind to a fx:id in the FXML file if it exists.
|
148
|
+
# If the name cannot be found, don't complain.
|
149
|
+
# === Example
|
150
|
+
# fx_id_optional :myVar
|
151
|
+
#
|
152
|
+
# === Equivalent Java
|
153
|
+
# @FXML
|
154
|
+
# private ClassName myVar;
|
155
|
+
#
|
156
|
+
def self.fx_id_optional(*names)
|
157
|
+
fx_id *names.map {|i| {i => :quiet} }
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Set scene object (setter), and update fxml-injected values. If you are manually
|
162
|
+
# loading FXML, you MUST call this to link `fx_id` specified names.
|
163
|
+
def scene=(s)
|
164
|
+
@scene = s
|
165
|
+
(@@fxml_linked_args[self.class] ||= []).each do |name|
|
166
|
+
quiet = false
|
167
|
+
# you can specify name => [quiet/verbose], so we need to check for that
|
168
|
+
if name.is_a? Hash
|
169
|
+
quiet = name.values[0] == :quiet
|
170
|
+
name = name.keys[0]
|
171
|
+
end
|
172
|
+
# set each instance variable from the lookup on the scene
|
173
|
+
val = s.lookup("##{name}")
|
174
|
+
if val == nil && !quiet
|
175
|
+
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)"
|
176
|
+
end
|
177
|
+
instance_variable_set("@#{name}".to_sym, val)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Return the scene object (getter)
|
183
|
+
def scene()
|
184
|
+
@scene
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Magic self-java-ifying new call. (Creates a Java instance)
|
189
|
+
def self.new_java(*args)
|
190
|
+
self.become_java!
|
191
|
+
self.new(*args)
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# Load given fxml file onto the given stage. `settings` is an optional hash of:
|
196
|
+
# * :initialize => [array of arguments to pass to the initialize function]
|
197
|
+
# * :width => Default width of the Scene
|
198
|
+
# * :height => Default height of the Scene
|
199
|
+
# * :fill => Fill color of the Scene's background
|
200
|
+
# * :depth_buffer => JavaFX Scene DepthBuffer argument (look it up)
|
201
|
+
# * :relative_to => number of calls back, or filename. `filename` is evaluated
|
202
|
+
# as being relative to this. Default is relative to caller (1)
|
203
|
+
# Returns a scene, either a new one, or the FXML root if its a Scene.
|
204
|
+
# === Examples
|
205
|
+
#
|
206
|
+
# controller = MyFXController.load_fxml("Demo.fxml", stage)
|
207
|
+
#
|
208
|
+
# === Equivalent Java
|
209
|
+
# Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
|
210
|
+
# Scene scene = new Scene(root);
|
211
|
+
# stage.setScene(scene);
|
212
|
+
# controller = root.getController();
|
213
|
+
#
|
214
|
+
def self.load_fxml(filename, stage, settings={})
|
215
|
+
# Create our class as a java class with any arguments it wants
|
216
|
+
ctrl = self.new_java *(settings[:initialize] || [])
|
217
|
+
# save the stage so we can reference it if needed later
|
218
|
+
ctrl.stage = stage
|
219
|
+
# load the FXML file
|
220
|
+
parent = load_fxml_resource(filename, ctrl, settings[:relative_to] || 1)
|
221
|
+
# set the controller and stage scene, so that all the fx_id variables are hooked up
|
222
|
+
ctrl.scene = stage.scene = if parent.is_a? Scene
|
223
|
+
parent
|
224
|
+
elsif settings.has_key? :fill
|
225
|
+
Scene.new(parent, settings[:width] || -1, settings[:height] || -1, settings[:fill] || Color::WHITE)
|
226
|
+
else
|
227
|
+
Scene.new(parent, settings[:width] || -1, settings[:height] || -1, settings[:depth_buffer] || settings[:depthBuffer] || false)
|
228
|
+
end
|
229
|
+
# return the controller. If they want the new scene, they can call the scene() method on it
|
230
|
+
return ctrl
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# call-seq:
|
235
|
+
# load_fxml_resource(filename) => Parent
|
236
|
+
# load_fxml_resource(filename, controller_instance) => Parent
|
237
|
+
# load_fxml_resource(filename, controller_instance, relative_to) => Parent
|
238
|
+
#
|
239
|
+
# Load a FXML file given a filename and a controller and return the root element
|
240
|
+
# relative_to can be a file that this should be relative to, or an index
|
241
|
+
# of the caller number. If you are calling this from a function, pass 0
|
242
|
+
# as you are the immediate caller of this function.
|
243
|
+
# === Examples
|
244
|
+
# root = JRubyFX::Controller.load_fxml_resource("Demo.fxml")
|
245
|
+
#
|
246
|
+
# root = JRubyFX::Controller.load_fxml_resource("Demo.fxml", my_controller)
|
247
|
+
#
|
248
|
+
# === Equivalent Java
|
249
|
+
# Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
|
250
|
+
#
|
251
|
+
def self.load_fxml_resource(filename, ctrlr=nil, relative_to=0)
|
252
|
+
fx = FXMLLoader.new()
|
253
|
+
fx.location = if JRubyFX::Application.in_jar?
|
254
|
+
# If we are in a jar file, use the class loader to get the file from the jar (like java)
|
255
|
+
JRuby.runtime.jruby_class_loader.get_resource(filename)
|
256
|
+
else
|
257
|
+
if relative_to.is_a? Fixnum or relative_to == nil
|
258
|
+
# caller[0] returns a string like so:
|
259
|
+
# "/home/user/.rvm/rubies/jruby-1.7.1/lib/ruby/1.9/irb/workspace.rb:80:in `eval'"
|
260
|
+
# and then we use a regex to filter out the filename
|
261
|
+
relative_to = caller[relative_to||0][/(.*):[0-9]+:in /, 1] # the 1 is the first match, aka everything up to the :
|
262
|
+
end
|
263
|
+
# If we are in the normal filesystem, create a normal file url path relative to the main file
|
264
|
+
URL.new(URL.new("file:"), "#{File.dirname(relative_to)}/#{filename}")
|
265
|
+
end
|
266
|
+
# we must set this here for JFX to call our events
|
267
|
+
fx.controller = ctrlr
|
268
|
+
return fx.load()
|
269
|
+
end
|
270
|
+
end
|