blob: 9112445238a427f48b8a421a8c05fded8ac29657 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quicksearchbox.ui;
import com.android.quicksearchbox.Corpus;
import com.android.quicksearchbox.Promoter;
import com.android.quicksearchbox.R;
import com.android.quicksearchbox.Suggestions;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
import android.widget.ImageView;
import android.widget.PopupMenu;
/**
* Two-pane variant for the search activity view.
*/
public class SearchActivityViewTwoPane extends SearchActivityView {
private static final int ENTRY_ANIMATION_START_DELAY = 150; // in millis
private static final int ENTRY_ANIMATION_DURATION = 150; // in millis
private static final float ANIMATION_STARTING_WIDTH_FACTOR = 0.5f;
private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
private ImageView mMenuButton;
// View that shows the results other than the query completions
private ClusteredSuggestionsView mResultsView;
private SuggestionsAdapter<ExpandableListAdapter> mResultsAdapter;
private View mResultsHeader;
private View mSearchPlate;
private boolean mJustCreated;
public SearchActivityViewTwoPane(Context context) {
super(context);
}
public SearchActivityViewTwoPane(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SearchActivityViewTwoPane(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuButton = (ImageView) findViewById(R.id.menu_button);
mMenuButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showPopupMenu();
}
});
mResultsView = (ClusteredSuggestionsView) findViewById(R.id.shortcuts);
mResultsAdapter = createClusteredSuggestionsAdapter();
mResultsAdapter.getListAdapter().registerDataSetObserver(new DataSetObserver(){
@Override
public void onChanged() {
mResultsView.expandAll();
}
});
mResultsView.setOnKeyListener(new SuggestionsViewKeyListener());
mResultsView.setFocusable(true);
mResultsHeader = findViewById(R.id.shortcut_title);
mSearchPlate = findViewById(R.id.left_pane);
mJustCreated = true;
View dismissBg = findViewById(R.id.dismiss_bg);
dismissBg.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isQueryEmpty() && mExitClickListener != null) {
mExitClickListener.onClick(v);
}
}
});
}
private void showPopupMenu() {
PopupMenu popup = new PopupMenu(getContext(), mMenuButton);
Menu menu = popup.getMenu();
getActivity().createMenuItems(menu, false);
popup.show();
}
protected SuggestionsAdapter<ExpandableListAdapter> createClusteredSuggestionsAdapter() {
return new DelayingSuggestionsAdapter<ExpandableListAdapter>(
new ClusteredSuggestionsAdapter(
getQsbApplication().getSuggestionViewFactory(),
getContext()));
}
@Override
public void onResume() {
if (mJustCreated) {
setupEntryAnimations();
mJustCreated = false;
}
}
@Override
public void onPause() {
super.onPause();
getActivity().overridePendingTransition(R.anim.fade_in_fast, R.anim.fade_out_fast);
}
private void setupEntryAnimations() {
// TODO: Use the left/top of the source bounds to start the animation from
final int endingWidth = getResources().getDimensionPixelSize(R.dimen.suggestions_width);
final int startingWidth = (int) (endingWidth * ANIMATION_STARTING_WIDTH_FACTOR);
ViewGroup.LayoutParams params = mSearchPlate.getLayoutParams();
params.width = startingWidth;
mSearchPlate.setLayoutParams(params);
Animator animator = ObjectAnimator.ofInt(mSearchPlate, "alpha", 0, 255);
animator.setDuration(ENTRY_ANIMATION_DURATION);
((ValueAnimator)animator).addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animator) {
ViewGroup.LayoutParams params = mSearchPlate.getLayoutParams();
params.width = startingWidth
+ (int) ((Integer) animator.getAnimatedValue() / 255f
* (endingWidth - startingWidth));
mSearchPlate.setLayoutParams(params);
}
});
animator.setStartDelay(ENTRY_ANIMATION_START_DELAY);
animator.start();
}
@Override
public void onStop() {
}
@Override
public void start() {
super.start();
mResultsAdapter.getListAdapter().registerDataSetObserver(new ResultsObserver());
mResultsView.setSuggestionsAdapter(mResultsAdapter);
}
@Override
public void destroy() {
mResultsView.setSuggestionsAdapter(null);
super.destroy();
}
@Override
protected Drawable getVoiceSearchIcon() {
ComponentName voiceSearch = getVoiceSearch().getComponent();
if (voiceSearch != null) {
// this code copied from Launcher to get the same icon that's displayed on home screen
try {
PackageManager packageManager = getContext().getPackageManager();
// Look for the toolbar icon specified in the activity meta-data
Bundle metaData = packageManager.getActivityInfo(
voiceSearch, PackageManager.GET_META_DATA).metaData;
if (metaData != null) {
int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
if (iconResId != 0) {
Resources res = packageManager.getResourcesForActivity(voiceSearch);
if (DBG) Log.d(TAG, "Got toolbar icon from Voice Search");
return res.getDrawable(iconResId);
}
}
} catch (NameNotFoundException e) {
// Do nothing
}
}
if (DBG) Log.d(TAG, "Failed to get toolbar icon from Voice Search; using default.");
return super.getVoiceSearchIcon();
}
@Override
public void considerHidingInputMethod() {
// Don't hide keyboard when interacting with suggestions list
}
@Override
public void hideSuggestions() {
// Never hiding suggestions view in two-pane UI
}
@Override
public void showSuggestions() {
// Never hiding suggestions view in two-pane UI
}
@Override
public void showCorpusSelectionDialog() {
// not used
}
@Override
public void clearSuggestions() {
super.clearSuggestions();
mResultsAdapter.setSuggestions(null);
}
@Override
public void setMaxPromotedResults(int maxPromoted) {
mResultsView.setLimitSuggestionsToViewHeight(false);
mResultsAdapter.setMaxPromoted(maxPromoted);
}
@Override
public void limitResultsToViewHeight() {
mResultsView.setLimitSuggestionsToViewHeight(true);
}
@Override
public void setSuggestionClickListener(SuggestionClickListener listener) {
super.setSuggestionClickListener(listener);
mResultsAdapter.setSuggestionClickListener(listener);
}
@Override
public void setSuggestions(Suggestions suggestions) {
super.setSuggestions(suggestions);
suggestions.acquire();
mResultsAdapter.setSuggestions(suggestions);
}
@Override
protected void setCorpus(Corpus corpus) {
super.setCorpus(corpus);
mResultsAdapter.setPromoter(createResultsPromoter());
}
@Override
protected Promoter createSuggestionsPromoter() {
return getQsbApplication().createWebPromoter();
}
protected Promoter createResultsPromoter() {
Corpus corpus = getCorpus();
if (corpus == null) {
return getQsbApplication().createResultsPromoter();
} else {
return getQsbApplication().createSingleCorpusResultsPromoter(corpus);
}
}
protected void onResultsChanged() {
checkHideResultsHeader();
}
@Override
protected void updateQueryTextView(boolean queryEmpty) {
super.updateQueryTextView(queryEmpty);
if (mSearchCloseButton == null) return;
if (queryEmpty) {
mSearchCloseButton.setImageResource(R.drawable.ic_clear_disabled);
} else {
mSearchCloseButton.setImageResource(R.drawable.ic_clear);
}
}
private void checkHideResultsHeader() {
if (mResultsHeader != null) {
if (!mResultsAdapter.isEmpty()) {
if (DBG) Log.d(TAG, "Results non-empty");
mResultsHeader.setVisibility(VISIBLE);
} else {
if (DBG) Log.d(TAG, "Results empty");
mResultsHeader.setVisibility(INVISIBLE);
}
}
}
@Override
public Corpus getSearchCorpus() {
return getWebCorpus();
}
protected class ResultsObserver extends DataSetObserver {
@Override
public void onChanged() {
onResultsChanged();
}
}
}