1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.layoutlib.bridge.impl.binding;
18
19import com.android.ide.common.rendering.api.DataBindingItem;
20import com.android.ide.common.rendering.api.IProjectCallback;
21import com.android.ide.common.rendering.api.LayoutLog;
22import com.android.ide.common.rendering.api.ResourceReference;
23import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute;
24import com.android.layoutlib.bridge.Bridge;
25import com.android.layoutlib.bridge.android.BridgeContext;
26import com.android.layoutlib.bridge.impl.RenderAction;
27import com.android.util.Pair;
28
29import android.view.View;
30import android.view.ViewGroup;
31import android.widget.AdapterView;
32import android.widget.Checkable;
33import android.widget.ImageView;
34import android.widget.TextView;
35
36/**
37 * A Helper class to do fake data binding in {@link AdapterView} objects.
38 */
39@SuppressWarnings("deprecation")
40public class AdapterHelper {
41
42    static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
43            IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
44        // we don't care about recycling here because we never scroll.
45        DataBindingItem dataBindingItem = item.getDataBindingItem();
46
47        BridgeContext context = RenderAction.getCurrentContext();
48
49        Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(),
50                parent, false /*attachToRoot*/, skipCallbackParser);
51
52        View view = pair.getFirst();
53        skipCallbackParser |= pair.getSecond();
54
55        if (view != null) {
56            fillView(context, view, item, parentItem, callback, adapterRef);
57        } else {
58            // create a text view to display an error.
59            TextView tv = new TextView(context);
60            tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName());
61            view = tv;
62        }
63
64        return Pair.of(view, skipCallbackParser);
65    }
66
67    private static void fillView(BridgeContext context, View view, AdapterItem item,
68            AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) {
69        if (view instanceof ViewGroup) {
70            ViewGroup group = (ViewGroup) view;
71            final int count = group.getChildCount();
72            for (int i = 0 ; i < count ; i++) {
73                fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef);
74            }
75        } else {
76            int id = view.getId();
77            if (id != 0) {
78                ResourceReference resolvedRef = context.resolveId(id);
79                if (resolvedRef != null) {
80                    int fullPosition = item.getFullPosition();
81                    int positionPerType = item.getPositionPerType();
82                    int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0;
83                    int parentPositionPerType = parentItem != null ?
84                            parentItem.getPositionPerType() : 0;
85
86                    if (view instanceof TextView) {
87                        TextView tv = (TextView) view;
88                        Object value = callback.getAdapterItemValue(
89                                adapterRef, context.getViewKey(view),
90                                item.getDataBindingItem().getViewReference(),
91                                fullPosition, positionPerType,
92                                fullParentPosition, parentPositionPerType,
93                                resolvedRef, ViewAttribute.TEXT, tv.getText().toString());
94                        if (value != null) {
95                            if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) {
96                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
97                                        "Wrong Adapter Item value class for TEXT. Expected String, got %s",
98                                        value.getClass().getName()), null);
99                            } else {
100                                tv.setText((String) value);
101                            }
102                        }
103                    }
104
105                    if (view instanceof Checkable) {
106                        Checkable cb = (Checkable) view;
107
108                        Object value = callback.getAdapterItemValue(
109                                adapterRef, context.getViewKey(view),
110                                item.getDataBindingItem().getViewReference(),
111                                fullPosition, positionPerType,
112                                fullParentPosition, parentPositionPerType,
113                                resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked());
114                        if (value != null) {
115                            if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) {
116                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
117                                        "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
118                                        value.getClass().getName()), null);
119                            } else {
120                                cb.setChecked((Boolean) value);
121                            }
122                        }
123                    }
124
125                    if (view instanceof ImageView) {
126                        ImageView iv = (ImageView) view;
127
128                        Object value = callback.getAdapterItemValue(
129                                adapterRef, context.getViewKey(view),
130                                item.getDataBindingItem().getViewReference(),
131                                fullPosition, positionPerType,
132                                fullParentPosition, parentPositionPerType,
133                                resolvedRef, ViewAttribute.SRC, iv.getDrawable());
134                        if (value != null) {
135                            if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) {
136                                Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
137                                        "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
138                                        value.getClass().getName()), null);
139                            } else {
140                                // FIXME
141                            }
142                        }
143                    }
144                }
145            }
146        }
147    }
148}
149