diff --git a/tools/data-binding/TestApp/build.gradle b/tools/data-binding/TestApp/build.gradle index 30ab4d8ee4d8d..30ae0db383f0a 100644 --- a/tools/data-binding/TestApp/build.gradle +++ b/tools/data-binding/TestApp/build.gradle @@ -59,7 +59,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.databinding:library:0.3-SNAPSHOT' + compile project(":library") compile "com.android.support:support-v4:+" - provided 'com.android.databinding:annotationprocessor:0.3-SNAPSHOT' + provided project(":annotationprocessor") } diff --git a/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java b/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java new file mode 100644 index 0000000000000..e7f430e5be2d7 --- /dev/null +++ b/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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 com.android.databinding.testapp; + +import com.android.databinding.library.PropertyChangeRegistry; +import com.android.databinding.testapp.generated.BasicBindingBinder; + +import android.binding.Observable; +import android.binding.OnPropertyChangedListener; +import android.util.ArrayMap; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashSet; + +public class ProcessBindableTest extends BaseDataBinderTest { + private static String[] EXPECTED_BINDING_NAMES = { + "bindableField1", + "bindableField2", + "bindableField3", + "bindableField4", + "mbindableField5", + "bindableField6", + "bindableField7", + "bindableField8", + }; + + public ProcessBindableTest() { + super(BasicBindingBinder.class, R.layout.basic_binding); + } + + public void testFieldsGenerated() throws IllegalAccessException { + Field[] fields = android.binding.BR.class.getFields(); + + ArrayMap fieldValues = new ArrayMap<>(); + int modifiers = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; + for (Field field: fields) { + assertTrue(field.getModifiers() == modifiers); + String name = field.getName(); + fieldValues.put(name, field.getInt(null)); + } + + assertTrue(fieldValues.containsKey("_all")); + assertEquals(0, (int) fieldValues.get("_all")); + HashSet values = new HashSet<>(); + values.add(0); + + for (String fieldName : EXPECTED_BINDING_NAMES) { + assertTrue("missing field: " + fieldName, fieldValues.containsKey(fieldName)); + assertFalse(values.contains(fieldValues.get(fieldName))); + values.add(fieldValues.get(fieldName)); + } + } +} diff --git a/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ViewBindingAdapterTest.java b/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ViewBindingAdapterTest.java new file mode 100644 index 0000000000000..7d9b8ae9dfab1 --- /dev/null +++ b/tools/data-binding/TestApp/src/androidTest/java/com/android/databinding/testapp/ViewBindingAdapterTest.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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 com.android.databinding.testapp; + +import com.android.databinding.testapp.generated.ViewAdapterTestBinder; +import com.android.databinding.testapp.vo.ViewBindingObject; + +import android.content.res.ColorStateList; +import android.os.Build; +import android.view.View; + +public class ViewBindingAdapterTest extends BaseDataBinderTest { + + ViewBindingObject mViewBindingObject = new ViewBindingObject(); + + public ViewBindingAdapterTest() { + super(ViewAdapterTestBinder.class, R.layout.view_adapter_test); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mBinder.setViewBinding(mViewBindingObject); + mBinder.rebindDirty(); + } + + private void changeValues() throws Throwable { + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mViewBindingObject.changeValues(); + mBinder.rebindDirty(); + } + }); + } + + public void testPadding() throws Throwable { + View view = mBinder.getPadding(); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingBottom()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingTop()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingRight()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingLeft()); + + changeValues(); + + assertEquals(mViewBindingObject.getPadding(), view.getPaddingBottom()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingTop()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingRight()); + assertEquals(mViewBindingObject.getPadding(), view.getPaddingLeft()); + } + + public void testPaddingLeftRight() throws Throwable { + View view = mBinder.getPaddingLeftRight(); + assertEquals(mViewBindingObject.getPaddingLeft(), view.getPaddingLeft()); + assertEquals(mViewBindingObject.getPaddingRight(), view.getPaddingRight()); + + changeValues(); + + assertEquals(mViewBindingObject.getPaddingLeft(), view.getPaddingLeft()); + assertEquals(mViewBindingObject.getPaddingRight(), view.getPaddingRight()); + } + + public void testPaddingStartEnd() throws Throwable { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + View view = mBinder.getPaddingStartEnd(); + assertEquals(mViewBindingObject.getPaddingStart(), view.getPaddingStart()); + assertEquals(mViewBindingObject.getPaddingEnd(), view.getPaddingEnd()); + + changeValues(); + + assertEquals(mViewBindingObject.getPaddingStart(), view.getPaddingStart()); + assertEquals(mViewBindingObject.getPaddingEnd(), view.getPaddingEnd()); + } + } + + public void testPaddingTopBottom() throws Throwable { + View view = mBinder.getPaddingTopBottom(); + assertEquals(mViewBindingObject.getPaddingTop(), view.getPaddingTop()); + assertEquals(mViewBindingObject.getPaddingBottom(), view.getPaddingBottom()); + + changeValues(); + + assertEquals(mViewBindingObject.getPaddingTop(), view.getPaddingTop()); + assertEquals(mViewBindingObject.getPaddingBottom(), view.getPaddingBottom()); + } + + public void testBackgroundTint() throws Throwable { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + View view = mBinder.getBackgroundTint(); + assertNotNull(view.getBackgroundTintList()); + ColorStateList colorStateList = view.getBackgroundTintList(); + assertEquals(mViewBindingObject.getBackgroundTint(), colorStateList.getDefaultColor()); + + changeValues(); + + assertNotNull(view.getBackgroundTintList()); + colorStateList = view.getBackgroundTintList(); + assertEquals(mViewBindingObject.getBackgroundTint(), colorStateList.getDefaultColor()); + } + } + + public void testFadeScrollbars() throws Throwable { + View view = mBinder.getFadeScrollbars(); + assertEquals(mViewBindingObject.getFadeScrollbars(), view.isScrollbarFadingEnabled()); + + changeValues(); + + assertEquals(mViewBindingObject.getFadeScrollbars(), view.isScrollbarFadingEnabled()); + } + + public void testNextFocus() throws Throwable { + View view = mBinder.getNextFocus(); + + assertEquals(mViewBindingObject.getNextFocusDown(), view.getNextFocusDownId()); + assertEquals(mViewBindingObject.getNextFocusUp(), view.getNextFocusUpId()); + assertEquals(mViewBindingObject.getNextFocusLeft(), view.getNextFocusLeftId()); + assertEquals(mViewBindingObject.getNextFocusRight(), view.getNextFocusRightId()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + assertEquals(mViewBindingObject.getNextFocusForward(), view.getNextFocusForwardId()); + } + + changeValues(); + + assertEquals(mViewBindingObject.getNextFocusDown(), view.getNextFocusDownId()); + assertEquals(mViewBindingObject.getNextFocusUp(), view.getNextFocusUpId()); + assertEquals(mViewBindingObject.getNextFocusLeft(), view.getNextFocusLeftId()); + assertEquals(mViewBindingObject.getNextFocusRight(), view.getNextFocusRightId()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + assertEquals(mViewBindingObject.getNextFocusForward(), view.getNextFocusForwardId()); + } + } + + public void testRequiresFadingEdge() throws Throwable { + View view = mBinder.getRequiresFadingEdge(); + + assertTrue(view.isVerticalFadingEdgeEnabled()); + assertFalse(view.isHorizontalFadingEdgeEnabled()); + + changeValues(); + + assertFalse(view.isVerticalFadingEdgeEnabled()); + assertTrue(view.isHorizontalFadingEdgeEnabled()); + } + + public void testScrollbar() throws Throwable { + View view = mBinder.getScrollbar(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + assertEquals(mViewBindingObject.getScrollbarDefaultDelayBeforeFade(), + view.getScrollBarDefaultDelayBeforeFade()); + assertEquals(mViewBindingObject.getScrollbarFadeDuration(), view.getScrollBarFadeDuration()); + assertEquals(mViewBindingObject.getScrollbarSize(), view.getScrollBarSize()); + } + assertEquals(mViewBindingObject.getScrollbarStyle(), view.getScrollBarStyle()); + + changeValues(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + assertEquals(mViewBindingObject.getScrollbarDefaultDelayBeforeFade(), + view.getScrollBarDefaultDelayBeforeFade()); + assertEquals(mViewBindingObject.getScrollbarFadeDuration(), view.getScrollBarFadeDuration()); + assertEquals(mViewBindingObject.getScrollbarSize(), view.getScrollBarSize()); + } + assertEquals(mViewBindingObject.getScrollbarStyle(), view.getScrollBarStyle()); + } + + public void testTransformPivot() throws Throwable { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + View view = mBinder.getTransformPivot(); + + assertEquals(mViewBindingObject.getTransformPivotX(), view.getPivotX()); + assertEquals(mViewBindingObject.getTransformPivotY(), view.getPivotY()); + + changeValues(); + + assertEquals(mViewBindingObject.getTransformPivotX(), view.getPivotX()); + assertEquals(mViewBindingObject.getTransformPivotY(), view.getPivotY()); + } + } +} diff --git a/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/BindableTestObject.java b/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/BindableTestObject.java new file mode 100644 index 0000000000000..63ef9c1f9c8d2 --- /dev/null +++ b/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/BindableTestObject.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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 com.android.databinding.testapp.vo; + +import android.binding.Bindable; + +public class BindableTestObject { + @Bindable + public int bindableField1; + + @Bindable + private int bindableField2; + + private int bindableField3; + + @Bindable + public int m_bindableField4; + + @Bindable + public int mbindableField5; + + @Bindable + public int _bindableField6; + + @Bindable + public int _BindableField7; + + @Bindable + public int mBindableField8; + + public int getBindableField2() { + return bindableField2; + } + + @Bindable + public int getBindableField3() { + return bindableField3; + } +} diff --git a/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/ViewBindingObject.java b/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/ViewBindingObject.java new file mode 100644 index 0000000000000..1d29ba80998f2 --- /dev/null +++ b/tools/data-binding/TestApp/src/main/java/com/android/databinding/testapp/vo/ViewBindingObject.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * 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 com.android.databinding.testapp.vo; + +import com.android.databinding.library.BaseObservable; +import com.android.databinding.testapp.R; + +import android.binding.Bindable; +import android.binding.adapters.ViewBindingAdapter; +import android.view.View; + +public class ViewBindingObject extends BaseObservable { + @Bindable + private int mBackgroundTint = 0xFF00FF00; + @Bindable + private boolean mFadeScrollbars = false; + @Bindable + private int mNextFocusForward = R.id.padding; + @Bindable + private int mNextFocusLeft = R.id.paddingStartEnd; + @Bindable + private int mNextFocusRight = R.id.paddingTopBottom; + @Bindable + private int mNextFocusUp = R.id.backgroundTint; + @Bindable + private int mNextFocusDown = R.id.fadeScrollbars; + @Bindable + private int mRequiresFadingEdge = ViewBindingAdapter.FADING_EDGE_VERTICAL; + @Bindable + private int mScrollbarDefaultDelayBeforeFade = 300; + @Bindable + private int mScrollbarFadeDuration = 400; + @Bindable + private int mScrollbarSize = 10; + @Bindable + private int mScrollbarStyle = View.SCROLLBARS_INSIDE_OVERLAY; + @Bindable + private float mTransformPivotX = 9; + @Bindable + private float mTransformPivotY = 8; + @Bindable + private int mPadding = 11; + @Bindable + private int mPaddingBottom = 12; + @Bindable + private int mPaddingTop = 13; + @Bindable + private int mPaddingLeft = 14; + @Bindable + private int mPaddingRight = 15; + @Bindable + private int mPaddingStart = 16; + @Bindable + private int mPaddingEnd = 17; + + public int getBackgroundTint() { + return mBackgroundTint; + } + + public int getScrollbarFadeDuration() { + return mScrollbarFadeDuration; + } + + public boolean getFadeScrollbars() { + return mFadeScrollbars; + } + + public int getNextFocusDown() { + return mNextFocusDown; + } + + public int getNextFocusForward() { + return mNextFocusForward; + } + + public int getNextFocusLeft() { + return mNextFocusLeft; + } + + public int getNextFocusRight() { + return mNextFocusRight; + } + + public int getNextFocusUp() { + return mNextFocusUp; + } + + public int getRequiresFadingEdge() { + return mRequiresFadingEdge; + } + + public int getScrollbarDefaultDelayBeforeFade() { + return mScrollbarDefaultDelayBeforeFade; + } + + public int getScrollbarSize() { + return mScrollbarSize; + } + + public int getScrollbarStyle() { + return mScrollbarStyle; + } + + public float getTransformPivotX() { + return mTransformPivotX; + } + + public float getTransformPivotY() { + return mTransformPivotY; + } + + public int getPadding() { + return mPadding; + } + + public int getPaddingBottom() { + return mPaddingBottom; + } + + public int getPaddingEnd() { + return mPaddingEnd; + } + + public int getPaddingLeft() { + return mPaddingLeft; + } + + public int getPaddingRight() { + return mPaddingRight; + } + + public int getPaddingStart() { + return mPaddingStart; + } + + public int getPaddingTop() { + return mPaddingTop; + } + + public void changeValues() { + mBackgroundTint = 0xFFFF0000; + mFadeScrollbars = true; + mNextFocusForward = R.id.paddingStartEnd; + mNextFocusLeft = R.id.paddingTopBottom; + mNextFocusRight = R.id.backgroundTint; + mNextFocusUp = R.id.fadeScrollbars; + mNextFocusDown = R.id.padding; + mRequiresFadingEdge = ViewBindingAdapter.FADING_EDGE_HORIZONTAL; + mScrollbarDefaultDelayBeforeFade = 400; + mScrollbarFadeDuration = 500; + mScrollbarSize = 11; + mScrollbarStyle = View.SCROLLBARS_INSIDE_INSET; + mTransformPivotX = 7; + mTransformPivotY = 6; + mPadding = 110; + mPaddingBottom = 120; + mPaddingTop = 130; + mPaddingLeft = 140; + mPaddingRight = 150; + mPaddingStart = 160; + mPaddingEnd = 170; + notifyChange(); + } +} diff --git a/tools/data-binding/TestApp/src/main/res/layout/view_adapter_test.xml b/tools/data-binding/TestApp/src/main/res/layout/view_adapter_test.xml new file mode 100644 index 0000000000000..1e24909c88dc8 --- /dev/null +++ b/tools/data-binding/TestApp/src/main/res/layout/view_adapter_test.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java index a5baa19f466ca..a3586d8c296d7 100644 --- a/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java +++ b/tools/data-binding/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java @@ -112,7 +112,13 @@ public class ProcessBindable extends AbstractProcessor { if (name.length() >= 2) { char firstChar = name.charAt(0); char secondChar = name.charAt(1); - if ((firstChar == 'm' && Character.isUpperCase(secondChar)) || + if (name.length() > 2 && firstChar == 'm' && secondChar == '_') { + char thirdChar = name.charAt(2); + if (Character.isJavaIdentifierStart(thirdChar)) { + return "" + Character.toLowerCase(thirdChar) + + name.subSequence(3, name.length()); + } + } else if ((firstChar == 'm' && Character.isUpperCase(secondChar)) || (firstChar == '_' && Character.isJavaIdentifierStart(secondChar))) { return "" + Character.toLowerCase(secondChar) + name.subSequence(2, name.length()); } diff --git a/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java b/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java index 24d61910702fb..9e0f565dc83fa 100644 --- a/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java +++ b/tools/data-binding/compiler/src/main/java/com/android/databinding/ClassAnalyzer.java @@ -227,7 +227,7 @@ public class ClassAnalyzer { return "0L"; } if("float".equals(className)) { - return "0fL"; + return "0f"; } if("double".equals(className)) { return "0.0"; diff --git a/tools/data-binding/library/build.gradle b/tools/data-binding/library/build.gradle index b9ae040b6f91f..f8bcb0b7a87f2 100644 --- a/tools/data-binding/library/build.gradle +++ b/tools/data-binding/library/build.gradle @@ -52,6 +52,9 @@ android { runProguard false } } + packagingOptions { + exclude 'META-INF/services/javax.annotation.processing.Processor' + } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) diff --git a/tools/data-binding/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java b/tools/data-binding/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java index 7333abedc31fb..1e361cf2e163f 100644 --- a/tools/data-binding/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java +++ b/tools/data-binding/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java @@ -28,7 +28,7 @@ import android.view.View; @BindingMethod(type = "android.view.View", attribute = "android:nextFocusLeft", method = "setNextFocusLeftId"), @BindingMethod(type = "android.view.View", attribute = "android:nextFocusRight", method = "setNextFocusRightId"), @BindingMethod(type = "android.view.View", attribute = "android:nextFocusUp", method = "setNextFocusUpId"), - @BindingMethod(type = "android.view.View", attribute = "android:padding", method = "setPaddingRelative"), + @BindingMethod(type = "android.view.View", attribute = "android:nextFocusDown", method = "setNextFocusDownId"), @BindingMethod(type = "android.view.View", attribute = "android:requiresFadingEdge", method = "setVerticalFadingEdgeEnabled"), @BindingMethod(type = "android.view.View", attribute = "android:scrollbarDefaultDelayBeforeFade", method = "setScrollBarDefaultDelayBeforeFade"), @BindingMethod(type = "android.view.View", attribute = "android:scrollbarFadeDuration", method = "setScrollBarFadeDuration"), @@ -38,6 +38,9 @@ import android.view.View; @BindingMethod(type = "android.view.View", attribute = "android:transformPivotY", method = "setPivotY"), }) public class ViewBindingAdapter { + public static int FADING_EDGE_NONE = 0; + public static int FADING_EDGE_HORIZONTAL = 1; + public static int FADING_EDGE_VERTICAL = 2; @BindingAdapter("android:padding") public static void setPadding(View view, int padding) { @@ -89,4 +92,12 @@ public class ViewBindingAdapter { view.setPadding(view.getPaddingLeft(), padding, view.getPaddingRight(), view.getPaddingBottom()); } + + @BindingAdapter("android:requiresFadingEdge") + public static void setRequiresFadingEdge(View view, int value) { + final boolean vertical = (value & FADING_EDGE_VERTICAL) != 0; + final boolean horizontal = (value & FADING_EDGE_HORIZONTAL) != 0; + view.setVerticalFadingEdgeEnabled(vertical); + view.setHorizontalFadingEdgeEnabled(horizontal); + } }