diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrollStateChanged.java b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrollStateChanged.java new file mode 100644 index 0000000000..f1100cb149 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrollStateChanged.java @@ -0,0 +1,92 @@ +/** + * 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * This annotation is intended to be used on methods to receive events defined + * by + * android.support.v4.view.ViewPager.OnPageChangeListener.onPageScrollStateChanged + * when the scroll state changes. + *

+ *

+ * The annotation value should be one or several R.id.* fields that refers to + * ViewPager or subclasses of ViewPager. If not set, the method name will be + * used as the R.id.* field name. + *

+ *

+ * The method MAY have multiple parameter : + *

+ * + * + *
+ * + * Examples : + * + *
+ * @PageScrollStateChanged(R.id.viewpager)
+ * void onPageScrollStateChanged(ViewPager view, int state) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrollStateChanged
+ * void viewPager(ViewPager view) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrollStateChanged({R.id.viewpager, R.id.viewpager2})
+ * void onPageScrollStateChangedOnMultipleViewPager(ViewPager v, int anything) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrollStateChanged(R.id.viewpager)
+ * void onPageScrollStateChangedNoParam() {
+ * 	// Something Here
+ * }
+ * 
+ * + *
+ * + * @see PageScrolled + * @see PageSelected + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.METHOD) +public @interface PageScrollStateChanged { + + /** + * The R.id.* fields which refer to the ViewPager. + * + * @return the ids of the ViewPager. + */ + int[] value() default ResId.DEFAULT_VALUE; + + /** + * The resource names as a strings which refer to the ViewPagers. + * + * @return the resource names of the ViewPagers. + */ + String[] resName() default ""; + +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrolled.java b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrolled.java new file mode 100644 index 0000000000..b8702f7ab8 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageScrolled.java @@ -0,0 +1,99 @@ +/** + * 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * This annotation is intended to be used on methods to receive events defined + * by + * android.support.v4.view.ViewPager.OnPageChangeListener.OnPageScrolled + * when the current page is scrolled, either as part of a programmatically + * initiated smooth scroll or a user initiated touch scroll. + *

+ *

+ * The annotation value should be one or several R.id.* fields that refers to + * ViewPager or subclasses of ViewPager. If not set, the method name will be + * used as the R.id.* field name. + *

+ *

+ * The method MAY have multiple parameters, but the order must be following : + *

+ * + * + *
+ * + * Examples : + * + *
+ * @PageScrolled(R.id.viewpager)
+ * void onPageScrolled(ViewPager view, int position, float positionOffset, int positionOffsetPixels) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrolled
+ * void viewPager(ViewPager view) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrolled({R.id.viewpager, R.id.viewpager2})
+ * void onPageScrolledOnMultipleViewPager(ViewPager v, int position) {
+ * 	// Something Here
+ * }
+ *
+ * @PageScrolled(R.id.viewpager)
+ * void onPageScrolledNoParam() {
+ * 	// Something Here
+ * }
+ * 
+ * + *
+ * + * @see PageScrollStateChanged + * @see PageSelected + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.METHOD) +public @interface PageScrolled { + + /** + * The R.id.* fields which refer to the ViewPager. + * + * @return the ids of the ViewPager. + */ + int[] value() default ResId.DEFAULT_VALUE; + + /** + * The resource names as a strings which refer to the ViewPagers. + * + * @return the resource names of the ViewPagers. + */ + String[] resName() default ""; + +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageSelected.java b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageSelected.java new file mode 100644 index 0000000000..e9e0e07472 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/PageSelected.java @@ -0,0 +1,92 @@ +/** + * 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * This annotation is intended to be used on methods to receive events defined + * by + * android.support.v4.view.ViewPager.OnPageChangeListener.onPageSelected + * when a new page becomes selected. Animation is not necessarily complete. + *

+ *

+ * The annotation value should be one or several R.id.* fields that refers to + * ViewPager or subclasses of ViewPager. If not set, the method name will be + * used as the R.id.* field name. + *

+ *

+ * The method MAY have multiple parameter : + *

+ * + * + *
+ * + * Examples : + * + *
+ * @PageSelected(R.id.viewpager)
+ * void onPageSelected(ViewPager view, int state) {
+ * 	// Something Here
+ * }
+ *
+ * @PageSelected
+ * void viewPager(ViewPager view) {
+ * 	// Something Here
+ * }
+ *
+ * @PageSelected({R.id.viewpager, R.id.viewpager2})
+ * void onPageSelectedOnMultipleViewPager(ViewPager v, int anything) {
+ * 	// Something Here
+ * }
+ *
+ * @PageSelected(R.id.viewpager)
+ * void onPageSelectedNoParam() {
+ * 	// Something Here
+ * }
+ * 
+ * + *
+ * + * @see PageScrolled + * @see PageScrollStateChanged + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.METHOD) +public @interface PageSelected { + + /** + * The R.id.* fields which refer to the ViewPager. + * + * @return the ids of the ViewPager. + */ + int[] value() default ResId.DEFAULT_VALUE; + + /** + * The resource names as a strings which refer to the ViewPagers. + * + * @return the resource names of the ViewPagers. + */ + String[] resName() default ""; + +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/java/org/androidannotations/test/PageChangeListenerActivity.java b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/java/org/androidannotations/test/PageChangeListenerActivity.java new file mode 100644 index 0000000000..6fe355e4a6 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/java/org/androidannotations/test/PageChangeListenerActivity.java @@ -0,0 +1,91 @@ +/** + * 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.test; + +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.PageScrollStateChanged; +import org.androidannotations.annotations.PageScrolled; +import org.androidannotations.annotations.PageSelected; + +import android.app.Activity; +import android.support.v4.view.ViewPager; + +@EActivity(R.layout.viewpagers) +public class PageChangeListenerActivity extends Activity { + + public ViewPager viewPager = null; + public int position = 0; + public float positionOffset = 0f; + public int positionOffsetPixels = 0; + + public int state = 0; + + @PageScrolled(R.id.viewPager1) + public void pageScrolled(ViewPager v, int p, float pOffset, int pOffsetPixels) { + viewPager = v; + position = p; + positionOffset = pOffset; + positionOffsetPixels = pOffsetPixels; + } + + @PageScrollStateChanged(R.id.viewPager1) + public void pageScrollStateChanged(ViewPager v, int s) { + viewPager = v; + state = s; + } + + @PageSelected(R.id.viewPager1) + public void pageSelected(ViewPager v, int p) { + viewPager = v; + position = p; + } + + @PageSelected(R.id.viewPager2) + public void pageSelected2() { + } + + @PageScrolled(R.id.viewPager2) + public void pageScrolled2() { + } + + @PageScrollStateChanged(R.id.viewPager2) + public void pageScrollStateChanged2() { + } + + @PageScrollStateChanged(R.id.viewPager3) + public void pageScrollStateChanged3(int s, ViewPager v) { + viewPager = v; + state = s; + } + + @PageSelected(R.id.viewPager3) + public void pageSelected3(int p, ViewPager v) { + viewPager = v; + position = p; + } + + @PageScrolled(R.id.viewPager3) + public void pageScrolled3(int p) { + position = p; + } + + @PageScrolled(R.id.viewPager4) + public void pageScrolled4(float f, int p) { + positionOffset = f; + positionOffsetPixels = p; + } + +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/res/layout/viewpagers.xml b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/res/layout/viewpagers.xml new file mode 100644 index 0000000000..355721de21 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/res/layout/viewpagers.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidAnnotations/androidannotations-core/androidannotations-test/src/test/java/org/androidannotations/test/PageChangeListenerActivityTest.java b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/test/java/org/androidannotations/test/PageChangeListenerActivityTest.java new file mode 100644 index 0000000000..3a01bf3c0e --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations-test/src/test/java/org/androidannotations/test/PageChangeListenerActivityTest.java @@ -0,0 +1,210 @@ +/** + * 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.test; + +import static org.fest.assertions.api.Assertions.assertThat; +import static org.fest.reflect.core.Reflection.field; +import static org.robolectric.Robolectric.setupActivity; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import android.support.v4.view.ViewPager; + +@RunWith(RobolectricTestRunner.class) +public class PageChangeListenerActivityTest { + private PageChangeListenerActivity_ activity; + private ViewPager viewPager; + private ViewPager.OnPageChangeListener listener; + + @Before + public void setUp() { + activity = setupActivity(PageChangeListenerActivity_.class); + } + + private void initViewPager(int viewPagerId) { + viewPager = (ViewPager) activity.findViewById(viewPagerId); + listener = field("mOnPageChangeListener").ofType(ViewPager.OnPageChangeListener.class).in(viewPager).get(); + } + + private void assertReadyForTest() { + assertViewPagerIsNull(); + assertPositionIsNotSet(); + assertPositionOffsetIsNotSet(); + assertPositionOffsetPixelsIsNotSet(); + assertStateIsNotSet(); + } + + private void assertViewPagerIsNull() { + assertThat(activity.viewPager).isNull(); + } + + private void assertPositionIsNotSet() { + assertThat(activity.position).isEqualTo(0); + } + + private void assertPositionOffsetPixelsIsNotSet() { + assertThat(activity.positionOffsetPixels).isEqualTo(0); + } + + private void assertPositionOffsetIsNotSet() { + assertThat(activity.positionOffset).isEqualTo(0f); + } + + private void assertStateIsNotSet() { + assertThat(activity.state).isEqualTo(0); + } + + @Test + public void handlePageSelected() { + initViewPager(R.id.viewPager1); + + assertViewPagerIsNull(); + assertPositionIsNotSet(); + + int position = 100; + + listener.onPageSelected(position); + + assertThat(activity.viewPager).isEqualTo(viewPager); + assertThat(activity.position).isEqualTo(position); + } + + @Test + public void handlePageScrolled() { + initViewPager(R.id.viewPager1); + assertReadyForTest(); + + int position = 101; + float positionOffset = 102f; + int positionOffsetPixels = 103; + + listener.onPageScrolled(position, positionOffset, positionOffsetPixels); + + assertThat(activity.viewPager).isEqualTo(viewPager); + assertThat(activity.position).isEqualTo(position); + assertThat(activity.positionOffset).isEqualTo(positionOffset); + assertThat(activity.positionOffsetPixels).isEqualTo(positionOffsetPixels); + } + + @Test + public void handlePageScrollStateChanged() { + initViewPager(R.id.viewPager1); + assertReadyForTest(); + + int state = 104; + + listener.onPageScrollStateChanged(state); + + assertThat(activity.viewPager).isEqualTo(viewPager); + assertThat(activity.state).isEqualTo(state); + } + + @Test + public void handleNoPageSelectedParameter() { + initViewPager(R.id.viewPager2); + assertReadyForTest(); + + listener.onPageSelected(1); + + assertViewPagerIsNull(); + assertPositionIsNotSet(); + } + + @Test + public void handleNoPageScrolledParameter() { + initViewPager(R.id.viewPager2); + assertReadyForTest(); + + listener.onPageScrolled(1, 1f, 2); + + assertViewPagerIsNull(); + assertPositionIsNotSet(); + assertPositionOffsetIsNotSet(); + assertPositionOffsetPixelsIsNotSet(); + } + + @Test + public void handleNoPageScrollStateChangedParameter() { + initViewPager(R.id.viewPager2); + assertReadyForTest(); + + listener.onPageScrollStateChanged(1); + + assertViewPagerIsNull(); + assertStateIsNotSet(); + } + + @Test + public void handleAnyOrderPageSelectedParameter() { + initViewPager(R.id.viewPager3); + assertReadyForTest(); + + int position = 105; + + listener.onPageSelected(position); + + assertThat(activity.viewPager).isEqualTo(viewPager); + assertThat(activity.position).isEqualTo(position); + } + + @Test + public void handleAnyOrderPageScrollStateChangedParameter() { + initViewPager(R.id.viewPager3); + assertReadyForTest(); + + int state = 106; + + listener.onPageScrollStateChanged(state); + + assertThat(activity.viewPager).isEqualTo(viewPager); + assertThat(activity.state).isEqualTo(state); + } + + @Test + public void handlePageScrollFirstIntBecomesPositionParameter() { + initViewPager(R.id.viewPager3); + assertReadyForTest(); + + int position = 107; + + listener.onPageScrolled(position, 108f, 109); + + assertViewPagerIsNull(); + assertThat(activity.position).isEqualTo(position); + assertPositionOffsetIsNotSet(); + assertPositionOffsetPixelsIsNotSet(); + } + + @Test + public void handleIntAfterPositionOffsetBecomesPositionOffsetPixels() { + initViewPager(R.id.viewPager4); + assertReadyForTest(); + + float positionOffset = 111f; + int positionOffsetPixels = 112; + + listener.onPageScrolled(110, positionOffset, positionOffsetPixels); + + assertViewPagerIsNull(); + assertPositionIsNotSet(); + assertThat(activity.positionOffset).isEqualTo(positionOffset); + assertThat(activity.positionOffsetPixels).isEqualTo(positionOffsetPixels); + } + +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/handler/BaseAnnotationHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/handler/BaseAnnotationHandler.java index 3065b4b1af..aa5ef94d63 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/handler/BaseAnnotationHandler.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/handler/BaseAnnotationHandler.java @@ -15,8 +15,13 @@ */ package org.androidannotations.handler; +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.AndroidAnnotationsEnvironment; import org.androidannotations.ElementValidation; @@ -32,11 +37,10 @@ public abstract class BaseAnnotationHandler implements AnnotationHandler { private final String target; - private AndroidAnnotationsEnvironment environment; - protected IdAnnotationHelper annotationHelper; protected IdValidatorHelper validatorHelper; protected APTCodeModelHelper codeModelHelper; + private AndroidAnnotationsEnvironment environment; public BaseAnnotationHandler(Class targetClass, AndroidAnnotationsEnvironment environment) { this(targetClass.getCanonicalName(), environment); @@ -87,4 +91,18 @@ protected AbstractJClass getJClass(String fullyQualifiedClassName) { protected AbstractJClass getJClass(Class clazz) { return environment.getJClass(clazz); } + + protected boolean hasTargetMethod(TypeElement type, String methodName) { + if (type == null) { + return false; + } + + List allMembers = getProcessingEnvironment().getElementUtils().getAllMembers(type); + for (ExecutableElement element : ElementFilter.methodsIn(allMembers)) { + if (element.getSimpleName().contentEquals(methodName)) { + return true; + } + } + return false; + } } diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java index 01ae520016..41d9aad601 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/CanonicalNameConstants.java @@ -137,6 +137,8 @@ public final class CanonicalNameConstants { public static final String APP_WIDGET_MANAGER = "android.appwidget.AppWidgetManager"; public static final String ACTIONBAR_ACTIVITY = "android.support.v7.app.ActionBarActivity"; public static final String APPCOMPAT_ACTIVITY = "android.support.v7.app.AppCompatActivity"; + public static final String VIEW_PAGER = "android.support.v4.view.ViewPager"; + public static final String PAGE_CHANGE_LISTENER = "android.support.v4.view.ViewPager.OnPageChangeListener"; /* * Android permission diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java index efd5dcfd7f..fdaf98bb40 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/helper/ValidatorHelper.java @@ -671,11 +671,19 @@ public void enclosingElementExtendsPreferenceActivityOrPreferenceFragment(Elemen extendsOneOfTypes(element.getEnclosingElement(), VALID_PREFERENCE_CLASSES, valid); } - public void isPreferenceFragmentClassPresent(Element element, ElementValidation valid) { - TypeElement preferenceFragmentElement = annotationHelper.getElementUtils().getTypeElement(CanonicalNameConstants.PREFERENCE_FRAGMENT); + public boolean isClassPresent(String className) { + return annotationHelper.getElementUtils().getTypeElement(className) != null; + } - if (preferenceFragmentElement == null) { + public void isPreferenceFragmentClassPresent(Element element, ElementValidation valid) { + if (!isClassPresent(CanonicalNameConstants.PREFERENCE_FRAGMENT)) { valid.addError("The class " + CanonicalNameConstants.PREFERENCE_FRAGMENT + " cannot be found. You have to use at least API 11"); } } + + public void isViewPagerClassPresent(ElementValidation validation) { + if (!isClassPresent(CanonicalNameConstants.VIEW_PAGER)) { + validation.addError("The class " + CanonicalNameConstants.VIEW_PAGER + " cannot be found. You have to include support v4 library"); + } + } } diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java index fa8a26acf8..9f6b8caf98 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java @@ -63,6 +63,7 @@ public abstract class EComponentWithViewSupportHolder extends EComponentHolder i protected JMethod findSupportFragmentByTag; private Map textWatcherHolders = new HashMap<>(); private Map onSeekBarChangeListenerHolders = new HashMap<>(); + private Map pageChangeHolders = new HashMap<>(); private KeyEventCallbackMethodsDelegate keyEventCallbackMethodsDelegate; public EComponentWithViewSupportHolder(AndroidAnnotationsEnvironment environment, TypeElement annotatedElement) throws Exception { @@ -302,6 +303,33 @@ private OnSeekBarChangeListenerHolder createOnSeekBarChangeListenerHolder(JField return new OnSeekBarChangeListenerHolder(this, onSeekbarChangeListenerClass); } + public PageChangeHolder getPageChangeHolder(JFieldRef idRef, TypeMirror viewParameterType, boolean hasAddOnPageChangeListenerMethod) { + String idRefString = idRef.name(); + PageChangeHolder pageChangeHolder = pageChangeHolders.get(idRefString); + if (pageChangeHolder == null) { + pageChangeHolder = createPageChangeHolder(idRef, viewParameterType, hasAddOnPageChangeListenerMethod); + pageChangeHolders.put(idRefString, pageChangeHolder); + } + return pageChangeHolder; + } + + private PageChangeHolder createPageChangeHolder(JFieldRef idRef, TypeMirror viewParameterType, boolean hasAddOnPageChangeListenerMethod) { + JDefinedClass onPageChangeListenerClass = getCodeModel().anonymousClass(getClasses().PAGE_CHANGE_LISTENER); + AbstractJClass viewClass = getClasses().VIEW_PAGER; + if (viewParameterType != null) { + viewClass = getJClass(viewParameterType.toString()); + } + JBlock onViewChangedBody = getOnViewChangedBodyInjectionBlock().blockSimple(); + JVar viewVariable = onViewChangedBody.decl(FINAL, viewClass, "view", cast(viewClass, findViewById(idRef))); + JBlock block = onViewChangedBody._if(viewVariable.ne(JExpr._null()))._then(); + if (hasAddOnPageChangeListenerMethod) { + block.invoke(viewVariable, "addOnPageChangeListener").arg(_new(onPageChangeListenerClass)); + } else { + block.invoke(viewVariable, "setOnPageChangeListener").arg(_new(onPageChangeListenerClass)); + } + return new PageChangeHolder(this, viewVariable, onPageChangeListenerClass); + } + @Override public JSwitch getOnKeyDownSwitchBody() { return keyEventCallbackMethodsDelegate.getOnKeyDownSwitchBody(); diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/PageChangeHolder.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/PageChangeHolder.java new file mode 100644 index 0000000000..95a25cce88 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/PageChangeHolder.java @@ -0,0 +1,113 @@ +/** + * 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.holder; + +import com.helger.jcodemodel.JBlock; +import com.helger.jcodemodel.JDefinedClass; +import com.helger.jcodemodel.JMethod; +import com.helger.jcodemodel.JMod; +import com.helger.jcodemodel.JPrimitiveType; +import com.helger.jcodemodel.JVar; + +public class PageChangeHolder { + + private EComponentWithViewSupportHolder holder; + private JVar viewPagerVariable; + private JDefinedClass listenerClass; + private JBlock pageScrollStateChangedBody; + private JVar pageScrollStateChangedStateParam; + private JBlock pageScrolledBody; + private JVar pageScrolledPositionParam; + private JVar pageScrolledPositionOffsetParam; + private JVar pageScrolledPositionOffsetPixelsParam; + private JBlock pageSelectedBody; + private JVar pageSelectedPositionParam; + + public PageChangeHolder(EComponentWithViewSupportHolder holder, JVar viewPagerVariable, JDefinedClass onPageChangeListenerClass) { + this.holder = holder; + this.viewPagerVariable = viewPagerVariable; + listenerClass = onPageChangeListenerClass; + createPageScrollStateChanged(); + createPageScroll(); + createPageSelected(); + } + + private void createPageScrollStateChanged() { + JMethod method = listenerClass.method(JMod.PUBLIC, holder.getCodeModel().VOID, "onPageScrollStateChanged"); + method.annotate(Override.class); + pageScrollStateChangedBody = method.body(); + JPrimitiveType intClass = holder.getCodeModel().INT; + pageScrollStateChangedStateParam = method.param(intClass, "state"); + } + + private void createPageScroll() { + JMethod method = listenerClass.method(JMod.PUBLIC, holder.getCodeModel().VOID, "onPageScrolled"); + method.annotate(Override.class); + pageScrolledBody = method.body(); + JPrimitiveType intClass = holder.getCodeModel().INT; + pageScrolledPositionParam = method.param(intClass, "position"); + pageScrolledPositionOffsetParam = method.param(holder.getCodeModel().FLOAT, "positionOffset"); + pageScrolledPositionOffsetPixelsParam = method.param(intClass, "positionOffsetPixels"); + } + + private void createPageSelected() { + JMethod method = listenerClass.method(JMod.PUBLIC, holder.getCodeModel().VOID, "onPageSelected"); + method.annotate(Override.class); + pageSelectedBody = method.body(); + JPrimitiveType intClass = holder.getCodeModel().INT; + pageSelectedPositionParam = method.param(intClass, "position"); + } + + public JVar getViewPagerVariable() { + return viewPagerVariable; + } + + public JDefinedClass getListenerClass() { + return listenerClass; + } + + public JBlock getPageScrollStateChangedBody() { + return pageScrollStateChangedBody; + } + + public JVar getPageScrollStateChangedStateParam() { + return pageScrollStateChangedStateParam; + } + + public JBlock getPageScrolledBody() { + return pageScrolledBody; + } + + public JVar getPageScrolledPositionParam() { + return pageScrolledPositionParam; + } + + public JVar getPageScrolledPositionOffsetParam() { + return pageScrolledPositionOffsetParam; + } + + public JVar getPageScrolledPositionOffsetPixelsParam() { + return pageScrolledPositionOffsetPixelsParam; + } + + public JBlock getPageSelectedBody() { + return pageSelectedBody; + } + + public JVar getPageSelectedPositionParam() { + return pageSelectedPositionParam; + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/CorePlugin.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/CorePlugin.java index 6e4ddd8cb2..1c0e9862ca 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/CorePlugin.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/CorePlugin.java @@ -76,6 +76,9 @@ import org.androidannotations.internal.core.handler.OptionsItemHandler; import org.androidannotations.internal.core.handler.OptionsMenuHandler; import org.androidannotations.internal.core.handler.OptionsMenuItemHandler; +import org.androidannotations.internal.core.handler.PageScrollStateChangedHandler; +import org.androidannotations.internal.core.handler.PageScrolledHandler; +import org.androidannotations.internal.core.handler.PageSelectedHandler; import org.androidannotations.internal.core.handler.PrefHandler; import org.androidannotations.internal.core.handler.PreferenceByKeyHandler; import org.androidannotations.internal.core.handler.PreferenceChangeHandler; @@ -199,6 +202,9 @@ public List> getHandlers(AndroidAnnotationsEnvironment andr annotationHandlers.add(new ReceiverHandler(androidAnnotationEnv)); annotationHandlers.add(new ReceiverActionHandler(androidAnnotationEnv)); annotationHandlers.add(new OnActivityResultHandler(androidAnnotationEnv)); + annotationHandlers.add(new PageScrolledHandler(androidAnnotationEnv)); + annotationHandlers.add(new PageScrollStateChangedHandler(androidAnnotationEnv)); + annotationHandlers.add(new PageSelectedHandler(androidAnnotationEnv)); annotationHandlers.add(new IgnoredWhenDetachedHandler(androidAnnotationEnv)); diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/AbstractPageChangeHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/AbstractPageChangeHandler.java new file mode 100644 index 0000000000..3b7286f7e0 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/AbstractPageChangeHandler.java @@ -0,0 +1,56 @@ +/** + * 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.internal.core.handler; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import org.androidannotations.AndroidAnnotationsEnvironment; +import org.androidannotations.ElementValidation; +import org.androidannotations.handler.BaseAnnotationHandler; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.helper.IdValidatorHelper; +import org.androidannotations.holder.EComponentWithViewSupportHolder; +import org.androidannotations.rclass.IRClass; + +public abstract class AbstractPageChangeHandler extends BaseAnnotationHandler { + public AbstractPageChangeHandler(Class targetClass, AndroidAnnotationsEnvironment environment) { + super(targetClass, environment); + } + + @Override + protected void validate(Element element, ElementValidation validation) { + validatorHelper.enclosingElementHasEnhancedViewSupportAnnotation(element, validation); + + validatorHelper.isViewPagerClassPresent(validation); + + validatorHelper.resIdsExist(element, IRClass.Res.ID, IdValidatorHelper.FallbackStrategy.USE_ELEMENT_NAME, validation); + + validatorHelper.isNotPrivate(element, validation); + + validatorHelper.doesntThrowException(element, validation); + + validatorHelper.returnTypeIsVoid((ExecutableElement) element, validation); + + validatorHelper.uniqueResourceId(element, IRClass.Res.ID, validation); + } + + protected boolean hasAddOnPageChangeListenerMethod() { + TypeElement viewPager = getProcessingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.VIEW_PAGER); + return hasTargetMethod(viewPager, "addOnPageChangeListener"); + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/ContextCompatAwareResHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/ContextCompatAwareResHandler.java index 5fb8e1f815..e033d300ae 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/ContextCompatAwareResHandler.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/ContextCompatAwareResHandler.java @@ -18,12 +18,7 @@ import static com.helger.jcodemodel.JExpr.invoke; import static com.helger.jcodemodel.JExpr.ref; -import java.util.List; - -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.AndroidAnnotationsEnvironment; import org.androidannotations.helper.CanonicalNameConstants; @@ -68,7 +63,7 @@ private boolean shouldUseContextMethod() { private boolean hasTargetMethodInContext() { TypeElement context = getProcessingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.CONTEXT); - return hasTargetMethod(context); + return hasTargetMethod(context, androidRes.getResourceMethodName()); } private void createCallWithIfGuard(EComponentHolder holder, JFieldRef ref, JBlock methodBody, JFieldRef idRef) { @@ -81,20 +76,6 @@ private void createCallWithIfGuard(EComponentHolder holder, JFieldRef ref, JBloc elseBlock.assign(ref, resourcesRef.invoke(androidRes.getResourceMethodName()).arg(idRef)); } - private boolean hasTargetMethod(TypeElement type) { - if (type == null) { - return false; - } - - List allMembers = getProcessingEnvironment().getElementUtils().getAllMembers(type); - for (ExecutableElement element : ElementFilter.methodsIn(allMembers)) { - if (element.getSimpleName().contentEquals(androidRes.getResourceMethodName())) { - return true; - } - } - return false; - } - protected boolean hasContextCompatInClasspath() { return getProcessingEnvironment().getElementUtils().getTypeElement(CanonicalNameConstants.CONTEXT_COMPAT) != null; } diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrollStateChangedHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrollStateChangedHandler.java new file mode 100644 index 0000000000..bf61395940 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrollStateChangedHandler.java @@ -0,0 +1,103 @@ +/** + * 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.internal.core.handler; + +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +import org.androidannotations.AndroidAnnotationsEnvironment; +import org.androidannotations.ElementValidation; +import org.androidannotations.annotations.PageScrollStateChanged; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.holder.EComponentWithViewSupportHolder; +import org.androidannotations.holder.PageChangeHolder; +import org.androidannotations.rclass.IRClass; + +import com.helger.jcodemodel.IJExpression; +import com.helger.jcodemodel.JBlock; +import com.helger.jcodemodel.JFieldRef; +import com.helger.jcodemodel.JInvocation; +import com.helger.jcodemodel.JVar; + +public class PageScrollStateChangedHandler extends AbstractPageChangeHandler { + + public PageScrollStateChangedHandler(AndroidAnnotationsEnvironment environment) { + super(PageScrollStateChanged.class, environment); + } + + @Override + public void validate(Element element, ElementValidation validation) { + super.validate(element, validation); + + validatorHelper.param.anyOrder() // + .type(CanonicalNameConstants.VIEW_PAGER).optional() // + .primitiveOrWrapper(TypeKind.INT).optional() // + .validate((ExecutableElement) element, validation); + } + + @Override + public void process(Element element, EComponentWithViewSupportHolder holder) { + String methodName = element.getSimpleName().toString(); + + ExecutableElement executableElement = (ExecutableElement) element; + List parameters = executableElement.getParameters(); + + int stateParameterPosition = -1; + int viewPagerParameterPosition = -1; + TypeMirror viewPagerParameterType = null; + + for (int i = 0; i < parameters.size(); i++) { + VariableElement parameter = parameters.get(i); + TypeMirror parameterType = parameter.asType(); + + if (parameterType.getKind() == TypeKind.INT || CanonicalNameConstants.INTEGER.equals(parameterType.toString())) { + stateParameterPosition = i; + } else { + TypeMirror viewPagerType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.VIEW_PAGER).asType(); + if (annotationHelper.isSubtype(parameterType, viewPagerType)) { + viewPagerParameterPosition = i; + viewPagerParameterType = parameterType; + } + } + } + + List idsRefs = annotationHelper.extractAnnotationFieldRefs(element, IRClass.Res.ID, true); + + for (JFieldRef idRef : idsRefs) { + PageChangeHolder pageChangeHolder = holder.getPageChangeHolder(idRef, viewPagerParameterType, hasAddOnPageChangeListenerMethod()); + JBlock methodBody = pageChangeHolder.getPageScrollStateChangedBody(); + + IJExpression thisRef = holder.getGeneratedClass().staticRef("this"); + JInvocation methodCall = methodBody.invoke(thisRef, methodName); + + for (int i = 0; i < parameters.size(); i++) { + if (i == stateParameterPosition) { + JVar stateParam = pageChangeHolder.getPageScrollStateChangedStateParam(); + methodCall.arg(stateParam); + } else if (i == viewPagerParameterPosition) { + JVar viewParameter = pageChangeHolder.getViewPagerVariable(); + methodCall.arg(viewParameter); + } + } + + } + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrolledHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrolledHandler.java new file mode 100644 index 0000000000..da1a310ce6 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageScrolledHandler.java @@ -0,0 +1,121 @@ +/** + * 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.internal.core.handler; + +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +import org.androidannotations.AndroidAnnotationsEnvironment; +import org.androidannotations.ElementValidation; +import org.androidannotations.annotations.PageScrolled; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.holder.EComponentWithViewSupportHolder; +import org.androidannotations.holder.PageChangeHolder; +import org.androidannotations.rclass.IRClass; + +import com.helger.jcodemodel.IJExpression; +import com.helger.jcodemodel.JBlock; +import com.helger.jcodemodel.JFieldRef; +import com.helger.jcodemodel.JInvocation; +import com.helger.jcodemodel.JVar; + +public class PageScrolledHandler extends AbstractPageChangeHandler { + + public PageScrolledHandler(AndroidAnnotationsEnvironment environment) { + super(PageScrolled.class, environment); + } + + @Override + protected void validate(Element element, ElementValidation validation) { + super.validate(element, validation); + + validatorHelper.param.inOrder() // + .type(CanonicalNameConstants.VIEW_PAGER).optional() // + .primitiveOrWrapper(TypeKind.INT).optional() // + .primitiveOrWrapper(TypeKind.FLOAT).optional() // + .primitiveOrWrapper(TypeKind.INT).optional() // + .validate((ExecutableElement) element, validation); + } + + @Override + public void process(Element element, EComponentWithViewSupportHolder holder) throws Exception { + String methodName = element.getSimpleName().toString(); + + ExecutableElement executableElement = (ExecutableElement) element; + List parameters = executableElement.getParameters(); + + int positionParameterPosition = -1; + int positionOffsetParameterPosition = -1; + int positionOffsetPixelsParameterPosition = -1; + int viewPagerParameterPosition = -1; + int numberOfIntParameters = 0; + TypeMirror viewPagerParameterType = null; + + for (int i = 0; i < parameters.size(); i++) { + VariableElement parameter = parameters.get(i); + TypeMirror parameterType = parameter.asType(); + + if (parameterType.getKind() == TypeKind.INT || CanonicalNameConstants.INTEGER.equals(parameterType.toString())) { + if (numberOfIntParameters == 0 && positionOffsetParameterPosition == -1) { + positionParameterPosition = i; + } else { + positionOffsetPixelsParameterPosition = i; + } + numberOfIntParameters++; + } else if (parameterType.getKind() == TypeKind.FLOAT || CanonicalNameConstants.FLOAT.equals(parameterType.toString())) { + positionOffsetParameterPosition = i; + } else { + TypeMirror viewPagerType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.VIEW_PAGER).asType(); + if (annotationHelper.isSubtype(parameterType, viewPagerType)) { + viewPagerParameterPosition = i; + viewPagerParameterType = parameterType; + } + } + } + + List idsRefs = annotationHelper.extractAnnotationFieldRefs(element, IRClass.Res.ID, true); + + for (JFieldRef idRef : idsRefs) { + PageChangeHolder pageChangeHolder = holder.getPageChangeHolder(idRef, viewPagerParameterType, hasAddOnPageChangeListenerMethod()); + JBlock methodBody = pageChangeHolder.getPageScrolledBody(); + + IJExpression activityRef = holder.getGeneratedClass().staticRef("this"); + JInvocation pageScrollCall = methodBody.invoke(activityRef, methodName); + + for (int i = 0; i < parameters.size(); i++) { + if (i == positionParameterPosition) { + JVar positionParam = pageChangeHolder.getPageScrolledPositionParam(); + pageScrollCall.arg(positionParam); + } else if (i == positionOffsetParameterPosition) { + JVar pageScrolledPositionOffsetParam = pageChangeHolder.getPageScrolledPositionOffsetParam(); + pageScrollCall.arg(pageScrolledPositionOffsetParam); + } else if (i == positionOffsetPixelsParameterPosition) { + JVar pageScrolledPositionOffsetPixelsParam = pageChangeHolder.getPageScrolledPositionOffsetPixelsParam(); + pageScrollCall.arg(pageScrolledPositionOffsetPixelsParam); + } else if (i == viewPagerParameterPosition) { + JVar viewParameter = pageChangeHolder.getViewPagerVariable(); + pageScrollCall.arg(viewParameter); + } + } + + } + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageSelectedHandler.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageSelectedHandler.java new file mode 100644 index 0000000000..5b736eab11 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/PageSelectedHandler.java @@ -0,0 +1,102 @@ +/** + * 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.internal.core.handler; + +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +import org.androidannotations.AndroidAnnotationsEnvironment; +import org.androidannotations.ElementValidation; +import org.androidannotations.annotations.PageSelected; +import org.androidannotations.helper.CanonicalNameConstants; +import org.androidannotations.holder.EComponentWithViewSupportHolder; +import org.androidannotations.holder.PageChangeHolder; +import org.androidannotations.rclass.IRClass; + +import com.helger.jcodemodel.IJExpression; +import com.helger.jcodemodel.JBlock; +import com.helger.jcodemodel.JFieldRef; +import com.helger.jcodemodel.JInvocation; +import com.helger.jcodemodel.JVar; + +public class PageSelectedHandler extends AbstractPageChangeHandler { + public PageSelectedHandler(AndroidAnnotationsEnvironment environment) { + super(PageSelected.class, environment); + } + + @Override + protected void validate(Element element, ElementValidation validation) { + super.validate(element, validation); + + validatorHelper.param.anyOrder() // + .type(CanonicalNameConstants.VIEW_PAGER).optional() // + .primitiveOrWrapper(TypeKind.INT).optional() // + .validate((ExecutableElement) element, validation); + } + + @Override + public void process(Element element, EComponentWithViewSupportHolder holder) throws Exception { + String methodName = element.getSimpleName().toString(); + + ExecutableElement executableElement = (ExecutableElement) element; + List parameters = executableElement.getParameters(); + + int positionParameterPosition = -1; + int viewPagerParameterPosition = -1; + TypeMirror viewPagerParameterType = null; + + for (int i = 0; i < parameters.size(); i++) { + VariableElement parameter = parameters.get(i); + TypeMirror parameterType = parameter.asType(); + + if (parameterType.getKind() == TypeKind.INT || CanonicalNameConstants.INTEGER.equals(parameterType.toString())) { + positionParameterPosition = i; + } else { + TypeMirror viewPagerType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.VIEW_PAGER).asType(); + if (annotationHelper.isSubtype(parameterType, viewPagerType)) { + viewPagerParameterPosition = i; + viewPagerParameterType = parameterType; + } + } + } + + List idsRefs = annotationHelper.extractAnnotationFieldRefs(element, IRClass.Res.ID, true); + + for (JFieldRef idRef : idsRefs) { + PageChangeHolder pageChangeHolder = holder.getPageChangeHolder(idRef, viewPagerParameterType, hasAddOnPageChangeListenerMethod()); + JBlock methodBody = pageChangeHolder.getPageSelectedBody(); + + IJExpression thisRef = holder.getGeneratedClass().staticRef("this"); + JInvocation methodCall = methodBody.invoke(thisRef, methodName); + + for (int i = 0; i < parameters.size(); i++) { + if (i == positionParameterPosition) { + JVar stateParam = pageChangeHolder.getPageSelectedPositionParam(); + methodCall.arg(stateParam); + } else if (i == viewPagerParameterPosition) { + JVar viewParameter = pageChangeHolder.getViewPagerVariable(); + methodCall.arg(viewParameter); + } + } + + } + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/process/ProcessHolder.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/process/ProcessHolder.java index d054faf488..5582a12bfc 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/process/ProcessHolder.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/process/ProcessHolder.java @@ -123,6 +123,8 @@ public class Classes { public final AbstractJClass ACTIVITY_COMPAT = refClass(CanonicalNameConstants.ACTIVITY_COMPAT); public final AbstractJClass CONTEXT_COMPAT = refClass(CanonicalNameConstants.CONTEXT_COMPAT); public final AbstractJClass APP_WIDGET_MANAGER = refClass(CanonicalNameConstants.APP_WIDGET_MANAGER); + public final AbstractJClass VIEW_PAGER = refClass(CanonicalNameConstants.VIEW_PAGER); + public final AbstractJClass PAGE_CHANGE_LISTENER = refClass(CanonicalNameConstants.PAGE_CHANGE_LISTENER); public final AbstractJClass PREFERENCE = refClass(CanonicalNameConstants.PREFERENCE); public final AbstractJClass SUPPORT_V7_PREFERENCE = refClass(CanonicalNameConstants.SUPPORT_V7_PREFERENCE); diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/android/support/v4/view/ViewPager.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/android/support/v4/view/ViewPager.java new file mode 100644 index 0000000000..1a257de30d --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/android/support/v4/view/ViewPager.java @@ -0,0 +1,46 @@ +/** + * 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 android.support.v4.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +public class ViewPager extends View { + public ViewPager(Context context) { + super(context); + } + + public ViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ViewPager(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void addOnPageChangeListener(OnPageChangeListener listener) { + + } + + public interface OnPageChangeListener { + void onPageScrollStateChanged(int state); + + void onPageScrolled(int position, float positionOffset, int positionOffsetPixels); + + void onPageSelected(int position); + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPager.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPager.java new file mode 100644 index 0000000000..5620025c2c --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPager.java @@ -0,0 +1,111 @@ +/** + * 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.PageScrollStateChanged; +import org.androidannotations.annotations.PageScrolled; +import org.androidannotations.annotations.PageSelected; + +import android.app.Activity; +import android.support.v4.view.ViewPager; + +@EActivity +public class ActivityWithViewPager extends Activity { + @PageScrollStateChanged(R.id.myViewPagerWithAllMethods) + public void pageScrollStateChanged() { + } + + @PageScrollStateChanged(R.id.myViewPagerWithPageScrollStateChanged) + public void pageScrollStateChangedOnly() { + } + + @PageScrollStateChanged(R.id.myViewPager) + public void pageScrollStateChangedWithParams(ViewPager v, int s) { + } + + @PageScrollStateChanged(R.id.myViewPager2) + public void pageScrollStateChangedWithOnlyViewPagerParams(ViewPager v) { + } + + @PageScrollStateChanged(R.id.myViewPager3) + public void pageScrollStateChangedWithOnlyIntParams(int state) { + } + + @PageScrollStateChanged + public void myViewPagerWithNoRes1() { + } + + @PageScrollStateChanged({ R.id.myViewPagerWithMultipleRes1, R.id.myViewPagerWithMultipleRes2 }) + public void pageScrollStateChangedWithMultipleRes() { + } + + @PageScrolled(R.id.myViewPagerWithAllMethods) + public void pageScrolled() { + } + + @PageScrolled(R.id.myViewPagerWithPageScrolled) + public void pageScrolledOnly() { + } + + @PageScrolled(R.id.myViewPager) + public void pageScrolledWithParams(ViewPager viewPager, int int1, float float1, int int2) { + } + + @PageScrolled(R.id.myViewPager2) + public void pageScrolledWithOnlyViewPager(ViewPager view) { + } + + @PageScrolled(R.id.myViewPager3) + public void pageScrolledWithOnlyInt(int position, int positionOffsetPixels) { + } + + @PageScrolled + public void myViewPagerWithNoRes2(float f, int positionOffsetPixels) { + } + + @PageScrolled({ R.id.myViewPagerWithMultipleRes1, R.id.myViewPagerWithMultipleRes2 }) + public void pageScrolledWithMultipleRes() { + } + + @PageSelected(R.id.myViewPagerWithAllMethods) + public void pageSelected() { + } + + @PageSelected(R.id.myViewPagerWithPageSelected) + public void pageSelectedOnly() { + } + + @PageSelected(R.id.myViewPager) + public void pageSelectedWithParams(ViewPager position, int view) { + } + + @PageSelected(R.id.myViewPager2) + public void pageSelectedWithOnlyViewPagerParams(ViewPager position) { + } + + @PageSelected(R.id.myViewPager3) + public void pageSelectedWithOnlyIntParams(int position) { + } + + @PageSelected + public void myViewPagerWithNoRes3() { + } + + @PageSelected({ R.id.myViewPagerWithMultipleRes1, R.id.myViewPagerWithMultipleRes2 }) + public void pageSelectedWithMultipleRes() { + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrollStateChanged.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrollStateChanged.java new file mode 100644 index 0000000000..2638866a66 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrollStateChanged.java @@ -0,0 +1,32 @@ +/** + * 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.PageScrollStateChanged; + +import android.app.Activity; + +@EActivity +public class ActivityWithViewPagerDuplicatePageScrollStateChanged extends Activity { + @PageScrollStateChanged(R.id.myViewPager) + public void pageScrollStateChanged() { + } + + @PageScrollStateChanged(R.id.myViewPager) + public void pageScrollStateChanged2() { + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrolled.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrolled.java new file mode 100644 index 0000000000..847f0cd890 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageScrolled.java @@ -0,0 +1,32 @@ +/** + * 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.PageScrolled; + +import android.app.Activity; + +@EActivity +public class ActivityWithViewPagerDuplicatePageScrolled extends Activity { + @PageScrolled(R.id.myViewPager) + public void pageScrolled() { + } + + @PageScrolled(R.id.myViewPager) + public void pageScrolled2() { + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageSelected.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageSelected.java new file mode 100644 index 0000000000..f344ba9028 --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerDuplicatePageSelected.java @@ -0,0 +1,32 @@ +/** + * 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.PageSelected; + +import android.app.Activity; + +@EActivity +public class ActivityWithViewPagerDuplicatePageSelected extends Activity { + @PageSelected(R.id.myViewPager) + public void pageSelected() { + } + + @PageSelected(R.id.myViewPager) + public void pageSelected2() { + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerWrongParams.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerWrongParams.java new file mode 100644 index 0000000000..fc41648f4b --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ActivityWithViewPagerWrongParams.java @@ -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.generation; + +import org.androidannotations.annotations.PageScrollStateChanged; +import org.androidannotations.annotations.PageScrolled; +import org.androidannotations.annotations.PageSelected; + +public class ActivityWithViewPagerWrongParams { + @PageSelected(R.id.myViewPager) + public void nonExistTypeForPageSelected(String text) { + } + + @PageScrolled(R.id.myViewPager) + public void nonExistTypeForPageScrolled(String text) { + } + + @PageScrollStateChanged(R.id.myViewPager) + public void nonExistTypeForPageScrollStateChanged(String text) { + } + + @PageScrolled(R.id.myViewPager2) + public void nonExistIntName(int text) { + } +} diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/R.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/R.java index 95f625bb4b..d049048197 100644 --- a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/R.java +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/R.java @@ -9,4 +9,19 @@ public static final class color { public static final int myColor = 0x7f06000b; public static final int myColorStateList = 0x7f06000c; } + + public static final class id { + public static final int myViewPagerWithAllMethods = 0x7f06000d; + public static final int myViewPagerWithPageSelected = 0x7f06000e; + public static final int myViewPagerWithPageScrolled = 0x7f06000f; + public static final int myViewPagerWithPageScrollStateChanged = 0x7f060010; + public static final int myViewPager = 0x7f060011; + public static final int myViewPager2 = 0x7f060012; + public static final int myViewPager3 = 0x7f060013; + public static final int myViewPagerWithNoRes1 = 0x7f060014; + public static final int myViewPagerWithNoRes2 = 0x7f060015; + public static final int myViewPagerWithNoRes3 = 0x7f060016; + public static final int myViewPagerWithMultipleRes1 = 0x7f060017; + public static final int myViewPagerWithMultipleRes2 = 0x7f060018; + } } diff --git a/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ViewPagerTest.java b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ViewPagerTest.java new file mode 100644 index 0000000000..71e651529e --- /dev/null +++ b/AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/generation/ViewPagerTest.java @@ -0,0 +1,70 @@ +/** + * 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 java.io.IOException; + +import org.androidannotations.internal.AndroidAnnotationProcessor; +import org.androidannotations.testutils.AAProcessorTestHelper; +import org.junit.Before; +import org.junit.Test; + +public class ViewPagerTest extends AAProcessorTestHelper { + + @Before + public void setUp() { + addProcessor(AndroidAnnotationProcessor.class); + } + + @Test + public void compileActivityWithViewPager() { + addManifestProcessorParameter(ViewPagerTest.class, "AndroidManifestForDrawable.xml"); + assertCompilationSuccessful(compileFiles(ActivityWithViewPager.class)); + } + + @Test + public void compileFailForRegisterDuplicatePageScrolled() { + addManifestProcessorParameter(ViewPagerTest.class, "AndroidManifestForDrawable.xml"); + CompileResult result = compileFiles(ActivityWithViewPagerDuplicatePageScrolled.class); + assertCompilationError(result); + } + + @Test + public void compileFailForRegisterDuplicatePageSelected() { + addManifestProcessorParameter(ViewPagerTest.class, "AndroidManifestForDrawable.xml"); + CompileResult result = compileFiles(ActivityWithViewPagerDuplicatePageSelected.class); + assertCompilationError(result); + } + + @Test + public void compileFailForRegisterDuplicatePageScrollStateChanged() { + addManifestProcessorParameter(ViewPagerTest.class, "AndroidManifestForDrawable.xml"); + CompileResult result = compileFiles(ActivityWithViewPagerDuplicatePageScrollStateChanged.class); + assertCompilationError(result); + } + + @Test + public void compileFailForNonExistParameter() throws IOException { + addManifestProcessorParameter(ViewPagerTest.class, "AndroidManifestForDrawable.xml"); + CompileResult result = compileFiles(ActivityWithViewPagerWrongParams.class); + assertCompilationErrorOn(ActivityWithViewPagerWrongParams.class, "@PageSelected(R.id.myViewPager)", result); + assertCompilationErrorOn(ActivityWithViewPagerWrongParams.class, "@PageScrolled(R.id.myViewPager)", result); + assertCompilationErrorOn(ActivityWithViewPagerWrongParams.class, "@PageScrollStateChanged(R.id.myViewPager)", result); + assertCompilationErrorOn(ActivityWithViewPagerWrongParams.class, "@PageScrolled(R.id.myViewPager2)", result); + assertCompilationError(result); + } + +}