jrubyfx-fxmlloader-master 0.4.master.2015.9.30-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.
- checksums.yaml +7 -0
- data/LICENSE +25 -0
- data/README +17 -0
- data/Rakefile +72 -0
- data/lib/FXMLLoader-j8.jar +0 -0
- data/lib/fxmlloader/elts.rb +576 -0
- data/lib/fxmlloader/fxml_jit_info.rb +158 -0
- data/lib/fxmlloader/j8_expression_value.rb +290 -0
- data/lib/fxmlloader/real_elts.rb +708 -0
- data/lib/fxmlloader/rorba.rb +107 -0
- data/lib/fxmlloader/rrba.rb +769 -0
- data/lib/fxmlloader/value_elts.rb +257 -0
- data/lib/jrubyfx-fxmlloader.rb +800 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dc644450732228d58cf46b09e83897507682f050
|
4
|
+
data.tar.gz: 5182f75c1ca24b6071bc05a1d8aa5ec1f471bd6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5af1098185d35a107bc1aaa56f4618df20a6d3ee5c23fcab8d0536543b0b3724a8e1c23997bf866431aaff03625fdd0d13f1d730b6b400193ad821b07b7ad1f1
|
7
|
+
data.tar.gz: 147737f1087b28239ce2939515a6ef5db4085a7ee14f5c979754d238d0b08a6befe91119f058027d1d87a6a01a458d7f99cb22004a017748b2b9fdc52354a106
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
=begin
|
2
|
+
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
3
|
+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4
|
+
*
|
5
|
+
* This code is free software; you can redistribute it and/or modify it
|
6
|
+
* under the terms of the GNU General Public License version 2 only, as
|
7
|
+
* published by the Free Software Foundation. Oracle designates this
|
8
|
+
* particular file as subject to the "Classpath" exception as provided
|
9
|
+
* by Oracle in the LICENSE file that accompanied this code.
|
10
|
+
*
|
11
|
+
* This code is distributed in the hope that it will be useful, but WITHOUT
|
12
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
13
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
14
|
+
* version 2 for more details (a copy is included in the LICENSE file that
|
15
|
+
* accompanied this code).
|
16
|
+
*
|
17
|
+
* You should have received a copy of the GNU General Public License version
|
18
|
+
* 2 along with this work; if not, write to the Free Software Foundation,
|
19
|
+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
20
|
+
*
|
21
|
+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
22
|
+
* or visit www.oracle.com if you need additional information or have any
|
23
|
+
* questions.
|
24
|
+
*/
|
25
|
+
=end
|
data/README
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# JRubyFX-FxmlLoader
|
2
|
+
|
3
|
+
JRubyFX-FxmlLoader is the JIT-enabled FXML parser for the JRubyFX project based
|
4
|
+
on the official OpenJDK 8 FXML parser. FxmlLoader strives to be a nearly drop-in
|
5
|
+
replacement FxmlLoader, only differing in JRuby compatibility.
|
6
|
+
|
7
|
+
At this point,
|
8
|
+
most code is directly copied from OpenJDK and converted to ruby via regexes and
|
9
|
+
as such is far from idiomatic ruby. The JIT compiler is also a work in progress.
|
10
|
+
|
11
|
+
If you would like to help clean up the code please do but be careful about breaking
|
12
|
+
FXML. Any 100% standard Java FXML document should work *identically* when run as a JRuby FXML document and
|
13
|
+
vice-versa with the exception of JRuby support (like ruby classes & controllers).
|
14
|
+
|
15
|
+
Use with JRubyFX!
|
16
|
+
|
17
|
+
rake gem to build. Note that half of this project is java and must be compiled.
|
data/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rubygems/package_task'
|
10
|
+
require 'ant'
|
11
|
+
|
12
|
+
build_dir = "build"
|
13
|
+
file build_dir
|
14
|
+
|
15
|
+
task :java_init => build_dir do
|
16
|
+
ant.property :name => "src.dir", :value => "src"
|
17
|
+
ant.path(:id => "project.class.path") do
|
18
|
+
pathelement :location => "classes"
|
19
|
+
end
|
20
|
+
ant.tstamp
|
21
|
+
ant.mkdir(:dir => build_dir)
|
22
|
+
end
|
23
|
+
|
24
|
+
task :compile => :java_init do
|
25
|
+
ant.javac(:destdir => build_dir) do
|
26
|
+
classpath :refid => "project.class.path"
|
27
|
+
src { pathelement :location => "${src.dir}" }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Build the Java component"
|
32
|
+
task :jar => :compile do
|
33
|
+
ant.jar :destfile => "lib/FXMLLoader-j8.jar", :basedir => build_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
task :java_clean do
|
37
|
+
ant.delete(:dir => build_dir)
|
38
|
+
ant.delete(:dir => "pkg")
|
39
|
+
ant.delete(:file => "lib/FXMLLoader-j8.jar")
|
40
|
+
end
|
41
|
+
|
42
|
+
task :clean => :java_clean
|
43
|
+
|
44
|
+
task :gem => :jar
|
45
|
+
|
46
|
+
spec = Gem::Specification.new do |s|
|
47
|
+
s.name = 'jrubyfx-fxmlloader-master'
|
48
|
+
s.version = '0.4.master.2015.9.30'
|
49
|
+
s.platform = 'java'
|
50
|
+
s.has_rdoc = true
|
51
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
52
|
+
s.summary = 'GPL\'d JavaFX FXMLLoder class in Ruby for JRubyFX'
|
53
|
+
s.description = "JRubyFX FxmlLoader gem bits"
|
54
|
+
s.author = 'Patrick Plenefisch & JRubyFX team & Oracle'
|
55
|
+
s.email = 'simonpatp@gmail.com'
|
56
|
+
s.homepage = "https://github.com/byteit101/JRubyFX-FXMLLoader"
|
57
|
+
# s.executables = ['your_executable_here']
|
58
|
+
# manually specify it to avoid globbing issues
|
59
|
+
s.files = %w(LICENSE README Rakefile lib/FXMLLoader-j8.jar) + Dir.glob("{bin,lib,spec}/**/*")
|
60
|
+
s.require_path = "lib"
|
61
|
+
s.bindir = "bin"
|
62
|
+
s.license = "GPL-2.0-with-classpath-exception"
|
63
|
+
end
|
64
|
+
|
65
|
+
Gem::PackageTask.new(spec) do |p|
|
66
|
+
p.gem_spec = spec
|
67
|
+
p.need_tar = true
|
68
|
+
p.need_zip = true
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
task :default => :gem
|
Binary file
|
@@ -0,0 +1,576 @@
|
|
1
|
+
class JavaProxy
|
2
|
+
def default_property
|
3
|
+
self.java_class.getAnnotation(DefaultProperty.java_class);
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Element
|
8
|
+
attr_accessor :parent, :lineNumber, :current, :xmlStreamReader, :loadListener, :parentLoader
|
9
|
+
attr_accessor :value, :valueAdapter, :eventHandlerAttributes, :instancePropertyAttributes, :staticPropertyAttributes, :staticPropertyElements
|
10
|
+
def initialize(current, xmlStreamReader, loadListener, parentLoader)
|
11
|
+
@parent = current;
|
12
|
+
@lineNumber = xmlStreamReader.getLocation().getLineNumber();
|
13
|
+
@current = current;
|
14
|
+
@xmlStreamReader = xmlStreamReader
|
15
|
+
@loadListener = loadListener
|
16
|
+
@value = nil
|
17
|
+
@valueAdapter = nil
|
18
|
+
@eventHandlerAttributes = []
|
19
|
+
@instancePropertyAttributes = []
|
20
|
+
@staticPropertyAttributes = []
|
21
|
+
@staticPropertyElements = []
|
22
|
+
@parentLoader = parentLoader
|
23
|
+
end
|
24
|
+
def staticLoad
|
25
|
+
@parentLoader.staticLoad
|
26
|
+
end
|
27
|
+
def callz
|
28
|
+
numz = 1
|
29
|
+
pppn = @parent
|
30
|
+
while pppn
|
31
|
+
numz+=1
|
32
|
+
pppn = pppn.parent
|
33
|
+
end
|
34
|
+
(" " * numz) + @lineNumber.to_s + ": "
|
35
|
+
end
|
36
|
+
|
37
|
+
def isCollection()
|
38
|
+
# Return true if value is a list, or if the value's type defines
|
39
|
+
# a default property that is a list
|
40
|
+
collection = false
|
41
|
+
if (@value.kind_of?(Enumerable) || @value.java_kind_of?(Java.java.util.List))
|
42
|
+
collection = true;
|
43
|
+
else
|
44
|
+
defaultProperty = @value.java_class.annotation(DefaultProperty.java_class);
|
45
|
+
|
46
|
+
if (defaultProperty != nil)
|
47
|
+
collection = getProperties()[defaultProperty.value].java_kind_of?(Java.java.util.List)
|
48
|
+
else
|
49
|
+
collection = false;
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return collection;
|
53
|
+
end
|
54
|
+
|
55
|
+
def add(element, prop_name=nil, rputs_elt=nil)
|
56
|
+
# If value is a list, add element to it; otherwise, get the value
|
57
|
+
# of the default property, which is assumed to be a list and add
|
58
|
+
# to that (coerce to the appropriate type)
|
59
|
+
if (@value.kind_of?(Enumerable) || @value.java_kind_of?(java.util.List))
|
60
|
+
if prop_name == nil
|
61
|
+
rputs value, "add(#{rget(element)||element.inspect})"
|
62
|
+
else
|
63
|
+
rputs @parent.value, "get#{prop_name[0].upcase}#{prop_name[1..-1]}.add(#{rputs_elt || rget(element)||element.inspect})"
|
64
|
+
end
|
65
|
+
value.to_java
|
66
|
+
else
|
67
|
+
type = value.java_class
|
68
|
+
defaultProperty = type.annotation(DefaultProperty.java_class);
|
69
|
+
defaultPropertyName = defaultProperty.to_java.value();
|
70
|
+
|
71
|
+
# Get the list value
|
72
|
+
list = getProperties[defaultPropertyName]
|
73
|
+
|
74
|
+
# Coerce the element to the list item type
|
75
|
+
if (!java.util.Map.java_class.assignable_from?(type))
|
76
|
+
listType = @valueAdapter.getGenericType(defaultPropertyName);
|
77
|
+
element = RubyWrapperBeanAdapter.coerce(element, RubyWrapperBeanAdapter.getListItemType(listType));
|
78
|
+
end
|
79
|
+
rputs @value, "get#{defaultPropertyName[0].upcase}#{defaultPropertyName[1..-1]}.add(#{rget(element)||element.inspect})"
|
80
|
+
list = list.to_java if list.class == Java::JavaObject
|
81
|
+
list
|
82
|
+
end.add(element)
|
83
|
+
end
|
84
|
+
|
85
|
+
def set(value)
|
86
|
+
unless @value
|
87
|
+
raise LoadException.new("Cannot set value on this element.");
|
88
|
+
end
|
89
|
+
|
90
|
+
# Apply value to this element's properties
|
91
|
+
type = @value.java_class;
|
92
|
+
defaultProperty = type.getAnnotation(DefaultProperty.java_class);
|
93
|
+
if (defaultProperty == nil)
|
94
|
+
raise LoadException.new("Element does not define a default property.");
|
95
|
+
end
|
96
|
+
|
97
|
+
getProperties[defaultProperty.value] = value
|
98
|
+
end
|
99
|
+
|
100
|
+
def updateValue(value)
|
101
|
+
@value = value;
|
102
|
+
@valueAdapter = nil;
|
103
|
+
end
|
104
|
+
|
105
|
+
def isTyped()
|
106
|
+
!(@value.java_kind_of? Java::java.util.Map or @value.is_a? Hash )
|
107
|
+
end
|
108
|
+
|
109
|
+
def getValueAdapter()
|
110
|
+
if (@valueAdapter == nil)
|
111
|
+
@valueAdapter = RubyWrapperBeanAdapter.for(@value)
|
112
|
+
end
|
113
|
+
return @valueAdapter;
|
114
|
+
end
|
115
|
+
|
116
|
+
def getProperties()
|
117
|
+
return (isTyped()) ? getValueAdapter() : @value;
|
118
|
+
end
|
119
|
+
|
120
|
+
def processStartElement()
|
121
|
+
n = @xmlStreamReader.getAttributeCount()
|
122
|
+
n.times do |i|
|
123
|
+
prefix = @xmlStreamReader.getAttributePrefix(i);
|
124
|
+
localName = @xmlStreamReader.getAttributeLocalName(i);
|
125
|
+
value = @xmlStreamReader.getAttributeValue(i);
|
126
|
+
|
127
|
+
if (@loadListener && prefix && prefix == (FXL::FX_NAMESPACE_PREFIX))
|
128
|
+
@loadListener.readInternalAttribute(prefix + ":" + localName, value);
|
129
|
+
end
|
130
|
+
|
131
|
+
processAttribute(prefix, localName, value);
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def processEndElement()
|
136
|
+
# No-op
|
137
|
+
end
|
138
|
+
|
139
|
+
def processCharacters()
|
140
|
+
raise LoadException.new("Unexpected characters in input stream.");
|
141
|
+
end
|
142
|
+
|
143
|
+
def processInstancePropertyAttributes()
|
144
|
+
if (@instancePropertyAttributes.length > 0)
|
145
|
+
for attribute in @instancePropertyAttributes
|
146
|
+
processPropertyAttribute(attribute);
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def processAttribute(prefix, localName, value)
|
152
|
+
if (prefix == nil)
|
153
|
+
# Add the attribute to the appropriate list
|
154
|
+
if (localName.start_with?(FXL::EVENT_HANDLER_PREFIX))
|
155
|
+
if (@loadListener != nil)
|
156
|
+
@loadListener.readEventHandlerAttribute(localName, value);
|
157
|
+
end
|
158
|
+
eventHandlerAttributes <<(Attribute.new(localName, nil, value));
|
159
|
+
else
|
160
|
+
i = localName.rindex('.');
|
161
|
+
|
162
|
+
if (i == nil)
|
163
|
+
# The attribute represents an instance property
|
164
|
+
if (@loadListener != nil)
|
165
|
+
@loadListener.readPropertyAttribute(localName, nil, value);
|
166
|
+
end
|
167
|
+
|
168
|
+
instancePropertyAttributes << (Attribute.new(localName, nil, value));
|
169
|
+
else
|
170
|
+
# The attribute represents a static property
|
171
|
+
name = localName[(i + 1)..-1];
|
172
|
+
sourceType = parentLoader.getType(localName[0, i]);
|
173
|
+
|
174
|
+
if (sourceType != nil)
|
175
|
+
if (@loadListener != nil)
|
176
|
+
@loadListener.readPropertyAttribute(name, sourceType, value);
|
177
|
+
end
|
178
|
+
|
179
|
+
@staticPropertyAttributes << (Attribute.new(name, sourceType, value));
|
180
|
+
elsif (staticLoad)
|
181
|
+
if (@loadListener != nil)
|
182
|
+
@loadListener.readUnknownStaticPropertyAttribute(localName, value);
|
183
|
+
end
|
184
|
+
else
|
185
|
+
raise LoadException.new(localName + " is not a valid attribute.");
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
else
|
191
|
+
raise LoadException.new(prefix + ":" + localName +
|
192
|
+
" is not a valid attribute.");
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def processPropertyAttribute(attribute)
|
197
|
+
value = attribute.value;
|
198
|
+
if (isBindingExpression(value))
|
199
|
+
# Resolve the expression
|
200
|
+
|
201
|
+
if (attribute.sourceType != nil)
|
202
|
+
raise LoadException.new("Cannot bind to static property.");
|
203
|
+
end
|
204
|
+
|
205
|
+
if (!isTyped())
|
206
|
+
raise LoadException.new("Cannot bind to untyped object.");
|
207
|
+
end
|
208
|
+
|
209
|
+
# TODO We may want to identify binding properties in processAttribute()
|
210
|
+
# and apply them after build() has been called
|
211
|
+
if (@value.is_a? Builder)
|
212
|
+
raise LoadException.new("Cannot bind to builder property.");
|
213
|
+
end
|
214
|
+
|
215
|
+
value = value[2..-2] # TODO: BINDING_EXPRESSION_PREFIX == ${
|
216
|
+
#value.length() - 1];
|
217
|
+
# TODO: this only works for 7, not 8
|
218
|
+
expression = Expression.valueOf(value);
|
219
|
+
# Create the binding
|
220
|
+
targetAdapter = RubyWrapperBeanAdapter.new(@value);
|
221
|
+
propertyModel = targetAdapter.getPropertyModel(attribute.name).to_java
|
222
|
+
type = targetAdapter.getType(attribute.name);
|
223
|
+
if (propertyModel.is_a? Property)
|
224
|
+
rputs @value, "#{attribute.name}Property.bind(RRExpressionValue.new(__local_namespace, Java::org.jruby.jfx8.Expression.valueOf(#{value.inspect}), Java::#{type.name.gsub(/[\$\.]/, "::")}.java_class))"
|
225
|
+
#expression.value_property.addListener(JRExpressionTargetMapping.new(expression, getProperties(), Expression.split(value)));
|
226
|
+
( propertyModel).bind(RRExpressionValue.new(parentLoader.namespace, expression, type));
|
227
|
+
end
|
228
|
+
elsif (isBidirectionalBindingExpression(value))
|
229
|
+
raise UnsupportedOperationException.new("This feature is not currently enabled.");
|
230
|
+
else
|
231
|
+
processValue3(attribute.sourceType, attribute.name, value);
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def isBindingExpression(aValue)
|
236
|
+
# TODO: BINDING_EXPRESSION_PREFIX == ${
|
237
|
+
aValue.start_with?("${") && aValue.end_with?(FXL::BINDING_EXPRESSION_SUFFIX);
|
238
|
+
end
|
239
|
+
|
240
|
+
def isBidirectionalBindingExpression(aValue)
|
241
|
+
return aValue.start_with?(FXL::BI_DIRECTIONAL_BINDING_PREFIX);
|
242
|
+
end
|
243
|
+
|
244
|
+
def processValue3( sourceType, propertyName, aValue)
|
245
|
+
|
246
|
+
|
247
|
+
processed = false;
|
248
|
+
#process list or array first
|
249
|
+
if (sourceType == nil && isTyped())
|
250
|
+
lvalueAdapter = getValueAdapter();
|
251
|
+
type = lvalueAdapter.getType(propertyName);
|
252
|
+
|
253
|
+
if (type == nil)
|
254
|
+
dputs "Processing values3 fails on: "
|
255
|
+
dp sourceType, propertyName, aValue
|
256
|
+
dp lvalueAdapter
|
257
|
+
dp caller
|
258
|
+
raise("Property \"" + propertyName + "\" does not exist" + " or is read-only.");
|
259
|
+
end
|
260
|
+
if (List.java_class.assignable_from?(type) && lvalueAdapter.read_only?(propertyName))
|
261
|
+
populateListFromString(lvalueAdapter, propertyName, aValue);
|
262
|
+
processed = true;
|
263
|
+
elsif false #TODO: fix type.ruby_class.ancestors.include? Enumerable
|
264
|
+
applyProperty(propertyName, sourceType, populateArrayFromString(type, aValue));
|
265
|
+
processed = true;
|
266
|
+
end
|
267
|
+
end
|
268
|
+
if (!processed)
|
269
|
+
applyProperty(propertyName, sourceType, resolvePrefixedValue(aValue));
|
270
|
+
processed = true;
|
271
|
+
end
|
272
|
+
return processed;
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
# Resolves value prefixed with RELATIVE_PATH_PREFIX and
|
277
|
+
# RESOURCE_KEY_PREFIX.
|
278
|
+
|
279
|
+
def resolvePrefixedValue(aValue)
|
280
|
+
if (aValue.start_with?(FXL::ESCAPE_PREFIX))
|
281
|
+
aValue = aValue[FXL::ESCAPE_PREFIX.length..-1]
|
282
|
+
|
283
|
+
if (aValue.length == 0 || !(aValue.start_with?(FXL::ESCAPE_PREFIX) ||
|
284
|
+
aValue.start_with?(FXL::RELATIVE_PATH_PREFIX) ||
|
285
|
+
aValue.start_with?(FXL::RESOURCE_KEY_PREFIX) ||
|
286
|
+
aValue.start_with?(FXL::EXPRESSION_PREFIX) ||
|
287
|
+
aValue.start_with?(FXL::BI_DIRECTIONAL_BINDING_PREFIX)))
|
288
|
+
raise LoadException.new("Invalid escape sequence.");
|
289
|
+
end
|
290
|
+
return aValue;
|
291
|
+
elsif (aValue.start_with?(FXL::RELATIVE_PATH_PREFIX))
|
292
|
+
aValue = aValue[FXL::RELATIVE_PATH_PREFIX.length..-1]
|
293
|
+
if (aValue.length == 0)
|
294
|
+
raise LoadException.new("Missing relative path.");
|
295
|
+
end
|
296
|
+
if (aValue.start_with?(FXL::RELATIVE_PATH_PREFIX))
|
297
|
+
# The prefix was escaped
|
298
|
+
warnDeprecatedEscapeSequence(RELATIVE_PATH_PREFIX);
|
299
|
+
return aValue;
|
300
|
+
else
|
301
|
+
begin
|
302
|
+
if $JRUBYFX_AOT_COMPILING
|
303
|
+
return RelativeFXMLString.new(aValue, URL.new(parentLoader.location, aValue).to_s)
|
304
|
+
else
|
305
|
+
return (aValue[0] == '/') ? classLoader.getResource(aValue[1..-1]).to_s : URL.new(parentLoader.location, aValue).to_s
|
306
|
+
end
|
307
|
+
rescue MalformedURLException => e
|
308
|
+
dp e
|
309
|
+
dputs "#{parentLoader.location} + /+ #{aValue}"
|
310
|
+
raise "whoops"
|
311
|
+
end
|
312
|
+
end
|
313
|
+
elsif (aValue.start_with?(FXL::RESOURCE_KEY_PREFIX))
|
314
|
+
aValue = aValue[FXL::RESOURCE_KEY_PREFIX.length..-1]
|
315
|
+
if (aValue.length() == 0)
|
316
|
+
raise LoadException.new("Missing resource key.");
|
317
|
+
end
|
318
|
+
if (aValue.start_with?(FXL::RESOURCE_KEY_PREFIX))
|
319
|
+
# The prefix was escaped
|
320
|
+
warnDeprecatedEscapeSequence(FXL::RESOURCE_KEY_PREFIX);
|
321
|
+
return aValue;
|
322
|
+
else
|
323
|
+
# Resolve the resource value
|
324
|
+
if (@resources == nil)
|
325
|
+
raise LoadException.new("No resources specified.");
|
326
|
+
end
|
327
|
+
if (!@resources.has_key?(aValue))
|
328
|
+
raise LoadException.new("Resource \"" + aValue + "\" not found.");
|
329
|
+
end
|
330
|
+
return @resources.getString(aValue);
|
331
|
+
end
|
332
|
+
elsif (aValue.start_with?(FXL::EXPRESSION_PREFIX))
|
333
|
+
aValue = aValue[FXL::EXPRESSION_PREFIX.length..-1]
|
334
|
+
if (aValue.length() == 0)
|
335
|
+
raise LoadException.new("Missing expression.");
|
336
|
+
end
|
337
|
+
if (aValue.start_with?(FXL::EXPRESSION_PREFIX))
|
338
|
+
# The prefix was escaped
|
339
|
+
warnDeprecatedEscapeSequence(FXL::EXPRESSION_PREFIX);
|
340
|
+
return aValue;
|
341
|
+
elsif (aValue == (FXL::NULL_KEYWORD))
|
342
|
+
# The attribute value is nil
|
343
|
+
return nil;
|
344
|
+
end
|
345
|
+
# remove all nils, them add one in at the end so [0] returns nil if empty
|
346
|
+
q = (KeyPath.parse(aValue).map{|i|parentLoader.namespace[i]} - [nil] + [nil])[0]
|
347
|
+
return q
|
348
|
+
end
|
349
|
+
return aValue;
|
350
|
+
end
|
351
|
+
|
352
|
+
=begin
|
353
|
+
* Creates an array of given type and populates it with values from a
|
354
|
+
* string where tokens are separated by ARRAY_COMPONENT_DELIMITER. If
|
355
|
+
* token is prefixed with RELATIVE_PATH_PREFIX a value added to the
|
356
|
+
* array becomes relative to document location.
|
357
|
+
=end
|
358
|
+
#TODO: fix this udp to use java arrays
|
359
|
+
def populateArrayFromString( type, stringValue)
|
360
|
+
|
361
|
+
propertyValue = nil;
|
362
|
+
# Split the string and set the values as an array
|
363
|
+
componentType = type.getComponentType();
|
364
|
+
|
365
|
+
if (stringValue.length > 0)
|
366
|
+
values = stringValue.split(FXL::ARRAY_COMPONENT_DELIMITER);
|
367
|
+
propertyValue = Array.newInstance(componentType, values.length);
|
368
|
+
values.length.times do |i|
|
369
|
+
Array.set(propertyValue, i,
|
370
|
+
RubyWrapperBeanAdapter.coerce(resolvePrefixedValue(values[i].strip),
|
371
|
+
type.getComponentType()));
|
372
|
+
end
|
373
|
+
else
|
374
|
+
propertyValue = Array.newInstance(componentType, 0);
|
375
|
+
end
|
376
|
+
return propertyValue;
|
377
|
+
end
|
378
|
+
|
379
|
+
=begin
|
380
|
+
* Populates list with values from a string where tokens are separated
|
381
|
+
* by ARRAY_COMPONENT_DELIMITER. If token is prefixed with
|
382
|
+
* RELATIVE_PATH_PREFIX a value added to the list becomes relative to
|
383
|
+
* document location.
|
384
|
+
=end
|
385
|
+
#TODO: check the types
|
386
|
+
def populateListFromString( valueAdapter, listPropertyName,stringValue)
|
387
|
+
# Split the string and add the values to the list
|
388
|
+
list = valueAdapter[listPropertyName].to_java
|
389
|
+
listType = valueAdapter.getGenericType(listPropertyName);
|
390
|
+
itemType = RubyWrapperBeanAdapter.getGenericListItemType(listType);
|
391
|
+
|
392
|
+
if (itemType.is_a? ParameterizedType)
|
393
|
+
itemType = ( itemType).getRawType();
|
394
|
+
end
|
395
|
+
|
396
|
+
if (stringValue.length() > 0)
|
397
|
+
values = stringValue.split(FXL::ARRAY_COMPONENT_DELIMITER)
|
398
|
+
|
399
|
+
for aValue in values
|
400
|
+
aValue = aValue.strip
|
401
|
+
list.add(
|
402
|
+
RubyWrapperBeanAdapter.coerce(resolvePrefixedValue(aValue),
|
403
|
+
itemType));
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def warnDeprecatedEscapeSequence(prefix)
|
409
|
+
puts(prefix + prefix + " is a deprecated escape sequence. " + "Please use \\" + prefix + " instead.");
|
410
|
+
end
|
411
|
+
|
412
|
+
def applyProperty(name, sourceType, value)
|
413
|
+
if (sourceType == nil)
|
414
|
+
getProperties[name] = value
|
415
|
+
else
|
416
|
+
RubyWrapperBeanAdapter.put3(@value, sourceType, name, value);
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def processEventHandlerAttributes()
|
421
|
+
if (@eventHandlerAttributes.length > 0 && !parentLoader.staticLoad)
|
422
|
+
for attribute in @eventHandlerAttributes
|
423
|
+
eventHandler = nil;
|
424
|
+
attrValue = attribute.value;
|
425
|
+
|
426
|
+
if (attrValue.start_with?(FXL::CONTROLLER_METHOD_PREFIX))
|
427
|
+
attrValue = attrValue[FXL::CONTROLLER_METHOD_PREFIX.length..-1]
|
428
|
+
if (!attrValue.start_with?(FXL::CONTROLLER_METHOD_PREFIX))
|
429
|
+
if (attrValue.length() == 0)
|
430
|
+
raise LoadException.new("Missing controller method.");
|
431
|
+
end
|
432
|
+
if (parentLoader.controller == nil)
|
433
|
+
dputs "eek"
|
434
|
+
raise LoadException.new("No controller specified. ");
|
435
|
+
end
|
436
|
+
|
437
|
+
# method = parentLoader.controller.method(attrValue)
|
438
|
+
#
|
439
|
+
# if (method == nil)
|
440
|
+
# raise LoadException.new("Controller method \"" + attrValue + "\" not found.");
|
441
|
+
# end
|
442
|
+
eventHandler = EventHandlerWrapper.new(parentLoader.controller, attrValue)
|
443
|
+
end
|
444
|
+
|
445
|
+
elsif (attrValue.start_with?(FXL::EXPRESSION_PREFIX))
|
446
|
+
attrValue = attrValue[FXL::EXPRESSION_PREFIX.length..-1]
|
447
|
+
if (attrValue.length() == 0)
|
448
|
+
raise LoadException.new("Missing expression reference.");
|
449
|
+
end
|
450
|
+
expression = Expression.get(@namespace, KeyPath.parse(attrValue));
|
451
|
+
if (expression.is_a? EventHandler)
|
452
|
+
eventHandler = expression;
|
453
|
+
end
|
454
|
+
|
455
|
+
end
|
456
|
+
if (eventHandler == nil)
|
457
|
+
if (attrValue.length() == 0 || parentLoader.scriptEngine == nil)
|
458
|
+
raise LoadException.new("Error resolving " + attribute.name + "='" + attribute.value +
|
459
|
+
"', either the event handler is not in the Namespace or there is an error in the script.");
|
460
|
+
end
|
461
|
+
|
462
|
+
eventHandler = ScriptEventHandler.new(attrValue, parentLoader.scriptEngine);
|
463
|
+
end
|
464
|
+
# Add the handler
|
465
|
+
if (eventHandler != nil)
|
466
|
+
|
467
|
+
addEventHandler(attribute, eventHandler);
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def addEventHandler(attribute, eventHandler)
|
474
|
+
if (attribute.name.end_with?(FXL::CHANGE_EVENT_HANDLER_SUFFIX))
|
475
|
+
i = FXL::EVENT_HANDLER_PREFIX.length();
|
476
|
+
j = attribute.name.length() - FXL::CHANGE_EVENT_HANDLER_SUFFIX.length();
|
477
|
+
if (i == j)
|
478
|
+
if (@value.is_a? ObservableList)
|
479
|
+
list = @value;
|
480
|
+
list.addListener(ObservableListChangeAdapter.new(list, eventHandler));
|
481
|
+
elsif (@value.is_a? ObservableMap)
|
482
|
+
map = @value;
|
483
|
+
map.addListener(ObservableMapChangeAdapter.new(map, eventHandler));
|
484
|
+
else
|
485
|
+
raise LoadException.new("Invalid event source.");
|
486
|
+
end
|
487
|
+
else
|
488
|
+
key = attribute.name[i].downcase + attribute.name[i + 1, j]
|
489
|
+
propertyModel = getValueAdapter().getPropertyModel(key);
|
490
|
+
if (propertyModel == nil)
|
491
|
+
raise LoadException.new(@value.getClass().getName() + " does not define" + " a property model for \"" + key + "\".");
|
492
|
+
end
|
493
|
+
|
494
|
+
propertyModel.addListener(PropertyChangeAdapter.new(@value, eventHandler));
|
495
|
+
end
|
496
|
+
else
|
497
|
+
getValueAdapter[attribute.name] = eventHandler
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
class Attribute
|
503
|
+
attr_accessor :name, :sourceType, :value
|
504
|
+
def initialize( paramString1,paramClass, paramString2)
|
505
|
+
@name = paramString1;
|
506
|
+
@sourceType = paramClass;
|
507
|
+
@value = paramString2;
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
class EventHandlerWrapper
|
512
|
+
include EventHandler
|
513
|
+
attr_reader :funcName
|
514
|
+
def initialize(ctrl, funcName)
|
515
|
+
@ctrl = ctrl
|
516
|
+
@funcName = funcName
|
517
|
+
end
|
518
|
+
def handle(eventArgs)
|
519
|
+
if @ctrl.respond_to? @funcName
|
520
|
+
if @ctrl.method(@funcName).arity == 0
|
521
|
+
@ctrl.send(@funcName)
|
522
|
+
else
|
523
|
+
@ctrl.send(@funcName, eventArgs)
|
524
|
+
end
|
525
|
+
else
|
526
|
+
puts "Warning: method #{@funcName} was not found on controller #{@ctrl}"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class ScriptEventHandler
|
532
|
+
include EventHandler
|
533
|
+
attr_reader :script, :scriptEngine
|
534
|
+
def initialize(script, scriptEngine)
|
535
|
+
@script = script;
|
536
|
+
@scriptEngine = scriptEngine;
|
537
|
+
end
|
538
|
+
|
539
|
+
def handle(event)
|
540
|
+
# Don't pollute the page namespace with values defined in the script
|
541
|
+
engineBindings = @scriptEngine.getBindings(ScriptContext::ENGINE_SCOPE);
|
542
|
+
#localBindings = @scriptEngine.createBindings(); # TODO: this causes errors with nashorn in jdk8 by creating a different kind of
|
543
|
+
# script object that doesn't respect the magic nashorn.global object
|
544
|
+
localBindings = Java::JavaxScript::SimpleBindings.new
|
545
|
+
localBindings.put_all(engineBindings)
|
546
|
+
localBindings.put(FXL::EVENT_KEY, event);
|
547
|
+
@scriptEngine.setBindings(localBindings, ScriptContext::ENGINE_SCOPE);
|
548
|
+
|
549
|
+
# Execute the script
|
550
|
+
begin
|
551
|
+
@scriptEngine.eval(@script);
|
552
|
+
rescue ScriptException => exception
|
553
|
+
raise exception
|
554
|
+
end
|
555
|
+
|
556
|
+
# Restore the original bindings
|
557
|
+
@scriptEngine.setBindings(engineBindings, ScriptContext::ENGINE_SCOPE);
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
class RelativeFXMLString < String
|
562
|
+
alias :super_inspect :inspect
|
563
|
+
def initialize(str, rel)
|
564
|
+
super(rel)
|
565
|
+
@rel = str
|
566
|
+
end
|
567
|
+
def inspect
|
568
|
+
"java.net.URL.new(__local_namespace['location'], #{@rel.inspect}).to_s"
|
569
|
+
end
|
570
|
+
def to_s
|
571
|
+
super
|
572
|
+
end
|
573
|
+
def class()
|
574
|
+
String
|
575
|
+
end
|
576
|
+
end
|