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; /* //w ww . j a va2s. c o 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.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.jogden.spunkycharts.ApplicationPreferences.ChartPreferencesSetup; import com.jogden.spunkycharts.animations.BaseSelectAnimationA; import com.jogden.spunkycharts.data.DataContentService; import com.jogden.spunkycharts.data.DataContentService.DataClientInterface; import com.jogden.spunkycharts.misc.Pair; import android.app.Activity; import android.app.Application; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.view.View; public class MainApplication extends Application { static{ /* our native lib */ System.loadLibrary("SpunkyCharts"); } /* a wrapper to interface popular findViewById method */ public interface ViewFindable{ public View findViewById(int id); } /* PRICE AXIS SCALE/INCREMENTS NATIVE SUB-ROUTINE: * determines what increment values fit 'best. (see SpunkyCharts.cpp) */ public static native float[] IncrementRegressNative( float adjRangeDiff, int maxNodes ); @SuppressWarnings("serial") public static class AppNotReadyForDataException extends IllegalStateException { public AppNotReadyForDataException(String msg){ super(msg); } } @SuppressWarnings("serial") static public class InvalidChartManifestException extends XmlPullParserException { public InvalidChartManifestException(String msg) { super(msg); } } @SuppressWarnings("serial") public static final List<Class<?>> availablePanels = new ArrayList<Class<?>>() {{ add(DockingPanelActivity.L2.class); add(DockingPanelActivity.L1.class); add(DockingPanelActivity.class); add(DockingPanelActivity.R1.class); add(DockingPanelActivity.R2.class); }}; public static final int TMOVE_THRSHLD = 10; public static final int WIRELESS_SETTINGS_REQ = 101; public static final int UPDATE_PREFS_REQ = 102; private static MainApplication thisApp = null; private static LocalBroadcastManager ourBroadcastMngr = null ; private static DataContentService ourDataService = null; private static ServiceConnection ourDataServiceConnection = null; public static volatile boolean readyForData = false; public static final Object currentDockingPanelMonitor = new Object(); /* docking panel currently 'active' (onStart, onStop) */ public static volatile Activity currentDockingPanel = null; public static Class<? extends DockingPanelActivity> currentDockingPanelActivity = null; /* all panels, active or in back stack */ public static final List<DockingPanelActivity> dockingPanels = new ArrayList<DockingPanelActivity>(); /* available chart type names and Fragment objects */ public static final Map< String, Class<? extends BaseChartFragmentA> > metaChartTypes = new LinkedHashMap< String, Class<? extends BaseChartFragmentA>>(); /* available chart selection animation names and Animation objects */ public static final Map< String, Class<? extends BaseSelectAnimationA> > metaSelectAnimTypes = new LinkedHashMap< String, Class<? extends BaseSelectAnimationA>>(); /* available data client names and implementations * currently we're just using the last added to this mapping */ public static final Map< String, Class<? extends DataClientInterface> > metaDataClients = new LinkedHashMap< String, Class<? extends DataClientInterface>>(); public static LocalBroadcastManager getLocalBroadcastManager() { return ourBroadcastMngr; } public static MainApplication getInstance() { return thisApp; } public static DataContentService getDataService() { return ourDataService; } public static void setDataService(DataContentService service) { ourDataService = service; } public static boolean isDataServiceRunning() { return ourDataService != null; } public static void connectToDataService() { thisApp.bindService( new Intent(thisApp,DataContentService.class), ourDataServiceConnection = new ServiceConnection() { public void onServiceConnected( ComponentName name, IBinder binder ){ ourDataService = ((DataContentService.OurBinder)binder).getService(); DataContentService.connect(); } public void onServiceDisconnected( ComponentName name ){ ourDataService = null; } }, Context.BIND_AUTO_CREATE ); thisApp.startService( new Intent(thisApp,DataContentService.class) ); } public static void disconnectFromDataService() { if(ourDataService != null){ if(ourDataServiceConnection != null) thisApp.unbindService(ourDataServiceConnection); else throw new IllegalStateException( "Failed to disconnect from data service, " + "ourDataServiceConnection is null." ); } } @Override public final void onCreate() { super.onCreate(); thisApp = this; /* DO NOT REFERENCE ApplicationPreferences BEFORE HERE- */ ourBroadcastMngr = LocalBroadcastManager.getInstance(this); try { /* check chart manifest */ _loadSpunkyManifest(); } catch (Exception e ){ e.printStackTrace(); } } /* sub for extracting from chart_manifest.xml */ @SuppressWarnings("unchecked") private final void _loadSpunkyManifest() throws XmlPullParserException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); InputStream manifestStrm = getResources().openRawResource( R.raw.spunky_manifest ); parser.setInput(manifestStrm, null); String name = null; String layName = null; String fragName = null; String prefsName = null; String className = null; Class<BaseChartFragmentA> fragCls = null; Class<ChartPreferencesSetup> prefCls = null; Class<BaseSelectAnimationA> animCls = null; Class<DataClientInterface> dataCls = null; Integer layId = 0; boolean validInner = false; int eType = parser.getEventType(); while( eType != XmlPullParser.END_DOCUMENT){ if(eType == XmlPullParser.START_TAG){ if( parser.getName().equals("SpunkyManifest") ) validInner = true; name = null; fragName = null; prefsName =null; className = null; fragCls = null; prefCls = null; animCls = null; dataCls = null; layId = 0; if( validInner && parser.getName().equals("ChartType") ){ if( (name = parser.getAttributeValue(null,"name")) == null ) throw new InvalidChartManifestException( "ChartType does not have a 'chartName' attr" ); if( (fragName = parser.getAttributeValue(null,"fragName")) == null ) throw new InvalidChartManifestException( "ChartType [" + name + "] does not have a 'fragName' attr" ); else{ try{ fragCls = (Class<BaseChartFragmentA>)Class.forName( fragName ); }catch( Exception e ){ throw new InvalidChartManifestException( "fragName attr [ " + fragName + " ] is not a valid fully " + "qualifed name or derived class of BaseChartFragmentA" ); } } if( (prefsName = parser.getAttributeValue(null,"prefsName")) == null ) throw new InvalidChartManifestException( "ChartType [" + name + "] does not have a 'prefsName' attr " ); else { try{ prefCls = (Class<ChartPreferencesSetup>)Class.forName( prefsName ); }catch( Exception e ){ throw new InvalidChartManifestException( "prefsName attr [ " + prefsName + " ] is not a valid " + "fully qualifed name or implementation of " + "ApplicationPreferences.ChartPreferencesSetup" ); } } if( (layName = parser.getAttributeValue(null,"layout")) == null ) throw new InvalidChartManifestException( "ChartType [ " + name + " ] does not have a 'layout' attr " ); else { try{ layId = getResources().getIdentifier( this.getPackageName() + ":" + layName.replace("@",""), null, null ); if(layId == 0) throw new Exception(); }catch( Exception e ){ throw new InvalidChartManifestException( "layout attr [" + layName + "] is not a valid layout " + "resource in the " + this.getPackageName() + " package" ); } } }else if( validInner && parser.getName().equals("DataClient") ) { if( (name = parser.getAttributeValue(null,"name")) == null ) throw new InvalidChartManifestException( "DataClient does not have a 'name' attr" ); if( (className = parser.getAttributeValue(null,"className")) == null ) throw new InvalidChartManifestException( "DataClient [" + name + "] " + "does not have a 'className' attr " ); else{ try{ dataCls = (Class<DataClientInterface>) Class.forName( className ); }catch( Exception e ){ throw new InvalidChartManifestException( "className attr [" + className + "] is not a valid fully " + "qualifed name or implementation of DataClientInterface" ); } } }else if( validInner && parser.getName().equals("ChartSelectAnimation") ){ if( (name = parser.getAttributeValue(null,"name")) == null ) throw new InvalidChartManifestException( "ChartSelectAnimation does not have a 'name' attr" ); if( (className = parser.getAttributeValue(null,"className")) == null ) throw new InvalidChartManifestException( "ChartSelectAnimation [" + name + "] " + "does not have a 'className' attr " ); else{ try{ animCls = (Class<BaseSelectAnimationA>) Class.forName( className ); }catch( Exception e ){ throw new InvalidChartManifestException( "className attr [" + className + "] is not a valid fully " + "qualifed name or derived class of BaseSelectAnimationA" ); } } } }else if( eType == XmlPullParser.END_TAG){ if( parser.getName().equals("SpunkyManifest") ) validInner = false; if( validInner && parser.getName().equals("ChartType")){ metaChartTypes.put(name, fragCls); ApplicationPreferences.metaChartPrefs.put( name, new Pair<ChartPreferencesSetup,Integer>( prefCls.newInstance(), layId ) ); }else if( validInner && parser.getName().equals("ChartSelectAnimation") ){ metaSelectAnimTypes.put(name,animCls); // // }else if( validInner && parser.getName().equals("DataClient") ){ metaDataClients.put(name,dataCls); /* use the last provided (for now) */ DataContentService.setDataClientInterface( dataCls.newInstance() ); // // }else if( !validInner ){ int metaFrags = metaChartTypes.size(); int metaPrefs = ApplicationPreferences.metaChartPrefs.size(); int metaPrefLayIds = ApplicationPreferences.metaChartPrefs.size(); if( metaFrags != metaPrefs) throw new InvalidChartManifestException( "inconsistent fragment and preference entries (count)" ); else if( metaPrefs != metaPrefLayIds) throw new InvalidChartManifestException( "inconsistent preference and preference " + "layout entries (count)" ); else if( metaFrags == 0) throw new InvalidChartManifestException( "Spunky Charts requires at least one chart type." ); if(metaSelectAnimTypes.size() < 1) throw new InvalidChartManifestException( "Spunky Charts requires at least one Select Animation." ); } } eType = parser.next(); } } }