/* * 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.launcher; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import com.android.launcher.catalogue.AppCatalogueFilter; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.TextView; import java.util.HashMap; /** * GridView adapter to show the list of applications and shortcuts */ public class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> { private final LayoutInflater mInflater; private Drawable mBackground; private int mTextColor = 0; private boolean useThemeTextColor = false; private Typeface themeFont=null; // TODO: Check if allItems is used somewhere else! public static ArrayList<ApplicationInfo> allItems = new ArrayList<ApplicationInfo>(); private static HashMap<ApplicationInfo, View> viewCache = new HashMap<ApplicationInfo, View>(); private CatalogueFilter filter; private static final Collator sCollator = Collator.getInstance(); private AppCatalogueFilter mCatalogueFilter; private boolean mWithDrawingCache = false; public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps, AppCatalogueFilter filter) { super(context, 0, apps); mCatalogueFilter = filter; mInflater = LayoutInflater.from(context); // ADW: Load textcolor and bubble color from theme String themePackage = AlmostNexusSettingsHelper.getThemePackageName( getContext(), Launcher.THEME_DEFAULT); if (!themePackage.equals(Launcher.THEME_DEFAULT)) { Resources themeResources = null; try { themeResources = getContext().getPackageManager() .getResourcesForApplication(themePackage); } catch (NameNotFoundException e) { // e.printStackTrace(); } if (themeResources != null) { int textColorId = themeResources.getIdentifier( "drawer_text_color", "color", themePackage); if (textColorId != 0) { mTextColor = themeResources.getColor(textColorId); useThemeTextColor = true; } mBackground = IconHighlights.getDrawable(getContext(), IconHighlights.TYPE_DRAWER); try{ themeFont=Typeface.createFromAsset(themeResources.getAssets(), "themefont.ttf"); }catch (RuntimeException e) { // TODO: handle exception } } } } public void buildViewCache(ViewGroup parent) { for(int i = 0; i < getCount(); i++) { final ApplicationInfo info = getItem(i); addToViewCache(parent, info); } } private void addToViewCache(ViewGroup parent, ApplicationInfo info) { if (!info.filtered) { info.icon = Utilities.createIconThumbnail(info.icon, getContext()); info.filtered = true; } View convertView = mInflater.inflate(R.layout.application_boxed, parent, false); convertView.setDrawingCacheEnabled(mWithDrawingCache); viewCache.put(info, convertView); final TextView textView = (TextView) convertView; textView.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null); textView.setText(info.title); if (useThemeTextColor) { textView.setTextColor(mTextColor); } //ADW: Custom font if(themeFont!=null) textView.setTypeface(themeFont); // so i'd better not use it, sorry themers if (mBackground != null) convertView.setBackgroundDrawable(mBackground); } public void setChildDrawingCacheEnabled(boolean aValue) { if (mWithDrawingCache != aValue) { mWithDrawingCache = aValue; for(View v : viewCache.values()) { v.setDrawingCacheEnabled(aValue); if(aValue) v.buildDrawingCache(); else v.destroyDrawingCache(); } } } @Override public View getView(int position, View convertView, ViewGroup parent) { final ApplicationInfo info = getItem(position); if (viewCache.isEmpty()) buildViewCache(parent); if (!viewCache.containsKey(info)) addToViewCache(parent, info); View result = viewCache.get(info); //ADW:Counters ((CounterTextView)result).setCounter(info.counter, info.counterColor); return result; } @Override public void add(ApplicationInfo info) { //check allItems before added. It is a fix for all of the multi-icon issue, but will //lose performance. Anyway, we do not expected to have many applications. synchronized (allItems) { /*if (!allItems.contains(info)) { changed = true; allItems.add(info); Collections.sort(allItems,new ApplicationInfoComparator()); }*/ int count=allItems.size(); boolean found=false; for(int i=0;i<count;i++){ ApplicationInfo athis=allItems.get(i); if(info.intent.getComponent()!=null){ if(athis.intent.getComponent().flattenToString().equals( info.intent.getComponent().flattenToString())){ found=true; break; } } } if(!found){ allItems.add(info); Collections.sort(allItems,new ApplicationInfoComparator()); updateDataSet(); } } } //2 super functions, to make sure related add/clear do not affect allItems. //in current Froyo/Eclair, it is not necessary. void superAdd(ApplicationInfo info) { if(info!=null) super.add(info); } void superClear() { super.clear(); } @Override public void remove(ApplicationInfo info) { synchronized (allItems) { //allItems.remove(info); int count=allItems.size(); for(int i=0;i<count;i++){ ApplicationInfo athis=allItems.get(i); if(info.intent.getComponent()!=null){ if(athis.intent.getComponent().flattenToString().equals( info.intent.getComponent().flattenToString())){ viewCache.remove(athis); allItems.remove(i); Collections.sort(allItems,new ApplicationInfoComparator()); updateDataSet(); break; } } } } } private boolean appInGroup(String s) { return mCatalogueFilter.checkAppInGroup(s); } private String getComponentName(ApplicationInfo info) { if (info == null || info.intent == null) return null; ComponentName cmpName = info.intent.getComponent(); if (cmpName == null) return null; return cmpName.flattenToString(); } private void filterApps(ArrayList<ApplicationInfo> theFiltered, ArrayList<ApplicationInfo> theItems) { theFiltered.clear(); //AppGrpUtils.checkAndInitGrp(); if (theItems != null) { int length = theItems.size(); for (int i = 0; i < length; i++) { ApplicationInfo info = theItems.get(i); String s = getComponentName(info); if (s != null && appInGroup(s)) { theFiltered.add(info); } } } } //filter,sort,update public void updateDataSet() { getFilter().filter(null); } @Override public Filter getFilter() { if (filter == null) filter = new CatalogueFilter(); return filter; } public synchronized void setCatalogueFilter(AppCatalogueFilter filter) { if (filter != mCatalogueFilter) { mCatalogueFilter = filter; updateDataSet(); notifyDataSetChanged(); } } public AppCatalogueFilter getCatalogueFilter() { return mCatalogueFilter; } private class CatalogueFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults result = new FilterResults(); ArrayList<ApplicationInfo> filt = new ArrayList<ApplicationInfo>(); synchronized (allItems) { filterApps(filt, allItems); } result.values = filt; result.count = filt.size(); return result; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { // NOTE: this function is *always* called from the UI thread. ArrayList<ApplicationInfo> localFiltered =(ArrayList<ApplicationInfo>) results.values; setNotifyOnChange(false); superClear(); // there could be a serious sync issue. // very bad for (int i = 0;i < results.count; i++) { superAdd(localFiltered.get(i)); } notifyDataSetChanged(); } } static class ApplicationInfoComparator implements Comparator<ApplicationInfo> { public final int compare(ApplicationInfo a, ApplicationInfo b) { return sCollator.compare(a.title.toString(), b.title.toString()); } } }