jrubyfx 0.9.2-java → 1.0.0-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.
Files changed (47) hide show
  1. data/README.md +19 -17
  2. data/bin/jrubyfx-generator +28 -11
  3. data/lib/jrubyfx.rb +8 -4
  4. data/lib/jrubyfx/{fxml_application.rb → application.rb} +0 -2
  5. data/lib/jrubyfx/controller.rb +307 -0
  6. data/lib/jrubyfx/core_ext/border_pane.rb +0 -1
  7. data/lib/jrubyfx/core_ext/duration.rb +1 -1
  8. data/lib/jrubyfx/core_ext/exts.yml +53 -0
  9. data/lib/jrubyfx/core_ext/image_view.rb +1 -0
  10. data/lib/jrubyfx/core_ext/observable_value.rb +69 -2
  11. data/lib/jrubyfx/core_ext/path.rb +0 -6
  12. data/lib/jrubyfx/core_ext/precompiled.rb +501 -0
  13. data/lib/jrubyfx/core_ext/stage.rb +12 -0
  14. data/lib/jrubyfx/core_ext/table_view.rb +0 -4
  15. data/lib/jrubyfx/core_ext/timeline.rb +3 -7
  16. data/lib/jrubyfx/dsl.rb +168 -150
  17. data/lib/jrubyfx/dsl_map.rb +267 -0
  18. data/lib/jrubyfx/imports.rb +64 -0
  19. data/lib/jrubyfx/java_fx_impl.rb +0 -1
  20. data/lib/jrubyfx/module.rb +172 -0
  21. data/lib/jrubyfx/{jfx_imports.rb → part_imports.rb} +17 -9
  22. data/lib/jrubyfx/utils.rb +13 -4
  23. data/lib/jrubyfx/utils/common_converters.rb +45 -13
  24. data/lib/jrubyfx/utils/common_utils.rb +1 -1
  25. data/lib/jrubyfx/version.rb +1 -1
  26. data/lib/jrubyfx_tasks.rb +9 -1
  27. metadata +69 -55
  28. data/lib/jrubyfx/core_ext/circle.rb +0 -26
  29. data/lib/jrubyfx/core_ext/drag_event.rb~ +0 -32
  30. data/lib/jrubyfx/core_ext/image_view.rb~ +0 -24
  31. data/lib/jrubyfx/core_ext/labeled.rb +0 -24
  32. data/lib/jrubyfx/core_ext/menu.rb +0 -25
  33. data/lib/jrubyfx/core_ext/menu.rb~ +0 -26
  34. data/lib/jrubyfx/core_ext/menu_bar.rb +0 -25
  35. data/lib/jrubyfx/core_ext/menu_bar.rb~ +0 -24
  36. data/lib/jrubyfx/core_ext/menu_item.rb +0 -22
  37. data/lib/jrubyfx/core_ext/node.rb +0 -26
  38. data/lib/jrubyfx/core_ext/parallel_transition.rb +0 -28
  39. data/lib/jrubyfx/core_ext/parent.rb +0 -28
  40. data/lib/jrubyfx/core_ext/scene.rb +0 -29
  41. data/lib/jrubyfx/core_ext/shape.rb +0 -29
  42. data/lib/jrubyfx/core_ext/stop.rb +0 -31
  43. data/lib/jrubyfx/core_ext/tree_item.rb +0 -25
  44. data/lib/jrubyfx/core_ext/tree_item.rb~ +0 -25
  45. data/lib/jrubyfx/core_ext/tree_view.rb~ +0 -33
  46. data/lib/jrubyfx/fxml_controller.rb +0 -325
  47. data/lib/jrubyfx/fxml_module.rb +0 -98
@@ -74,4 +74,16 @@ class Java::javafx::stage::Stage
74
74
  root = code.arity == 1 ? code[node] : instance_eval(&code)
75
75
  build(Scene, root, *args).tap { |scene| set_scene scene }
76
76
  end
