Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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 all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,11 @@
*/
package org.androidannotations.handler;

import static com.sun.codemodel.JExpr.invoke;
import static com.sun.codemodel.JExpr.ref;

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

import org.androidannotations.annotations.res.DrawableRes;
import org.androidannotations.annotations.res.HtmlRes;
import org.androidannotations.helper.AndroidManifest;
import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.helper.IdAnnotationHelper;
import org.androidannotations.helper.IdValidatorHelper;
import org.androidannotations.holder.EComponentHolder;
Expand All @@ -38,12 +32,12 @@
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JFieldRef;

public class ResHandler extends BaseAnnotationHandler<EComponentHolder> {
public abstract class AbstractResHandler extends BaseAnnotationHandler<EComponentHolder> {

private AndroidRes androidRes;
protected AndroidRes androidRes;
private IdAnnotationHelper annotationHelper;

public ResHandler(AndroidRes androidRes, ProcessingEnvironment processingEnvironment) {
public AbstractResHandler(AndroidRes androidRes, ProcessingEnvironment processingEnvironment) {
super(androidRes.getAnnotationClass(), processingEnvironment);
this.androidRes = androidRes;
}
Expand Down Expand Up @@ -77,27 +71,8 @@ public void process(Element element, EComponentHolder holder) {

JBlock methodBody = holder.getInitBody();

TypeMirror fieldTypeMirror = element.asType();
String fieldType = fieldTypeMirror.toString();

// Special case for loading animations
if (CanonicalNameConstants.ANIMATION.equals(fieldType)) {
methodBody.assign(ref(fieldName), classes().ANIMATION_UTILS.staticInvoke("loadAnimation").arg(holder.getContextRef()).arg(idRef));
} else {
String resourceMethodName = androidRes.getResourceMethodName();

// Special case for @HtmlRes
if (element.getAnnotation(HtmlRes.class) != null) {
methodBody.assign(ref(fieldName), classes().HTML.staticInvoke("fromHtml").arg(invoke(holder.getResourcesRef(), resourceMethodName).arg(idRef)));
} else if (element.getAnnotation(DrawableRes.class) != null && hasContextCompatInClasspath()) {
methodBody.assign(ref(fieldName), classes().CONTEXT_COMPAT.staticInvoke("getDrawable").arg(holder.getContextRef()).arg(idRef));
} else {
methodBody.assign(ref(fieldName), invoke(holder.getResourcesRef(), resourceMethodName).arg(idRef));
}
}
}

protected boolean hasContextCompatInClasspath() {
return processingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.CONTEXT_COMPAT) != null;
makeCall(fieldName, holder, methodBody, idRef);
}

protected abstract void makeCall(String fieldName, EComponentHolder holder, JBlock methodBody, JFieldRef idRef);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (C) 2010-2015 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.handler;

import static com.sun.codemodel.JExpr.ref;

import javax.annotation.processing.ProcessingEnvironment;

import org.androidannotations.holder.EComponentHolder;
import org.androidannotations.model.AndroidRes;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JFieldRef;

public class AnimationResHandler extends AbstractResHandler {

public AnimationResHandler(ProcessingEnvironment processingEnvironment) {
super(AndroidRes.ANIMATION, processingEnvironment);
}

@Override
protected void makeCall(String fieldName, EComponentHolder holder, JBlock methodBody, JFieldRef idRef) {
methodBody.assign(ref(fieldName), classes().ANIMATION_UTILS.staticInvoke("loadAnimation").arg(holder.getContextRef()).arg(idRef));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,15 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) {
add(new ItemLongClickHandler(processingEnvironment));
add(new EditorActionHandler(processingEnvironment));
for (AndroidRes androidRes : AndroidRes.values()) {
add(new ResHandler(androidRes, processingEnvironment));
if (androidRes == AndroidRes.ANIMATION) {
add(new AnimationResHandler(processingEnvironment));
} else if (androidRes == AndroidRes.DRAWABLE) {
add(new DrawableResHandler(processingEnvironment));
} else if (androidRes == AndroidRes.HTML) {
add(new HtmlResHandler(processingEnvironment));
} else {
add(new DefaultResHandler(androidRes, processingEnvironment));
}
}
add(new TransactionalHandler(processingEnvironment));
add(new FragmentArgHandler(processingEnvironment));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (C) 2010-2015 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.handler;

import static com.sun.codemodel.JExpr.invoke;
import static com.sun.codemodel.JExpr.ref;

import javax.annotation.processing.ProcessingEnvironment;

import org.androidannotations.holder.EComponentHolder;
import org.androidannotations.model.AndroidRes;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JFieldRef;

public class DefaultResHandler extends AbstractResHandler {

public DefaultResHandler(AndroidRes androidRes, ProcessingEnvironment processingEnvironment) {
super(androidRes, processingEnvironment);
}

@Override
protected void makeCall(String fieldName, EComponentHolder holder, JBlock methodBody, JFieldRef idRef) {
methodBody.assign(ref(fieldName), invoke(holder.getResourcesRef(), androidRes.getResourceMethodName()).arg(idRef));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Copyright (C) 2010-2015 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.AnimationResHandler.java
*/
package org.androidannotations.handler;

import static com.sun.codemodel.JExpr.invoke;
import static com.sun.codemodel.JExpr.ref;

import java.util.List;

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

import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.holder.EComponentHolder;
import org.androidannotations.model.AndroidRes;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JConditional;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JVar;

public class DrawableResHandler extends AbstractResHandler {

private static final int MIN_SDK_WITH_CONTEXT_GET_DRAWABLE = 21;

public DrawableResHandler(ProcessingEnvironment processingEnvironment) {
super(AndroidRes.DRAWABLE, processingEnvironment);
}

@Override
protected void makeCall(String fieldName, EComponentHolder holder, JBlock methodBody, JFieldRef idRef) {
JFieldRef ref = ref(fieldName);
if (hasContextCompatInClasspath()) {
methodBody.assign(ref, classes().CONTEXT_COMPAT.staticInvoke("getDrawable").arg(holder.getContextRef()).arg(idRef));
} else if (shouldUseContextGetDrawableMethod() && !hasContextCompatInClasspath()) {
methodBody.assign(ref, holder.getContextRef().invoke("getDrawable").arg(idRef));
} else if (!shouldUseContextGetDrawableMethod() && hasGetDrawableInContext() && !hasContextCompatInClasspath()) {
createCallWithIfGuard(holder, ref, methodBody, idRef);
} else {
methodBody.assign(ref, invoke(holder.getResourcesRef(), androidRes.getResourceMethodName()).arg(idRef));
}
}

protected boolean hasContextCompatInClasspath() {
return processingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.CONTEXT_COMPAT) != null;
}

protected boolean shouldUseContextGetDrawableMethod() {
return androidManifest.getMinSdkVersion() >= MIN_SDK_WITH_CONTEXT_GET_DRAWABLE;
}

protected boolean hasGetDrawableInContext() {
TypeElement context = processingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.CONTEXT);

return hasGetDrawable(context);
}

private void createCallWithIfGuard(EComponentHolder holder, JFieldRef ref, JBlock methodBody, JFieldRef idRef) {
JVar resourcesRef = holder.getResourcesRef();
JConditional guardIf = methodBody._if(holder.classes().BUILD_VERSION.staticRef("SDK_INT").gte(holder.classes().BUILD_VERSION_CODES.staticRef("LOLLIPOP")));
JBlock ifBlock = guardIf._then();
ifBlock.assign(ref, holder.getContextRef().invoke("getDrawable").arg(idRef));

JBlock elseBlock = guardIf._else();
elseBlock.assign(ref, resourcesRef.invoke("getDrawable").arg(idRef));
}

private boolean hasGetDrawable(TypeElement type) {
if (type == null) {
return false;
}

List<? extends Element> allMembers = processingEnvironment().getElementUtils().getAllMembers(type);
for (ExecutableElement element : ElementFilter.methodsIn(allMembers)) {
if (element.getSimpleName().contentEquals("getDrawable")) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (C) 2010-2015 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.handler;

import static com.sun.codemodel.JExpr.ref;

import javax.annotation.processing.ProcessingEnvironment;

import org.androidannotations.holder.EComponentHolder;
import org.androidannotations.model.AndroidRes;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JFieldRef;

public class HtmlResHandler extends AbstractResHandler {

public HtmlResHandler(ProcessingEnvironment processingEnvironment) {
super(AndroidRes.HTML, processingEnvironment);
}

@Override
protected void makeCall(String fieldName, EComponentHolder holder, JBlock methodBody, JFieldRef idRef) {
methodBody.assign(ref(fieldName), classes().HTML.staticInvoke("fromHtml").arg(holder.getResourcesRef().invoke(AndroidRes.HTML.getResourceMethodName()).arg(idRef)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (C) 2010-2015 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.generation;

import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.res.DrawableRes;

import android.app.Activity;
import android.graphics.drawable.Drawable;

@EActivity
public class ActivityWithGetDrawableMethod extends Activity {

@DrawableRes(R.drawable.myDrawable)
Drawable myDrawable;

// http://developer.android.com/reference/android/content/Context.html#getDrawable(int)
// This method was added in API 21 and should be used to get a Drawable which is styled/adjusted for the current theme.
public Drawable getDrawable(int drawableId) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe we should add a comment to clarify the origin of this method.

return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,24 @@ public class ContextCompatDrawableTest extends AAProcessorTestHelper {

private static final String DRAWABLE_SIGNATURE = ".*myDrawable = resources_\\.getDrawable\\(drawable\\.myDrawable\\);.*";
private static final String DRAWABLE_VIA_SUPPORT_SIGNATURE = ".*myDrawable = ContextCompat\\.getDrawable\\(this, drawable\\.myDrawable\\);.*";
private static final String DRAWABLE_VIA_CONTEXT_ON_LOLLIPOP = ".*myDrawable = this\\.getDrawable\\(drawable\\.myDrawable\\);.*";
private static final String[] DRAWABLE_CONDITIONAL_WITHOUT_CONTEXT_COMPAT = new String[] {
" if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {",
" myDrawable = this.getDrawable(drawable.myDrawable);",
" } else {",
" myDrawable = resources_.getDrawable(drawable.myDrawable);",
" }",
};

@Before
public void setUp() {
addProcessor(AndroidAnnotationProcessor.class);
addManifestProcessorParameter(ContextCompatDrawableTest.class, "AndroidManifestForDrawable.xml");
}

@Test
public void activityCompilesWithRegularDrawable() {
addManifestProcessorParameter(ContextCompatDrawableTest.class, "AndroidManifestForDrawable.xml");

CompileResult result = compileFiles(ActivityWithDrawable.class);
File generatedFile = toGeneratedFile(ActivityWithDrawable.class);

Expand All @@ -47,10 +56,36 @@ public void activityCompilesWithContextCompatDrawable() {
// To simulate android support v4 in classpath, we add
// android.support.v4.content.ContextCompat
// in classpath
addManifestProcessorParameter(ContextCompatDrawableTest.class, "AndroidManifestForDrawable.xml");
CompileResult result = compileFiles(toPath(ContextCompatDrawableTest.class, "ContextCompat.java"), ActivityWithDrawable.class);
File generatedFile = toGeneratedFile(ActivityWithDrawable.class);

assertCompilationSuccessful(result);
assertGeneratedClassMatches(generatedFile, DRAWABLE_VIA_SUPPORT_SIGNATURE);
}

@Test
public void activityCompilesOnMinSdk21WithoutContextCompat() throws Exception {
addManifestProcessorParameter(ContextCompatDrawableTest.class, "AndroidManifestForDrawableMinSdk21.xml");

CompileResult result = compileFiles(ActivityWithGetDrawableMethod.class);
File generatedFile = toGeneratedFile(ActivityWithGetDrawableMethod.class);

assertCompilationSuccessful(result);
assertGeneratedClassMatches(generatedFile, DRAWABLE_VIA_CONTEXT_ON_LOLLIPOP);
}

@Test
public void activityCompilesOnMinSdkLower21CompileSdkHigher21WithoutContextCompat() throws Exception {
addManifestProcessorParameter(ContextCompatDrawableTest.class, "AndroidManifestForDrawableMinSdk20.xml");

CompileResult result = compileFiles(toPath(ContextCompatDrawableTest.class, "Context.java"),
toPath(ContextCompatDrawableTest.class, "Build.java"),
ActivityWithGetDrawableMethod.class);
File generatedFile = toGeneratedFile(ActivityWithGetDrawableMethod.class);

assertCompilationSuccessful(result);
assertGeneratedClassContains(generatedFile, DRAWABLE_CONDITIONAL_WITHOUT_CONTEXT_COMPAT);
}

}
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.