blob: 4d0ba4b79346beae3fb5429dd5cd41b3c76aa4b1 [file] [log] [blame]
Aga Wronska8788dad2016-01-15 17:30:15 -08001/*
2 * Copyright (C) 2013 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.documentsui;
18
Ben Kwa543a2922016-03-22 11:11:46 -070019import static com.android.documentsui.Shared.DEBUG;
20
Aga Wronskaaf5ace52016-02-17 13:50:42 -080021import android.annotation.Nullable;
22import android.os.Bundle;
Aga Wronska8788dad2016-01-15 17:30:15 -080023import android.provider.DocumentsContract.Root;
24import android.text.TextUtils;
25import android.util.Log;
26import android.view.MenuItem;
27import android.view.View;
28import android.view.View.OnClickListener;
29import android.view.View.OnFocusChangeListener;
30import android.widget.SearchView;
31import android.widget.SearchView.OnQueryTextListener;
32
33import com.android.documentsui.model.RootInfo;
34
35/**
36 * Manages searching UI behavior.
37 */
Aga Wronskaaf5ace52016-02-17 13:50:42 -080038final class SearchViewManager implements
Aga Wronska8788dad2016-01-15 17:30:15 -080039 SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener {
40
41 public interface SearchManagerListener {
Aga Wronskaaf5ace52016-02-17 13:50:42 -080042 void onSearchChanged(@Nullable String query);
Aga Wronska8788dad2016-01-15 17:30:15 -080043 }
44
45 public static final String TAG = "SearchManger";
46
47 private SearchManagerListener mListener;
Aga Wronska8788dad2016-01-15 17:30:15 -080048 private boolean mSearchExpanded;
Aga Wronskaaf5ace52016-02-17 13:50:42 -080049 private String mCurrentSearch;
Aga Wronska8788dad2016-01-15 17:30:15 -080050 private boolean mIgnoreNextClose;
51
Steve McKay18d01e82016-02-03 11:15:57 -080052 private DocumentsToolbar mActionBar;
Aga Wronska8788dad2016-01-15 17:30:15 -080053 private MenuItem mMenu;
54 private SearchView mView;
55
Aga Wronskaaf5ace52016-02-17 13:50:42 -080056 public SearchViewManager(SearchManagerListener listener, @Nullable Bundle savedState) {
Aga Wronska8788dad2016-01-15 17:30:15 -080057 mListener = listener;
Aga Wronskaaf5ace52016-02-17 13:50:42 -080058 mCurrentSearch = savedState != null ? savedState.getString(Shared.EXTRA_QUERY) : null;
Aga Wronska8788dad2016-01-15 17:30:15 -080059 }
60
61 public void setSearchMangerListener(SearchManagerListener listener) {
62 mListener = listener;
63 }
64
Steve McKay18d01e82016-02-03 11:15:57 -080065 public void install(DocumentsToolbar actionBar) {
Steve McKay0af8afd2016-02-25 13:34:03 -080066 // assert(mActionBar == null);
67
Aga Wronska8788dad2016-01-15 17:30:15 -080068 mActionBar = actionBar;
69 mMenu = actionBar.getSearchMenu();
70 mView = (SearchView) mMenu.getActionView();
71
72 mView.setOnQueryTextListener(this);
73 mView.setOnCloseListener(this);
74 mView.setOnSearchClickListener(this);
75 mView.setOnQueryTextFocusChangeListener(this);
Aga Wronskaaf5ace52016-02-17 13:50:42 -080076
77 restoreSearch();
Aga Wronska8788dad2016-01-15 17:30:15 -080078 }
79
80 /**
81 * @param root Info about the current directory.
82 */
83 void update(RootInfo root) {
84 if (mMenu == null) {
Ben Kwa543a2922016-03-22 11:11:46 -070085 if (DEBUG) Log.d(TAG, "update called before Search MenuItem installed.");
Aga Wronska8788dad2016-01-15 17:30:15 -080086 return;
87 }
88
Aga Wronskaaf5ace52016-02-17 13:50:42 -080089 if (mCurrentSearch != null) {
Aga Wronska8788dad2016-01-15 17:30:15 -080090 mMenu.expandActionView();
91
92 mView.setIconified(false);
93 mView.clearFocus();
Aga Wronskaaf5ace52016-02-17 13:50:42 -080094 mView.setQuery(mCurrentSearch, false);
Aga Wronska8788dad2016-01-15 17:30:15 -080095 } else {
96 mView.clearFocus();
97 if (!mView.isIconified()) {
98 mIgnoreNextClose = true;
99 mView.setIconified(true);
100 }
101
102 if (mMenu.isActionViewExpanded()) {
103 mMenu.collapseActionView();
104 }
105 }
106
107 showMenu(root != null
108 && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0));
109 }
110
111 void showMenu(boolean visible) {
112 if (mMenu == null) {
Ben Kwa543a2922016-03-22 11:11:46 -0700113 if (DEBUG) Log.d(TAG, "showMenu called before Search MenuItem installed.");
Aga Wronska8788dad2016-01-15 17:30:15 -0800114 return;
115 }
116
Aga Wronska8788dad2016-01-15 17:30:15 -0800117 if (!visible) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800118 mCurrentSearch = null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800119 }
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800120
121 mMenu.setVisible(visible);
Aga Wronska8788dad2016-01-15 17:30:15 -0800122 }
123
124 /**
125 * Cancels current search operation. Triggers clearing and collapsing the SearchView.
126 *
127 * @return True if it cancels search. False if it does not operate search currently.
128 */
129 boolean cancelSearch() {
130 if (isExpanded() || isSearching()) {
131 // If the query string is not empty search view won't get iconified
132 mView.setQuery("", false);
133 // Causes calling onClose(). onClose() is triggering directory content update.
134 mView.setIconified(true);
135 return true;
136 }
137 return false;
138 }
139
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800140 private void restoreSearch() {
141 if (isSearching()) {
142 onSearchExpanded();
143 mView.setIconified(false);
144 mView.setQuery(mCurrentSearch, false);
145 mView.clearFocus();
146 }
147 }
148
149 private void onSearchExpanded() {
150 mSearchExpanded = true;
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800151 }
152
Aga Wronska8788dad2016-01-15 17:30:15 -0800153 boolean isSearching() {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800154 return mCurrentSearch != null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800155 }
156
157 boolean isExpanded() {
158 return mSearchExpanded;
159 }
160
161 /**
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800162 * Called when owning activity is saving state to be used to restore state during creation.
163 * @param state Bundle to save state too
164 */
165 public void onSaveInstanceState(Bundle state) {
166 state.putString(Shared.EXTRA_QUERY, mCurrentSearch);
167 }
168
169 /**
Aga Wronska8788dad2016-01-15 17:30:15 -0800170 * Clears the search. Clears the SearchView background color. Triggers refreshing of the
171 * directory content.
172 * @return True if the default behavior of clearing/dismissing SearchView should be overridden.
173 * False otherwise.
174 */
175 @Override
176 public boolean onClose() {
177 mSearchExpanded = false;
178 if (mIgnoreNextClose) {
179 mIgnoreNextClose = false;
180 return false;
181 }
182
Aga Wronska8788dad2016-01-15 17:30:15 -0800183 // Refresh the directory if a search was done
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800184 if (mCurrentSearch != null) {
185 mCurrentSearch = null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800186 if (mListener != null) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800187 mListener.onSearchChanged(mCurrentSearch);
Aga Wronska8788dad2016-01-15 17:30:15 -0800188 }
189 }
190 return false;
191 }
192
193 /**
194 * Sets mSearchExpanded. Called when search icon is clicked to start search. Used to detect when
195 * the view expanded instead of onMenuItemActionExpand, because SearchView has showAsAction set
196 * to always and onMenuItemAction* methods are not called.
197 */
198 @Override
199 public void onClick(View v) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800200 onSearchExpanded();
Aga Wronska8788dad2016-01-15 17:30:15 -0800201 }
202
203 @Override
204 public boolean onQueryTextSubmit(String query) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800205 mCurrentSearch = query;
Aga Wronska8788dad2016-01-15 17:30:15 -0800206 mView.clearFocus();
207 if (mListener != null) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800208 mListener.onSearchChanged(mCurrentSearch);
Aga Wronska8788dad2016-01-15 17:30:15 -0800209 }
210 return true;
211 }
212
213 @Override
214 public void onFocusChange(View v, boolean hasFocus) {
215 if (!hasFocus) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800216 if (mCurrentSearch == null) {
Aga Wronska8788dad2016-01-15 17:30:15 -0800217 mView.setIconified(true);
218 } else if (TextUtils.isEmpty(mView.getQuery())) {
219 cancelSearch();
220 }
221 }
222 }
223
224 @Override
225 public boolean onQueryTextChange(String newText) {
226 return false;
227 }
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800228
229 String getCurrentSearch() {
230 return mCurrentSearch;
231 }
232
Aga Wronska8788dad2016-01-15 17:30:15 -0800233}