package mobi.urika.android.widget;
import java.util.HashMap;
import mobi.urika.android.content.LauncherIntent;
import mobi.urika.android.widget.WidgetListAdapter.ViewHolder;
import android.app.Activity;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.drawable.AnimationDrawable;
import android.net.Uri;
import android.os.Handler;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Animation.AnimationListener;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.OnItemClickListener;
/**
*
* @author Bo & Koxx
*
*/
public abstract class WidgetSpace extends ViewGroup {
private static final String TAG = "WidgetSpace";
private static final boolean LOGD = true;
private static final boolean CLEAR_DATA_CACHE = true;
private static final boolean FORCE_FREE_MEMORY = true;
protected boolean mAllowLongPress;
protected int mCurrentScreen;
public WidgetSpace(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WidgetSpace(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WidgetSpace(Context context) {
super(context);
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
// do nothing here
}
public abstract Activity getLauncherActivity();
/**
*
*/
BroadcastReceiver mAnimationProvider = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("AnimationProvider", "" + intent);
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (widgetId < 0)
widgetId = intent.getIntExtra(LauncherIntent.Extra.EXTRA_APPWIDGET_ID, -1);
if (widgetId < 0) {
Log.e(TAG, "Scroll Provider cannot get a legal widget id");
return;
}
AppWidgetHostView widgetView = null;
try {
// Find widget view in the current view
widgetView = findWidget(mCurrentScreen, widgetId);
// Do corresponding animation on it
if (LauncherIntent.Action.ACTION_START_FRAME_ANIMATION.equals(action)) {
actFrameAnimation(widgetView, intent.getIntExtra(
LauncherIntent.Extra.EXTRA_IMAGEVIEW_ID, 0), intent, true);
} else if (LauncherIntent.Action.ACTION_STOP_FRAME_ANIMATION.equals(action)) {
actFrameAnimation(widgetView, intent.getIntExtra(
LauncherIntent.Extra.EXTRA_IMAGEVIEW_ID, 0), intent, false);
} else if (LauncherIntent.Action.ACTION_START_TWEEN_ANIMATION.equals(action)) {
startTweenAnimation(widgetView, intent.getIntExtra(
LauncherIntent.Extra.EXTRA_VIEW_ID, 0), intent);
}
} catch (FrameAnimationException ae) {
// Reset the action and broadcast
if (widgetView != null)
intent.setComponent(widgetView.getAppWidgetInfo().provider);
getContext().sendBroadcast(
intent.setAction(ae.mAction).putExtra(
LauncherIntent.Extra.EXTRA_ERROR_MESSAGE, ae.getMessage()));
} catch (TweenAnimationException ae) {
// Reset the action and broadcast
if (widgetView != null)
intent.setComponent(widgetView.getAppWidgetInfo().provider);
getContext().sendBroadcast(
intent.setAction(ae.mAction).putExtra(
LauncherIntent.Extra.EXTRA_ERROR_MESSAGE, ae.getMessage()));
} catch (Exception e) {
// TODO may be flurry may help me collect this kind of
// exceptions
e.printStackTrace();
}
}
/**
*
* @param widgetView
* @param imgViewId
* @param intent
* @param start
* true to start, false to stop
* @throws AnimationException
*/
void actFrameAnimation(AppWidgetHostView widgetView, int imgViewId, Intent intent,
boolean start) throws FrameAnimationException {
if (widgetView == null)
throw new FrameAnimationException("Cannot find queried widget "
+ intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
+ " in the current screen.");
// Start animation
try {
ImageView imgView = (ImageView) widgetView.findViewById(imgViewId);
AnimationDrawable ad = (AnimationDrawable) (imgView).getDrawable();
if (ad == null)
return;
if (start) {
// Start the animation
ad.start();
getContext()
.sendBroadcast(
intent
.setComponent(widgetView.getAppWidgetInfo().provider)
.setAction(
LauncherIntent.Notification.NOTIFICATION_FRAME_ANIMATION_STARTED));
} else {
// Stop the animation
ad.stop();
getContext()
.sendBroadcast(
intent
.setComponent(widgetView.getAppWidgetInfo().provider)
.setAction(
LauncherIntent.Notification.NOTIFICATION_FRAME_ANIMATION_STOPPED));
}
} catch (Exception e) {
throw new FrameAnimationException(
"Fail to start frame animation on queried ImageView: " + imgViewId);
}
}
/**
*
* @param widgetView
* @param viewId
* @param intent
* @param start
* true to start, false to stop
* @throws TweenAnimationException
* @throws AnimationException
*/
void startTweenAnimation(AppWidgetHostView widgetView, int viewId, Intent intent)
throws Exception, TweenAnimationException {
if (widgetView == null)
throw new NullPointerException("Cannot find queried widget "
+ intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
+ " in the current screen.");
int animId = intent.getIntExtra(LauncherIntent.Extra.EXTRA_ANIMATION_ID, -1);
try {
// Create a context for resources loading later
Context remoteContext = getContext().createPackageContext(
widgetView.getAppWidgetInfo().provider.getPackageName(),
Context.CONTEXT_IGNORE_SECURITY);
// Load animation from remote context
Animation a = AnimationUtils.loadAnimation(remoteContext, animId);
a.setAnimationListener(new TweenAnimListener(intent.setComponent(widgetView
.getAppWidgetInfo().provider)));
// Generally, I don't recommend this, for you never know if the
// user is still
// staying at this screen when the animation start
long animStartTime = intent.getLongExtra(
LauncherIntent.Extra.EXTRA_ANIMATION_STARTTIME, -1);
if (animStartTime > 0) {
a.setStartTime(animStartTime);
}
// Check and verify
if (a.getRepeatCount() == Animation.INFINITE)
a.setRepeatCount(0);
if (a.getRepeatCount() > 10)
a.setRepeatCount(10);
// Start the animation
widgetView.findViewById(viewId).startAnimation(a);
} catch (NameNotFoundException e) {
throw new TweenAnimationException("Cannot load resources");
} catch (Exception e) {
e.printStackTrace();
throw new TweenAnimationException("Cannot start animation: " + animId);
}
}
/**
*
* @author bo
*
*/
class TweenAnimListener implements AnimationListener {
Intent mIntent;
TweenAnimListener(Intent intent) {
mIntent = intent;
}
public void onAnimationEnd(Animation animation) {
getContext()
.sendBroadcast(
mIntent
.setAction(LauncherIntent.Notification.NOTIFICATION_TWEEN_ANIMATION_ENDED));
mIntent = null;
animation.setAnimationListener(null);
}
public void onAnimationRepeat(Animation animation) {
getContext()
.sendBroadcast(
mIntent
.setAction(LauncherIntent.Notification.NOTIFICATION_TWEEN_ANIMATION_REPEATED));
}
public void onAnimationStart(Animation animation) {
getContext()
.sendBroadcast(
mIntent
.setAction(LauncherIntent.Notification.NOTIFICATION_TWEEN_ANIMATION_STARTED));
}
}
};
/**
* Look for a widget in all screens
*
* @param appWidgetId
* @return
*/
final AppWidgetHostView findWidget(int appWidgetId) {
AppWidgetHostView wv;
for (int i = getChildCount() - 1; i >= 0; i--) {
wv = findWidget(i, appWidgetId);
if (wv != null)
return wv;
}
return null;
}
/**
* Find widget in a given screen
*
* @param screen
* @param appWidgetId
* @return
*/
final AppWidgetHostView findWidget(int screen, int appWidgetId) {
if (appWidgetId < 0)
return null;
View child = getChildAt(screen);
if (child == null)
return null;
if (child instanceof AppWidgetHostView) {
AppWidgetHostView widgetView = (AppWidgetHostView) child;
if (widgetView.getAppWidgetId() == appWidgetId)
return widgetView;
} else if (child instanceof ViewGroup) {
ViewGroup cells = (ViewGroup) getChildAt(screen);
for (int i = cells.getChildCount() - 1; i >= 0; i--) {
View widgetView = cells.getChildAt(i);
if (widgetView instanceof AppWidgetHostView) {
if (((AppWidgetHostView) widgetView).getAppWidgetId() == appWidgetId)
return (AppWidgetHostView) widgetView;
}
}
}
return null;
}
ScrollViewProvider mScrollViewProvider = new ScrollViewProvider();
// listview informations storage for each provider data Uri
class ScrollViewInfos {
AbsListView lv = null;
int widgetId = -1;
ContentObserver obs;
Handler obsHandler;
ScrollableBaseAdapter lvAdapter;
CharSequence key;
}
static HashMap<String, ScrollViewInfos> mScrollViewCursorInfos = new HashMap<String, ScrollViewInfos>();
// Test if this widget is scrollable
public synchronized boolean isWidgetScrollable(int widgetId) {
for (ScrollViewInfos item : mScrollViewCursorInfos.values()) {
if (item.widgetId == widgetId)
return true;
}
return false;
}
// Unbind ressource of scrollable widget
public synchronized boolean unbindWidgetScrollable() {
for (ScrollViewInfos item : mScrollViewCursorInfos.values()) {
if (item.lv != null) {
if (CLEAR_DATA_CACHE) {
ListAdapter adapter = item.lv.getAdapter();
if (adapter != null) {
if (adapter instanceof WidgetListAdapter)
((WidgetListAdapter)adapter).clearDataCache();
else if (adapter instanceof WidgetRemoteViewsListAdapter)
((WidgetRemoteViewsListAdapter)adapter).dropCache();
}
}
item.lv.setAdapter(null);
}
item.lv = null;
}
ListViewImageManager.getInstance().unbindDrawables();
if (CLEAR_DATA_CACHE) {
ListViewImageManager.getInstance().clearCache();
}
if (FORCE_FREE_MEMORY) {
System.gc();
}
return false;
}
public synchronized boolean unbindWidgetScrollableId(int widgetId) {
Log.d(TAG, "trying to completely unallocate widget ID="+widgetId);
CharSequence keyToDelete=null;
for (ScrollViewInfos item : mScrollViewCursorInfos.values()) {
Log.d(TAG, "Comparing widget ID="+item.widgetId);
if (item.widgetId == widgetId){
Log.d(TAG, "trying to completely unallocate widget stuff...");
AppWidgetHostView widgetView = findWidget(widgetId);
Log.d(TAG, "Widget view to KILL:"+widgetView);
Context remoteContext=null;
if (widgetView != null) {
AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
if (info != null && info.provider != null) {
final String packageName = info.provider.getPackageName();
try {
remoteContext = getContext().createPackageContext(
packageName,
Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
Log.e(TAG, "couldn't find widget id:"+widgetId);
}
} else
remoteContext = null;
}
if(remoteContext==null)
remoteContext=getContext();
if(item.lv!=null){
Log.d(TAG, "Trying to KILL the ListView...");
if(item.lvAdapter!=null){
item.lvAdapter.dropCache(remoteContext);
}
item.lv.setAdapter(null);
item.lv = null;
}
remoteContext.getContentResolver().unregisterContentObserver(item.obs);
item.obsHandler = null;
item.obs = null;
keyToDelete=item.key;
item=null;
ListViewImageManager.getInstance().clearCacheForWidget(getContext(), widgetId);
}
}
if(keyToDelete!=null)mScrollViewCursorInfos.remove(keyToDelete);
ListViewImageManager.getInstance().unbindDrawables();
if (FORCE_FREE_MEMORY) {
System.gc();
}
Log.d(TAG, "AFTER REMOVING, Our Scrollable widgets array contains:"+mScrollViewCursorInfos.size());
return false;
}
class ScrollViewProvider extends BroadcastReceiver implements OnScrollListener {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("WidgetSpace - onReceive: ", "" + intent);
// Try to get the widget view
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (widgetId < 0)
widgetId = intent.getIntExtra(LauncherIntent.Extra.EXTRA_APPWIDGET_ID, -1);
if (widgetId < 0) {
Log.e(TAG, "Scroll Provider cannot get a legal widget id");
return;
}
AppWidgetHostView widgetView = findWidget(widgetId);
if (widgetView == null) {
getContext().sendBroadcast(
intent.setAction(LauncherIntent.Error.ERROR_SCROLL_CURSOR).putExtra(
LauncherIntent.Extra.EXTRA_ERROR_MESSAGE,
"Cannot find app widget with id: " + widgetId));
return;
}
final ComponentName appWidgetProvider = widgetView.getAppWidgetInfo().provider;
String error = "unknow action";
if (TextUtils.equals(action, LauncherIntent.Action.ACTION_SCROLL_WIDGET_START)) {
// Drop the old stuff first!
error = releaseScrollable(context, intent, widgetView);
if (error == null)
error = makeScrollable(context, intent, widgetView);
} else if (TextUtils.equals(action,
LauncherIntent.Action.ACTION_SCROLL_WIDGET_SELECT_ITEM)) {
error = setSelection(context, intent, widgetView);
} else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLOSE)) {
error = releaseScrollable(context, intent, widgetView);
} else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLEAR_IMAGE_CACHE)) {
error = ListViewImageManager.getInstance().clearCacheForWidget(context, widgetId);
}
if (error == null) {
// send finish signal
intent.setComponent(appWidgetProvider);
getContext().sendBroadcast(intent.setAction(LauncherIntent.Action.ACTION_FINISH));
} else {
// send error message
intent.setComponent(appWidgetProvider);
getContext().sendBroadcast(
intent.setAction(LauncherIntent.Error.ERROR_SCROLL_CURSOR).putExtra(
LauncherIntent.Extra.EXTRA_ERROR_MESSAGE, error));
}
}
private synchronized String makeScrollable(Context context, Intent intent,
AppWidgetHostView widgetView) {
// get the dummy view to replace
final int dummyViewId = intent.getIntExtra(LauncherIntent.Extra.EXTRA_VIEW_ID, -1);
if (dummyViewId <= 0)
return "Dummy view id needed.";
final ComponentName appWidgetProvider = widgetView.getAppWidgetInfo().provider;
final int appWidgetId = widgetView.getAppWidgetId();
try {
// Create a context for loading resources
Context remoteContext = getContext().createPackageContext(
widgetView.getAppWidgetInfo().provider.getPackageName(),
Context.CONTEXT_IGNORE_SECURITY);
AbsListView lv = null;
View dummyView = widgetView.findViewById(dummyViewId);
if (dummyView == null)
return "Dummy view needed.";
if (dummyView instanceof AbsListView)
lv = (AbsListView) dummyView;
else {
dummyView = null;
if (intent.hasExtra(LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_REMOTEVIEWS)) {
SimpleRemoteViews rvs = (SimpleRemoteViews)intent.getParcelableExtra(LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_REMOTEVIEWS);
dummyView = rvs.apply(remoteContext, null);
if (dummyView instanceof AbsListView) {
lv = (AbsListView) dummyView;
if (!replaceView(widgetView, dummyViewId, lv))
return "Cannot replace the dummy with the list view inflated from the passed RemoteViews.";
} else
return "could not create AbsListView from the passed RemoteViews";
} else {
// inflate listview
final int listViewResId = intent.getIntExtra(
LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_LAYOUT_ID, -1);
if (listViewResId <= 0) {
// try to post the newly created listview to the widget
lv = postListView(widgetView, dummyViewId);
if (lv == null)
return "Cannot create the default list view.";
} else {
// Inflate it
LayoutInflater inflater = LayoutInflater.from(remoteContext);
dummyView = inflater.inflate(listViewResId, null);
if (dummyView instanceof AbsListView) {
lv = (AbsListView) dummyView;
if (!replaceView(widgetView, dummyViewId, lv))
return "Cannot replace the dummy with the list view inflated from the passed layout resource id.";
} else
return "Cannot inflate a list view from the passed layout resource id.";
}
}
}
String cursorDataUriString = intent
.getStringExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI);
ScrollViewInfos listViewInfos = mScrollViewCursorInfos.get(cursorDataUriString);
final boolean newListView = listViewInfos == null;
// new widget, initialize observer
if (newListView) {
listViewInfos = new ScrollViewInfos();
final ScrollableBaseAdapter lvAdapter;
if (intent.hasExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_LAYOUT_REMOTEVIEWS))
lvAdapter = new WidgetRemoteViewsListAdapter(remoteContext, intent,
appWidgetProvider, appWidgetId, dummyViewId);
else
lvAdapter = new WidgetListAdapter(remoteContext,
intent, appWidgetProvider, appWidgetId, dummyViewId);
// create listener for content Provider data modification
WidgetDataChangeListener widgetDataChangeListener = new WidgetDataChangeListener() {
@Override
public void onChange() {
lvAdapter.notifyToRegenerate();
}
};
// register contentProvider observer
listViewInfos.obs = new WidgetContentObserver(listViewInfos.obsHandler,
widgetDataChangeListener);
Uri uriToObserver = Uri.parse(intent
.getStringExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI));
context.getContentResolver().registerContentObserver(uriToObserver, true,
listViewInfos.obs);
// store new adapter
listViewInfos.lvAdapter = lvAdapter;
if (LOGD)
Log.d(TAG, "makeScrollable : recreate listview adapter");
} else {
if (LOGD)
Log.d(TAG, "makeScrollable : restore listview adapter");
if (listViewInfos.lvAdapter instanceof WidgetRemoteViewsListAdapter)
((WidgetRemoteViewsListAdapter)listViewInfos.lvAdapter).updateFromIntent(intent);
}
lv.setAdapter(listViewInfos.lvAdapter);
// finish listview configuration
if ((listViewInfos.lvAdapter instanceof WidgetListAdapter) &&
!((WidgetListAdapter)listViewInfos.lvAdapter).mItemChildrenClickable)
lv.setOnItemClickListener(new WidgetItemListener(appWidgetProvider,
appWidgetId, dummyViewId));
lv.setFocusableInTouchMode(false);
lv.setOnScrollListener(this);
// store informations in static memory
listViewInfos.widgetId = appWidgetId;
listViewInfos.lv = lv;
listViewInfos.key=cursorDataUriString;
mScrollViewCursorInfos.put(cursorDataUriString, listViewInfos);
// force listview position if asked
int position = intent.getIntExtra(
LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_POSITION, -1);
if (position >= 0)
lv.setSelection(position);
if (!newListView && CLEAR_DATA_CACHE &&
(listViewInfos.lvAdapter instanceof WidgetListAdapter)) {
listViewInfos.lvAdapter.notifyToRegenerate();
}
if (FORCE_FREE_MEMORY) {
System.gc();
}
Log.d(TAG, "AFTER ADDING, Our Scrollable widgets array contains:"+mScrollViewCursorInfos.size());
return null;
} catch (Exception e) {
return e.getMessage();
}
}
private String setSelection(Context context, Intent intent, AppWidgetHostView widgetView) {
try {
// select item at position
String cursorDataUriString = intent
.getStringExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI);
int position = intent.getIntExtra(
LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_POSITION, 0);
ScrollViewInfos cursorInfos = mScrollViewCursorInfos.get(cursorDataUriString);
if (cursorInfos != null) {
cursorInfos.lv.setSelection(position);
}
return null;
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
private synchronized String releaseScrollable(Context context, Intent intent,
AppWidgetHostView widgetView) {
try {
// destroy listview
String cursorDataUriString = intent
.getStringExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI);
ScrollViewInfos listViewInfos = mScrollViewCursorInfos.get(cursorDataUriString);
if (listViewInfos != null) {
if (listViewInfos.lv != null)
listViewInfos.lv.setAdapter(null);
listViewInfos.lv = null;
context.getContentResolver().unregisterContentObserver(listViewInfos.obs);
listViewInfos.obsHandler = null;
listViewInfos.obs = null;
if (listViewInfos.lvAdapter != null)
listViewInfos.lvAdapter.dropCache(context);
mScrollViewCursorInfos.remove(cursorDataUriString);
}
return null;
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
class WidgetItemListener implements OnItemClickListener {
ComponentName mAppWidgetProvider;
int mAppWidgetId;
int mListViewId;
WidgetItemListener(ComponentName cname, int id, int viewId) {
mAppWidgetProvider = cname;
mAppWidgetId = id;
mListViewId = viewId;
}
public void onItemClick(AdapterView<?> arg0, View view, int pos, long arg3) {
try {
ViewHolder holder = (ViewHolder) view.getTag();
Object tag = holder.lvClickItemTag;
if (tag != null && tag instanceof String) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse((String) tag));
getContext().startActivity(intent);
} else {
Intent intent = new Intent(LauncherIntent.Action.ACTION_ITEM_CLICK);
intent.setComponent(mAppWidgetProvider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)
.putExtra(LauncherIntent.Extra.EXTRA_APPWIDGET_ID, mAppWidgetId);
intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_ID, mListViewId);
intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS, pos);
Rect srcRect = new Rect();
final int[] location = new int[2];
view.getLocationOnScreen(location);
srcRect.left = location[0];
srcRect.top = location[1];
srcRect.right = srcRect.left + view.getWidth();
srcRect.bottom = srcRect.top + view.getHeight();
intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_SOURCE_BOUNDS, srcRect);
getContext().sendBroadcast(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
*
* @param widgetView
* @param dummyViewId
* @return whether the dummy view is replaced by listview
*/
ListView postListView(AppWidgetHostView widgetView, int dummyViewId) {
ListView lv = new ListView(getContext());
lv.setCacheColorHint(0);
if (replaceView(widgetView, dummyViewId, lv))
return lv;
else
return null;
}
/**
*
* @param vg
* @param id
* @param replacement
* @return
*/
boolean replaceView(ViewGroup vg, int id, View replacement) {
View child;
boolean result = false;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
child = vg.getChildAt(i);
if (child.getId() == id) {
// Remove the dummy
vg.removeView(child);
// Set the replacement id to be the old one
replacement.setId(id);
// Put the replacement in
vg.addView(replacement, i, child.getLayoutParams());
return true;
} else if (child instanceof ViewGroup)
result |= replaceView((ViewGroup) child, id, replacement);
}
return result;
}
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
mAllowLongPress = scrollState == SCROLL_STATE_IDLE;
}
}
/**
* Register receivers given by this workspace
*/
public void registerProvider() {
final Context context = getContext();
IntentFilter filter = new IntentFilter();
filter.addAction(LauncherIntent.Action.ACTION_START_FRAME_ANIMATION);
filter.addAction(LauncherIntent.Action.ACTION_STOP_FRAME_ANIMATION);
filter.addAction(LauncherIntent.Action.ACTION_START_TWEEN_ANIMATION);
context.registerReceiver(mAnimationProvider, filter);
IntentFilter scrollFilter = new IntentFilter();
scrollFilter.addAction(LauncherIntent.Action.ACTION_SCROLL_WIDGET_START);
scrollFilter.addAction(LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLOSE);
scrollFilter.addAction(LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLEAR_IMAGE_CACHE);
scrollFilter.addAction(LauncherIntent.Action.ACTION_SCROLL_WIDGET_SELECT_ITEM);
context.registerReceiver(mScrollViewProvider, scrollFilter);
}
/**
* Unregister receivers given by this workspace
*/
public void unregisterProvider() {
final Context context = getContext();
unregisterReceiver(context, mAnimationProvider);
unregisterReceiver(context, mScrollViewProvider);
}
/**
* So en exception in unregistering last receiver will not bypass the second one
*
* @param context
* @param receiver
*/
void unregisterReceiver(Context context, BroadcastReceiver receiver) {
try {
context.unregisterReceiver(receiver);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @author bo
*
*/
class AnimationException extends Exception {
private static final long serialVersionUID = 5532638962504199766L;
public String mAction;
AnimationException(String action, String msg) {
super(msg);
mAction = action;
}
}
class FrameAnimationException extends AnimationException {
/**
*
*/
private static final long serialVersionUID = -3873320976176961709L;
public FrameAnimationException(String msg) {
super(LauncherIntent.Error.ERROR_FRAME_ANIMATION, msg);
}
}
class TweenAnimationException extends AnimationException {
/**
*
*/
private static final long serialVersionUID = 1459429645365799185L;
public TweenAnimationException(String msg) {
super(LauncherIntent.Error.ERROR_TWEEN_ANIMATION, msg);
}
}
}