ChangeListener.java
01 /*
02  * Copyright 2008-2016 the original author or authors.
03  *
04  * Licensed under the Apache License, Version 2.0 (the "License");
05  * you may not use this file except in compliance with the License.
06  * You may obtain a copy of the License at
07  *
08  *     http://www.apache.org/licenses/LICENSE-2.0
09  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package griffon.transform;
17 
18 import org.codehaus.groovy.transform.GroovyASTTransformationClass;
19 
20 import java.lang.annotation.ElementType;
21 import java.lang.annotation.Retention;
22 import java.lang.annotation.RetentionPolicy;
23 import java.lang.annotation.Target;
24 
25 /**
26  <p>Annotates a property.</p>
27  <p>This transformation provides a convenient way to register ChangeListeners
28  * on an observable bean by leveraging Groovy's closures and the Groovy cast operator.</p>
29  <p/>
30  <p>The following code exemplifies what must be written by hand in order to register a ChangeListener.
31  <pre>
32  * import griffon.transform.FXObservable
33  * import javafx.beans.value.ChangeListener
34  *
35  * class MyModel {
36  *     &#064;FXObservable String name
37  *     &#064;FXObservable String lastname
38  *
39  *     private def snoopAll = { ob, ov, nv -> ... }
40  *
41  *     MyModel() {
42  *         nameProperty().addListener(snoopAll as ChangeListener)
43  *         lastnameProperty().addListener({ ob, ov, nv ->
44  *             controller.someAction(nv)
45  *         } as ChangeListener)
46  *     }
47  * }
48  </pre>
49  <p/>
50  <p>Applying &#064;ChangeListener to the previous snippet results in the following code</p>
51  <pre>
52  * import griffon.transform.FXObservable
53  * import griffon.transform.ChangeListener
54  *
55  * class MyModel {
56  *     &#064;FXObservable
57  *     &#064;ChangeListener(snoopAll)
58  *     String name
59  *
60  *     &#064;FXObservable
61  *     &#064;ChangeListener({ ob, ov, nv -> controller.someAction(nv)})
62  *     String lastname
63  *
64  *     private def snoopAll = { ob, ov, nv -> ... }
65  * }
66  </pre>
67  <p>
68  * Any closures found as the annotation's value will be either transformed
69  * into inner classes that implement ChangeListener (when the value
70  * is a closure defined in place) or be casted as a proxy of ChangeListener
71  * (when the value is a property reference found in the same class).<p>
72  * List of closures are also supported.
73  *
74  @author Andres Almiray
75  */
76 @Retention(RetentionPolicy.SOURCE)
77 @Target({ElementType.FIELD})
78 @GroovyASTTransformationClass("org.codehaus.griffon.compile.core.ast.transform.ChangeListenerASTTransformation")
79 public @interface ChangeListener {
80     String value();
81 
82     /**
83      * If the {@code ChangeListener} should be wrapped with a {@code WeakChangeListener} or not
84      *
85      @since 2.4.0
86      */
87     boolean weak() default true;
88 }