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