Skip to content

Commit 85a5434

Browse files
committed
Add @CheckedChange androidannotations#389
1 parent 1196bc2 commit 85a5434

12 files changed

Lines changed: 275 additions & 8 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.androidannotations.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
9+
/**
10+
*
11+
* @author Rostislav Chekan
12+
*/
13+
@Retention(RetentionPolicy.CLASS)
14+
@Target(ElementType.METHOD)
15+
public @interface CheckedChange {
16+
int[] value() default ResId.DEFAULT_VALUE;
17+
18+
String[] resName() default "";
19+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.androidannotations.annotations.Background;
4040
import org.androidannotations.annotations.Bean;
4141
import org.androidannotations.annotations.BeforeTextChange;
42+
import org.androidannotations.annotations.CheckedChange;
4243
import org.androidannotations.annotations.Click;
4344
import org.androidannotations.annotations.EActivity;
4445
import org.androidannotations.annotations.EApplication;
@@ -125,6 +126,7 @@
125126
import org.androidannotations.processing.BackgroundProcessor;
126127
import org.androidannotations.processing.BeanProcessor;
127128
import org.androidannotations.processing.BeforeTextChangeProcessor;
129+
import org.androidannotations.processing.CheckedChangeProcessor;
128130
import org.androidannotations.processing.ClickProcessor;
129131
import org.androidannotations.processing.EActivityProcessor;
130132
import org.androidannotations.processing.EApplicationProcessor;
@@ -190,6 +192,7 @@
190192
import org.androidannotations.validation.AppValidator;
191193
import org.androidannotations.validation.BeanValidator;
192194
import org.androidannotations.validation.BeforeTextChangeValidator;
195+
import org.androidannotations.validation.CheckedChangeValidator;
193196
import org.androidannotations.validation.ClickValidator;
194197
import org.androidannotations.validation.EActivityValidator;
195198
import org.androidannotations.validation.EApplicationValidator;
@@ -258,6 +261,7 @@
258261
ItemLongClick.class, //
259262
Touch.class, //
260263
FocusChange.class, //
264+
CheckedChange.class, //
261265
ItemSelect.class, //
262266
UiThread.class, //
263267
Transactional.class, //
@@ -454,6 +458,7 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices
454458
modelValidator.register(new LongClickValidator(processingEnv, rClass));
455459
modelValidator.register(new TouchValidator(processingEnv, rClass));
456460
modelValidator.register(new FocusChangeValidator(processingEnv, rClass));
461+
modelValidator.register(new CheckedChangeValidator(processingEnv, rClass));
457462
modelValidator.register(new ItemClickValidator(processingEnv, rClass));
458463
modelValidator.register(new ItemSelectedValidator(processingEnv, rClass));
459464
modelValidator.register(new ItemLongClickValidator(processingEnv, rClass));
@@ -545,6 +550,7 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
545550
modelProcessor.register(new LongClickProcessor(processingEnv, rClass));
546551
modelProcessor.register(new TouchProcessor(processingEnv, rClass));
547552
modelProcessor.register(new FocusChangeProcessor(processingEnv, rClass));
553+
modelProcessor.register(new CheckedChangeProcessor(processingEnv, rClass));
548554
modelProcessor.register(new ItemClickProcessor(processingEnv, rClass));
549555
modelProcessor.register(new ItemSelectedProcessor(processingEnv, rClass));
550556
modelProcessor.register(new ItemLongClickProcessor(processingEnv, rClass));

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public final class CanonicalNameConstants {
4848
public static final String SEEKBAR = "android.widget.SeekBar";
4949
public static final String ON_SEEKBAR_CHANGE_LISTENER = "android.widget.SeekBar.OnSeekBarChangeListener";
5050
public static final String TEXT_VIEW = "android.widget.TextView";
51+
public static final String COMPOUND_BUTTON = "android.widget.CompoundButton";
5152
public static final String VIEW = "android.view.View";
5253
public static final String VIEW_ON_CLICK_LISTENER = "android.view.View.OnClickListener";
5354
public static final String VIEW_ON_TOUCH_LISTENER = "android.view.View.OnTouchListener";

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorParameterHelper.java‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,32 @@ public void hasZeroOrOneViewOrTwoViewBooleanParameters(ExecutableElement executa
116116
}
117117
}
118118

119+
public void hasZeroOrOneCompoundButtonOrTwoCompoundButtonBooleanParameters(ExecutableElement executableElement, IsValid valid) {
120+
List<? extends VariableElement> parameters = executableElement.getParameters();
121+
122+
if (parameters.size() == 0) {
123+
return;
124+
} else if (parameters.size() > 2) {
125+
valid.invalidate();
126+
annotationHelper.printAnnotationError(executableElement, "%s can only be used on a method with 0 or 1(CompoundButton) or 2(CompoundButton, boolean) parameter, instead of " + parameters.size());
127+
} else {
128+
VariableElement firstParameter = parameters.get(0);
129+
String firstParameterType = firstParameter.asType().toString();
130+
if (!firstParameterType.equals(CanonicalNameConstants.COMPOUND_BUTTON)) {
131+
valid.invalidate();
132+
annotationHelper.printAnnotationError(executableElement, "the first parameter must be a " + CanonicalNameConstants.COMPOUND_BUTTON + ", not a " + firstParameterType);
133+
}
134+
if (parameters.size() == 2) {
135+
VariableElement secondParameter = parameters.get(1);
136+
String secondParameterType = secondParameter.asType().toString();
137+
if (!secondParameterType.equals(CanonicalNameConstants.BOOLEAN) && !secondParameterType.equals("boolean")) {
138+
valid.invalidate();
139+
annotationHelper.printAnnotationError(executableElement, "the second parameter must be a " + CanonicalNameConstants.BOOLEAN + " or boolean, not a " + secondParameterType);
140+
}
141+
}
142+
}
143+
}
144+
119145
public void hasOneMotionEventOrTwoMotionEventViewParameters(ExecutableElement executableElement, IsValid valid) {
120146
List<? extends VariableElement> parameters = executableElement.getParameters();
121147

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/AbstractListenerProcessor.java‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,17 @@ public abstract class AbstractListenerProcessor implements DecoratingElementProc
5252
private IdAnnotationHelper helper;
5353
protected Classes classes;
5454
protected JCodeModel codeModel;
55+
protected EBeanHolder holder;
5556

5657
public AbstractListenerProcessor(ProcessingEnvironment processingEnv, IRClass rClass) {
5758
helper = new IdAnnotationHelper(processingEnv, getTarget(), rClass);
5859
}
5960

6061
@Override
61-
public void process(Element element, JCodeModel jcodeModel, EBeanHolder holder) {
62+
public void process(Element element, JCodeModel codeModel, EBeanHolder holder) {
6263
classes = holder.classes();
63-
codeModel = jcodeModel;
64+
this.codeModel = codeModel;
65+
this.holder = holder;
6466

6567
String methodName = element.getSimpleName().toString();
6668

@@ -88,7 +90,7 @@ public void process(Element element, JCodeModel jcodeModel, EBeanHolder holder)
8890
JInvocation findViewById = invoke("findViewById");
8991

9092
JVar view = block.decl(classes.VIEW, "view", findViewById.arg(idRef));
91-
block._if(view.ne(_null()))._then().invoke(view, getSetterName()).arg(_new(listenerAnonymousClass));
93+
block._if(view.ne(_null()))._then().invoke(castWidget(view), getSetterName()).arg(_new(listenerAnonymousClass));
9294
}
9395
}
9496

@@ -102,4 +104,8 @@ public void process(Element element, JCodeModel jcodeModel, EBeanHolder holder)
102104

103105
protected abstract JClass getListenerClass();
104106

107+
protected JExpression castWidget(JVar view) {
108+
return view;
109+
}
110+
105111
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package org.androidannotations.processing;
2+
3+
import java.lang.annotation.Annotation;
4+
import java.util.List;
5+
6+
import javax.annotation.processing.ProcessingEnvironment;
7+
import javax.lang.model.element.VariableElement;
8+
import javax.lang.model.type.TypeMirror;
9+
10+
import org.androidannotations.annotations.CheckedChange;
11+
import org.androidannotations.rclass.IRClass;
12+
13+
import com.sun.codemodel.JBlock;
14+
import com.sun.codemodel.JClass;
15+
import com.sun.codemodel.JDefinedClass;
16+
import com.sun.codemodel.JExpr;
17+
import com.sun.codemodel.JExpression;
18+
import com.sun.codemodel.JInvocation;
19+
import com.sun.codemodel.JMethod;
20+
import com.sun.codemodel.JMod;
21+
import com.sun.codemodel.JVar;
22+
23+
/**
24+
*
25+
* @author Rostislav Chekan
26+
*
27+
*/
28+
public class CheckedChangeProcessor extends AbstractListenerProcessor {
29+
30+
public CheckedChangeProcessor(ProcessingEnvironment processingEnv, IRClass rClass) {
31+
super(processingEnv, rClass);
32+
}
33+
34+
@Override
35+
public Class<? extends Annotation> getTarget() {
36+
return CheckedChange.class;
37+
}
38+
39+
@Override
40+
protected void makeCall(JBlock listenerMethodBody, JInvocation call, TypeMirror returnType) {
41+
listenerMethodBody.add(call);
42+
}
43+
44+
@Override
45+
protected void processParameters(JMethod listenerMethod, JInvocation call, List<? extends VariableElement> parameters) {
46+
JVar btnParam = listenerMethod.param(classes.COMPOUND_BUTTON, "buttonView");
47+
JVar isCheckedParam = listenerMethod.param(codeModel.BOOLEAN, "isChecked");
48+
boolean isCheckedParamExists = parameters.size() == 2;
49+
boolean btnParamExists = parameters.size() >= 1;
50+
51+
if (btnParamExists) {
52+
call.arg(btnParam);
53+
}
54+
if (isCheckedParamExists) {
55+
call.arg(isCheckedParam);
56+
}
57+
}
58+
59+
@Override
60+
protected JMethod createListenerMethod(JDefinedClass listenerAnonymousClass) {
61+
return listenerAnonymousClass.method(JMod.PUBLIC, codeModel.VOID, "onCheckedChanged");
62+
}
63+
64+
@Override
65+
protected String getSetterName() {
66+
return "setOnCheckedChangeListener";
67+
}
68+
69+
@Override
70+
protected JClass getListenerClass() {
71+
return holder.refClass("android.widget.CompoundButton.OnCheckedChangeListener");
72+
}
73+
74+
@Override
75+
protected JExpression castWidget(JVar view) {
76+
return JExpr.cast(classes.COMPOUND_BUTTON, view);
77+
}
78+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/EBeansHolder.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public class Classes {
6262
public final JClass SEEKBAR = refClass(CanonicalNameConstants.SEEKBAR);
6363
public final JClass ON_SEEKBAR_CHANGE_LISTENER = refClass(CanonicalNameConstants.ON_SEEKBAR_CHANGE_LISTENER);
6464
public final JClass TEXT_VIEW = refClass(CanonicalNameConstants.TEXT_VIEW);
65+
public final JClass COMPOUND_BUTTON = refClass(CanonicalNameConstants.COMPOUND_BUTTON);
6566
public final JClass VIEW = refClass(CanonicalNameConstants.VIEW);
6667
public final JClass VIEW_ON_CLICK_LISTENER = refClass(CanonicalNameConstants.VIEW_ON_CLICK_LISTENER);
6768
public final JClass VIEW_ON_TOUCH_LISTENER = refClass(CanonicalNameConstants.VIEW_ON_TOUCH_LISTENER);

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/processing/FocusChangeProcessor.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
import com.sun.codemodel.JMod;
1919
import com.sun.codemodel.JVar;
2020

21+
/**
22+
*
23+
* @author Rostislav Chekan
24+
*
25+
*/
2126
public class FocusChangeProcessor extends AbstractListenerProcessor {
2227

2328
public FocusChangeProcessor(ProcessingEnvironment processingEnv, IRClass rClass) {
@@ -63,5 +68,4 @@ protected String getSetterName() {
6368
protected JClass getListenerClass() {
6469
return classes.VIEW_ON_FOCUS_CHANGE_LISTENER;
6570
}
66-
6771
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.validation;
17+
18+
import java.lang.annotation.Annotation;
19+
20+
import javax.annotation.processing.ProcessingEnvironment;
21+
import javax.lang.model.element.Element;
22+
import javax.lang.model.element.ExecutableElement;
23+
24+
import org.androidannotations.annotations.CheckedChange;
25+
import org.androidannotations.helper.IdAnnotationHelper;
26+
import org.androidannotations.helper.IdValidatorHelper;
27+
import org.androidannotations.helper.IdValidatorHelper.FallbackStrategy;
28+
import org.androidannotations.model.AnnotationElements;
29+
import org.androidannotations.rclass.IRClass;
30+
import org.androidannotations.rclass.IRClass.Res;
31+
32+
public class CheckedChangeValidator implements ElementValidator {
33+
34+
private IdValidatorHelper validatorHelper;
35+
36+
public CheckedChangeValidator(ProcessingEnvironment processingEnv, IRClass rClass) {
37+
IdAnnotationHelper annotationHelper = new IdAnnotationHelper(processingEnv, getTarget(), rClass);
38+
validatorHelper = new IdValidatorHelper(annotationHelper);
39+
}
40+
41+
@Override
42+
public Class<? extends Annotation> getTarget() {
43+
return CheckedChange.class;
44+
}
45+
46+
@Override
47+
public boolean validate(Element element, AnnotationElements validatedElements) {
48+
49+
IsValid valid = new IsValid();
50+
51+
validatorHelper.enclosingElementHasEnhancedViewSupportAnnotation(element, validatedElements, valid);
52+
53+
validatorHelper.resIdsExist(element, Res.ID, FallbackStrategy.USE_ELEMENT_NAME, valid);
54+
55+
validatorHelper.isNotPrivate(element, valid);
56+
57+
validatorHelper.doesntThrowException(element, valid);
58+
59+
validatorHelper.uniqueId(element, validatedElements, valid);
60+
61+
ExecutableElement executableElement = (ExecutableElement) element;
62+
validatorHelper.returnTypeIsVoid(executableElement, valid);
63+
64+
validatorHelper.param.hasZeroOrOneCompoundButtonOrTwoCompoundButtonBooleanParameters(executableElement, valid);
65+
66+
return valid.isValid();
67+
}
68+
69+
}

‎AndroidAnnotations/functional-test-1-5/AndroidManifest.xml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<activity android:name=".ViewsInjectedActivity_" />
4242
<activity android:name=".ClicksHandledActivity_" />
4343
<activity android:name=".FocusChangeHandledActivity_" />
44+
<activity android:name=".CheckedChangeHandledActivity_" />
4445
<activity android:name=".LongClicksHandledActivity_" />
4546
<activity android:name=".TouchesHandledActivity_" />
4647
<activity android:name=".ItemClicksHandledActivity_" />

0 commit comments

Comments
 (0)