/* * Copyright (C) 2011 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.layoutlib.bridge.impl.binding; import com.android.ide.common.rendering.api.AdapterBinding; import com.android.ide.common.rendering.api.DataBindingItem; import com.android.ide.common.rendering.api.IProjectCallback; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.ResourceReference; import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.impl.RenderAction; import com.android.util.Pair; import android.database.DataSetObserver; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Checkable; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Base adapter to do fake data binding in {@link AdapterView} objects. */ public class BaseAdapter { /** * This is the items provided by the adapter. They are dynamically generated. */ protected final static class AdapterItem { private final DataBindingItem mItem; private final int mType; private final int mFullPosition; private final int mPositionPerType; private List<AdapterItem> mChildren; protected AdapterItem(DataBindingItem item, int type, int fullPosition, int positionPerType) { mItem = item; mType = type; mFullPosition = fullPosition; mPositionPerType = positionPerType; } void addChild(AdapterItem child) { if (mChildren == null) { mChildren = new ArrayList<AdapterItem>(); } mChildren.add(child); } List<AdapterItem> getChildren() { if (mChildren != null) { return mChildren; } return Collections.emptyList(); } int getType() { return mType; } int getFullPosition() { return mFullPosition; } int getPositionPerType() { return mPositionPerType; } DataBindingItem getDataBindingItem() { return mItem; } } private final AdapterBinding mBinding; private final IProjectCallback mCallback; private final ResourceReference mAdapterRef; private boolean mSkipCallbackParser = false; protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>(); protected BaseAdapter(ResourceReference adapterRef, AdapterBinding binding, IProjectCallback callback) { mAdapterRef = adapterRef; mBinding = binding; mCallback = callback; } // ------- Some Adapter method used by all children classes. public boolean areAllItemsEnabled() { return true; } public boolean hasStableIds() { return true; } public boolean isEmpty() { return mItems.size() == 0; } public void registerDataSetObserver(DataSetObserver observer) { // pass } public void unregisterDataSetObserver(DataSetObserver observer) { // pass } // ------- protected AdapterBinding getBinding() { return mBinding; } protected View getView(AdapterItem item, AdapterItem parentItem, View convertView, ViewGroup parent) { // we don't care about recycling here because we never scroll. DataBindingItem dataBindingItem = item.getDataBindingItem(); BridgeContext context = RenderAction.getCurrentContext(); Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(), parent, false /*attachToRoot*/, mSkipCallbackParser); View view = pair.getFirst(); mSkipCallbackParser |= pair.getSecond(); if (view != null) { fillView(context, view, item, parentItem); } else { // create a text view to display an error. TextView tv = new TextView(context); tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName()); view = tv; } return view; } private void fillView(BridgeContext context, View view, AdapterItem item, AdapterItem parentItem) { if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; final int count = group.getChildCount(); for (int i = 0 ; i < count ; i++) { fillView(context, group.getChildAt(i), item, parentItem); } } else { int id = view.getId(); if (id != 0) { ResourceReference resolvedRef = context.resolveId(id); if (resolvedRef != null) { int fullPosition = item.getFullPosition(); int positionPerType = item.getPositionPerType(); int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0; int parentPositionPerType = parentItem != null ? parentItem.getPositionPerType() : 0; if (view instanceof TextView) { TextView tv = (TextView) view; Object value = mCallback.getAdapterItemValue( mAdapterRef, context.getViewKey(view), item.getDataBindingItem().getViewReference(), fullPosition, positionPerType, fullParentPosition, parentPositionPerType, resolvedRef, ViewAttribute.TEXT, tv.getText().toString()); if (value != null) { if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) { Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( "Wrong Adapter Item value class for TEXT. Expected String, got %s", value.getClass().getName()), null); } else { tv.setText((String) value); } } } if (view instanceof Checkable) { Checkable cb = (Checkable) view; Object value = mCallback.getAdapterItemValue( mAdapterRef, context.getViewKey(view), item.getDataBindingItem().getViewReference(), fullPosition, positionPerType, fullParentPosition, parentPositionPerType, resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked()); if (value != null) { if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) { Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", value.getClass().getName()), null); } else { cb.setChecked((Boolean) value); } } } if (view instanceof ImageView) { ImageView iv = (ImageView) view; Object value = mCallback.getAdapterItemValue( mAdapterRef, context.getViewKey(view), item.getDataBindingItem().getViewReference(), fullPosition, positionPerType, fullParentPosition, parentPositionPerType, resolvedRef, ViewAttribute.SRC, iv.getDrawable()); if (value != null) { if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) { Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format( "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s", value.getClass().getName()), null); } else { // FIXME } } } } } } } }