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 MapChangeListeners
30 * on an ObservableMap 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.MapChangeListener
35 * import griffon.transform.FXObservable
36 * import javafx.collections.FXCollections
37 * import javafx.collections.ObservableMap
38 * import griffon.core.artifact.GriffonModel
39 *
40 * @griffon.metadata.ArtifactProviderFor(GriffonModel)
41 * class SampleModel {
42 * def controller
43 *
44 * @FXObservable
45 * @MapChangeListener(snoop)
46 * ObservableMap map = FXCollections.observableHashMap()
47 *
48 * def snoop = { change -> ... }
49 * }
50 * </pre>
51 * <p/>
52 * <p>Applying @ChangeListener to the previous snippet results in the following code</p>
53 * <pre>
54 * import javafx.collections.MapChangeListener
55 * import javafx.collections.FXCollections
56 * import javafx.collections.ObservableMap
57 * import griffon.core.artifact.GriffonModel
58 *
59 * @griffon.metadata.ArtifactProviderFor(GriffonModel)
60 * class SampleModel {
61 * def controller
62 *
63 * @FXObservable ObservableMap map = FXCollections.observableHashMap()
64 *
65 * def snoop = { change -> ... }
66 *
67 * SampleModel() {
68 * mapProperty().addListener(snoopAll as MapChangeListener)
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 MapChangeListener (when the value
75 * is a closure defined in place) or be casted as a proxy of MapChangeListener
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.MapChangeListenerASTTransformation")
85 public @interface MapChangeListener {
86 String value();
87
88 /**
89 * If the {@code MapChangeListener} should be wrapped with a {@code WeakMapChangeListener} or not
90 */
91 boolean weak() default false;
92 }
|