1185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert/*
2185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * Copyright (C) 2009 The Android Open Source Project
3185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert *
4185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
5185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * you may not use this file except in compliance with the License.
6185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * You may obtain a copy of the License at
7185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert *
8185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
9185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert *
10185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * Unless required by applicable law or agreed to in writing, software
11185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
12185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * See the License for the specific language governing permissions and
14185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert * limitations under the License.
15185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert */
16185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
17185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertpackage com.android.quicksearchbox.ui;
18185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
19fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwoodimport com.android.quicksearchbox.R;
20782dd228e78e9294692d639597f96c26283968bbBjorn Bringertimport com.android.quicksearchbox.SuggestionPosition;
21782dd228e78e9294692d639597f96c26283968bbBjorn Bringert
22185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport android.content.Context;
23185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport android.util.AttributeSet;
24fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwoodimport android.util.Log;
25fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwoodimport android.view.View;
26fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwoodimport android.widget.FrameLayout;
27aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwoodimport android.widget.ListAdapter;
28713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringertimport android.widget.ListView;
29185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
30185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert/**
31713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert * Holds a list of suggestions.
32185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert */
33fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwoodpublic class SuggestionsView extends ListView implements SuggestionsListView<ListAdapter> {
34185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
35b5fc08b7f16a32d3865f44b7f26d8aaa5304a2adBjorn Bringert    private static final boolean DBG = false;
36185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    private static final String TAG = "QSB.SuggestionsView";
37185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
38fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    private boolean mLimitSuggestionsToViewHeight;
39fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    private SuggestionsAdapter<ListAdapter> mSuggestionsAdapter;
40fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood
41185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    public SuggestionsView(Context context, AttributeSet attrs) {
42185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        super(context, attrs);
43185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    }
44185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
45fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public void setSuggestionsAdapter(SuggestionsAdapter<ListAdapter> adapter) {
46fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        super.setAdapter(adapter == null ? null : adapter.getListAdapter());
47fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        mSuggestionsAdapter = adapter;
48fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        if (mLimitSuggestionsToViewHeight) {
49fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            setMaxPromotedByHeight();
50fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        }
51aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood    }
52aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood
53fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood    public SuggestionsAdapter<ListAdapter> getSuggestionsAdapter() {
54fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        return mSuggestionsAdapter;
55aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood    }
56aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood
57aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood    @Override
58713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert    public void onFinishInflate() {
59713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert        super.onFinishInflate();
6066ee1cc883f77fee930587503ecdcd8d18f12b23Mathew Inwood        setItemsCanFocus(true);
61185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    }
62185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
63782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    /**
64713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert     * Gets the position of the selected suggestion.
65782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     *
66782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     * @return A 0-based index, or {@code -1} if no suggestion is selected.
67782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     */
68782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    public int getSelectedPosition() {
69713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert        return getSelectedItemPosition();
70782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    }
71782dd228e78e9294692d639597f96c26283968bbBjorn Bringert
72782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    /**
73713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert     * Gets the selected suggestion.
74782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     *
75782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     * @return {@code null} if no suggestion is selected.
76782dd228e78e9294692d639597f96c26283968bbBjorn Bringert     */
77782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    public SuggestionPosition getSelectedSuggestion() {
78713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert        return (SuggestionPosition) getSelectedItem();
79782dd228e78e9294692d639597f96c26283968bbBjorn Bringert    }
80782dd228e78e9294692d639597f96c26283968bbBjorn Bringert
81fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    public void setLimitSuggestionsToViewHeight(boolean limit) {
82fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        mLimitSuggestionsToViewHeight = limit;
83fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        if (mLimitSuggestionsToViewHeight) {
84fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            setMaxPromotedByHeight();
85fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        }
86fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    }
87fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood
88fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    @Override
89fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
90fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        if (mLimitSuggestionsToViewHeight) {
91fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            setMaxPromotedByHeight();
92fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        }
93fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    }
94fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood
95fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    private void setMaxPromotedByHeight() {
96fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood        if (mSuggestionsAdapter != null) {
97fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            float maxHeight;
98fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            if (getParent() instanceof FrameLayout) {
99fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                // We put the SuggestionView inside a frame layout so that we know what its
100fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                // maximum height is. Since this views height is set to 'wrap content' (in two-pane
101fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                // mode at least), we can't use our own height for these calculations.
102fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                maxHeight = ((View) getParent()).getHeight();
103fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                if (DBG) Log.d(TAG, "Parent height=" + maxHeight);
104fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            } else {
105fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                maxHeight = getHeight();
106fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                if (DBG) Log.d(TAG, "This height=" + maxHeight);
107fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            }
108fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            float suggestionHeight =
109fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                getContext().getResources().getDimension(R.dimen.suggestion_view_height);
110fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            if (suggestionHeight != 0) {
111fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                int suggestions = Math.max(1, (int) Math.floor(maxHeight / suggestionHeight));
112fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                if (DBG) {
113fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                    Log.d(TAG, "view height=" + maxHeight + " suggestion height=" +
114fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                            suggestionHeight + " -> maxSuggestions=" + suggestions);
115fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood                }
116fd4a4cbc1143a734d357897531daa7105db6459bMathew Inwood                mSuggestionsAdapter.setMaxPromoted(suggestions);
117fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood            }
118fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood        }
119fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood    }
120fdb80c2962c88ac62dcd7ee7f2fab1857b61506bMathew Inwood
121185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert}
122