jrubyfx 0.9.2-java → 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
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