jrubyfx-openjfx.patch 1.2.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 (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