Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add @CheckedChange #389
  • Loading branch information
naixx committed Jan 18, 2013
commit 85a5434017ceba7ddac52b2772a3892fcafacf58
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.androidannotations.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
*
* @author Rostislav Chekan
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface CheckedChange {
int[] value() default ResId.DEFAULT_VALUE;

String[] resName() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.BeforeTextChange;
import org.androidannotations.annotations.CheckedChange;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.EApplication;
Expand Down Expand Up @@ -125,6 +126,7 @@
import org.androidannotations.processing.BackgroundProcessor;
import org.androidannotations.processing.BeanProcessor;
import org.androidannotations.processing.BeforeTextChangeProcessor;
import org.androidannotations.processing.CheckedChangeProcessor;
import org.androidannotations.processing.ClickProcessor;
import org.androidannotations.processing.EActivityProcessor;
import org.androidannotations.processing.EApplicationProcessor;
Expand Down Expand Up @@ -190,6 +192,7 @@
import org.androidannotations.validation.AppValidator;
import org.androidannotations.validation.BeanValidator;
import org.androidannotations.validation.BeforeTextChangeValidator;
import org.androidannotations.validation.CheckedChangeValidator;
import org.androidannotations.validation.ClickValidator;
import org.androidannotations.validation.EActivityValidator;
import org.androidannotations.validation.EApplicationValidator;
Expand Down Expand Up @@ -258,6 +261,7 @@
ItemLongClick.class, //
Touch.class, //
FocusChange.class, //
CheckedChange.class, //
ItemSelect.class, //
UiThread.class, //
Transactional.class, //
Expand Down Expand Up @@ -454,6 +458,7 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices
modelValidator.register(new LongClickValidator(processingEnv, rClass));
modelValidator.register(new TouchValidator(processingEnv, rClass));
modelValidator.register(new FocusChangeValidator(processingEnv, rClass));
modelValidator.register(new CheckedChangeValidator(processingEnv, rClass));
modelValidator.register(new ItemClickValidator(processingEnv, rClass));
modelValidator.register(new ItemSelectedValidator(processingEnv, rClass));
modelValidator.register(new ItemLongClickValidator(processingEnv, rClass));
Expand Down Expand Up @@ -545,6 +550,7 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
modelProcessor.register(new LongClickProcessor(processingEnv, rClass));
modelProcessor.register(new TouchProcessor(processingEnv, rClass));
modelProcessor.register(new FocusChangeProcessor(processingEnv, rClass));
modelProcessor.register(new CheckedChangeProcessor(processingEnv, rClass));
modelProcessor.register(new ItemClickProcessor(processingEnv, rClass));
modelProcessor.register(new ItemSelectedProcessor(processingEnv, rClass));
modelProcessor.register(new ItemLongClickProcessor(processingEnv, rClass));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class CanonicalNameConstants {
public static final String SEEKBAR = "android.widget.SeekBar";
public static final String ON_SEEKBAR_CHANGE_LISTENER = "android.widget.SeekBar.OnSeekBarChangeListener";
public static final String TEXT_VIEW = "android.widget.TextView";
public static final String COMPOUND_BUTTON = "android.widget.CompoundButton";
public static final String VIEW = "android.view.View";
public static final String VIEW_ON_CLICK_LISTENER = "android.view.View.OnClickListener";
public static final String VIEW_ON_TOUCH_LISTENER = "android.view.View.OnTouchListener";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,32 @@ public void hasZeroOrOneViewOrTwoViewBooleanParameters(ExecutableElement executa
}
}

public void hasZeroOrOneCompoundButtonOrTwoCompoundButtonBooleanParameters(ExecutableElement executableElement, IsValid valid) {
List<? extends VariableElement> parameters = executableElement.getParameters();

if (parameters.size() == 0) {
return;
} else if (parameters.size() > 2) {
valid.invalidate();
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());
} else {
VariableElement firstParameter = parameters.get(0);
String firstParameterType = firstParameter.asType().toString();
if (!firstParameterType.equals(CanonicalNameConstants.COMPOUND_BUTTON)) {
valid.invalidate();
annotationHelper.printAnnotationError(executableElement, "the first parameter must be a " + CanonicalNameConstants.COMPOUND_BUTTON + ", not a " + firstParameterType);
}
if (parameters.size() == 2) {
VariableElement secondParameter = parameters.get(1);
String secondParameterType = secondParameter.asType().toString();
if (!secondParameterType.equals(CanonicalNameConstants.BOOLEAN) && !secondParameterType.equals("boolean")) {
valid.invalidate();
annotationHelper.printAnnotationError(executableElement, "the second parameter must be a " + CanonicalNameConstants.BOOLEAN + " or boolean, not a " + secondParameterType);
}
}
}
}

