ListChangeListener.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 ListChangeListeners
28  * on an ObservableList 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.ListChangeListener
33  * import griffon.transform.FXObservable
34  * import javafx.collections.FXCollections
35  * import javafx.collections.ObservableList
36  * import griffon.core.artifact.GriffonModel
37  *
38  * &#064;griffon.metadata.ArtifactProviderFor(GriffonModel)
39  * class SampleModel {
40  *     def controller
41  *
42  *     &#064;FXObservable
43  *     &#064;ListChangeListener(snoop)
44  *     ObservableList list = FXCollections.observableArrayList()
45  *
46  *     def snoop = { change -> ... }
47  * }
48  </pre>
49  <p/>
50  <p>Applying &#064;ChangeListener to the previous snippet results in the following code</p>
51  <pre>
52  * import javafx.collections.ListChangeListener
53  * import javafx.collections.FXCollections
54  * import javafx.collections.ObservableList
55  * import griffon.core.artifact.GriffonModel
56  *
57  * &#064;griffon.metadata.ArtifactProviderFor(GriffonModel)
58  * class SampleModel {
59  *    def controller
60  *
61  *     &#064;FXObservable ObservableList list = FXCollections.observableArrayList()
62  *
63  *     def snoop = { change -> ... }
64  *
65  *     SampleModel() {
66  *         listProperty().addListener(snoopAll as ListChangeListener)
67  *     }
68  * }
69  </pre>
70  <p>
71  * Any closures found as the annotation's value will be either transformed
72  * into inner classes that implement ListChangeListener (when the value
73  * is a closure defined in place) or be casted as a proxy of ListChangeListener
74  * (when the value is a property reference found in the same class).<p>
75  * List of closures are also supported.
76  *
77  @author Andres Almiray
78  @since 2.4.0
79  */
80 @Retention(RetentionPolicy.SOURCE)
81 @Target({ElementType.FIELD})
82 @GroovyASTTransformationClass("org.codehaus.griffon.compile.core.ast.transform.ListChangeListenerASTTransformation")
83 public @interface ListChangeListener {
84     String value();
85 
86     /**
87      * If the {@code ListChangeListener} should be wrapped with a {@code WeakListChangeListener} or not
88      */
89     boolean weak() default false;
90 }