From d4ee671aa446fc2215e837c47b8857ef9560e900 Mon Sep 17 00:00:00 2001 From: Nathanael Silverman Date: Fri, 15 Jun 2018 17:06:20 -0500 Subject: [PATCH 01/14] Generate model factory methods --- epoxy-modelfactory/.gitignore | 1 + epoxy-modelfactory/build.gradle | 56 + .../build.workaround-missing-resource.gradle | 23 + epoxy-modelfactory/gradle.properties | 3 + .../src/main/AndroidManifest.xml | 2 + .../com/airbnb/epoxy/ModelProperties.java | 39 + .../src/main/res/values/strings.xml | 3 + .../airbnb/epoxy/FromModelPropertiesTest.kt | 104 ++ .../epoxy/ModelFactoryViewProcessorTest.kt | 61 + .../com/airbnb/epoxy/ProcessorTestUtils.kt | 36 + .../airbnb/epoxy/TestModelPropertiesView.java | 54 + .../java/com/airbnb/epoxy/package-info.java | 5 + .../src/test/resources/AllTypesModelView.java | 52 + .../resources/AllTypesModelViewModel_.java | 509 ++++++++ .../src/test/resources/BaseModelView.java | 17 + .../test/resources/BaseModelViewModel_.java | 261 ++++ .../test/resources/CallbackPropModelView.java | 18 + .../CallbackPropModelViewModel_.java | 270 ++++ .../test/resources/StyleableModelView.java | 20 + .../resources/StyleableModelViewModel_.java | 348 +++++ .../src/test/resources/TextPropModelView.java | 17 + .../resources/TextPropModelViewModel_.java | 305 +++++ .../java/com/airbnb/epoxy/AttributeInfo.java | 40 +- .../java/com/airbnb/epoxy/ClassNames.java | 1 + .../com/airbnb/epoxy/GeneratedModelWriter.kt | 1150 ++++++++++------- .../epoxy/ModelBuilderInterfaceWriter.kt | 9 +- .../src/main/java/com/airbnb/epoxy/Utils.java | 14 + epoxy-processortest/build.gradle | 9 +- .../com/airbnb/epoxy/ProcessorTestUtils.kt | 3 - settings.gradle | 2 +- 30 files changed, 2970 insertions(+), 462 deletions(-) create mode 100644 epoxy-modelfactory/.gitignore create mode 100644 epoxy-modelfactory/build.gradle create mode 100644 epoxy-modelfactory/build.workaround-missing-resource.gradle create mode 100644 epoxy-modelfactory/gradle.properties create mode 100644 epoxy-modelfactory/src/main/AndroidManifest.xml create mode 100644 epoxy-modelfactory/src/main/java/com/airbnb/epoxy/ModelProperties.java create mode 100644 epoxy-modelfactory/src/main/res/values/strings.xml create mode 100644 epoxy-modelfactory/src/test/java/com/airbnb/epoxy/FromModelPropertiesTest.kt create mode 100644 epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ModelFactoryViewProcessorTest.kt create mode 100644 epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ProcessorTestUtils.kt create mode 100644 epoxy-modelfactory/src/test/java/com/airbnb/epoxy/TestModelPropertiesView.java create mode 100644 epoxy-modelfactory/src/test/java/com/airbnb/epoxy/package-info.java create mode 100644 epoxy-modelfactory/src/test/resources/AllTypesModelView.java create mode 100644 epoxy-modelfactory/src/test/resources/AllTypesModelViewModel_.java create mode 100644 epoxy-modelfactory/src/test/resources/BaseModelView.java create mode 100644 epoxy-modelfactory/src/test/resources/BaseModelViewModel_.java create mode 100644 epoxy-modelfactory/src/test/resources/CallbackPropModelView.java create mode 100644 epoxy-modelfactory/src/test/resources/CallbackPropModelViewModel_.java create mode 100644 epoxy-modelfactory/src/test/resources/StyleableModelView.java create mode 100644 epoxy-modelfactory/src/test/resources/StyleableModelViewModel_.java create mode 100644 epoxy-modelfactory/src/test/resources/TextPropModelView.java create mode 100644 epoxy-modelfactory/src/test/resources/TextPropModelViewModel_.java diff --git a/epoxy-modelfactory/.gitignore b/epoxy-modelfactory/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/epoxy-modelfactory/.gitignore @@ -0,0 +1 @@ +/build diff --git a/epoxy-modelfactory/build.gradle b/epoxy-modelfactory/build.gradle new file mode 100644 index 0000000000..52c9e26cbb --- /dev/null +++ b/epoxy-modelfactory/build.gradle @@ -0,0 +1,56 @@ +import org.gradle.internal.jvm.Jvm + +apply plugin: 'com.android.library' +apply from: 'build.workaround-missing-resource.gradle' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion rootProject.COMPILE_SDK_VERSION + + defaultConfig { + minSdkVersion rootProject.MIN_SDK_VERSION + targetSdkVersion rootProject.TARGET_SDK_VERSION + } +} + +configurations.all { strategy -> + strategy.resolutionStrategy.force rootProject.deps.junit, rootProject.deps.robolectric, + rootProject.deps.mockito +} + +dependencies { + compile project(':epoxy-adapter') + compile rootProject.deps.paris + + testCompile project(':epoxy-adapter') + // Need to include the processor directly since we create an instance of it in code for testing + testCompile project(':epoxy-processor') + testCompile project(':epoxy-processortest') + testCompile rootProject.deps.googleTestingCompile + testCompile rootProject.deps.junit + testCompile rootProject.deps.kotlin + // Need to include the processor directly since we create an instance of it in code for testing + testCompile rootProject.deps.parisProcessor + testCompile rootProject.deps.robolectric + testCompile files(getRuntimeJar()) + testCompile files(Jvm.current().getToolsJar()) + + kaptTest project(':epoxy-processor') +} + +static def getRuntimeJar() { + try { + final File javaBase = new File(System.getProperty("java.home")).getCanonicalFile() + File runtimeJar = new File(javaBase, "lib/rt.jar") + if (runtimeJar.exists()) { + return runtimeJar + } + runtimeJar = new File(javaBase, "jre/lib/rt.jar") + return runtimeJar.exists() ? runtimeJar : null + } catch (IOException e) { + throw new RuntimeException(e) + } +} + +apply from: rootProject.file('gradle/gradle-maven-push.gradle') diff --git a/epoxy-modelfactory/build.workaround-missing-resource.gradle b/epoxy-modelfactory/build.workaround-missing-resource.gradle new file mode 100644 index 0000000000..7637db440d --- /dev/null +++ b/epoxy-modelfactory/build.workaround-missing-resource.gradle @@ -0,0 +1,23 @@ +// Source - https://github.com/nenick/AndroidStudioAndRobolectric/blob/master/app/build.workaround-missing-resource.gradle +// Workaround for missing test resources when running unit tests within android studio. +// This copies the test resources next to the test classes for each variant. +// Tracked at https://github.com/nenick/AndroidStudioAndRobolectric/issues/7 +// Original solution comes from https://code.google.com/p/android/issues/detail?id=136013#c10 +// See also https://code.google.com/p/android/issues/detail?id=64887 +gradle.projectsEvaluated { + // Base path which is recognized by android studio. + def testClassesPath = "${buildDir}/intermediates/classes/test/" + // Copy must be done for each variant. + def variants = android.libraryVariants.collect() + + variants.each { variant -> + def variationName = variant.name.capitalize() + def variationPath = variant.buildType.name + + // Specific copy task for each variant + def copyTestResourcesTask = project.tasks.create("copyTest${variationName}Resources", Copy) + copyTestResourcesTask.from("${projectDir}/src/test/resources") + copyTestResourcesTask.into("${testClassesPath}/${variationPath}") + copyTestResourcesTask.execute() + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/gradle.properties b/epoxy-modelfactory/gradle.properties new file mode 100644 index 0000000000..834da184d1 --- /dev/null +++ b/epoxy-modelfactory/gradle.properties @@ -0,0 +1,3 @@ +POM_NAME=Epoxy Model Factory +POM_ARTIFACT_ID=epoxy-modelfactory +POM_PACKAGING=jar \ No newline at end of file diff --git a/epoxy-modelfactory/src/main/AndroidManifest.xml b/epoxy-modelfactory/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..884085bc7f --- /dev/null +++ b/epoxy-modelfactory/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/epoxy-modelfactory/src/main/java/com/airbnb/epoxy/ModelProperties.java b/epoxy-modelfactory/src/main/java/com/airbnb/epoxy/ModelProperties.java new file mode 100644 index 0000000000..6ab5e4e123 --- /dev/null +++ b/epoxy-modelfactory/src/main/java/com/airbnb/epoxy/ModelProperties.java @@ -0,0 +1,39 @@ +package com.airbnb.epoxy; + +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.View.OnClickListener; + +import com.airbnb.paris.styles.Style; + +import java.util.List; + +public interface ModelProperties { + + boolean has(@NonNull String propertyName); + + boolean getBoolean(@NonNull String propertyName); + + double getDouble(@NonNull String propertyName); + + @NonNull + Drawable getDrawable(@NonNull String propertyName); + + int getInt(@NonNull String propertyName); + + @NonNull + OnClickListener getOnClickListener(@NonNull String propertyName); + + @NonNull + String getString(@NonNull String propertyName); + + @NonNull + List getStringList(@NonNull String propertyName); + + /** + * @return Null to apply the default style. + */ + @Nullable + Style getStyle(); +} diff --git a/epoxy-modelfactory/src/main/res/values/strings.xml b/epoxy-modelfactory/src/main/res/values/strings.xml new file mode 100644 index 0000000000..5b7aab467d --- /dev/null +++ b/epoxy-modelfactory/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Epoxy Model Factory + diff --git a/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/FromModelPropertiesTest.kt b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/FromModelPropertiesTest.kt new file mode 100644 index 0000000000..eebd84c5c9 --- /dev/null +++ b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/FromModelPropertiesTest.kt @@ -0,0 +1,104 @@ +package com.airbnb.epoxy + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.view.View +import com.airbnb.paris.styles.Style +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Asserts that using from(ModelProperties) to create a model applies the property values correctly + */ +class FromModelPropertiesTest { + + @Test + fun getBoolean() { + val model = TestModelPropertiesViewModel_.from(TestModelProperties(booleanValue = true)) + assertEquals(true, model.booleanValue()) + } + + @Test + fun getDouble() { + val model = TestModelPropertiesViewModel_.from(TestModelProperties(doubleValue = 42.0)) + assertEquals(42.0, model.doubleValue(), 0.0) + } + + @Test + fun getDrawable() { + val drawable = ColorDrawable(Color.GREEN) + val model = TestModelPropertiesViewModel_.from(TestModelProperties(drawable = drawable)) + assertEquals(drawable, model.drawable()) + } + + @Test + fun getInt() { + val model = TestModelPropertiesViewModel_.from(TestModelProperties(intValue = 51)) + assertEquals(51, model.intValue()) + } + + @Test + fun getOnClickListener() { + val clickListener = View.OnClickListener { } + val model = TestModelPropertiesViewModel_.from(TestModelProperties(onClickListener = clickListener)) + assertEquals(clickListener, model.onClickListener()) + } + + @Test + fun getString() { + val model = TestModelPropertiesViewModel_.from(TestModelProperties(stringValue = "ModelFactory")) + assertEquals("ModelFactory", model.stringValue()) + } + + @Test + fun getStringList() { + val stringList = listOf("Model", "Factory") + val model = TestModelPropertiesViewModel_.from(TestModelProperties(stringList = stringList)) + assertEquals(stringList, model.stringList()) + } + + class TestModelProperties( + private val id: String? = "", + private val booleanValue: Boolean? = null, + private val doubleValue: Double? = null, + private val drawable: Drawable? = null, + private val intValue: Int? = null, + private val onClickListener: View.OnClickListener? = null, + private val stringValue: String? = null, + private val stringList: List? = null, + private val styleValue: Style? = null + ) : ModelProperties { + + override fun has(propertyName: String): Boolean { + return mapOf( + "id" to id, + "booleanValue" to booleanValue, + "doubleValue" to doubleValue, + "drawable" to drawable, + "intValue" to intValue, + "onClickListener" to onClickListener, + "stringList" to stringList, + "stringValue" to stringValue + )[propertyName] != null + } + + override fun getBoolean(propertyName: String) = booleanValue!! + + override fun getDouble(propertyName: String) = doubleValue!! + + override fun getDrawable(propertyName: String) = drawable!! + + override fun getInt(propertyName: String) = intValue!! + + override fun getOnClickListener(propertyName: String) = onClickListener!! + + override fun getString(propertyName: String): String { + return if (propertyName == "id") id!! else stringValue!! + } + + override fun getStringList(propertyName: String) = stringList!! + + override fun getStyle() = styleValue + } +} diff --git a/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ModelFactoryViewProcessorTest.kt b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ModelFactoryViewProcessorTest.kt new file mode 100644 index 0000000000..e78696dd71 --- /dev/null +++ b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ModelFactoryViewProcessorTest.kt @@ -0,0 +1,61 @@ +package com.airbnb.epoxy + +import com.airbnb.epoxy.ProcessorTestUtils.assertGeneration +import com.google.testing.compile.JavaFileObjects +import org.junit.Test +import javax.tools.JavaFileObject + +class ModelFactoryViewProcessorTest { + + @Test + fun baseModel() { + assertGeneration( + "BaseModelView.java", + "BaseModelViewModel_.java" + ) + } + + @Test + fun callbackPropModel() { + assertGeneration( + "CallbackPropModelView.java", + "CallbackPropModelViewModel_.java" + ) + } + + @Test + fun textPropModel() { + assertGeneration( + "TextPropModelView.java", + "TextPropModelViewModel_.java" + ) + } + + @Test + fun allTypesModel() { + assertGeneration( + "AllTypesModelView.java", + "AllTypesModelViewModel_.java" + ) + } + + @Test + fun styleableModel() { + // If the view is styleable then the generated "from" method supports setting a style + + val configClass: JavaFileObject = JavaFileObjects + .forSourceLines("com.airbnb.epoxy.package-info", + "@ParisConfig(rClass = R.class)\n" + + "package com.airbnb.epoxy;\n" + + "\n" + + "import com.airbnb.paris.annotations.ParisConfig;\n" + + "import com.airbnb.epoxymodelfactory.R;\n") + + assertGeneration( + "StyleableModelView.java", + "StyleableModelViewModel_.java", + useParis = true, + helperObjects = listOf(configClass) + ) + } +} diff --git a/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ProcessorTestUtils.kt b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ProcessorTestUtils.kt new file mode 100644 index 0000000000..457aa6018b --- /dev/null +++ b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/ProcessorTestUtils.kt @@ -0,0 +1,36 @@ +package com.airbnb.epoxy + +import com.airbnb.paris.processor.ParisProcessor +import com.google.common.truth.Truth.assert_ +import com.google.testing.compile.JavaFileObjects +import com.google.testing.compile.JavaSourcesSubjectFactory.javaSources +import javax.annotation.processing.Processor +import javax.tools.JavaFileObject + +internal object ProcessorTestUtils { + @JvmOverloads + @JvmStatic + fun assertGeneration( + inputFile: String, + generatedFile: String, + useParis: Boolean = false, + helperObjects: List = emptyList() + ) { + val model = JavaFileObjects + .forResource(inputFile) + + val generatedModel = JavaFileObjects.forResource(generatedFile) + + val processors = mutableListOf().apply { + add(EpoxyProcessor()) + if (useParis) add(ParisProcessor()) + } + + assert_().about(javaSources()) + .that(helperObjects + listOf(model)) + .processedWith(processors) + .compilesWithoutError() + .and() + .generatesSources(generatedModel) + } +} diff --git a/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/TestModelPropertiesView.java b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/TestModelPropertiesView.java new file mode 100644 index 0000000000..08676a2677 --- /dev/null +++ b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/TestModelPropertiesView.java @@ -0,0 +1,54 @@ +package com.airbnb.epoxy; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.widget.FrameLayout; + +import com.airbnb.epoxy.ModelProp.Option; +import com.airbnb.epoxy.ModelView.Size; + +import java.util.List; + +@ModelView(autoLayout = Size.MATCH_WIDTH_WRAP_HEIGHT) +public class TestModelPropertiesView extends FrameLayout { + + public TestModelPropertiesView(Context context) { + super(context); + } + + @ModelProp + public void setBooleanValue(boolean value) { + + } + + @ModelProp + public void setDoubleValue(double value) { + + } + + @ModelProp({ Option.DoNotHash }) + public void setDrawable(Drawable value) { + + } + + @ModelProp + public void setIntValue(int value) { + + } + + @CallbackProp + public void setOnClickListener(@Nullable OnClickListener value) { + + } + + @ModelProp + public void setStringValue(CharSequence value) { + + } + + @ModelProp + public void setStringList(List value) { + + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/package-info.java b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/package-info.java new file mode 100644 index 0000000000..af3865f78f --- /dev/null +++ b/epoxy-modelfactory/src/test/java/com/airbnb/epoxy/package-info.java @@ -0,0 +1,5 @@ +@ParisConfig(rClass = R.class) +package com.airbnb.epoxy; + +import com.airbnb.epoxymodelfactory.R; +import com.airbnb.paris.annotations.ParisConfig; diff --git a/epoxy-modelfactory/src/test/resources/AllTypesModelView.java b/epoxy-modelfactory/src/test/resources/AllTypesModelView.java new file mode 100644 index 0000000000..5f8ea01462 --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/AllTypesModelView.java @@ -0,0 +1,52 @@ +package com.airbnb.epoxy; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.widget.FrameLayout; + +import com.airbnb.epoxy.ModelProp.Option; + +import java.util.List; + +@ModelView(defaultLayout = 1) +public class AllTypesModelView extends FrameLayout { + + public AllTypesModelView(Context context) { + super(context); + } + + @ModelProp + public void setBooleanValue(boolean value) { + + } + + @ModelProp + public void setDoubleValue(double value) { + + } + + @ModelProp({ Option.DoNotHash }) + public void setDrawable(Drawable value) { + + } + + @ModelProp + public void setIntValue(int value) { + + } + + @ModelProp({ Option.DoNotHash }) + public void setOnClickListener(OnClickListener value) { + + } + + @ModelProp + public void setStringValue(String value) { + + } + + @ModelProp + public void setStringList(List value) { + + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/AllTypesModelViewModel_.java b/epoxy-modelfactory/src/test/resources/AllTypesModelViewModel_.java new file mode 100644 index 0000000000..13e54564fb --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/AllTypesModelViewModel_.java @@ -0,0 +1,509 @@ +package com.airbnb.epoxy; + +import android.graphics.drawable.Drawable; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.View; +import java.lang.CharSequence; +import java.lang.IllegalArgumentException; +import java.lang.IllegalStateException; +import java.lang.Number; +import java.lang.Object; +import java.lang.Override; +import java.lang.String; +import java.util.BitSet; +import java.util.List; + +/** + * Generated file. Do not modify! */ +public class AllTypesModelViewModel_ extends EpoxyModel implements GeneratedModel, AllTypesModelViewModelBuilder { + private final BitSet assignedAttributes_epoxyGeneratedModel = new BitSet(7); + + private OnModelBoundListener onModelBoundListener_epoxyGeneratedModel; + + private OnModelUnboundListener onModelUnboundListener_epoxyGeneratedModel; + + /** + * Bitset index: 0 */ + private boolean booleanValue_Boolean = false; + + /** + * Bitset index: 1 */ + private double doubleValue_Double = 0.0d; + + /** + * Bitset index: 2 */ + @NonNull + private Drawable drawable_Drawable; + + /** + * Bitset index: 3 */ + private int intValue_Int = 0; + + /** + * Bitset index: 4 */ + @NonNull + private View.OnClickListener onClickListener_OnClickListener; + + /** + * Bitset index: 5 */ + @NonNull + private String stringValue_String; + + /** + * Bitset index: 6 */ + @NonNull + private List stringList_List; + + @Override + public void addTo(EpoxyController controller) { + super.addTo(controller); + addWithDebugValidation(controller); + if (!assignedAttributes_epoxyGeneratedModel.get(5)) { + throw new IllegalStateException("A value is required for setStringValue"); + } + if (!assignedAttributes_epoxyGeneratedModel.get(4)) { + throw new IllegalStateException("A value is required for setOnClickListener"); + } + if (!assignedAttributes_epoxyGeneratedModel.get(2)) { + throw new IllegalStateException("A value is required for setDrawable"); + } + if (!assignedAttributes_epoxyGeneratedModel.get(6)) { + throw new IllegalStateException("A value is required for setStringList"); + } + } + + @Override + public void handlePreBind(final EpoxyViewHolder holder, final AllTypesModelView object, + final int position) { + validateStateHasNotChangedSinceAdded("The model was changed between being added to the controller and being bound.", position); + } + + @Override + public void bind(final AllTypesModelView object) { + super.bind(object); + object.setStringValue(stringValue_String); + object.setOnClickListener(onClickListener_OnClickListener); + object.setIntValue(intValue_Int); + object.setBooleanValue(booleanValue_Boolean); + object.setDoubleValue(doubleValue_Double); + object.setDrawable(drawable_Drawable); + object.setStringList(stringList_List); + } + + @Override + public void bind(final AllTypesModelView object, EpoxyModel previousModel) { + if (!(previousModel instanceof AllTypesModelViewModel_)) { + bind(object); + return; + } + AllTypesModelViewModel_ that = (AllTypesModelViewModel_) previousModel; + super.bind(object); + + if ((stringValue_String != null ? !stringValue_String.equals(that.stringValue_String) : that.stringValue_String != null)) { + object.setStringValue(stringValue_String); + } + + if (((onClickListener_OnClickListener == null) != (that.onClickListener_OnClickListener == null))) { + object.setOnClickListener(onClickListener_OnClickListener); + } + + if ((intValue_Int != that.intValue_Int)) { + object.setIntValue(intValue_Int); + } + + if ((booleanValue_Boolean != that.booleanValue_Boolean)) { + object.setBooleanValue(booleanValue_Boolean); + } + + if ((Double.compare(that.doubleValue_Double, doubleValue_Double) != 0)) { + object.setDoubleValue(doubleValue_Double); + } + + if (((drawable_Drawable == null) != (that.drawable_Drawable == null))) { + object.setDrawable(drawable_Drawable); + } + + if ((stringList_List != null ? !stringList_List.equals(that.stringList_List) : that.stringList_List != null)) { + object.setStringList(stringList_List); + } + } + + @Override + public void handlePostBind(final AllTypesModelView object, int position) { + if (onModelBoundListener_epoxyGeneratedModel != null) { + onModelBoundListener_epoxyGeneratedModel.onModelBound(this, object, position); + } + validateStateHasNotChangedSinceAdded("The model was changed during the bind call.", position); + } + + /** + * Register a listener that will be called when this model is bound to a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public AllTypesModelViewModel_ onBind(OnModelBoundListener listener) { + onMutation(); + this.onModelBoundListener_epoxyGeneratedModel = listener; + return this; + } + + @Override + public void unbind(AllTypesModelView object) { + super.unbind(object); + if (onModelUnboundListener_epoxyGeneratedModel != null) { + onModelUnboundListener_epoxyGeneratedModel.onModelUnbound(this, object); + } + } + + /** + * Register a listener that will be called when this model is unbound from a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public AllTypesModelViewModel_ onUnbind(OnModelUnboundListener listener) { + onMutation(); + this.onModelUnboundListener_epoxyGeneratedModel = listener; + return this; + } + + /** + * Optional: Default value is false + * + * @see AllTypesModelView#setBooleanValue(boolean) + */ + public AllTypesModelViewModel_ booleanValue(boolean booleanValue) { + assignedAttributes_epoxyGeneratedModel.set(0); + onMutation(); + this.booleanValue_Boolean = booleanValue; + return this; + } + + public boolean booleanValue() { + return booleanValue_Boolean; + } + + /** + * Optional: Default value is 0.0d + * + * @see AllTypesModelView#setDoubleValue(double) + */ + public AllTypesModelViewModel_ doubleValue(double doubleValue) { + assignedAttributes_epoxyGeneratedModel.set(1); + onMutation(); + this.doubleValue_Double = doubleValue; + return this; + } + + public double doubleValue() { + return doubleValue_Double; + } + + /** + * Required. + * + * @see AllTypesModelView#setDrawable(Drawable) + */ + public AllTypesModelViewModel_ drawable(@NonNull Drawable drawable) { + if (drawable == null) { + throw new IllegalArgumentException("drawable cannot be null"); + } + assignedAttributes_epoxyGeneratedModel.set(2); + onMutation(); + this.drawable_Drawable = drawable; + return this; + } + + @NonNull + public Drawable drawable() { + return drawable_Drawable; + } + + /** + * Optional: Default value is 0 + * + * @see AllTypesModelView#setIntValue(int) + */ + public AllTypesModelViewModel_ intValue(int intValue) { + assignedAttributes_epoxyGeneratedModel.set(3); + onMutation(); + this.intValue_Int = intValue; + return this; + } + + public int intValue() { + return intValue_Int; + } + + /** + * Set a click listener that will provide the parent view, model, and adapter position of the clicked view. This will clear the normal View.OnClickListener if one has been set */ + @NonNull + public AllTypesModelViewModel_ onClickListener(final OnModelClickListener onClickListener) { + assignedAttributes_epoxyGeneratedModel.set(4); + onMutation(); + if (onClickListener == null) { + this.onClickListener_OnClickListener = null; + } + else { + this.onClickListener_OnClickListener = new WrappedEpoxyModelClickListener(onClickListener); + } + return this; + } + + /** + * Required. + * + * @see AllTypesModelView#setOnClickListener(View.OnClickListener) + */ + public AllTypesModelViewModel_ onClickListener(@NonNull View.OnClickListener onClickListener) { + if (onClickListener == null) { + throw new IllegalArgumentException("onClickListener cannot be null"); + } + assignedAttributes_epoxyGeneratedModel.set(4); + onMutation(); + this.onClickListener_OnClickListener = onClickListener; + return this; + } + + @NonNull + public View.OnClickListener onClickListener() { + return onClickListener_OnClickListener; + } + + /** + * Required. + * + * @see AllTypesModelView#setStringValue(String) + */ + public AllTypesModelViewModel_ stringValue(@NonNull String stringValue) { + if (stringValue == null) { + throw new IllegalArgumentException("stringValue cannot be null"); + } + assignedAttributes_epoxyGeneratedModel.set(5); + onMutation(); + this.stringValue_String = stringValue; + return this; + } + + @NonNull + public String stringValue() { + return stringValue_String; + } + + /** + * Required. + * + * @see AllTypesModelView#setStringList(List) + */ + public AllTypesModelViewModel_ stringList(@NonNull List stringList) { + if (stringList == null) { + throw new IllegalArgumentException("stringList cannot be null"); + } + assignedAttributes_epoxyGeneratedModel.set(6); + onMutation(); + this.stringList_List = stringList; + return this; + } + + @NonNull + public List stringList() { + return stringList_List; + } + + @Override + public AllTypesModelViewModel_ id(long id) { + super.id(id); + return this; + } + + @Override + public AllTypesModelViewModel_ id(@NonNull Number... arg0) { + super.id(arg0); + return this; + } + + @Override + public AllTypesModelViewModel_ id(long id1, long id2) { + super.id(id1, id2); + return this; + } + + @Override + public AllTypesModelViewModel_ id(@NonNull CharSequence arg0) { + super.id(arg0); + return this; + } + + @Override + public AllTypesModelViewModel_ id(@NonNull CharSequence arg0, @NonNull CharSequence... arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public AllTypesModelViewModel_ id(@NonNull CharSequence arg0, long arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public AllTypesModelViewModel_ layout(@LayoutRes int arg0) { + super.layout(arg0); + return this; + } + + @Override + public AllTypesModelViewModel_ spanSizeOverride(@Nullable EpoxyModel.SpanSizeOverrideCallback arg0) { + super.spanSizeOverride(arg0); + return this; + } + + @Override + public AllTypesModelViewModel_ show() { + super.show(); + return this; + } + + @Override + public AllTypesModelViewModel_ show(boolean show) { + super.show(show); + return this; + } + + @Override + public AllTypesModelViewModel_ hide() { + super.hide(); + return this; + } + + @Override + @LayoutRes + protected int getDefaultLayout() { + return 1; + } + + @Override + public AllTypesModelViewModel_ reset() { + onModelBoundListener_epoxyGeneratedModel = null; + onModelUnboundListener_epoxyGeneratedModel = null; + assignedAttributes_epoxyGeneratedModel.clear(); + this.booleanValue_Boolean = false; + this.doubleValue_Double = 0.0d; + this.drawable_Drawable = null; + this.intValue_Int = 0; + this.onClickListener_OnClickListener = null; + this.stringValue_String = null; + this.stringList_List = null; + super.reset(); + return this; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof AllTypesModelViewModel_)) { + return false; + } + if (!super.equals(o)) { + return false; + } + AllTypesModelViewModel_ that = (AllTypesModelViewModel_) o; + if (((onModelBoundListener_epoxyGeneratedModel == null) != (that.onModelBoundListener_epoxyGeneratedModel == null))) { + return false; + } + if (((onModelUnboundListener_epoxyGeneratedModel == null) != (that.onModelUnboundListener_epoxyGeneratedModel == null))) { + return false; + } + if ((booleanValue_Boolean != that.booleanValue_Boolean)) { + return false; + } + if ((Double.compare(that.doubleValue_Double, doubleValue_Double) != 0)) { + return false; + } + if (((drawable_Drawable == null) != (that.drawable_Drawable == null))) { + return false; + } + if ((intValue_Int != that.intValue_Int)) { + return false; + } + if (((onClickListener_OnClickListener == null) != (that.onClickListener_OnClickListener == null))) { + return false; + } + if ((stringValue_String != null ? !stringValue_String.equals(that.stringValue_String) : that.stringValue_String != null)) { + return false; + } + if ((stringList_List != null ? !stringList_List.equals(that.stringList_List) : that.stringList_List != null)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (onModelBoundListener_epoxyGeneratedModel != null ? 1 : 0); + result = 31 * result + (onModelUnboundListener_epoxyGeneratedModel != null ? 1 : 0); + long temp; + result = 31 * result + (booleanValue_Boolean ? 1 : 0); + temp = Double.doubleToLongBits(doubleValue_Double); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + (drawable_Drawable != null ? 1 : 0); + result = 31 * result + intValue_Int; + result = 31 * result + (onClickListener_OnClickListener != null ? 1 : 0); + result = 31 * result + (stringValue_String != null ? stringValue_String.hashCode() : 0); + result = 31 * result + (stringList_List != null ? stringList_List.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "AllTypesModelViewModel_{" + + "booleanValue_Boolean=" + booleanValue_Boolean + + ", doubleValue_Double=" + doubleValue_Double + + ", drawable_Drawable=" + drawable_Drawable + + ", intValue_Int=" + intValue_Int + + ", onClickListener_OnClickListener=" + onClickListener_OnClickListener + + ", stringValue_String=" + stringValue_String + + ", stringList_List=" + stringList_List + + "}" + super.toString(); + } + + public static AllTypesModelViewModel_ from(ModelProperties properties) { + AllTypesModelViewModel_ model = new AllTypesModelViewModel_(); + model.id(properties.getString("id")); + if (properties.has("booleanValue")) { + model.booleanValue(properties.getBoolean("booleanValue")); + } + if (properties.has("doubleValue")) { + model.doubleValue(properties.getDouble("doubleValue")); + } + if (properties.has("drawable")) { + model.drawable(properties.getDrawable("drawable")); + } + if (properties.has("intValue")) { + model.intValue(properties.getInt("intValue")); + } + if (properties.has("onClickListener")) { + model.onClickListener(properties.getOnClickListener("onClickListener")); + } + if (properties.has("stringValue")) { + model.stringValue(properties.getString("stringValue")); + } + if (properties.has("stringList")) { + model.stringList(properties.getStringList("stringList")); + } + return model; + } + + @Override + public int getSpanSize(int totalSpanCount, int position, int itemCount) { + return totalSpanCount; + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/BaseModelView.java b/epoxy-modelfactory/src/test/resources/BaseModelView.java new file mode 100644 index 0000000000..995c16864a --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/BaseModelView.java @@ -0,0 +1,17 @@ +package com.airbnb.epoxy; + +import android.content.Context; +import android.widget.FrameLayout; + +@ModelView(defaultLayout = 1) +public class BaseModelView extends FrameLayout { + + public BaseModelView(Context context) { + super(context); + } + + @ModelProp + public void setTitle(String title) { + + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/BaseModelViewModel_.java b/epoxy-modelfactory/src/test/resources/BaseModelViewModel_.java new file mode 100644 index 0000000000..2d0c4258d9 --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/BaseModelViewModel_.java @@ -0,0 +1,261 @@ +package com.airbnb.epoxy; + +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import java.lang.CharSequence; +import java.lang.IllegalArgumentException; +import java.lang.IllegalStateException; +import java.lang.Number; +import java.lang.Object; +import java.lang.Override; +import java.lang.String; +import java.util.BitSet; + +/** + * Generated file. Do not modify! */ +public class BaseModelViewModel_ extends EpoxyModel implements GeneratedModel, BaseModelViewModelBuilder { + private final BitSet assignedAttributes_epoxyGeneratedModel = new BitSet(1); + + private OnModelBoundListener onModelBoundListener_epoxyGeneratedModel; + + private OnModelUnboundListener onModelUnboundListener_epoxyGeneratedModel; + + /** + * Bitset index: 0 */ + @NonNull + private String title_String; + + @Override + public void addTo(EpoxyController controller) { + super.addTo(controller); + addWithDebugValidation(controller); + if (!assignedAttributes_epoxyGeneratedModel.get(0)) { + throw new IllegalStateException("A value is required for setTitle"); + } + } + + @Override + public void handlePreBind(final EpoxyViewHolder holder, final BaseModelView object, + final int position) { + validateStateHasNotChangedSinceAdded("The model was changed between being added to the controller and being bound.", position); + } + + @Override + public void bind(final BaseModelView object) { + super.bind(object); + object.setTitle(title_String); + } + + @Override + public void bind(final BaseModelView object, EpoxyModel previousModel) { + if (!(previousModel instanceof BaseModelViewModel_)) { + bind(object); + return; + } + BaseModelViewModel_ that = (BaseModelViewModel_) previousModel; + super.bind(object); + + if ((title_String != null ? !title_String.equals(that.title_String) : that.title_String != null)) { + object.setTitle(title_String); + } + } + + @Override + public void handlePostBind(final BaseModelView object, int position) { + if (onModelBoundListener_epoxyGeneratedModel != null) { + onModelBoundListener_epoxyGeneratedModel.onModelBound(this, object, position); + } + validateStateHasNotChangedSinceAdded("The model was changed during the bind call.", position); + } + + /** + * Register a listener that will be called when this model is bound to a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public BaseModelViewModel_ onBind(OnModelBoundListener listener) { + onMutation(); + this.onModelBoundListener_epoxyGeneratedModel = listener; + return this; + } + + @Override + public void unbind(BaseModelView object) { + super.unbind(object); + if (onModelUnboundListener_epoxyGeneratedModel != null) { + onModelUnboundListener_epoxyGeneratedModel.onModelUnbound(this, object); + } + } + + /** + * Register a listener that will be called when this model is unbound from a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public BaseModelViewModel_ onUnbind(OnModelUnboundListener listener) { + onMutation(); + this.onModelUnboundListener_epoxyGeneratedModel = listener; + return this; + } + + /** + * Required. + * + * @see BaseModelView#setTitle(String) + */ + public BaseModelViewModel_ title(@NonNull String title) { + if (title == null) { + throw new IllegalArgumentException("title cannot be null"); + } + assignedAttributes_epoxyGeneratedModel.set(0); + onMutation(); + this.title_String = title; + return this; + } + + @NonNull + public String title() { + return title_String; + } + + @Override + public BaseModelViewModel_ id(long id) { + super.id(id); + return this; + } + + @Override + public BaseModelViewModel_ id(@NonNull Number... arg0) { + super.id(arg0); + return this; + } + + @Override + public BaseModelViewModel_ id(long id1, long id2) { + super.id(id1, id2); + return this; + } + + @Override + public BaseModelViewModel_ id(@NonNull CharSequence arg0) { + super.id(arg0); + return this; + } + + @Override + public BaseModelViewModel_ id(@NonNull CharSequence arg0, @NonNull CharSequence... arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public BaseModelViewModel_ id(@NonNull CharSequence arg0, long arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public BaseModelViewModel_ layout(@LayoutRes int arg0) { + super.layout(arg0); + return this; + } + + @Override + public BaseModelViewModel_ spanSizeOverride(@Nullable EpoxyModel.SpanSizeOverrideCallback arg0) { + super.spanSizeOverride(arg0); + return this; + } + + @Override + public BaseModelViewModel_ show() { + super.show(); + return this; + } + + @Override + public BaseModelViewModel_ show(boolean show) { + super.show(show); + return this; + } + + @Override + public BaseModelViewModel_ hide() { + super.hide(); + return this; + } + + @Override + @LayoutRes + protected int getDefaultLayout() { + return 1; + } + + @Override + public BaseModelViewModel_ reset() { + onModelBoundListener_epoxyGeneratedModel = null; + onModelUnboundListener_epoxyGeneratedModel = null; + assignedAttributes_epoxyGeneratedModel.clear(); + this.title_String = null; + super.reset(); + return this; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof BaseModelViewModel_)) { + return false; + } + if (!super.equals(o)) { + return false; + } + BaseModelViewModel_ that = (BaseModelViewModel_) o; + if (((onModelBoundListener_epoxyGeneratedModel == null) != (that.onModelBoundListener_epoxyGeneratedModel == null))) { + return false; + } + if (((onModelUnboundListener_epoxyGeneratedModel == null) != (that.onModelUnboundListener_epoxyGeneratedModel == null))) { + return false; + } + if ((title_String != null ? !title_String.equals(that.title_String) : that.title_String != null)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (onModelBoundListener_epoxyGeneratedModel != null ? 1 : 0); + result = 31 * result + (onModelUnboundListener_epoxyGeneratedModel != null ? 1 : 0); + result = 31 * result + (title_String != null ? title_String.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "BaseModelViewModel_{" + + "title_String=" + title_String + + "}" + super.toString(); + } + + public static BaseModelViewModel_ from(ModelProperties properties) { + BaseModelViewModel_ model = new BaseModelViewModel_(); + model.id(properties.getString("id")); + if (properties.has("title")) { + model.title(properties.getString("title")); + } + return model; + } + + @Override + public int getSpanSize(int totalSpanCount, int position, int itemCount) { + return totalSpanCount; + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/CallbackPropModelView.java b/epoxy-modelfactory/src/test/resources/CallbackPropModelView.java new file mode 100644 index 0000000000..d5a86457de --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/CallbackPropModelView.java @@ -0,0 +1,18 @@ +package com.airbnb.epoxy; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.widget.FrameLayout; + +@ModelView(defaultLayout = 1) +public class CallbackPropModelView extends FrameLayout { + + public CallbackPropModelView(Context context) { + super(context); + } + + @CallbackProp + public void setOnClickListener(@Nullable OnClickListener listener) { + + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/CallbackPropModelViewModel_.java b/epoxy-modelfactory/src/test/resources/CallbackPropModelViewModel_.java new file mode 100644 index 0000000000..b8071df576 --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/CallbackPropModelViewModel_.java @@ -0,0 +1,270 @@ +package com.airbnb.epoxy; + +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.View; +import java.lang.CharSequence; +import java.lang.Number; +import java.lang.Object; +import java.lang.Override; +import java.lang.String; +import java.util.BitSet; + +/** + * Generated file. Do not modify! */ +public class CallbackPropModelViewModel_ extends EpoxyModel implements GeneratedModel, CallbackPropModelViewModelBuilder { + private final BitSet assignedAttributes_epoxyGeneratedModel = new BitSet(1); + + private OnModelBoundListener onModelBoundListener_epoxyGeneratedModel; + + private OnModelUnboundListener onModelUnboundListener_epoxyGeneratedModel; + + /** + * Bitset index: 0 */ + @Nullable + private View.OnClickListener onClickListener_OnClickListener = (View.OnClickListener) null; + + @Override + public void addTo(EpoxyController controller) { + super.addTo(controller); + addWithDebugValidation(controller); + } + + @Override + public void handlePreBind(final EpoxyViewHolder holder, final CallbackPropModelView object, + final int position) { + validateStateHasNotChangedSinceAdded("The model was changed between being added to the controller and being bound.", position); + } + + @Override + public void bind(final CallbackPropModelView object) { + super.bind(object); + object.setOnClickListener(onClickListener_OnClickListener); + } + + @Override + public void bind(final CallbackPropModelView object, EpoxyModel previousModel) { + if (!(previousModel instanceof CallbackPropModelViewModel_)) { + bind(object); + return; + } + CallbackPropModelViewModel_ that = (CallbackPropModelViewModel_) previousModel; + super.bind(object); + + if (((onClickListener_OnClickListener == null) != (that.onClickListener_OnClickListener == null))) { + object.setOnClickListener(onClickListener_OnClickListener); + } + } + + @Override + public void handlePostBind(final CallbackPropModelView object, int position) { + if (onModelBoundListener_epoxyGeneratedModel != null) { + onModelBoundListener_epoxyGeneratedModel.onModelBound(this, object, position); + } + validateStateHasNotChangedSinceAdded("The model was changed during the bind call.", position); + } + + /** + * Register a listener that will be called when this model is bound to a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public CallbackPropModelViewModel_ onBind(OnModelBoundListener listener) { + onMutation(); + this.onModelBoundListener_epoxyGeneratedModel = listener; + return this; + } + + @Override + public void unbind(CallbackPropModelView object) { + super.unbind(object); + if (onModelUnboundListener_epoxyGeneratedModel != null) { + onModelUnboundListener_epoxyGeneratedModel.onModelUnbound(this, object); + } + object.setOnClickListener((View.OnClickListener) null); + } + + /** + * Register a listener that will be called when this model is unbound from a view. + *

+ * The listener will contribute to this model's hashCode state per the {@link + * com.airbnb.epoxy.EpoxyAttribute.Option#DoNotHash} rules. + *

+ * You may clear the listener by setting a null value, or by calling {@link #reset()} */ + public CallbackPropModelViewModel_ onUnbind(OnModelUnboundListener listener) { + onMutation(); + this.onModelUnboundListener_epoxyGeneratedModel = listener; + return this; + } + + /** + * Set a click listener that will provide the parent view, model, and adapter position of the clicked view. This will clear the normal View.OnClickListener if one has been set */ + @Nullable + public CallbackPropModelViewModel_ onClickListener(final OnModelClickListener onClickListener) { + assignedAttributes_epoxyGeneratedModel.set(0); + onMutation(); + if (onClickListener == null) { + this.onClickListener_OnClickListener = null; + } + else { + this.onClickListener_OnClickListener = new WrappedEpoxyModelClickListener(onClickListener); + } + return this; + } + + /** + * Optional: Default value is (View.OnClickListener) null + * + * @see CallbackPropModelView#setOnClickListener(View.OnClickListener) + */ + public CallbackPropModelViewModel_ onClickListener(@Nullable View.OnClickListener onClickListener) { + assignedAttributes_epoxyGeneratedModel.set(0); + onMutation(); + this.onClickListener_OnClickListener = onClickListener; + return this; + } + + @Nullable + public View.OnClickListener onClickListener() { + return onClickListener_OnClickListener; + } + + @Override + public CallbackPropModelViewModel_ id(long id) { + super.id(id); + return this; + } + + @Override + public CallbackPropModelViewModel_ id(@NonNull Number... arg0) { + super.id(arg0); + return this; + } + + @Override + public CallbackPropModelViewModel_ id(long id1, long id2) { + super.id(id1, id2); + return this; + } + + @Override + public CallbackPropModelViewModel_ id(@NonNull CharSequence arg0) { + super.id(arg0); + return this; + } + + @Override + public CallbackPropModelViewModel_ id(@NonNull CharSequence arg0, @NonNull CharSequence... arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public CallbackPropModelViewModel_ id(@NonNull CharSequence arg0, long arg1) { + super.id(arg0, arg1); + return this; + } + + @Override + public CallbackPropModelViewModel_ layout(@LayoutRes int arg0) { + super.layout(arg0); + return this; + } + + @Override + public CallbackPropModelViewModel_ spanSizeOverride(@Nullable EpoxyModel.SpanSizeOverrideCallback arg0) { + super.spanSizeOverride(arg0); + return this; + } + + @Override + public CallbackPropModelViewModel_ show() { + super.show(); + return this; + } + + @Override + public CallbackPropModelViewModel_ show(boolean show) { + super.show(show); + return this; + } + + @Override + public CallbackPropModelViewModel_ hide() { + super.hide(); + return this; + } + + @Override + @LayoutRes + protected int getDefaultLayout() { + return 1; + } + + @Override + public CallbackPropModelViewModel_ reset() { + onModelBoundListener_epoxyGeneratedModel = null; + onModelUnboundListener_epoxyGeneratedModel = null; + assignedAttributes_epoxyGeneratedModel.clear(); + this.onClickListener_OnClickListener = (View.OnClickListener) null; + super.reset(); + return this; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof CallbackPropModelViewModel_)) { + return false; + } + if (!super.equals(o)) { + return false; + } + CallbackPropModelViewModel_ that = (CallbackPropModelViewModel_) o; + if (((onModelBoundListener_epoxyGeneratedModel == null) != (that.onModelBoundListener_epoxyGeneratedModel == null))) { + return false; + } + if (((onModelUnboundListener_epoxyGeneratedModel == null) != (that.onModelUnboundListener_epoxyGeneratedModel == null))) { + return false; + } + if (((onClickListener_OnClickListener == null) != (that.onClickListener_OnClickListener == null))) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (onModelBoundListener_epoxyGeneratedModel != null ? 1 : 0); + result = 31 * result + (onModelUnboundListener_epoxyGeneratedModel != null ? 1 : 0); + result = 31 * result + (onClickListener_OnClickListener != null ? 1 : 0); + return result; + } + + @Override + public String toString() { + return "CallbackPropModelViewModel_{" + + "onClickListener_OnClickListener=" + onClickListener_OnClickListener + + "}" + super.toString(); + } + + public static CallbackPropModelViewModel_ from(ModelProperties properties) { + CallbackPropModelViewModel_ model = new CallbackPropModelViewModel_(); + model.id(properties.getString("id")); + if (properties.has("onClickListener")) { + model.onClickListener(properties.getOnClickListener("onClickListener")); + } + return model; + } + + @Override + public int getSpanSize(int totalSpanCount, int position, int itemCount) { + return totalSpanCount; + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/StyleableModelView.java b/epoxy-modelfactory/src/test/resources/StyleableModelView.java new file mode 100644 index 0000000000..dd163cf94f --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/StyleableModelView.java @@ -0,0 +1,20 @@ +package com.airbnb.epoxy; + +import android.content.Context; +import android.widget.FrameLayout; + +import com.airbnb.paris.annotations.Styleable; + +@Styleable +@ModelView +public class StyleableModelView extends FrameLayout { + + public StyleableModelView(Context context) { + super(context); + } + + @ModelProp + public void setTitle(String title) { + + } +} \ No newline at end of file diff --git a/epoxy-modelfactory/src/test/resources/StyleableModelViewModel_.java b/epoxy-modelfactory/src/test/resources/StyleableModelViewModel_.java new file mode 100644 index 0000000000..f981a90c86 --- /dev/null +++ b/epoxy-modelfactory/src/test/resources/StyleableModelViewModel_.java @@ -0,0 +1,348 @@ +package com.airbnb.epoxy; + +import android.os.AsyncTask; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.ViewGroup; +import com.airbnb.paris.StyleApplierUtils; +import com.airbnb.paris.styles.Style; +import com.airbnb.viewmodeladapter.R; +import java.lang.AssertionError; +import java.lang.CharSequence; +import java.lang.IllegalArgumentException; +import java.lang.IllegalStateException; +import java.lang.Number; +import java.lang.Object; +import java.lang.Override; +import java.lang.Runnable; +import java.lang.String; +import java.lang.UnsupportedOperationException; +import java.lang.ref.WeakReference; +import java.util.BitSet; +import java.util.Objects; + +/** + * Generated file. Do not modify! */ +public class StyleableModelViewModel_ extends EpoxyModel implements GeneratedModel, StyleableModelViewModelBuilder { + private static final Style DEFAULT_PARIS_STYLE = new StyleableModelViewStyleApplier.StyleBuilder().addDefault().build(); + + private static WeakReference