jrubyfx-openjfx.patch 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +202 -0
  3. data/README.md +121 -0
  4. data/bin/jrubyfx-compile +32 -0
  5. data/bin/jrubyfx-generator +98 -0
  6. data/bin/jrubyfx-jarify +115 -0
  7. data/lib/jrubyfx.rb +41 -0
  8. data/lib/jrubyfx/application.rb +42 -0
  9. data/lib/jrubyfx/compiler_app.rb +51 -0
  10. data/lib/jrubyfx/controller.rb +375 -0
  11. data/lib/jrubyfx/core_ext/border_pane.rb +30 -0
  12. data/lib/jrubyfx/core_ext/column_constraints.rb +43 -0
  13. data/lib/jrubyfx/core_ext/drag_event.rb +32 -0
  14. data/lib/jrubyfx/core_ext/duration.rb +30 -0
  15. data/lib/jrubyfx/core_ext/effects.rb +32 -0
  16. data/lib/jrubyfx/core_ext/exts.yml +57 -0
  17. data/lib/jrubyfx/core_ext/file_chooser.rb +63 -0
  18. data/lib/jrubyfx/core_ext/geometry.rb +27 -0
  19. data/lib/jrubyfx/core_ext/grid_pane.rb +30 -0
  20. data/lib/jrubyfx/core_ext/image_view.rb +25 -0
  21. data/lib/jrubyfx/core_ext/media_player.rb +25 -0
  22. data/lib/jrubyfx/core_ext/observable_value.rb +158 -0
  23. data/lib/jrubyfx/core_ext/pagination.rb +28 -0
  24. data/lib/jrubyfx/core_ext/path.rb +37 -0
  25. data/lib/jrubyfx/core_ext/precompiled.rb +1883 -0
  26. data/lib/jrubyfx/core_ext/progress_indicator.rb +41 -0
  27. data/lib/jrubyfx/core_ext/radial_gradient.rb +37 -0
  28. data/lib/jrubyfx/core_ext/region.rb +42 -0
  29. data/lib/jrubyfx/core_ext/rotate.rb +39 -0
  30. data/lib/jrubyfx/core_ext/stage.rb +89 -0
  31. data/lib/jrubyfx/core_ext/table_view.rb +31 -0
  32. data/lib/jrubyfx/core_ext/timeline.rb +56 -0
  33. data/lib/jrubyfx/core_ext/transition.rb +26 -0
  34. data/lib/jrubyfx/core_ext/tree_view.rb +40 -0
  35. data/lib/jrubyfx/core_ext/xy_chart.rb +53 -0
  36. data/lib/jrubyfx/dsl.rb +330 -0
  37. data/lib/jrubyfx/dsl_control.rb +28 -0
  38. data/lib/jrubyfx/dsl_map.rb +273 -0
  39. data/lib/jrubyfx/imports.rb +324 -0
  40. data/lib/jrubyfx/java_fx_impl.rb +144 -0
  41. data/lib/jrubyfx/module.rb +178 -0
  42. data/lib/jrubyfx/part_imports.rb +141 -0
  43. data/lib/jrubyfx/utils.rb +86 -0
  44. data/lib/jrubyfx/utils/__ignore_java_stupid_rdoc.rb +30 -0
  45. data/lib/jrubyfx/utils/common_converters.rb +223 -0
  46. data/lib/jrubyfx/utils/common_utils.rb +72 -0
  47. data/lib/jrubyfx/utils/string_utils.rb +48 -0
  48. data/lib/jrubyfx/version.rb +4 -0
  49. data/lib/jrubyfx_tasks.rb +183 -0
  50. metadata +145 -0
