Module: JRubyFX::DSL
- Includes:
- JRubyFX
- Included in:
- Application, Controller, Java::javafx::animation::ParallelTransition, Java::javafx::animation::Timeline, Java::javafx::scene::Node, Java::javafx::scene::Parent, Java::javafx::scene::Scene, Java::javafx::scene::chart::XYChart, Java::javafx::scene::chart::XYChart::Data, Java::javafx::scene::chart::XYChart::Series, Java::javafx::scene::control::Menu, Java::javafx::scene::control::MenuBar, Java::javafx::scene::control::MenuItem, Java::javafx::scene::control::TableView, Java::javafx::scene::control::TreeItem, Java::javafx::scene::control::TreeView, Java::javafx::scene::layout::BorderPane, Java::javafx::scene::shape::Path, Java::javafx::stage::FileChooser, Java::javafx::stage::Stage
- Defined in:
- lib/jrubyfx/dsl.rb
Overview
Defines a nice DSL for building JavaFX applications. Include it in a class for access to the DSL. JRubyFX::Application and JRubyFX::Controller include it already.
Defined Under Namespace
Modules: ClassUtils
Constant Summary collapse
- NAME_TO_CLASSES =
– FIXME: This should be broken up with nice override for each type of fx object so we can manually create static overrides. ++ The list of snake_case names mapped to full java classes to use for DSL mapping. This list is dynamically generated using JRubyFX::FXImports::JFX_CLASS_HIERARCHY and Hash.flat_tree_inject.
{ # observable structs 'observable_array_list' => proc { |*args| FXCollections.observable_array_list(*args) }, 'double_property' => SimpleDoubleProperty, 'xy_chart_series' => Java::javafx.scene.chart.XYChart::Series, 'xy_chart_data' => Java::javafx.scene.chart.XYChart::Data, }.merge(JFX_CLASS_HIERARCHY.flat_tree_inject(Hash) do |res, name, values| # Merge in auto-generated list of classes from all the imported classes unless values.is_a? Hash values.map do |i| # this regexp does snake_casing # TODO: Anybody got a better way to get the java class instead of evaling its name? res.merge!({i.snake_case.gsub(/(h|v)_(line|box)/, '\1\2') => eval(i)}) end res else # we are not at a leaf node anymore, merge in previous work res.merge!(values) end end)
- ENUM_OVERRIDES =
List of known overrides for enums.
{PathTransition::OrientationType => {:orthogonal_to_tangent => :orthogonal}, BlendMode => {:src_over => :over, :src_atop => :atop, :color_dodge => :dodge, :color_burn => :burn}, ContentDisplay => {:graphic_only => :graphic, :text_only => :text}, BlurType => {:one_pass_box => [:one, :one_pass], :two_pass_box => [:two, :two_pass], :three_pass_box => [:three, :three_pass]}, Modality => {:window_modal => :window, :application_modal => [:application, :app]}}
Constants included from JRubyFX
Constants included from FXImports
FXImports::JFX_CLASS_HIERARCHY
Class Method Summary collapse
-
.included(mod) ⇒ Object
When a class includes JRubyFX, extend (add to the metaclass) ClassUtils.
-
.inject_enum_method_converter(jfunc, in_class) ⇒ Object
“overrides” given function name in given class to parse ruby symbols into proper enums.
-
.inject_symbol_converter(jclass) ⇒ Object
Adds ‘parse_ruby_symbols` method to given enum/class to enable symbol conversion.
-
.load_dsl ⇒ Object
This loads the entire DSL.
-
.load_enum_converter ⇒ Object
Loads the special symbol to enum converter functions into all methods and enums.
Instance Method Summary collapse
-
#method_missing(name, *args, &block) ⇒ Object
(also: #node_method_missing)
This is the heart of the DSL.
Methods included from JRubyFX
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
#method_missing(name, *args, &block) ⇒ Object Also known as: node_method_missing
This is the heart of the DSL. When a method is missing and the name of the method is in the NAME_TO_CLASSES mapping, it calls JRubyFX.build with the Java class. This means that instead of saying
build(JavaClass, hash) { ... }
you can say
java_class(hash) { ... }
Another major portion of the DSL is the ability to implicitly add new created components to their parent on construction. There are a few places where this is undesirable. In order to prevent implicit construction you can add a ‘!’ on the end:
circle!(30)
This will construct a Circle but it will not add it into its parent container. This is useful for specifying clipping regions in particular.
171 172 173 174 175 176 |
# File 'lib/jrubyfx/dsl.rb', line 171 def method_missing(name, *args, &block) clazz = NAME_TO_CLASSES[name.to_s.gsub(/!$/, '')] super unless clazz build(clazz, *args, &block) end |
Class Method Details
.included(mod) ⇒ Object
When a class includes JRubyFX, extend (add to the metaclass) ClassUtils
117 118 119 |
# File 'lib/jrubyfx/dsl.rb', line 117 def self.included(mod) mod.extend(JRubyFX::DSL::ClassUtils) end |
.inject_enum_method_converter(jfunc, in_class) ⇒ Object
“overrides” given function name in given class to parse ruby symbols into proper enums. Rewrites method name as ‘my_method=` from `setMyMethod`
233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/jrubyfx/dsl.rb', line 233 def self.inject_enum_method_converter(jfunc, in_class) jclass = in_class.java_class.java_instance_methods.find_all {|i| i.name == jfunc.to_s}[0].argument_types[0] jclass = JavaUtilities.get_proxy_class(jclass) # Define the conversion function as the snake cased assignment, calling parse_ruby in_class.class_eval do define_method "#{jfunc.to_s.gsub(/^set/i,'').snake_case}=" do |rbenum| java_send jfunc, [jclass], jclass.parse_ruby_symbols(rbenum) end end end |
.inject_symbol_converter(jclass) ⇒ Object
Adds ‘parse_ruby_symbols` method to given enum/class to enable symbol conversion
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/jrubyfx/dsl.rb', line 220 def self.inject_symbol_converter(jclass) # inject! class << jclass define_method :parse_ruby_symbols do |const| # cache it. It could be expensive @map = JRubyFX::Utils::CommonConverters.map_enums(self) if @map == nil @map[const.to_s] || const end end end |
.load_dsl ⇒ Object
This loads the entire DSL. Call this immediately after requiring this file, but not inside this file, or it requires itself twice.
247 248 249 250 251 252 253 254 |
# File 'lib/jrubyfx/dsl.rb', line 247 def self.load_dsl rt = "#{File.dirname(__FILE__)}/core_ext" Dir.glob("#{rt}/*.rb") do |file| require file end JRubyFX::DSL.load_enum_converter() end |
.load_enum_converter ⇒ Object
Loads the special symbol to enum converter functions into all methods and enums
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/jrubyfx/dsl.rb', line 182 def self.load_enum_converter # load overrides ENUM_OVERRIDES.each do |cls, overrides| JRubyFX::Utils::CommonConverters.set_overrides_for cls, overrides end # use reflection to load all enums into all_enums and methods that use them # into enum_methods mod_list = { :methods => [], :all => [] } JRubyFX::DSL::NAME_TO_CLASSES.each do |n,cls| cls.java_class.java_instance_methods.each do |method| args = method.argument_types.find_all(&:enum?).tap {|i| mod_list[:all] << i } # one and only, must be a setter style if method.argument_types.length == 1 and (args.length == method.argument_types.length) mod_list[:methods] << [method.name, cls] end end if cls.respond_to? :ancestors and cls.ancestors.include? JavaProxy # some are not java classes. ignore those end # Get the proper class (only need them once) mod_list[:all] = mod_list[:all].flatten.uniq.map {|i| JavaUtilities.get_proxy_class(i) } # Inject our converter into each enum/class mod_list[:all].each do |enum| inject_symbol_converter enum end # finally, "override" each method mod_list[:methods].each do |method| inject_enum_method_converter *method end end |