77
+
78
+ def fxml(source, options={})
79
+ if source.is_a? String
80
+ JRubyFX::Controller.load_fxml_only(source, self, options)
81
+ else
82
+ source.load_into self, options
83
+ end
84
+ end
85
+
86
+ def fxml=(source)
87
+ fxml(source)
88
+ end
77
89
  end
@@ -20,12 +20,8 @@ require 'jrubyfx/dsl'
20
20
  class Java::javafx::scene::control::TableView
21
21
  java_import Java::javafx.scene.control.TableColumn
22
22
 
23
- include JRubyFX::DSL
24
23
  extend JRubyFX::Utils::CommonConverters
25
24
 
26
- include_add :get_columns
27
- include_method_missing TableColumn
28
-
29
25
  resize_policy = map_converter(unconstrained_resize_policy: UNCONSTRAINED_RESIZE_POLICY,
30
26
  constrained_resize_policy: CONSTRAINED_RESIZE_POLICY,
31
27
  unconstrained: UNCONSTRAINED_RESIZE_POLICY,
@@ -20,19 +20,15 @@ require 'jrubyfx/dsl'
20
20
  class Java::javafx::animation::Timeline
21
21
  java_import Java::javafx.animation.KeyFrame
22
22
 
23
- include JRubyFX::DSL
24
23
  extend JRubyFX::Utils::CommonConverters
25
24
 
26
- include_add :key_frames
27
- include_method_missing KeyFrame
28
-
29
25
  # call-seq:
30
26
  # animate myProperty, from_duration => to_duration, start_value => next_value
31
27
  # animate myProperty, from_duration => [with_duration, ..., to_duration], start_value => [next_value, ...]
32
- #
28
+ #
33
29
  # Animates a given JavaFX property over the given duration, using the given values
34
30
  # as keyFrames
35
- #
31
+ #
36
32
  # === Examples
37
33
  # animate translateXProperty, 0.sec => [100.ms, 1.sec], 0 => [500, 200]
38
34
  # animate translateYProperty, 0.sec => 1.sec, 0 => 200
@@ -55,6 +51,6 @@ class Java::javafx::animation::Timeline
55
51
  key_frame(time[i], key_value(prop, values[i]))
56
52
  end
57
53
  end
58
-
54
+
59
55
  converter_for :cycle_count, [map_converter(indefinite: Java::javafx::animation::Timeline::INDEFINITE)]
60
56
  end
data/lib/jrubyfx/dsl.rb CHANGED
@@ -15,7 +15,6 @@ See the License for the specific language governing permissions and
15
15
  limitations under the License.
16
16
  =end
17
17
  require 'java'
18
- require 'jrubyfx'
19
18
 
20
19
  module JRubyFX
21
20
  # Defines a nice DSL for building JavaFX applications. Include it in a class for
@@ -26,14 +25,14 @@ module JRubyFX
26
25
  # Contains methods to be defined inside all classes that include JRubyFX
27
26
  module ClassUtils
28
27
  include JRubyFX::FXImports
29
-
28
+
30
29
  ##
31
30
  # Register your own type for use in the DSL.
32
31
  #
33
32
  # class MyFooWidget < Region
34
33
  # #...
35
34
  # end
36
- # #...
35
+ # #...
37
36
  # register_type(MyFooWidget)
38
37
  # register_type(MyFooWidget, "aliased_name")
39
38
  #
@@ -44,73 +43,7 @@ module JRubyFX
44
43
  name = type.name.snake_case unless name
45
44
  JRubyFX::DSL::NAME_TO_CLASSES[name.to_s] = type
46
45
  end
47
-
48
- ##
49
- # Define a dual-mode method which acts as both a getter and
50
- # setter depending on whether it has been supplied an argument
51
- # or not.
52
- #
53
- def getter_setter(name)
54
- self.class_eval do
55
- # FIXME: Is arity of splat the best way to do this?
56
- define_method(name) do |*r|
57
- if r.length > 0
58
- set_effect *r
59
- else
60
- get_effect
61
- end
62
- end
63
- end
64
- end
65
-
66
- # Lots of DSL extensions use these methods, so define them here so multiple classes can use them
67
-
68
- ##
69
- # call-seq:
70
- # include_add
71
- # include_add :child_getter
72
- #
73
- # Include a function to add to child list (optional argument) without need
74
- # to ask for children
75
- # include_add
76
- # include_add :elements
77
- #
78
- def include_add(adder = :get_children)
79
- self.class_eval do
80
- define_method :add do |value|
81
- self.send(adder) << value
82
- end
83
- end
84
- end
85
-
86
- ##
87
- # Adds a function to the class that Adds rotate to transform (manually
88
- # added ebcause there is a getRotate on Node already. Use get_rotate
89
- # to get property
90
- def include_rotate
91
- self.class_eval do
92
- def rotate(*args) #:nodoc:
93
- transforms << build(Rotate, *args)
94
- end
95
- end
96
- end
97
-
98
- ##
99
- # Adds a method_missing that automatically calls add if the DSL builds it
100
- # as the given type.
101
- # This will defer to node to construct proper object, but will
102
- # optionally add paths primary child automatically if it is a
103
- # PathElement.
104
- def include_method_missing(type)
105
- self.class_eval do
106
- define_method :method_missing do |name, *args, &block|
107
- # we must manually call super otherwise it will call super(type)
108
- super(name, *args, &block).tap do |obj|
109
- add(obj) if obj.kind_of?(type) && !name.to_s.end_with?('!')
110
- end
111
- end
112
- end
113
- end
46
+ module_function :register_type
114
47
  end
115
48
 
116
49
  # When a class includes JRubyFX, extend (add to the metaclass) ClassUtils
@@ -119,39 +52,14 @@ module JRubyFX
119
52
  end
120
53
 
121
54
  #--
122
- # FIXME: This should be broken up with nice override for each type of
55
+ # FIXME: This should be broken up with nice override for each type of
123
56
  # fx object so we can manually create static overrides.
124
57
  #++
125
58
  # The list of snake_case names mapped to full java classes to use for DSL mapping.
126
- # This list is dynamically generated using JRubyFX::FXImports::JFX_CLASS_HIERARCHY and
127
- # Hash.flat_tree_inject.
128
- NAME_TO_CLASSES = {
129
- # observable structs
130
- 'observable_array_list' => proc { |*args| FXCollections.observable_array_list(*args) },
131
- 'double_property' => SimpleDoubleProperty,
132
- 'xy_chart_series' => Java::javafx.scene.chart.XYChart::Series,
133
- 'xy_chart_data' => Java::javafx.scene.chart.XYChart::Data,
134
- }.merge(JFX_CLASS_HIERARCHY.flat_tree_inject(Hash) do |res, name, values|
135
- # Merge in auto-generated list of classes from all the imported classes
136
- unless values.is_a? Hash
137
- values.map do |i|
138
- # this regexp does snake_casing
139
- # TODO: Anybody got a better way to get the java class instead of evaling its name?
140
- res.merge!({i.snake_case.gsub(/(h|v)_(line|box)/, '\1\2') => eval(i)})
141
- end
142
- res
143
- else
144
- # we are not at a leaf node anymore, merge in previous work
145
- res.merge!(values)
146
- end
147
- end)
148
-
59
+ # This list is dynamically generated using the `rake reflect` task.
60
+ require_relative 'dsl_map'
61
+
149
62
  # List of known overrides for enums.
150
- ENUM_OVERRIDES = {PathTransition::OrientationType => {:orthogonal_to_tangent => :orthogonal},
151
- BlendMode => {:src_over => :over, :src_atop => :atop, :color_dodge => :dodge, :color_burn => :burn},
152
- ContentDisplay => {:graphic_only => :graphic, :text_only => :text},
153
- BlurType => {:one_pass_box => [:one, :one_pass], :two_pass_box => [:two, :two_pass], :three_pass_box => [:three, :three_pass]},
154
- Modality => {:window_modal => :window, :application_modal => [:application, :app]}}
155
63
 
156
64
  # This is the heart of the DSL. When a method is missing and the name of the
157
65
  # method is in the NAME_TO_CLASSES mapping, it calls JRubyFX.build with the
@@ -162,7 +70,7 @@ module JRubyFX
162
70
  #
163
71
  # Another major portion of the DSL is the ability to implicitly add new
164
72
  # created components to their parent on construction. There are a few
165
- # places where this is undesirable. In order to prevent implicit
73
+ # places where this is undesirable. In order to prevent implicit
166
74
  # construction you can add a '!' on the end:
167
75
  # circle!(30)
168
76
  # This will construct a Circle but it will not add it into its parent
@@ -170,87 +78,197 @@ module JRubyFX
170
78
  #
171
79
  def method_missing(name, *args, &block)
172
80
  clazz = NAME_TO_CLASSES[name.to_s.gsub(/!$/, '')]
81
+
82
+ if caller[0] == caller[2]
83
+ raise "Whoa! method_missing caught infinite loop. Trying to run #{name}(#{args.inspect}) failed. Method not found."
84
+ end
85
+
173
86
  super unless clazz
174
-
87
+
175
88
  build(clazz, *args, &block)
176
89
  end
177
90
 
178
91
  alias :node_method_missing :method_missing
179
-
180
- # Loads the special symbol to enum converter functions into all methods
92
+
93
+ # Loads the special symbol to enum converter functions into all methods
181
94
  # and enums
182
- def self.load_enum_converter
183
- # load overrides
184
- ENUM_OVERRIDES.each do |cls, overrides|
185
- JRubyFX::Utils::CommonConverters.set_overrides_for cls, overrides
186
- end
187
-
95
+ def self.write_enum_converter(outf)
96
+
188
97
  # use reflection to load all enums into all_enums and methods that use them
189
98
  # into enum_methods
190
99
  mod_list = {
191
- :methods => [],
100
+ :methods =>{},
192
101
  :all => []
193
102
  }
194
103
  JRubyFX::DSL::NAME_TO_CLASSES.each do |n,cls|
195
104
  cls.java_class.java_instance_methods.each do |method|
196
105
  args = method.argument_types.find_all(&:enum?).tap {|i| mod_list[:all] << i }
197
-
106
+
198
107
  # one and only, must be a setter style
199
- if method.argument_types.length == 1 and (args.length == method.argument_types.length)
200
- mod_list[:methods] << [method.name, cls]
108
+ if method.argument_types.length == 1 and (args.length == method.argument_types.length) and !(cls.ancestors[1].public_instance_methods.include? method.name.to_sym)
109
+ mod_list[:methods][cls] = [] unless mod_list[:methods][cls]
110
+ # stuff both method name and the type of the argument in
111
+ mod_list[:methods][cls] << [method.name, JavaUtilities.get_proxy_class(args[0])]
201
112
  end
202
113
  end if cls.respond_to? :ancestors and cls.ancestors.include? JavaProxy # some are not java classes. ignore those
203
114
  end
204
-
205
- # Get the proper class (only need them once)
206
- mod_list[:all] = mod_list[:all].flatten.uniq.map {|i| JavaUtilities.get_proxy_class(i) }
207
-
208
- # Inject our converter into each enum/class
209
- mod_list[:all].each do |enum|
210
- inject_symbol_converter enum
211
- end
212
-
115
+
116
+ require 'yaml'
117
+
118
+ child_catcher = {}
119
+
120
+
121
+
213
122
  # finally, "override" each method
214
- mod_list[:methods].each do |method|
215
- inject_enum_method_converter *method
123
+ mod_list[:methods].each do |clz, method|
124
+ child_catcher[clz.to_s] = "" unless child_catcher[clz.to_s]
125
+ write_enum_method_converter child_catcher, clz, method
216
126
  end
127
+ # cleanout and search for colors. TODO: combind with previous
128
+ mod_list = {:methods =>{}, :all => []}
129
+ JRubyFX::DSL::NAME_TO_CLASSES.each do |n,cls|
130
+ cls.java_class.java_instance_methods.each do |method|
131
+ args = method.argument_types.find_all{|i| JavaUtilities.get_proxy_class(i).ancestors.include? Java::javafx.scene.paint.Paint}
132
+
133
+ # one and only, must be a setter style
134
+ if args.length == 1 and !(cls.ancestors[1].public_instance_methods.include? method.name.to_sym) #TODO: multiple args
135
+ mod_list[:methods][cls] = [] unless mod_list[:methods][cls]
136
+ # stuff both method name and the type of the argument in
137
+ mod_list[:methods][cls] << method.name
138
+ end
139
+ end if cls.respond_to? :ancestors and cls.ancestors.include? JavaProxy # some are not java classes. ignore those
140
+ end
141
+
142
+ mod_list[:methods].each do |clz, method|
143
+ child_catcher[clz.to_s] = "" unless child_catcher[clz.to_s]
144
+ write_color_method_converter child_catcher, clz, method
145
+ end
146
+
147
+ # load the yaml descriptors
148
+
149
+ ydescs = YAML.load_file("#{File.dirname(__FILE__)}/core_ext/exts.yml")
150
+
151
+ builders = {add: ->(on, adder){
152
+ " def add(value)
153
+ #{adder}() << value
154
+ end\n"
155
+ },
156
+ rotate: ->(on){
157
+ " def rotate(*args)
158
+ transforms << build(Rotate, *args)
159
+ end\n"
160
+ },
161
+ method_missing: ->(on, type) {
162
+ # we must manually call super otherwise it will call super(type)
163
+ " def method_missing(name, *args, &block)
164
+ super(name, *args, &block).tap do |obj|
165
+ add(obj) if obj.kind_of?(#{type}) && !name.to_s.end_with?('!')
217
166
  end
218
-
219
- # Adds `parse_ruby_symbols` method to given enum/class to enable symbol conversion
220
- def self.inject_symbol_converter(jclass)
221
- # inject!
222
- class << jclass
223
- define_method :parse_ruby_symbols do |const|
224
- # cache it. It could be expensive
225
- @map = JRubyFX::Utils::CommonConverters.map_enums(self) if @map == nil
226
- @map[const.to_s] || const
167
+ end\n"
168
+ },
169
+ logical_child: ->(on, prop_name){" #TODO: logical_child(#{prop_name})\n"},
170
+ logical_children: ->(on, prop_name){" #TODO: logical_children(#{prop_name})\n"},
171
+ getter_setter: ->(on, name) {
172
+ # FIXME: Is arity of splat the best way to do this?
173
+ " def #{name}(*r)
174
+ if r.length > 0
175
+ self.#{name} = r[0]
176
+ else
177
+ get_#{name}
178
+ end
179
+ end\n"
180
+ },
181
+ new_converter: ->(on, *args){
182
+ els = 0
183
+ " def self.new(*args)
184
+ super *JRubyFX::Utils::CommonConverters.convert_args(args, #{args.map{|i|i.map(&:to_sym)}.inspect})
185
+ end\n"
186
+ },
187
+ dsl: ->(on, *args){" "},
188
+ }
189
+
190
+ #parse the ydescs
191
+ ydescs.each do |clz, acts|
192
+ acts.each do |mname, arg|
193
+ child_catcher[clz] = "" unless child_catcher[clz]
194
+ lamb = builders[mname.to_sym]
195
+ arg = [arg] unless arg.is_a? Array
196
+ child_catcher[clz] << lamb.call(*([clz] + arg))
227
197
  end
228
198
  end
199
+
200
+ child_catcher.each do |clz, defs|
201
+ next if defs == "" || defs == nil
202
+ # TODO: do we need to include the dsl? is this the fastest way to do it?
203
+ outf<< <<HERDOC
204
+ class #{clz}
205
+ include JRubyFX::DSL
206
+ #{defs}end
207
+ HERDOC
208
+ end
229
209
  end
230
-
231
- # "overrides" given function name in given class to parse ruby symbols into
232
- # proper enums. Rewrites method name as `my_method=` from `setMyMethod`
233
- def self.inject_enum_method_converter(jfunc, in_class)
234
- jclass = in_class.java_class.java_instance_methods.find_all {|i| i.name == jfunc.to_s}[0].argument_types[0]
235
- jclass = JavaUtilities.get_proxy_class(jclass)
236
-
237
- # Define the conversion function as the snake cased assignment, calling parse_ruby
238
- in_class.class_eval do
239
- define_method "#{jfunc.to_s.gsub(/^set/i,'').snake_case}=" do |rbenum|
240
- java_send jfunc, [jclass], jclass.parse_ruby_symbols(rbenum)
241
- end
210
+
211
+ def self.write_enum_method_converter(outf, in_class, jfuncnclasses)
212
+ jfuncnclasses.each do |jfunc, jclass|
213
+ next if jfunc.include? "impl_"
214
+ outf[in_class.to_s] << <<ENDNAIVE
215
+ def #{jfunc.to_s.gsub(/^set/i,'').snake_case}=(rbenum)
216
+ java_send #{jfunc.inspect}, [#{jclass}], JRubyFX::Utils::CommonConverters.parse_ruby_symbols(rbenum, #{jclass})
217
+ end
218
+ ENDNAIVE
219
+ end
220
+ end
221
+
222
+ def self.write_color_method_converter(outf, in_class, jfuncnclasses)
223
+ jfuncnclasses.each do |jfunc|
224
+ next if jfunc.include? "impl_"
225
+ outf[in_class.to_s] << <<ENDNAIVE
226
+ def #{jfunc.to_s.gsub(/^set/i,'').snake_case}=(value)
227
+ #{jfunc}(JRubyFX::Utils::CommonConverters::CONVERTERS[:color].call(value))
228
+ end
229
+ ENDNAIVE
230
+ end
231
+ end
232
+
233
+ def self_test_lookup(selector)
234
+ if selector.start_with? "#"
235
+ return (if "##{self.id}" == selector
236
+ self
237
+ else
238
+ nil
239
+ end)
242
240
  end
243
241
  end
244
-
245
- # This loads the entire DSL. Call this immediately after requiring
242
+
243
+ def logical_lookup(*args)
244
+ unless self.is_a?(Node)
245
+ p self
246
+ p self.to_s
247
+ return self_test_lookup(*args)
248
+ end
249
+ self.lookup(*args) || self.tap do |x|
250
+ return nil unless x.respond_to? :children
251
+ return x.children.map_find{|i| i.logical_lookup(*args)}
252
+ end
253
+ end
254
+
255
+ # This loads the entire DSL. Call this immediately after requiring
246
256
  # this file, but not inside this file, or it requires itself twice.
247
257
  def self.load_dsl
248
- rt = "#{File.dirname(__FILE__)}/core_ext"
258
+ unless File.size? "#{File.dirname(__FILE__)}/core_ext/precompiled.rb"
259
+ puts "Please run `rake reflect` to generate the converters"
260
+ exit -1
261
+ end
262
+ rt = "#{File.dirname(__FILE__)}/core_ext".sub /\Ajar:/, ""
249
263
  Dir.glob("#{rt}/*.rb") do |file|
250
264
  require file
251
265
  end
252
-
253
- JRubyFX::DSL.load_enum_converter()
266
+ end
267
+
268
+ # This loads the entire DSL. Call this immediately after requiring
269
+ # this file, but not inside this file, or it requires itself twice.
270
+ def self.compile_dsl(out)
271
+ JRubyFX::DSL.write_enum_converter out
254
272
  end
255
273
  end
256
274
  end