15bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam/*
25bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * Copyright (C) 2015 The Android Open Source Project
35bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam *
45bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * Licensed under the Apache License, Version 2.0 (the "License");
55bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * you may not use this file except in compliance with the License.
65bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * You may obtain a copy of the License at
75bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam *
85bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam *      http://www.apache.org/licenses/LICENSE-2.0
95bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam *
105bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * Unless required by applicable law or agreed to in writing, software
115bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * distributed under the License is distributed on an "AS IS" BASIS,
125bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * See the License for the specific language governing permissions and
145bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam * limitations under the License.
155bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam */
165bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
175bf291fde3dfd64f264d525534730514a279c8fcMaurice Lampackage com.android.setupwizardlib.items;
185bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
195bf291fde3dfd64f264d525534730514a279c8fcMaurice Lamimport android.util.SparseIntArray;
205bf291fde3dfd64f264d525534730514a279c8fcMaurice Lamimport android.view.LayoutInflater;
215bf291fde3dfd64f264d525534730514a279c8fcMaurice Lamimport android.view.View;
225bf291fde3dfd64f264d525534730514a279c8fcMaurice Lamimport android.view.ViewGroup;
235bf291fde3dfd64f264d525534730514a279c8fcMaurice Lamimport android.widget.BaseAdapter;
245bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
255bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam/**
26960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam * An adapter typically used with ListView to display an
27960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam * {@link com.android.setupwizardlib.items.ItemHierarchy}. The item hierarchy used to create this
28960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam * adapter can be inflated by {@link ItemInflater} from XML.
295bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam */
30960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lampublic class ItemAdapter extends BaseAdapter implements ItemHierarchy.Observer {
315bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
32960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    private final ItemHierarchy mItemHierarchy;
335bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    private ViewTypes mViewTypes = new ViewTypes();
345bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
35960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public ItemAdapter(ItemHierarchy hierarchy) {
36960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        mItemHierarchy = hierarchy;
37960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        mItemHierarchy.registerObserver(this);
385bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        refreshViewTypes();
395bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
405bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
415bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
425bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    public int getCount() {
43960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        return mItemHierarchy.getCount();
445bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
455bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
465bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
47960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public IItem getItem(int position) {
48960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        return mItemHierarchy.getItemAt(position);
495bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
505bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
515bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
525bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    public long getItemId(int position) {
535bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        return position;
545bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
555bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
565bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
575bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    public int getItemViewType(int position) {
58960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        IItem item = getItem(position);
59960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        int layoutRes = item.getLayoutResource();
605bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        return mViewTypes.get(layoutRes);
615bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
625bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
635bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
645bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    public int getViewTypeCount() {
655bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        return mViewTypes.size();
665bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
675bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
68960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    private void refreshViewTypes() {
69960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        for (int i = 0; i < getCount(); i++) {
70960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam            IItem item = getItem(i);
715bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            mViewTypes.add(item.getLayoutResource());
725bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        }
735bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
745bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
755bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    @Override
765bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    public View getView(int position, View convertView, ViewGroup parent) {
77960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        IItem item = getItem(position);
785bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        if (convertView == null) {
795bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
805bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            convertView = inflater.inflate(item.getLayoutResource(), parent, false);
815bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        }
825bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        item.onBindView(convertView);
835bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        return convertView;
845bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
855bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
86960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    @Override
87960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public void onChanged(ItemHierarchy hierarchy) {
88960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        refreshViewTypes();
89960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        notifyDataSetChanged();
90960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    }
91960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam
92960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    @Override
93ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    public void onItemRangeChanged(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
94ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam        onChanged(itemHierarchy);
95ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    }
96ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam
97ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    @Override
98ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    public void onItemRangeInserted(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
99ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam        onChanged(itemHierarchy);
100ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    }
101ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam
102ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    @Override
103ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    public void onItemRangeMoved(ItemHierarchy itemHierarchy, int fromPosition, int toPosition,
104ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam            int itemCount) {
105ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam        onChanged(itemHierarchy);
106ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    }
107ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam
108ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    @Override
109ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    public void onItemRangeRemoved(ItemHierarchy itemHierarchy, int positionStart, int itemCount) {
110ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam        onChanged(itemHierarchy);
111ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    }
112ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam
113ab45bdf67a01ba13efb45334cc43f9632de6f034Maurice Lam    @Override
114960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public boolean isEnabled(int position) {
115960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        return getItem(position).isEnabled();
116960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    }
117960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam
118960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public ItemHierarchy findItemById(int id) {
119960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        return mItemHierarchy.findItemById(id);
120960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    }
121960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam
122960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    public ItemHierarchy getRootItemHierarchy() {
123960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam        return mItemHierarchy;
124960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam    }
125960c0ea0b1d36904beef0f01715dd43a211e88caMaurice Lam
1265bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    /**
1275bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam     * A helper class to pack a sparse set of integers (e.g. resource IDs) to a contiguous list of
1285bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam     * integers (e.g. adapter positions), providing mapping to retrieve the original ID from a given
1295bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam     * position. This is used to pack the view types of the adapter into contiguous integers from
1305bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam     * a given layout resource.
1315bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam     */
1325bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    private static class ViewTypes {
1335bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        private SparseIntArray mPositionMap = new SparseIntArray();
1345bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        private int nextPosition = 0;
1355bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
1365bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        public int add(int id) {
1375bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            if (mPositionMap.indexOfKey(id) < 0) {
1385bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam                mPositionMap.put(id, nextPosition);
1395bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam                nextPosition++;
1405bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            }
1415bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            return mPositionMap.get(id);
1425bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        }
1435bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
1445bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        public int size() {
1455bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            return mPositionMap.size();
1465bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        }
1475bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam
1485bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        public int get(int id) {
1495bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam            return mPositionMap.get(id);
1505bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam        }
1515bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam    }
1525bf291fde3dfd64f264d525534730514a279c8fcMaurice Lam}
153