@@ -0,0 +1,178 @@
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_relative 'utils/common_utils'
19
+
20
+ # This module contains useful methods for defining JavaFX code. Include it in your
21
+ # class to use it, and the JRubyFX::FXImports. JRubyFX::Application and JRubyFX::Controller already include it.
22
+ module JRubyFX
23
+ include JRubyFX::FXImports
24
+ include JRubyFX::Utils::CommonUtils
25
+
26
+ ##
27
+ # call-seq:
28
+ # with(obj, hash) => obj
29
+ # with(obj) { block } => obj
30
+ # with(obj, hash) { block }=> obj
31
+ #
32
+ # Set properties (e.g. setters) on the passed in object plus also invoke
33
+ # any block passed against this object.
34
+ # === Examples
35
+ #
36
+ # with(grid, vgap: 2, hgap: 2) do
37
+ # set_pref_size(500, 400)
38
+ # children << location << go << view
39
+ # end
40
+ #
41
+ def with(obj, properties = {}, &block)
42
+ puts "Warning: calling 'with' on a nil object from #{caller[0]}" if obj.nil?
43
+ populate_properties(obj, properties)
44
+
45
+ if block_given?
46
+ # cache the proxy - http://wiki.jruby.org/Persistence
47
+ obj.class.__persistent__ = true if obj.class.ancestors.include? JavaProxy
48
+ obj.extend(JRubyFX)
49
+ obj.instance_eval(&block)
50
+ end
51
+
52
+ obj
53
+ end
54
+
55
+ ##
56
+ # call-seq:
57
+ # run_later { block }
58
+ #
59
+ # Convenience method so anything can safely schedule to run on JavaFX
60
+ # main thread.
61
+ def run_later(&block)
62
+ Java::javafx.application.Platform.run_later &block
63
+ end
64
+
65
+ ##
66
+ # call-seq:
67
+ # build(class) => obj
68
+ # build(class, hash) => obj
69
+ # build(class) { block } => obj
70
+ # build(class, hash) { block } => obj
71
+ #
72
+ # Create "build" a new JavaFX instance with the provided class and
73
+ # set properties (e.g. setters) on that new instance plus also invoke
74
+ # any block passed against this new instance. This also can build a proc
75
+ # or lambda form in which case the return value of the block will be what
76
+ # is used to set the additional properties on.
77
+ # === Examples
78
+ #
79
+ # grid = build(GridPane, vgap: 2, hgap: 2) do
80
+ # set_pref_size(500, 400)
81
+ # children << location << go << view
82
+ # end
83
+ #
84
+ # build(proc { Foo.new }, vgap: 2, hgap: 2)
85
+ #
86
+ def build(klass, *args, &block)
87
+ args, properties = split_args_from_properties(*args)
88
+
89
+ obj = if klass.kind_of? Proc
90
+ klass.call(*args)
91
+ else
92
+ klass.new(*attempt_conversion(klass, :new, *args))
93
+ end
94
+
95
+ with(obj, properties, &block)
96
+ end
97
+
98
+ def self.included(mod)
99
+ mod.extend(JRubyFX::FXMLClassUtils)
100
+ mod.extend(JRubyFX::FXImports)
101
+ end
102
+
103
+ module FXMLClassUtils
104
+ def fxml_raw_accessor(symbol_name, type=java::lang::String)
105
+ # TODO: RDoc
106
+ # TODO: somebody clean this up
107
+ # TODO: _reader and _writer
108
+ send(:define_method, symbol_name.id2name.snake_case + "=") do |val|
109
+ instance_variable_set("@#{symbol_name}", val)
110
+ end
111
+ send(:define_method, symbol_name.id2name.snake_case) do
112
+ instance_variable_get("@#{symbol_name}")
113
+ end
114
+ send(:define_method, symbol_name.id2name.snake_case + "GetType") do
115
+ return type.java_class
116
+ end
117
+ camel = symbol_name.id2name
118
+ camel = camel[0].upcase + camel[1..-1]
119
+ send(:define_method, "set" + camel) do |val|
120
+ instance_variable_set("@#{symbol_name}", val)
121
+ end
122
+ send(:define_method, "get" + camel) do
123
+ instance_variable_get("@#{symbol_name}")
124
+ end
125
+ send(:define_method, symbol_name.id2name + "GetType") do
126
+ return type.java_class
127
+ end
128
+ end
129
+ def fxml_accessor(symbol_name,ptype=Java::javafx.beans.property.SimpleStringProperty, type=nil)
130
+ # TODO: RDoc
131
+ # TODO: somebody clean this up
132
+ # TODO: _reader and _writer ? maybe? not?
133
+ pname = symbol_name.id2name + "Property"
134
+ raise "#{ptype} does not inherit from Property." unless ptype.ancestors.include? Java::javafx.beans.property.Property
135
+ unless type
136
+ type = ptype.java_class.java_instance_methods.find_all{|x|x.name == "getValue"}.map{|x|x.return_type}.find_all{|x|x != java.lang.Object.java_class}
137
+ if type.length != 1
138
+ raise "Unknown property type. Please manually supply a type or report this as a bug"
139
+ end
140
+ type = type[0]
141
+ else
142
+ type = type.java_class
143
+ end
144
+ send(:define_method, symbol_name.id2name.snake_case + "=") do |val|
145
+ send(pname).setValue val
146
+ end
147
+ send(:define_method, symbol_name.id2name.snake_case) do
148
+ send(pname).getValue
149
+ end
150
+ send(:define_method, symbol_name.id2name.snake_case + "GetType") do
151
+ return type
152
+ end
153
+ camel = symbol_name.id2name
154
+ camel = camel[0].upcase + camel[1..-1]
155
+ send(:define_method, "set" + camel) do |val|
156
+ send(pname).setValue val
157
+ end
158
+ send(:define_method, "get" + camel) do
159
+ send(pname).getValue
160
+ end
161
+ send(:define_method, symbol_name.id2name + "GetType") do
162
+ return type
163
+ end
164
+ send(:define_method, pname) do
165
+ unless instance_variable_get("@#{symbol_name}")
166
+ instance_variable_set("@#{symbol_name}", ptype.new(self, symbol_name.to_s))
167
+ end
168
+ return instance_variable_get("@#{symbol_name}")
169
+ end
170
+ send(:define_method, pname.snake_case) do
171
+ send(pname)
172
+ end
173
+ add_method_signature pname, [ptype]
174
+ add_method_signature "set" + camel, [java.lang.Void, type]
175
+ add_method_signature "get" + camel, [type]
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,141 @@
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_relative 'utils'
19
+
20
+ # Update load path to include the JavaFX runtime and fail nicely if we can't find it
21
+ begin
22
+ if ENV['JFX_DIR']
23
+ $LOAD_PATH << ENV['JFX_DIR']
24
+ else #should we check for 1.7 vs 1.8? oh well, adding extra paths won't hurt anybody (maybe performance loading)
25
+ jfx_path = ENV_JAVA["sun.boot.library.path"]
26
+ $LOAD_PATH << if jfx_path.include? ":\\" and !jfx_path.include? "/" # can be tricked, but should work fine
27
+ #windows
28
+ jfx_path.gsub(/\\bin[\\]*$/i, "\\lib")
29
+ else
30
+ # *nix
31
+ jfx_path.gsub(/[\/\\][amdix345678_]+$/, "") # strip i386 or amd64 (including variants). TODO: ARM
32
+ end
33
+ end
34
+
35
+ # Java 8 (after ea-b75) and above has JavaFX as part of the normal distib, only require it if we are 7 or below
36
+ jre = ENV_JAVA["java.runtime.version"].match %r{^(?<version>(?<major>\d+)\.(?<minor>\d+))\.(?<patch>\d+)(_\d+)?-?(?<release>ea|u\d)?(-?b(?<build>\d+))?}
37
+ # add OpenJFX support if follow instruction from https://openjfx.io
38
+ if ENV['JFX_DIR'] or
39
+ jre[:version].to_f < 1.8 or
40
+ (jre[:version].to_f == 1.8 and jre[:release] == 'ea' and jre[:build].to_i < 75)
41
+ require 'jfxrt.jar'
42
+ elsif ENV['PATH_TO_FX'] # support the OpenJFX installation as in https://openjfx.io/openjfx-docs/#install-javafx as of 15th May 2020
43
+ Dir.glob(File.join(ENV['PATH_TO_FX'],"*.jar")).each do |jar|
44
+ require jar
45
+ end
46
+ end
47
+
48
+ # Java 8 at some point requires explicit toolkit/platform initialization
49
+ # before any controls can be loaded.
50
+ JRubyFX.load_fx
51
+
52
+ # Attempt to load a javafx class
53
+ Java.javafx.application.Application
54
+ rescue LoadError, NameError
55
+ # Advice user too about the OpenJFX support
56
+ puts "JavaFX runtime not found. Please install Java 7u6 or newer, set environment variable JFX_DIR to the folder that contains jfxrt.jar or set the environment variable PATH_TO_FX that points to the OpenJFX libraries"
57
+ puts "If you have Java 7u6 or later, this is a bug. Please report to the issue tracker on github. Include your OS version, 32/64bit, and architecture (x86, ARM, PPC, etc)"
58
+ exit -1
59
+ end
60
+
61
+ module JRubyFX
62
+ # If you need JavaFX, just include this module. Its sole purpose in life is to
63
+ # import all JavaFX stuff, plus a few useful Java classes (like Void)
64
+ module FXImports
65
+
66
+ # If something is missing, just java_import it in your code.
67
+ # And then ask us to put it in this list
68
+ ###### IMPORTANT LINE ##### (see rakefile, this is a magic line, don't delete)
69
+
70
+ ##
71
+ # This is the list of all classes in JavaFX that most apps should care about.
72
+ # It is a hashmaps with the leafs as arrays. Where a leaf also contains more
73
+ # packages, the hashmap key is "" (empty string). You can utilize this constant
74
+ # to save yourself some typing when adding code for most/all of the JavaFX
75
+ # classes by using either `Hash.flat_tree_inject` from jrubyfx/utils.rb or
76
+ # writing your own traversal function
77
+ #
78
+ JFX_CLASS_HIERARCHY = { :javafx => {
79
+ :animation => %w[Animation AnimationTimer FadeTransition FillTransition Interpolator KeyFrame KeyValue ParallelTransition PathTransition
80
+ PauseTransition RotateTransition ScaleTransition SequentialTransition StrokeTransition Timeline Transition TranslateTransition],
81
+ :application => ['Platform'],
82
+ :beans => {
83
+ :property => %w[SimpleBooleanProperty SimpleDoubleProperty SimpleFloatProperty SimpleIntegerProperty SimpleListProperty SimpleLongProperty SimpleMapProperty SimpleObjectProperty SimpleSetProperty SimpleStringProperty],
84
+ #TODO: import more
85
+ :value => ['ChangeListener']
86
+ },
87
+ :collections => ['FXCollections'],
88
+ :concurrent => %w[Worker Task Service],
89
+ :event => %w[Event ActionEvent EventHandler],
90
+ :fxml => ['Initializable', 'LoadException'],
91
+ :geometry => %w[HorizontalDirection HPos Insets Orientation Pos Rectangle2D Side VerticalDirection VPos],
92
+ :scene => {
93
+ '' => %w[Group Node Parent Scene],
94
+ :canvas => ['Canvas'],
95
+ :chart => %w[AreaChart Axis BarChart BubbleChart CategoryAxis Chart LineChart NumberAxis
96
+ PieChart ScatterChart StackedAreaChart StackedBarChart ValueAxis XYChart],
97
+ :control => %w[Accordion Button Cell CheckBox CheckBoxTreeItem CheckMenuItem ChoiceBox ColorPicker ComboBox ContextMenu Hyperlink
98
+ Label ListCell ListView Menu MenuBar MenuButton MenuItem Pagination PasswordField PopupControl ProgressBar ProgressIndicator RadioButton
99
+ RadioMenuItem ScrollBar ScrollPane Separator SeparatorMenuItem Slider SplitMenuButton SplitPane Tab TableView TableCell TableColumn TabPane TextArea
100
+ TextField TitledPane ToggleButton ToggleGroup ToolBar Tooltip TreeCell TreeItem TreeView ContentDisplay OverrunStyle SelectionMode],
101
+ :effect => %w[Blend BlendMode Bloom BlurType BoxBlur ColorAdjust ColorInput DisplacementMap DropShadow GaussianBlur Glow ImageInput
102
+ InnerShadow Lighting MotionBlur PerspectiveTransform Reflection SepiaTone Shadow],
103
+ :image => %w[Image ImageView PixelReader PixelWriter],
104
+ :input => %w[Clipboard ClipboardContent ContextMenuEvent DragEvent GestureEvent InputEvent InputMethodEvent KeyCode KeyEvent
105
+ Mnemonic MouseButton MouseDragEvent MouseEvent RotateEvent ScrollEvent SwipeEvent TouchEvent TransferMode ZoomEvent],
106
+ :layout => %w[AnchorPane BorderPane ColumnConstraints FlowPane GridPane HBox Pane Priority RowConstraints StackPane TilePane VBox],
107
+ :media => %w[AudioClip AudioEqualizer AudioTrack EqualizerBand Media MediaException
108
+ MediaErrorEvent MediaMarkerEvent MediaPlayer MediaView VideoTrack],
109
+ :paint => %w[Color CycleMethod ImagePattern LinearGradient Paint RadialGradient Stop],
110
+ :shape => %w[Arc ArcTo ArcType Circle ClosePath CubicCurve CubicCurveTo Ellipse FillRule HLineTo Line LineTo MoveTo Path PathElement
111
+ Polygon Polyline QuadCurve QuadCurveTo Rectangle Shape StrokeLineCap StrokeLineJoin StrokeType SVGPath VLineTo],
112
+ :text => %w[Font FontPosture FontSmoothingType FontWeight Text TextAlignment TextBoundsType],
113
+ :transform => %w[Affine Rotate Scale Shear Translate],
114
+ :web => ['WebView', 'HTMLEditor']
115
+ },
116
+ :stage => %w[DirectoryChooser FileChooser Modality Popup PopupWindow Screen Stage StageStyle Window WindowEvent],
117
+ :util => ['Duration']
118
+ }
119
+ }
120
+
121
+ $WRITE_OUT << <<HERE
122
+ def const_missing(c)
123
+ if LOCAL_NAME_MAP.has_key? c
124
+ java_import(LOCAL_NAME_MAP[c])[0]
125
+ else
126
+ super
127
+ end
128
+ end
129
+
130
+ HERE
131
+
132
+ # Imports all the listed JavaFX classes
133
+ $WRITE_OUT << "LOCAL_NAME_MAP = { \n "
134
+ $WRITE_OUT << (JFX_CLASS_HIERARCHY.flat_tree_inject do |res, name, values|
135
+ name = "#{name.to_s}."
136
+ name = "" if name == "."
137
+ res.concat(values.map{|i| "#{name}#{i}"})
138
+ end).map{|x| "#{x.split(".").last.to_sym.inspect} => #{x.inspect}"}.join(",\n ")
139
+ $WRITE_OUT << "\n}\njava_import 'java.lang.Void'"
140
+ end
141
+ end
@@ -0,0 +1,86 @@
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
+ # This feels kinda like a hack. If anyone has a better idea, please let me know
19
+
20
+ # Standard ruby Hash class extensions
21
+ class Hash
22
+
23
+ # call-seq:
24
+ # flat_tree_inject() {|results, key, value| block} => array
25
+ # flat_tree_inject(Hash) {|results, key, value| block} => hash
26
+ #
27
+ # Execute given block against all nodes in the hash tree, returning `results`.
28
+ # Similar to Hash#each except goes into all sub-Hashes
29
+ #
30
+ def flat_tree_inject(klass=Array,&block)
31
+ self.inject(klass.new) do |lres, pair|
32
+ if pair[1].is_a? Hash
33
+ pair[1] = pair[1].flat_tree_inject(klass, &block)
34
+ end
35
+ block.call(lres, *pair)
36
+ end
37
+ end
38
+ end
39
+
40
+ # Standard ruby String class extensions
41
+ class String
42
+ # call-seq:
43
+ # snake_case(ignore_prefix_namespace=false) => string
44
+ #
45
+ # Converts a CamelCaseString to a snake_case_string
46
+ #
47
+ # "JavaFX".snake_case #=> "java_fx"
48
+ #
49
+ # If ignore_prefix_namespace is specified it will strip
50
+ # any preceding modules/classes off front of string before
51
+ # snake casing:
52
+ # Foo::BigBar #=> "big_bar"
53
+ #
54
+ # By default it will separate modules with a "/":
55
+ # Foo::BigBar #=> "foo/big_bar"
56
+ #
57
+ def snake_case(ignore_prefix_namespace=false)
58
+ base = ignore_prefix_namespace ?
59
+ self.gsub(/.*::/, '') : self.gsub(/::/, '/')
60
+ base.
61
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
62
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
63
+ tr("-", "_").
64
+ downcase
65
+ end
66
+ end
67
+
68
+ module Enumerable
69
+ def map_find(&block)
70
+ m = {}
71
+ m[self.find do |i|
72
+ m[i] = block.call(i)
73
+ end]
74
+ end
75
+ end
76
+
77
+ module JRubyFX
78
+ def self.load_fx(force=false)
79
+ return if @already_loaded_fx and !force
80
+ @already_loaded_fx = true
81
+ java.util.concurrent.CountDownLatch.new(1).tap do |latch|
82
+ com.sun.javafx.application.PlatformImpl.startup { latch.countDown }
83
+ latch.await
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,30 @@
1
+ module Java #:nodoc: all
2
+ module javafx
3
+ module animation
4
+ end
5
+ module beans
6
+ module value
7
+ end
8
+ end
9
+ module scene
10
+ module chart
11
+ end
12
+ module control
13
+ end
14
+ module effect
15
+ end
16
+ module layout
17
+ end
18
+ module media
19
+ end
20
+ module paint
21
+ end
22
+ module shape
23
+ end
24
+ module transform
25
+ end
26
+ end
27
+ module stage
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,223 @@
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
+ false # Do NOT delete this or it will make RDOC associate the copyright header with JRubyFX module
18
+
19
+ module JRubyFX
20
+ module Utils
21
+ # Contains conversion utilities to ease Ruby => JavaFX coding
22
+ module CommonConverters
23
+ java_import 'javafx.scene.paint.Color'
24
+ java_import 'javafx.geometry.Insets'
25
+ java_import 'javafx.geometry.Rectangle2D'
26
+
27
+ # argument converter method name suffix
28
+ ARG_CONVERTER_SUFFIX = '_arg_converter'
29
+
30
+ # map of snake_cased colors to JavaFX Colors
31
+ NAME_TO_COLORS = {
32
+ 'darkyellow' => Color.web('0xc0c000'),
33
+ 'lightmagenta' => Color.web('0xffc0ff'),
34
+ 'lightred' => Color.web('0xffc0c0'),
35
+ }.merge(Color.java_class.fields.inject({}) {|final, field|
36
+ final[field.name.downcase] = field.value(nil) # TODO: what is nil supposed to be?
37
+ final
38
+ })
39
+
40
+ ##
41
+ # Generate a converter for a map of supplied values.
42
+ def map_converter(map)
43
+ lambda do |value|
44
+ map.key?(value) ? map[value] : value
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Generate a converter for an enum of the given class
50
+ def enum_converter(enum_class)
51
+ lambda do |value|
52
+ (JRubyFX::Utils::CommonConverters.map_enums(enum_class)[value.to_s] || value)
53
+ end
54
+ end
55
+
56
+ ##
57
+ # call-seq:
58
+ # animation_converter_for :property_name, ...
59
+ #
60
+ # Generates an animation adapter for the given properties so you can specify
61
+ # transformations, etc with a hashmap of from, to values
62
+ # === Examples
63
+ # animation_converter_for :value
64
+ #
65
+ # ...
66
+ #
67
+ # _my_type_(value: {0 => 360})
68
+ #
69
+ def animation_converter_for(*prop_names)
70
+ prop_names.each do |prop_name|
71
+ self.__send__(:define_method, prop_name.to_s + "=") do |hash|
72
+ method("from_#{prop_name}=").call hash.keys[0]
73
+ method("to_#{prop_name}=").call hash.values[0]
74
+ end
75
+ end
76
+ end
77
+
78
+ ##
79
+ # Allows you to specify you want a converter method created for the
80
+ # specified method where each listed converter corresponds to each
81
+ # argument for that method. You can have n-arity lists for all
82
+ # matching Java overloads. This mechanism means you may not always
83
+ # be able to specify all coercions you want.
84
+ # === Examples
85
+ #
86
+ # coverter_for :new, [:none, :color]
87
+ #
88
+ # This method will define a method on the current class called
89
+ # *new_arg_converter* which will perform no argument coercion on
90
+ # the first argument and a color coercion on the second argument.
91
+ #
92
+ # e = enum_converter(Java::javafx::scene::input::TransferMode)
93
+ # converter_for :accept_transfer_modes &e
94
+ #
95
+ # This method will allow a catch-all converter to be used for all
96
+ # arities not specified. In this case since no arities are given
97
+ # all arities will pass through this enum_converter. This form
98
+ # is useful for single var_args signatures.
99
+ #
100
+ def converter_for(method_name, *converters, &default)
101
+ # puts "[converter for #{self}, #{method_name}]"
102
+ sheep = lambda do |direct, this, *values|
103
+ converter = converters.find { |e| e.length == values.length }
104
+ converter = Array.new(values.length, default) unless converter
105
+
106
+ # FIXME: Better error reporting on many things which can fail
107
+ i = 0
108
+ values = values.inject([]) do |s, value|
109
+ conv = converter[i]
110
+ if conv.kind_of? Proc
111
+ s << conv.call(value)
112
+ else
113
+ s << CONVERTERS[converter[i]].call(value)
114
+ end
115
+ i += 1
116
+ s
117
+ end
118
+ if direct
119
+ return this.method("set_" + method_name.to_s).call(*values)
120
+ else
121
+ return values
122
+ end
123
+ end
124
+ # define a setter for normal usage
125
+ unless method_name == :new
126
+ self.__send__(:define_method, method_name.to_s + "=") do |*values|
127
+ sheep.call(true, self, *values)
128
+ end
129
+ end
130
+ # define a build/with usage
131
+ self.__send__(:define_method, method_name.to_s + ARG_CONVERTER_SUFFIX) do |*values|
132
+ sheep.call(false, self, *values)
133
+ end
134
+ end
135
+
136
+ # Map of different kinds of known converters
137
+ CONVERTERS = {
138
+ :none => lambda { |value|
139
+ value
140
+ },
141
+ :color => lambda { |value|
142
+ new_value = NAME_TO_COLORS[value.to_s.gsub(/_/, "")]
143
+ if !new_value && value.kind_of?(Symbol)
144
+ raise ArgumentError.new("No such color: #{value.to_s}")
145
+ end
146
+ new_value ? new_value : value
147
+ },
148
+ :rectangle2d => lambda { |value|
149
+ if value == :empty
150
+ Rectangle2D::EMPTY
151
+ elsif value.is_a? Array
152
+ Rectangle2D.new(*value)
153
+ else
154
+ value
155
+ end
156
+ },
157
+ :insets => lambda { |value|
158
+ if value == :empty
159
+ Insets::EMPTY
160
+ elsif value.is_a? Numeric
161
+ Insets.new(value)
162
+ elsif value.is_a? Array
163
+ # top/bottom, left/right
164
+ value = [value[0], value[1], value[0], value[1]] if value.size == 2
165
+ Insets.new(*value)
166
+ else
167
+ value
168
+ end
169
+ },
170
+ }
171
+
172
+ ENUM_CACHE = {}
173
+
174
+ # Store enum mapping overrides
175
+ ENUM_OVERRIDES = {Java::JavafxAnimation::PathTransition::OrientationType => {:orthogonal_to_tangent => :orthogonal},
176
+ Java::JavafxSceneEffect::BlendMode => {:src_over => :over, :src_atop => :atop, :color_dodge => :dodge, :color_burn => :burn},
177
+ Java::JavafxSceneControl::ContentDisplay => {:graphic_only => :graphic, :text_only => :text},
178
+ Java::JavafxSceneEffect::BlurType => {:one_pass_box => [:one, :one_pass], :two_pass_box => [:two, :two_pass], :three_pass_box => [:three, :three_pass]},
179
+ Java::JavafxStage::Modality => {:window_modal => :window, :application_modal => [:application, :app]}}
180
+
181
+ # sets the given overrides for the given class/enum
182
+ def self.set_overrides_for(enum_class,ovr)
183
+ ENUM_OVERRIDES[enum_class] = ovr
184
+ end
185
+
186
+ # Given a class, returns a hash of lowercase strings mapped to Java Enums
187
+ def self.map_enums(enum_class)
188
+ res = Hash[enum_class.java_class.enum_constants.map {|i| [i.to_s.downcase, i] }]
189
+ (ENUM_OVERRIDES[enum_class]||[]).each do |oldk, newks|
190
+ [newks].flatten.each do |newk|
191
+ res[newk.to_s] = res[oldk.to_s]
192
+ end
193
+ end
194
+ res
195
+ end
196
+
197
+ def self.parse_ruby_symbols(const, enum)
198
+ ENUM_CACHE[enum] = JRubyFX::Utils::CommonConverters.map_enums(enum) if ENUM_CACHE[enum] == nil
199
+ ENUM_CACHE[enum][const.to_s] || const
200
+ end
201
+
202
+ def self.convert_args(values, converters)
203
+ converter = converters.find { |e| e.length == values.length }
204
+ converter = Array.new(values.length) unless converter
205
+
206
+ # FIXME: Better error reporting on many things which can fail
207
+ i = 0
208
+ values = values.inject([]) do |s, value|
209
+ conv = converter[i]
210
+ if conv.kind_of? Proc
211
+ s << conv.call(value)
212
+ else
213
+ s << CONVERTERS[converter[i]].call(value)
214
+ end
215
+ i += 1
216
+ s
217
+ end
218
+ return values
219
+ end
220
+ end
221
+
222
+ end
223
+ end