1/*
2 * Copyright (C) 2011 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.AdapterBinding;
20import com.android.ide.common.rendering.api.DataBindingItem;
21import com.android.ide.common.rendering.api.IProjectCallback;
22import com.android.ide.common.rendering.api.ResourceReference;
23
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.ExpandableListAdapter;
27import android.widget.HeterogeneousExpandableList;
28
29import java.util.ArrayList;
30import java.util.List;
31
32public class FakeExpandableAdapter extends BaseAdapter implements ExpandableListAdapter,
33        HeterogeneousExpandableList {
34
35    // don't use a set because the order is important.
36    private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>();
37    private final List<ResourceReference> mChildrenTypes = new ArrayList<ResourceReference>();
38
39    public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding,
40            IProjectCallback callback) {
41        super(adapterRef, binding, callback);
42
43        createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1);
44    }
45
46    private void createItems(Iterable<DataBindingItem> iterable, final int itemCount,
47            final int repeatCount, List<ResourceReference> types, int depth) {
48        // Need an array to count for each type.
49        // This is likely too big, but is the max it can be.
50        int[] typeCount = new int[itemCount];
51
52        // we put several repeating sets.
53        for (int r = 0 ; r < repeatCount ; r++) {
54            // loop on the type of list items, and add however many for each type.
55            for (DataBindingItem dataBindingItem : iterable) {
56                ResourceReference viewRef = dataBindingItem.getViewReference();
57                int typeIndex = types.indexOf(viewRef);
58                if (typeIndex == -1) {
59                    typeIndex = types.size();
60                    types.add(viewRef);
61                }
62
63                List<DataBindingItem> children = dataBindingItem.getChildren();
64                int count = dataBindingItem.getCount();
65
66                // if there are children, we use the count as a repeat count for the children.
67                if (children.size() > 0) {
68                    count = 1;
69                }
70
71                int index = typeCount[typeIndex];
72                typeCount[typeIndex] += count;
73
74                for (int k = 0 ; k < count ; k++) {
75                    AdapterItem item = new AdapterItem(dataBindingItem, typeIndex, mItems.size(),
76                            index++);
77                    mItems.add(item);
78
79                    if (children.size() > 0) {
80                        createItems(dataBindingItem, depth + 1);
81                    }
82                }
83            }
84        }
85    }
86
87    private void createItems(DataBindingItem item, int depth) {
88        if (depth == 2) {
89            createItems(item, item.getChildren().size(), item.getCount(), mChildrenTypes, depth);
90        }
91    }
92
93    private AdapterItem getChildItem(int groupPosition, int childPosition) {
94        AdapterItem item = mItems.get(groupPosition);
95
96        List<AdapterItem> children = item.getChildren();
97        return children.get(childPosition);
98    }
99
100    // ---- ExpandableListAdapter
101
102    @Override
103    public int getGroupCount() {
104        return mItems.size();
105    }
106
107    @Override
108    public int getChildrenCount(int groupPosition) {
109        AdapterItem item = mItems.get(groupPosition);
110        return item.getChildren().size();
111    }
112
113    @Override
114    public Object getGroup(int groupPosition) {
115        return mItems.get(groupPosition);
116    }
117
118    @Override
119    public Object getChild(int groupPosition, int childPosition) {
120        return getChildItem(groupPosition, childPosition);
121    }
122
123    @Override
124    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
125            ViewGroup parent) {
126        // we don't care about recycling here because we never scroll.
127        AdapterItem item = mItems.get(groupPosition);
128        return getView(item, null /*parentItem*/, convertView, parent);
129    }
130
131    @Override
132    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
133            View convertView, ViewGroup parent) {
134        // we don't care about recycling here because we never scroll.
135        AdapterItem parentItem = mItems.get(groupPosition);
136        AdapterItem item = getChildItem(groupPosition, childPosition);
137        return getView(item, parentItem, convertView, parent);
138    }
139
140    @Override
141    public long getGroupId(int groupPosition) {
142        return groupPosition;
143    }
144
145    @Override
146    public long getChildId(int groupPosition, int childPosition) {
147        return childPosition;
148    }
149
150    @Override
151    public long getCombinedGroupId(long groupId) {
152        return groupId << 16 | 0x0000FFFF;
153    }
154
155    @Override
156    public long getCombinedChildId(long groupId, long childId) {
157        return groupId << 16 | childId;
158    }
159
160    @Override
161    public boolean isChildSelectable(int groupPosition, int childPosition) {
162        return true;
163    }
164
165    @Override
166    public void onGroupCollapsed(int groupPosition) {
167        // pass
168    }
169
170    @Override
171    public void onGroupExpanded(int groupPosition) {
172        // pass
173    }
174
175    // ---- HeterogeneousExpandableList
176
177    @Override
178    public int getChildType(int groupPosition, int childPosition) {
179        return getChildItem(groupPosition, childPosition).getType();
180    }
181
182    @Override
183    public int getChildTypeCount() {
184        return mChildrenTypes.size();
185    }
186
187    @Override
188    public int getGroupType(int groupPosition) {
189        return mItems.get(groupPosition).getType();
190    }
191
192    @Override
193    public int getGroupTypeCount() {
194        return mGroupTypes.size();
195    }
196}
197