12fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet/*
254d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta * Copyright (C) 2013 The Android Open Source Project
32fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet *
42fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
52fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * you may not use this file except in compliance with the License.
62fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * You may obtain a copy of the License at
72fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet *
82fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
92fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet *
102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * See the License for the specific language governing permissions and
142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet * limitations under the License.
152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet */
162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetpackage com.android.layoutlib.bridge.impl.binding;
182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.DataBindingItem;
202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback;
212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog;
222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute;
242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.RenderAction;
272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.util.Pair;
282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.view.View;
302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.view.ViewGroup;
312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView;
322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.Checkable;
332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ImageView;
342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.TextView;
352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet/**
3754d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta * A Helper class to do fake data binding in {@link AdapterView} objects.
382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet */
3954d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta@SuppressWarnings("deprecation")
4054d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Guptapublic class AdapterHelper {
412fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
4254d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta    static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
4354d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta            IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        // we don't care about recycling here because we never scroll.
452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        DataBindingItem dataBindingItem = item.getDataBindingItem();
462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        BridgeContext context = RenderAction.getCurrentContext();
482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
492fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(),
5054d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                parent, false /*attachToRoot*/, skipCallbackParser);
512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
522fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        View view = pair.getFirst();
5354d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta        skipCallbackParser |= pair.getSecond();
542fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
552fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        if (view != null) {
5654d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta            fillView(context, view, item, parentItem, callback, adapterRef);
572fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        } else {
582fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // create a text view to display an error.
592fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            TextView tv = new TextView(context);
602fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName());
612fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            view = tv;
622fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        }
632fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
6454d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta        return Pair.of(view, skipCallbackParser);
652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet    }
662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
6754d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta    private static void fillView(BridgeContext context, View view, AdapterItem item,
6854d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta            AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) {
692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        if (view instanceof ViewGroup) {
702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            ViewGroup group = (ViewGroup) view;
712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            final int count = group.getChildCount();
722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            for (int i = 0 ; i < count ; i++) {
7354d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef);
742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            }
752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        } else {
762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            int id = view.getId();
772fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            if (id != 0) {
782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                ResourceReference resolvedRef = context.resolveId(id);
792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (resolvedRef != null) {
802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    int fullPosition = item.getFullPosition();
812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    int positionPerType = item.getPositionPerType();
822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0;
832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    int parentPositionPerType = parentItem != null ?
842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            parentItem.getPositionPerType() : 0;
852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof TextView) {
872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        TextView tv = (TextView) view;
8854d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                        Object value = callback.getAdapterItemValue(
8954d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                                adapterRef, context.getViewKey(view),
902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                item.getDataBindingItem().getViewReference(),
912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullPosition, positionPerType,
922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullParentPosition, parentPositionPerType,
932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                resolvedRef, ViewAttribute.TEXT, tv.getText().toString());
942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (value != null) {
952fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) {
962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        "Wrong Adapter Item value class for TEXT. Expected String, got %s",
982fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        value.getClass().getName()), null);
992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            } else {
1002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                tv.setText((String) value);
1012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
1022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
1032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
1042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
1052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof Checkable) {
1062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        Checkable cb = (Checkable) view;
1072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
10854d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                        Object value = callback.getAdapterItemValue(
10954d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                                adapterRef, context.getViewKey(view),
1102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                item.getDataBindingItem().getViewReference(),
1112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullPosition, positionPerType,
1122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullParentPosition, parentPositionPerType,
1132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked());
1142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (value != null) {
1152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) {
1162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
1172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
1182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        value.getClass().getName()), null);
1192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            } else {
1202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                cb.setChecked((Boolean) value);
1212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
1222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
1232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
1242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
1252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof ImageView) {
1262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        ImageView iv = (ImageView) view;
1272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12854d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                        Object value = callback.getAdapterItemValue(
12954d88f7678387a6eb871ec2dccd36af4ff35b1feDeepanshu Gupta                                adapterRef, context.getViewKey(view),
1302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                item.getDataBindingItem().getViewReference(),
1312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullPosition, positionPerType,
1322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                fullParentPosition, parentPositionPerType,
1332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                resolvedRef, ViewAttribute.SRC, iv.getDrawable());
1342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (value != null) {
1352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) {
1362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
1372fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
1382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        value.getClass().getName()), null);
1392fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            } else {
1402fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                // FIXME
1412fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
1422fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
1432fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
1442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
1452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            }
1462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        }
1472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet    }
1482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet}
149