1816804b67619af133860a1e28e92f58bc642260dBjorn Bringert/*
2816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * Copyright (C) 2009 The Android Open Source Project
3816804b67619af133860a1e28e92f58bc642260dBjorn Bringert *
4816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
5816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * you may not use this file except in compliance with the License.
6816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * You may obtain a copy of the License at
7816804b67619af133860a1e28e92f58bc642260dBjorn Bringert *
8816804b67619af133860a1e28e92f58bc642260dBjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
9816804b67619af133860a1e28e92f58bc642260dBjorn Bringert *
10816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * Unless required by applicable law or agreed to in writing, software
11816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
12816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * See the License for the specific language governing permissions and
14816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * limitations under the License.
15816804b67619af133860a1e28e92f58bc642260dBjorn Bringert */
16816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
17816804b67619af133860a1e28e92f58bc642260dBjorn Bringertpackage com.android.quicksearchbox.ui;
18816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
19116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwoodimport com.android.quicksearchbox.CorpusResult;
20fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwoodimport com.android.quicksearchbox.Promoter;
21816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport com.android.quicksearchbox.SuggestionCursor;
227a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwoodimport com.android.quicksearchbox.SuggestionPosition;
23816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport com.android.quicksearchbox.Suggestions;
24816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
25816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport android.database.DataSetObserver;
26816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport android.util.Log;
27fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwoodimport android.view.View.OnFocusChangeListener;
28816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
29816804b67619af133860a1e28e92f58bc642260dBjorn Bringert/**
30fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood * A {@link SuggestionsListAdapter} that doesn't expose the new suggestions
31816804b67619af133860a1e28e92f58bc642260dBjorn Bringert * until there are some results to show.
32816804b67619af133860a1e28e92f58bc642260dBjorn Bringert */
33fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwoodpublic class DelayingSuggestionsAdapter<A> implements SuggestionsAdapter<A> {
34816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
35b5fc08b7f16a32d3865f44b7f26d8aaa5304a2adBjorn Bringert    private static final boolean DBG = false;
36816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private static final String TAG = "QSB.DelayingSuggestionsAdapter";
37816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
38816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private DataSetObserver mPendingDataSetObserver;
39816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
40816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private Suggestions mPendingSuggestions;
41816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
42fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    private final SuggestionsAdapterBase<A> mDelayedAdapter;
43fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
44fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public DelayingSuggestionsAdapter(SuggestionsAdapterBase<A> delayed) {
45fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter = delayed;
46816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
47816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
48816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    public void close() {
49816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        setPendingSuggestions(null);
50fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter.close();
51816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
52816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
53fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    @Override
54816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    public void setSuggestions(Suggestions suggestions) {
55816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (suggestions == null) {
56fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood            mDelayedAdapter.setSuggestions(null);
57816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            setPendingSuggestions(null);
58816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            return;
59816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
60816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (shouldPublish(suggestions)) {
61816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            if (DBG) Log.d(TAG, "Publishing suggestions immediately: " + suggestions);
62fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood            mDelayedAdapter.setSuggestions(suggestions);
63816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            // Clear any old pending suggestions.
64816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            setPendingSuggestions(null);
65816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        } else {
66816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            if (DBG) Log.d(TAG, "Delaying suggestions publishing: " + suggestions);
67816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            setPendingSuggestions(suggestions);
68816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
69816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
70816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
71816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    /**
72816804b67619af133860a1e28e92f58bc642260dBjorn Bringert     * Gets whether the given suggestions are non-empty for the selected source.
73816804b67619af133860a1e28e92f58bc642260dBjorn Bringert     */
74816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private boolean shouldPublish(Suggestions suggestions) {
75816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (suggestions.isDone()) return true;
76fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        SuggestionCursor cursor = mDelayedAdapter.getPromoted(suggestions);
77116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood        if (cursor != null && cursor.getCount() > 0) {
78116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood            return true;
79116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood        } else if (mDelayedAdapter.willPublishNonPromotedSuggestions()) {
80116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood            Iterable<CorpusResult> results = suggestions.getCorpusResults();
81116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood            for (CorpusResult result : results) {
82116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood                if (result.getCount() > 0) {
83116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood                    return true;
84116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood                }
85116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood            }
86116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood        }
87116affd19a834a2df4226a1ae37afcc1113a230eMathew Inwood        return false;
88816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
89816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
90816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private void setPendingSuggestions(Suggestions suggestions) {
91816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (mPendingSuggestions == suggestions) {
92816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            return;
93816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
94fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        if (mDelayedAdapter.isClosed()) {
95816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            if (suggestions != null) {
96b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert                suggestions.release();
97816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            }
98816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            return;
99816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
100816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (mPendingDataSetObserver == null) {
101816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            mPendingDataSetObserver = new PendingSuggestionsObserver();
102816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
103816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (mPendingSuggestions != null) {
104816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            mPendingSuggestions.unregisterDataSetObserver(mPendingDataSetObserver);
105816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            // Close old suggestions, but only if they are not also the current
106816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            // suggestions.
107816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            if (mPendingSuggestions != getSuggestions()) {
108b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert                mPendingSuggestions.release();
109816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            }
110816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
111816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        mPendingSuggestions = suggestions;
112816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (mPendingSuggestions != null) {
113816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            mPendingSuggestions.registerDataSetObserver(mPendingDataSetObserver);
114816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
115816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
116816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
117816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    protected void onPendingSuggestionsChanged() {
118816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (DBG) {
119816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            Log.d(TAG, "onPendingSuggestionsChanged(), mPendingSuggestions="
120816804b67619af133860a1e28e92f58bc642260dBjorn Bringert                    + mPendingSuggestions);
121816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
122816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        if (shouldPublish(mPendingSuggestions)) {
123816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            if (DBG) Log.d(TAG, "Suggestions now available, publishing: " + mPendingSuggestions);
124fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood            mDelayedAdapter.setSuggestions(mPendingSuggestions);
125816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            // The suggestions are no longer pending.
126816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            setPendingSuggestions(null);
127816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
128816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
129816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
130816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    private class PendingSuggestionsObserver extends DataSetObserver {
131816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        @Override
132816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        public void onChanged() {
133816804b67619af133860a1e28e92f58bc642260dBjorn Bringert            onPendingSuggestionsChanged();
134816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        }
135816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
136816804b67619af133860a1e28e92f58bc642260dBjorn Bringert
137fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public A getListAdapter() {
138fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        return mDelayedAdapter.getListAdapter();
139fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
140fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
141fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public SuggestionCursor getCurrentPromotedSuggestions() {
142fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        return mDelayedAdapter.getCurrentPromotedSuggestions();
143fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
144fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
145fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public Suggestions getSuggestions() {
146fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        return mDelayedAdapter.getSuggestions();
147fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
148fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
1497a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public SuggestionPosition getSuggestion(long suggestionId) {
1507a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        return mDelayedAdapter.getSuggestion(suggestionId);
151fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
152fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
1537a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public void onSuggestionClicked(long suggestionId) {
1547a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        mDelayedAdapter.onSuggestionClicked(suggestionId);
155fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
156fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
1577a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public void onSuggestionQueryRefineClicked(long suggestionId) {
1587a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        mDelayedAdapter.onSuggestionQueryRefineClicked(suggestionId);
159fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
160fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
1617a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public void onSuggestionQuickContactClicked(long suggestionId) {
1627a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        mDelayedAdapter.onSuggestionQuickContactClicked(suggestionId);
1637a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    }
1647a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood
1657a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public void onSuggestionRemoveFromHistoryClicked(long suggestionId) {
1667a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        mDelayedAdapter.onSuggestionRemoveFromHistoryClicked(suggestionId);
167fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
168fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
169fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public void setMaxPromoted(int maxPromoted) {
170fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter.setMaxPromoted(maxPromoted);
171fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
172fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
173fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public void setOnFocusChangeListener(OnFocusChangeListener l) {
174fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter.setOnFocusChangeListener(l);
175fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
176fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
177fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    @Override
178fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public void setPromoter(Promoter promoter) {
179fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter.setPromoter(promoter);
180fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
181fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
182fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public void setSuggestionClickListener(SuggestionClickListener listener) {
183fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mDelayedAdapter.setSuggestionClickListener(listener);
184fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    }
185fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood
1867a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    @Override
1877a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    public boolean isEmpty() {
1887a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood        return mDelayedAdapter.isEmpty();
1897a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood    }
1907a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood
191816804b67619af133860a1e28e92f58bc642260dBjorn Bringert}
192