1 /*
2  * Copyright (C) 2021 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.launcher3.widget.picker.search;
18 
19 import static android.view.View.GONE;
20 import static android.view.View.VISIBLE;
21 
22 import android.text.Editable;
23 import android.text.TextWatcher;
24 import android.util.Log;
25 import android.view.KeyEvent;
26 import android.view.View;
27 import android.widget.ImageButton;
28 
29 import com.android.launcher3.ExtendedEditText;
30 import com.android.launcher3.search.SearchAlgorithm;
31 import com.android.launcher3.search.SearchCallback;
32 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
33 
34 import java.util.ArrayList;
35 
36 /**
37  * Controller for a search bar with an edit text and a cancel button.
38  */
39 public class WidgetsSearchBarController implements TextWatcher,
40         SearchCallback<WidgetsListBaseEntry>,  ExtendedEditText.OnBackKeyListener,
41         View.OnKeyListener {
42     private static final String TAG = "WidgetsSearchBarController";
43     private static final boolean DEBUG = false;
44 
45     protected SearchAlgorithm<WidgetsListBaseEntry> mSearchAlgorithm;
46     protected ExtendedEditText mInput;
47     protected ImageButton mCancelButton;
48     protected SearchModeListener mSearchModeListener;
49     protected String mQuery;
50 
WidgetsSearchBarController( SearchAlgorithm<WidgetsListBaseEntry> algo, ExtendedEditText editText, ImageButton cancelButton, SearchModeListener searchModeListener)51     public WidgetsSearchBarController(
52             SearchAlgorithm<WidgetsListBaseEntry> algo, ExtendedEditText editText,
53             ImageButton cancelButton, SearchModeListener searchModeListener) {
54         mSearchAlgorithm = algo;
55         mInput = editText;
56         mInput.addTextChangedListener(this);
57         mInput.setOnBackKeyListener(this);
58         mInput.setOnKeyListener(this);
59         mCancelButton = cancelButton;
60         mCancelButton.setOnClickListener(v -> clearSearchResult());
61         mSearchModeListener = searchModeListener;
62     }
63 
64     @Override
afterTextChanged(final Editable s)65     public void afterTextChanged(final Editable s) {
66         mQuery = s.toString();
67         if (mQuery.isEmpty()) {
68             mSearchAlgorithm.cancel(/* interruptActiveRequests= */ true);
69             mSearchModeListener.exitSearchMode();
70             mCancelButton.setVisibility(GONE);
71         } else {
72             mSearchAlgorithm.cancel(/* interruptActiveRequests= */ false);
73             mSearchModeListener.enterSearchMode(true);
74             mSearchAlgorithm.doSearch(mQuery, this);
75             mCancelButton.setVisibility(VISIBLE);
76         }
77     }
78 
79     @Override
beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)80     public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
81         // Do nothing.
82     }
83 
84     @Override
onTextChanged(CharSequence charSequence, int i, int i1, int i2)85     public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
86         // Do nothing.
87     }
88 
89     @Override
onSearchResult(String query, ArrayList<WidgetsListBaseEntry> items)90     public void onSearchResult(String query, ArrayList<WidgetsListBaseEntry> items) {
91         if (DEBUG) {
92             Log.d(TAG, "onSearchResult query: " + query + " items: " + items);
93         }
94         mSearchModeListener.onSearchResults(items);
95     }
96 
97     @Override
clearSearchResult()98     public void clearSearchResult() {
99         // Any existing search session will be cancelled by setting text to empty.
100         mInput.setText("");
101     }
102 
103     /**
104      * Cleans up after search is no longer needed.
105      */
onDestroy()106     public void onDestroy() {
107         mSearchAlgorithm.destroy();
108     }
109 
110     @Override
onBackKey()111     public boolean onBackKey() {
112         clearFocus();
113         return true;
114     }
115 
116     @Override
onKey(View view, int keyCode, KeyEvent event)117     public boolean onKey(View view, int keyCode, KeyEvent event) {
118         if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
119             clearFocus();
120             return true;
121         }
122         return false;
123     }
124 
125     /**
126      * Clears focus from edit text.
127      */
clearFocus()128     public void clearFocus() {
129         mInput.clearFocus();
130         mInput.hideKeyboard();
131     }
132 }
133