Back to project page SpunkyCharts.
The source code is released under:
GNU General Public License
If you think the Android project SpunkyCharts listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.jogden.spunkycharts; /* /*from www. j a va2 s. co m*/ Copyright (C) 2014 Jonathon Ogden < jeog.dev@gmail.com > This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses. */ import java.lang.reflect.InvocationTargetException; import android.app.Activity; import android.app.Dialog; import android.app.Fragment; import android.database.Cursor; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; import android.text.format.Time; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.ViewGroup.LayoutParams; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.jogden.spunkycharts.animations.BaseAnimationA; import com.jogden.spunkycharts.animations.BaseSelectAnimationA; import com.jogden.spunkycharts.animations.HorizontalBulgeAnimation; import com.jogden.spunkycharts.animations.HorizontalShakeAnimation; import com.jogden.spunkycharts.animations.VerticalBulgeAnimation; import com.jogden.spunkycharts.animations.VerticalShakeAnimation; import com.jogden.spunkycharts.animations.WiggleAnimation; import com.jogden.spunkycharts.misc.BorderOverlay; import com.jogden.spunkycharts.traditionalchart.TraditionalChartFragment; /** The abstract base class for all SpunkyChart charts. * This fragment is how the application views chart objects; * to position, move, adjust, stack,close them etc. * </p> * Extend this class and define refresh() to handle updating * internal views and state when the chart is resized. Define * onHoldDown to handle a touch and hold of the screen * within the bounds of the frag view. * </p> * There are certain universal settings/preferences like * chart opacity and border thickness that are handled within, * with appropriate getters and setters. *</p> * When a chart has another stacked on top or removed its * onStacked and onDeStacked handlers are called, * respectively. Be sure to call down if you override them. * </p> * Once you've created a ChartPreferences object, you * should Override getLocalPreferencesDialog() as public, * pass the dialog returned from calling the base version * and your layout id to mergeLocalPreferencesDialog(), * returning that after you've passed the bundle and callback * to the setup method of the preferences object. ( Use * the version in TraditionalChartFragment.java as a template. ) * */ public abstract class BaseChartFragmentA extends Fragment { /* refresh the whole chart */ public abstract void refresh(); /* what happens when a touch is held for * more than 'hold threshold' milleseconds */ protected abstract void onHoldDown(); protected static final Handler guiHandler = new Handler(); private BaseChartFragmentA _this; private String _uTag; private boolean _isMin = false; private boolean _tabToggleFlag = true; private int _tabBrdrMltpl = 3; private Bundle _instanceBundle; /* 'virtual' stack of charts for supporting overlay */ private volatile int _stackSize = 1; private BaseChartFragmentA _stackBase = this; private BaseChartFragmentA _stackTop = this; private BaseChartFragmentA _stackLastLink = null; public final boolean FALSE = false; public final boolean TRUE = true; /* private settings */ private RelativeLayout.LayoutParams _lParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ); private GlobalChartPreferences.LineThickness _lineThickness = GlobalChartPreferences.getDefaultLineThickness(); private int _refreshRate = GlobalChartPreferences.getDefaultRefreshRate(); private float _alpha = GlobalChartPreferences.getDefaultAlpha(); private int _borderSz = GlobalChartPreferences.getDefaultChartBorder(); /* since not in a pref object we'll create our own key */ private final String BASE_COLOR = "com.jogden.spunkycharts.BASE_COLOR"; private int _colorId = Color.BLACK; private BorderOverlay _borderOverlay; private TotalFragmentTouchListener _totalTouchListener; protected DockingPanelActivity parentActivity; protected ViewGroup ourViewGroup; protected BorderOverlay symbolTab; /*|---------> begin PUBLIC interface <--------|*/ public int getStackSize() { return _stackSize; } public BaseChartFragmentA getBaseOfStack() { return _stackBase; } public BaseChartFragmentA getTopOfStack() { return _stackTop; } public BaseChartFragmentA getLastLinkOfStack() { return _stackLastLink; } public void setLayoutParams( RelativeLayout.LayoutParams layoutParams ){ _lParams = layoutParams; if( ourViewGroup != null) ourViewGroup.setLayoutParams(_lParams); } public void setTabView(BorderOverlay tabView) { if(tabView != null) tabView.setBorderColor(_colorId); this.symbolTab = tabView; } public String getUniqueTag() { return _uTag; } public BorderOverlay getTabView() { return this.symbolTab; } public void releaseTabView(BorderOverlay tabView) { if(tabView == this.symbolTab) this.symbolTab = null; } public void toggleSymbolTab() { if(_tabToggleFlag){ symbolTab.setBorderSize( symbolTab.getBorderSize() * _tabBrdrMltpl ); } else { symbolTab.setBorderSize( symbolTab.getBorderSize() / _tabBrdrMltpl ); } _tabToggleFlag = _tabToggleFlag ? false : true; } private void setIsMinimized(boolean isMin) { _isMin = isMin; } public boolean isMinimized() { return _isMin; } public void hide() { ourViewGroup.setVisibility(View.GONE); toggleSymbolTab(); setIsMinimized(true); } public void hideStack() { for( BaseChartFragmentA tmp = _stackTop ; tmp != null ; tmp = tmp._stackLastLink ) tmp.hide(); } public void show() { ourViewGroup.setVisibility(View.VISIBLE); toggleSymbolTab(); setIsMinimized(false); } public void showStack() { for( BaseChartFragmentA tmp = _stackTop ; tmp != null ; tmp = tmp._stackLastLink ) tmp.show(); } public void popOffStackAndMove( boolean remove, float newX, float newY ){ if(!remove){ RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams )( ourViewGroup.getLayoutParams() ); float shiftRight = newX - ( lParams.leftMargin + (ourViewGroup.getWidth()/2) ); float shiftDown = newY - ( lParams.topMargin + (ourViewGroup.getHeight()/2) ); parentActivity.resizeAndOrMove( DockingPanelActivity.copyParams(lParams), ourViewGroup, 0, 0, (int)shiftRight, (int)shiftDown ); } popStack(); } public void setSelectAnimation( String animName ) { _totalTouchListener.setSelectAnimation(animName); } public void resetAnimationPrefs() { _totalTouchListener.setupSelectAnimation(); } /* for passing temp state to ourselves */ public void saveInstanceBundle(Bundle bndl, boolean overWrite) { if(overWrite || _instanceBundle == null) _instanceBundle = bndl; } public Bundle loadInstanceBundle() { return _instanceBundle; } /*|---------> end PUBLIC interface <--------|*/ /*|---------> begin PROTECTED interface <--------|*/ /* stubs here for convenience, define if you'd like */ protected void setAxisFontSize(int sp) {} protected void setAxisFontColor(int colorId) {} protected void setXAxisPaddingSize(int pixSize) {} protected void setAxisTimeout(int value) {} protected void setTimeoutIncrement(int value) {} static protected void setAxisMarkColor(int colorId) {} static protected void setAxisMarkThickness(int pixSize) {} static protected void setShowMinorMark(boolean show) {} static protected void setShowMajorMark(boolean show) {} /* getter/setters for private settings */ protected void setColor(int colorId) { _colorId = colorId; _borderOverlay.setBorderColor(colorId); if(symbolTab != null) symbolTab.setBorderColor(colorId); } protected int getColor() { return _colorId; } protected void setBorderSize(int borderSize) { _borderSz = borderSize; ourViewGroup.setPadding( _borderSz,_borderSz,_borderSz,_borderSz ); _borderOverlay.setBorderSize(borderSize); } protected int getBorderSize() { return _borderSz; } protected void setAlpha(float alpha) { ourViewGroup.setAlpha(alpha); _alpha = alpha; } protected float getAlpha() { return _alpha; } protected void setLineThickness( GlobalChartPreferences.LineThickness thickness ){ _lineThickness = thickness; } protected GlobalChartPreferences.LineThickness getLineThickness() { return _lineThickness; } protected void setRefreshRate( int refreshRate) { _refreshRate = refreshRate; } protected int getRefreshRate() { return _refreshRate; } /* should be a mirror of onSavedState handler */ protected void extractState(Bundle savedState) { _lineThickness = GlobalChartPreferences.LineThickness.valueOf( savedState.getString( GlobalChartPreferences.GLOBAL_LINE_THICKNESS ) ); _refreshRate = savedState.getInt( GlobalChartPreferences.GLOBAL_REFRESH_RATE ); _alpha = savedState.getFloat( GlobalChartPreferences.GLOBAL_ALPHA ); _borderSz = savedState.getInt( GlobalChartPreferences.GLOBAL_BORDER_SIZE ); _colorId = savedState.getInt( BASE_COLOR); } /* local (to a chart instance) preferences dialog; call * mergeDialogLayout from your fragment to add your * custom preference layout below it (GlobalChartPreferences) */ protected Dialog mergeLocalPreferencesDialog( Dialog dialog, int layoutId ){ dialog.getLayoutInflater().inflate( layoutId, (ViewGroup)dialog.findViewById(R.id.chart_settings_merged) ); return dialog; } protected Dialog getLocalPreferencesDialog() { final Dialog prefDialog = new Dialog(parentActivity); prefDialog.setTitle("Chart Preferences"); prefDialog.setContentView(R.layout.chart_settings_merged); Bundle bndl = new Bundle(); bndl.putFloat( GlobalChartPreferences.GLOBAL_ALPHA, this.getAlpha() ); bndl.putString( GlobalChartPreferences.GLOBAL_LINE_THICKNESS, this.getLineThickness().toString() ); bndl.putInt( GlobalChartPreferences.GLOBAL_REFRESH_RATE, this.getRefreshRate() ); bndl.putInt( GlobalChartPreferences.GLOBAL_BORDER_SIZE, this.getBorderSize() ); GlobalChartPreferences gPref = new GlobalChartPreferences(); MainApplication.ViewFindable finder = new MainApplication.ViewFindable(){ public View findViewById(int id){ return prefDialog.findViewById(id); } }; if( gPref.findViews(finder) ) gPref.setup( bndl, new ApplicationPreferences.ChartPreferencesSetup.Callback(){ @Override public <T> void callback(String pref, T val){ if ( pref.equals( GlobalChartPreferences.GLOBAL_ALPHA )) _this.setAlpha((Float)val); else if ( pref.equals( GlobalChartPreferences.GLOBAL_LINE_THICKNESS )) _this.setLineThickness( GlobalChartPreferences.LineThickness.valueOf( (String)val ) ); else if ( pref.equals( GlobalChartPreferences.GLOBAL_REFRESH_RATE )) _this.setRefreshRate((Integer)val); else if( pref.equals( GlobalChartPreferences.GLOBAL_BORDER_SIZE )) _this.setBorderSize((Integer)val); } }, this.getActivity() ); return prefDialog; } /* override these to deal with 'stack' events */ /* remember oldTop == this */ protected void onStacked( BaseChartFragmentA base, BaseChartFragmentA oldTop, BaseChartFragmentA newTop ){ BaseChartFragmentA tmp = newTop.getTopOfStack(); do{ /*assimilate the views */ tmp.setBorderSize(_borderSz); }while( tmp.getLastLinkOfStack() != oldTop && (tmp = tmp.getLastLinkOfStack() ).TRUE ); } /* currently not reseting prefs changed in onStacked */ protected void onDeStacked( BaseChartFragmentA base, BaseChartFragmentA oldTop, BaseChartFragmentA newTop ){ } /*|---------> end PROTECTED interface <--------|*/ /*|---------> begin PRIVATE methods <--------|*/ private void pushStack( BaseChartFragmentA upper) { final int sz = _this._stackBase._stackSize + upper._stackBase._stackSize; /* link the base of the new to top of the old */ upper._stackBase._stackLastLink = _this; /* loop thru the new stack updating size,base, and top*/ for( BaseChartFragmentA tmp = upper._stackTop ; tmp != null ; tmp = tmp._stackLastLink ) { tmp._stackSize = sz; tmp._stackBase = _this._stackBase; tmp._stackTop = upper._stackTop; } onStacked(_this._stackBase,_this, upper); } /* note: we are only popping one at a time but * can add multi/middle functionality at some point*/ private void popStack() { /* can call even if we are base */ if(_stackBase != this) { BaseChartFragmentA tmpTop = _stackTop; BaseChartFragmentA tmpBase = _stackBase; BaseChartFragmentA tmpLink = _stackLastLink; for( BaseChartFragmentA tmp = _stackTop ; tmp != null ; tmp = tmp._stackLastLink ) { tmp._stackSize--; tmp._stackTop = _stackLastLink; } _stackBase = this; _stackTop = this; _stackLastLink = null; _stackSize = 1; onDeStacked(tmpBase, tmpTop, tmpLink); } } /*|---------> end PRIVATE methods <--------|*/ /*|---------> begin LIFE-CYCLE handlers <--------|*/ @Override public void onAttach(Activity activity) { super.onAttach(activity); try{ parentActivity = (DockingPanelActivity)activity; }catch( ClassCastException e ){ throw new ClassCastException( activity.toString() + " must extend DockingPanelActivity." ); } _this = this; _uTag = this.getArguments().getString("uTag"); } @Override public void onCreate(Bundle savedState) { this.setRetainInstance(true); super.onCreate(savedState); } @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedState ){ super.onCreateView(inflater, container, savedState); ourViewGroup = (ViewGroup)inflater.inflate( R.layout.chart_fragment_base, container, false ); if( ourViewGroup == null) throw new IllegalStateException( "BaseChartFragmentA failed to return a valid ourViewGroup" ); ourViewGroup.setLayoutParams(_lParams); ImageButton resizeButton = (ImageButton)ourViewGroup.findViewById( R.id.frag_resize_button ); resizeButton.setOnTouchListener( new ResizeButtonTouchListener() ); _totalTouchListener = new TotalFragmentTouchListener( ApplicationPreferences.getSelectAnimation() ); ourViewGroup.setOnTouchListener( _totalTouchListener); // ourViewGroup.setAlpha(_alpha); ourViewGroup.setPadding( _borderSz,_borderSz,_borderSz,_borderSz ); _borderOverlay = new BorderOverlay( this.getActivity(),_borderSz, Color.BLACK, true ); ourViewGroup.addView( _borderOverlay, new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT ) ); ourViewGroup.setFocusable(false); return ourViewGroup; } @Override public void onActivityCreated(Bundle savedState) { super.onActivityCreated(savedState); if( this._uTag == null && savedState != null) this._uTag = savedState.getString("uTag"); if( this._uTag == null) throw new IllegalStateException( "ChartFragment does not have valid symbol string" ); } @Override public void onStart() { super.onStart(); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } @Override public void onStop() { super.onStop(); } @Override public void onSaveInstanceState(Bundle savedState) { savedState.putString( GlobalChartPreferences.GLOBAL_LINE_THICKNESS, _lineThickness.toString() ); savedState.putInt( GlobalChartPreferences.GLOBAL_REFRESH_RATE, _refreshRate ); savedState.putFloat( GlobalChartPreferences.GLOBAL_ALPHA, _alpha ); savedState.putInt( GlobalChartPreferences.GLOBAL_BORDER_SIZE, _borderSz ); savedState.putInt(BASE_COLOR, _colorId); super.onSaveInstanceState(savedState); } @Override public void onDestroyView() { super.onDestroyView(); } @Override public void onDestroy() { super.onDestroy(); } @Override public void onDetach() { super.onDetach(); } /*|---------> end LIFE-CYCLE handlers <--------|*/ /*|---------> begin NESTED OBJECT DEFS <--------|*/ /* attempt to asynchronously wait for our resized frag view * to get to its appropriate dimensions before we refresh it*/ static class AsyncRefresh extends Thread { private static final Object refLock = new Object(); private final Handler root; private final int width; private final int height; private final BaseChartFragmentA frag; private int timeOutCount = 0; private final int INCR = ApplicationPreferences.getTimeoutIncrement(); private final int TOUT = ApplicationPreferences.getLongTimeout(); public AsyncRefresh( Handler root, int w, int h, BaseChartFragmentA frag ){ this.root = root; this.width = w; this.height = h; this.frag = frag; } @Override public void run() { do{ if( frag.ourViewGroup.getMeasuredHeight() == height && frag.ourViewGroup.getMeasuredWidth() == width) break; try{ Thread.sleep(INCR); } catch (InterruptedException e){ } if((timeOutCount+=INCR) > TOUT){ Log.d("SpunkyCharts","BaseChartFragmentA " + "time out, calling refresh w/o guarantees" ); break; } }while(true); root.post( new Runnable(){ @Override public void run(){ synchronized(refLock){ frag.refresh(); } }}); } } /* handle resize touches (drags and double tap * of the resize button - bottom right corner)*/ class ResizeButtonTouchListener implements View.OnTouchListener { private float startX = 0; private float startY = 0; private boolean hasBeenTouched = false; private boolean hasMoved = false; public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch(action) { case(MotionEvent.ACTION_DOWN): if(hasBeenTouched) { /* since we share params only need this once */ parentActivity.resizeAndOrMove( (RelativeLayout.LayoutParams )ourViewGroup.getLayoutParams(), ourViewGroup, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 0, 0 ); /* make sure we refresh the entire stack */ final View conn = (View)ourViewGroup.getParent(); for( BaseChartFragmentA tmp = getTopOfStack() ; tmp != null; tmp = tmp.getLastLinkOfStack() ){ tmp.ourViewGroup.invalidate(); new AsyncRefresh( guiHandler, conn.getMeasuredWidth(), conn.getMeasuredHeight(), tmp ).start(); } hasBeenTouched = false; return true; } hasBeenTouched = true; startX = event.getX(); startY = event.getY(); break; case(MotionEvent.ACTION_MOVE): float moveX = event.getX(); float moveY = event.getY(); if( Math.abs(moveX-startX) > MainApplication.TMOVE_THRSHLD || Math.abs(moveY-startY) > MainApplication.TMOVE_THRSHLD ){ hasMoved = true; } break; case(MotionEvent.ACTION_CANCEL): case(MotionEvent.ACTION_UP): if( hasBeenTouched && hasMoved ){ float x = ourViewGroup.getWidth(); float y = ourViewGroup.getHeight(); float newX = x + (event.getX() - startX); float newY = y + (event.getY() - startY); if( newX >= 0 && newY >= 0){ parentActivity.resizeAndOrMove( (RelativeLayout.LayoutParams ) ourViewGroup.getLayoutParams(), ourViewGroup, (int)newX, (int)newY, 0, 0 ); } /* make sure we refresh the entire stack */ for( BaseChartFragmentA tmp = getTopOfStack() ; tmp != null; tmp = tmp.getLastLinkOfStack() ){ tmp.ourViewGroup.invalidate(); new AsyncRefresh( guiHandler, (int)newX, (int)newY, tmp ).start(); } hasBeenTouched = false; hasMoved = false; } } return true; } } /* hand touches (drags, source-tap, destination-tap, * add-to-stack tap of the entire view, except the * resize touch(above); also deals with setting up * and controlling user-defined default and custom * animations*/ class TotalFragmentTouchListener implements View.OnTouchListener { private float yDistFromUpper = 0; private float yDistFromLower = 0; private float xDistFromLeft = 0; private float xDistFromRight = 0; private float startX = 0; private float startY = 0; private boolean hasMoved = false; private BaseSelectAnimationA onSelectedAnimation; public TotalFragmentTouchListener(String animName) { super(); setSelectAnimation(animName); } // TODO: interrupt redraw ops while moving / resizing // public synchronized boolean onTouch( View v, MotionEvent event ){ BaseChartFragmentA downFrag = parentActivity.getActiveFrag(); int action = event.getAction(); if( _stackTop != _this) return false; /* if we're not the top of the chart 'stack' */ switch(action) { case(MotionEvent.ACTION_DOWN): yDistFromLower = parentActivity.getPanelHeight() - ourViewGroup.getBottom(); yDistFromUpper = ourViewGroup.getTop(); xDistFromLeft = ourViewGroup.getLeft(); xDistFromRight = parentActivity.getPanelWidth() - ourViewGroup.getRight(); startX = event.getX(); startY = event.getY(); break; case(MotionEvent.ACTION_MOVE): float moveX = event.getX(); float moveY = event.getY(); if( Math.abs(moveX-startX) > MainApplication.TMOVE_THRSHLD || Math.abs(moveY-startY) > MainApplication.TMOVE_THRSHLD ){ parentActivity.setActiveFrag( null); hasMoved = true; } break; case(MotionEvent.ACTION_CANCEL): case(MotionEvent.ACTION_UP): if( hasMoved){ final float shiftX = event.getX() - startX; final float shiftY = event.getY() - startY; final float overAllow = ApplicationPreferences.getPanelOverflowAllowed() * ourViewGroup.getMeasuredHeight(); final float snapThrshld = ApplicationPreferences.getPanelSnapThreshold(); /* if 'too far' up : minimize */ if( (shiftY*-1) >= yDistFromUpper + overAllow ) { parentActivity.minimizeChartFragment(_this._uTag); /* if 'too far' down : remove */ } else if( shiftY >= yDistFromLower + overAllow ){ parentActivity.removeChartFragment(_this._uTag); } else { float snapShiftX = shiftX; float snapShiftY = shiftY; /* if 'close' to top: snap in */ if( (shiftY*-1) >= yDistFromUpper - snapThrshld && (shiftY*-1) <= yDistFromUpper + snapThrshld ){ snapShiftY = yDistFromUpper * -1; /* if 'close' to bottom: snap in */ } else if( shiftY >= yDistFromLower - snapThrshld && shiftY <= yDistFromLower + snapThrshld ){ snapShiftY = yDistFromLower; } /* if 'close' to left: snap in */ if( (shiftX*-1) >= xDistFromLeft - snapThrshld && (shiftX*-1) <= xDistFromLeft + snapThrshld ){ snapShiftX = xDistFromLeft * -1; /* if 'close' to right: snap in */ } else if( shiftX >= xDistFromRight - snapThrshld && shiftX <= xDistFromRight + snapThrshld ){ snapShiftX = xDistFromRight; } /*note: not copying params */ parentActivity.resizeAndOrMove( (RelativeLayout.LayoutParams ) ourViewGroup.getLayoutParams(), ourViewGroup, 0, 0, (int)snapShiftX, (int)snapShiftY ); } parentActivity.setActiveFrag( null); hasMoved = false; } else if( (event.getEventTime() - event.getDownTime()) > ApplicationPreferences.getChartHoldThreshold() ){ onHoldDown(); } else { if(downFrag == null){ parentActivity.setActiveFrag( _this); (new timeoutThreadTy()).start(); onSelectedAnimation.start(); } else if( downFrag != _this) { parentActivity.setActiveFrag( null); pushStack(downFrag); for( BaseChartFragmentA tmp = downFrag ; tmp != downFrag.getBaseOfStack(); tmp = tmp.getLastLinkOfStack() ){ RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) ourViewGroup.getLayoutParams(); /* note: not copying params */ tmp.setLayoutParams( lp ); tmp.ourViewGroup.invalidate(); new AsyncRefresh( guiHandler, (int)lp.width, (int)lp.height, tmp ).start(); } } else { /* if we click on 'ourself' pass the event 'down' */ parentActivity.setActiveFrag( null); return false; } } } return true; } public void setSelectAnimation( String animName) { Class<? extends BaseSelectAnimationA>animCls = MainApplication.metaSelectAnimTypes.get( animName ); if(animCls == null) throw new BaseSelectAnimationA.SelectAnimationException( "invalid animation string" ); Exception exc = null; try { onSelectedAnimation = animCls.getConstructor( View.class, BaseSelectAnimationA.AbortSignalCallback.class ).newInstance( ourViewGroup, new BaseSelectAnimationA.AbortSignalCallback(){ public boolean check(){ return (parentActivity.getActiveFrag() != _this); } } ); } catch (java.lang.InstantiationException e) { e.printStackTrace(); exc = e; } catch (IllegalAccessException e) { e.printStackTrace(); exc = e; } catch (IllegalArgumentException e) { e.printStackTrace(); exc = e; } catch (InvocationTargetException e) { e.printStackTrace(); exc = e; } catch (NoSuchMethodException e) { e.printStackTrace(); exc = e; } finally { if( exc != null) throw new BaseSelectAnimationA.SelectAnimationException( exc.getMessage() ); } setupSelectAnimation(); } public void setupSelectAnimation() { if(onSelectedAnimation != null) onSelectedAnimation.setup( ApplicationPreferences.getSelectAnimationFrequency(), ApplicationPreferences.getSelectAnimationSeverity(), ApplicationPreferences.getSelectAnimationTimeout() ); } private class timeoutThreadTy extends Thread { public void run(){ try { Thread.sleep( ApplicationPreferences.getSelectAnimationTimeout() ); parentActivity.setActiveFrag( null); } catch (InterruptedException e) {} } }; } }