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 17 package com.android.quicksearchbox.ui; 18 19 import com.android.quicksearchbox.SuggestionCursor; 20 import com.android.quicksearchbox.SuggestionPosition; 21 import com.android.quicksearchbox.Suggestions; 22 23 import android.database.DataSetObserver; 24 import android.util.Log; 25 import android.view.View.OnFocusChangeListener; 26 27 /** 28 * A {@link SuggestionsListAdapter} that doesn't expose the new suggestions 29 * until there are some results to show. 30 */ 31 public class DelayingSuggestionsAdapter<A> implements SuggestionsAdapter<A> { 32 33 private static final boolean DBG = false; 34 private static final String TAG = "QSB.DelayingSuggestionsAdapter"; 35 36 private DataSetObserver mPendingDataSetObserver; 37 38 private Suggestions mPendingSuggestions; 39 40 private final SuggestionsAdapterBase<A> mDelayedAdapter; 41 42 public DelayingSuggestionsAdapter(SuggestionsAdapterBase<A> delayed) { 43 mDelayedAdapter = delayed; 44 } 45 46 public void close() { 47 setPendingSuggestions(null); 48 mDelayedAdapter.close(); 49 } 50 51 @Override 52 public void setSuggestions(Suggestions suggestions) { 53 if (suggestions == null) { 54 mDelayedAdapter.setSuggestions(null); 55 setPendingSuggestions(null); 56 return; 57 } 58 if (shouldPublish(suggestions)) { 59 if (DBG) Log.d(TAG, "Publishing suggestions immediately: " + suggestions); 60 mDelayedAdapter.setSuggestions(suggestions); 61 // Clear any old pending suggestions. 62 setPendingSuggestions(null); 63 } else { 64 if (DBG) Log.d(TAG, "Delaying suggestions publishing: " + suggestions); 65 setPendingSuggestions(suggestions); 66 } 67 } 68 69 /** 70 * Gets whether the given suggestions are non-empty for the selected source. 71 */ 72 private boolean shouldPublish(Suggestions suggestions) { 73 if (suggestions.isDone()) return true; 74 SuggestionCursor cursor = suggestions.getResult(); 75 if (cursor != null && cursor.getCount() > 0) { 76 return true; 77 } 78 return false; 79 } 80 81 private void setPendingSuggestions(Suggestions suggestions) { 82 if (mPendingSuggestions == suggestions) { 83 return; 84 } 85 if (mDelayedAdapter.isClosed()) { 86 if (suggestions != null) { 87 suggestions.release(); 88 } 89 return; 90 } 91 if (mPendingDataSetObserver == null) { 92 mPendingDataSetObserver = new PendingSuggestionsObserver(); 93 } 94 if (mPendingSuggestions != null) { 95 mPendingSuggestions.unregisterDataSetObserver(mPendingDataSetObserver); 96 // Close old suggestions, but only if they are not also the current 97 // suggestions. 98 if (mPendingSuggestions != getSuggestions()) { 99 mPendingSuggestions.release(); 100 } 101 } 102 mPendingSuggestions = suggestions; 103 if (mPendingSuggestions != null) { 104 mPendingSuggestions.registerDataSetObserver(mPendingDataSetObserver); 105 } 106 } 107 108 protected void onPendingSuggestionsChanged() { 109 if (DBG) { 110 Log.d(TAG, "onPendingSuggestionsChanged(), mPendingSuggestions=" 111 + mPendingSuggestions); 112 } 113 if (shouldPublish(mPendingSuggestions)) { 114 if (DBG) Log.d(TAG, "Suggestions now available, publishing: " + mPendingSuggestions); 115 mDelayedAdapter.setSuggestions(mPendingSuggestions); 116 // The suggestions are no longer pending. 117 setPendingSuggestions(null); 118 } 119 } 120 121 private class PendingSuggestionsObserver extends DataSetObserver { 122 @Override 123 public void onChanged() { 124 onPendingSuggestionsChanged(); 125 } 126 } 127 128 @Override 129 public A getListAdapter() { 130 return mDelayedAdapter.getListAdapter(); 131 } 132 133 public SuggestionCursor getCurrentPromotedSuggestions() { 134 return mDelayedAdapter.getCurrentSuggestions(); 135 } 136 137 @Override 138 public Suggestions getSuggestions() { 139 return mDelayedAdapter.getSuggestions(); 140 } 141 142 @Override 143 public SuggestionPosition getSuggestion(long suggestionId) { 144 return mDelayedAdapter.getSuggestion(suggestionId); 145 } 146 147 @Override 148 public void onSuggestionClicked(long suggestionId) { 149 mDelayedAdapter.onSuggestionClicked(suggestionId); 150 } 151 152 @Override 153 public void onSuggestionQueryRefineClicked(long suggestionId) { 154 mDelayedAdapter.onSuggestionQueryRefineClicked(suggestionId); 155 } 156 157 @Override 158 public void setOnFocusChangeListener(OnFocusChangeListener l) { 159 mDelayedAdapter.setOnFocusChangeListener(l); 160 } 161 162 @Override 163 public void setSuggestionClickListener(SuggestionClickListener listener) { 164 mDelayedAdapter.setSuggestionClickListener(listener); 165 } 166 167 @Override 168 public boolean isEmpty() { 169 return mDelayedAdapter.isEmpty(); 170 } 171 172 } 173