/* * Copyright (C) 2008 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.launcher2; import com.android.launcher.R; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.GridView; import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; import java.util.Collections; public class AllApps2D extends RelativeLayout implements AllAppsView, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener, View.OnKeyListener, DragSource { private static final String TAG = "Launcher.AllApps2D"; private static final boolean DEBUG = false; private Launcher mLauncher; private DragController mDragController; private GridView mGrid; /** All applications in the system (we might only be showing a subset) */ private ArrayList mAllAppsList = new ArrayList(); /** Currently visible applications in the grid */ private ArrayList mVisibleAppsList = new ArrayList(); public enum AppType { APP, GAME, DOWNLOADED, ALL }; private AppType mCurrentFilter = AppType.ALL; // preserve compatibility with 3D all apps: // 0.0 -> hidden // 1.0 -> shown and opaque // intermediate values -> partially shown & partially opaque private float mZoom; private AppsAdapter mAppsAdapter; // ------------------------------------------------------------ public static class HomeButton extends ImageButton { public HomeButton(Context context, AttributeSet attrs) { super(context, attrs); } @Override public View focusSearch(int direction) { if (direction == FOCUS_UP) return super.focusSearch(direction); return null; } } public class AppsAdapter extends ArrayAdapter { private final LayoutInflater mInflater; public AppsAdapter(Context context, ArrayList apps) { super(context, 0, apps); mInflater = LayoutInflater.from(context); } @Override public View getView(int position, View convertView, ViewGroup parent) { final ApplicationInfo info = getItem(position); if (convertView == null) { convertView = mInflater.inflate(R.layout.application_boxed, parent, false); } // if (!info.filtered) { // info.icon = Utilities.createIconThumbnail(info.icon, getContext()); // info.filtered = true; // } final TextView textView = (TextView) convertView; if (DEBUG) { Log.d(TAG, "icon bitmap = " + info.iconBitmap + " density = " + info.iconBitmap.getDensity()); } info.iconBitmap.setDensity(Bitmap.DENSITY_NONE); textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null); textView.setText(info.title); return convertView; } } public AllApps2D(Context context, AttributeSet attrs) { super(context, attrs); setVisibility(View.GONE); setSoundEffectsEnabled(false); mAppsAdapter = new AppsAdapter(getContext(), mVisibleAppsList); } @Override protected void onFinishInflate() { try { mGrid = (GridView)findViewWithTag("all_apps_2d_grid"); if (mGrid == null) throw new Resources.NotFoundException(); mGrid.setOnItemClickListener(this); mGrid.setOnItemLongClickListener(this); // The home button is optional; some layouts might not use it ImageButton homeButton = (ImageButton) findViewWithTag("all_apps_2d_home"); if (homeButton != null) { homeButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { mLauncher.showWorkspace(true); } }); } } catch (Resources.NotFoundException e) { Log.e(TAG, "Can't find necessary layout elements for AllApps2D"); } setOnKeyListener(this); } public AllApps2D(Context context, AttributeSet attrs, int defStyle) { this(context, attrs); } @Override public void setup(Launcher launcher, DragController dragController) { mLauncher = launcher; mDragController = dragController; } public boolean onKey(View v, int keyCode, KeyEvent event) { if (!isVisible()) return false; switch (keyCode) { case KeyEvent.KEYCODE_BACK: mLauncher.showWorkspace(true); break; default: return false; } return true; } public void onItemClick(AdapterView parent, View v, int position, long id) { ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position); mLauncher.startActivitySafely(app.intent, app); } public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { if (!view.isInTouchMode()) { return false; } ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position); app = new ApplicationInfo(app); mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY); mLauncher.showWorkspace(true); return true; } protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect prev) { if (gainFocus) { mGrid.requestFocus(); } } @Override public void onDragViewVisible() { } @Override public void onDropCompleted(View target, Object dragInfo, boolean success) { } /** * Zoom to the specifed level. * * @param zoom [0..1] 0 is hidden, 1 is open */ public void zoom(float zoom, boolean animate) { // Log.d(TAG, "zooming " + ((zoom == 1.0) ? "open" : "closed")); cancelLongPress(); mZoom = zoom; if (isVisible()) { getParent().bringChildToFront(this); setVisibility(View.VISIBLE); mGrid.setAdapter(mAppsAdapter); if (animate) { startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_in)); } else { onAnimationEnd(); } } else { if (animate) { startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.all_apps_2d_fade_out)); } else { onAnimationEnd(); } } } protected void onAnimationEnd() { if (!isVisible()) { setVisibility(View.GONE); mGrid.setAdapter(null); mZoom = 0.0f; } else { mZoom = 1.0f; } mLauncher.zoomed(mZoom); } public boolean isVisible() { return mZoom > 0.001f; } public boolean isAnimating() { return (getAnimation() != null); } public void setApps(ArrayList list) { mAllAppsList.clear(); addApps(list); filterApps(mCurrentFilter); } public void addApps(ArrayList list) { final int N = list.size(); for (int i=0; i list) { final int N = list.size(); for (int i=0; i= 0) { mAllAppsList.remove(index); } else { Log.w(TAG, "couldn't find a match for item \"" + item + "\""); // Try to recover. This should keep us from crashing for now. } } filterApps(mCurrentFilter); } public void updateApps(ArrayList list) { // Just remove and add, because they may need to be re-sorted. removeApps(list); addApps(list); } public void filterApps(AppType appType) { mCurrentFilter = appType; mAppsAdapter.setNotifyOnChange(false); mVisibleAppsList.clear(); if (appType == AppType.ALL) { mVisibleAppsList.addAll(mAllAppsList); } else if (appType == AppType.DOWNLOADED) { for (ApplicationInfo info : mAllAppsList) { if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) { mVisibleAppsList.add(info); } } } mAppsAdapter.notifyDataSetChanged(); } private static int findAppByComponent(ArrayList list, ApplicationInfo item) { ComponentName component = item.intent.getComponent(); final int N = list.size(); for (int i=0; i