1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta * Copyright (C) 2013 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.layoutlib.bridge.impl.binding; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.DataBindingItem; 2037dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Guptaimport com.android.ide.common.rendering.api.LayoutlibCallback; 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.ResourceReference; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.RenderAction; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.util.Pair; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.View; 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.ViewGroup; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.AdapterView; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.Checkable; 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.ImageView; 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.widget.TextView; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 37e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta * A Helper class to do fake data binding in {@link AdapterView} objects. 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 39e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Guptapublic class AdapterHelper { 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta @SuppressWarnings("deprecation") 42e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent, 4337dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) { 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we don't care about recycling here because we never scroll. 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DataBindingItem dataBindingItem = item.getDataBindingItem(); 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski BridgeContext context = RenderAction.getCurrentContext(); 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(), 50e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta parent, false /*attachToRoot*/, skipCallbackParser); 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski View view = pair.getFirst(); 53e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta skipCallbackParser |= pair.getSecond(); 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (view != null) { 56e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta fillView(context, view, item, parentItem, callback, adapterRef); 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create a text view to display an error. 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TextView tv = new TextView(context); 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName()); 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski view = tv; 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 64e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta return Pair.of(view, skipCallbackParser); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta private static void fillView(BridgeContext context, View view, AdapterItem item, 6837dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta AdapterItem parentItem, LayoutlibCallback callback, ResourceReference adapterRef) { 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (view instanceof ViewGroup) { 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ViewGroup group = (ViewGroup) view; 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final int count = group.getChildCount(); 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0 ; i < count ; i++) { 73e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef); 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int id = view.getId(); 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (id != 0) { 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceReference resolvedRef = context.resolveId(id); 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (resolvedRef != null) { 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int fullPosition = item.getFullPosition(); 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int positionPerType = item.getPositionPerType(); 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0; 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int parentPositionPerType = parentItem != null ? 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski parentItem.getPositionPerType() : 0; 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (view instanceof TextView) { 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TextView tv = (TextView) view; 88e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta Object value = callback.getAdapterItemValue( 89e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta adapterRef, context.getViewKey(view), 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item.getDataBindingItem().getViewReference(), 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullPosition, positionPerType, 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullParentPosition, parentPositionPerType, 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resolvedRef, ViewAttribute.TEXT, tv.getText().toString()); 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value != null) { 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) { 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Wrong Adapter Item value class for TEXT. Expected String, got %s", 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value.getClass().getName()), null); 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tv.setText((String) value); 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (view instanceof Checkable) { 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Checkable cb = (Checkable) view; 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 108e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta Object value = callback.getAdapterItemValue( 109e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta adapterRef, context.getViewKey(view), 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item.getDataBindingItem().getViewReference(), 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullPosition, positionPerType, 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullParentPosition, parentPositionPerType, 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked()); 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value != null) { 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 1178b4a6981fdd7849a57de2f56203cfd81e9eb6e99Tor Norbye "Wrong Adapter Item value class for IS_CHECKED. Expected Boolean, got %s", 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value.getClass().getName()), null); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cb.setChecked((Boolean) value); 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (view instanceof ImageView) { 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ImageView iv = (ImageView) view; 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 128e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta Object value = callback.getAdapterItemValue( 129e98d2cb65c0915d5278c593d14ff4bdc778557f7Deepanshu Gupta adapterRef, context.getViewKey(view), 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item.getDataBindingItem().getViewReference(), 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullPosition, positionPerType, 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullParentPosition, parentPositionPerType, 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resolvedRef, ViewAttribute.SRC, iv.getDrawable()); 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value != null) { 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) { 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( 1378b4a6981fdd7849a57de2f56203cfd81e9eb6e99Tor Norbye "Wrong Adapter Item value class for SRC. Expected Boolean, got %s", 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value.getClass().getName()), null); 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // FIXME 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 149