CorporaAdapter.java revision 8b2936607176720172aee068abc5631bdf77e843
1/*
2 * Copyright (C) 2009 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.quicksearchbox.ui;
18
19import com.android.quicksearchbox.Corpora;
20import com.android.quicksearchbox.Corpus;
21import com.android.quicksearchbox.R;
22import com.google.common.collect.Multiset;
23
24import android.content.Context;
25import android.database.DataSetObserver;
26import android.graphics.drawable.Drawable;
27import android.util.Log;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.ViewGroup;
31import android.widget.BaseAdapter;
32
33import java.util.ArrayList;
34import java.util.Collections;
35import java.util.Comparator;
36import java.util.List;
37
38/**
39 * Adapter for showing a list of sources in the source selection activity.
40 */
41public class CorporaAdapter extends BaseAdapter {
42
43    private static final String TAG = "CorporaAdapter";
44    private static final boolean DBG = false;
45
46    private final Context mContext;
47
48    private final Corpora mCorpora;
49
50    private final int mCorpusViewRes;
51
52    private final DataSetObserver mCorporaObserver = new CorporaObserver();
53
54    private List<Corpus> mSortedCorpora;
55
56    private String mCurrentCorpusName;
57
58    private Multiset<String> mCorpusResultCounts;
59
60    public CorporaAdapter(Context context, Corpora corpora, int corpusViewRes) {
61        mContext = context;
62        mCorpora = corpora;
63        mCorpusViewRes = corpusViewRes;
64        mCorpora.registerDataSetObserver(mCorporaObserver);
65        updateCorpora();
66    }
67
68    public void setCorpusResultCounts(Multiset<String> corpusResultCounts) {
69        mCorpusResultCounts = corpusResultCounts;
70        notifyDataSetChanged();
71    }
72
73    public void setCurrentCorpus(Corpus corpus) {
74        mCurrentCorpusName = corpus == null ? null : corpus.getName();
75        notifyDataSetChanged();
76    }
77
78    private void updateCorpora() {
79        List<Corpus> enabledCorpora = mCorpora.getEnabledCorpora();
80        ArrayList<Corpus> sorted = new ArrayList<Corpus>(enabledCorpora.size());
81        for (Corpus corpus : enabledCorpora) {
82            if (!corpus.isCorpusHidden()) {
83                sorted.add(corpus);
84            }
85        }
86        Collections.sort(sorted, new CorpusComparator());
87        mSortedCorpora = sorted;
88        notifyDataSetChanged();
89    }
90
91    private static class CorpusComparator implements Comparator<Corpus> {
92        public int compare(Corpus corpus1, Corpus corpus2) {
93            // Comparing a corpus against itself
94            if (corpus1 == corpus2) return 0;
95            // Web always comes first
96            if (corpus1.isWebCorpus()) return -1;
97            if (corpus2.isWebCorpus()) return 1;
98            // Alphabetically by name
99            return corpus1.getLabel().toString().compareTo(corpus2.getLabel().toString());
100        }
101    }
102
103    public void close() {
104        mCorpora.unregisterDataSetObserver(mCorporaObserver);
105    }
106
107    public int getCount() {
108        return 1 + (mSortedCorpora == null ? 0 : mSortedCorpora.size());
109    }
110
111    public Corpus getItem(int position) {
112        if (position == 0) {
113            return null;
114        } else {
115            return mSortedCorpora.get(position - 1);
116        }
117    }
118
119    public long getItemId(int position) {
120        return position;
121    }
122
123    /**
124     * Gets the position of the given corpus.
125     */
126    public int getCorpusPosition(Corpus corpus) {
127        if (corpus == null) {
128            return 0;
129        }
130        int count = getCount();
131        for (int i = 0; i < count; i++) {
132            if (corpus.equals(getItem(i))) {
133                return i;
134            }
135        }
136        Log.w(TAG, "Corpus not in adapter: " + corpus);
137        return 0;
138    }
139
140    public View getView(int position, View convertView, ViewGroup parent) {
141        CorpusView view = (CorpusView) convertView;
142        if (view == null) {
143            view = createView(parent);
144        }
145        Corpus corpus = getItem(position);
146        if (DBG) Log.d(TAG, "Binding " + position + ", corpus=" + corpus);
147        bindView(view, corpus);
148        return view;
149    }
150
151    protected void bindView(CorpusView view, Corpus corpus) {
152        Drawable icon = getCorpusIcon(corpus);
153        CharSequence label = getCorpusLabel(corpus);
154        boolean isCurrent = isCurrentCorpus(corpus);
155        if (DBG) Log.d(TAG, "bind:name=" + corpus + ",label=" + label + ",current=" + isCurrent);
156        view.setIcon(icon);
157        view.setLabel(label);
158        view.setChecked(isCurrent);
159    }
160
161    protected Drawable getCorpusIcon(Corpus corpus) {
162        if (corpus == null) {
163            return mContext.getResources().getDrawable(R.drawable.search_app_icon);
164        } else {
165            return corpus.getCorpusIcon();
166        }
167    }
168
169    protected CharSequence getCorpusLabel(Corpus corpus) {
170        if (corpus == null) {
171            return mContext.getText(R.string.corpus_label_global);
172        } else {
173            CharSequence label = corpus.getLabel();
174            if (mCorpusResultCounts != null) {
175                int resultCount = mCorpusResultCounts.count(corpus.getName());
176                if (resultCount > 0) {
177                    return mContext.getString(R.string.corpus_count_format, label, resultCount);
178                }
179            }
180            return label;
181        }
182    }
183
184    protected boolean isCurrentCorpus(Corpus corpus) {
185        if (corpus == null) {
186            return mCurrentCorpusName == null;
187        } else {
188            return corpus.getName().equals(mCurrentCorpusName);
189        }
190    }
191
192    protected CorpusView createView(ViewGroup parent) {
193        return (CorpusView) LayoutInflater.from(mContext).inflate(mCorpusViewRes, parent, false);
194    }
195
196    protected LayoutInflater getInflater() {
197        return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
198    }
199
200    private class CorporaObserver extends DataSetObserver {
201        @Override
202        public void onChanged() {
203            updateCorpora();
204        }
205
206        @Override
207        public void onInvalidated() {
208            updateCorpora();
209        }
210    }
211
212}
213