- Loading...
- No images or files uploaded yet.
Other Tasks:
Week 15: (11/29 – 12/05)
Changed the bind implementation a little. Now the syntax for bind is field1.property.text.bind field2.property.text and now field1.text works as expected (returns the String text).
Issue: ActionListener does get invoked on UI input but does not get called on setText() .. Have not found any solution for this yet.. Source Code:
Might be useful someday: (added the link to reference)I have been testing the dynamic method invocation in Groovy: It allows method calls such as field1."$methodname"() so we could create the getter and setter method names of the property dynamically and call them.
Invalid Syntax: String foo = "$toUpperCase" String bar = "bar" bar.foo()
Valid syntax: String foo = "toUpperCase" String bar = "bar" bar."$foo"()
Week 13 & 14: (11/15 – 11/28)Hours:
To Do:
The problem with last week's appraoches was that we wanted to do field1.text.bind field2.text and not field1.bind field2 Initially I tried to override the dot operator since operators are overload-able in groovy but found out that groovy only allows operator overloading on a selected set of operators and the dot operator was not included. Next approach was based on trying to override the actual dot method since "Since 1.0, Groovy supports the ability to intercept all method and property access via the invokeMethod and get/setProperty hooks" but the dot method was not captured in the invokeMethod block.
So finally I added some magic to the field1.text part by overriding the getProperty method (using ExpandoMetaClass and its overriding magic) on JTextField. Now instead of returning the text property of the JTextField it returns a BoundJTextField, a class that contains a bind method. So the user can do field1.text.bind field2.text and in the background both the text properties get bound to each other. Right now by default the text property is bound but we could potentially bind any property since we are passing in the property name.
Issue: ActionListener does get invoked on UI input but does not get called on setText()
Source Code:
Next Step: I need to move the replace getProperty code to a seperate place and see how to include it. Also need to try out other components and binding with BoundProp type variables. (BoundProp to BoundProp binding was already done in last week's work)
Might be useful someday: I have been testing the dynamic method invocation in Groovy: It allows method calls such as field1."$methodname"() so we could create the getter and setter method names of the property dynamically and call them.
Updates: Finally I have been able to move the getProperty override code to a seperate class. It only works with the latest version of groovy which I checked out from SVN and built (doesn't even work with Groovy1.1 RC2). Even the latest developer version of Eclipse plugin could not run the code so will have to stick to command line for the time being. Beauty of it is that the packages just need to be in the project and the user doesn't even have to import anything. All this is done by using the DelegatingMetaClass & Package Name Convention Solution
So the code looks something like this (for JTextField):
package groovy.runtime.metaclass.javax.swing;
class JTextFieldMetaClass extends DelegatingMetaClass{
JTextFieldMetaClass(MetaClass metaclass) { super(metaclass); }
public Object getProperty(Object object, String property){ //if property is "text" return a BoundJTextField //else return the property value }
Based on the package and the class name the MetaClass of JTextField is automatically replaced by the above class. Source Code:
Week 12: (11/08 – 11/14)Hours: 9
To Do:
2. Bind in Groovy1st Approach: Categories With Categories "To add a method to a class T, simply define a new class with a static method whose first parameter is of type T." e.g.
class BoundCategory { static void bind(JTextField field1, BoundProp other) { field1.actionPerformed = { e -> println "event fired from component"; other.set(field1.getText()) } other.propertyChange = { e -> println "event fired from boundProperty"; field1.setText(e.getNewValue()) } } }
and then to use it
JTextField field1 = new JTextField() Book book1 = new Book() // A class with a member "title" of type BoundProp
use (BoundCategory) { /*binding a JTextField to a property*/ field1.bind book1.title }
but we want to bind the text property of the JTextField and not the field itself. A possible syntax is field1.bind("text", book1.title) .. but this does not seem very intuitive!
2nd Approach: BoundJTextField The other approach was to create our own BoundJTextField class as we did in Scala.. Then the syntax to use it would be..
def field1 = new BoundJTextField() Book book1 = new Book() field1.bText.bind book1.title //could not use field.text because apparently text is a member of JTextField in Groovy
Not as great as Scala where you didnt have to know about BoundJTextField's (except importing headers) and you would get the added functionality automagically.. also this isn't using any of the Dynamic features of Groovy. So no Groovy magic here.
3rd Approach: ExpandoMetaClass You can add new methods to classes using the ExpandoMetaClass.. with the following syntax..
JTextField.metaClass.bind << {BoundProp other -> //do binding here} def field1 = new JTextField() Book book1 = new Book() field1.bind book1.title
but this has the same problem as the 1st approach. We want to say field1.text.bind not field1.bind.
Sample Code for above approaches: (The MetaTester requires Groovy-1.1-rc2)
Other issues:
Week 11: (11/01 – 11/07)Hours: 10
To Do:
1. Fix sample (Stocks) applicationSource Code:
Nice to Have Feature: An overloaded method bind that handles the following situation.
val field = new JTextField; field bind dollarAmount * euroRate or val label = new JLabel label bind "Number of button clicks: {model.numClicks}"
Our bind only does a bidirectional bind between two Bound Properties (the Bound Property could belong to a JComponent). It does not allow unidirectional binding where the property can be attached to a Statement/Expression/Closure. If we were to create an overloaded method bind what type of parameter can we pass in it to store the required information?
3. How to implement bind in Groovy
a) Most promising way seems to be through Categories. Created a trivial example of adding a method to a JTextField and that ran successfully.
b) Another way seems to be through ExpandoMetaClasses but have been unsuccessful yet in getting the following example from link to run class Book {
The above fails with "No such property: metaClass for class: java.lang.Class" error. Tried to import ExpandoMetaClass but that gives the error "unable to resolve groovy.lang.ExpandoMetaClass" Will test if my version of Groovy supports ExpandoMetaClass or I need to upgrade.
Other useful Groovy features:1. Parenthesis less methods & named parameters Reference: UserGuide- statements Method calls in Groovy can omit the parenthesis if there is at least one parameter and there is no ambiguity.
println "Hello world" System.out.println "Nice cheese Gromit!"
It is also possible to omit parenthesis when using named arguments. This makes for nicer DSLs:
compare fund: "SuperInvestment", withBench: "NIKEI" monster.move from: [3,4], to: [4,5]
When calling a method you can pass in named parameters. Parameter names and values are separated by a colon (like the Map syntax) though the parameter names are identifiers rather than Strings. Currently this kind of method passing is only implemented for calling methods which take a Map or for constructing JavaBeans.
def bean = new Expando(name:"James", location:"London", id:123) println "Hey " + bean.name assert bean.id == 123
2. Adding Listeners in Groovy Reference: Getting Stated Guide - Groovy Beans Though Groovy doesn't support anonymous inner classes, it is possible to define action listeners inline through the means of closures. So instead of writing in Java:
Processor deviceProc = ... deviceProc.addControllerListener(new ControllerListener() { public void controllerUpdate(ControllerEvent ce) { ... } }
You can do that in Groovy with a closure:
//Add a closure for a particular method on the listener interface deviceProc.controllerUpdate = { ce -> println "I was just called with event $ce" }
Notice how the closure is for a method on the listener interface (controllerUpdate), and not for the interface itself(ControllerListener). This technique means that Groovy's listener closures are used like a ListenerAdapter where only one method of interest is overridden. This mechanism is heavily used in the Swing builder to define event listeners for various components and listeners. The JavaBeans introspector is used to make event listener methods available as properties which can be set with a closure The Java Beans introspector (java.beans.Introspector) which will look for a BeanInfo for your bean or create one using its own naming conventions. (See the Java Beans spec for details of the naming conventions it uses if you don't provide your own BeanInfo class). We're not performing any naming conventions ourselves - the standard Java Bean introspector does that for us. Basically the BeanInfo is retrieved for a bean and its EventSetDescriptors are exposed as properties (assuming there is no clash with regular beans). It's actually the EventSetDescriptor.getListenerMethods() which is exposed as a writable property which can be assigned to a closure.
3. Beans in Groovy Reference: Groovy Beans When Groovy is compiled to bytecode, the following rules are used.
4. Closures Reference: Groovy Statements If a method takes parameters you can leave the closure outside of the parenthesis (provided that the closure parameter is the last parameter on the underlying method). def value = [1, 2, 3].inject(0) { count, item -> count + item } assert value == 6
5. Miscellaneous
Week 10: (10/25 – 10/31)Hours: 6
To Do:
1. Create other Bound JComponents and package them up
2. Generate Scaladoc:Link to scaladoc man page: http://www.scala-lang.org/docu/files/tools/scaladoc.html Generated Documentation for BoundUtilities:
5. List JavaFX classes that encapsulates JComponentsLink to API: https://openjfx.dev.java.net/nonav/api/index.html
JavaFX has its own classes that encapsulate functionality of many JComponents such as:
Week 9: (10/18 – 10/24)Hours: 14 To Do:
1. Create BoundBeanProp classProblem: The listeners are not getting called when the user changes value in the JTextField (or JComboBox or JList). This is due to the fact that when the value is changed through the UI the firePropertyChange does not happen.
How does JavaFX handle this? JavaFX has its own classes that encapsulate each underlying JComponent class. So it uses other listeners besides propertyChangeListener.
Is DocumentListener an option? Question: Can we assume all BoundBean properties will have a document listener? Question: Isnt the document listener added to the document or can we add it to the eventSetDescriptor of the BoundBeanProp? If yes which one of the eventSetDescriptors?
We are trying to make a BoundBeanProperty class by adding propertyChangeListeners using reflection. After encountering the above problem we decided to do what JavaFX does and create our own TextField class. Now facing another road block because the propertyChangeListeners do get called but with a propertyEvent named "ancestor" (my guess is this happens because the text isn't a property of the JTextField but its ancestor Document). But this leaves us with the problem of how to find which property changed? Anyways I thought if we were creating our own components anyways (and also adding firepropertychange listeners for each one of the properties manually) so why not go back to the BoundJTextField approach. So with the newly acquired nifty view creating power and a tiny hack I have created the BoundJTextField (JTextField on steroids!) and the user just has to add an import statement to automagically get the power of bind in the good ol' JTextField.
import util.BoundJTextField._;
and you can do:
val field1 = new JTextField; field1.text bind p.name; //name is a BoundProp[String] and p is an object of some class Person
and Voila! you have bi-directional bind:) Compare this to the JavaFX bind (the nicer readabilty is due to the Declarative syntax!) TextField {
Even if for some reason we decide to plod on with the BoundBeanProperty approach.. this was still worth the time put in just to see the results.. I am officially a Scala convert now:)
Source Code for the magic:
Week 8: (10/11 – 10/17)Hours: 8 To Do:
3. Move implicit conversions to a seperate packageCreated companion objects and moved implicit conversion to those. Attached sample src code.
4. Remove propertyChangeListener from BoundJTextListenerIf I remove the "with PropertyChangeListener" part from the declaration of class BoundJTextField it gives the following error: "The method addPropertyChangeListener(PropertyChangeListener) in the type PropertyChangeSupport is not applicable for the arguments (BoundJTextField) ". Why is this happening when JComponent implements PropertyChangeListener? (Answer: Use anonymous inner class)
5. Are variables public by default in Scala, and how to get Field objectsTo get field objects of "private" vars we can do class.getDeclaredField("fieldName"); I was using the getField method which only returns public fields. Jury still out on whether vars are public/private by default in Scala. From above fact it seems that vars are private but you can specifically say "private var xname : String = _;" in which case you cannot access the var without the getter. So how is this private different than the by default private type behavior? there is apparently no public access modifier in Scala for variables (gives an error if I qualify a var with it!) and the specs do not mention public as an access modifier! (Answer: One is implementation detail)
6. Why were overridden methods not being called when I used viewsI wanted to add and override some methods in class BigInt using views, I could successfully add the methods but the method that I overrode (toString) were not being called and instead it was just calling the regular toString of BigInt. Reason from the Scala list: "The implicit conversion is only applied when it *needs* to be. Since (variable) is declared as a BigInt, and BigInt already defines a toString method, no conversion is necessary. The conversion is inferred separately at each site." Possible solution is subclass RichInt from BigInt and then override the method.
Week 7: (10/4 – 10/10)Hours: 12 hrs To Do:
1. Sample program to implement student name BoundProperty which is bound to a textboxSome success at last!
JavaFX syntax TextField { value: bind someVariable }
OurSyntax: val field1 = new BoundJTextField; field1.value bind name; //name being a BoundProp[String]
2. Actual uses of triggers in programs:Basically on update perform a check, call a function, or take some action. Bind on the other hand is bidirectional update of 2 variables dependent on each other. Sample uses of triggers in a program:
Also this javafx script page says "JavaFX Triggers are introduced with the A trigger consists of a header and a body. The header specifies the type of event the <-- So I think triggers only provide functionality that JavaFX lacks due to absence of constructors and setters. We could do all the trigger work in setters and constructors.
3. Can we get field objects in Scala?Field objects are useless since all the class members are actually accessor methods below the hood so we won't have any fields in a scala class when we do javap/scalap.
We can get method objects though. But since we don't do bind on class but on objects we don't need to look into this right now.
Week 6: (9/27 – 10/3)Hours: 8 To Do:
1. Sample BoundProp Program:JavaFX code we are trying to simulate:
class X { attribute num: Number?; }
trigger on X.num[oldValue] = newValue {
var x = X { num: 100 };
x.num = 3; // prints X.num: just replaced 100 with 3
Code for the BoundProp class and tester (with closures):
Problems:
Questions:
Prof. Horstmann suggested the java beans PropertyChangeListener and implicit conversions. Result still not perfect:( Code for the BoundProp class and tester (with java beans PropertyChangeListener):
Problems:
About overloading assignment (=) operator: Source: Scala mailing list
"The short answer to your question is that assignment isn't an operator defined for a class, it's an operation treated specially by the compiler. The long answer: in Scala, "operators" are really messages sent to objects.
1 + 2 is really
1.+(2)
But if you try to look at assignment that way, you run into a problem.
val foo = new Foo()
would become
val foo.=(new Foo())
So what class would define the method to receive the message? No Foo exists before the Foo is constructed and after the Foo is constructed we don't want to assign it to itself. The only answer is that, in some situations at least, the compiler has to have a default mechanism for assignment. Scala takes the simplest path - all assignments use that same mechanism."
Look at:
2. How to convert from Scala to Java:"Scala is designed to be Java compatible, and its translation attempts to map like constructs to like. Scala classes become same-named Java classes, etc. To know for sure, however, you must use tools like
Week 5: (9/20 – 9/26)Hours: 8 To Do:
1. Access level + Final and sealed modifiers: Reference: Scala Language Specification Tested with a sample program and classes are public by default.
The final modifier applies to class member definitions and to class definitions. A final class member definition may not be overridden in subclasses. A final class may not be inherited by a template. final is redundant for object definitions. Members of final classes or objects are implicitly also final, so the final modifier is redundant for them, too. final may not be applied to incomplete members, and it may not be combined in one modifier list with private or sealed. The sealed modifier applies to class definitions. A sealed class may not be directly inherited, except if the inheriting template is defined the same source file as the inherited class. However, subclasses of a sealed class can inherited anywhere.
2. Operator Precedence: Reference: Scala Overview The precedence of an infix operator is determined by its first character; it coincides with the operator precedence of Java for those operators that start with an operator character used in these languages. The following lists operators in increasing precedence: (all letters) | ^ & < > = ! : + * / % (all other special characters) Operators are usually left-associative, i.e. x + y + z is interpreted as (x + y) + z. The only exception to that rule are operators ending in a colon. These are treated as right-associative. An example is the list-consing operator ::. Here, x :: y :: zs is interpreted as x :: (y :: zs). Right-associative operators are also treated differently with respect to method lookup. Whereas normal operators take their left operand as receiver, right-associative operators take their right operand as receiver. For instance, the list consing sequence x :: y :: zs is treated as equivalent to zs.::(y).::(x). In fact, :: is implemented as a method in Scala’s List class, which prefixes a given argument to the receiver list and returns the resulting list as result.
4. Override default getter and setters: Tried in code to override default accessors but it does not allow this either in class or even in subclasses. Though this Link says you could do override in subclasses but I tried to run the code and it gave me an error "error overriding variable x in class Foo of type Int; method x_= cannot override a mutable variable"
The link said: "You can override the setters/getters in a subclass: class Foo {
Also read up on properties in C#
5. Did any of the Scala features of last week allow us to do replace triggers? On a second look the statement "For every definition of a variable var x: T in a class, Scala defines setter and getter methods as follows. def x: T def x_= (newval: T): unit" seems to be talk about defining getters and setters only in terms of explaining how we can do variable dereferencing and assignment if every operation is a method call. They don't seem to be getters and setters in the real sense (of accessors) since the following does not work
class Kelvin { private var d: int = 0 //private variable }
object KelvinTester { def main(args: Array[String]) { val k:Kelvin = new Kelvin(); k.d_ = 5 //error value d_ is not a member of Kelvin k.d = 5 //variable d cannot be accessed in Kelvin System.out.println("k.d: " + k.d); //variable d cannot be accessed in Kelvin } } which makes sense since you cannot override these "getters and setters" so what use could they be to begin with?
so when they say Scala allows one to define properties in the C# sense, I think this is only possible when the actual variable name is different then the name of the setters/getters or there is no variable, just a getter and setter function
class Celsius { private var d: int = 0 def degree: int = d def degree_=(x: int): unit = if (x >= 273) d = x }
This does not seem to help us define a replace trigger: trigger on c.degree = newValue{ //do some action (call a function or print something etc.) when an assignment takes place. } even regular C# style properties would not help in defining triggers since triggers are defined outside of the class.. and we shouldn't be going back and changing the class definition .... hmm back to square 1 .. no idea how to do triggers(new or replace type). Is JavaFX able to do triggers cause they have methods declared outside the class definition and override the new or "=" operator when a trigger is defined?
Is it possible to change a class from outside the class definition (like add a method or override a method) in Scala? Then I could define a triggerOnNew(String className) and in that method override the new method of the given class or triggerOnReplace(String className, String variableName) and override the setter method of the className.variableName in the method.
On a side note this problem of not being able to add methods to existing classes is called external extensibility problem according to Scala Overview. Interesting project called MultiJava extends java to add open classes to it!
So In the end I think views might be the best options since "views allow one to augment a class with new members and supported traits." Understand them a little better now. So next trying to make a small code example to see how we could use those to may be a add some functionality to a class.
Week 4: (9/13 – 9/19)Hours: 16 To Do:
Scala Features:Includes ideas for triggers and XML, pattern matching etc. in Scala
Week 3: (9/06 – 9/12)Hours: 8
To Do:
Examples and Features used in them:
New discovery:dur operator (from “duration”): "When assigning any value with an array of possible values and the operator Notes: To simulate multiple inheritance in scala look at mixins/Traits.
1. iTunes Display Shelf:Link to demo and code: http://blogs.sun.com/chrisoliver/feed/entries/atom?cat=%2FF3 Uses bind extensively. Trigger is used only on replace (mostly call a function on trigger). Some list comprehension, do/do later and dur operator also used.
2. Yahoo Maps:Link to demo and code: http://blogs.sun.com/chrisoliver/entry/more_f3_demos Uses bind extensively. Trigger is used only on replace. Some embedded HTML (Search errors). Also uses list comprehension, do/do later and dur operator.
3. Mariah Carey website:Link and code: http://javaboutique.internet.com/tutorials/javafx/ Used bind operator and possible areas of use for embedding HTML (for links and news etc.). Used dur a lot as well.
Insert keyword mimicked in scala:Code files: Results: The syntax is not as cool as JavaFX's "insert 5 into array". Also still need to figure out a way to mimic "insert 5 before expression in array" feature. Still working to find a better solution.
Week 2: (8/30 – 9/05)Hours: 13
To Do:
Features:1. Incremental dependency-based evaluation (automatic data binding): [1] Considering the following model/View type example, the value of the View's title is dependent upon the model's saying attribute. The dependency between View's textField and Model's saying attribute is bi-directional. Initially the value of the title and textField are set by model.saying but when the user updates the textField value the model.saying is automatically updated (which in turn updates the title).
import javafx.ui.*; The same functionality mimicked in java code is HelloWorldTest.java It also allows lazy incremental evaluation by using the keyword "lazy" [2] 2. Update Triggers: [2] JavaFX provides Triggers for data modification instead of constructors, destructors and setters etc. You can trigger on
Example: import java.lang.System;
3. List Comprehensions: [2] You can perform complex queries on arrays by using "select" and "foreach" key words. These are called List Comprehensions. Also note the use of conditional keyword "where".
Examples: var a:Integer* = select n*n from n in [1..10] where (n%2 == 0); // yields [4,16,36,64,100] var a:Integer* = foreach(n in [1..4], m in [100,200] where (n%2 == 0) )
4. Declarative syntax: Allows both declarative and procedural syntax. The declarative syntax makes for an easier read.
5. Static Typing: It does static typing (efficient compilation, compile time errors and warnings)
6. Type Inference: [2] Allows the programmer to omit the type in which case the interpreter tries to resolve the type.
7. First-class functions: [3] Treats functions as first-class objects.
8. Ability to embed HTML: [1] Allows embedding HTML in Labels (find out where else) .. seemed like the same thing as JSTL. # and ? operators where # stringifies the operand and ? dereferences it.
9. Multiple Inheritance: [2] Allows a class to extend from multiple classes (unlike Java).
10. Misc.: [2]
References:
Week 1: (8/23 – 8/29)Hours: 10
To do:
Deliverable :Project proposal
Issues/Questions:What are views in Scala? (supposedly enable metaprogramming)
Activities:Aug 23: Initial research for proposal material Aug 24: Created first draft of project proposal Aug 26: Apparently cannot update Eclipse so installed a 3.3 along with the old 3.2 one (don't want to redo all the pluggins!). Draft two of proposal created and uploaded. Aug 27: Installed scala plugin in Eclipse. Proposal finalized.
Week 0:
JavaFX:
Scala:
|
|
Comments (0)
You don't have permission to comment on this page.