01 /*
02 * Copyright 2008-2015 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 * @griffon.metadata.ArtifactProviderFor(GriffonModel)
39 * class SampleModel {
40 * def controller
41 *
42 * @FXObservable
43 * @ListChangeListener(snoop)
44 * ObservableList list = FXCollections.observableArrayList()
45 *
46 * def snoop = { change -> ... }
47 * }
48 * </pre>
49 * <p/>
50 * <p>Applying @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 * @griffon.metadata.ArtifactProviderFor(GriffonModel)
58 * class SampleModel {
59 * def controller
60 *
61 * @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 }
|