public void hasOneMotionEventOrTwoMotionEventViewParameters(ExecutableElement executableElement, IsValid valid) {
List<? extends VariableElement> parameters = executableElement.getParameters();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,17 @@ public abstract class AbstractListenerProcessor implements DecoratingElementProc
private IdAnnotationHelper helper;
protected Classes classes;
protected JCodeModel codeModel;
protected EBeanHolder holder;

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

@Override
public void process(Element element, JCodeModel jcodeModel, EBeanHolder holder) {
public void process(Element element, JCodeModel codeModel, EBeanHolder holder) {
classes = holder.classes();
codeModel = jcodeModel;
this.codeModel = codeModel;
this.holder = holder;

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

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

JVar view = block.decl(classes.VIEW, "view", findViewById.arg(idRef));
block._if(view.ne(_null()))._then().invoke(view, getSetterName()).arg(_new(listenerAnonymousClass));
block._if(view.ne(_null()))._then().invoke(castWidget(view), getSetterName()).arg(_new(listenerAnonymousClass));
}
}

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

protected abstract JClass getListenerClass();

protected JExpression castWidget(JVar view) {
return view;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.androidannotations.processing;

import java.lang.annotation.Annotation;
import java.util.List;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

import org.androidannotations.annotations.CheckedChange;
import org.androidannotations.rclass.IRClass;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JVar;

/**
*
* @author Rostislav Chekan
*
*/
public class CheckedChangeProcessor extends AbstractListenerProcessor {

public CheckedChangeProcessor(ProcessingEnvironment processingEnv, IRClass rClass) {
super(processingEnv, rClass);
}

@Override
public Class<? extends Annotation> getTarget() {
return CheckedChange.class;
}

@Override
protected void makeCall(JBlock listenerMethodBody, JInvocation call, TypeMirror returnType) {
listenerMethodBody.add(call);
}

@Override
protected void processParameters(JMethod listenerMethod, JInvocation call, List<? extends VariableElement> parameters) {
JVar btnParam = listenerMethod.param(classes.COMPOUND_BUTTON, "buttonView");
JVar isCheckedParam = listenerMethod.param(codeModel.BOOLEAN, "isChecked");
boolean isCheckedParamExists = parameters.size() == 2;
boolean btnParamExists = parameters.size() >= 1;

if (btnParamExists) {
call.arg(btnParam);
}
if (isCheckedParamExists) {
call.arg(isCheckedParam);
}
}

@Override
protected JMethod createListenerMethod(JDefinedClass listenerAnonymousClass) {
return listenerAnonymousClass.method(JMod.PUBLIC, codeModel.VOID, "onCheckedChanged");
}

@Override
protected String getSetterName() {
return "setOnCheckedChangeListener";
}

@Override
protected JClass getListenerClass() {
return holder.refClass("android.widget.CompoundButton.OnCheckedChangeListener");
}

@Override
protected JExpression castWidget(JVar view) {
return JExpr.cast(classes.COMPOUND_BUTTON, view);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class Classes {
public final JClass SEEKBAR = refClass(CanonicalNameConstants.SEEKBAR);
public final JClass ON_SEEKBAR_CHANGE_LISTENER = refClass(CanonicalNameConstants.ON_SEEKBAR_CHANGE_LISTENER);
public final JClass TEXT_VIEW = refClass(CanonicalNameConstants.TEXT_VIEW);
public final JClass COMPOUND_BUTTON = refClass(CanonicalNameConstants.COMPOUND_BUTTON);
public final JClass VIEW = refClass(CanonicalNameConstants.VIEW);
public final JClass VIEW_ON_CLICK_LISTENER = refClass(CanonicalNameConstants.VIEW_ON_CLICK_LISTENER);
public final JClass VIEW_ON_TOUCH_LISTENER = refClass(CanonicalNameConstants.VIEW_ON_TOUCH_LISTENER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
import com.sun.codemodel.JMod;
import com.sun.codemodel.JVar;

/**
*
* @author Rostislav Chekan
*
*/
public class FocusChangeProcessor extends AbstractListenerProcessor {

public FocusChangeProcessor(ProcessingEnvironment processingEnv, IRClass rClass) {
Expand Down Expand Up @@ -63,5 +68,4 @@ protected String getSetterName() {
protected JClass getListenerClass() {
return classes.VIEW_ON_FOCUS_CHANGE_LISTENER;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.validation;

import java.lang.annotation.Annotation;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;

import org.androidannotations.annotations.CheckedChange;
import org.androidannotations.helper.IdAnnotationHelper;
import org.androidannotations.helper.IdValidatorHelper;
import org.androidannotations.helper.IdValidatorHelper.FallbackStrategy;
import org.androidannotations.model.AnnotationElements;
import org.androidannotations.rclass.IRClass;
import org.androidannotations.rclass.IRClass.Res;

public class CheckedChangeValidator implements ElementValidator {

private IdValidatorHelper validatorHelper;

public CheckedChangeValidator(ProcessingEnvironment processingEnv, IRClass rClass) {
IdAnnotationHelper annotationHelper = new IdAnnotationHelper(processingEnv, getTarget(), rClass);
validatorHelper = new IdValidatorHelper(annotationHelper);
}

@Override
public Class<? extends Annotation> getTarget() {
return CheckedChange.class;
}

@Override
public boolean validate(Element element, AnnotationElements validatedElements) {

IsValid valid = new IsValid();

validatorHelper.enclosingElementHasEnhancedViewSupportAnnotation(element, validatedElements, valid);

validatorHelper.resIdsExist(element, Res.ID, FallbackStrategy.USE_ELEMENT_NAME, valid);

validatorHelper.isNotPrivate(element, valid);

validatorHelper.doesntThrowException(element, valid);

validatorHelper.uniqueId(element, validatedElements, valid);

ExecutableElement executableElement = (ExecutableElement) element;
validatorHelper.returnTypeIsVoid(executableElement, valid);

validatorHelper.param.hasZeroOrOneCompoundButtonOrTwoCompoundButtonBooleanParameters(executableElement, valid);

return valid.isValid();
}

}
1 change: 1 addition & 0 deletions AndroidAnnotations/functional-test-1-5/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<activity android:name=".ViewsInjectedActivity_" />
<activity android:name=".ClicksHandledActivity_" />
<activity android:name=".FocusChangeHandledActivity_" />
<activity android:name=".CheckedChangeHandledActivity_" />
<activity android:name=".LongClicksHandledActivity_" />
<activity android:name=".TouchesHandledActivity_" />
<activity android:name=".ItemClicksHandledActivity_" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (C) 2010-2012 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.androidannotations.test15;

import org.androidannotations.annotations.CheckedChange;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.FocusChange;

import android.view.View;
import android.widget.CompoundButton;

@EActivity(R.layout.clickable_widgets)
public class CheckedChangeHandledActivity extends EventsHandledAbstractActivity {

@CheckedChange
public void conventionButton(CompoundButton evt, boolean hasFocus) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you test that this method is called when the checked state is changed (CompundButton.setChecked(boolean)) ?
You could checkout ClicksHandledActivity from the functional-test-1-5 module and ClicksHandledActivityTest from the functional-test-1-5-tests module as example.

}

@CheckedChange
public void snakeCaseButton() {

}

@CheckedChange
public void extendedConventionButton(CompoundButton evt) {

}

@CheckedChange(R.id.configurationOverConventionButton)
public void overridenConventionButton() {

}

@CheckedChange
public void buttonWithViewArgument() {

}

@CheckedChange({ R.id.button1, R.id.button2 })
public void multipleButtonWithViewArgument(CompoundButton v, boolean hasFocus) {

}

}
Loading