jrubyfx-fxmlloader 0.2-java

Sign up to get free protection for your applications and to get access to all the features.
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,5 @@
1
+ == FXMLLoader
2
+
3
+ Use with JRubyFX.
4
+
5
+ rake gem to build
@@ -0,0 +1,71 @@
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'
48
+ s.version = '0.2'
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
+ end
63
+
64
+ Gem::PackageTask.new(spec) do |p|
65
+ p.gem_spec = spec
66
+ p.need_tar = true
67
+ p.need_zip = true
68
+ end
69
+
70
+
71
+ task :default => :gem
Binary file
@@ -0,0 +1,564 @@
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
+ dputs callz + "Is it a collection? #{collection.inspect} <= #{@value.java_class}"
53
+ return collection;
54
+ end
55
+
56
+ def add(element)
57
+ dputs callz + "about to add #{element} to #{value.to_java}"
58
+ # If value is a list, add element to it; otherwise, get the value
59
+ # of the default property, which is assumed to be a list and add
60
+ # to that (coerce to the appropriate type)
61
+ if (@value.kind_of?(Enumerable) || @value.java_kind_of?(java.util.List))
62
+ value.to_java
63
+ else
64
+ type = value.java_class
65
+ defaultProperty = type.annotation(DefaultProperty.java_class);
66
+ defaultPropertyName = defaultProperty.to_java.value();
67
+
68
+ # Get the list value
69
+ list = getProperties[defaultPropertyName]
70
+
71
+ # Coerce the element to the list item type
72
+ if (!Map.java_class.assignable_from?(type))
73
+ listType = @valueAdapter.getGenericType(defaultPropertyName);
74
+ element = RubyWrapperBeanAdapter.coerce(element, RubyWrapperBeanAdapter.getListItemType(listType));
75
+ end
76
+ list = list.to_java if list.class == Java::JavaObject
77
+ list
78
+ end.add(element)
79
+ end
80
+
81
+ def set(value)
82
+ unless @value
83
+ raise LoadException.new("Cannot set value on this element.");
84
+ end
85
+
86
+ # Apply value to this element's properties
87
+ type = @value.java_class;
88
+ defaultProperty = type.getAnnotation(DefaultProperty.java_class);
89
+ if (defaultProperty == nil)
90
+ raise LoadException.new("Element does not define a default property.");
91
+ end
92
+
93
+ getProperties[defaultProperty.value] = value
94
+ end
95
+
96
+ def updateValue(value)
97
+ dputs callz + "Updating value from #{@value} to #{value.class}"
98
+ @value = value;
99
+ @valueAdapter = nil;
100
+ end
101
+
102
+ def isTyped()
103
+ dputs callz + "checking if typed"
104
+ dp @value.class
105
+ dp @value
106
+ q = !(@value.java_kind_of? Java::java.util.Map or @value.is_a? Hash );
107
+ dputs callz + "type result: #{q.inspect}"
108
+ q
109
+ end
110
+
111
+ def getValueAdapter()
112
+ if (@valueAdapter == nil)
113
+ dputs callz + "trying to get itqq"
114
+ dprint callz
115
+ dprint @value
116
+ dputs @value.class
117
+ dputs caller
118
+ if @value.class.to_s == "Java::JavafxFxml::ObjectBuilder"
119
+ dputs caller
120
+ end
121
+ if @value.is_a? java.lang.Object
122
+ dputs callz + "trying to call wrapper"
123
+ @valueAdapter = RubyWrapperBeanAdapter.new(@value);
124
+ else
125
+ dputs callz + "trying to call ruby object wrapper"
126
+ @valueAdapter = RubyObjectWrapperBeanAdapter.new(@value)
127
+ end
128
+ dputs callz + "got"
129
+ end
130
+ return @valueAdapter;
131
+ end
132
+
133
+ def getProperties()
134
+ return (isTyped()) ? getValueAdapter() : @value;
135
+ end
136
+
137
+ def processStartElement()
138
+ n = @xmlStreamReader.getAttributeCount()
139
+ n.times do |i|
140
+ prefix = @xmlStreamReader.getAttributePrefix(i);
141
+ localName = @xmlStreamReader.getAttributeLocalName(i);
142
+ value = @xmlStreamReader.getAttributeValue(i);
143
+
144
+ if (@loadListener && prefix && prefix == (FXL::FX_NAMESPACE_PREFIX))
145
+ @loadListener.readInternalAttribute(prefix + ":" + localName, value);
146
+ end
147
+
148
+ processAttribute(prefix, localName, value);
149
+ end
150
+ end
151
+
152
+ def processEndElement()
153
+ # No-op
154
+ end
155
+
156
+ def processCharacters()
157
+ raise LoadException.new("Unexpected characters in input stream.");
158
+ end
159
+
160
+ def processInstancePropertyAttributes()
161
+ if (@instancePropertyAttributes.length > 0)
162
+ for attribute in @instancePropertyAttributes
163
+ processPropertyAttribute(attribute);
164
+ end
165
+ end
166
+ end
167
+
168
+ def processAttribute(prefix, localName, value)
169
+ if (prefix == nil)
170
+ # Add the attribute to the appropriate list
171
+ if (localName.start_with?(FXL::EVENT_HANDLER_PREFIX))
172
+ if (@loadListener != nil)
173
+ @loadListener.readEventHandlerAttribute(localName, value);
174
+ end
175
+ dputs callz + "found eventHandler prefix #{prefix}, #{localName}, #{value}"
176
+ eventHandlerAttributes <<(Attribute.new(localName, nil, value));
177
+ else
178
+ i = localName.rindex('.');
179
+
180
+ if (i == nil)
181
+ # The attribute represents an instance property
182
+ if (@loadListener != nil)
183
+ @loadListener.readPropertyAttribute(localName, nil, value);
184
+ end
185
+
186
+ dputs callz + "found property attrib #{prefix}, #{localName}, #{value}"
187
+ instancePropertyAttributes << (Attribute.new(localName, nil, value));
188
+ else
189
+ # The attribute represents a static property
190
+ name = localName[(i + 1)..-1];
191
+ sourceType = parentLoader.getType(localName[0, i]);
192
+
193
+ dputs callz + "found static property #{prefix}, #{localName}, #{value}"
194
+ dputs callz + "and its #{sourceType}, #{staticLoad}"
195
+ if (sourceType != nil)
196
+ if (@loadListener != nil)
197
+ @loadListener.readPropertyAttribute(name, sourceType, value);
198
+ end
199
+
200
+ @staticPropertyAttributes << (Attribute.new(name, sourceType, value));
201
+ elsif (staticLoad)
202
+ if (@loadListener != nil)
203
+ @loadListener.readUnknownStaticPropertyAttribute(localName, value);
204
+ end
205
+ else
206
+ raise LoadException.new(localName + " is not a valid attribute.");
207
+ end
208
+ end
209
+
210
+ end
211
+ else
212
+ raise LoadException.new(prefix + ":" + localName +
213
+ " is not a valid attribute.");
214
+ end
215
+ end
216
+
217
+ def processPropertyAttribute(attribute)
218
+ value = attribute.value;
219
+ if (isBindingExpression(value))
220
+ dputs callz + "is a binding !"
221
+ # Resolve the expression
222
+
223
+ if (attribute.sourceType != nil)
224
+ raise LoadException.new("Cannot bind to static property.");
225
+ end
226
+
227
+ if (!isTyped())
228
+ raise LoadException.new("Cannot bind to untyped object.");
229
+ end
230
+
231
+ # TODO We may want to identify binding properties in processAttribute()
232
+ # and apply them after build() has been called
233
+ if (@value.is_a? Builder)
234
+ raise LoadException.new("Cannot bind to builder property.");
235
+ end
236
+
237
+ value = value[2..-2] # TODO: BINDING_EXPRESSION_PREFIX == ${
238
+ #value.length() - 1];
239
+ # TODO: this only works for 7, not 8
240
+ dputs "getting expression value of '#{value}' with #{parentLoader.namespace}"
241
+ expression = Expression.valueOf(value);
242
+ dputs callz + "got the expression as '#{expression}'"
243
+ dp expression
244
+ # Create the binding
245
+ targetAdapter = RubyWrapperBeanAdapter.new(@value);
246
+ dputs callz + "target adapter is #{targetAdapter} from #{value}"
247
+ propertyModel = targetAdapter.getPropertyModel(attribute.name).to_java
248
+ type = targetAdapter.getType(attribute.name);
249
+ dputs callz + "prop model is #{propertyModel.inspect} and type is #{type.inspect}"
250
+ if (propertyModel.is_a? Property)
251
+ dputs callz + "checking out value using #{parentLoader.namespace}"
252
+ #expression.value_property.addListener(JRExpressionTargetMapping.new(expression, getProperties(), Expression.split(value)));
253
+ ( propertyModel).bind(RRExpressionValue.new(parentLoader.namespace, expression, type));
254
+ dputs callz + "bound!"
255
+ end
256
+ elsif (isBidirectionalBindingExpression(value))
257
+ raise UnsupportedOperationException.new("This feature is not currently enabled.");
258
+ else
259
+ dputs callz + "processing 3 for #{attribute.sourceType}, #{attribute.name}, #{value}"
260
+ processValue3(attribute.sourceType, attribute.name, value);
261
+ end
262
+ end
263
+
264
+ def isBindingExpression(aValue)
265
+ dputs callz + "checking if '#{aValue}' is a binding prefix..."
266
+ # TODO: BINDING_EXPRESSION_PREFIX == ${
267
+ q = aValue.start_with?("${") && aValue.end_with?(FXL::BINDING_EXPRESSION_SUFFIX);
268
+ dputs callz + "it is? #{q.inspect}"
269
+ q
270
+ end
271
+
272
+ def isBidirectionalBindingExpression(aValue)
273
+ return aValue.start_with?(FXL::BI_DIRECTIONAL_BINDING_PREFIX);
274
+ end
275
+
276
+ def processValue3( sourceType, propertyName, aValue)
277
+
278
+
279
+ processed = false;
280
+ #process list or array first
281
+ if (sourceType == nil && isTyped())
282
+ dputs callz + "getting value adptr"
283
+ lvalueAdapter = getValueAdapter();
284
+ type = lvalueAdapter.getType(propertyName);
285
+
286
+ if (type == nil)
287
+ dputs "Processing values3 fails on: "
288
+ dp sourceType, propertyName, aValue
289
+ dp lvalueAdapter
290
+ dp caller
291
+ raise PropertyNotFoundException.new("Property \"" + propertyName + "\" does not exist" + " or is read-only.");
292
+ end
293
+ dputs "checking assignable"
294
+ if (List.java_class.assignable_from?(type) && lvalueAdapter.read_only?(propertyName))
295
+ populateListFromString(lvalueAdapter, propertyName, aValue);
296
+ processed = true;
297
+ elsif false #TODO: fix type.ruby_class.ancestors.include? Enumerable
298
+ applyProperty(propertyName, sourceType, populateArrayFromString(type, aValue));
299
+ processed = true;
300
+ end
301
+ end
302
+ dputs callz + "276"
303
+ if (!processed)
304
+ dputs callz + "Must appky it"
305
+ applyProperty(propertyName, sourceType, resolvePrefixedValue(aValue));
306
+ dputs callz + "280"
307
+ processed = true;
308
+ end
309
+ return processed;
310
+ end
311
+
312
+
313
+ # Resolves value prefixed with RELATIVE_PATH_PREFIX and
314
+ # RESOURCE_KEY_PREFIX.
315
+
316
+ def resolvePrefixedValue(aValue)
317
+ if (aValue.start_with?(FXL::ESCAPE_PREFIX))
318
+ aValue = aValue[FXL::ESCAPE_PREFIX.length..-1]
319
+
320
+ if (aValue.length == 0 || !(aValue.start_with?(FXL::ESCAPE_PREFIX) ||
321
+ aValue.start_with?(FXL::RELATIVE_PATH_PREFIX) ||
322
+ aValue.start_with?(FXL::RESOURCE_KEY_PREFIX) ||
323
+ aValue.start_with?(FXL::EXPRESSION_PREFIX) ||
324
+ aValue.start_with?(FXL::BI_DIRECTIONAL_BINDING_PREFIX)))
325
+ raise LoadException.new("Invalid escape sequence.");
326
+ end
327
+ return aValue;
328
+ elsif (aValue.start_with?(FXL::RELATIVE_PATH_PREFIX))
329
+ aValue = aValue[FXL::RELATIVE_PATH_PREFIX.length..-1]
330
+ if (aValue.length == 0)
331
+ raise LoadException.new("Missing relative path.");
332
+ end
333
+ if (aValue.start_with?(FXL::RELATIVE_PATH_PREFIX))
334
+ # The prefix was escaped
335
+ warnDeprecatedEscapeSequence(RELATIVE_PATH_PREFIX);
336
+ return aValue;
337
+ else
338
+ begin
339
+ return (aValue[0] == '/') ? classLoader.getResource(aValue[1..-1]).to_s : URL.new(parentLoader.location, aValue).to_s
340
+ rescue MalformedURLException => e
341
+ dp e
342
+ dputs "#{parentLoader.location} + /+ #{aValue}"
343
+ raise "whoops"
344
+ end
345
+ end
346
+ elsif (aValue.start_with?(FXL::RESOURCE_KEY_PREFIX))
347
+ aValue = aValue[FXL::RESOURCE_KEY_PREFIX.length..-1]
348
+ if (aValue.length() == 0)
349
+ raise LoadException.new("Missing resource key.");
350
+ end
351
+ if (aValue.start_with?(FXL::RESOURCE_KEY_PREFIX))
352
+ # The prefix was escaped
353
+ warnDeprecatedEscapeSequence(FXL::RESOURCE_KEY_PREFIX);
354
+ return aValue;
355
+ else
356
+ # Resolve the resource value
357
+ if (@resources == nil)
358
+ raise LoadException.new("No resources specified.");
359
+ end
360
+ if (!@resources.has_key?(aValue))
361
+ raise LoadException.new("Resource \"" + aValue + "\" not found.");
362
+ end
363
+ return @resources.getString(aValue);
364
+ end
365
+ elsif (aValue.start_with?(FXL::EXPRESSION_PREFIX))
366
+ aValue = aValue[FXL::EXPRESSION_PREFIX.length..-1]
367
+ if (aValue.length() == 0)
368
+ raise LoadException.new("Missing expression.");
369
+ end
370
+ if (aValue.start_with?(FXL::EXPRESSION_PREFIX))
371
+ # The prefix was escaped
372
+ warnDeprecatedEscapeSequence(FXL::EXPRESSION_PREFIX);
373
+ return aValue;
374
+ elsif (aValue == (FXL::NULL_KEYWORD))
375
+ # The attribute value is nil
376
+ return nil;
377
+ end
378
+ dputs callz + "Getting expression '#{aValue}'"
379
+ # remove all nils, them add one in at the end so [0] returns nil if empty
380
+ q = (KeyPath.parse(aValue).map{|i|parentLoader.namespace[i]} - [nil] + [nil])[0]
381
+ dputs callz + "Parsed Expression! #{q};;;;#{q.inspect}"
382
+ return q
383
+ end
384
+ return aValue;
385
+ end
386
+
387
+ =begin
388
+ * Creates an array of given type and populates it with values from a
389
+ * string where tokens are separated by ARRAY_COMPONENT_DELIMITER. If
390
+ * token is prefixed with RELATIVE_PATH_PREFIX a value added to the
391
+ * array becomes relative to document location.
392
+ =end
393
+ #TODO: fix this udp to use java arrays
394
+ def populateArrayFromString( type, stringValue)
395
+
396
+ propertyValue = nil;
397
+ # Split the string and set the values as an array
398
+ componentType = type.getComponentType();
399
+
400
+ if (stringValue.length > 0)
401
+ values = stringValue.split(FXL::ARRAY_COMPONENT_DELIMITER);
402
+ propertyValue = Array.newInstance(componentType, values.length);
403
+ values.length.times do |i|
404
+ Array.set(propertyValue, i,
405
+ RubyWrapperBeanAdapter.coerce(resolvePrefixedValue(values[i].strip),
406
+ type.getComponentType()));
407
+ end
408
+ else
409
+ propertyValue = Array.newInstance(componentType, 0);
410
+ end
411
+ return propertyValue;
412
+ end
413
+
414
+ =begin
415
+ * Populates list with values from a string where tokens are separated
416
+ * by ARRAY_COMPONENT_DELIMITER. If token is prefixed with
417
+ * RELATIVE_PATH_PREFIX a value added to the list becomes relative to
418
+ * document location.
419
+ =end
420
+ #TODO: check the types
421
+ def populateListFromString( valueAdapter, listPropertyName,stringValue)
422
+ # Split the string and add the values to the list
423
+ list = valueAdapter[listPropertyName].to_java
424
+ listType = valueAdapter.getGenericType(listPropertyName);
425
+ itemType = RubyWrapperBeanAdapter.getGenericListItemType(listType);
426
+
427
+ if (itemType.is_a? ParameterizedType)
428
+ itemType = ( itemType).getRawType();
429
+ end
430
+
431
+ if (stringValue.length() > 0)
432
+ values = stringValue.split(FXL::ARRAY_COMPONENT_DELIMITER)
433
+
434
+ for aValue in values
435
+ aValue = aValue.strip
436
+ list.add(
437
+ RubyWrapperBeanAdapter.coerce(resolvePrefixedValue(aValue),
438
+ itemType));
439
+ end
440
+ end
441
+ end
442
+
443
+ def warnDeprecatedEscapeSequence(prefix)
444
+ puts(prefix + prefix + " is a deprecated escape sequence. " + "Please use \\" + prefix + " instead.");
445
+ end
446
+
447
+ def applyProperty(name, sourceType, value)
448
+ if (sourceType == nil)
449
+ getProperties[name] = value
450
+ else
451
+ RubyWrapperBeanAdapter.put3(@value, sourceType, name, value);
452
+ end
453
+ end
454
+
455
+ def processEventHandlerAttributes()
456
+ if (@eventHandlerAttributes.length > 0 && !parentLoader.staticLoad)
457
+ for attribute in @eventHandlerAttributes
458
+ eventHandler = nil;
459
+ attrValue = attribute.value;
460
+
461
+ if (attrValue.start_with?(FXL::CONTROLLER_METHOD_PREFIX))
462
+ attrValue = attrValue[FXL::CONTROLLER_METHOD_PREFIX.length..-1]
463
+ if (!attrValue.start_with?(FXL::CONTROLLER_METHOD_PREFIX))
464
+ if (attrValue.length() == 0)
465
+ raise LoadException.new("Missing controller method.");
466
+ end
467
+ if (parentLoader.controller == nil)
468
+ dputs "eek"
469
+ raise LoadException.new("No controller specified. ");
470
+ end
471
+
472
+ # method = parentLoader.controller.method(attrValue)
473
+ #
474
+ # if (method == nil)
475
+ # raise LoadException.new("Controller method \"" + attrValue + "\" not found.");
476
+ # end
477
+ eventHandler = EventHandlerWrapper.new(parentLoader.controller, attrValue)
478
+ end
479
+
480
+ elsif (attrValue.start_with?(FXL::EXPRESSION_PREFIX))
481
+ attrValue = attrValue[FXL::EXPRESSION_PREFIX.length..-1]
482
+ if (attrValue.length() == 0)
483
+ raise LoadException.new("Missing expression reference.");
484
+ end
485
+ dputs callz + "exprValue!' #{attrValue}'"
486
+ expression = Expression.get(@namespace, KeyPath.parse(attrValue));
487
+ if (expression.is_a? EventHandler)
488
+ eventHandler = expression;
489
+ end
490
+
491
+ end
492
+ if (eventHandler == nil)
493
+ if (attrValue.length() == 0 || @scriptEngine == nil)
494
+ raise LoadException.new("Error resolving " + attribute.name + "='" + attribute.value +
495
+ "', either the event handler is not in the Namespace or there is an error in the script.");
496
+ end
497
+
498
+ eventHandler = ScriptEventHandler.new(attrValue, @scriptEngine);
499
+ end
500
+ # Add the handler
501
+ if (eventHandler != nil)
502
+
503
+ addEventHandler(attribute, eventHandler);
504
+ end
505
+ end
506
+ end
507
+ end
508
+
509
+ def addEventHandler(attribute, eventHandler)
510
+ if (attribute.name.end_with?(FXL::CHANGE_EVENT_HANDLER_SUFFIX))
511
+ i = FXL::EVENT_HANDLER_PREFIX.length();
512
+ j = attribute.name.length() - FXL::CHANGE_EVENT_HANDLER_SUFFIX.length();
513
+ if (i == j)
514
+ if (@value.is_a? ObservableList)
515
+ list = @value;
516
+ list.addListener(ObservableListChangeAdapter.new(list, eventHandler));
517
+ elsif (@value.is_a? ObservableMap)
518
+ map = @value;
519
+ map.addListener(ObservableMapChangeAdapter.new(map, eventHandler));
520
+ else
521
+ raise LoadException.new("Invalid event source.");
522
+ end
523
+ else
524
+ key = attribute.name[i].downcase + attribute.name[i + 1, j]
525
+ propertyModel = getValueAdapter().getPropertyModel(key);
526
+ if (propertyModel == nil)
527
+ raise LoadException.new(@value.getClass().getName() + " does not define" + " a property model for \"" + key + "\".");
528
+ end
529
+
530
+ propertyModel.addListener(PropertyChangeAdapter.new(@value, eventHandler));
531
+ end
532
+ else
533
+ getValueAdapter[attribute.name] = eventHandler
534
+ end
535
+ end
536
+ end
537
+
538
+ class Attribute
539
+ attr_accessor :name, :sourceType, :value
540
+ def initialize( paramString1,paramClass, paramString2)
541
+ @name = paramString1;
542
+ @sourceType = paramClass;
543
+ @value = paramString2;
544
+ end
545
+ end
546
+
547
+ class EventHandlerWrapper
548
+ include EventHandler
549
+ def initialize(ctrl, funcName)
550
+ @ctrl = ctrl
551
+ @funcName = funcName
552
+ end
553
+ def handle(eventArgs)
554
+ if @ctrl.respond_to? @funcName
555
+ if @ctrl.method(@funcName).arity == 0
556
+ @ctrl.send(@funcName)
557
+ else
558
+ @ctrl.send(@funcName, eventArgs)
559
+ end
560
+ else
561
+ dputs "Warning: method #{@funcName} was not found on controller #{@ctrl}"
562
+ end
563
+ end
564
+ end