/* * Copyright (C) 2014 Clark Scheff * * 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.scheffsblend.iconfilters; import android.animation.AnimatorInflater; import android.animation.AnimatorSet; import android.app.Activity; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import au.com.glassechidna.velocityviewpager.VelocityViewPager; import com.scheffsblend.iconfilters.viewpagerindicator.CirclePageIndicator; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class FilterDesignerActivity extends Activity { private static final String TAG_FILTER = "filter"; private static final String FILTER_HUE = "hue"; private static final String FILTER_SATURATION = "saturation"; private static final String FILTER_INVERT = "invert"; private static final String FILTER_BRIGHTNESS = "brightness"; private static final String FILTER_CONTRAST = "contrast"; private static final String FILTER_ALPHA = "alpha"; private static final String FILTER_TINT = "tint"; private static final long PULSE_ADD_BUTTON_INITIAL_DELAY = 3000; private static final long PULSE_ADD_BUTTON_DELAY = 5000; private IconPagerAdapter mIconAdapter; private FilterListAdapter mFilterAdapter; private ImageButton mAddFilterButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); VelocityViewPager pager = (VelocityViewPager) findViewById(R.id.icon_pager); mIconAdapter = new IconPagerAdapter(this); pager.setAdapter(mIconAdapter); mIconAdapter.notifyDataSetChanged(); DynamicListView listView = (DynamicListView) findViewById(R.id.list_view); mFilterAdapter = new FilterListAdapter(this); listView.setAdapter(mFilterAdapter); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setFilterList(mFilterAdapter.getFilterList()); mAddFilterButton = (ImageButton) findViewById(R.id.add_filter); mAddFilterButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mAddFilterButton.removeCallbacks(mPulseAddButtonRunnable); String[] items = getResources().getStringArray(R.array.filters); AlertDialog.Builder b = new AlertDialog.Builder(FilterDesignerActivity.this); b.setTitle(R.string.filter_picker_title); b.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); mFilterAdapter.addFilter(i); } }); b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }); b.create().show(); } }); mAddFilterButton.postDelayed(mPulseAddButtonRunnable, PULSE_ADD_BUTTON_INITIAL_DELAY); CirclePageIndicator indicator = (CirclePageIndicator) findViewById(R.id.pager_indicator); indicator.setViewPager(pager); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.show_xml: showXml(); return true; default: return super.onOptionsItemSelected(item); } } public void updateColorFilter(ColorMatrix cm) { if (mIconAdapter != null) mIconAdapter.setColorMatrix(cm); } private Runnable mPulseAddButtonRunnable = new Runnable() { @Override public void run() { AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator( FilterDesignerActivity.this, R.animator.pulse_button); set.setTarget(mAddFilterButton); set.start(); mAddFilterButton.postDelayed(mPulseAddButtonRunnable, PULSE_ADD_BUTTON_DELAY); } }; private void showXml() { ArrayList<FilterListAdapter.FilterItem> filters = mFilterAdapter.getFilterList(); StringBuilder sb = new StringBuilder(); String name = null; String value = null; for (FilterListAdapter.FilterItem item : filters) { switch (item.filterType) { case FilterListAdapter.FILTER_TYPE_HUE: name = FILTER_HUE; value = "" + ((FilterListAdapter.AdjustableFilter) item).current; break; case FilterListAdapter.FILTER_TYPE_SATURATION: name = FILTER_SATURATION; value = "" + ((FilterListAdapter.AdjustableFilter) item).current; break; case FilterListAdapter.FILTER_TYPE_BRIGHTNESS: name = FILTER_BRIGHTNESS; value = "" + ((FilterListAdapter.AdjustableFilter) item).current; break; case FilterListAdapter.FILTER_TYPE_CONTRAST: name = FILTER_CONTRAST; value = "" + ((FilterListAdapter.AdjustableFilter) item).current; break; case FilterListAdapter.FILTER_TYPE_ALPHA: name = FILTER_ALPHA; value = "" + ((FilterListAdapter.AdjustableFilter) item).current; break; case FilterListAdapter.FILTER_TYPE_INVERT: name = FILTER_INVERT; value = ((FilterListAdapter.ToggleableFilter) item).enabled ? "true" : "false"; break; case FilterListAdapter.FILTER_TYPE_TINT: name = FILTER_TINT; value = String.format("#%08x", ((FilterListAdapter.ValueFilter) item).value); break; } sb.append(String.format("<%s name=\"%s\">%s</%s>\r\n", TAG_FILTER, name, value, TAG_FILTER)); } if (filters.size() == 0) { sb.append(getString(R.string.dialog_show_xml_empty)); } AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(filters.size() > 0 ? R.string.dialog_show_xml_title : R.string.dialog_show_xml_empty_title); builder.setMessage(sb.toString()); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }); builder.create().show(); } private class IconPagerAdapter extends PagerAdapter { private static final int ICONS_PER_PAGE = 5; List<ResolveInfo> mAppList; Context mContext; PackageManager mPm; LayoutInflater mInflater; private ColorMatrixColorFilter mColorFilter; public IconPagerAdapter(Context context) { mContext = context; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mPm = context.getPackageManager(); new FetchResolveInfosTask(context, this).execute(); } public void setAppList(List<ResolveInfo> list) { mAppList = list; notifyDataSetChanged(); } public void setColorMatrix(ColorMatrix cm) { mColorFilter = cm != null ? new ColorMatrixColorFilter(cm) : null; notifyDataSetChanged(); } @Override public int getCount() { if (mAppList == null) return 0; int count = mAppList.size(); return (int) Math.ceil((float)count / ICONS_PER_PAGE); } @Override public boolean isViewFromObject(View view, Object o) { return o == view; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public Object instantiateItem(ViewGroup container, int position) { View page = mInflater.inflate(R.layout.icon_page_item, container, false); for (int i = 0; i < ICONS_PER_PAGE; i++) { int index = position * ICONS_PER_PAGE + i; if (mAppList.size() <= index) continue; ImageView icon = (ImageView) ((ViewGroup) page).getChildAt(i); if (icon != null) { ResolveInfo info = mAppList.get(index); try { Drawable d = mPm.getActivityIcon( new ComponentName(info.activityInfo.packageName, info.activityInfo.name)); if (d instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) d; bd.setColorFilter(mColorFilter); } icon.setImageDrawable(d); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } } container.addView(page); return page; } @Override public void destroyItem(ViewGroup container, int position, Object object) { if (object instanceof View) { container.removeView((View) object); } } } class FetchResolveInfosTask extends AsyncTask { private Context mContext; private List<ResolveInfo> mAppList; private IconPagerAdapter mIconAdapter; public FetchResolveInfosTask(Context context, IconPagerAdapter adapter) { mContext = context; this.mIconAdapter = adapter; } @Override protected Object doInBackground(Object[] objects) { PackageManager pm = mContext.getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); mAppList = pm.queryIntentActivities(mainIntent, 0); Collections.sort(mAppList, new ResolveInfo.DisplayNameComparator(pm)); return null; } @Override protected void onPostExecute(Object o) { if (mAppList != null && mAppList.size() > 0) { this.mIconAdapter.setAppList(mAppList); } } } }