blob: 049686289eee9fb692851711d0a66b4a54cb4c65 [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
Aga Wronskaaf5ace52016-02-17 13:50:42 -080019import android.annotation.Nullable;
20import android.os.Bundle;
Aga Wronska8788dad2016-01-15 17:30:15 -080021import android.provider.DocumentsContract.Root;
22import android.text.TextUtils;
23import android.util.Log;
24import android.view.MenuItem;
25import android.view.View;
26import android.view.View.OnClickListener;
27import android.view.View.OnFocusChangeListener;
28import android.widget.SearchView;
29import android.widget.SearchView.OnQueryTextListener;
30
31import com.android.documentsui.model.RootInfo;
32
33/**
34 * Manages searching UI behavior.
35 */
Aga Wronskaaf5ace52016-02-17 13:50:42 -080036final class SearchViewManager implements
Aga Wronska8788dad2016-01-15 17:30:15 -080037 SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener {
38
39 public interface SearchManagerListener {
Aga Wronskaaf5ace52016-02-17 13:50:42 -080040 void onSearchChanged(@Nullable String query);
Aga Wronska8788dad2016-01-15 17:30:15 -080041 }
42
43 public static final String TAG = "SearchManger";
44
45 private SearchManagerListener mListener;
Aga Wronska8788dad2016-01-15 17:30:15 -080046 private boolean mSearchExpanded;
Aga Wronskaaf5ace52016-02-17 13:50:42 -080047 private String mCurrentSearch;
Aga Wronska8788dad2016-01-15 17:30:15 -080048 private boolean mIgnoreNextClose;
49
Steve McKay18d01e82016-02-03 11:15:57 -080050 private DocumentsToolbar mActionBar;
Aga Wronska8788dad2016-01-15 17:30:15 -080051 private MenuItem mMenu;
52 private SearchView mView;
53
Aga Wronskaaf5ace52016-02-17 13:50:42 -080054 public SearchViewManager(SearchManagerListener listener, @Nullable Bundle savedState) {
Aga Wronska8788dad2016-01-15 17:30:15 -080055 mListener = listener;
Aga Wronskaaf5ace52016-02-17 13:50:42 -080056 mCurrentSearch = savedState != null ? savedState.getString(Shared.EXTRA_QUERY) : null;
Aga Wronska8788dad2016-01-15 17:30:15 -080057 }
58
59 public void setSearchMangerListener(SearchManagerListener listener) {
60 mListener = listener;
61 }
62
Steve McKay18d01e82016-02-03 11:15:57 -080063 public void install(DocumentsToolbar actionBar) {
Aga Wronska8788dad2016-01-15 17:30:15 -080064 assert (mActionBar == null);
65 mActionBar = actionBar;
66 mMenu = actionBar.getSearchMenu();
67 mView = (SearchView) mMenu.getActionView();
68
69 mView.setOnQueryTextListener(this);
70 mView.setOnCloseListener(this);
71 mView.setOnSearchClickListener(this);
72 mView.setOnQueryTextFocusChangeListener(this);
Aga Wronskaaf5ace52016-02-17 13:50:42 -080073
74 restoreSearch();
Aga Wronska8788dad2016-01-15 17:30:15 -080075 }
76
77 /**
78 * @param root Info about the current directory.
79 */
80 void update(RootInfo root) {
81 if (mMenu == null) {
82 Log.d(TAG, "update called before Search MenuItem installed.");
83 return;
84 }
85
Aga Wronskaaf5ace52016-02-17 13:50:42 -080086 if (mCurrentSearch != null) {
Aga Wronska8788dad2016-01-15 17:30:15 -080087 mMenu.expandActionView();
88
89 mView.setIconified(false);
90 mView.clearFocus();
Aga Wronskaaf5ace52016-02-17 13:50:42 -080091 mView.setQuery(mCurrentSearch, false);
Aga Wronska8788dad2016-01-15 17:30:15 -080092 } else {
93 mView.clearFocus();
94 if (!mView.isIconified()) {
95 mIgnoreNextClose = true;
96 mView.setIconified(true);
97 }
98
99 if (mMenu.isActionViewExpanded()) {
100 mMenu.collapseActionView();
101 }
102 }
103
104 showMenu(root != null
105 && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0));
106 }
107
108 void showMenu(boolean visible) {
109 if (mMenu == null) {
110 Log.d(TAG, "showMenu called before Search MenuItem installed.");
111 return;
112 }
113
Aga Wronska8788dad2016-01-15 17:30:15 -0800114 if (!visible) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800115 mCurrentSearch = null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800116 }
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800117
118 mMenu.setVisible(visible);
Aga Wronska8788dad2016-01-15 17:30:15 -0800119 }
120
121 /**
122 * Cancels current search operation. Triggers clearing and collapsing the SearchView.
123 *
124 * @return True if it cancels search. False if it does not operate search currently.
125 */
126 boolean cancelSearch() {
127 if (isExpanded() || isSearching()) {
128 // If the query string is not empty search view won't get iconified
129 mView.setQuery("", false);
130 // Causes calling onClose(). onClose() is triggering directory content update.
131 mView.setIconified(true);
132 return true;
133 }
134 return false;
135 }
136
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800137 private void restoreSearch() {
138 if (isSearching()) {
139 onSearchExpanded();
140 mView.setIconified(false);
141 mView.setQuery(mCurrentSearch, false);
142 mView.clearFocus();
143 }
144 }
145
146 private void onSearchExpanded() {
147 mSearchExpanded = true;
148 mView.setBackgroundColor(
149 mView.getResources().getColor(R.color.menu_search_background, null));
150 }
151
Aga Wronska8788dad2016-01-15 17:30:15 -0800152 boolean isSearching() {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800153 return mCurrentSearch != null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800154 }
155
156 boolean isExpanded() {
157 return mSearchExpanded;
158 }
159
160 /**
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800161 * Called when owning activity is saving state to be used to restore state during creation.
162 * @param state Bundle to save state too
163 */
164 public void onSaveInstanceState(Bundle state) {
165 state.putString(Shared.EXTRA_QUERY, mCurrentSearch);
166 }
167
168 /**
Aga Wronska8788dad2016-01-15 17:30:15 -0800169 * Clears the search. Clears the SearchView background color. Triggers refreshing of the
170 * directory content.
171 * @return True if the default behavior of clearing/dismissing SearchView should be overridden.
172 * False otherwise.
173 */
174 @Override
175 public boolean onClose() {
176 mSearchExpanded = false;
177 if (mIgnoreNextClose) {
178 mIgnoreNextClose = false;
179 return false;
180 }
181
182 mView.setBackgroundColor(
183 mView.getResources().getColor(android.R.color.transparent, null));
184
185 // Refresh the directory if a search was done
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800186 if (mCurrentSearch != null) {
187 mCurrentSearch = null;
Aga Wronska8788dad2016-01-15 17:30:15 -0800188 if (mListener != null) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800189 mListener.onSearchChanged(mCurrentSearch);
Aga Wronska8788dad2016-01-15 17:30:15 -0800190 }
191 }
192 return false;
193 }
194
195 /**
196 * Sets mSearchExpanded. Called when search icon is clicked to start search. Used to detect when
197 * the view expanded instead of onMenuItemActionExpand, because SearchView has showAsAction set
198 * to always and onMenuItemAction* methods are not called.
199 */
200 @Override
201 public void onClick(View v) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800202 onSearchExpanded();
Aga Wronska8788dad2016-01-15 17:30:15 -0800203 }
204
205 @Override
206 public boolean onQueryTextSubmit(String query) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800207 mCurrentSearch = query;
Aga Wronska8788dad2016-01-15 17:30:15 -0800208 mView.clearFocus();
209 if (mListener != null) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800210 mListener.onSearchChanged(mCurrentSearch);
Aga Wronska8788dad2016-01-15 17:30:15 -0800211 }
212 return true;
213 }
214
215 @Override
216 public void onFocusChange(View v, boolean hasFocus) {
217 if (!hasFocus) {
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800218 if (mCurrentSearch == null) {
Aga Wronska8788dad2016-01-15 17:30:15 -0800219 mView.setIconified(true);
220 } else if (TextUtils.isEmpty(mView.getQuery())) {
221 cancelSearch();
222 }
223 }
224 }
225
226 @Override
227 public boolean onQueryTextChange(String newText) {
228 return false;
229 }
Aga Wronskaaf5ace52016-02-17 13:50:42 -0800230
231 String getCurrentSearch() {
232 return mCurrentSearch;
233 }
234
Aga Wronska8788dad2016-01-15 17:30:15 -0800235}