/* * Copyright 2011 - AndroidQuery.com (tinyeeliu@gmail.com) * * 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.external.androidquery.util; import java.io.File; import java.util.Comparator; import android.app.Activity; import android.app.Dialog; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.Adapter; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.Gallery; import android.widget.ListAdapter; import android.widget.ProgressBar; import com.external.androidquery.AQuery; import com.external.androidquery.callback.BitmapAjaxCallback; /** * AQuery internal use only. A shared listener class to reduce the number of classes. * */ public class Common implements Comparator<File>, Runnable, OnClickListener, OnLongClickListener, OnItemClickListener, OnScrollListener, OnItemSelectedListener, TextWatcher{ private Object handler; private String method; private Object[] params; private boolean fallback; private Class<?>[] sig; private int methodId; public Common forward(Object handler, String callback, boolean fallback, Class<?>[] sig){ this.handler = handler; this.method = callback; this.fallback = fallback; this.sig = sig; return this; } public Common method(int methodId, Object... params){ this.methodId = methodId; this.params = params; return this; } private Object invoke(Object... args){ if(method != null){ Object[] input = args; if(params != null){ input = params; } Object cbo = handler; if(cbo == null){ cbo = this; } Object result = AQUtility.invokeHandler(cbo, method, fallback, true, sig, input); return result; }else if(methodId != 0){ switch(methodId){ case CLEAN_CACHE: AQUtility.cleanCache((File) params[0], (Long) params[1], (Long) params[2]); break; case STORE_FILE: AQUtility.store((File) params[0], (byte[]) params[1]); break; } } return null; } @Override public int compare(File f1, File f2) { long m1 = f1.lastModified(); long m2 = f2.lastModified(); if(m2 > m1){ return 1; }else if(m2 == m1){ return 0; }else{ return -1; } } protected static final int STORE_FILE = 1; protected static final int CLEAN_CACHE = 2; @Override public void run() { invoke(); } @Override public void onClick(View v) { invoke(v); } @Override public boolean onLongClick(View v) { Object result = invoke(v); if(result instanceof Boolean){ return (Boolean) result; } return false; } @Override public void onItemClick(AdapterView<?> parent, View v, int pos, long id) { invoke(parent, v, pos, id); } private int scrollState = OnScrollListener.SCROLL_STATE_IDLE; private OnScrollListener osl; @Override public void onScroll(AbsListView view, int first, int visibleItemCount, int totalItemCount) { checkScrolledBottom(view, scrollState); if(osl != null) osl.onScroll(view, first, visibleItemCount, totalItemCount); } public int getScrollState(){ return scrollState; } public void forward(OnScrollListener listener){ this.osl = listener; } private int lastBottom; private void checkScrolledBottom(AbsListView view, int scrollState){ int cc = view.getCount(); int last = view.getLastVisiblePosition(); if(scrollState == OnScrollListener.SCROLL_STATE_IDLE && cc == last + 1){ if(last != lastBottom){ lastBottom = last; invoke(view, scrollState); } }else{ lastBottom = -1; } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState; checkScrolledBottom(view, scrollState); if(view instanceof ExpandableListView){ onScrollStateChanged((ExpandableListView) view, scrollState); }else{ onScrollStateChanged2(view, scrollState); } if(osl != null) osl.onScrollStateChanged(view, scrollState); } private void onScrollStateChanged(ExpandableListView elv, int scrollState){ elv.setTag(AQuery.TAG_NUM, scrollState); if(scrollState == SCROLL_STATE_IDLE){ int first = elv.getFirstVisiblePosition(); int last = elv.getLastVisiblePosition(); int count = last - first; ExpandableListAdapter ela = elv.getExpandableListAdapter(); for(int i = 0; i <= count; i++){ long packed = elv.getExpandableListPosition(i + first); int group = ExpandableListView.getPackedPositionGroup(packed); int child = ExpandableListView.getPackedPositionChild(packed); if(group >= 0){ View convertView = elv.getChildAt(i); Long targetPacked = (Long) convertView.getTag(AQuery.TAG_NUM); if(targetPacked != null && targetPacked.longValue() == packed){ if(child == -1){ ela.getGroupView(group, elv.isGroupExpanded(group), convertView, elv); }else{ ela.getChildView(group, child, child == ela.getChildrenCount(group) - 1, convertView, elv); } convertView.setTag(AQuery.TAG_NUM, null); }else{ //AQUtility.debug("skip!"); } } } } } private void onScrollStateChanged2(AbsListView lv, int scrollState){ lv.setTag(AQuery.TAG_NUM, scrollState); if(scrollState == SCROLL_STATE_IDLE){ int first = lv.getFirstVisiblePosition(); int last = lv.getLastVisiblePosition(); int count = last - first; ListAdapter la = lv.getAdapter(); for(int i = 0; i <= count; i++){ long packed = i + first; View convertView = lv.getChildAt(i); Number targetPacked = (Number) convertView.getTag(AQuery.TAG_NUM); if(targetPacked != null){ la.getView((int) packed, convertView, lv); convertView.setTag(AQuery.TAG_NUM, null); }else{ //AQUtility.debug("skip!"); } } } } public static boolean shouldDelay(int groupPosition, int childPosition, View convertView, ViewGroup parent, String url){ if(url == null || BitmapAjaxCallback.isMemoryCached(url)){ return false; } AbsListView lv = (AbsListView) parent; OnScrollListener sl = (OnScrollListener) parent.getTag(AQuery.TAG_SCROLL_LISTENER); if(sl == null){ sl = new Common(); lv.setOnScrollListener(sl); parent.setTag(AQuery.TAG_SCROLL_LISTENER, sl); } Integer scrollState = (Integer) lv.getTag(AQuery.TAG_NUM); if(scrollState == null || scrollState == OnScrollListener.SCROLL_STATE_IDLE || scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){ return false; } long packed = childPosition; if(parent instanceof ExpandableListView){ packed = ExpandableListView.getPackedPositionForChild(groupPosition, childPosition); } convertView.setTag(AQuery.TAG_NUM, packed); //TODO add draw count and skip drawing list if possible return true; } public static boolean shouldDelay(int position, View convertView, ViewGroup parent, String url){ if(parent instanceof Gallery){ return shouldDelayGallery(position, convertView, parent, url); }else{ return shouldDelay(-2, position, convertView, parent, url); } } public static boolean shouldDelay(View convertView, ViewGroup parent, String url, float velocity, boolean fileCheck){ return shouldDelay(-1, convertView, parent, url); } private static boolean shouldDelayGallery(int position, View convertView, ViewGroup parent, String url){ if(url == null || BitmapAjaxCallback.isMemoryCached(url)){ return false; } Gallery gallery = (Gallery) parent; Integer selected = (Integer) gallery.getTag(AQuery.TAG_NUM); if(selected == null){ selected = 0; gallery.setTag(AQuery.TAG_NUM, 0); gallery.setCallbackDuringFling(false); Common common = new Common(); common.listen(gallery); } int first = gallery.getFirstVisiblePosition(); int last = gallery.getLastVisiblePosition(); int diff = last - first; int delta = (diff / 2) + 1; int from = selected - delta; int to = selected + delta; if(from < 0){ //shift window back to positive region to = to - from; from = 0; } if((position >= from && position <= to)){ //AQUtility.debug("yes", position + ":" + from + "." + to); convertView.setTag(AQuery.TAG_NUM, position); return false; } //AQUtility.debug("no", position + ":" + from + "." + to); convertView.setTag(AQuery.TAG_NUM, null); return true; } @Override public void afterTextChanged(Editable s) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { invoke(s, start, before, count); } private OnItemSelectedListener galleryListener; private boolean galleryListen = false; public void listen(Gallery gallery){ galleryListener = gallery.getOnItemSelectedListener(); galleryListen = true; gallery.setOnItemSelectedListener(this); } @Override public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) { invoke(parent, v, pos, id); if(galleryListener != null){ galleryListener.onItemSelected(parent, v, pos, id); } if(galleryListen){ Integer selected = (Integer) parent.getTag(AQuery.TAG_NUM); if(selected != pos){ Adapter adapter = parent.getAdapter(); parent.setTag(AQuery.TAG_NUM, pos); int count = parent.getChildCount(); //AQUtility.debug("redrawing", count); int first = parent.getFirstVisiblePosition(); for(int i = 0; i < count; i++){ View convertView = parent.getChildAt(i); int drawPos = first + i; Integer lastDrawn = (Integer) convertView.getTag(AQuery.TAG_NUM); if(lastDrawn != null && lastDrawn.intValue() == drawPos){ //AQUtility.debug("skip", drawPos); }else{ //AQUtility.debug("redraw", drawPos); adapter.getView(drawPos, convertView, parent); } } } } } @Override public void onNothingSelected(AdapterView<?> arg0) { if(galleryListener != null){ galleryListener.onNothingSelected(arg0); } } public static void showProgress(Object p, String url, boolean show){ if(p != null){ if(p instanceof View){ View pv = (View) p; ProgressBar pbar = null; if(p instanceof ProgressBar){ pbar = (ProgressBar) p; } if(show){ pv.setTag(AQuery.TAG_URL, url); pv.setVisibility(View.VISIBLE); if(pbar != null){ pbar.setProgress(0); pbar.setMax(100); } }else{ Object tag = pv.getTag(AQuery.TAG_URL); if(tag == null || tag.equals(url)){ pv.setTag(AQuery.TAG_URL, null); if(pbar == null || pbar.isIndeterminate()){ pv.setVisibility(View.GONE); } } } }else if(p instanceof Dialog){ Dialog pd = (Dialog) p; AQuery aq = new AQuery(pd.getContext()); if(show){ aq.show(pd); }else{ aq.dismiss(pd); } }else if(p instanceof Activity){ Activity act = (Activity) p;; act.setProgressBarIndeterminateVisibility(show); act.setProgressBarVisibility(show); if(show){ act.setProgress(0); } } } } }