--- /dev/null
+package net.sf.openrocket.android;\r
+\r
+import java.util.Locale;\r
+\r
+import android.preference.PreferenceManager;\r
+\r
+import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;\r
+import net.sf.openrocket.document.OpenRocketDocument;\r
+import net.sf.openrocket.l10n.DebugTranslator;\r
+import net.sf.openrocket.l10n.ResourceBundleTranslator;\r
+import net.sf.openrocket.l10n.Translator;\r
+\r
+public class Application extends android.app.Application {\r
+\r
+ private OpenRocketDocument rocketDocument;\r
+ \r
+ // Big B boolean so I can synchronize on it.\r
+ private static Boolean initialized = false;\r
+ \r
+ public static void initialize() {\r
+ synchronized (initialized) {\r
+ if ( initialized == true ) {\r
+ return;\r
+ }\r
+\r
+ // Android does not have a default sax parser set. This needs to be defined first.\r
+ System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");\r
+\r
+ net.sf.openrocket.startup.Application.setLogger( new LogHelper() );\r
+ \r
+ net.sf.openrocket.startup.Application.setPreferences( new PreferencesAdapter() );\r
+ \r
+ ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {\r
+ \r
+ @Override\r
+ protected void loadMotors() {\r
+ }\r
+ };\r
+ db.startLoading();\r
+\r
+ net.sf.openrocket.startup.Application.setMotorSetDatabase(db);\r
+ \r
+ Translator t;\r
+ t = new ResourceBundleTranslator("l10n.messages");\r
+ if (Locale.getDefault().getLanguage().equals("xx")) {\r
+ t = new DebugTranslator(t);\r
+ }\r
+ \r
+ net.sf.openrocket.startup.Application.setBaseTranslator(t);\r
+\r
+ initialized = true;\r
+ }\r
+ }\r
+\r
+ public Application() {\r
+ initialize();\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.app.Application#onCreate()\r
+ */\r
+ @Override\r
+ public void onCreate() {\r
+ super.onCreate();\r
+ PreferencesActivity.initializePreferences(this, PreferenceManager.getDefaultSharedPreferences(this));\r
+ }\r
+\r
+ /**\r
+ * @return the rocketDocument\r
+ */\r
+ public OpenRocketDocument getRocketDocument() {\r
+ return rocketDocument;\r
+ }\r
+\r
+ /**\r
+ * @param rocketDocument the rocketDocument to set\r
+ */\r
+ public void setRocketDocument(OpenRocketDocument rocketDocument) {\r
+ this.rocketDocument = rocketDocument;\r
+ }\r
+ \r
+ \r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android;\r
+\r
+import android.util.Log;\r
+import net.sf.openrocket.logging.LogLevel;\r
+import net.sf.openrocket.logging.LogLine;\r
+\r
+\r
+public class LogHelper extends net.sf.openrocket.logging.LogHelper {\r
+\r
+ /* (non-Javadoc)\r
+ * @see net.sf.openrocket.logging.LogHelper#log(net.sf.openrocket.logging.LogLine)\r
+ */\r
+ @Override\r
+ public void log(LogLine line) {\r
+ \r
+ LogLevel level = line.getLevel();\r
+ \r
+ switch ( level ) {\r
+ case ERROR:\r
+ Log.e("OpenRocket", line.toString());\r
+ break;\r
+ case WARN:\r
+ Log.w("OpenRocket", line.toString());\r
+ break;\r
+ case INFO:\r
+ Log.i("OpenRocket", line.toString());\r
+ break;\r
+ case DEBUG:\r
+ Log.d("OpenRocket", line.toString());\r
+ break;\r
+ default:\r
+ Log.v("OpenRocket", line.toString());\r
+ }\r
+ }\r
+\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.motor.MotorHierarchicalBrowser;\r
+import android.app.Activity;\r
+import android.content.Intent;\r
+import android.net.Uri;\r
+import android.os.Bundle;\r
+import android.os.Handler;\r
+import android.os.Message;\r
+import android.view.View;\r
+import android.widget.ImageView;\r
+\r
+public class Main extends Activity {\r
+\r
+ private static final int PICK_ORK_FILE_RESULT = 1;\r
+\r
+ private static final int STOPSPLASH = 0;\r
+ //time in milliseconds\r
+ private static final long SPLASHTIME = 3000;\r
+\r
+ private ImageView splash;\r
+\r
+ //handler for splash screen\r
+ private Handler splashHandler = new Handler() {\r
+ /* (non-Javadoc)\r
+ * @see android.os.Handler#handleMessage(android.os.Message)\r
+ */\r
+ @Override\r
+ public void handleMessage(Message msg) {\r
+ switch (msg.what) {\r
+ case STOPSPLASH:\r
+ //remove SplashScreen from view\r
+ splash.setVisibility(View.GONE);\r
+ break;\r
+ }\r
+ super.handleMessage(msg);\r
+ }\r
+ };\r
+\r
+ /** Called when the activity is first created. */\r
+ @Override\r
+ public void onCreate(Bundle icicle) {\r
+ super.onCreate(icicle);\r
+ setContentView(R.layout.main);\r
+ splash = (ImageView) findViewById(R.id.splashscreen);\r
+ Message msg = new Message();\r
+ msg.what = STOPSPLASH;\r
+ splashHandler.sendMessageDelayed(msg, SPLASHTIME);\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)\r
+ */\r
+ @Override\r
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {\r
+ switch ( requestCode ) {\r
+ case PICK_ORK_FILE_RESULT:\r
+ if(resultCode==RESULT_OK){\r
+ Uri file = data.getData();\r
+ Intent intent = new Intent(Intent.ACTION_VIEW);\r
+ intent.setData(file);\r
+ startActivity(intent);\r
+ }\r
+ break;\r
+ }\r
+ super.onActivityResult(requestCode, resultCode, data);\r
+ }\r
+\r
+ public void pickOrkFiles( View v ) {\r
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\r
+ intent.setType("file/*");\r
+ startActivityForResult(intent,PICK_ORK_FILE_RESULT);\r
+ }\r
+\r
+ public void browseMotors( View v ) {\r
+ Intent i = new Intent(Main.this, MotorHierarchicalBrowser.class);\r
+ startActivity(i);\r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.unit.UnitGroup;\r
+import android.content.SharedPreferences;\r
+import android.os.Bundle;\r
+import android.preference.PreferenceManager;\r
+\r
+public class PreferencesActivity extends android.preference.PreferenceActivity \r
+implements SharedPreferences.OnSharedPreferenceChangeListener {\r
+\r
+ @Override\r
+ protected void onCreate( Bundle savedInstanceState ) {\r
+ super.onCreate( savedInstanceState );\r
+ addPreferencesFromResource(R.xml.preferences);\r
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
+ prefs.registerOnSharedPreferenceChangeListener(this);\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String)\r
+ */\r
+ @Override\r
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r
+\r
+ initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this));\r
+ }\r
+\r
+ /**\r
+ * This method is to be called from Application setup to pull the saved preference\r
+ * values into the various datastructures used in OpenRocket.\r
+ * This method is located in this class because it is probably best to have as much\r
+ * of the code in the same place as possible.\r
+ * @param sharedPreferences\r
+ */\r
+ public static void initializePreferences( android.app.Application app, SharedPreferences sharedPreferences ) {\r
+ \r
+ String unitLength = app.getResources().getString(R.string.PreferenceUnitLengthOption);\r
+ String len = sharedPreferences.getString(unitLength, "cm");\r
+ UnitGroup.UNITS_LENGTH.setDefaultUnit( len );\r
+ \r
+ String unitMass = app.getResources().getString(R.string.PreferenceUnitMassOption);\r
+ String mass = sharedPreferences.getString(unitMass, "g");\r
+ UnitGroup.UNITS_MASS.setDefaultUnit( mass );\r
+ \r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android;\r
+\r
+import java.util.Collections;\r
+import java.util.Set;\r
+\r
+import net.sf.openrocket.material.Material;\r
+\r
+public class PreferencesAdapter extends net.sf.openrocket.startup.Preferences {\r
+\r
+ @Override\r
+ public boolean getBoolean(String key, boolean defaultValue) {\r
+ // TODO Auto-generated method stub\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public void putBoolean(String key, boolean value) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ @Override\r
+ public int getInt(String key, int defaultValue) {\r
+ // TODO Auto-generated method stub\r
+ return 0;\r
+ }\r
+\r
+ @Override\r
+ public void putInt(String key, int value) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ @Override\r
+ public double getDouble(String key, double defaultValue) {\r
+ // TODO Auto-generated method stub\r
+ return 0;\r
+ }\r
+\r
+ @Override\r
+ public void putDouble(String key, double value) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ @Override\r
+ public String getString(String key, String defaultValue) {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void putString(String key, String value) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ @Override\r
+ public String getString(String directory, String key, String defaultValue) {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void putString(String directory, String key, String value) {\r
+ // TODO Auto-generated method stub\r
+\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see net.sf.openrocket.startup.Preferences#addUserMaterial(net.sf.openrocket.material.Material)\r
+ */\r
+ @Override\r
+ public void addUserMaterial(Material m) {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see net.sf.openrocket.startup.Preferences#getUserMaterials()\r
+ */\r
+ @Override\r
+ public Set<Material> getUserMaterials() {\r
+ return Collections.<Material>emptySet();\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see net.sf.openrocket.startup.Preferences#removeUserMaterial(net.sf.openrocket.material.Material)\r
+ */\r
+ @Override\r
+ public void removeUserMaterial(Material m) {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.db;\r
+\r
+import android.content.Context;\r
+import android.database.SQLException;\r
+import android.database.sqlite.SQLiteDatabase;\r
+import android.database.sqlite.SQLiteOpenHelper;\r
+import android.util.Log;\r
+\r
+public class DbAdapter {\r
+\r
+ private static final String TAG = "DbAdapter";\r
+ private DatabaseHelper mDbHelper;\r
+ private SQLiteDatabase mDb;\r
+\r
+ private static final String DATABASE_NAME = "rocketflightnotebook";\r
+ private static final int DATABASE_VERSION = 5;\r
+\r
+ private final Context mCtx;\r
+\r
+ private MotorDao motorDao;\r
+ \r
+ public MotorDao getMotorDao() {\r
+ return motorDao;\r
+ }\r
+ \r
+ private class DatabaseHelper extends SQLiteOpenHelper {\r
+ DatabaseHelper(Context context) {\r
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);\r
+ }\r
+\r
+ @Override\r
+ public void onCreate(SQLiteDatabase db) {\r
+ executeSQL( db, MotorDao.create());\r
+ }\r
+ \r
+ @Override\r
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\r
+ Log.w(TAG, "Upgrading database from version " + oldVersion + " to "\r
+ + newVersion + ", which will destroy all old data");\r
+ executeSQL(db, MotorDao.update(oldVersion, newVersion));\r
+ }\r
+\r
+ private void executeSQL( SQLiteDatabase db, String[] sqls ) {\r
+ for(String s: sqls ) {\r
+ db.execSQL(s);\r
+ }\r
+ }\r
+\r
+ }\r
+ \r
+ /**\r
+ * Constructor - takes the context to allow the database to be\r
+ * opened/created\r
+ * \r
+ * @param ctx the Context within which to work\r
+ */\r
+ public DbAdapter(Context ctx) {\r
+ this.mCtx = ctx;\r
+ }\r
+\r
+ /**\r
+ * Open the database. If it cannot be opened, try to create a new\r
+ * instance of the database. If it cannot be created, throw an exception to\r
+ * signal the failure\r
+ * \r
+ * @return this (self reference, allowing this to be chained in an\r
+ * initialization call)\r
+ * @throws SQLException if the database could be neither opened or created\r
+ */\r
+ public DbAdapter open() throws SQLException {\r
+ mDbHelper = new DatabaseHelper(mCtx);\r
+ mDb = mDbHelper.getWritableDatabase();\r
+ motorDao = new MotorDao(mDb);\r
+ return this;\r
+ }\r
+\r
+ public void close() {\r
+ mDbHelper.close();\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package net.sf.openrocket.android.db;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.ObjectInputStream;\r
+import java.io.ObjectOutputStream;\r
+import java.util.Vector;\r
+\r
+import net.sf.openrocket.android.motor.Motor;\r
+import android.content.ContentValues;\r
+import android.database.Cursor;\r
+import android.database.SQLException;\r
+import android.database.sqlite.SQLiteDatabase;\r
+import android.util.Log;\r
+\r
+public class MotorDao {\r
+\r
+ private static final String TAG = "MotorDao";\r
+\r
+ private SQLiteDatabase mDb;\r
+\r
+ private final static String DATABASE_TABLE = "motor";\r
+ private final static String DROP_TABLE = "DROP TABLE IF EXISTS " + DATABASE_TABLE;\r
+ private final static String CREATE_TABLE =\r
+ "create table "+ DATABASE_TABLE + " ( " +\r
+ "_id integer primary key, "+\r
+ "unique_name text unique, "+\r
+ "name text, "+\r
+ "diameter number, "+\r
+ "tot_impulse_ns number, "+\r
+ "avg_thrust_n number, "+\r
+ "max_thrust_n number, "+\r
+ "burn_time_s number, "+\r
+ "length number," +\r
+ "prop_mass_g number,"+\r
+ "tot_mass_g number,"+\r
+ "case_info text,"+\r
+ "manufacturer text," +\r
+ "impulse_class text," +\r
+ "burndata blob"+\r
+ ");";\r
+\r
+ MotorDao( SQLiteDatabase mDb ) {\r
+ this.mDb = mDb;\r
+ }\r
+\r
+ static String[] create() { return new String[] {CREATE_TABLE}; }\r
+\r
+ static String[] update( int oldVer, int newVer ) {\r
+ return new String[] { DROP_TABLE, CREATE_TABLE };\r
+ }\r
+\r
+ public final static String ID = "_id";\r
+ public final static String UNIQUE_NAME = "unique_name";\r
+ public final static String NAME = "name";\r
+ public final static String DIAMETER = "diameter";\r
+ public final static String TOTAL_IMPULSE = "tot_impulse_ns"; \r
+ public final static String AVG_THRUST = "avg_thrust_n";\r
+ public final static String MAX_THRUST = "max_thrust_n";\r
+ public final static String BURN_TIME = "burn_time_s";\r
+ public final static String LENGTH = "length";\r
+ public final static String PROP_MASS = "prop_mass_g";\r
+ public final static String TOT_MASS = "tot_mass_g";\r
+ public final static String BURNDATA = "burndata";\r
+ public final static String CASE_INFO = "case_info";\r
+ public final static String MANUFACTURER = "manufacturer";\r
+ public final static String IMPULSE_CLASS = "impulse_class";\r
+\r
+ public long insertOrUpdateMotor(Motor mi) {\r
+ ContentValues initialValues = new ContentValues();\r
+ initialValues.put(ID, mi.getMotor_id());\r
+ initialValues.put(NAME, mi.getName());\r
+ initialValues.put(DIAMETER,mi.getDiameter());\r
+ initialValues.put(TOTAL_IMPULSE,mi.getTotalImpulse());\r
+ initialValues.put(AVG_THRUST,mi.getAvgThrust());\r
+ initialValues.put(MAX_THRUST,mi.getMaxThrust());\r
+ initialValues.put(BURN_TIME,mi.getBurnTime());\r
+ initialValues.put(LENGTH, mi.getLength());\r
+ initialValues.put(PROP_MASS, mi.getPropMass());\r
+ initialValues.put(TOT_MASS,mi.getTotMass());\r
+ initialValues.put(CASE_INFO, mi.getCaseInfo());\r
+ initialValues.put(MANUFACTURER,mi.getManufacturer());\r
+ initialValues.put(IMPULSE_CLASS,mi.getImpulseClass());\r
+ initialValues.put(UNIQUE_NAME, mi.getManufacturer()+mi.getName());\r
+ {\r
+ // Serialize the Vector of burn data\r
+ Vector<Double> burndata = mi.getBurndata();\r
+ byte[] serObj = null;\r
+ if ( burndata != null ) {\r
+ try {\r
+ ByteArrayOutputStream b = new ByteArrayOutputStream();\r
+ ObjectOutputStream os = new ObjectOutputStream(b);\r
+ os.writeObject(burndata);\r
+ os.close();\r
+ serObj = b.toByteArray();\r
+ } catch (Exception ex) {\r
+ Log.d(TAG,"unable to serialze burndata");\r
+ }\r
+ }\r
+ initialValues.put(BURNDATA, serObj);\r
+ }\r
+\r
+\r
+ Log.d(TAG,"insertOrUpdate Motor");\r
+ long rv = mDb.insertWithOnConflict(DATABASE_TABLE, null, initialValues,SQLiteDatabase.CONFLICT_REPLACE);\r
+ return rv;\r
+ }\r
+\r
+ /**\r
+ * Delete the motor and burn data with the given rowId\r
+ * \r
+ * @param name name of motor to delete\r
+ * @return true if deleted, false otherwise\r
+ */\r
+ public boolean deleteMotor(Long id) {\r
+\r
+ boolean rv = mDb.delete(DATABASE_TABLE, ID + "=" + id, null) > 0;\r
+ return rv;\r
+ }\r
+\r
+ /**\r
+ * \r
+ * @param groupCol\r
+ * @param groupVal\r
+ * @return\r
+ */\r
+ public Cursor fetchAllInGroups( String groupCol, String groupVal ) {\r
+ return mDb.query(DATABASE_TABLE, \r
+ /* columns */new String[] {\r
+ ID,\r
+ NAME,\r
+ DIAMETER ,\r
+ TOTAL_IMPULSE,\r
+ AVG_THRUST ,\r
+ MAX_THRUST ,\r
+ BURN_TIME ,\r
+ LENGTH,\r
+ PROP_MASS,\r
+ TOT_MASS,\r
+ CASE_INFO,\r
+ IMPULSE_CLASS,\r
+ MANUFACTURER\r
+ },\r
+ /* selection */groupCol + "=?",\r
+ /* selection args*/new String[] {groupVal},\r
+ /* groupby */null,\r
+ /* having*/null,\r
+ /* orderby*/ NAME );\r
+\r
+ }\r
+\r
+ /**\r
+ * Fetch the groups based on groupCol\r
+ * @param groupCol\r
+ * @return\r
+ */\r
+ public Cursor fetchGroups( String groupCol ) {\r
+ return mDb.query(true, DATABASE_TABLE, \r
+ /* columns */new String[] {\r
+ groupCol\r
+ },\r
+ /* selection */null,\r
+ /* selection args*/null,\r
+ /* groupby */null,\r
+ /* having*/null,\r
+ /* orderby*/null,\r
+ /* limit*/ null);\r
+\r
+ }\r
+\r
+ /**\r
+ * Return a Cursor over the list of all motors\r
+ * \r
+ * @return Cursor over all notes\r
+ */\r
+ public Cursor fetchAllMotors() {\r
+\r
+ return mDb.query(DATABASE_TABLE, \r
+ /* columns */new String[] {\r
+ ID,\r
+ NAME,\r
+ DIAMETER ,\r
+ TOTAL_IMPULSE,\r
+ AVG_THRUST ,\r
+ MAX_THRUST ,\r
+ BURN_TIME ,\r
+ LENGTH,\r
+ PROP_MASS,\r
+ TOT_MASS,\r
+ CASE_INFO,\r
+ IMPULSE_CLASS,\r
+ MANUFACTURER\r
+ },\r
+ /* selection */null,\r
+ /* selection args*/null,\r
+ /* groupby */null,\r
+ /* having*/null,\r
+ /* orderby*/null);\r
+ }\r
+\r
+ public Motor fetchMotor(Long id ) throws SQLException {\r
+ Cursor mCursor = mDb.query(DATABASE_TABLE, \r
+ /* columns */new String[] {\r
+ ID,\r
+ NAME ,\r
+ DIAMETER ,\r
+ TOTAL_IMPULSE ,\r
+ AVG_THRUST ,\r
+ MAX_THRUST ,\r
+ BURN_TIME ,\r
+ LENGTH,\r
+ PROP_MASS,\r
+ TOT_MASS,\r
+ CASE_INFO,\r
+ IMPULSE_CLASS,\r
+ MANUFACTURER,\r
+ BURNDATA\r
+ },\r
+ /* selection */ID + "="+id,\r
+ /* selection args*/null,\r
+ /* groupby */null,\r
+ /* having*/null,\r
+ /* orderby*/null);\r
+ if ( mCursor == null ) {\r
+ return null;\r
+ }\r
+ try {\r
+ if (mCursor.getCount() == 0) {\r
+ return null;\r
+ }\r
+ mCursor.moveToFirst();\r
+ Motor mi = new Motor();\r
+ mi.setMotor_id(mCursor.getLong(mCursor.getColumnIndex(ID)));\r
+ mi.setName(mCursor.getString(mCursor.getColumnIndex(NAME)));\r
+ mi.setDiameter(mCursor.getLong(mCursor.getColumnIndex(DIAMETER)));\r
+ mi.setTotalImpulse(mCursor.getFloat(mCursor.getColumnIndex(TOTAL_IMPULSE)));\r
+ mi.setAvgThrust(mCursor.getFloat(mCursor.getColumnIndex(AVG_THRUST)));\r
+ mi.setMaxThrust(mCursor.getFloat(mCursor.getColumnIndex(MAX_THRUST)));\r
+ mi.setBurnTime(mCursor.getFloat(mCursor.getColumnIndex(BURN_TIME)));\r
+ mi.setLength(mCursor.getFloat(mCursor.getColumnIndex(LENGTH)));\r
+ mi.setPropMass(mCursor.getDouble(mCursor.getColumnIndex(PROP_MASS)));\r
+ mi.setCaseInfo(mCursor.getString(mCursor.getColumnIndex(CASE_INFO)));\r
+ mi.setTotMass(mCursor.getDouble(mCursor.getColumnIndex(TOT_MASS)));\r
+ mi.setManufacturer(mCursor.getString(mCursor.getColumnIndex(MANUFACTURER)));\r
+ mi.setImpulseClass(mCursor.getString(mCursor.getColumnIndex(IMPULSE_CLASS)));\r
+\r
+ {\r
+ // Deserialize burndata column\r
+ byte[] serObj = mCursor.getBlob(mCursor.getColumnIndex(BURNDATA));\r
+ Vector<Double> burndata = null;\r
+ if (serObj != null ) {\r
+ try {\r
+ ObjectInputStream is = new ObjectInputStream( new ByteArrayInputStream(serObj));\r
+ burndata = (Vector<Double>) is.readObject();\r
+ }\r
+ catch (Exception ex) {\r
+ Log.d(TAG,"cannot deserialize burndata");\r
+ }\r
+ }\r
+ mi.setBurndata(burndata);\r
+ }\r
+ return mi;\r
+ }\r
+ finally {\r
+ mCursor.close();\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import java.util.Vector;\r
+\r
+import net.sf.openrocket.R;\r
+import android.app.Activity;\r
+import android.graphics.Color;\r
+import android.graphics.PointF;\r
+import android.os.Bundle;\r
+import android.support.v4.app.Fragment;\r
+import android.util.Log;\r
+import android.view.LayoutInflater;\r
+import android.view.MotionEvent;\r
+import android.view.ScaleGestureDetector;\r
+import android.view.View;\r
+import android.view.View.OnTouchListener;\r
+import android.view.ViewGroup;\r
+\r
+import com.androidplot.xy.BoundaryMode;\r
+import com.androidplot.xy.LineAndPointFormatter;\r
+import com.androidplot.xy.LineAndPointRenderer;\r
+import com.androidplot.xy.SimpleXYSeries;\r
+import com.androidplot.xy.XYPlot;\r
+import com.androidplot.xy.YValueMarker;\r
+\r
+public class BurnPlotFragment extends Fragment implements OnTouchListener {\r
+\r
+ private final static String TAG = "BurnPlotFragment";\r
+\r
+ private XYPlot mySimpleXYPlot;\r
+ private SimpleXYSeries mySeries;\r
+ private PointF minXY;\r
+ private PointF maxXY;\r
+ \r
+ private float absMinX;\r
+ private float absMaxX;\r
+ private float minNoError;\r
+ private float maxNoError;\r
+\r
+ private ScaleGestureDetector mScaleDetector;\r
+ private float mScaleFactor = 1.f;\r
+\r
+ public static BurnPlotFragment initializeBurnPlotHelper( Motor motor ) {\r
+ BurnPlotFragment h = new BurnPlotFragment();\r
+\r
+ Bundle args = new Bundle();\r
+ args.putSerializable("Motor", motor);\r
+ h.setArguments(args);\r
+ return h;\r
+ }\r
+\r
+ @Override\r
+ public void onAttach(Activity activity) {\r
+ super.onAttach(activity);\r
+ Log.d(TAG,"onAttach");\r
+ }\r
+\r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ Log.d(TAG,"onCreate");\r
+ super.onCreate(savedInstanceState);\r
+ }\r
+\r
+ @Override\r
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
+ Bundle savedInstanceState) {\r
+ Log.d(TAG,"onCreateView");\r
+ View v = inflater.inflate(R.layout.motor_burn, container, false);\r
+ mySimpleXYPlot = (XYPlot) v.findViewById(R.id.xyplot);\r
+ mySimpleXYPlot.setOnTouchListener(this);\r
+ mScaleDetector = new ScaleGestureDetector(v.getContext(), new ScaleListener());\r
+ // Motor motor = getMotor();\r
+ // init(motor);\r
+ return v;\r
+ }\r
+\r
+ void init( Motor motor ) {\r
+\r
+ mySimpleXYPlot.setUserDomainOrigin(0);\r
+ mySimpleXYPlot.setUserRangeOrigin(0);\r
+ mySimpleXYPlot.setRangeLabel("impuse (n)");\r
+ mySimpleXYPlot.setDomainLabel("time (s)");\r
+ mySimpleXYPlot.addMarker(new YValueMarker(motor.getAvgThrust(),"average" ));\r
+ mySimpleXYPlot.disableAllMarkup();\r
+\r
+ Vector<Double> data = null;\r
+ try {\r
+ data = motor.getBurndata();\r
+ } catch ( Exception ex ) {\r
+ }\r
+ if ( data == null || data.size() == 0 ) {\r
+ data = new Vector<Double>();\r
+ data.add(0.0);\r
+ data.add(0.0);\r
+ data.add(1.0);\r
+ data.add(1.0);\r
+ }\r
+ Log.d("plot","data = " + data.toString());\r
+\r
+ mySeries = new SimpleXYSeries(data, SimpleXYSeries.ArrayFormat.XY_VALS_INTERLEAVED,motor.getName());\r
+\r
+ mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class,\r
+ new LineAndPointFormatter(Color.rgb(0, 255, 0), Color.rgb(200, 0, 0), null));\r
+\r
+ //Set of internal variables for keeping track of the boundaries\r
+ mySimpleXYPlot.calculateMinMaxVals();\r
+ \r
+ mySimpleXYPlot.redraw();\r
+\r
+ minXY=new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),mySimpleXYPlot.getCalculatedMinY().floatValue());\r
+ maxXY=new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),mySimpleXYPlot.getCalculatedMaxY().floatValue());\r
+\r
+ absMinX = minXY.x;\r
+ absMaxX = maxXY.x;\r
+ \r
+ minNoError = Math.round(mySeries.getX(1).floatValue() +2);\r
+ maxNoError = Math.round(mySeries.getX(mySeries.size() -1).floatValue()) - 2.0f;\r
+ }\r
+\r
+ private float mPosX;\r
+ private float mPosY;\r
+\r
+ private float mLastTouchX;\r
+ private float mLastTouchY;\r
+\r
+ private int mActivePointerId = -1;\r
+\r
+ @Override\r
+ public boolean onTouch(View arg0, MotionEvent event) {\r
+ mScaleDetector.onTouchEvent(event);\r
+\r
+ final int action = event.getAction();\r
+ switch ( action & MotionEvent.ACTION_MASK ) {\r
+ case MotionEvent.ACTION_DOWN: {\r
+ final float x = event.getX();\r
+ final float y = event.getY();\r
+\r
+ mLastTouchX = x;\r
+ mLastTouchY = y;\r
+\r
+ mActivePointerId = event.getPointerId(0);\r
+ break;\r
+ }\r
+ \r
+ case MotionEvent.ACTION_MOVE: {\r
+ final int pointerIndex = event.findPointerIndex(mActivePointerId);\r
+ final float x = event.getX(pointerIndex);\r
+ final float y = event.getY(pointerIndex);\r
+\r
+ if (!mScaleDetector.isInProgress()) {\r
+ final float dx = x - mLastTouchX;\r
+ final float dy = y - mLastTouchY;\r
+ \r
+ mPosX += dx;\r
+ mPosY += dy;\r
+ scroll(dx);\r
+ // do scroll.\r
+ \r
+ }\r
+ mLastTouchX = x;\r
+ mLastTouchY = y;\r
+ \r
+ break;\r
+ }\r
+ \r
+ case MotionEvent.ACTION_UP: {\r
+ mActivePointerId = -1;\r
+ break;\r
+ }\r
+ \r
+ case MotionEvent.ACTION_CANCEL: {\r
+ mActivePointerId = -1;\r
+ break;\r
+ }\r
+ \r
+ case MotionEvent.ACTION_POINTER_UP: {\r
+ final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;\r
+ final int pointerId = event.getPointerId(pointerIndex);\r
+ if (pointerId == mActivePointerId) {\r
+ // This was our active pointer going up. choose a new active pointer and adjust accordingly.\r
+ final int newPointerIndex = pointerIndex ==0 ? 1:0;\r
+ mLastTouchX = event.getX(newPointerIndex);\r
+ mLastTouchY = event.getY(newPointerIndex);\r
+ mActivePointerId = event.getPointerId(newPointerIndex);\r
+ }\r
+ break;\r
+ }\r
+ } \r
+ return true;\r
+ }\r
+\r
+ private void zoom(float scale) {\r
+ Log.d(TAG,"zoom by " + scale);\r
+ float domainSpan = absMaxX - absMinX;\r
+ Log.d(TAG,"domainSpan = " + domainSpan);\r
+ float domainMidPoint = absMaxX - domainSpan / 2.0f;\r
+ Log.d(TAG,"domainMidPoint = " + domainMidPoint);\r
+ float offset = domainSpan / scale;\r
+ Log.d(TAG,"offset " + offset);\r
+ minXY.x=domainMidPoint- offset;\r
+ Log.d(TAG,"min X " + minXY.x);\r
+ maxXY.x=domainMidPoint+offset;\r
+ Log.d(TAG,"max X " + maxXY.x);\r
+ checkBoundaries();\r
+ mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
+ mySimpleXYPlot.redraw();\r
+ }\r
+\r
+ private void scroll(float pan) {\r
+ float domainSpan = maxXY.x - minXY.x;\r
+ float step = domainSpan / mySimpleXYPlot.getWidth();\r
+ float offset = pan * step;\r
+ minXY.x+= offset;\r
+ maxXY.x+= offset;\r
+ checkBoundaries();\r
+ mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
+ mySimpleXYPlot.redraw();\r
+ }\r
+\r
+ private void checkBoundaries() {\r
+ \r
+ if ( minXY.x < absMinX) \r
+ minXY.x = absMinX;\r
+// else if ( minXY.x > maxNoError )\r
+// minXY.x = maxNoError;\r
+ \r
+ if ( maxXY.x > absMaxX)\r
+ maxXY.x = absMaxX;\r
+// else if ( maxXY.x < minNoError)\r
+// maxXY.x = minNoError;\r
+ }\r
+ private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {\r
+ @Override\r
+ public boolean onScale( ScaleGestureDetector detector ) {\r
+ mScaleFactor *= detector.getScaleFactor();\r
+\r
+ mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));\r
+ zoom(mScaleFactor);\r
+ return true;\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import java.io.Serializable;\r
+import java.util.Vector;\r
+\r
+public class Motor implements Serializable {\r
+ \r
+ private Long motor_id;\r
+ private String name;\r
+ private String impulseClass;\r
+ private String manufacturer;\r
+ private Long diameter;\r
+ private String caseInfo;\r
+ private Float avgThrust;\r
+ private Float maxThrust;\r
+ private Float totalImpulse;\r
+ private Float burnTime;\r
+ private Float length;\r
+ private Double propMass;\r
+ private Double totMass;\r
+ private Vector<Double> burndata;\r
+ public Long getMotor_id() {\r
+ return motor_id;\r
+ }\r
+ public void setMotor_id(Long motor_id) {\r
+ this.motor_id = motor_id;\r
+ }\r
+ public String getName() {\r
+ return name;\r
+ }\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+ public String getImpulseClass() {\r
+ return impulseClass;\r
+ }\r
+ public void setImpulseClass(String impulseClass) {\r
+ this.impulseClass = impulseClass;\r
+ }\r
+ public String getManufacturer() {\r
+ return manufacturer;\r
+ }\r
+ public void setManufacturer(String manufacturer) {\r
+ this.manufacturer = manufacturer;\r
+ }\r
+ public Long getDiameter() {\r
+ return diameter;\r
+ }\r
+ public void setDiameter(Long diameter) {\r
+ this.diameter = diameter;\r
+ }\r
+ public String getCaseInfo() {\r
+ return caseInfo;\r
+ }\r
+ public void setCaseInfo(String caseInfo) {\r
+ this.caseInfo = caseInfo;\r
+ }\r
+ public Float getAvgThrust() {\r
+ return avgThrust;\r
+ }\r
+ public void setAvgThrust(Float avgThrust) {\r
+ this.avgThrust = avgThrust;\r
+ }\r
+ public Float getMaxThrust() {\r
+ return maxThrust;\r
+ }\r
+ public void setMaxThrust(Float maxThrust) {\r
+ this.maxThrust = maxThrust;\r
+ }\r
+ public Float getTotalImpulse() {\r
+ return totalImpulse;\r
+ }\r
+ public void setTotalImpulse(Float totalImpulse) {\r
+ this.totalImpulse = totalImpulse;\r
+ }\r
+ public Float getBurnTime() {\r
+ return burnTime;\r
+ }\r
+ public void setBurnTime(Float burnTime) {\r
+ this.burnTime = burnTime;\r
+ }\r
+ public Float getLength() {\r
+ return length;\r
+ }\r
+ public void setLength(Float length) {\r
+ this.length = length;\r
+ }\r
+ public Double getPropMass() {\r
+ return propMass;\r
+ }\r
+ public void setPropMass(Double propMass) {\r
+ this.propMass = propMass;\r
+ }\r
+ public Double getTotMass() {\r
+ return totMass;\r
+ }\r
+ public void setTotMass(Double totMass) {\r
+ this.totMass = totMass;\r
+ }\r
+ public Vector<Double> getBurndata() {\r
+ return burndata;\r
+ }\r
+ public void setBurndata(Vector<Double> burndata) {\r
+ this.burndata = burndata;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import net.sf.openrocket.R;\r
+import android.content.Intent;\r
+import android.os.Bundle;\r
+import android.support.v4.app.FragmentActivity;\r
+import android.util.Log;\r
+import android.view.Menu;\r
+import android.view.MenuInflater;\r
+import android.view.MenuItem;\r
+import android.widget.ImageView;\r
+import android.widget.SlidingDrawer;\r
+\r
+public class MotorDetails extends FragmentActivity\r
+implements SlidingDrawer.OnDrawerCloseListener, SlidingDrawer.OnDrawerOpenListener {\r
+\r
+ private final static String TAG = "MotorDetails";\r
+ \r
+ private SlidingDrawer slidingDrawer;\r
+ private ImageView handle;\r
+ \r
+ private Motor motor;\r
+ \r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+ Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState));\r
+ setContentView(R.layout.motor_detail);\r
+\r
+ Intent i = getIntent();\r
+ motor = (Motor) i.getSerializableExtra("Motor");\r
+ \r
+ BurnPlotFragment burnPlot = (BurnPlotFragment) getSupportFragmentManager().findFragmentById(R.id.burnPlotFragment);\r
+ burnPlot.init(motor);\r
+ \r
+ MotorDetailsFragment motorDetails = (MotorDetailsFragment) getSupportFragmentManager().findFragmentById(R.id.motorDetailForm);\r
+ motorDetails.init(motor);\r
+ \r
+ slidingDrawer = (SlidingDrawer) findViewById(R.id.drawer);\r
+ \r
+ slidingDrawer.setOnDrawerOpenListener(this);\r
+ slidingDrawer.setOnDrawerCloseListener(this);\r
+ \r
+ handle = (ImageView) findViewById(R.id.handle);\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void onDrawerOpened() {\r
+ handle.setImageResource(R.drawable.arrow_down_float);\r
+ }\r
+ \r
+ @Override\r
+ public void onDrawerClosed() {\r
+ handle.setImageResource(R.drawable.arrow_up_float);\r
+ }\r
+\r
+ @Override\r
+ public boolean onCreateOptionsMenu(Menu menu) {\r
+ MenuInflater inflater = getMenuInflater();\r
+ inflater.inflate(R.menu.motor_details_option_menu, menu);\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
+ switch(item.getItemId()) {\r
+ case R.id.save:\r
+ // Extract form data to Motor.\r
+ // Save motor.\r
+ return true;\r
+ }\r
+ return super.onMenuItemSelected(featureId, item);\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import net.sf.openrocket.R;\r
+import android.os.Bundle;\r
+import android.support.v4.app.Fragment;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.EditText;\r
+\r
+public class MotorDetailsFragment extends Fragment {\r
+\r
+ EditText manuField;\r
+ EditText nameField;\r
+ EditText caseField;\r
+ EditText impulseClassField;\r
+ EditText diameterField;\r
+ EditText lengthField;\r
+ \r
+ @Override\r
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
+ Bundle savedInstanceState) {\r
+ View v = inflater.inflate(R.layout.motor_detail_form, container, false);\r
+ manuField = (EditText) v.findViewById(R.id.motorDetailsManufacturer);\r
+ nameField = (EditText) v.findViewById(R.id.motorDetailsName);\r
+ caseField = (EditText) v.findViewById(R.id.motorDetailsCaseInfo);\r
+ impulseClassField = (EditText) v.findViewById(R.id.motorDetailsImpuseClass);\r
+ diameterField = (EditText) v.findViewById(R.id.motorDetailsDiameter);\r
+ lengthField = (EditText) v.findViewById(R.id.motorDetailsLength);\r
+ return v;\r
+ }\r
+\r
+ public void init( Motor m ) {\r
+ manuField.setText( m.getManufacturer());\r
+ nameField.setText( m.getName() );\r
+ caseField.setText( m.getCaseInfo());\r
+ impulseClassField.setText( m.getImpulseClass());\r
+ diameterField.setText( m.getDiameter().toString() );\r
+ lengthField.setText( m.getLength().toString() );\r
+ \r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.PreferencesActivity;\r
+import net.sf.openrocket.android.db.DbAdapter;\r
+import net.sf.openrocket.android.db.MotorDao;\r
+import net.sf.openrocket.android.thrustcurve.TCQueryActivity;\r
+import android.content.Context;\r
+import android.content.Intent;\r
+import android.content.SharedPreferences;\r
+import android.content.res.Resources;\r
+import android.database.Cursor;\r
+import android.os.Bundle;\r
+import android.preference.PreferenceManager;\r
+import android.util.Log;\r
+import android.view.ContextMenu;\r
+import android.view.ContextMenu.ContextMenuInfo;\r
+import android.view.Menu;\r
+import android.view.MenuInflater;\r
+import android.view.MenuItem;\r
+import android.view.View;\r
+import android.widget.CursorTreeAdapter;\r
+import android.widget.ExpandableListView;\r
+import android.widget.SimpleCursorTreeAdapter;\r
+\r
+\r
+public class MotorHierarchicalBrowser\r
+extends PersistentExpandableListActivity\r
+implements SharedPreferences.OnSharedPreferenceChangeListener\r
+{\r
+ private static final String TAG = "MotorHierarchicalBrowser";\r
+\r
+ private static final int ACTIVITY_DOWNLOAD=0;\r
+\r
+ private static final int CONTEXTMENU_DELETE = Menu.FIRST+1;\r
+\r
+ private String groupColumnPreferenceKey;\r
+ private String groupColumn = MotorDao.CASE_INFO;\r
+\r
+ private static final String[] groupColumns = new String[] {\r
+ MotorDao.CASE_INFO,\r
+ MotorDao.DIAMETER,\r
+ MotorDao.IMPULSE_CLASS,\r
+ MotorDao.MANUFACTURER\r
+ };\r
+\r
+ private CursorTreeAdapter mAdapter;\r
+\r
+ private DbAdapter mDbHelper;\r
+\r
+ public class MotorHierarchicalListAdapter extends SimpleCursorTreeAdapter\r
+ {\r
+\r
+ // Note that the constructor does not take a Cursor. This is done to avoid querying the \r
+ // database on the main thread.\r
+ public MotorHierarchicalListAdapter(Context context, Cursor cursor, int groupLayout,\r
+ int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom,\r
+ int[] childrenTo) {\r
+\r
+ super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom,\r
+ childrenTo);\r
+ }\r
+\r
+ @Override\r
+ protected Cursor getChildrenCursor(Cursor arg0) {\r
+ Log.d(TAG,"getChildrenCursor");\r
+ String group = arg0.getString(arg0.getColumnIndex(groupColumn));\r
+ Log.d(TAG," for: "+ groupColumn + " = " + group);\r
+ Cursor c = mDbHelper.getMotorDao().fetchAllInGroups(groupColumn,group);\r
+ Log.d(TAG," got cursor");\r
+ startManagingCursor(c);\r
+ return c;\r
+ }\r
+\r
+ @Override\r
+ public long getGroupId(int groupPosition) {\r
+ return groupPosition;\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {\r
+ if ( groupColumnPreferenceKey.equals(arg1) ) {\r
+ setGroupColumnFromPreferences(arg0);\r
+ refreshData();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+\r
+ mDbHelper = new DbAdapter(this);\r
+ mDbHelper.open();\r
+\r
+ Resources resources = this.getResources();\r
+ groupColumnPreferenceKey = resources.getString(R.string.PreferenceMotorBrowserGroupingOption);\r
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r
+\r
+ setGroupColumnFromPreferences(pref);\r
+\r
+ pref.registerOnSharedPreferenceChangeListener(this);\r
+\r
+ refreshData();\r
+\r
+ registerForContextMenu(getExpandableListView());\r
+\r
+ }\r
+\r
+ @Override\r
+ public boolean onCreateOptionsMenu(Menu menu) {\r
+ MenuInflater inflater = getMenuInflater();\r
+ inflater.inflate(R.menu.motor_browser_option_menu, menu);\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
+ Log.d(TAG,"onMenuItemSelected" + item.getItemId());\r
+ switch(item.getItemId()) {\r
+ case R.id.download_from_thrustcurve_menu_option:\r
+ tcDownload();\r
+ return true;\r
+ case R.id.preference_menu_option:\r
+ Intent intent = new Intent().setClass(this, PreferencesActivity.class);\r
+ this.startActivity(intent);\r
+ return true;\r
+ }\r
+ return super.onMenuItemSelected(featureId, item);\r
+ }\r
+\r
+ @Override\r
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {\r
+ Log.d(TAG,"onCreateContextMenu " + menuInfo);\r
+ Log.d(TAG, "v.getId() = " + v.getId());\r
+ Log.d(TAG, "motorListView = " + R.id.motorListView);\r
+ // if (v.getId() == R.id.motorListView) {\r
+ ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;\r
+ menu.setHeaderTitle("context menu");\r
+ menu.add(Menu.NONE,CONTEXTMENU_DELETE,CONTEXTMENU_DELETE,"Delete");\r
+ // }\r
+ super.onCreateContextMenu(menu, v, menuInfo);\r
+ }\r
+\r
+ @Override\r
+ public boolean onContextItemSelected(MenuItem item) {\r
+ ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo();\r
+ long motorId = info.id;\r
+ Log.d(TAG,"ContextMenu: " + motorId);\r
+ switch(item.getItemId()) {\r
+ case CONTEXTMENU_DELETE:\r
+ mDbHelper.getMotorDao().deleteMotor(motorId);\r
+ refreshData();\r
+ return true;\r
+ }\r
+ return super.onContextItemSelected(item);\r
+ }\r
+\r
+ @Override\r
+ protected void onActivityResult(int requestCode, int resultCode, Intent intent) {\r
+ super.onActivityResult(requestCode, resultCode, intent);\r
+ refreshData();\r
+ }\r
+\r
+\r
+ @Override\r
+ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {\r
+ super.onChildClick(parent, v, groupPosition, childPosition, id);\r
+ Motor m = mDbHelper.getMotorDao().fetchMotor(id);\r
+ //Intent i = new Intent(this, BurnPlotActivity.class);\r
+ Intent i = new Intent(this,MotorDetails.class);\r
+ i.putExtra("Motor", m);\r
+ startActivity(i);\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ protected void onDestroy() {\r
+ super.onDestroy();\r
+ \r
+ SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r
+ pref.unregisterOnSharedPreferenceChangeListener(this);\r
+\r
+ // Null out the group cursor. This will cause the group cursor and all of the child cursors\r
+ // to be closed.\r
+ mAdapter.changeCursor(null);\r
+ mAdapter = null;\r
+\r
+ mDbHelper.close();\r
+ }\r
+\r
+ private void tcDownload() {\r
+ Intent i = new Intent(this, TCQueryActivity.class);\r
+ startActivityForResult(i, ACTIVITY_DOWNLOAD);\r
+ }\r
+\r
+ private void setGroupColumnFromPreferences( SharedPreferences prefs ) {\r
+ String indexStr = prefs.getString(groupColumnPreferenceKey, "1");\r
+ int index;\r
+ //Dirty hack, you can't use integer-array in ListPreferences\r
+ try {\r
+ index = Integer.parseInt(indexStr);\r
+ } catch ( Exception e ) {\r
+ index = 1;\r
+ }\r
+ if ( index >= groupColumns.length ) {\r
+ index = 1;\r
+ }\r
+ groupColumn = groupColumns[index];\r
+\r
+ }\r
+ private void refreshData() {\r
+ if (mAdapter != null ) {\r
+ mAdapter.changeCursor(null);\r
+ }\r
+ Cursor motorCursor = mDbHelper.getMotorDao().fetchGroups(groupColumn);\r
+ startManagingCursor(motorCursor);\r
+ // Set up our adapter\r
+ mAdapter = new MotorHierarchicalListAdapter( \r
+ this,\r
+ motorCursor,\r
+ R.layout.motor_list_group,\r
+ R.layout.motor_list_child,\r
+ new String[] { groupColumn }, // Name for group layouts\r
+ new int[] { R.id.motorGroup },\r
+ new String[] { MotorDao.MANUFACTURER, MotorDao.NAME, MotorDao.TOTAL_IMPULSE }, // Number for child layouts\r
+ new int[] { R.id.motorChildManu, R.id.motorChildName, R.id.motorChildImpulse });\r
+ setListAdapter(mAdapter);\r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.motor;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import android.app.ExpandableListActivity;\r
+import android.os.Bundle;\r
+import android.widget.ExpandableListAdapter;\r
+import android.widget.ExpandableListView;\r
+\r
+public class PersistentExpandableListActivity extends ExpandableListActivity {\r
+ private long[] expandedIds;\r
+\r
+ @Override\r
+ protected void onStart() {\r
+ super.onStart();\r
+ if (this.expandedIds != null) {\r
+ restoreExpandedState(expandedIds);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void onStop() {\r
+ super.onStop();\r
+ expandedIds = getExpandedIds();\r
+ }\r
+\r
+ @Override\r
+ protected void onSaveInstanceState(Bundle outState) {\r
+ super.onSaveInstanceState(outState);\r
+ this.expandedIds = getExpandedIds();\r
+ outState.putLongArray("ExpandedIds", this.expandedIds);\r
+ }\r
+\r
+ @Override\r
+ protected void onRestoreInstanceState(Bundle state) {\r
+ super.onRestoreInstanceState(state);\r
+ long[] expandedIds = state.getLongArray("ExpandedIds");\r
+ if (expandedIds != null) {\r
+ restoreExpandedState(expandedIds);\r
+ }\r
+ }\r
+\r
+ private long[] getExpandedIds() {\r
+ ExpandableListView list = getExpandableListView();\r
+ ExpandableListAdapter adapter = getExpandableListAdapter();\r
+ if (adapter != null) {\r
+ int length = adapter.getGroupCount();\r
+ ArrayList<Long> expandedIds = new ArrayList<Long>();\r
+ for(int i=0; i < length; i++) {\r
+ if(list.isGroupExpanded(i)) {\r
+ expandedIds.add(adapter.getGroupId(i));\r
+ }\r
+ }\r
+ return toLongArray(expandedIds);\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ private void restoreExpandedState(long[] expandedIds) {\r
+ this.expandedIds = expandedIds;\r
+ if (expandedIds != null) {\r
+ ExpandableListView list = getExpandableListView();\r
+ ExpandableListAdapter adapter = getExpandableListAdapter();\r
+ if (adapter != null) {\r
+ for (int i=0; i<adapter.getGroupCount(); i++) {\r
+ long id = adapter.getGroupId(i);\r
+ if (inArray(expandedIds, id)) list.expandGroup(i);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private static boolean inArray(long[] array, long element) {\r
+ for (long l : array) {\r
+ if (l == element) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ private static long[] toLongArray(List<Long> list) {\r
+ long[] ret = new long[list.size()];\r
+ int i = 0;\r
+ for (Long e : list) \r
+ ret[i++] = e.longValue();\r
+ return ret;\r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.rocket;\r
+\r
+import java.io.File;\r
+\r
+import net.sf.openrocket.document.OpenRocketDocument;\r
+import net.sf.openrocket.file.RocketLoadException;\r
+import net.sf.openrocket.file.openrocket.OpenRocketLoader;\r
+import android.os.AsyncTask;\r
+import android.util.Log;\r
+\r
+public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketDocument> {\r
+\r
+ private final static String TAG = "OpenRocketLoaderTask";\r
+ \r
+ /* (non-Javadoc)\r
+ * @see android.os.AsyncTask#doInBackground(Params[])\r
+ */\r
+ @Override\r
+ protected OpenRocketDocument doInBackground(File... arg0) {\r
+ Log.d(TAG,"doInBackgroud");\r
+ \r
+ OpenRocketLoader rocketLoader = new OpenRocketLoader();\r
+ try {\r
+ OpenRocketDocument rocket = rocketLoader.load(arg0[0]);\r
+ return rocket;\r
+ }\r
+ catch( RocketLoadException ex ) {\r
+ Log.e(TAG, "doInBackground rocketLaoder.load threw", ex);\r
+ }\r
+ return null;\r
+ \r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.rocket;\r
+\r
+\r
+import java.io.File;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.Application;\r
+import net.sf.openrocket.android.PreferencesActivity;\r
+import net.sf.openrocket.android.motor.MotorHierarchicalBrowser;\r
+import net.sf.openrocket.android.simulation.SimulationViewer;\r
+import net.sf.openrocket.document.OpenRocketDocument;\r
+import net.sf.openrocket.document.Simulation;\r
+import net.sf.openrocket.rocketcomponent.Rocket;\r
+import net.sf.openrocket.rocketcomponent.RocketComponent;\r
+import net.sf.openrocket.rocketcomponent.RocketUtils;\r
+import net.sf.openrocket.unit.Unit;\r
+import net.sf.openrocket.unit.UnitGroup;\r
+import net.sf.openrocket.util.Coordinate;\r
+import android.app.Activity;\r
+import android.app.ProgressDialog;\r
+import android.content.Intent;\r
+import android.content.SharedPreferences;\r
+import android.net.Uri;\r
+import android.os.Bundle;\r
+import android.preference.PreferenceManager;\r
+import android.util.Log;\r
+import android.view.LayoutInflater;\r
+import android.view.Menu;\r
+import android.view.MenuInflater;\r
+import android.view.MenuItem;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.AdapterView;\r
+import android.widget.AdapterView.OnItemClickListener;\r
+import android.widget.ArrayAdapter;\r
+import android.widget.ListView;\r
+import android.widget.TabHost;\r
+import android.widget.TextView;\r
+\r
+public class OpenRocketViewer extends Activity\r
+implements SharedPreferences.OnSharedPreferenceChangeListener\r
+{\r
+\r
+ private static final String TAG = "OpenRocketViewer";\r
+\r
+ private ProgressDialog progress;\r
+\r
+ private ListView componentList;\r
+ private ListView simulationList;\r
+\r
+ private Application app;\r
+\r
+ private final static int PICK_ORK_FILE_RESULT = 1;\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.app.Activity#onCreate(android.os.Bundle)\r
+ */\r
+ @Override\r
+ protected void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+\r
+ Log.d(TAG,"In onCreate");\r
+\r
+ app = (Application) this.getApplication();\r
+\r
+ setContentView(R.layout.openrocketviewer);\r
+\r
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
+ prefs.registerOnSharedPreferenceChangeListener(this);\r
+\r
+ TabHost tabs=(TabHost)findViewById(R.id.openrocketviewerTabHost);\r
+\r
+ tabs.setup();\r
+\r
+ TabHost.TabSpec spec=tabs.newTabSpec("tag1");\r
+\r
+ spec.setContent(R.id.openrocketviewerOverview);\r
+ spec.setIndicator("Overview");\r
+ tabs.addTab(spec);\r
+\r
+ spec=tabs.newTabSpec("tag2");\r
+ spec.setContent(R.id.openrocketviewerComponentList);\r
+ spec.setIndicator("Components");\r
+ tabs.addTab(spec); \r
+\r
+ spec=tabs.newTabSpec("tag3");\r
+ spec.setContent(R.id.openrocketviewerSimulationList);\r
+ spec.setIndicator("Simulations");\r
+ tabs.addTab(spec); \r
+\r
+ componentList = (ListView) findViewById(R.id.openrocketviewerComponentList);\r
+ simulationList = (ListView) findViewById(R.id.openrocketviewerSimulationList);\r
+\r
+ Intent i = getIntent();\r
+ Uri file = i.getData();\r
+\r
+ if ( file == null ) {\r
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\r
+ intent.setType("file/*");\r
+ startActivityForResult(intent,PICK_ORK_FILE_RESULT);\r
+\r
+ } else {\r
+ loadOrkFile(file);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void onDestroy() {\r
+ if ( progress != null ) {\r
+ if ( progress.isShowing() ) {\r
+ progress.dismiss();\r
+ }\r
+ progress = null;\r
+ }\r
+ super.onDestroy();\r
+ }\r
+\r
+ @Override\r
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {\r
+ // TODO Auto-generated method stub\r
+ switch(requestCode){\r
+ case PICK_ORK_FILE_RESULT:\r
+ if(resultCode==RESULT_OK){\r
+ Uri file = data.getData();\r
+ loadOrkFile(file);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ \r
+ private void loadOrkFile( Uri file ) {\r
+ Log.d(TAG,"Use ork file: " + file);\r
+ String path = file.getPath();\r
+ File orkFile = new File(path);\r
+ progress = ProgressDialog.show(this, "Loading file", "");\r
+\r
+ final OpenRocketLoaderTask task = new OpenRocketLoaderTask() {\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.os.AsyncTask#onPostExecute(java.lang.Object)\r
+ */\r
+ @Override\r
+ protected void onPostExecute(OpenRocketDocument result) {\r
+ super.onPostExecute(result);\r
+ app.setRocketDocument( result );\r
+ updateContents();\r
+ }\r
+\r
+ };\r
+\r
+ task.execute(orkFile);\r
+\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String)\r
+ */\r
+ @Override\r
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r
+ // just in case the user changed the units, we redraw.\r
+ PreferencesActivity.initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this));\r
+ updateContents();\r
+ }\r
+\r
+ private void updateContents() {\r
+\r
+ OpenRocketDocument rocketDocument = app.getRocketDocument();\r
+ Rocket rocket = rocketDocument.getRocket();\r
+ \r
+ setTitle(rocket.getName());\r
+ \r
+ Unit LengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();\r
+ Unit MassUnit = UnitGroup.UNITS_MASS.getDefaultUnit();\r
+ \r
+ Coordinate cg = RocketUtils.getCG(rocket);\r
+ double length = RocketUtils.getLength(rocket);\r
+ ((TextView) findViewById(R.id.openrocketviewerRocketName)).setText( rocket.getName());\r
+ ((TextView)findViewById(R.id.openrocketviewerDesigner)).setText(rocket.getDesigner());\r
+ ((TextView)findViewById(R.id.openrocketviewerCG)).setText(LengthUnit.toStringUnit(cg.x) );\r
+ ((TextView)findViewById(R.id.openrocketviewerLength)).setText(LengthUnit.toStringUnit(length));\r
+ ((TextView)findViewById(R.id.openrocketviewerMass)).setText(MassUnit.toStringUnit(cg.weight));\r
+ ((TextView)findViewById(R.id.openrocketviewerStageCount)).setText(String.valueOf(rocket.getStageCount()));\r
+ ((TextView)findViewById(R.id.openrocketviewerComment)).setText(rocket.getComment());\r
+\r
+ ArrayAdapter<Simulation> sims = new ArrayAdapter<Simulation>(this,android.R.layout.simple_list_item_2,rocketDocument.getSimulations()) {\r
+\r
+ @Override\r
+ public View getView(int position, View convertView, ViewGroup parent) {\r
+ View v = convertView;\r
+ if ( v == null ) {\r
+ LayoutInflater li = getLayoutInflater();\r
+ v = li.inflate(android.R.layout.simple_list_item_2,null);\r
+ }\r
+ Simulation sim = this.getItem(position);\r
+ ((TextView)v.findViewById(android.R.id.text1)).setText( sim.getName() );\r
+ ((TextView)v.findViewById(android.R.id.text2)).setText( "motors: " + sim.getConfiguration().getMotorConfigurationDescription() + " apogee: " + sim.getSimulatedData().getMaxAltitude() + "m time: " + sim.getSimulatedData().getFlightTime() + "s");\r
+ return v;\r
+ }\r
+\r
+ };\r
+ simulationList.setOnItemClickListener( new OnItemClickListener() {\r
+ @Override\r
+ public void onItemClick(AdapterView l, View v, int position, long id) {\r
+ Intent i = new Intent(OpenRocketViewer.this, SimulationViewer.class);\r
+ Log.d(TAG,"onItemClick simulation number " + id );\r
+ i.putExtra("Simulation",(int)id);\r
+ startActivityForResult(i, 1/*magic*/);\r
+ }\r
+\r
+ });\r
+ simulationList.setAdapter(sims);\r
+\r
+ ArrayAdapter<RocketComponent> comps = new ArrayAdapter<RocketComponent>(this, android.R.layout.simple_list_item_1,rocket.getChildren()) {\r
+\r
+ /* (non-Javadoc)\r
+ * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)\r
+ */\r
+ @Override\r
+ public View getView(int position, View convertView, ViewGroup parent) {\r
+ View v = convertView;\r
+ if ( v == null ) {\r
+ LayoutInflater li = getLayoutInflater();\r
+ v = li.inflate(android.R.layout.simple_list_item_1,null);\r
+ }\r
+ RocketComponent comp = this.getItem(position);\r
+ ((TextView)v.findViewById(android.R.id.text1)).setText( comp.getName() );\r
+ return v;\r
+ }\r
+ \r
+ \r
+ };\r
+ componentList.setAdapter(comps);\r
+ \r
+ if ( progress.isShowing() ) {\r
+ progress.dismiss();\r
+ }\r
+\r
+ }\r
+\r
+ @Override\r
+ public boolean onCreateOptionsMenu(Menu menu) {\r
+ MenuInflater inflater = getMenuInflater();\r
+ inflater.inflate(R.menu.rocket_viewer_option_menu, menu);\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
+ Log.d(TAG,"onMenuItemSelected" + item.getItemId());\r
+ switch(item.getItemId()) {\r
+ case R.id.motor_list_menu_option:\r
+ startMotorBrowser();\r
+ return true;\r
+ case R.id.preference_menu_option:\r
+ Intent intent = new Intent().setClass(this, PreferencesActivity.class);\r
+ this.startActivity(intent);\r
+ return true;\r
+ }\r
+ return super.onMenuItemSelected(featureId, item);\r
+ }\r
+\r
+ public void startMotorBrowser() {\r
+ Log.d(TAG,"motorBrowserButton clicked");\r
+ Intent i = new Intent(OpenRocketViewer.this, MotorHierarchicalBrowser.class);\r
+ startActivity(i);\r
+ }\r
+\r
+\r
+\r
+}\r
--- /dev/null
+/**\r
+ * Copyright (C) 2009, 2010 SC 4ViewSoft SRL\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package net.sf.openrocket.android.simulation;\r
+\r
+import org.achartengine.ChartFactory;\r
+import org.achartengine.GraphicalView;\r
+import org.achartengine.chart.AbstractChart;\r
+\r
+import android.app.Activity;\r
+import android.os.Bundle;\r
+import android.view.Window;\r
+\r
+/**\r
+ * An activity that encapsulates a graphical view of the chart.\r
+ */\r
+public class GraphicalActivity extends Activity {\r
+ /** The encapsulated graphical view. */\r
+ private GraphicalView mView;\r
+ /** The chart to be drawn. */\r
+ private AbstractChart mChart;\r
+\r
+ @Override\r
+ protected void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+ requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+ Bundle extras = getIntent().getExtras();\r
+ mChart = (AbstractChart) extras.getSerializable(ChartFactory.CHART);\r
+ mView = new GraphicalView(this, mChart);\r
+ String title = extras.getString(ChartFactory.TITLE);\r
+ if (title == null) {\r
+ requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+ } else if (title.length() > 0) {\r
+ setTitle(title);\r
+ }\r
+ setContentView(mView);\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * Copyright (C) 2009, 2010 SC 4ViewSoft SRL\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package net.sf.openrocket.android.simulation;\r
+\r
+import java.util.List;\r
+\r
+import net.sf.openrocket.simulation.FlightDataBranch;\r
+import net.sf.openrocket.simulation.FlightDataType;\r
+import net.sf.openrocket.simulation.FlightEvent;\r
+\r
+import org.achartengine.ChartFactory;\r
+import org.achartengine.chart.LineChart;\r
+import org.achartengine.chart.PointStyle;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYSeriesRenderer;\r
+\r
+import android.content.Context;\r
+import android.content.Intent;\r
+import android.graphics.Color;\r
+import android.graphics.Paint.Align;\r
+import android.util.Log;\r
+\r
+/**\r
+ * Multiple temperature demo chart.\r
+ */\r
+public class SimulationChart {\r
+ \r
+ private final static String TAG = "SimulationChart";\r
+\r
+ private FlightDataBranch flightDataBranch;\r
+ private FlightDataType series1;\r
+ private FlightDataType series2;\r
+ private final FlightDataType time = FlightDataType.TYPE_TIME;\r
+ private List<FlightEvent> flightEvents;\r
+\r
+ // Define 4 different colors and point styles to use for the series.\r
+ // For now only 2 series are supported though.\r
+ private final static int[] colors = new int[] { Color.BLUE, Color.YELLOW, Color.GREEN, Color.RED };\r
+ private final static PointStyle[] styles = new PointStyle[] { PointStyle.CIRCLE, PointStyle.DIAMOND,\r
+ PointStyle.TRIANGLE, PointStyle.SQUARE };\r
+\r
+ /**\r
+ * @param flightDataBranch the flightDataBranch to set\r
+ */\r
+ public void setFlightDataBranch(FlightDataBranch flightDataBranch) {\r
+ this.flightDataBranch = flightDataBranch;\r
+ }\r
+\r
+ /**\r
+ * @param series1 the series1 to set\r
+ */\r
+ public void setSeries1(FlightDataType series1) {\r
+ this.series1 = series1;\r
+ }\r
+\r
+ /**\r
+ * @param series2 the series2 to set\r
+ */\r
+ public void setSeries2(FlightDataType series2) {\r
+ this.series2 = series2;\r
+ }\r
+\r
+ /**\r
+ * @param flightEvents the flightEvents to set\r
+ */\r
+ public void setFlightEvents(List<FlightEvent> flightEvents) {\r
+ this.flightEvents = flightEvents;\r
+ }\r
+\r
+ private static String formatFlightDataTypeAxisLabel( FlightDataType fdt ) {\r
+ return fdt.getName() + " (" + fdt.getUnitGroup().getDefaultUnit().toString() + ")";\r
+ }\r
+\r
+ /**\r
+ * Executes the chart demo.\r
+ * \r
+ * @param context the context\r
+ * @return the built intent\r
+ */\r
+ public Intent execute(Context context) {\r
+\r
+ /*\r
+ * TODO -\r
+ * Figure out why you can pan all over the place even where there are no visible points.\r
+ */\r
+ int seriesCount = 2;\r
+ // if the same series is selected twice, only plot it once.\r
+ if ( series1 == series2 ) {\r
+ seriesCount = 1;\r
+ }\r
+\r
+ XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(seriesCount);\r
+\r
+ renderer.setAxisTitleTextSize(16);\r
+ renderer.setChartTitleTextSize(20);\r
+ renderer.setLabelsTextSize(15);\r
+ renderer.setLegendTextSize(15);\r
+ renderer.setPointSize(5f);\r
+ renderer.setXLabels(10);\r
+ renderer.setYLabels(10);\r
+ renderer.setShowGrid(true);\r
+ renderer.setZoomButtonsVisible(true);\r
+ renderer.setChartTitle("Simulation");\r
+\r
+ renderer.setMargins(new int[] { 50, 30, 0, 20 });\r
+ {\r
+ for (int i = 0; i < seriesCount; i++) {\r
+ XYSeriesRenderer r = new XYSeriesRenderer();\r
+ r.setColor(colors[i]);\r
+ r.setPointStyle(styles[i]);\r
+ r.setFillPoints(true);\r
+ renderer.addSeriesRenderer(r);\r
+ // setting the YAximMin to 0 locks the origins.\r
+ renderer.setYAxisMin(0.0, i);\r
+ }\r
+ }\r
+\r
+ renderer.setXTitle(formatFlightDataTypeAxisLabel(time));\r
+ renderer.setXLabelsAlign(Align.RIGHT);\r
+\r
+ renderer.setYTitle(formatFlightDataTypeAxisLabel(series1),0);\r
+ renderer.setYLabelsAlign(Align.RIGHT,0);\r
+\r
+ if ( seriesCount > 1 ) {\r
+ renderer.setYTitle(formatFlightDataTypeAxisLabel(series2), 1);\r
+ renderer.setYAxisAlign(Align.RIGHT, 1);\r
+ renderer.setYLabelsAlign(Align.LEFT, 1);\r
+ }\r
+\r
+ renderer.setAxesColor(Color.LTGRAY);\r
+ renderer.setLabelsColor(Color.LTGRAY);\r
+\r
+ XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();\r
+\r
+ List<Double> timevalues = flightDataBranch.get(time);\r
+ List<Double> series1values = flightDataBranch.get(series1);\r
+\r
+ // compute the axis limits using timevalues and series1values.\r
+ double xmin = 0;\r
+ double ymin = 0;\r
+ renderer.setXAxisMin(xmin);\r
+ renderer.setYAxisMin(ymin);\r
+\r
+ double ymax = computeMaxValueWithPadding( series1values );\r
+ double xmax = Math.ceil( timevalues.get( timevalues.size()-1));\r
+ \r
+ Log.d(TAG,"ymax = " + ymax);\r
+ renderer.setXAxisMax(xmax);\r
+ renderer.setYAxisMax(ymax);\r
+\r
+ // These configurations don't really work well just now.\r
+ //renderer.setPanLimits(new double[] { xmin, xmax, ymin, ymax });\r
+ //renderer.setZoomLimits(new double[] { xmin, xmax, ymin, ymax });\r
+\r
+ // Add first series\r
+ addXYSeries(dataset, series1.getName(), timevalues, series1values, 0);\r
+\r
+ if ( seriesCount > 1 ) {\r
+ // Add second series\r
+ addXYSeries(dataset, series2.getName(), timevalues, flightDataBranch.get(series2), 1);\r
+ }\r
+ Intent intent = getLineChartIntent(context, dataset, renderer,"Simulation");\r
+ return intent;\r
+ }\r
+\r
+ private static void addXYSeries(XYMultipleSeriesDataset dataset, String titles, List<Double> xValues, List<Double> yValues, int scale) {\r
+ XYSeries series = new XYSeries(titles, scale);\r
+ int datasize = xValues.size();\r
+ for( int i = 0; i<datasize; i++ ) {\r
+ series.add(xValues.get(i), yValues.get(i));\r
+ }\r
+ dataset.addSeries(series);\r
+\r
+ }\r
+\r
+ private static Intent getLineChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+ XYMultipleSeriesRenderer renderer, String activityTitle) {\r
+ // checkParameters(dataset, renderer);\r
+ Intent intent = new Intent(context, GraphicalActivity.class);\r
+ XYChart chart = new LineChart(dataset, renderer);\r
+ intent.putExtra(ChartFactory.CHART, chart);\r
+ intent.putExtra(ChartFactory.TITLE, activityTitle);\r
+ return intent;\r
+ }\r
+\r
+ private static double computeMaxValueWithPadding( List<Double> list ) {\r
+ double max = list.get(0);\r
+ for( double v : list ) {\r
+ if ( v > max ) {\r
+ max = v;\r
+ }\r
+ }\r
+ if ( max <= 0 ) return 1.0;\r
+\r
+ // Do something stupid.\r
+ // return:\r
+ // 10 if max <= 10\r
+ // next 10 if 10 < max < 1000\r
+ // next 100 if 1000 < max < 10,000\r
+ // next 1000 if max >= 10,000\r
+ double numdigits = Math.floor(Math.log10(max));\r
+ \r
+ if ( numdigits <= 1.0 ) {\r
+ return 10.0;\r
+ } else if ( numdigits <= 3.0 ) {\r
+ return 10.0 * ( Math.ceil( max/10.0));\r
+ } else if ( numdigits <= 4.0 ) {\r
+ return 100.0 * ( Math.ceil( max/ 100.0) );\r
+ } else {\r
+ return 1000.0 * ( Math.ceil( max / 1000.0 ));\r
+ }\r
+ \r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.simulation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.Application;\r
+import net.sf.openrocket.document.Simulation;\r
+import net.sf.openrocket.simulation.FlightDataBranch;\r
+import net.sf.openrocket.simulation.FlightDataType;\r
+import net.sf.openrocket.simulation.FlightEvent;\r
+import android.app.Activity;\r
+import android.content.Intent;\r
+import android.os.Bundle;\r
+import android.util.Log;\r
+import android.util.SparseBooleanArray;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.ArrayAdapter;\r
+import android.widget.ListView;\r
+import android.widget.Spinner;\r
+import android.widget.TabHost;\r
+import android.widget.TextView;\r
+\r
+public class SimulationViewer extends Activity {\r
+\r
+ private final static String TAG = "SimulationViewer";\r
+\r
+ private ListView eventList;\r
+ private Spinner series1Spinner;\r
+ private Spinner series2Spinner;\r
+\r
+ private Simulation sim;\r
+ private FlightDataBranch data;\r
+\r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+ Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState));\r
+ setContentView(R.layout.simulation_detail);\r
+\r
+ Intent i = getIntent();\r
+ int simnumber = i.getIntExtra("Simulation", 0);\r
+ sim = ((Application)this.getApplication()).getRocketDocument().getSimulation(simnumber);\r
+ data = sim.getSimulatedData().getBranch(0);\r
+\r
+ TabHost tabs=(TabHost)findViewById(R.id.simulationConfigurationForm);\r
+\r
+ tabs.setup();\r
+\r
+ TabHost.TabSpec spec=tabs.newTabSpec("tag1");\r
+\r
+ spec.setContent(R.id.simulationEventsList);\r
+ spec.setIndicator("Events");\r
+ tabs.addTab(spec);\r
+\r
+ spec=tabs.newTabSpec("tag2");\r
+ spec.setContent(R.id.simulationSeriesSelection);\r
+ spec.setIndicator("Series");\r
+ tabs.addTab(spec); \r
+\r
+ eventList = (ListView) findViewById(R.id.simulationEventsList);\r
+\r
+ // Initialize the eventList\r
+ ArrayAdapter<FlightEvent> events = new ArrayAdapter<FlightEvent>(this,android.R.layout.simple_list_item_multiple_choice,data.getEvents()) {\r
+\r
+ @Override\r
+ public View getView(int position, View convertView,\r
+ ViewGroup parent) {\r
+ View v = convertView;\r
+ if ( v == null ) {\r
+ LayoutInflater li = getLayoutInflater();\r
+ v = li.inflate(android.R.layout.simple_list_item_multiple_choice,null);\r
+ }\r
+ FlightEvent event = this.getItem(position);\r
+ ((TextView)v.findViewById(android.R.id.text1)).setText( event.getType().toString() + " " + event.getTime() + " (s)" );\r
+ return v;\r
+ }\r
+\r
+ };\r
+ eventList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);\r
+ eventList.setAdapter(events);\r
+\r
+ series1Spinner = (Spinner) findViewById(R.id.simulationSeries1);\r
+ series2Spinner = (Spinner) findViewById(R.id.simulationSeries2);\r
+\r
+ List<FlightDataType> selectableSeries = new ArrayList<FlightDataType>();\r
+ for( FlightDataType fdt : data.getTypes() ) {\r
+ if ( fdt == FlightDataType.TYPE_TIME ) { \r
+\r
+ } else {\r
+ selectableSeries.add(fdt);\r
+ }\r
+ }\r
+ ArrayAdapter<FlightDataType> serieses = new ArrayAdapter<FlightDataType>(this,android.R.layout.simple_spinner_item,selectableSeries) {\r
+\r
+ @Override\r
+ public View getView(int position, View convertView,\r
+ ViewGroup parent) {\r
+ View v = convertView;\r
+ if ( v == null ) {\r
+ LayoutInflater li = getLayoutInflater();\r
+ v = li.inflate(android.R.layout.simple_spinner_item,null);\r
+ }\r
+ FlightDataType fdt = this.getItem(position);\r
+ ((TextView)v.findViewById(android.R.id.text1)).setText( fdt.toString() );\r
+ return v;\r
+ }\r
+\r
+ };\r
+ series1Spinner.setAdapter(serieses);\r
+ series2Spinner.setAdapter(serieses);\r
+\r
+ }\r
+\r
+ public void draw( View v ) {\r
+ List<FlightEvent> eventsToShow = new ArrayList<FlightEvent>();\r
+ {\r
+ SparseBooleanArray eventsSelected = eventList.getCheckedItemPositions();\r
+ List<FlightEvent> flightEvents = data.getEvents();\r
+ for( int i=0; i< flightEvents.size(); i++ ) {\r
+ if ( eventsSelected.get(i) ) {\r
+ eventsToShow.add(flightEvents.get(i) );\r
+ }\r
+ }\r
+ }\r
+ FlightDataType series1 = (FlightDataType) series1Spinner.getSelectedItem();\r
+ Log.d(TAG,"sereis1 = " + series1.toString());\r
+ FlightDataType series2 = (FlightDataType) series2Spinner.getSelectedItem();\r
+ Log.d(TAG,"series2 = " + series2.toString());\r
+\r
+ SimulationChart chart = new SimulationChart();\r
+ chart.setFlightDataBranch(data);\r
+ chart.setSeries1(series1);\r
+ chart.setSeries2(series2);\r
+ chart.setFlightEvents(eventsToShow);\r
+ \r
+ startActivity(chart.execute(this));\r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.IOException;\r
+import java.io.Reader;\r
+import java.io.StringReader;\r
+import java.io.StringWriter;\r
+\r
+public abstract class Base64Decoder {\r
+\r
+ private static final String BASE64_CHARS =\r
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
+ private static final char PAD_CHAR = '=';\r
+\r
+ private final static short[] _charToBits = new short[128];\r
+\r
+ static {\r
+\r
+ for (int i = 0; i < _charToBits.length; i++)\r
+ _charToBits[i] = -1;\r
+\r
+ for (int i = 0; i < BASE64_CHARS.length(); i++)\r
+ _charToBits[BASE64_CHARS.charAt(i)] = (byte) i;\r
+ _charToBits[PAD_CHAR] = 0;\r
+\r
+ }\r
+ \r
+ /**\r
+ * Decode the specified Base64 string and write binary data\r
+ * to the given stream.\r
+ * @param str Base64 encoded string\r
+ * @param w output stream\r
+ */\r
+ public static String decodeData(String str) throws IOException\r
+ {\r
+ StringReader r;\r
+ int c1;\r
+\r
+ if (str == null || str.length() < 1)\r
+ return null;\r
+\r
+ r = new StringReader(str);\r
+ \r
+ StringWriter w = new StringWriter();\r
+\r
+ // spin through the input string\r
+ c1 = readToNonSpace(r);\r
+ while (c1 > 0)\r
+ {\r
+ int c2, c3, c4;\r
+ int p1, p2, p3, p4;\r
+ int pad, n;\r
+\r
+ pad = 0;\r
+\r
+ c2 = readToNonSpace(r);\r
+ c3 = readToNonSpace(r);\r
+ c4 = readToNonSpace(r);\r
+ if (c4 < 0)\r
+ throw new IllegalArgumentException("Encoded string ends prematurely.");\r
+\r
+ p1 = charToBits(c1);\r
+ p2 = charToBits(c2);\r
+\r
+ if (c3 == PAD_CHAR)\r
+ {\r
+ p3 = 0;\r
+ pad++;\r
+ }\r
+ else\r
+ p3 = charToBits(c3);\r
+\r
+ if (c4 == PAD_CHAR)\r
+ {\r
+ p4 = 0;\r
+ pad++;\r
+ }\r
+ else\r
+ p4 = charToBits(c4);\r
+\r
+ if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)\r
+ throw new IllegalArgumentException("Encoded string contains invalid characters.");\r
+\r
+ n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;\r
+\r
+ w.write((byte) ((n & 0xFF0000) >> 16));\r
+ if (pad < 2)\r
+ w.write((byte) ((n & 0x00FF00) >> 8));\r
+ if (pad < 1)\r
+ w.write((byte) (n & 0x0000FF));\r
+\r
+ c1 = readToNonSpace(r);\r
+ if (c1 > 0 && pad > 0)\r
+ throw new IllegalArgumentException("Extra characters found after padding.");\r
+ }\r
+ \r
+ return w.toString();\r
+ }\r
+\r
+\r
+ private static int readToNonSpace(Reader r)\r
+ throws IOException\r
+ {\r
+ int c;\r
+\r
+ c = r.read();\r
+ while (c >= 0 && Character.isWhitespace(c))\r
+ c = r.read();\r
+\r
+ return c;\r
+ }\r
+\r
+ private static int charToBits(int c)\r
+ {\r
+ // use it to look up the value\r
+ if (c < 0 || c >= _charToBits.length)\r
+ return -1;\r
+ else\r
+ return _charToBits[c];\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.ArrayList;\r
+\r
+class DownloadRequest {\r
+\r
+ private ArrayList<Integer> motorIds = new ArrayList<Integer>();\r
+ \r
+ private String format = null;\r
+ \r
+ public void add( Integer motorId ) {\r
+ this.motorIds.add(motorId);\r
+ }\r
+ \r
+ public void setFormat( String format ) {\r
+ this.format = format;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ StringBuilder w = new StringBuilder();\r
+ \r
+ w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");\r
+ w.append("<download-request\n");\r
+ w.append(" xmlns=\"http://www.thrustcurve.org/2008/DownloadRequest\"\n");\r
+ w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");\r
+ w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2008/DownloadRequest http://www.thrustcurve.org/2008/download-request.xsd\">\n");\r
+\r
+ if ( format != null ) {\r
+ w.append(" <format>").append(format).append("</format>\n");\r
+ }\r
+ \r
+ w.append(" <motor-ids>\n");\r
+ for( Integer i : motorIds ) {\r
+ w.append(" <id>").append(i).append("</id>\n");\r
+ }\r
+ w.append(" </motor-ids>\n");\r
+ w.append("</download-request>\n");\r
+ return w.toString();\r
+ }\r
+\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+\r
+public class DownloadResponse {\r
+\r
+ private Map<Integer,MotorBurnFile> data = new HashMap<Integer,MotorBurnFile>();\r
+ \r
+ private String error = null;\r
+ \r
+ public void add( MotorBurnFile mbd ) {\r
+ MotorBurnFile currentData = data.get(mbd.getMotorId());\r
+ if ( currentData == null || currentData.getDatapoints().size() < mbd.getDatapoints().size() ) {\r
+ data.put(mbd.getMotorId(),mbd);\r
+ }\r
+ }\r
+\r
+ public MotorBurnFile getData(Integer motor_id) {\r
+ return data.get(motor_id);\r
+ }\r
+ \r
+ public void setError(String error) {\r
+ this.error = error;\r
+ }\r
+ \r
+ public String getError() {\r
+ return error;\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return "DownloadResponse [error=" + error + ", data=" + data + "]";\r
+ }\r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.InputStream;\r
+\r
+import org.xml.sax.Attributes;\r
+\r
+import android.sax.Element;\r
+import android.sax.EndElementListener;\r
+import android.sax.EndTextElementListener;\r
+import android.sax.RootElement;\r
+import android.sax.StartElementListener;\r
+import android.util.Log;\r
+import android.util.Xml;\r
+\r
+public class DownloadResponseParser {\r
+\r
+ private static final String TAG = "DownloadResponseParser";\r
+\r
+ private static final String thrustcurveURI = "http://www.thrustcurve.org/2009/DownloadResponse";\r
+\r
+ private static final String root_tag = "download-response";\r
+ private static final String results_tag = "results";\r
+ private static final String result_tag = "result";\r
+ private static final String motor_id_tag = "motor-id";\r
+ private static final String simfile_id_tag = "simfile-id";\r
+ private static final String format_tag = "format";\r
+ private static final String source_tag = "source";\r
+ private static final String license_tag = "license";\r
+ private static final String data_tag = "data";\r
+ private static final String error_tag = "error";\r
+\r
+ public static DownloadResponse parse( InputStream in ) {\r
+\r
+ final DownloadResponse ret = new DownloadResponse();\r
+ final MotorBurnFile currentMotor = new MotorBurnFile();\r
+\r
+ // Have a place to put the data string and format.\r
+ // We hold on to these here, then push them into the currentMotor\r
+ // only if it a supported filetype\r
+ final StringHolder current_format = new StringHolder();\r
+ final StringHolder current_data = new StringHolder();\r
+\r
+ RootElement rootEl = new RootElement(thrustcurveURI, root_tag);\r
+ /*\r
+ rootEl.setStartElementListener(\r
+ new StartElementListener() {\r
+ public void start(Attributes arg0) {\r
+ Log.d(TAG,"Start Element error");\r
+ ret.setError("IsError");\r
+ }\r
+ }\r
+ );\r
+ */\r
+ Element resultsEl = rootEl.getChild( thrustcurveURI, results_tag);\r
+ Element resultEl = resultsEl.getChild( thrustcurveURI, result_tag);\r
+ resultEl.setStartElementListener(\r
+ new StartElementListener() {\r
+ @Override\r
+ public void start(Attributes arg0) {\r
+ Log.d(TAG,"Start Element result");\r
+ currentMotor.init();\r
+ }\r
+ }\r
+ );\r
+\r
+ resultEl.setEndElementListener(\r
+ new EndElementListener() {\r
+ @Override\r
+ public void end() {\r
+ if ( SupportedFileTypes.isSupportedFileType(current_format.s) ) {\r
+ currentMotor.setFiletype(current_format.s);\r
+ String s = null;\r
+ try {\r
+ s = Base64Decoder.decodeData(current_data.s);\r
+ } catch ( Exception ex ) {\r
+ Log.d(TAG,"base64: " + ex.getMessage());\r
+ }\r
+ currentMotor.decodeFile( s );\r
+ }\r
+ ret.add((MotorBurnFile)currentMotor.clone());\r
+ }\r
+ }\r
+ );\r
+\r
+ resultEl.getChild(thrustcurveURI,motor_id_tag).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setMotor_id(Integer.parseInt(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,format_tag).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ current_format.s = arg0;\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,data_tag).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ current_data.s = arg0;\r
+ }\r
+ }\r
+ );\r
+ try {\r
+ Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
+ } catch (Exception e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+\r
+ return ret;\r
+ }\r
+\r
+ private static class StringHolder {\r
+ public String s;\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.Vector;\r
+\r
+public class MotorBurnFile {\r
+\r
+ private Integer motor_id;\r
+ private String filetype;\r
+ private Float length;\r
+ private String delays;\r
+ private Double propWeightG;\r
+ private Double totWeightG;\r
+ private Vector<Double> datapoints = new Vector<Double>();\r
+ \r
+ public void init() {\r
+ this.motor_id = null;\r
+ this.filetype = null;\r
+ this.length = null;\r
+ this.delays = null;\r
+ this.propWeightG = null;\r
+ this.totWeightG = null;\r
+ this.datapoints = new Vector<Double>();\r
+ }\r
+ \r
+ @Override\r
+ public MotorBurnFile clone() {\r
+ MotorBurnFile clone = new MotorBurnFile();\r
+ clone.motor_id = this.motor_id;\r
+ clone.filetype = this.filetype;\r
+ clone.length = this.length;\r
+ clone.delays = this.delays;\r
+ clone.propWeightG = this.propWeightG;\r
+ clone.totWeightG = this.totWeightG;\r
+ clone.datapoints = this.datapoints;\r
+ return clone;\r
+ }\r
+\r
+ public void decodeFile(String data){\r
+ if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) {\r
+ RaspBurnFile.parse(this,data);\r
+ } else if (SupportedFileTypes.ROCKSIM_FORMAT.equals(filetype) ){\r
+ RSEBurnFile.parse(this,data);\r
+ }\r
+ }\r
+ \r
+ public Integer getMotorId() {\r
+ return motor_id;\r
+ }\r
+ public String getFileType() {\r
+ return filetype;\r
+ }\r
+ public Float getLength() {\r
+ return length;\r
+ }\r
+ public String getDelays() {\r
+ return delays;\r
+ }\r
+ public Double getPropWeightG() {\r
+ return propWeightG;\r
+ }\r
+ public Double getTotWeightG() {\r
+ return totWeightG;\r
+ }\r
+ public Vector<Double> getDatapoints() {\r
+ return datapoints;\r
+ }\r
+\r
+ void setMotor_id(Integer motor_id) {\r
+ this.motor_id = motor_id;\r
+ }\r
+ void setFiletype(String filetype ) {\r
+ this.filetype = filetype;\r
+ }\r
+ void setLength(Float length) {\r
+ this.length = length;\r
+ }\r
+ void setDelays(String delays) {\r
+ this.delays = delays;\r
+ }\r
+ void setPropWeightG(Double propWeightG) {\r
+ this.propWeightG = propWeightG;\r
+ }\r
+ void setTotWeightG(Double totWeightG) {\r
+ this.totWeightG = totWeightG;\r
+ }\r
+ void setDatapoints(Vector<Double> datapoints) {\r
+ this.datapoints = datapoints;\r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.InputStream;\r
+import java.util.Vector;\r
+\r
+import org.xml.sax.Attributes;\r
+\r
+import android.sax.Element;\r
+import android.sax.RootElement;\r
+import android.sax.StartElementListener;\r
+import android.util.Log;\r
+import android.util.Xml;\r
+\r
+class RSEBurnFile extends MotorBurnFile {\r
+\r
+ private final static String TAG = "RSEBurnFile";\r
+\r
+ static void parse( MotorBurnFile that, String filecontents ) {\r
+\r
+ parse(that, new ByteArrayInputStream(filecontents.getBytes()) );\r
+ }\r
+\r
+ private final static String root_tag = "engine-database";\r
+ private final static String engine_list_tag = "engine-list";\r
+ private final static String engine_tag = "engine";\r
+\r
+ private final static String delays_attr = "delays";\r
+ private final static String len_attr = "len";\r
+ private final static String propwgt_attr = "propWt";\r
+ private final static String totwgt_attr = "initWt";\r
+\r
+ private final static String data_tag = "data";\r
+ private final static String eng_data_tag = "eng-data";\r
+\r
+ private final static String time_attr="t";\r
+ private final static String force_attr="f";\r
+\r
+ static void parse( final MotorBurnFile that, InputStream in ) {\r
+\r
+ RootElement rootEl = new RootElement(root_tag);\r
+ Element engineEl = rootEl.getChild(engine_list_tag).getChild(engine_tag);\r
+\r
+ final Vector<Double> datapoints = new Vector<Double>();\r
+ \r
+ Log.d(TAG,"parsing start");\r
+\r
+ engineEl.setStartElementListener(\r
+ new StartElementListener() {\r
+ @Override\r
+ public void start(Attributes arg0) {\r
+ Log.d(TAG,"start engineEl");\r
+ that.setPropWeightG(Double.parseDouble(arg0.getValue(propwgt_attr)));\r
+ that.setTotWeightG(Double.parseDouble(arg0.getValue(totwgt_attr)));\r
+ that.setLength(Float.parseFloat(arg0.getValue(len_attr)));\r
+ that.setDelays(arg0.getValue(delays_attr));\r
+ Log.d(TAG, "me is now " + that.toString());\r
+ }\r
+ }\r
+ );\r
+\r
+ Element datapointEl = engineEl.getChild(data_tag).getChild(eng_data_tag);\r
+ datapointEl.setStartElementListener(\r
+ new StartElementListener() {\r
+ @Override\r
+ public void start(Attributes attributes) {\r
+ Double x = Double.parseDouble(attributes.getValue(time_attr));\r
+ Double y = Double.parseDouble(attributes.getValue(force_attr));\r
+ Log.d(TAG, "add data point " + x + "," + y);\r
+ datapoints.add(x);\r
+ datapoints.add(y);\r
+ }\r
+ }\r
+ );\r
+\r
+ try {\r
+ Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
+ } catch (Exception e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+\r
+ that.setDatapoints(datapoints);\r
+ }\r
+}\r
+//\r
+// <engine-database>\r
+// <engine-list>\r
+// <engine FDiv="10" FFix="1" FStep="-1." Isp="202.11" Itot="8.919" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.795" burn-time="2.35" cgDiv="10" cgFix="1" cgStep="-1." code="C4" delays="3,5,7" dia="18." exitDia="0." initWt="17." len="50." mDiv="10" mFix="1" mStep="-1." massFrac="26.47" mfg="Apogee" peakThrust="11.31" propWt="4.5" tDiv="10" tFix="1" tStep="-1." throatDia="0.">\r
+// <comments>Apogee C4 RASP.ENG file made from NAR published data\r
+// File produced September 4, 2000\r
+// The total impulse, peak thrust, average thrust and burn time are\r
+// the same as the averaged static test data on the NAR web site in\r
+// the certification file. The curve drawn with these data points is as\r
+// close to the certification curve as can be with such a limited\r
+// number of points (32) allowed with wRASP up to v1.6.\r
+// </comments>\r
+// <data>\r
+// <eng-data cg="25." f="0." m="4.5" t="0."/>\r
+// <eng-data cg="25." f="3.23" m="4.48533" t="0.018"/>\r
+// <eng-data cg="25." f="6.874" m="4.42671" t="0.041"/>\r
+// <eng-data cg="25." f="8.779" m="4.00814" t="0.147"/>\r
+// <eng-data cg="25." f="10.683" m="3.28643" t="0.294"/>\r
+// <eng-data cg="25." f="11.31" m="2.89252" t="0.365"/>\r
+// <eng-data cg="25." f="10.521" m="2.76585" t="0.388"/>\r
+// <eng-data cg="25." f="8.779" m="2.649" t="0.412"/>\r
+// <eng-data cg="25." f="7.04" m="2.53328" t="0.441"/>\r
+// <eng-data cg="25." f="4.555" m="2.46308" t="0.465"/>\r
+// <eng-data cg="25." f="3.479" m="2.33337" t="0.529"/>\r
+// <eng-data cg="25." f="2.981" m="2.1704" t="0.629"/>\r
+// <eng-data cg="25." f="3.23" m="2.1328" t="0.653"/>\r
+// <eng-data cg="25." f="2.816" m="2.03366" t="0.718"/>\r
+// <eng-data cg="25." f="2.733" m="1.84469" t="0.853"/>\r
+// <eng-data cg="25." f="2.65" m="1.5568" t="1.065"/>\r
+// <eng-data cg="25." f="2.567" m="1.30938" t="1.253"/>\r
+// <eng-data cg="25." f="2.401" m="1.05873" t="1.453"/>\r
+// <eng-data cg="25." f="2.484" m="0.761739" t="1.694"/>\r
+// <eng-data cg="25." f="2.484" m="0.636413" t="1.794"/>\r
+// <eng-data cg="25." f="2.733" m="0.612724" t="1.812"/>\r
+// <eng-data cg="25." f="2.401" m="0.575165" t="1.841"/>\r
+// <eng-data cg="25." f="2.401" m="0.446759" t="1.947"/>\r
+// <eng-data cg="25." f="2.401" m="0.246881" t="2.112"/>\r
+// <eng-data cg="25." f="2.401" m="0.0978809" t="2.235"/>\r
+// <eng-data cg="25." f="2.236" m="0.0429024" t="2.282"/>\r
+// <eng-data cg="25." f="1.656" m="0.0134478" t="2.312"/>\r
+// <eng-data cg="25." f="0.662" m="0.003507" t="2.329"/>\r
+// <eng-data cg="25." f="0." m="-0." t="2.35"/>\r
+// </data>\r
+// </engine>\r
+// </engine-list>\r
+// </engine-database>\r
+//\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.IOException;\r
+import java.io.LineNumberReader;\r
+import java.io.StringReader;\r
+import java.util.Vector;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import android.util.Log;\r
+\r
+\r
+class RaspBurnFile{\r
+\r
+ private final static String TAG = "RaspBurnFile";\r
+ \r
+ private final static int HEADER = 0;\r
+ private final static int DATA = 1;\r
+ private final static Pattern headerPattern = Pattern.compile("(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)");\r
+ private final static Pattern dataPattern = Pattern.compile("(\\S*)\\s+(\\S*)");\r
+ \r
+ static void parse( MotorBurnFile that, String filecontents ) {\r
+ \r
+ int state = HEADER;\r
+ \r
+ LineNumberReader reader = new LineNumberReader( new StringReader(filecontents));\r
+ \r
+ Vector<Double> datapoints = new Vector<Double>();\r
+ \r
+ String line;\r
+ Matcher m;\r
+ try {\r
+ while ( (line = reader.readLine()) != null ) {\r
+ line = line.trim();\r
+ Log.d("RASP",line);\r
+ if ( line.startsWith(";")) {\r
+ continue;\r
+ }\r
+ switch (state) {\r
+ \r
+ case HEADER:\r
+ Log.d("RASP","header");\r
+ m = headerPattern.matcher(line);\r
+ if ( m.matches() ) {\r
+ Log.d("RASP","header matches");\r
+ \r
+ /*motorName = m.group(1);*/\r
+ /*diameter = Integer.decode(m.group(2));*/\r
+ that.setLength(Float.parseFloat(m.group(3)) );\r
+ String delays = m.group(4);\r
+ if ( delays != null ) {\r
+ delays = delays.replace("-", ",");\r
+ that.setDelays(delays);\r
+ }\r
+ that.setPropWeightG(Double.parseDouble(m.group(5))*1000.0);\r
+ that.setTotWeightG(Double.parseDouble(m.group(6))*1000.0);\r
+ /*manufacturer = m.group(7);*/\r
+ \r
+ }\r
+ state = DATA;\r
+ break;\r
+ \r
+ case DATA:\r
+ Log.d("RASP","data");\r
+ m = dataPattern.matcher(line);\r
+ if ( m.matches() ) {\r
+ Log.d("RASP","data matches");\r
+ Double x = Double.parseDouble(m.group(1));\r
+ Double y = Double.parseDouble(m.group(2));\r
+ Log.d("RASP","data matches ("+x+","+y+")");\r
+ datapoints.add(x);\r
+ datapoints.add(y);\r
+ }\r
+ break;\r
+ }\r
+ that.setDatapoints(datapoints);\r
+ }\r
+ } catch (IOException ex ) {\r
+ Log.d(TAG,"Unable to parse Rasp file: " + ex);\r
+ }\r
+ \r
+ }\r
+ \r
+\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+public class SearchRequest {\r
+\r
+ private String manufacturer;\r
+ private String designation;\r
+ private String brand_name;\r
+ \r
+ private String common_name;\r
+ private String impulse_class;\r
+ private Integer diameter;\r
+ \r
+ /*\r
+ public enum Type {\r
+ "SU";\r
+ "reload";\r
+ "hybrid"\r
+ };\r
+ */\r
+ private String type;\r
+ \r
+ public void setManufacturer(String manufacturer) {\r
+ this.manufacturer = null;\r
+ if ( manufacturer != null ) {\r
+ manufacturer = manufacturer.trim();\r
+ if ( ! "".equals(manufacturer) ) {\r
+ this.manufacturer = manufacturer;\r
+ }\r
+ }\r
+ }\r
+\r
+ public void setDesignation(String designation) {\r
+ this.designation = designation;\r
+ }\r
+\r
+ public void setBrand_name(String brand_name) {\r
+ this.brand_name = brand_name;\r
+ }\r
+\r
+ public void setCommon_name(String common_name) {\r
+ if ( common_name == null ) {\r
+ this.common_name = null;\r
+ return;\r
+ }\r
+ this.common_name = common_name.trim();\r
+ if ( "".equals(this.common_name)) {\r
+ this.common_name = null;\r
+ }\r
+ }\r
+\r
+ public void setImpulse_class(String impulse_class) {\r
+ this.impulse_class = null;\r
+ if ( impulse_class != null ) {\r
+ this.impulse_class = impulse_class.trim();\r
+ if ( "".equals(impulse_class) ) {\r
+ this.impulse_class = null;\r
+ }\r
+ }\r
+ }\r
+\r
+ public void setDiameter(Integer diameter) {\r
+ this.diameter = diameter;\r
+ }\r
+ \r
+ public void setDiameter(String diameter) {\r
+ this.diameter = null;\r
+ if ( diameter == null ) {\r
+ return;\r
+ }\r
+ try {\r
+ this.diameter = Integer.decode(diameter);\r
+ } catch ( NumberFormatException ex ) {\r
+ this.diameter = null;\r
+ }\r
+ }\r
+\r
+ public void setType(String type) {\r
+ this.type = type;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder w = new StringBuilder();\r
+ \r
+ w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");\r
+ w.append("<search-request\n");\r
+ w.append(" xmlns=\"http://www.thrustcurve.org/2011/SearchRequest\"\n");\r
+ w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");\r
+ w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2011/SearchRequest http://www.thrustcurve.org/2011/search-request.xsd\">\n");\r
+\r
+ if ( manufacturer != null ) {\r
+ w.append(" <manufacturer>").append(manufacturer).append("</manufacturer>\n");\r
+ }\r
+ if ( designation != null ) {\r
+ w.append(" <designation>").append(designation).append("</designation>\n");\r
+ }\r
+ if ( brand_name != null ) {\r
+ w.append(" <brand-name>").append(brand_name).append("</brand-name>\n");\r
+ }\r
+ if ( common_name != null ) {\r
+ w.append(" <common-name>").append(common_name).append("</common-name>\n");\r
+ }\r
+ if ( impulse_class != null ) {\r
+ w.append(" <impulse-class>").append(impulse_class).append("</impulse-class>\n");\r
+ }\r
+ if ( diameter != null ) {\r
+ w.append(" <diameter>").append(diameter).append("</diameter>\n");\r
+ }\r
+ if ( type != null ) {\r
+ w.append(" <type>").append(type).append("</type>\n");\r
+ }\r
+ w.append("<data-fields>*</data-fields>");\r
+ w.append("<max-results>50</max-results>");\r
+ w.append("</search-request>\n");\r
+ return w.toString();\r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+\r
+public class SearchResponse {\r
+\r
+ private List<TCMotor> results = new ArrayList<TCMotor>();\r
+ \r
+ private int matches;\r
+ \r
+ private String error;\r
+\r
+ public List<TCMotor> getResults() {\r
+ return results;\r
+ }\r
+\r
+ public void setResults(List<TCMotor> results) {\r
+ this.results = results;\r
+ }\r
+\r
+ public int getMatches() {\r
+ return matches;\r
+ }\r
+\r
+ public void setMatches(int matches) {\r
+ this.matches = matches;\r
+ }\r
+\r
+ public String getError() {\r
+ return error;\r
+ }\r
+\r
+ public void setError(String error) {\r
+ this.error = error;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "SearchResult [results=" + results + ", matches=" + matches\r
+ + ", error=" + error + "]";\r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.InputStream;\r
+\r
+import org.xml.sax.Attributes;\r
+\r
+import android.sax.Element;\r
+import android.sax.EndElementListener;\r
+import android.sax.EndTextElementListener;\r
+import android.sax.RootElement;\r
+import android.sax.StartElementListener;\r
+import android.util.Xml;\r
+\r
+public class SearchResponseParser {\r
+\r
+ private static final String thrustcurveURI = "http://www.thrustcurve.org/2008/SearchResponse";\r
+ /*\r
+ * XML Tags in SearchResult xsd\r
+ */\r
+ private static final String root_tag = "search-response";\r
+ private static final String criteria = "criteria";\r
+ private static final String criterion = "criterion";\r
+ private static final String name = "name";\r
+ private static final String value = "value";\r
+ private static final String matches = "matches";\r
+ private static final String results = "results";\r
+ private static final String result = "result";\r
+ \r
+ private static final String motor_id = "motor-id";\r
+ private static final String manufacturer = "manufacturer";\r
+ private static final String manufacturer_abbr = "manufacturer-abbrev";\r
+ private static final String designation = "designation";\r
+ private static final String brand_name = "brand-name";\r
+ private static final String common_name = "common-name";\r
+ private static final String impulse_class = "impulse-class";\r
+ private static final String diameter = "diameter";\r
+ private static final String length = "length";\r
+ private static final String type = "type";\r
+ private static final String cert_org = "cert-org";\r
+ private static final String avg_thrust_n = "avg-thrust-n";\r
+ private static final String max_thrust_n = "max-thrust-n";\r
+ private static final String tot_impulse_ns = "tot-impulse-ns";\r
+ private static final String burn_time_s = "burn-time-s";\r
+ private static final String data_files = "data-files";\r
+ private static final String info_url = "info-url";\r
+ private static final String total_weight_g = "total-weight-g";\r
+ private static final String prop_weight_g = "prop-weight-g";\r
+ private static final String delays = "delays";\r
+ private static final String case_info = "case-info";\r
+ private static final String prop_info = "prop-info";\r
+ private static final String updated_on = "updated-on";\r
+ \r
+ public static SearchResponse parse( InputStream in ) {\r
+ \r
+ final SearchResponse ret = new SearchResponse();\r
+ final TCMotor currentMotor = new TCMotor();\r
+\r
+ RootElement rootEl = new RootElement(thrustcurveURI, root_tag);\r
+ Element criteriaEl = rootEl.getChild( thrustcurveURI, criteria);\r
+ \r
+ criteriaEl.getChild(thrustcurveURI,matches).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ ret.setMatches(Integer.parseInt(arg0));\r
+ }\r
+ }\r
+ );\r
+ Element resultsEl = rootEl.getChild(thrustcurveURI,results);\r
+ Element resultEl = resultsEl.getChild(thrustcurveURI,result);\r
+\r
+ resultEl.setStartElementListener(\r
+ new StartElementListener() {\r
+ @Override\r
+ public void start(Attributes arg0) {\r
+ currentMotor.init();\r
+ }\r
+ }\r
+ );\r
+ \r
+ resultEl.setEndElementListener(\r
+ new EndElementListener() {\r
+ @Override\r
+ public void end() {\r
+ ret.getResults().add((TCMotor)currentMotor.clone());\r
+ }\r
+ }\r
+ );\r
+ \r
+ resultEl.getChild(thrustcurveURI,motor_id).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setMotor_id(Integer.parseInt(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,manufacturer).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ if ( arg0 != null ) {\r
+ currentMotor.setManufacturer(arg0);\r
+ }\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,manufacturer_abbr).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ if ( arg0 != null ) {\r
+ currentMotor.setManufacturer_abbr(arg0);\r
+ }\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,designation).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setDesignation(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,brand_name).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setBrand_name(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,common_name).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setCommon_name(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,impulse_class).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setImpulse_class(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,diameter).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setDiameter(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,length).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setLength(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,type).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setType(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,cert_org).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setCert_org(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,avg_thrust_n).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setAvg_thrust_n(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,max_thrust_n).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setMax_thrust_n(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,tot_impulse_ns).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setTot_impulse_ns(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,burn_time_s).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setBurn_time_s(Float.parseFloat(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,data_files).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setData_files(Integer.parseInt(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,info_url).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setInfo_url(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,total_weight_g).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setTot_mass_g(Double.parseDouble(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,prop_weight_g).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setProp_mass_g(Double.parseDouble(arg0));\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,delays).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setDelays(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,case_info).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setCase_info(arg0);\r
+ }\r
+ }\r
+ );\r
+ resultEl.getChild(thrustcurveURI,prop_info).setEndTextElementListener(\r
+ new EndTextElementListener() {\r
+ @Override\r
+ public void end(String arg0) {\r
+ currentMotor.setProp_info(arg0);\r
+ }\r
+ }\r
+ );\r
+\r
+\r
+ try {\r
+ Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
+ } catch (Exception e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+\r
+ return ret;\r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+public abstract class SupportedFileTypes {\r
+\r
+ public final static String ROCKSIM_FORMAT = "RockSim";\r
+ public final static String RASP_FORMAT = "RASP";\r
+ \r
+ public static boolean isSupportedFileType( String arg0 ) {\r
+ return (ROCKSIM_FORMAT.equals(arg0) || RASP_FORMAT.equals(arg0));\r
+ }\r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.Date;\r
+import java.util.Vector;\r
+\r
+public class TCMotor implements Cloneable {\r
+\r
+ private Integer motor_id;\r
+ private String manufacturer;\r
+ private String manufacturer_abbr;\r
+ private String designation;\r
+ private String brand_name;\r
+ private String common_name;\r
+ private String impulse_class;\r
+ private Float diameter;\r
+ private Float length;\r
+ private String type;\r
+ private String cert_org;\r
+ private Float avg_thrust_n;\r
+ private Float max_thrust_n;\r
+ private Float tot_impulse_ns;\r
+ private Float burn_time_s;\r
+ private Integer data_files;\r
+ private String info_url;\r
+ private Double tot_mass_g;\r
+ private Double prop_mass_g;\r
+ private String delays;\r
+ private String case_info;\r
+ private String prop_info;\r
+ private Date updated_on;\r
+ private Vector<Double> burndata;\r
+ \r
+ public void init() {\r
+ motor_id = null;\r
+ manufacturer = null;\r
+ manufacturer_abbr = null;\r
+ designation = null;\r
+ brand_name = null;\r
+ common_name = null;\r
+ impulse_class = null;\r
+ diameter = null;\r
+ length = null;\r
+ type = null;\r
+ cert_org = null;\r
+ avg_thrust_n = null;\r
+ max_thrust_n = null;\r
+ tot_impulse_ns = null;\r
+ burn_time_s = null;\r
+ data_files = null;\r
+ info_url = null;\r
+ tot_mass_g = null;\r
+ prop_mass_g = null;\r
+ delays = null;\r
+ case_info = null;\r
+ prop_info = null;\r
+ updated_on = null;\r
+ burndata = null;\r
+ }\r
+ \r
+ @Override\r
+ public TCMotor clone() {\r
+ TCMotor clone = new TCMotor();\r
+ clone.motor_id = this.motor_id;\r
+ clone.manufacturer = this.manufacturer;\r
+ clone.manufacturer_abbr = this.manufacturer_abbr;\r
+ clone.designation = this.designation;\r
+ clone.brand_name = this.brand_name;\r
+ clone.common_name = this.common_name;\r
+ clone.impulse_class = this.impulse_class;\r
+ clone.diameter = this.diameter;\r
+ clone.length = this.length;\r
+ clone.type = this.type;\r
+ clone.cert_org = this.cert_org;\r
+ clone.avg_thrust_n = this.avg_thrust_n;\r
+ clone.max_thrust_n = this.max_thrust_n;\r
+ clone.tot_impulse_ns = this.tot_impulse_ns;\r
+ clone.burn_time_s = this.burn_time_s;\r
+ clone.data_files = this.data_files;\r
+ clone.info_url = this.info_url;\r
+ clone.tot_mass_g = this.tot_mass_g;\r
+ clone.prop_mass_g = this.prop_mass_g;\r
+ clone.delays = this.delays;\r
+ clone.case_info = this.case_info;\r
+ clone.prop_info = this.prop_info;\r
+ clone.updated_on = this.updated_on;\r
+ clone.burndata = this.burndata;\r
+ return clone;\r
+ }\r
+\r
+ public Integer getMotor_id() {\r
+ return motor_id;\r
+ }\r
+\r
+ public void setMotor_id(Integer motor_id) {\r
+ this.motor_id = motor_id;\r
+ }\r
+\r
+ public String getManufacturer() {\r
+ return manufacturer;\r
+ }\r
+\r
+ public void setManufacturer(String manufacturer) {\r
+ this.manufacturer = manufacturer;\r
+ }\r
+\r
+ public String getManufacturer_abbr() {\r
+ return manufacturer_abbr;\r
+ }\r
+\r
+ public void setManufacturer_abbr(String manufacturer_abbr) {\r
+ this.manufacturer_abbr = manufacturer_abbr;\r
+ }\r
+\r
+ public String getDesignation() {\r
+ return designation;\r
+ }\r
+\r
+ public void setDesignation(String designation) {\r
+ this.designation = designation;\r
+ }\r
+\r
+ public String getBrand_name() {\r
+ return brand_name;\r
+ }\r
+\r
+ public void setBrand_name(String brand_name) {\r
+ this.brand_name = brand_name;\r
+ }\r
+\r
+ public String getCommon_name() {\r
+ return common_name;\r
+ }\r
+\r
+ public void setCommon_name(String common_name) {\r
+ this.common_name = common_name;\r
+ }\r
+\r
+ public String getImpulse_class() {\r
+ return impulse_class;\r
+ }\r
+\r
+ public void setImpulse_class(String impulse_class) {\r
+ this.impulse_class = impulse_class;\r
+ }\r
+\r
+ public Float getDiameter() {\r
+ return diameter;\r
+ }\r
+\r
+ public void setDiameter(Float diameter) {\r
+ this.diameter = diameter;\r
+ }\r
+\r
+ public Float getLength() {\r
+ return length;\r
+ }\r
+\r
+ public void setLength(Float length) {\r
+ this.length = length;\r
+ }\r
+\r
+ public String getType() {\r
+ return type;\r
+ }\r
+\r
+ public void setType(String type) {\r
+ this.type = type;\r
+ }\r
+\r
+ public String getCert_org() {\r
+ return cert_org;\r
+ }\r
+\r
+ public void setCert_org(String cert_org) {\r
+ this.cert_org = cert_org;\r
+ }\r
+\r
+ public Float getAvg_thrust_n() {\r
+ return avg_thrust_n;\r
+ }\r
+\r
+ public void setAvg_thrust_n(Float avg_thrust_n) {\r
+ this.avg_thrust_n = avg_thrust_n;\r
+ }\r
+\r
+ public Float getMax_thrust_n() {\r
+ return max_thrust_n;\r
+ }\r
+\r
+ public void setMax_thrust_n(Float max_thrust_n) {\r
+ this.max_thrust_n = max_thrust_n;\r
+ }\r
+\r
+ public Float getTot_impulse_ns() {\r
+ return tot_impulse_ns;\r
+ }\r
+\r
+ public void setTot_impulse_ns(Float tot_impulse_ns) {\r
+ this.tot_impulse_ns = tot_impulse_ns;\r
+ }\r
+\r
+ public Float getBurn_time_s() {\r
+ return burn_time_s;\r
+ }\r
+\r
+ public void setBurn_time_s(Float burn_time_s) {\r
+ this.burn_time_s = burn_time_s;\r
+ }\r
+\r
+ public Integer getData_files() {\r
+ return data_files;\r
+ }\r
+\r
+ public void setData_files(Integer data_files) {\r
+ this.data_files = data_files;\r
+ }\r
+\r
+ public String getInfo_url() {\r
+ return info_url;\r
+ }\r
+\r
+ public void setInfo_url(String info_url) {\r
+ this.info_url = info_url;\r
+ }\r
+\r
+ public Double getTot_mass_g() {\r
+ return tot_mass_g;\r
+ }\r
+\r
+ public void setTot_mass_g(Double tot_mass_g) {\r
+ this.tot_mass_g = tot_mass_g;\r
+ }\r
+\r
+ public Double getProp_mass_g() {\r
+ return prop_mass_g;\r
+ }\r
+\r
+ public void setProp_mass_g(Double prop_mass_g) {\r
+ this.prop_mass_g = prop_mass_g;\r
+ }\r
+\r
+ public String getDelays() {\r
+ return delays;\r
+ }\r
+\r
+ public void setDelays(String delays) {\r
+ this.delays = delays;\r
+ }\r
+\r
+ public String getCase_info() {\r
+ return case_info;\r
+ }\r
+\r
+ public void setCase_info(String case_info) {\r
+ this.case_info = case_info;\r
+ }\r
+\r
+ public String getProp_info() {\r
+ return prop_info;\r
+ }\r
+\r
+ public void setProp_info(String prop_info) {\r
+ this.prop_info = prop_info;\r
+ }\r
+\r
+ public Date getUpdated_on() {\r
+ return updated_on;\r
+ }\r
+\r
+ public void setUpdated_on(Date updated_on) {\r
+ this.updated_on = updated_on;\r
+ }\r
+\r
+ public Vector<Double> getBurndata() {\r
+ return burndata;\r
+ }\r
+\r
+ public void setBurndata(Vector<Double> burndata) {\r
+ this.burndata = burndata;\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return "TCMotor [motor_id=" + motor_id + ", manufacturer="\r
+ + manufacturer + ", manufacturer_abbr=" + manufacturer_abbr\r
+ + ", designation=" + designation + ", brand_name=" + brand_name\r
+ + ", common_name=" + common_name + ", impulse_class="\r
+ + impulse_class + ", diameter=" + diameter + ", length="\r
+ + length + ", type=" + type + ", cert_org=" + cert_org\r
+ + ", avg_thrust_n=" + avg_thrust_n + ", max_thrust_n="\r
+ + max_thrust_n + ", tot_impulse_ns=" + tot_impulse_ns\r
+ + ", burn_time_s=" + burn_time_s + ", data_files=" + data_files\r
+ + ", info_url=" + info_url + ", tot_mass_g=" + tot_mass_g\r
+ + ", prop_mass_g=" + prop_mass_g + ", delays=" + delays\r
+ + ", case_info=" + case_info + ", prop_info=" + prop_info\r
+ + ", updated_on=" + updated_on + "]";\r
+ }\r
+ \r
+}\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.util.Vector;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.db.DbAdapter;\r
+import net.sf.openrocket.android.motor.Motor;\r
+import android.app.Activity;\r
+import android.app.AlertDialog;\r
+import android.app.ProgressDialog;\r
+import android.content.DialogInterface;\r
+import android.os.Bundle;\r
+import android.os.Handler;\r
+import android.util.Log;\r
+import android.view.View;\r
+import android.widget.Button;\r
+import android.widget.EditText;\r
+import android.widget.Spinner;\r
+\r
+public class TCQueryActivity extends Activity {\r
+\r
+ private static final String TAG = "ThrustCurveQueryActivity";\r
+\r
+ private DbAdapter mDbHelper;\r
+\r
+ private ProgressDialog progress;\r
+ private Thread downloadThread;\r
+ private Handler handler;\r
+\r
+ @Override\r
+ protected void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+ setContentView(R.layout.tcqueryform);\r
+\r
+ mDbHelper = new DbAdapter(this);\r
+ mDbHelper.open();\r
+\r
+ final Spinner manufacturerField = (Spinner) findViewById(R.id.TCMotorSearchFormManufacturerField);\r
+ final Spinner impulseField = (Spinner) findViewById(R.id.TCMotorSearchFormImpulseField);\r
+ final Spinner diameterField = (Spinner) findViewById(R.id.TCMotorSearchFormDiameterField);\r
+ final EditText commonNameField = (EditText) findViewById(R.id.TCMotorSearchFormCommonNameField);\r
+\r
+ Button submitButton = (Button) findViewById(R.id.TCMotorSearchFromSubmitButton);\r
+ submitButton.setOnClickListener(\r
+ new View.OnClickListener() {\r
+ @Override\r
+ public void onClick( View v ) {\r
+ Log.d(TAG,"submit button clicked");\r
+\r
+ String commonName = commonNameField.getText().toString();\r
+\r
+ SearchRequest r = new SearchRequest();\r
+ if ( manufacturerField.getSelectedItemPosition() != 0) {\r
+ String m = (String) manufacturerField.getSelectedItem();\r
+ Log.d(TAG,"manufacturer = " + m);\r
+ r.setManufacturer(m);\r
+ }\r
+ if ( impulseField.getSelectedItemPosition() != 0 ) {\r
+ String impulse = (String) impulseField.getSelectedItem();\r
+ Log.d(TAG,"impulse = " + impulse);\r
+ r.setImpulse_class(impulse);\r
+ }\r
+ if ( diameterField.getSelectedItemPosition() != 0 ) {\r
+ String diameter = (String)diameterField.getSelectedItem();\r
+ Log.d(TAG,"diameter = " + diameter);\r
+ r.setDiameter(diameter);\r
+ }\r
+ r.setCommon_name(commonName);\r
+\r
+ Downloader d = new Downloader(r);\r
+\r
+ handler = new Handler();\r
+ progress = ProgressDialog.show(TCQueryActivity.this, null, "");\r
+\r
+ downloadThread = new Thread( d );\r
+ downloadThread.start();\r
+ }\r
+ }\r
+ );\r
+ }\r
+\r
+ @Override\r
+ public Object onRetainNonConfigurationInstance() {\r
+ return downloadThread;\r
+ }\r
+\r
+ @Override\r
+ protected void onDestroy() {\r
+ mDbHelper.close();\r
+ if ( progress != null ) {\r
+ if ( progress.isShowing() ) {\r
+ progress.dismiss();\r
+ }\r
+ progress = null;\r
+ }\r
+ super.onDestroy();\r
+ }\r
+\r
+ private class UpdateMessage implements Runnable {\r
+ private String newMessage;\r
+ UpdateMessage( String message ) {\r
+ this.newMessage = message;\r
+ }\r
+ @Override\r
+ public void run() {\r
+ progress.setMessage(newMessage);\r
+ }\r
+ }\r
+\r
+ private class Dismiss implements Runnable {\r
+ @Override\r
+ public void run() {\r
+ progress.dismiss();\r
+ TCQueryActivity.this.finish();\r
+ }\r
+ }\r
+\r
+ private class Error implements Runnable {\r
+ private String newMessage;\r
+ Error( String message ) {\r
+ this.newMessage = message;\r
+ }\r
+ @Override\r
+ public void run() {\r
+ progress.dismiss();\r
+ final AlertDialog dialog = new AlertDialog.Builder(TCQueryActivity.this).create();\r
+ dialog.setMessage(newMessage);\r
+ dialog.setButton(DialogInterface.BUTTON_NEUTRAL,"Dismiss", new DialogInterface.OnClickListener() {\r
+\r
+ @Override\r
+ public void onClick(DialogInterface arg0, int arg1) {\r
+ dialog.dismiss();\r
+ }\r
+\r
+ });\r
+ dialog.show();\r
+ }\r
+ }\r
+ private class Downloader implements Runnable {\r
+\r
+ SearchRequest request;\r
+\r
+ Downloader( SearchRequest request ) {\r
+ this.request = request;\r
+ }\r
+\r
+ @Override\r
+ public void run() {\r
+ try {\r
+ handler.post( new UpdateMessage("Quering Thrustcurve"));\r
+ SearchResponse res = new ThrustCurveAPI().doSearch(request);\r
+\r
+ int total = res.getResults().size();\r
+ int count = 1;\r
+ for( TCMotor mi : res.getResults() ) {\r
+ handler.post(new UpdateMessage("Downloading details " + count + " of " + total));\r
+ count++;\r
+ if ( mi.getData_files() == null || mi.getData_files().intValue() == 0 ) {\r
+ continue;\r
+ }\r
+\r
+ MotorBurnFile b = new ThrustCurveAPI().downloadData(mi.getMotor_id());\r
+\r
+ if ( b != null ) {\r
+ if ( b.getLength() != null ) {\r
+ mi.setLength( b.getLength() );\r
+ }\r
+ if ( b.getPropWeightG() != null ) {\r
+ mi.setProp_mass_g(b.getPropWeightG());\r
+ }\r
+ if ( b.getTotWeightG() != null ) {\r
+ mi.setTot_mass_g(b.getTotWeightG());\r
+ }\r
+ if ( b.getDelays() != null ) {\r
+ mi.setDelays(b.getDelays());\r
+ }\r
+ mi.setBurndata(b.getDatapoints());\r
+ }\r
+ Log.d(TAG, mi.toString());\r
+\r
+ // convert to Motors. One per delay.\r
+ Motor m = new Motor();\r
+ // Base name of motor.\r
+ String name = mi.getCommon_name() + "-";\r
+\r
+ m.setManufacturer(mi.getManufacturer_abbr());\r
+ // Convert impulse class. ThrustCurve puts mmx, 1/4a and 1/2a as A.\r
+ m.setImpulseClass(mi.getImpulse_class());\r
+ if ( "a".equalsIgnoreCase(mi.getImpulse_class())) {\r
+ if( mi.getCommon_name().startsWith("1/2A") ) {\r
+ m.setImpulseClass("1/2A");\r
+ } else if (mi.getCommon_name().startsWith("1/4A") ) {\r
+ m.setImpulseClass("1/4A");\r
+ } else if (mi.getCommon_name().startsWith("Micro") ) {\r
+ m.setImpulseClass("1/8A");\r
+ }\r
+ }\r
+ m.setAvgThrust(mi.getAvg_thrust_n());\r
+ m.setBurndata(mi.getBurndata());\r
+ m.setBurnTime(mi.getBurn_time_s());\r
+ m.setDiameter(mi.getDiameter() == null ? null : mi.getDiameter().longValue());\r
+ m.setLength(mi.getLength());\r
+ m.setMaxThrust(mi.getMax_thrust_n());\r
+ m.setPropMass(mi.getProp_mass_g());\r
+ m.setTotalImpulse(mi.getTot_impulse_ns());\r
+ m.setTotMass(mi.getTot_mass_g());\r
+ // Convert Case Info.\r
+ if ( mi.getCase_info() == null\r
+ || "single use".equalsIgnoreCase(mi.getCase_info())\r
+ || "single-use".equalsIgnoreCase(mi.getCase_info())) {\r
+ m.setCaseInfo(mi.getType()+ " " + mi.getDiameter() + "x" + mi.getLength());\r
+ } else {\r
+ m.setCaseInfo(mi.getCase_info());\r
+ }\r
+\r
+ Vector<String> delays = new Vector<String>();\r
+ {\r
+ String delaysString = mi.getDelays();\r
+ if ( delaysString != null ) {\r
+ delaysString = delaysString.trim();\r
+ }\r
+\r
+ if ( delaysString == null || "".equals(delaysString)) {\r
+ delays.add("");\r
+ } else {\r
+ String[] delayString = delaysString.split(",");\r
+ for( String d : delayString ) {\r
+ delays.add( d.trim() );\r
+ }\r
+ }\r
+ }\r
+\r
+ for( String d: delays ) {\r
+ if ( "100".equals(d) ) {\r
+ m.setName(name + "P");\r
+ } else {\r
+ m.setName(name + d);\r
+ }\r
+ mDbHelper.getMotorDao().insertOrUpdateMotor(m);\r
+ }\r
+ }\r
+ if ( total < res.getMatches() ) {\r
+ handler.post( new Error( total + " motors downloaded, " + res.getMatches() + " matched. Try restricting the query more.") );\r
+ } else {\r
+ handler.post( new Dismiss());\r
+ }\r
+ }\r
+ catch( Exception ex){\r
+ Log.d(TAG,ex.toString());\r
+ handler.post( new Error(ex.toString()) );\r
+ }\r
+\r
+ }\r
+ }\r
+}\r
+\r
--- /dev/null
+package net.sf.openrocket.android.thrustcurve;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+import java.net.URLConnection;\r
+\r
+import android.util.Log;\r
+\r
+\r
+public class ThrustCurveAPI {\r
+\r
+ private final static String TAG = "ThrustCurveAPI";\r
+ \r
+ private String url_base = "http://www.thrustcurve.org/servlets/";\r
+ \r
+ public SearchResponse doSearch( SearchRequest request ) throws MalformedURLException, IOException {\r
+ \r
+ String requestString = request.toString();\r
+ \r
+ Log.d(TAG, "doSearch: " + requestString);\r
+ URL url = new URL(url_base + "search");\r
+\r
+ OutputStream stream;\r
+\r
+ URLConnection conn = url.openConnection();\r
+ conn.setConnectTimeout(2000);\r
+ conn.setDoInput(true);\r
+ conn.setDoOutput(true);\r
+ conn.setUseCaches(false);\r
+\r
+ stream = conn.getOutputStream();\r
+\r
+ stream.write(requestString.getBytes());\r
+ \r
+ InputStream is = conn.getInputStream();\r
+\r
+ SearchResponse result = SearchResponseParser.parse(is);\r
+ Log.d(TAG,result.toString());\r
+ \r
+ return result;\r
+ }\r
+\r
+ public MotorBurnFile downloadData( Integer motor_id ) throws MalformedURLException, IOException {\r
+\r
+ if ( motor_id == null ) {\r
+ return null;\r
+ }\r
+ DownloadRequest dr = new DownloadRequest();\r
+ dr.add(motor_id);\r
+\r
+ String requestString = dr.toString();\r
+\r
+ Log.d(TAG, "downloadData: " + requestString);\r
+ URL url = new URL(url_base + "download");\r
+\r
+ OutputStream stream;\r
+\r
+ URLConnection conn = url.openConnection();\r
+ conn.setDoInput(true);\r
+ conn.setDoOutput(true);\r
+ conn.setUseCaches(false);\r
+\r
+ stream = conn.getOutputStream();\r
+\r
+ stream.write(requestString.getBytes());\r
+\r
+ InputStream is = conn.getInputStream();\r
+\r
+ DownloadResponse downloadResponse = DownloadResponseParser.parse(is);\r
+ Log.d(TAG,downloadResponse.toString());\r
+\r
+ MotorBurnFile mbf = downloadResponse.getData(motor_id);\r
+\r
+ return mbf;\r
+\r
+ }\r
+}\r
+++ /dev/null
-package net.sf.openrocket.android;\r
-\r
-import java.util.Locale;\r
-\r
-import android.preference.PreferenceManager;\r
-\r
-import net.sf.openrocket.database.ThrustCurveMotorSetDatabase;\r
-import net.sf.openrocket.document.OpenRocketDocument;\r
-import net.sf.openrocket.l10n.DebugTranslator;\r
-import net.sf.openrocket.l10n.ResourceBundleTranslator;\r
-import net.sf.openrocket.l10n.Translator;\r
-\r
-public class Application extends android.app.Application {\r
-\r
- private OpenRocketDocument rocketDocument;\r
- \r
- // Big B boolean so I can synchronize on it.\r
- private static Boolean initialized = false;\r
- \r
- public static void initialize() {\r
- synchronized (initialized) {\r
- if ( initialized == true ) {\r
- return;\r
- }\r
-\r
- // Android does not have a default sax parser set. This needs to be defined first.\r
- System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");\r
-\r
- net.sf.openrocket.startup.Application.setLogger( new LogHelper() );\r
- \r
- net.sf.openrocket.startup.Application.setPreferences( new PreferencesAdapter() );\r
- \r
- ThrustCurveMotorSetDatabase db = new ThrustCurveMotorSetDatabase(false) {\r
- \r
- @Override\r
- protected void loadMotors() {\r
- }\r
- };\r
- db.startLoading();\r
-\r
- net.sf.openrocket.startup.Application.setMotorSetDatabase(db);\r
- \r
- Translator t;\r
- t = new ResourceBundleTranslator("l10n.messages");\r
- if (Locale.getDefault().getLanguage().equals("xx")) {\r
- t = new DebugTranslator(t);\r
- }\r
- \r
- net.sf.openrocket.startup.Application.setBaseTranslator(t);\r
-\r
- initialized = true;\r
- }\r
- }\r
-\r
- public Application() {\r
- initialize();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see android.app.Application#onCreate()\r
- */\r
- @Override\r
- public void onCreate() {\r
- super.onCreate();\r
- PreferencesActivity.initializePreferences(this, PreferenceManager.getDefaultSharedPreferences(this));\r
- }\r
-\r
- /**\r
- * @return the rocketDocument\r
- */\r
- public OpenRocketDocument getRocketDocument() {\r
- return rocketDocument;\r
- }\r
-\r
- /**\r
- * @param rocketDocument the rocketDocument to set\r
- */\r
- public void setRocketDocument(OpenRocketDocument rocketDocument) {\r
- this.rocketDocument = rocketDocument;\r
- }\r
- \r
- \r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android;\r
-\r
-import android.util.Log;\r
-import net.sf.openrocket.logging.LogLevel;\r
-import net.sf.openrocket.logging.LogLine;\r
-\r
-\r
-public class LogHelper extends net.sf.openrocket.logging.LogHelper {\r
-\r
- /* (non-Javadoc)\r
- * @see net.sf.openrocket.logging.LogHelper#log(net.sf.openrocket.logging.LogLine)\r
- */\r
- @Override\r
- public void log(LogLine line) {\r
- \r
- LogLevel level = line.getLevel();\r
- \r
- switch ( level ) {\r
- case ERROR:\r
- Log.e("OpenRocket", line.toString());\r
- break;\r
- case WARN:\r
- Log.w("OpenRocket", line.toString());\r
- break;\r
- case INFO:\r
- Log.i("OpenRocket", line.toString());\r
- break;\r
- case DEBUG:\r
- Log.d("OpenRocket", line.toString());\r
- break;\r
- default:\r
- Log.v("OpenRocket", line.toString());\r
- }\r
- }\r
-\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.android.motor.MotorHierarchicalBrowser;\r
-import android.app.Activity;\r
-import android.content.Intent;\r
-import android.net.Uri;\r
-import android.os.Bundle;\r
-import android.os.Handler;\r
-import android.os.Message;\r
-import android.view.View;\r
-import android.widget.ImageView;\r
-\r
-public class Main extends Activity {\r
-\r
- private static final int PICK_ORK_FILE_RESULT = 1;\r
-\r
- private static final int STOPSPLASH = 0;\r
- //time in milliseconds\r
- private static final long SPLASHTIME = 3000;\r
-\r
- private ImageView splash;\r
-\r
- //handler for splash screen\r
- private Handler splashHandler = new Handler() {\r
- /* (non-Javadoc)\r
- * @see android.os.Handler#handleMessage(android.os.Message)\r
- */\r
- @Override\r
- public void handleMessage(Message msg) {\r
- switch (msg.what) {\r
- case STOPSPLASH:\r
- //remove SplashScreen from view\r
- splash.setVisibility(View.GONE);\r
- break;\r
- }\r
- super.handleMessage(msg);\r
- }\r
- };\r
-\r
- /** Called when the activity is first created. */\r
- @Override\r
- public void onCreate(Bundle icicle) {\r
- super.onCreate(icicle);\r
- setContentView(R.layout.main);\r
- splash = (ImageView) findViewById(R.id.splashscreen);\r
- Message msg = new Message();\r
- msg.what = STOPSPLASH;\r
- splashHandler.sendMessageDelayed(msg, SPLASHTIME);\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)\r
- */\r
- @Override\r
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {\r
- switch ( requestCode ) {\r
- case PICK_ORK_FILE_RESULT:\r
- if(resultCode==RESULT_OK){\r
- Uri file = data.getData();\r
- Intent intent = new Intent(Intent.ACTION_VIEW);\r
- intent.setData(file);\r
- startActivity(intent);\r
- }\r
- break;\r
- }\r
- super.onActivityResult(requestCode, resultCode, data);\r
- }\r
-\r
- public void pickOrkFiles( View v ) {\r
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\r
- intent.setType("file/*");\r
- startActivityForResult(intent,PICK_ORK_FILE_RESULT);\r
- }\r
-\r
- public void browseMotors( View v ) {\r
- Intent i = new Intent(Main.this, MotorHierarchicalBrowser.class);\r
- startActivity(i);\r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.unit.UnitGroup;\r
-import android.content.SharedPreferences;\r
-import android.os.Bundle;\r
-import android.preference.PreferenceManager;\r
-\r
-public class PreferencesActivity extends android.preference.PreferenceActivity \r
-implements SharedPreferences.OnSharedPreferenceChangeListener {\r
-\r
- @Override\r
- protected void onCreate( Bundle savedInstanceState ) {\r
- super.onCreate( savedInstanceState );\r
- addPreferencesFromResource(R.xml.preferences);\r
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
- prefs.registerOnSharedPreferenceChangeListener(this);\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String)\r
- */\r
- @Override\r
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r
-\r
- initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this));\r
- }\r
-\r
- /**\r
- * This method is to be called from Application setup to pull the saved preference\r
- * values into the various datastructures used in OpenRocket.\r
- * This method is located in this class because it is probably best to have as much\r
- * of the code in the same place as possible.\r
- * @param sharedPreferences\r
- */\r
- public static void initializePreferences( android.app.Application app, SharedPreferences sharedPreferences ) {\r
- \r
- String unitLength = app.getResources().getString(R.string.PreferenceUnitLengthOption);\r
- String len = sharedPreferences.getString(unitLength, "cm");\r
- UnitGroup.UNITS_LENGTH.setDefaultUnit( len );\r
- \r
- String unitMass = app.getResources().getString(R.string.PreferenceUnitMassOption);\r
- String mass = sharedPreferences.getString(unitMass, "g");\r
- UnitGroup.UNITS_MASS.setDefaultUnit( mass );\r
- \r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android;\r
-\r
-import java.util.Collections;\r
-import java.util.Set;\r
-\r
-import net.sf.openrocket.material.Material;\r
-\r
-public class PreferencesAdapter extends net.sf.openrocket.startup.Preferences {\r
-\r
- @Override\r
- public boolean getBoolean(String key, boolean defaultValue) {\r
- // TODO Auto-generated method stub\r
- return false;\r
- }\r
-\r
- @Override\r
- public void putBoolean(String key, boolean value) {\r
- // TODO Auto-generated method stub\r
-\r
- }\r
-\r
- @Override\r
- public int getInt(String key, int defaultValue) {\r
- // TODO Auto-generated method stub\r
- return 0;\r
- }\r
-\r
- @Override\r
- public void putInt(String key, int value) {\r
- // TODO Auto-generated method stub\r
-\r
- }\r
-\r
- @Override\r
- public double getDouble(String key, double defaultValue) {\r
- // TODO Auto-generated method stub\r
- return 0;\r
- }\r
-\r
- @Override\r
- public void putDouble(String key, double value) {\r
- // TODO Auto-generated method stub\r
-\r
- }\r
-\r
- @Override\r
- public String getString(String key, String defaultValue) {\r
- // TODO Auto-generated method stub\r
- return null;\r
- }\r
-\r
- @Override\r
- public void putString(String key, String value) {\r
- // TODO Auto-generated method stub\r
-\r
- }\r
-\r
- @Override\r
- public String getString(String directory, String key, String defaultValue) {\r
- // TODO Auto-generated method stub\r
- return null;\r
- }\r
-\r
- @Override\r
- public void putString(String directory, String key, String value) {\r
- // TODO Auto-generated method stub\r
-\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see net.sf.openrocket.startup.Preferences#addUserMaterial(net.sf.openrocket.material.Material)\r
- */\r
- @Override\r
- public void addUserMaterial(Material m) {\r
- // TODO Auto-generated method stub\r
- \r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see net.sf.openrocket.startup.Preferences#getUserMaterials()\r
- */\r
- @Override\r
- public Set<Material> getUserMaterials() {\r
- return Collections.<Material>emptySet();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see net.sf.openrocket.startup.Preferences#removeUserMaterial(net.sf.openrocket.material.Material)\r
- */\r
- @Override\r
- public void removeUserMaterial(Material m) {\r
- // TODO Auto-generated method stub\r
- \r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.db;\r
-\r
-import android.content.Context;\r
-import android.database.SQLException;\r
-import android.database.sqlite.SQLiteDatabase;\r
-import android.database.sqlite.SQLiteOpenHelper;\r
-import android.util.Log;\r
-\r
-public class DbAdapter {\r
-\r
- private static final String TAG = "DbAdapter";\r
- private DatabaseHelper mDbHelper;\r
- private SQLiteDatabase mDb;\r
-\r
- private static final String DATABASE_NAME = "rocketflightnotebook";\r
- private static final int DATABASE_VERSION = 5;\r
-\r
- private final Context mCtx;\r
-\r
- private MotorDao motorDao;\r
- \r
- public MotorDao getMotorDao() {\r
- return motorDao;\r
- }\r
- \r
- private class DatabaseHelper extends SQLiteOpenHelper {\r
- DatabaseHelper(Context context) {\r
- super(context, DATABASE_NAME, null, DATABASE_VERSION);\r
- }\r
-\r
- @Override\r
- public void onCreate(SQLiteDatabase db) {\r
- executeSQL( db, MotorDao.create());\r
- }\r
- \r
- @Override\r
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\r
- Log.w(TAG, "Upgrading database from version " + oldVersion + " to "\r
- + newVersion + ", which will destroy all old data");\r
- executeSQL(db, MotorDao.update(oldVersion, newVersion));\r
- }\r
-\r
- private void executeSQL( SQLiteDatabase db, String[] sqls ) {\r
- for(String s: sqls ) {\r
- db.execSQL(s);\r
- }\r
- }\r
-\r
- }\r
- \r
- /**\r
- * Constructor - takes the context to allow the database to be\r
- * opened/created\r
- * \r
- * @param ctx the Context within which to work\r
- */\r
- public DbAdapter(Context ctx) {\r
- this.mCtx = ctx;\r
- }\r
-\r
- /**\r
- * Open the database. If it cannot be opened, try to create a new\r
- * instance of the database. If it cannot be created, throw an exception to\r
- * signal the failure\r
- * \r
- * @return this (self reference, allowing this to be chained in an\r
- * initialization call)\r
- * @throws SQLException if the database could be neither opened or created\r
- */\r
- public DbAdapter open() throws SQLException {\r
- mDbHelper = new DatabaseHelper(mCtx);\r
- mDb = mDbHelper.getWritableDatabase();\r
- motorDao = new MotorDao(mDb);\r
- return this;\r
- }\r
-\r
- public void close() {\r
- mDbHelper.close();\r
- }\r
-\r
-}
\ No newline at end of file
+++ /dev/null
-package net.sf.openrocket.android.db;\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.ObjectInputStream;\r
-import java.io.ObjectOutputStream;\r
-import java.util.Vector;\r
-\r
-import net.sf.openrocket.android.motor.Motor;\r
-import android.content.ContentValues;\r
-import android.database.Cursor;\r
-import android.database.SQLException;\r
-import android.database.sqlite.SQLiteDatabase;\r
-import android.util.Log;\r
-\r
-public class MotorDao {\r
-\r
- private static final String TAG = "MotorDao";\r
-\r
- private SQLiteDatabase mDb;\r
-\r
- private final static String DATABASE_TABLE = "motor";\r
- private final static String DROP_TABLE = "DROP TABLE IF EXISTS " + DATABASE_TABLE;\r
- private final static String CREATE_TABLE =\r
- "create table "+ DATABASE_TABLE + " ( " +\r
- "_id integer primary key, "+\r
- "unique_name text unique, "+\r
- "name text, "+\r
- "diameter number, "+\r
- "tot_impulse_ns number, "+\r
- "avg_thrust_n number, "+\r
- "max_thrust_n number, "+\r
- "burn_time_s number, "+\r
- "length number," +\r
- "prop_mass_g number,"+\r
- "tot_mass_g number,"+\r
- "case_info text,"+\r
- "manufacturer text," +\r
- "impulse_class text," +\r
- "burndata blob"+\r
- ");";\r
-\r
- MotorDao( SQLiteDatabase mDb ) {\r
- this.mDb = mDb;\r
- }\r
-\r
- static String[] create() { return new String[] {CREATE_TABLE}; }\r
-\r
- static String[] update( int oldVer, int newVer ) {\r
- return new String[] { DROP_TABLE, CREATE_TABLE };\r
- }\r
-\r
- public final static String ID = "_id";\r
- public final static String UNIQUE_NAME = "unique_name";\r
- public final static String NAME = "name";\r
- public final static String DIAMETER = "diameter";\r
- public final static String TOTAL_IMPULSE = "tot_impulse_ns"; \r
- public final static String AVG_THRUST = "avg_thrust_n";\r
- public final static String MAX_THRUST = "max_thrust_n";\r
- public final static String BURN_TIME = "burn_time_s";\r
- public final static String LENGTH = "length";\r
- public final static String PROP_MASS = "prop_mass_g";\r
- public final static String TOT_MASS = "tot_mass_g";\r
- public final static String BURNDATA = "burndata";\r
- public final static String CASE_INFO = "case_info";\r
- public final static String MANUFACTURER = "manufacturer";\r
- public final static String IMPULSE_CLASS = "impulse_class";\r
-\r
- public long insertOrUpdateMotor(Motor mi) {\r
- ContentValues initialValues = new ContentValues();\r
- initialValues.put(ID, mi.getMotor_id());\r
- initialValues.put(NAME, mi.getName());\r
- initialValues.put(DIAMETER,mi.getDiameter());\r
- initialValues.put(TOTAL_IMPULSE,mi.getTotalImpulse());\r
- initialValues.put(AVG_THRUST,mi.getAvgThrust());\r
- initialValues.put(MAX_THRUST,mi.getMaxThrust());\r
- initialValues.put(BURN_TIME,mi.getBurnTime());\r
- initialValues.put(LENGTH, mi.getLength());\r
- initialValues.put(PROP_MASS, mi.getPropMass());\r
- initialValues.put(TOT_MASS,mi.getTotMass());\r
- initialValues.put(CASE_INFO, mi.getCaseInfo());\r
- initialValues.put(MANUFACTURER,mi.getManufacturer());\r
- initialValues.put(IMPULSE_CLASS,mi.getImpulseClass());\r
- initialValues.put(UNIQUE_NAME, mi.getManufacturer()+mi.getName());\r
- {\r
- // Serialize the Vector of burn data\r
- Vector<Double> burndata = mi.getBurndata();\r
- byte[] serObj = null;\r
- if ( burndata != null ) {\r
- try {\r
- ByteArrayOutputStream b = new ByteArrayOutputStream();\r
- ObjectOutputStream os = new ObjectOutputStream(b);\r
- os.writeObject(burndata);\r
- os.close();\r
- serObj = b.toByteArray();\r
- } catch (Exception ex) {\r
- Log.d(TAG,"unable to serialze burndata");\r
- }\r
- }\r
- initialValues.put(BURNDATA, serObj);\r
- }\r
-\r
-\r
- Log.d(TAG,"insertOrUpdate Motor");\r
- long rv = mDb.insertWithOnConflict(DATABASE_TABLE, null, initialValues,SQLiteDatabase.CONFLICT_REPLACE);\r
- return rv;\r
- }\r
-\r
- /**\r
- * Delete the motor and burn data with the given rowId\r
- * \r
- * @param name name of motor to delete\r
- * @return true if deleted, false otherwise\r
- */\r
- public boolean deleteMotor(Long id) {\r
-\r
- boolean rv = mDb.delete(DATABASE_TABLE, ID + "=" + id, null) > 0;\r
- return rv;\r
- }\r
-\r
- /**\r
- * \r
- * @param groupCol\r
- * @param groupVal\r
- * @return\r
- */\r
- public Cursor fetchAllInGroups( String groupCol, String groupVal ) {\r
- return mDb.query(DATABASE_TABLE, \r
- /* columns */new String[] {\r
- ID,\r
- NAME,\r
- DIAMETER ,\r
- TOTAL_IMPULSE,\r
- AVG_THRUST ,\r
- MAX_THRUST ,\r
- BURN_TIME ,\r
- LENGTH,\r
- PROP_MASS,\r
- TOT_MASS,\r
- CASE_INFO,\r
- IMPULSE_CLASS,\r
- MANUFACTURER\r
- },\r
- /* selection */groupCol + "=?",\r
- /* selection args*/new String[] {groupVal},\r
- /* groupby */null,\r
- /* having*/null,\r
- /* orderby*/ NAME );\r
-\r
- }\r
-\r
- /**\r
- * Fetch the groups based on groupCol\r
- * @param groupCol\r
- * @return\r
- */\r
- public Cursor fetchGroups( String groupCol ) {\r
- return mDb.query(true, DATABASE_TABLE, \r
- /* columns */new String[] {\r
- groupCol\r
- },\r
- /* selection */null,\r
- /* selection args*/null,\r
- /* groupby */null,\r
- /* having*/null,\r
- /* orderby*/null,\r
- /* limit*/ null);\r
-\r
- }\r
-\r
- /**\r
- * Return a Cursor over the list of all motors\r
- * \r
- * @return Cursor over all notes\r
- */\r
- public Cursor fetchAllMotors() {\r
-\r
- return mDb.query(DATABASE_TABLE, \r
- /* columns */new String[] {\r
- ID,\r
- NAME,\r
- DIAMETER ,\r
- TOTAL_IMPULSE,\r
- AVG_THRUST ,\r
- MAX_THRUST ,\r
- BURN_TIME ,\r
- LENGTH,\r
- PROP_MASS,\r
- TOT_MASS,\r
- CASE_INFO,\r
- IMPULSE_CLASS,\r
- MANUFACTURER\r
- },\r
- /* selection */null,\r
- /* selection args*/null,\r
- /* groupby */null,\r
- /* having*/null,\r
- /* orderby*/null);\r
- }\r
-\r
- public Motor fetchMotor(Long id ) throws SQLException {\r
- Cursor mCursor = mDb.query(DATABASE_TABLE, \r
- /* columns */new String[] {\r
- ID,\r
- NAME ,\r
- DIAMETER ,\r
- TOTAL_IMPULSE ,\r
- AVG_THRUST ,\r
- MAX_THRUST ,\r
- BURN_TIME ,\r
- LENGTH,\r
- PROP_MASS,\r
- TOT_MASS,\r
- CASE_INFO,\r
- IMPULSE_CLASS,\r
- MANUFACTURER,\r
- BURNDATA\r
- },\r
- /* selection */ID + "="+id,\r
- /* selection args*/null,\r
- /* groupby */null,\r
- /* having*/null,\r
- /* orderby*/null);\r
- if ( mCursor == null ) {\r
- return null;\r
- }\r
- try {\r
- if (mCursor.getCount() == 0) {\r
- return null;\r
- }\r
- mCursor.moveToFirst();\r
- Motor mi = new Motor();\r
- mi.setMotor_id(mCursor.getLong(mCursor.getColumnIndex(ID)));\r
- mi.setName(mCursor.getString(mCursor.getColumnIndex(NAME)));\r
- mi.setDiameter(mCursor.getLong(mCursor.getColumnIndex(DIAMETER)));\r
- mi.setTotalImpulse(mCursor.getFloat(mCursor.getColumnIndex(TOTAL_IMPULSE)));\r
- mi.setAvgThrust(mCursor.getFloat(mCursor.getColumnIndex(AVG_THRUST)));\r
- mi.setMaxThrust(mCursor.getFloat(mCursor.getColumnIndex(MAX_THRUST)));\r
- mi.setBurnTime(mCursor.getFloat(mCursor.getColumnIndex(BURN_TIME)));\r
- mi.setLength(mCursor.getFloat(mCursor.getColumnIndex(LENGTH)));\r
- mi.setPropMass(mCursor.getDouble(mCursor.getColumnIndex(PROP_MASS)));\r
- mi.setCaseInfo(mCursor.getString(mCursor.getColumnIndex(CASE_INFO)));\r
- mi.setTotMass(mCursor.getDouble(mCursor.getColumnIndex(TOT_MASS)));\r
- mi.setManufacturer(mCursor.getString(mCursor.getColumnIndex(MANUFACTURER)));\r
- mi.setImpulseClass(mCursor.getString(mCursor.getColumnIndex(IMPULSE_CLASS)));\r
-\r
- {\r
- // Deserialize burndata column\r
- byte[] serObj = mCursor.getBlob(mCursor.getColumnIndex(BURNDATA));\r
- Vector<Double> burndata = null;\r
- if (serObj != null ) {\r
- try {\r
- ObjectInputStream is = new ObjectInputStream( new ByteArrayInputStream(serObj));\r
- burndata = (Vector<Double>) is.readObject();\r
- }\r
- catch (Exception ex) {\r
- Log.d(TAG,"cannot deserialize burndata");\r
- }\r
- }\r
- mi.setBurndata(burndata);\r
- }\r
- return mi;\r
- }\r
- finally {\r
- mCursor.close();\r
- }\r
-\r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import java.util.Vector;\r
-\r
-import net.sf.openrocket.R;\r
-import android.app.Activity;\r
-import android.graphics.Color;\r
-import android.graphics.PointF;\r
-import android.os.Bundle;\r
-import android.support.v4.app.Fragment;\r
-import android.util.Log;\r
-import android.view.LayoutInflater;\r
-import android.view.MotionEvent;\r
-import android.view.ScaleGestureDetector;\r
-import android.view.View;\r
-import android.view.View.OnTouchListener;\r
-import android.view.ViewGroup;\r
-\r
-import com.androidplot.xy.BoundaryMode;\r
-import com.androidplot.xy.LineAndPointFormatter;\r
-import com.androidplot.xy.LineAndPointRenderer;\r
-import com.androidplot.xy.SimpleXYSeries;\r
-import com.androidplot.xy.XYPlot;\r
-import com.androidplot.xy.YValueMarker;\r
-\r
-public class BurnPlotFragment extends Fragment implements OnTouchListener {\r
-\r
- private final static String TAG = "BurnPlotFragment";\r
-\r
- private XYPlot mySimpleXYPlot;\r
- private SimpleXYSeries mySeries;\r
- private PointF minXY;\r
- private PointF maxXY;\r
- \r
- private float absMinX;\r
- private float absMaxX;\r
- private float minNoError;\r
- private float maxNoError;\r
-\r
- private ScaleGestureDetector mScaleDetector;\r
- private float mScaleFactor = 1.f;\r
-\r
- public static BurnPlotFragment initializeBurnPlotHelper( Motor motor ) {\r
- BurnPlotFragment h = new BurnPlotFragment();\r
-\r
- Bundle args = new Bundle();\r
- args.putSerializable("Motor", motor);\r
- h.setArguments(args);\r
- return h;\r
- }\r
-\r
- @Override\r
- public void onAttach(Activity activity) {\r
- super.onAttach(activity);\r
- Log.d(TAG,"onAttach");\r
- }\r
-\r
- @Override\r
- public void onCreate(Bundle savedInstanceState) {\r
- Log.d(TAG,"onCreate");\r
- super.onCreate(savedInstanceState);\r
- }\r
-\r
- @Override\r
- public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
- Bundle savedInstanceState) {\r
- Log.d(TAG,"onCreateView");\r
- View v = inflater.inflate(R.layout.motor_burn, container, false);\r
- mySimpleXYPlot = (XYPlot) v.findViewById(R.id.xyplot);\r
- mySimpleXYPlot.setOnTouchListener(this);\r
- mScaleDetector = new ScaleGestureDetector(v.getContext(), new ScaleListener());\r
- // Motor motor = getMotor();\r
- // init(motor);\r
- return v;\r
- }\r
-\r
- void init( Motor motor ) {\r
-\r
- mySimpleXYPlot.setUserDomainOrigin(0);\r
- mySimpleXYPlot.setUserRangeOrigin(0);\r
- mySimpleXYPlot.setRangeLabel("impuse (n)");\r
- mySimpleXYPlot.setDomainLabel("time (s)");\r
- mySimpleXYPlot.addMarker(new YValueMarker(motor.getAvgThrust(),"average" ));\r
- mySimpleXYPlot.disableAllMarkup();\r
-\r
- Vector<Double> data = null;\r
- try {\r
- data = motor.getBurndata();\r
- } catch ( Exception ex ) {\r
- }\r
- if ( data == null || data.size() == 0 ) {\r
- data = new Vector<Double>();\r
- data.add(0.0);\r
- data.add(0.0);\r
- data.add(1.0);\r
- data.add(1.0);\r
- }\r
- Log.d("plot","data = " + data.toString());\r
-\r
- mySeries = new SimpleXYSeries(data, SimpleXYSeries.ArrayFormat.XY_VALS_INTERLEAVED,motor.getName());\r
-\r
- mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class,\r
- new LineAndPointFormatter(Color.rgb(0, 255, 0), Color.rgb(200, 0, 0), null));\r
-\r
- //Set of internal variables for keeping track of the boundaries\r
- mySimpleXYPlot.calculateMinMaxVals();\r
- \r
- mySimpleXYPlot.redraw();\r
-\r
- minXY=new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),mySimpleXYPlot.getCalculatedMinY().floatValue());\r
- maxXY=new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),mySimpleXYPlot.getCalculatedMaxY().floatValue());\r
-\r
- absMinX = minXY.x;\r
- absMaxX = maxXY.x;\r
- \r
- minNoError = Math.round(mySeries.getX(1).floatValue() +2);\r
- maxNoError = Math.round(mySeries.getX(mySeries.size() -1).floatValue()) - 2.0f;\r
- }\r
-\r
- private float mPosX;\r
- private float mPosY;\r
-\r
- private float mLastTouchX;\r
- private float mLastTouchY;\r
-\r
- private int mActivePointerId = -1;\r
-\r
- @Override\r
- public boolean onTouch(View arg0, MotionEvent event) {\r
- mScaleDetector.onTouchEvent(event);\r
-\r
- final int action = event.getAction();\r
- switch ( action & MotionEvent.ACTION_MASK ) {\r
- case MotionEvent.ACTION_DOWN: {\r
- final float x = event.getX();\r
- final float y = event.getY();\r
-\r
- mLastTouchX = x;\r
- mLastTouchY = y;\r
-\r
- mActivePointerId = event.getPointerId(0);\r
- break;\r
- }\r
- \r
- case MotionEvent.ACTION_MOVE: {\r
- final int pointerIndex = event.findPointerIndex(mActivePointerId);\r
- final float x = event.getX(pointerIndex);\r
- final float y = event.getY(pointerIndex);\r
-\r
- if (!mScaleDetector.isInProgress()) {\r
- final float dx = x - mLastTouchX;\r
- final float dy = y - mLastTouchY;\r
- \r
- mPosX += dx;\r
- mPosY += dy;\r
- scroll(dx);\r
- // do scroll.\r
- \r
- }\r
- mLastTouchX = x;\r
- mLastTouchY = y;\r
- \r
- break;\r
- }\r
- \r
- case MotionEvent.ACTION_UP: {\r
- mActivePointerId = -1;\r
- break;\r
- }\r
- \r
- case MotionEvent.ACTION_CANCEL: {\r
- mActivePointerId = -1;\r
- break;\r
- }\r
- \r
- case MotionEvent.ACTION_POINTER_UP: {\r
- final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;\r
- final int pointerId = event.getPointerId(pointerIndex);\r
- if (pointerId == mActivePointerId) {\r
- // This was our active pointer going up. choose a new active pointer and adjust accordingly.\r
- final int newPointerIndex = pointerIndex ==0 ? 1:0;\r
- mLastTouchX = event.getX(newPointerIndex);\r
- mLastTouchY = event.getY(newPointerIndex);\r
- mActivePointerId = event.getPointerId(newPointerIndex);\r
- }\r
- break;\r
- }\r
- } \r
- return true;\r
- }\r
-\r
- private void zoom(float scale) {\r
- Log.d(TAG,"zoom by " + scale);\r
- float domainSpan = absMaxX - absMinX;\r
- Log.d(TAG,"domainSpan = " + domainSpan);\r
- float domainMidPoint = absMaxX - domainSpan / 2.0f;\r
- Log.d(TAG,"domainMidPoint = " + domainMidPoint);\r
- float offset = domainSpan / scale;\r
- Log.d(TAG,"offset " + offset);\r
- minXY.x=domainMidPoint- offset;\r
- Log.d(TAG,"min X " + minXY.x);\r
- maxXY.x=domainMidPoint+offset;\r
- Log.d(TAG,"max X " + maxXY.x);\r
- checkBoundaries();\r
- mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
- mySimpleXYPlot.redraw();\r
- }\r
-\r
- private void scroll(float pan) {\r
- float domainSpan = maxXY.x - minXY.x;\r
- float step = domainSpan / mySimpleXYPlot.getWidth();\r
- float offset = pan * step;\r
- minXY.x+= offset;\r
- maxXY.x+= offset;\r
- checkBoundaries();\r
- mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);\r
- mySimpleXYPlot.redraw();\r
- }\r
-\r
- private void checkBoundaries() {\r
- \r
- if ( minXY.x < absMinX) \r
- minXY.x = absMinX;\r
-// else if ( minXY.x > maxNoError )\r
-// minXY.x = maxNoError;\r
- \r
- if ( maxXY.x > absMaxX)\r
- maxXY.x = absMaxX;\r
-// else if ( maxXY.x < minNoError)\r
-// maxXY.x = minNoError;\r
- }\r
- private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {\r
- @Override\r
- public boolean onScale( ScaleGestureDetector detector ) {\r
- mScaleFactor *= detector.getScaleFactor();\r
-\r
- mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 5.0f));\r
- zoom(mScaleFactor);\r
- return true;\r
- }\r
- }\r
-}\r
-\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import java.io.Serializable;\r
-import java.util.Vector;\r
-\r
-public class Motor implements Serializable {\r
- \r
- private Long motor_id;\r
- private String name;\r
- private String impulseClass;\r
- private String manufacturer;\r
- private Long diameter;\r
- private String caseInfo;\r
- private Float avgThrust;\r
- private Float maxThrust;\r
- private Float totalImpulse;\r
- private Float burnTime;\r
- private Float length;\r
- private Double propMass;\r
- private Double totMass;\r
- private Vector<Double> burndata;\r
- public Long getMotor_id() {\r
- return motor_id;\r
- }\r
- public void setMotor_id(Long motor_id) {\r
- this.motor_id = motor_id;\r
- }\r
- public String getName() {\r
- return name;\r
- }\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
- public String getImpulseClass() {\r
- return impulseClass;\r
- }\r
- public void setImpulseClass(String impulseClass) {\r
- this.impulseClass = impulseClass;\r
- }\r
- public String getManufacturer() {\r
- return manufacturer;\r
- }\r
- public void setManufacturer(String manufacturer) {\r
- this.manufacturer = manufacturer;\r
- }\r
- public Long getDiameter() {\r
- return diameter;\r
- }\r
- public void setDiameter(Long diameter) {\r
- this.diameter = diameter;\r
- }\r
- public String getCaseInfo() {\r
- return caseInfo;\r
- }\r
- public void setCaseInfo(String caseInfo) {\r
- this.caseInfo = caseInfo;\r
- }\r
- public Float getAvgThrust() {\r
- return avgThrust;\r
- }\r
- public void setAvgThrust(Float avgThrust) {\r
- this.avgThrust = avgThrust;\r
- }\r
- public Float getMaxThrust() {\r
- return maxThrust;\r
- }\r
- public void setMaxThrust(Float maxThrust) {\r
- this.maxThrust = maxThrust;\r
- }\r
- public Float getTotalImpulse() {\r
- return totalImpulse;\r
- }\r
- public void setTotalImpulse(Float totalImpulse) {\r
- this.totalImpulse = totalImpulse;\r
- }\r
- public Float getBurnTime() {\r
- return burnTime;\r
- }\r
- public void setBurnTime(Float burnTime) {\r
- this.burnTime = burnTime;\r
- }\r
- public Float getLength() {\r
- return length;\r
- }\r
- public void setLength(Float length) {\r
- this.length = length;\r
- }\r
- public Double getPropMass() {\r
- return propMass;\r
- }\r
- public void setPropMass(Double propMass) {\r
- this.propMass = propMass;\r
- }\r
- public Double getTotMass() {\r
- return totMass;\r
- }\r
- public void setTotMass(Double totMass) {\r
- this.totMass = totMass;\r
- }\r
- public Vector<Double> getBurndata() {\r
- return burndata;\r
- }\r
- public void setBurndata(Vector<Double> burndata) {\r
- this.burndata = burndata;\r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import net.sf.openrocket.R;\r
-import android.content.Intent;\r
-import android.os.Bundle;\r
-import android.support.v4.app.FragmentActivity;\r
-import android.util.Log;\r
-import android.view.Menu;\r
-import android.view.MenuInflater;\r
-import android.view.MenuItem;\r
-import android.widget.ImageView;\r
-import android.widget.SlidingDrawer;\r
-\r
-public class MotorDetails extends FragmentActivity\r
-implements SlidingDrawer.OnDrawerCloseListener, SlidingDrawer.OnDrawerOpenListener {\r
-\r
- private final static String TAG = "MotorDetails";\r
- \r
- private SlidingDrawer slidingDrawer;\r
- private ImageView handle;\r
- \r
- private Motor motor;\r
- \r
- @Override\r
- public void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
- Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState));\r
- setContentView(R.layout.motor_detail);\r
-\r
- Intent i = getIntent();\r
- motor = (Motor) i.getSerializableExtra("Motor");\r
- \r
- BurnPlotFragment burnPlot = (BurnPlotFragment) getSupportFragmentManager().findFragmentById(R.id.burnPlotFragment);\r
- burnPlot.init(motor);\r
- \r
- MotorDetailsFragment motorDetails = (MotorDetailsFragment) getSupportFragmentManager().findFragmentById(R.id.motorDetailForm);\r
- motorDetails.init(motor);\r
- \r
- slidingDrawer = (SlidingDrawer) findViewById(R.id.drawer);\r
- \r
- slidingDrawer.setOnDrawerOpenListener(this);\r
- slidingDrawer.setOnDrawerCloseListener(this);\r
- \r
- handle = (ImageView) findViewById(R.id.handle);\r
- \r
- }\r
- \r
- @Override\r
- public void onDrawerOpened() {\r
- handle.setImageResource(R.drawable.arrow_down_float);\r
- }\r
- \r
- @Override\r
- public void onDrawerClosed() {\r
- handle.setImageResource(R.drawable.arrow_up_float);\r
- }\r
-\r
- @Override\r
- public boolean onCreateOptionsMenu(Menu menu) {\r
- MenuInflater inflater = getMenuInflater();\r
- inflater.inflate(R.menu.motor_details_option_menu, menu);\r
- return true;\r
- }\r
-\r
- @Override\r
- public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
- switch(item.getItemId()) {\r
- case R.id.save:\r
- // Extract form data to Motor.\r
- // Save motor.\r
- return true;\r
- }\r
- return super.onMenuItemSelected(featureId, item);\r
- }\r
-\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import net.sf.openrocket.R;\r
-import android.os.Bundle;\r
-import android.support.v4.app.Fragment;\r
-import android.view.LayoutInflater;\r
-import android.view.View;\r
-import android.view.ViewGroup;\r
-import android.widget.EditText;\r
-\r
-public class MotorDetailsFragment extends Fragment {\r
-\r
- EditText manuField;\r
- EditText nameField;\r
- EditText caseField;\r
- EditText impulseClassField;\r
- EditText diameterField;\r
- EditText lengthField;\r
- \r
- @Override\r
- public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
- Bundle savedInstanceState) {\r
- View v = inflater.inflate(R.layout.motor_detail_form, container, false);\r
- manuField = (EditText) v.findViewById(R.id.motorDetailsManufacturer);\r
- nameField = (EditText) v.findViewById(R.id.motorDetailsName);\r
- caseField = (EditText) v.findViewById(R.id.motorDetailsCaseInfo);\r
- impulseClassField = (EditText) v.findViewById(R.id.motorDetailsImpuseClass);\r
- diameterField = (EditText) v.findViewById(R.id.motorDetailsDiameter);\r
- lengthField = (EditText) v.findViewById(R.id.motorDetailsLength);\r
- return v;\r
- }\r
-\r
- public void init( Motor m ) {\r
- manuField.setText( m.getManufacturer());\r
- nameField.setText( m.getName() );\r
- caseField.setText( m.getCaseInfo());\r
- impulseClassField.setText( m.getImpulseClass());\r
- diameterField.setText( m.getDiameter().toString() );\r
- lengthField.setText( m.getLength().toString() );\r
- \r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.android.PreferencesActivity;\r
-import net.sf.openrocket.android.db.DbAdapter;\r
-import net.sf.openrocket.android.db.MotorDao;\r
-import net.sf.openrocket.android.thrustcurve.TCQueryActivity;\r
-import android.content.Context;\r
-import android.content.Intent;\r
-import android.content.SharedPreferences;\r
-import android.content.res.Resources;\r
-import android.database.Cursor;\r
-import android.os.Bundle;\r
-import android.preference.PreferenceManager;\r
-import android.util.Log;\r
-import android.view.ContextMenu;\r
-import android.view.ContextMenu.ContextMenuInfo;\r
-import android.view.Menu;\r
-import android.view.MenuInflater;\r
-import android.view.MenuItem;\r
-import android.view.View;\r
-import android.widget.CursorTreeAdapter;\r
-import android.widget.ExpandableListView;\r
-import android.widget.SimpleCursorTreeAdapter;\r
-\r
-\r
-public class MotorHierarchicalBrowser\r
-extends PersistentExpandableListActivity\r
-implements SharedPreferences.OnSharedPreferenceChangeListener\r
-{\r
- private static final String TAG = "MotorHierarchicalBrowser";\r
-\r
- private static final int ACTIVITY_DOWNLOAD=0;\r
-\r
- private static final int CONTEXTMENU_DELETE = Menu.FIRST+1;\r
-\r
- private String groupColumnPreferenceKey;\r
- private String groupColumn = MotorDao.CASE_INFO;\r
-\r
- private static final String[] groupColumns = new String[] {\r
- MotorDao.CASE_INFO,\r
- MotorDao.DIAMETER,\r
- MotorDao.IMPULSE_CLASS,\r
- MotorDao.MANUFACTURER\r
- };\r
-\r
- private CursorTreeAdapter mAdapter;\r
-\r
- private DbAdapter mDbHelper;\r
-\r
- public class MotorHierarchicalListAdapter extends SimpleCursorTreeAdapter\r
- {\r
-\r
- // Note that the constructor does not take a Cursor. This is done to avoid querying the \r
- // database on the main thread.\r
- public MotorHierarchicalListAdapter(Context context, Cursor cursor, int groupLayout,\r
- int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom,\r
- int[] childrenTo) {\r
-\r
- super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom,\r
- childrenTo);\r
- }\r
-\r
- @Override\r
- protected Cursor getChildrenCursor(Cursor arg0) {\r
- Log.d(TAG,"getChildrenCursor");\r
- String group = arg0.getString(arg0.getColumnIndex(groupColumn));\r
- Log.d(TAG," for: "+ groupColumn + " = " + group);\r
- Cursor c = mDbHelper.getMotorDao().fetchAllInGroups(groupColumn,group);\r
- Log.d(TAG," got cursor");\r
- startManagingCursor(c);\r
- return c;\r
- }\r
-\r
- @Override\r
- public long getGroupId(int groupPosition) {\r
- return groupPosition;\r
- }\r
-\r
- }\r
-\r
- @Override\r
- public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) {\r
- if ( groupColumnPreferenceKey.equals(arg1) ) {\r
- setGroupColumnFromPreferences(arg0);\r
- refreshData();\r
- }\r
- }\r
-\r
- @Override\r
- public void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
-\r
- mDbHelper = new DbAdapter(this);\r
- mDbHelper.open();\r
-\r
- Resources resources = this.getResources();\r
- groupColumnPreferenceKey = resources.getString(R.string.PreferenceMotorBrowserGroupingOption);\r
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r
-\r
- setGroupColumnFromPreferences(pref);\r
-\r
- pref.registerOnSharedPreferenceChangeListener(this);\r
-\r
- refreshData();\r
-\r
- registerForContextMenu(getExpandableListView());\r
-\r
- }\r
-\r
- @Override\r
- public boolean onCreateOptionsMenu(Menu menu) {\r
- MenuInflater inflater = getMenuInflater();\r
- inflater.inflate(R.menu.motor_browser_option_menu, menu);\r
- return true;\r
- }\r
-\r
- @Override\r
- public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
- Log.d(TAG,"onMenuItemSelected" + item.getItemId());\r
- switch(item.getItemId()) {\r
- case R.id.download_from_thrustcurve_menu_option:\r
- tcDownload();\r
- return true;\r
- case R.id.preference_menu_option:\r
- Intent intent = new Intent().setClass(this, PreferencesActivity.class);\r
- this.startActivity(intent);\r
- return true;\r
- }\r
- return super.onMenuItemSelected(featureId, item);\r
- }\r
-\r
- @Override\r
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {\r
- Log.d(TAG,"onCreateContextMenu " + menuInfo);\r
- Log.d(TAG, "v.getId() = " + v.getId());\r
- Log.d(TAG, "motorListView = " + R.id.motorListView);\r
- // if (v.getId() == R.id.motorListView) {\r
- ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;\r
- menu.setHeaderTitle("context menu");\r
- menu.add(Menu.NONE,CONTEXTMENU_DELETE,CONTEXTMENU_DELETE,"Delete");\r
- // }\r
- super.onCreateContextMenu(menu, v, menuInfo);\r
- }\r
-\r
- @Override\r
- public boolean onContextItemSelected(MenuItem item) {\r
- ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo();\r
- long motorId = info.id;\r
- Log.d(TAG,"ContextMenu: " + motorId);\r
- switch(item.getItemId()) {\r
- case CONTEXTMENU_DELETE:\r
- mDbHelper.getMotorDao().deleteMotor(motorId);\r
- refreshData();\r
- return true;\r
- }\r
- return super.onContextItemSelected(item);\r
- }\r
-\r
- @Override\r
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {\r
- super.onActivityResult(requestCode, resultCode, intent);\r
- refreshData();\r
- }\r
-\r
-\r
- @Override\r
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {\r
- super.onChildClick(parent, v, groupPosition, childPosition, id);\r
- Motor m = mDbHelper.getMotorDao().fetchMotor(id);\r
- //Intent i = new Intent(this, BurnPlotActivity.class);\r
- Intent i = new Intent(this,MotorDetails.class);\r
- i.putExtra("Motor", m);\r
- startActivity(i);\r
- return true;\r
- }\r
-\r
- @Override\r
- protected void onDestroy() {\r
- super.onDestroy();\r
- \r
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r
- pref.unregisterOnSharedPreferenceChangeListener(this);\r
-\r
- // Null out the group cursor. This will cause the group cursor and all of the child cursors\r
- // to be closed.\r
- mAdapter.changeCursor(null);\r
- mAdapter = null;\r
-\r
- mDbHelper.close();\r
- }\r
-\r
- private void tcDownload() {\r
- Intent i = new Intent(this, TCQueryActivity.class);\r
- startActivityForResult(i, ACTIVITY_DOWNLOAD);\r
- }\r
-\r
- private void setGroupColumnFromPreferences( SharedPreferences prefs ) {\r
- String indexStr = prefs.getString(groupColumnPreferenceKey, "1");\r
- int index;\r
- //Dirty hack, you can't use integer-array in ListPreferences\r
- try {\r
- index = Integer.parseInt(indexStr);\r
- } catch ( Exception e ) {\r
- index = 1;\r
- }\r
- if ( index >= groupColumns.length ) {\r
- index = 1;\r
- }\r
- groupColumn = groupColumns[index];\r
-\r
- }\r
- private void refreshData() {\r
- if (mAdapter != null ) {\r
- mAdapter.changeCursor(null);\r
- }\r
- Cursor motorCursor = mDbHelper.getMotorDao().fetchGroups(groupColumn);\r
- startManagingCursor(motorCursor);\r
- // Set up our adapter\r
- mAdapter = new MotorHierarchicalListAdapter( \r
- this,\r
- motorCursor,\r
- R.layout.motor_list_group,\r
- R.layout.motor_list_child,\r
- new String[] { groupColumn }, // Name for group layouts\r
- new int[] { R.id.motorGroup },\r
- new String[] { MotorDao.MANUFACTURER, MotorDao.NAME, MotorDao.TOTAL_IMPULSE }, // Number for child layouts\r
- new int[] { R.id.motorChildManu, R.id.motorChildName, R.id.motorChildImpulse });\r
- setListAdapter(mAdapter);\r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.motor;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import android.app.ExpandableListActivity;\r
-import android.os.Bundle;\r
-import android.widget.ExpandableListAdapter;\r
-import android.widget.ExpandableListView;\r
-\r
-public class PersistentExpandableListActivity extends ExpandableListActivity {\r
- private long[] expandedIds;\r
-\r
- @Override\r
- protected void onStart() {\r
- super.onStart();\r
- if (this.expandedIds != null) {\r
- restoreExpandedState(expandedIds);\r
- }\r
- }\r
-\r
- @Override\r
- protected void onStop() {\r
- super.onStop();\r
- expandedIds = getExpandedIds();\r
- }\r
-\r
- @Override\r
- protected void onSaveInstanceState(Bundle outState) {\r
- super.onSaveInstanceState(outState);\r
- this.expandedIds = getExpandedIds();\r
- outState.putLongArray("ExpandedIds", this.expandedIds);\r
- }\r
-\r
- @Override\r
- protected void onRestoreInstanceState(Bundle state) {\r
- super.onRestoreInstanceState(state);\r
- long[] expandedIds = state.getLongArray("ExpandedIds");\r
- if (expandedIds != null) {\r
- restoreExpandedState(expandedIds);\r
- }\r
- }\r
-\r
- private long[] getExpandedIds() {\r
- ExpandableListView list = getExpandableListView();\r
- ExpandableListAdapter adapter = getExpandableListAdapter();\r
- if (adapter != null) {\r
- int length = adapter.getGroupCount();\r
- ArrayList<Long> expandedIds = new ArrayList<Long>();\r
- for(int i=0; i < length; i++) {\r
- if(list.isGroupExpanded(i)) {\r
- expandedIds.add(adapter.getGroupId(i));\r
- }\r
- }\r
- return toLongArray(expandedIds);\r
- } else {\r
- return null;\r
- }\r
- }\r
-\r
- private void restoreExpandedState(long[] expandedIds) {\r
- this.expandedIds = expandedIds;\r
- if (expandedIds != null) {\r
- ExpandableListView list = getExpandableListView();\r
- ExpandableListAdapter adapter = getExpandableListAdapter();\r
- if (adapter != null) {\r
- for (int i=0; i<adapter.getGroupCount(); i++) {\r
- long id = adapter.getGroupId(i);\r
- if (inArray(expandedIds, id)) list.expandGroup(i);\r
- }\r
- }\r
- }\r
- }\r
-\r
- private static boolean inArray(long[] array, long element) {\r
- for (long l : array) {\r
- if (l == element) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- private static long[] toLongArray(List<Long> list) {\r
- long[] ret = new long[list.size()];\r
- int i = 0;\r
- for (Long e : list) \r
- ret[i++] = e.longValue();\r
- return ret;\r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.rocket;\r
-\r
-import java.io.File;\r
-\r
-import net.sf.openrocket.document.OpenRocketDocument;\r
-import net.sf.openrocket.file.RocketLoadException;\r
-import net.sf.openrocket.file.openrocket.OpenRocketLoader;\r
-import android.os.AsyncTask;\r
-import android.util.Log;\r
-\r
-public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketDocument> {\r
-\r
- private final static String TAG = "OpenRocketLoaderTask";\r
- \r
- /* (non-Javadoc)\r
- * @see android.os.AsyncTask#doInBackground(Params[])\r
- */\r
- @Override\r
- protected OpenRocketDocument doInBackground(File... arg0) {\r
- Log.d(TAG,"doInBackgroud");\r
- \r
- OpenRocketLoader rocketLoader = new OpenRocketLoader();\r
- try {\r
- OpenRocketDocument rocket = rocketLoader.load(arg0[0]);\r
- return rocket;\r
- }\r
- catch( RocketLoadException ex ) {\r
- Log.e(TAG, "doInBackground rocketLaoder.load threw", ex);\r
- }\r
- return null;\r
- \r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.rocket;\r
-\r
-\r
-import java.io.File;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.android.Application;\r
-import net.sf.openrocket.android.PreferencesActivity;\r
-import net.sf.openrocket.android.motor.MotorHierarchicalBrowser;\r
-import net.sf.openrocket.android.simulation.SimulationViewer;\r
-import net.sf.openrocket.document.OpenRocketDocument;\r
-import net.sf.openrocket.document.Simulation;\r
-import net.sf.openrocket.rocketcomponent.Rocket;\r
-import net.sf.openrocket.rocketcomponent.RocketComponent;\r
-import net.sf.openrocket.rocketcomponent.RocketUtils;\r
-import net.sf.openrocket.unit.Unit;\r
-import net.sf.openrocket.unit.UnitGroup;\r
-import net.sf.openrocket.util.Coordinate;\r
-import android.app.Activity;\r
-import android.app.ProgressDialog;\r
-import android.content.Intent;\r
-import android.content.SharedPreferences;\r
-import android.net.Uri;\r
-import android.os.Bundle;\r
-import android.preference.PreferenceManager;\r
-import android.util.Log;\r
-import android.view.LayoutInflater;\r
-import android.view.Menu;\r
-import android.view.MenuInflater;\r
-import android.view.MenuItem;\r
-import android.view.View;\r
-import android.view.ViewGroup;\r
-import android.widget.AdapterView;\r
-import android.widget.AdapterView.OnItemClickListener;\r
-import android.widget.ArrayAdapter;\r
-import android.widget.ListView;\r
-import android.widget.TabHost;\r
-import android.widget.TextView;\r
-\r
-public class OpenRocketViewer extends Activity\r
-implements SharedPreferences.OnSharedPreferenceChangeListener\r
-{\r
-\r
- private static final String TAG = "OpenRocketViewer";\r
-\r
- private ProgressDialog progress;\r
-\r
- private ListView componentList;\r
- private ListView simulationList;\r
-\r
- private Application app;\r
-\r
- private final static int PICK_ORK_FILE_RESULT = 1;\r
-\r
- /* (non-Javadoc)\r
- * @see android.app.Activity#onCreate(android.os.Bundle)\r
- */\r
- @Override\r
- protected void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
-\r
- Log.d(TAG,"In onCreate");\r
-\r
- app = (Application) this.getApplication();\r
-\r
- setContentView(R.layout.openrocketviewer);\r
-\r
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
- prefs.registerOnSharedPreferenceChangeListener(this);\r
-\r
- TabHost tabs=(TabHost)findViewById(R.id.openrocketviewerTabHost);\r
-\r
- tabs.setup();\r
-\r
- TabHost.TabSpec spec=tabs.newTabSpec("tag1");\r
-\r
- spec.setContent(R.id.openrocketviewerOverview);\r
- spec.setIndicator("Overview");\r
- tabs.addTab(spec);\r
-\r
- spec=tabs.newTabSpec("tag2");\r
- spec.setContent(R.id.openrocketviewerComponentList);\r
- spec.setIndicator("Components");\r
- tabs.addTab(spec); \r
-\r
- spec=tabs.newTabSpec("tag3");\r
- spec.setContent(R.id.openrocketviewerSimulationList);\r
- spec.setIndicator("Simulations");\r
- tabs.addTab(spec); \r
-\r
- componentList = (ListView) findViewById(R.id.openrocketviewerComponentList);\r
- simulationList = (ListView) findViewById(R.id.openrocketviewerSimulationList);\r
-\r
- Intent i = getIntent();\r
- Uri file = i.getData();\r
-\r
- if ( file == null ) {\r
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\r
- intent.setType("file/*");\r
- startActivityForResult(intent,PICK_ORK_FILE_RESULT);\r
-\r
- } else {\r
- loadOrkFile(file);\r
- }\r
- }\r
-\r
- @Override\r
- protected void onDestroy() {\r
- if ( progress != null ) {\r
- if ( progress.isShowing() ) {\r
- progress.dismiss();\r
- }\r
- progress = null;\r
- }\r
- super.onDestroy();\r
- }\r
-\r
- @Override\r
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {\r
- // TODO Auto-generated method stub\r
- switch(requestCode){\r
- case PICK_ORK_FILE_RESULT:\r
- if(resultCode==RESULT_OK){\r
- Uri file = data.getData();\r
- loadOrkFile(file);\r
- }\r
- break;\r
- }\r
- }\r
- \r
- private void loadOrkFile( Uri file ) {\r
- Log.d(TAG,"Use ork file: " + file);\r
- String path = file.getPath();\r
- File orkFile = new File(path);\r
- progress = ProgressDialog.show(this, "Loading file", "");\r
-\r
- final OpenRocketLoaderTask task = new OpenRocketLoaderTask() {\r
-\r
- /* (non-Javadoc)\r
- * @see android.os.AsyncTask#onPostExecute(java.lang.Object)\r
- */\r
- @Override\r
- protected void onPostExecute(OpenRocketDocument result) {\r
- super.onPostExecute(result);\r
- app.setRocketDocument( result );\r
- updateContents();\r
- }\r
-\r
- };\r
-\r
- task.execute(orkFile);\r
-\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String)\r
- */\r
- @Override\r
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r
- // just in case the user changed the units, we redraw.\r
- PreferencesActivity.initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this));\r
- updateContents();\r
- }\r
-\r
- private void updateContents() {\r
-\r
- OpenRocketDocument rocketDocument = app.getRocketDocument();\r
- Rocket rocket = rocketDocument.getRocket();\r
- \r
- setTitle(rocket.getName());\r
- \r
- Unit LengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();\r
- Unit MassUnit = UnitGroup.UNITS_MASS.getDefaultUnit();\r
- \r
- Coordinate cg = RocketUtils.getCG(rocket);\r
- double length = RocketUtils.getLength(rocket);\r
- ((TextView) findViewById(R.id.openrocketviewerRocketName)).setText( rocket.getName());\r
- ((TextView)findViewById(R.id.openrocketviewerDesigner)).setText(rocket.getDesigner());\r
- ((TextView)findViewById(R.id.openrocketviewerCG)).setText(LengthUnit.toStringUnit(cg.x) );\r
- ((TextView)findViewById(R.id.openrocketviewerLength)).setText(LengthUnit.toStringUnit(length));\r
- ((TextView)findViewById(R.id.openrocketviewerMass)).setText(MassUnit.toStringUnit(cg.weight));\r
- ((TextView)findViewById(R.id.openrocketviewerStageCount)).setText(String.valueOf(rocket.getStageCount()));\r
- ((TextView)findViewById(R.id.openrocketviewerComment)).setText(rocket.getComment());\r
-\r
- ArrayAdapter<Simulation> sims = new ArrayAdapter<Simulation>(this,android.R.layout.simple_list_item_2,rocketDocument.getSimulations()) {\r
-\r
- @Override\r
- public View getView(int position, View convertView, ViewGroup parent) {\r
- View v = convertView;\r
- if ( v == null ) {\r
- LayoutInflater li = getLayoutInflater();\r
- v = li.inflate(android.R.layout.simple_list_item_2,null);\r
- }\r
- Simulation sim = this.getItem(position);\r
- ((TextView)v.findViewById(android.R.id.text1)).setText( sim.getName() );\r
- ((TextView)v.findViewById(android.R.id.text2)).setText( "motors: " + sim.getConfiguration().getMotorConfigurationDescription() + " apogee: " + sim.getSimulatedData().getMaxAltitude() + "m time: " + sim.getSimulatedData().getFlightTime() + "s");\r
- return v;\r
- }\r
-\r
- };\r
- simulationList.setOnItemClickListener( new OnItemClickListener() {\r
- @Override\r
- public void onItemClick(AdapterView l, View v, int position, long id) {\r
- Intent i = new Intent(OpenRocketViewer.this, SimulationViewer.class);\r
- Log.d(TAG,"onItemClick simulation number " + id );\r
- i.putExtra("Simulation",(int)id);\r
- startActivityForResult(i, 1/*magic*/);\r
- }\r
-\r
- });\r
- simulationList.setAdapter(sims);\r
-\r
- ArrayAdapter<RocketComponent> comps = new ArrayAdapter<RocketComponent>(this, android.R.layout.simple_list_item_1,rocket.getChildren()) {\r
-\r
- /* (non-Javadoc)\r
- * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)\r
- */\r
- @Override\r
- public View getView(int position, View convertView, ViewGroup parent) {\r
- View v = convertView;\r
- if ( v == null ) {\r
- LayoutInflater li = getLayoutInflater();\r
- v = li.inflate(android.R.layout.simple_list_item_1,null);\r
- }\r
- RocketComponent comp = this.getItem(position);\r
- ((TextView)v.findViewById(android.R.id.text1)).setText( comp.getName() );\r
- return v;\r
- }\r
- \r
- \r
- };\r
- componentList.setAdapter(comps);\r
- \r
- if ( progress.isShowing() ) {\r
- progress.dismiss();\r
- }\r
-\r
- }\r
-\r
- @Override\r
- public boolean onCreateOptionsMenu(Menu menu) {\r
- MenuInflater inflater = getMenuInflater();\r
- inflater.inflate(R.menu.rocket_viewer_option_menu, menu);\r
- return true;\r
- }\r
-\r
- @Override\r
- public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
- Log.d(TAG,"onMenuItemSelected" + item.getItemId());\r
- switch(item.getItemId()) {\r
- case R.id.motor_list_menu_option:\r
- startMotorBrowser();\r
- return true;\r
- case R.id.preference_menu_option:\r
- Intent intent = new Intent().setClass(this, PreferencesActivity.class);\r
- this.startActivity(intent);\r
- return true;\r
- }\r
- return super.onMenuItemSelected(featureId, item);\r
- }\r
-\r
- public void startMotorBrowser() {\r
- Log.d(TAG,"motorBrowserButton clicked");\r
- Intent i = new Intent(OpenRocketViewer.this, MotorHierarchicalBrowser.class);\r
- startActivity(i);\r
- }\r
-\r
-\r
-\r
-}\r
+++ /dev/null
-/**\r
- * Copyright (C) 2009, 2010 SC 4ViewSoft SRL\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package net.sf.openrocket.android.simulation;\r
-\r
-import org.achartengine.ChartFactory;\r
-import org.achartengine.GraphicalView;\r
-import org.achartengine.chart.AbstractChart;\r
-\r
-import android.app.Activity;\r
-import android.os.Bundle;\r
-import android.view.Window;\r
-\r
-/**\r
- * An activity that encapsulates a graphical view of the chart.\r
- */\r
-public class GraphicalActivity extends Activity {\r
- /** The encapsulated graphical view. */\r
- private GraphicalView mView;\r
- /** The chart to be drawn. */\r
- private AbstractChart mChart;\r
-\r
- @Override\r
- protected void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
- requestWindowFeature(Window.FEATURE_NO_TITLE);\r
- Bundle extras = getIntent().getExtras();\r
- mChart = (AbstractChart) extras.getSerializable(ChartFactory.CHART);\r
- mView = new GraphicalView(this, mChart);\r
- String title = extras.getString(ChartFactory.TITLE);\r
- if (title == null) {\r
- requestWindowFeature(Window.FEATURE_NO_TITLE);\r
- } else if (title.length() > 0) {\r
- setTitle(title);\r
- }\r
- setContentView(mView);\r
- }\r
-\r
-}
\ No newline at end of file
+++ /dev/null
-/**\r
- * Copyright (C) 2009, 2010 SC 4ViewSoft SRL\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package net.sf.openrocket.android.simulation;\r
-\r
-import java.util.List;\r
-\r
-import net.sf.openrocket.simulation.FlightDataBranch;\r
-import net.sf.openrocket.simulation.FlightDataType;\r
-import net.sf.openrocket.simulation.FlightEvent;\r
-\r
-import org.achartengine.ChartFactory;\r
-import org.achartengine.chart.LineChart;\r
-import org.achartengine.chart.PointStyle;\r
-import org.achartengine.chart.XYChart;\r
-import org.achartengine.model.XYMultipleSeriesDataset;\r
-import org.achartengine.model.XYSeries;\r
-import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
-import org.achartengine.renderer.XYSeriesRenderer;\r
-\r
-import android.content.Context;\r
-import android.content.Intent;\r
-import android.graphics.Color;\r
-import android.graphics.Paint.Align;\r
-import android.util.Log;\r
-\r
-/**\r
- * Multiple temperature demo chart.\r
- */\r
-public class SimulationChart {\r
- \r
- private final static String TAG = "SimulationChart";\r
-\r
- private FlightDataBranch flightDataBranch;\r
- private FlightDataType series1;\r
- private FlightDataType series2;\r
- private final FlightDataType time = FlightDataType.TYPE_TIME;\r
- private List<FlightEvent> flightEvents;\r
-\r
- // Define 4 different colors and point styles to use for the series.\r
- // For now only 2 series are supported though.\r
- private final static int[] colors = new int[] { Color.BLUE, Color.YELLOW, Color.GREEN, Color.RED };\r
- private final static PointStyle[] styles = new PointStyle[] { PointStyle.CIRCLE, PointStyle.DIAMOND,\r
- PointStyle.TRIANGLE, PointStyle.SQUARE };\r
-\r
- /**\r
- * @param flightDataBranch the flightDataBranch to set\r
- */\r
- public void setFlightDataBranch(FlightDataBranch flightDataBranch) {\r
- this.flightDataBranch = flightDataBranch;\r
- }\r
-\r
- /**\r
- * @param series1 the series1 to set\r
- */\r
- public void setSeries1(FlightDataType series1) {\r
- this.series1 = series1;\r
- }\r
-\r
- /**\r
- * @param series2 the series2 to set\r
- */\r
- public void setSeries2(FlightDataType series2) {\r
- this.series2 = series2;\r
- }\r
-\r
- /**\r
- * @param flightEvents the flightEvents to set\r
- */\r
- public void setFlightEvents(List<FlightEvent> flightEvents) {\r
- this.flightEvents = flightEvents;\r
- }\r
-\r
- private static String formatFlightDataTypeAxisLabel( FlightDataType fdt ) {\r
- return fdt.getName() + " (" + fdt.getUnitGroup().getDefaultUnit().toString() + ")";\r
- }\r
-\r
- /**\r
- * Executes the chart demo.\r
- * \r
- * @param context the context\r
- * @return the built intent\r
- */\r
- public Intent execute(Context context) {\r
-\r
- /*\r
- * TODO -\r
- * Figure out why you can pan all over the place even where there are no visible points.\r
- */\r
- int seriesCount = 2;\r
- // if the same series is selected twice, only plot it once.\r
- if ( series1 == series2 ) {\r
- seriesCount = 1;\r
- }\r
-\r
- XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(seriesCount);\r
-\r
- renderer.setAxisTitleTextSize(16);\r
- renderer.setChartTitleTextSize(20);\r
- renderer.setLabelsTextSize(15);\r
- renderer.setLegendTextSize(15);\r
- renderer.setPointSize(5f);\r
- renderer.setXLabels(10);\r
- renderer.setYLabels(10);\r
- renderer.setShowGrid(true);\r
- renderer.setZoomButtonsVisible(true);\r
- renderer.setChartTitle("Simulation");\r
-\r
- renderer.setMargins(new int[] { 50, 30, 0, 20 });\r
- {\r
- for (int i = 0; i < seriesCount; i++) {\r
- XYSeriesRenderer r = new XYSeriesRenderer();\r
- r.setColor(colors[i]);\r
- r.setPointStyle(styles[i]);\r
- r.setFillPoints(true);\r
- renderer.addSeriesRenderer(r);\r
- // setting the YAximMin to 0 locks the origins.\r
- renderer.setYAxisMin(0.0, i);\r
- }\r
- }\r
-\r
- renderer.setXTitle(formatFlightDataTypeAxisLabel(time));\r
- renderer.setXLabelsAlign(Align.RIGHT);\r
-\r
- renderer.setYTitle(formatFlightDataTypeAxisLabel(series1),0);\r
- renderer.setYLabelsAlign(Align.RIGHT,0);\r
-\r
- if ( seriesCount > 1 ) {\r
- renderer.setYTitle(formatFlightDataTypeAxisLabel(series2), 1);\r
- renderer.setYAxisAlign(Align.RIGHT, 1);\r
- renderer.setYLabelsAlign(Align.LEFT, 1);\r
- }\r
-\r
- renderer.setAxesColor(Color.LTGRAY);\r
- renderer.setLabelsColor(Color.LTGRAY);\r
-\r
- XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();\r
-\r
- List<Double> timevalues = flightDataBranch.get(time);\r
- List<Double> series1values = flightDataBranch.get(series1);\r
-\r
- // compute the axis limits using timevalues and series1values.\r
- double xmin = 0;\r
- double ymin = 0;\r
- renderer.setXAxisMin(xmin);\r
- renderer.setYAxisMin(ymin);\r
-\r
- double ymax = computeMaxValueWithPadding( series1values );\r
- double xmax = Math.ceil( timevalues.get( timevalues.size()-1));\r
- \r
- Log.d(TAG,"ymax = " + ymax);\r
- renderer.setXAxisMax(xmax);\r
- renderer.setYAxisMax(ymax);\r
-\r
- // These configurations don't really work well just now.\r
- //renderer.setPanLimits(new double[] { xmin, xmax, ymin, ymax });\r
- //renderer.setZoomLimits(new double[] { xmin, xmax, ymin, ymax });\r
-\r
- // Add first series\r
- addXYSeries(dataset, series1.getName(), timevalues, series1values, 0);\r
-\r
- if ( seriesCount > 1 ) {\r
- // Add second series\r
- addXYSeries(dataset, series2.getName(), timevalues, flightDataBranch.get(series2), 1);\r
- }\r
- Intent intent = getLineChartIntent(context, dataset, renderer,"Simulation");\r
- return intent;\r
- }\r
-\r
- private static void addXYSeries(XYMultipleSeriesDataset dataset, String titles, List<Double> xValues, List<Double> yValues, int scale) {\r
- XYSeries series = new XYSeries(titles, scale);\r
- int datasize = xValues.size();\r
- for( int i = 0; i<datasize; i++ ) {\r
- series.add(xValues.get(i), yValues.get(i));\r
- }\r
- dataset.addSeries(series);\r
-\r
- }\r
-\r
- private static Intent getLineChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
- XYMultipleSeriesRenderer renderer, String activityTitle) {\r
- // checkParameters(dataset, renderer);\r
- Intent intent = new Intent(context, GraphicalActivity.class);\r
- XYChart chart = new LineChart(dataset, renderer);\r
- intent.putExtra(ChartFactory.CHART, chart);\r
- intent.putExtra(ChartFactory.TITLE, activityTitle);\r
- return intent;\r
- }\r
-\r
- private static double computeMaxValueWithPadding( List<Double> list ) {\r
- double max = list.get(0);\r
- for( double v : list ) {\r
- if ( v > max ) {\r
- max = v;\r
- }\r
- }\r
- if ( max <= 0 ) return 1.0;\r
-\r
- // Do something stupid.\r
- // return:\r
- // 10 if max <= 10\r
- // next 10 if 10 < max < 1000\r
- // next 100 if 1000 < max < 10,000\r
- // next 1000 if max >= 10,000\r
- double numdigits = Math.floor(Math.log10(max));\r
- \r
- if ( numdigits <= 1.0 ) {\r
- return 10.0;\r
- } else if ( numdigits <= 3.0 ) {\r
- return 10.0 * ( Math.ceil( max/10.0));\r
- } else if ( numdigits <= 4.0 ) {\r
- return 100.0 * ( Math.ceil( max/ 100.0) );\r
- } else {\r
- return 1000.0 * ( Math.ceil( max / 1000.0 ));\r
- }\r
- \r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.simulation;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.android.Application;\r
-import net.sf.openrocket.document.Simulation;\r
-import net.sf.openrocket.simulation.FlightDataBranch;\r
-import net.sf.openrocket.simulation.FlightDataType;\r
-import net.sf.openrocket.simulation.FlightEvent;\r
-import android.app.Activity;\r
-import android.content.Intent;\r
-import android.os.Bundle;\r
-import android.util.Log;\r
-import android.util.SparseBooleanArray;\r
-import android.view.LayoutInflater;\r
-import android.view.View;\r
-import android.view.ViewGroup;\r
-import android.widget.ArrayAdapter;\r
-import android.widget.ListView;\r
-import android.widget.Spinner;\r
-import android.widget.TabHost;\r
-import android.widget.TextView;\r
-\r
-public class SimulationViewer extends Activity {\r
-\r
- private final static String TAG = "SimulationViewer";\r
-\r
- private ListView eventList;\r
- private Spinner series1Spinner;\r
- private Spinner series2Spinner;\r
-\r
- private Simulation sim;\r
- private FlightDataBranch data;\r
-\r
- @Override\r
- public void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
- Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState));\r
- setContentView(R.layout.simulation_detail);\r
-\r
- Intent i = getIntent();\r
- int simnumber = i.getIntExtra("Simulation", 0);\r
- sim = ((Application)this.getApplication()).getRocketDocument().getSimulation(simnumber);\r
- data = sim.getSimulatedData().getBranch(0);\r
-\r
- TabHost tabs=(TabHost)findViewById(R.id.simulationConfigurationForm);\r
-\r
- tabs.setup();\r
-\r
- TabHost.TabSpec spec=tabs.newTabSpec("tag1");\r
-\r
- spec.setContent(R.id.simulationEventsList);\r
- spec.setIndicator("Events");\r
- tabs.addTab(spec);\r
-\r
- spec=tabs.newTabSpec("tag2");\r
- spec.setContent(R.id.simulationSeriesSelection);\r
- spec.setIndicator("Series");\r
- tabs.addTab(spec); \r
-\r
- eventList = (ListView) findViewById(R.id.simulationEventsList);\r
-\r
- // Initialize the eventList\r
- ArrayAdapter<FlightEvent> events = new ArrayAdapter<FlightEvent>(this,android.R.layout.simple_list_item_multiple_choice,data.getEvents()) {\r
-\r
- @Override\r
- public View getView(int position, View convertView,\r
- ViewGroup parent) {\r
- View v = convertView;\r
- if ( v == null ) {\r
- LayoutInflater li = getLayoutInflater();\r
- v = li.inflate(android.R.layout.simple_list_item_multiple_choice,null);\r
- }\r
- FlightEvent event = this.getItem(position);\r
- ((TextView)v.findViewById(android.R.id.text1)).setText( event.getType().toString() + " " + event.getTime() + " (s)" );\r
- return v;\r
- }\r
-\r
- };\r
- eventList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);\r
- eventList.setAdapter(events);\r
-\r
- series1Spinner = (Spinner) findViewById(R.id.simulationSeries1);\r
- series2Spinner = (Spinner) findViewById(R.id.simulationSeries2);\r
-\r
- List<FlightDataType> selectableSeries = new ArrayList<FlightDataType>();\r
- for( FlightDataType fdt : data.getTypes() ) {\r
- if ( fdt == FlightDataType.TYPE_TIME ) { \r
-\r
- } else {\r
- selectableSeries.add(fdt);\r
- }\r
- }\r
- ArrayAdapter<FlightDataType> serieses = new ArrayAdapter<FlightDataType>(this,android.R.layout.simple_spinner_item,selectableSeries) {\r
-\r
- @Override\r
- public View getView(int position, View convertView,\r
- ViewGroup parent) {\r
- View v = convertView;\r
- if ( v == null ) {\r
- LayoutInflater li = getLayoutInflater();\r
- v = li.inflate(android.R.layout.simple_spinner_item,null);\r
- }\r
- FlightDataType fdt = this.getItem(position);\r
- ((TextView)v.findViewById(android.R.id.text1)).setText( fdt.toString() );\r
- return v;\r
- }\r
-\r
- };\r
- series1Spinner.setAdapter(serieses);\r
- series2Spinner.setAdapter(serieses);\r
-\r
- }\r
-\r
- public void draw( View v ) {\r
- List<FlightEvent> eventsToShow = new ArrayList<FlightEvent>();\r
- {\r
- SparseBooleanArray eventsSelected = eventList.getCheckedItemPositions();\r
- List<FlightEvent> flightEvents = data.getEvents();\r
- for( int i=0; i< flightEvents.size(); i++ ) {\r
- if ( eventsSelected.get(i) ) {\r
- eventsToShow.add(flightEvents.get(i) );\r
- }\r
- }\r
- }\r
- FlightDataType series1 = (FlightDataType) series1Spinner.getSelectedItem();\r
- Log.d(TAG,"sereis1 = " + series1.toString());\r
- FlightDataType series2 = (FlightDataType) series2Spinner.getSelectedItem();\r
- Log.d(TAG,"series2 = " + series2.toString());\r
-\r
- SimulationChart chart = new SimulationChart();\r
- chart.setFlightDataBranch(data);\r
- chart.setSeries1(series1);\r
- chart.setSeries2(series2);\r
- chart.setFlightEvents(eventsToShow);\r
- \r
- startActivity(chart.execute(this));\r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.IOException;\r
-import java.io.Reader;\r
-import java.io.StringReader;\r
-import java.io.StringWriter;\r
-\r
-public abstract class Base64Decoder {\r
-\r
- private static final String BASE64_CHARS =\r
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
- private static final char PAD_CHAR = '=';\r
-\r
- private final static short[] _charToBits = new short[128];\r
-\r
- static {\r
-\r
- for (int i = 0; i < _charToBits.length; i++)\r
- _charToBits[i] = -1;\r
-\r
- for (int i = 0; i < BASE64_CHARS.length(); i++)\r
- _charToBits[BASE64_CHARS.charAt(i)] = (byte) i;\r
- _charToBits[PAD_CHAR] = 0;\r
-\r
- }\r
- \r
- /**\r
- * Decode the specified Base64 string and write binary data\r
- * to the given stream.\r
- * @param str Base64 encoded string\r
- * @param w output stream\r
- */\r
- public static String decodeData(String str) throws IOException\r
- {\r
- StringReader r;\r
- int c1;\r
-\r
- if (str == null || str.length() < 1)\r
- return null;\r
-\r
- r = new StringReader(str);\r
- \r
- StringWriter w = new StringWriter();\r
-\r
- // spin through the input string\r
- c1 = readToNonSpace(r);\r
- while (c1 > 0)\r
- {\r
- int c2, c3, c4;\r
- int p1, p2, p3, p4;\r
- int pad, n;\r
-\r
- pad = 0;\r
-\r
- c2 = readToNonSpace(r);\r
- c3 = readToNonSpace(r);\r
- c4 = readToNonSpace(r);\r
- if (c4 < 0)\r
- throw new IllegalArgumentException("Encoded string ends prematurely.");\r
-\r
- p1 = charToBits(c1);\r
- p2 = charToBits(c2);\r
-\r
- if (c3 == PAD_CHAR)\r
- {\r
- p3 = 0;\r
- pad++;\r
- }\r
- else\r
- p3 = charToBits(c3);\r
-\r
- if (c4 == PAD_CHAR)\r
- {\r
- p4 = 0;\r
- pad++;\r
- }\r
- else\r
- p4 = charToBits(c4);\r
-\r
- if (p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0)\r
- throw new IllegalArgumentException("Encoded string contains invalid characters.");\r
-\r
- n = (p1 << 18) | (p2 << 12) | (p3 << 6) | p4;\r
-\r
- w.write((byte) ((n & 0xFF0000) >> 16));\r
- if (pad < 2)\r
- w.write((byte) ((n & 0x00FF00) >> 8));\r
- if (pad < 1)\r
- w.write((byte) (n & 0x0000FF));\r
-\r
- c1 = readToNonSpace(r);\r
- if (c1 > 0 && pad > 0)\r
- throw new IllegalArgumentException("Extra characters found after padding.");\r
- }\r
- \r
- return w.toString();\r
- }\r
-\r
-\r
- private static int readToNonSpace(Reader r)\r
- throws IOException\r
- {\r
- int c;\r
-\r
- c = r.read();\r
- while (c >= 0 && Character.isWhitespace(c))\r
- c = r.read();\r
-\r
- return c;\r
- }\r
-\r
- private static int charToBits(int c)\r
- {\r
- // use it to look up the value\r
- if (c < 0 || c >= _charToBits.length)\r
- return -1;\r
- else\r
- return _charToBits[c];\r
- }\r
-\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.ArrayList;\r
-\r
-class DownloadRequest {\r
-\r
- private ArrayList<Integer> motorIds = new ArrayList<Integer>();\r
- \r
- private String format = null;\r
- \r
- public void add( Integer motorId ) {\r
- this.motorIds.add(motorId);\r
- }\r
- \r
- public void setFormat( String format ) {\r
- this.format = format;\r
- }\r
- \r
- @Override\r
- public String toString() {\r
- StringBuilder w = new StringBuilder();\r
- \r
- w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");\r
- w.append("<download-request\n");\r
- w.append(" xmlns=\"http://www.thrustcurve.org/2008/DownloadRequest\"\n");\r
- w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");\r
- w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2008/DownloadRequest http://www.thrustcurve.org/2008/download-request.xsd\">\n");\r
-\r
- if ( format != null ) {\r
- w.append(" <format>").append(format).append("</format>\n");\r
- }\r
- \r
- w.append(" <motor-ids>\n");\r
- for( Integer i : motorIds ) {\r
- w.append(" <id>").append(i).append("</id>\n");\r
- }\r
- w.append(" </motor-ids>\n");\r
- w.append("</download-request>\n");\r
- return w.toString();\r
- }\r
-\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-\r
-public class DownloadResponse {\r
-\r
- private Map<Integer,MotorBurnFile> data = new HashMap<Integer,MotorBurnFile>();\r
- \r
- private String error = null;\r
- \r
- public void add( MotorBurnFile mbd ) {\r
- MotorBurnFile currentData = data.get(mbd.getMotorId());\r
- if ( currentData == null || currentData.getDatapoints().size() < mbd.getDatapoints().size() ) {\r
- data.put(mbd.getMotorId(),mbd);\r
- }\r
- }\r
-\r
- public MotorBurnFile getData(Integer motor_id) {\r
- return data.get(motor_id);\r
- }\r
- \r
- public void setError(String error) {\r
- this.error = error;\r
- }\r
- \r
- public String getError() {\r
- return error;\r
- }\r
- \r
- @Override\r
- public String toString() {\r
- return "DownloadResponse [error=" + error + ", data=" + data + "]";\r
- }\r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.InputStream;\r
-\r
-import org.xml.sax.Attributes;\r
-\r
-import android.sax.Element;\r
-import android.sax.EndElementListener;\r
-import android.sax.EndTextElementListener;\r
-import android.sax.RootElement;\r
-import android.sax.StartElementListener;\r
-import android.util.Log;\r
-import android.util.Xml;\r
-\r
-public class DownloadResponseParser {\r
-\r
- private static final String TAG = "DownloadResponseParser";\r
-\r
- private static final String thrustcurveURI = "http://www.thrustcurve.org/2009/DownloadResponse";\r
-\r
- private static final String root_tag = "download-response";\r
- private static final String results_tag = "results";\r
- private static final String result_tag = "result";\r
- private static final String motor_id_tag = "motor-id";\r
- private static final String simfile_id_tag = "simfile-id";\r
- private static final String format_tag = "format";\r
- private static final String source_tag = "source";\r
- private static final String license_tag = "license";\r
- private static final String data_tag = "data";\r
- private static final String error_tag = "error";\r
-\r
- public static DownloadResponse parse( InputStream in ) {\r
-\r
- final DownloadResponse ret = new DownloadResponse();\r
- final MotorBurnFile currentMotor = new MotorBurnFile();\r
-\r
- // Have a place to put the data string and format.\r
- // We hold on to these here, then push them into the currentMotor\r
- // only if it a supported filetype\r
- final StringHolder current_format = new StringHolder();\r
- final StringHolder current_data = new StringHolder();\r
-\r
- RootElement rootEl = new RootElement(thrustcurveURI, root_tag);\r
- /*\r
- rootEl.setStartElementListener(\r
- new StartElementListener() {\r
- public void start(Attributes arg0) {\r
- Log.d(TAG,"Start Element error");\r
- ret.setError("IsError");\r
- }\r
- }\r
- );\r
- */\r
- Element resultsEl = rootEl.getChild( thrustcurveURI, results_tag);\r
- Element resultEl = resultsEl.getChild( thrustcurveURI, result_tag);\r
- resultEl.setStartElementListener(\r
- new StartElementListener() {\r
- @Override\r
- public void start(Attributes arg0) {\r
- Log.d(TAG,"Start Element result");\r
- currentMotor.init();\r
- }\r
- }\r
- );\r
-\r
- resultEl.setEndElementListener(\r
- new EndElementListener() {\r
- @Override\r
- public void end() {\r
- if ( SupportedFileTypes.isSupportedFileType(current_format.s) ) {\r
- currentMotor.setFiletype(current_format.s);\r
- String s = null;\r
- try {\r
- s = Base64Decoder.decodeData(current_data.s);\r
- } catch ( Exception ex ) {\r
- Log.d(TAG,"base64: " + ex.getMessage());\r
- }\r
- currentMotor.decodeFile( s );\r
- }\r
- ret.add((MotorBurnFile)currentMotor.clone());\r
- }\r
- }\r
- );\r
-\r
- resultEl.getChild(thrustcurveURI,motor_id_tag).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setMotor_id(Integer.parseInt(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,format_tag).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- current_format.s = arg0;\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,data_tag).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- current_data.s = arg0;\r
- }\r
- }\r
- );\r
- try {\r
- Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
- } catch (Exception e) {\r
- throw new RuntimeException(e);\r
- }\r
-\r
- return ret;\r
- }\r
-\r
- private static class StringHolder {\r
- public String s;\r
- }\r
-\r
-}
\ No newline at end of file
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.Vector;\r
-\r
-public class MotorBurnFile {\r
-\r
- private Integer motor_id;\r
- private String filetype;\r
- private Float length;\r
- private String delays;\r
- private Double propWeightG;\r
- private Double totWeightG;\r
- private Vector<Double> datapoints = new Vector<Double>();\r
- \r
- public void init() {\r
- this.motor_id = null;\r
- this.filetype = null;\r
- this.length = null;\r
- this.delays = null;\r
- this.propWeightG = null;\r
- this.totWeightG = null;\r
- this.datapoints = new Vector<Double>();\r
- }\r
- \r
- @Override\r
- public MotorBurnFile clone() {\r
- MotorBurnFile clone = new MotorBurnFile();\r
- clone.motor_id = this.motor_id;\r
- clone.filetype = this.filetype;\r
- clone.length = this.length;\r
- clone.delays = this.delays;\r
- clone.propWeightG = this.propWeightG;\r
- clone.totWeightG = this.totWeightG;\r
- clone.datapoints = this.datapoints;\r
- return clone;\r
- }\r
-\r
- public void decodeFile(String data){\r
- if (SupportedFileTypes.RASP_FORMAT.equals(filetype)) {\r
- RaspBurnFile.parse(this,data);\r
- } else if (SupportedFileTypes.ROCKSIM_FORMAT.equals(filetype) ){\r
- RSEBurnFile.parse(this,data);\r
- }\r
- }\r
- \r
- public Integer getMotorId() {\r
- return motor_id;\r
- }\r
- public String getFileType() {\r
- return filetype;\r
- }\r
- public Float getLength() {\r
- return length;\r
- }\r
- public String getDelays() {\r
- return delays;\r
- }\r
- public Double getPropWeightG() {\r
- return propWeightG;\r
- }\r
- public Double getTotWeightG() {\r
- return totWeightG;\r
- }\r
- public Vector<Double> getDatapoints() {\r
- return datapoints;\r
- }\r
-\r
- void setMotor_id(Integer motor_id) {\r
- this.motor_id = motor_id;\r
- }\r
- void setFiletype(String filetype ) {\r
- this.filetype = filetype;\r
- }\r
- void setLength(Float length) {\r
- this.length = length;\r
- }\r
- void setDelays(String delays) {\r
- this.delays = delays;\r
- }\r
- void setPropWeightG(Double propWeightG) {\r
- this.propWeightG = propWeightG;\r
- }\r
- void setTotWeightG(Double totWeightG) {\r
- this.totWeightG = totWeightG;\r
- }\r
- void setDatapoints(Vector<Double> datapoints) {\r
- this.datapoints = datapoints;\r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.io.InputStream;\r
-import java.util.Vector;\r
-\r
-import org.xml.sax.Attributes;\r
-\r
-import android.sax.Element;\r
-import android.sax.RootElement;\r
-import android.sax.StartElementListener;\r
-import android.util.Log;\r
-import android.util.Xml;\r
-\r
-class RSEBurnFile extends MotorBurnFile {\r
-\r
- private final static String TAG = "RSEBurnFile";\r
-\r
- static void parse( MotorBurnFile that, String filecontents ) {\r
-\r
- parse(that, new ByteArrayInputStream(filecontents.getBytes()) );\r
- }\r
-\r
- private final static String root_tag = "engine-database";\r
- private final static String engine_list_tag = "engine-list";\r
- private final static String engine_tag = "engine";\r
-\r
- private final static String delays_attr = "delays";\r
- private final static String len_attr = "len";\r
- private final static String propwgt_attr = "propWt";\r
- private final static String totwgt_attr = "initWt";\r
-\r
- private final static String data_tag = "data";\r
- private final static String eng_data_tag = "eng-data";\r
-\r
- private final static String time_attr="t";\r
- private final static String force_attr="f";\r
-\r
- static void parse( final MotorBurnFile that, InputStream in ) {\r
-\r
- RootElement rootEl = new RootElement(root_tag);\r
- Element engineEl = rootEl.getChild(engine_list_tag).getChild(engine_tag);\r
-\r
- final Vector<Double> datapoints = new Vector<Double>();\r
- \r
- Log.d(TAG,"parsing start");\r
-\r
- engineEl.setStartElementListener(\r
- new StartElementListener() {\r
- @Override\r
- public void start(Attributes arg0) {\r
- Log.d(TAG,"start engineEl");\r
- that.setPropWeightG(Double.parseDouble(arg0.getValue(propwgt_attr)));\r
- that.setTotWeightG(Double.parseDouble(arg0.getValue(totwgt_attr)));\r
- that.setLength(Float.parseFloat(arg0.getValue(len_attr)));\r
- that.setDelays(arg0.getValue(delays_attr));\r
- Log.d(TAG, "me is now " + that.toString());\r
- }\r
- }\r
- );\r
-\r
- Element datapointEl = engineEl.getChild(data_tag).getChild(eng_data_tag);\r
- datapointEl.setStartElementListener(\r
- new StartElementListener() {\r
- @Override\r
- public void start(Attributes attributes) {\r
- Double x = Double.parseDouble(attributes.getValue(time_attr));\r
- Double y = Double.parseDouble(attributes.getValue(force_attr));\r
- Log.d(TAG, "add data point " + x + "," + y);\r
- datapoints.add(x);\r
- datapoints.add(y);\r
- }\r
- }\r
- );\r
-\r
- try {\r
- Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
- } catch (Exception e) {\r
- throw new RuntimeException(e);\r
- }\r
-\r
- that.setDatapoints(datapoints);\r
- }\r
-}\r
-//\r
-// <engine-database>\r
-// <engine-list>\r
-// <engine FDiv="10" FFix="1" FStep="-1." Isp="202.11" Itot="8.919" Type="single-use" auto-calc-cg="1" auto-calc-mass="1" avgThrust="3.795" burn-time="2.35" cgDiv="10" cgFix="1" cgStep="-1." code="C4" delays="3,5,7" dia="18." exitDia="0." initWt="17." len="50." mDiv="10" mFix="1" mStep="-1." massFrac="26.47" mfg="Apogee" peakThrust="11.31" propWt="4.5" tDiv="10" tFix="1" tStep="-1." throatDia="0.">\r
-// <comments>Apogee C4 RASP.ENG file made from NAR published data\r
-// File produced September 4, 2000\r
-// The total impulse, peak thrust, average thrust and burn time are\r
-// the same as the averaged static test data on the NAR web site in\r
-// the certification file. The curve drawn with these data points is as\r
-// close to the certification curve as can be with such a limited\r
-// number of points (32) allowed with wRASP up to v1.6.\r
-// </comments>\r
-// <data>\r
-// <eng-data cg="25." f="0." m="4.5" t="0."/>\r
-// <eng-data cg="25." f="3.23" m="4.48533" t="0.018"/>\r
-// <eng-data cg="25." f="6.874" m="4.42671" t="0.041"/>\r
-// <eng-data cg="25." f="8.779" m="4.00814" t="0.147"/>\r
-// <eng-data cg="25." f="10.683" m="3.28643" t="0.294"/>\r
-// <eng-data cg="25." f="11.31" m="2.89252" t="0.365"/>\r
-// <eng-data cg="25." f="10.521" m="2.76585" t="0.388"/>\r
-// <eng-data cg="25." f="8.779" m="2.649" t="0.412"/>\r
-// <eng-data cg="25." f="7.04" m="2.53328" t="0.441"/>\r
-// <eng-data cg="25." f="4.555" m="2.46308" t="0.465"/>\r
-// <eng-data cg="25." f="3.479" m="2.33337" t="0.529"/>\r
-// <eng-data cg="25." f="2.981" m="2.1704" t="0.629"/>\r
-// <eng-data cg="25." f="3.23" m="2.1328" t="0.653"/>\r
-// <eng-data cg="25." f="2.816" m="2.03366" t="0.718"/>\r
-// <eng-data cg="25." f="2.733" m="1.84469" t="0.853"/>\r
-// <eng-data cg="25." f="2.65" m="1.5568" t="1.065"/>\r
-// <eng-data cg="25." f="2.567" m="1.30938" t="1.253"/>\r
-// <eng-data cg="25." f="2.401" m="1.05873" t="1.453"/>\r
-// <eng-data cg="25." f="2.484" m="0.761739" t="1.694"/>\r
-// <eng-data cg="25." f="2.484" m="0.636413" t="1.794"/>\r
-// <eng-data cg="25." f="2.733" m="0.612724" t="1.812"/>\r
-// <eng-data cg="25." f="2.401" m="0.575165" t="1.841"/>\r
-// <eng-data cg="25." f="2.401" m="0.446759" t="1.947"/>\r
-// <eng-data cg="25." f="2.401" m="0.246881" t="2.112"/>\r
-// <eng-data cg="25." f="2.401" m="0.0978809" t="2.235"/>\r
-// <eng-data cg="25." f="2.236" m="0.0429024" t="2.282"/>\r
-// <eng-data cg="25." f="1.656" m="0.0134478" t="2.312"/>\r
-// <eng-data cg="25." f="0.662" m="0.003507" t="2.329"/>\r
-// <eng-data cg="25." f="0." m="-0." t="2.35"/>\r
-// </data>\r
-// </engine>\r
-// </engine-list>\r
-// </engine-database>\r
-//\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.IOException;\r
-import java.io.LineNumberReader;\r
-import java.io.StringReader;\r
-import java.util.Vector;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import android.util.Log;\r
-\r
-\r
-class RaspBurnFile{\r
-\r
- private final static String TAG = "RaspBurnFile";\r
- \r
- private final static int HEADER = 0;\r
- private final static int DATA = 1;\r
- private final static Pattern headerPattern = Pattern.compile("(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)\\s+(\\S*)");\r
- private final static Pattern dataPattern = Pattern.compile("(\\S*)\\s+(\\S*)");\r
- \r
- static void parse( MotorBurnFile that, String filecontents ) {\r
- \r
- int state = HEADER;\r
- \r
- LineNumberReader reader = new LineNumberReader( new StringReader(filecontents));\r
- \r
- Vector<Double> datapoints = new Vector<Double>();\r
- \r
- String line;\r
- Matcher m;\r
- try {\r
- while ( (line = reader.readLine()) != null ) {\r
- line = line.trim();\r
- Log.d("RASP",line);\r
- if ( line.startsWith(";")) {\r
- continue;\r
- }\r
- switch (state) {\r
- \r
- case HEADER:\r
- Log.d("RASP","header");\r
- m = headerPattern.matcher(line);\r
- if ( m.matches() ) {\r
- Log.d("RASP","header matches");\r
- \r
- /*motorName = m.group(1);*/\r
- /*diameter = Integer.decode(m.group(2));*/\r
- that.setLength(Float.parseFloat(m.group(3)) );\r
- String delays = m.group(4);\r
- if ( delays != null ) {\r
- delays = delays.replace("-", ",");\r
- that.setDelays(delays);\r
- }\r
- that.setPropWeightG(Double.parseDouble(m.group(5))*1000.0);\r
- that.setTotWeightG(Double.parseDouble(m.group(6))*1000.0);\r
- /*manufacturer = m.group(7);*/\r
- \r
- }\r
- state = DATA;\r
- break;\r
- \r
- case DATA:\r
- Log.d("RASP","data");\r
- m = dataPattern.matcher(line);\r
- if ( m.matches() ) {\r
- Log.d("RASP","data matches");\r
- Double x = Double.parseDouble(m.group(1));\r
- Double y = Double.parseDouble(m.group(2));\r
- Log.d("RASP","data matches ("+x+","+y+")");\r
- datapoints.add(x);\r
- datapoints.add(y);\r
- }\r
- break;\r
- }\r
- that.setDatapoints(datapoints);\r
- }\r
- } catch (IOException ex ) {\r
- Log.d(TAG,"Unable to parse Rasp file: " + ex);\r
- }\r
- \r
- }\r
- \r
-\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-public class SearchRequest {\r
-\r
- private String manufacturer;\r
- private String designation;\r
- private String brand_name;\r
- \r
- private String common_name;\r
- private String impulse_class;\r
- private Integer diameter;\r
- \r
- /*\r
- public enum Type {\r
- "SU";\r
- "reload";\r
- "hybrid"\r
- };\r
- */\r
- private String type;\r
- \r
- public void setManufacturer(String manufacturer) {\r
- this.manufacturer = null;\r
- if ( manufacturer != null ) {\r
- manufacturer = manufacturer.trim();\r
- if ( ! "".equals(manufacturer) ) {\r
- this.manufacturer = manufacturer;\r
- }\r
- }\r
- }\r
-\r
- public void setDesignation(String designation) {\r
- this.designation = designation;\r
- }\r
-\r
- public void setBrand_name(String brand_name) {\r
- this.brand_name = brand_name;\r
- }\r
-\r
- public void setCommon_name(String common_name) {\r
- if ( common_name == null ) {\r
- this.common_name = null;\r
- return;\r
- }\r
- this.common_name = common_name.trim();\r
- if ( "".equals(this.common_name)) {\r
- this.common_name = null;\r
- }\r
- }\r
-\r
- public void setImpulse_class(String impulse_class) {\r
- this.impulse_class = null;\r
- if ( impulse_class != null ) {\r
- this.impulse_class = impulse_class.trim();\r
- if ( "".equals(impulse_class) ) {\r
- this.impulse_class = null;\r
- }\r
- }\r
- }\r
-\r
- public void setDiameter(Integer diameter) {\r
- this.diameter = diameter;\r
- }\r
- \r
- public void setDiameter(String diameter) {\r
- this.diameter = null;\r
- if ( diameter == null ) {\r
- return;\r
- }\r
- try {\r
- this.diameter = Integer.decode(diameter);\r
- } catch ( NumberFormatException ex ) {\r
- this.diameter = null;\r
- }\r
- }\r
-\r
- public void setType(String type) {\r
- this.type = type;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- StringBuilder w = new StringBuilder();\r
- \r
- w.append("<?xml version=\"1.0\" encoding=\"ascii\"?>\n");\r
- w.append("<search-request\n");\r
- w.append(" xmlns=\"http://www.thrustcurve.org/2011/SearchRequest\"\n");\r
- w.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");\r
- w.append(" xsi:schemaLocation=\"http://www.thrustcurve.org/2011/SearchRequest http://www.thrustcurve.org/2011/search-request.xsd\">\n");\r
-\r
- if ( manufacturer != null ) {\r
- w.append(" <manufacturer>").append(manufacturer).append("</manufacturer>\n");\r
- }\r
- if ( designation != null ) {\r
- w.append(" <designation>").append(designation).append("</designation>\n");\r
- }\r
- if ( brand_name != null ) {\r
- w.append(" <brand-name>").append(brand_name).append("</brand-name>\n");\r
- }\r
- if ( common_name != null ) {\r
- w.append(" <common-name>").append(common_name).append("</common-name>\n");\r
- }\r
- if ( impulse_class != null ) {\r
- w.append(" <impulse-class>").append(impulse_class).append("</impulse-class>\n");\r
- }\r
- if ( diameter != null ) {\r
- w.append(" <diameter>").append(diameter).append("</diameter>\n");\r
- }\r
- if ( type != null ) {\r
- w.append(" <type>").append(type).append("</type>\n");\r
- }\r
- w.append("<data-fields>*</data-fields>");\r
- w.append("<max-results>50</max-results>");\r
- w.append("</search-request>\n");\r
- return w.toString();\r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-\r
-public class SearchResponse {\r
-\r
- private List<TCMotor> results = new ArrayList<TCMotor>();\r
- \r
- private int matches;\r
- \r
- private String error;\r
-\r
- public List<TCMotor> getResults() {\r
- return results;\r
- }\r
-\r
- public void setResults(List<TCMotor> results) {\r
- this.results = results;\r
- }\r
-\r
- public int getMatches() {\r
- return matches;\r
- }\r
-\r
- public void setMatches(int matches) {\r
- this.matches = matches;\r
- }\r
-\r
- public String getError() {\r
- return error;\r
- }\r
-\r
- public void setError(String error) {\r
- this.error = error;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return "SearchResult [results=" + results + ", matches=" + matches\r
- + ", error=" + error + "]";\r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.InputStream;\r
-\r
-import org.xml.sax.Attributes;\r
-\r
-import android.sax.Element;\r
-import android.sax.EndElementListener;\r
-import android.sax.EndTextElementListener;\r
-import android.sax.RootElement;\r
-import android.sax.StartElementListener;\r
-import android.util.Xml;\r
-\r
-public class SearchResponseParser {\r
-\r
- private static final String thrustcurveURI = "http://www.thrustcurve.org/2008/SearchResponse";\r
- /*\r
- * XML Tags in SearchResult xsd\r
- */\r
- private static final String root_tag = "search-response";\r
- private static final String criteria = "criteria";\r
- private static final String criterion = "criterion";\r
- private static final String name = "name";\r
- private static final String value = "value";\r
- private static final String matches = "matches";\r
- private static final String results = "results";\r
- private static final String result = "result";\r
- \r
- private static final String motor_id = "motor-id";\r
- private static final String manufacturer = "manufacturer";\r
- private static final String manufacturer_abbr = "manufacturer-abbrev";\r
- private static final String designation = "designation";\r
- private static final String brand_name = "brand-name";\r
- private static final String common_name = "common-name";\r
- private static final String impulse_class = "impulse-class";\r
- private static final String diameter = "diameter";\r
- private static final String length = "length";\r
- private static final String type = "type";\r
- private static final String cert_org = "cert-org";\r
- private static final String avg_thrust_n = "avg-thrust-n";\r
- private static final String max_thrust_n = "max-thrust-n";\r
- private static final String tot_impulse_ns = "tot-impulse-ns";\r
- private static final String burn_time_s = "burn-time-s";\r
- private static final String data_files = "data-files";\r
- private static final String info_url = "info-url";\r
- private static final String total_weight_g = "total-weight-g";\r
- private static final String prop_weight_g = "prop-weight-g";\r
- private static final String delays = "delays";\r
- private static final String case_info = "case-info";\r
- private static final String prop_info = "prop-info";\r
- private static final String updated_on = "updated-on";\r
- \r
- public static SearchResponse parse( InputStream in ) {\r
- \r
- final SearchResponse ret = new SearchResponse();\r
- final TCMotor currentMotor = new TCMotor();\r
-\r
- RootElement rootEl = new RootElement(thrustcurveURI, root_tag);\r
- Element criteriaEl = rootEl.getChild( thrustcurveURI, criteria);\r
- \r
- criteriaEl.getChild(thrustcurveURI,matches).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- ret.setMatches(Integer.parseInt(arg0));\r
- }\r
- }\r
- );\r
- Element resultsEl = rootEl.getChild(thrustcurveURI,results);\r
- Element resultEl = resultsEl.getChild(thrustcurveURI,result);\r
-\r
- resultEl.setStartElementListener(\r
- new StartElementListener() {\r
- @Override\r
- public void start(Attributes arg0) {\r
- currentMotor.init();\r
- }\r
- }\r
- );\r
- \r
- resultEl.setEndElementListener(\r
- new EndElementListener() {\r
- @Override\r
- public void end() {\r
- ret.getResults().add((TCMotor)currentMotor.clone());\r
- }\r
- }\r
- );\r
- \r
- resultEl.getChild(thrustcurveURI,motor_id).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setMotor_id(Integer.parseInt(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,manufacturer).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- if ( arg0 != null ) {\r
- currentMotor.setManufacturer(arg0);\r
- }\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,manufacturer_abbr).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- if ( arg0 != null ) {\r
- currentMotor.setManufacturer_abbr(arg0);\r
- }\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,designation).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setDesignation(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,brand_name).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setBrand_name(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,common_name).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setCommon_name(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,impulse_class).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setImpulse_class(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,diameter).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setDiameter(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,length).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setLength(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,type).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setType(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,cert_org).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setCert_org(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,avg_thrust_n).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setAvg_thrust_n(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,max_thrust_n).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setMax_thrust_n(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,tot_impulse_ns).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setTot_impulse_ns(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,burn_time_s).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setBurn_time_s(Float.parseFloat(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,data_files).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setData_files(Integer.parseInt(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,info_url).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setInfo_url(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,total_weight_g).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setTot_mass_g(Double.parseDouble(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,prop_weight_g).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setProp_mass_g(Double.parseDouble(arg0));\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,delays).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setDelays(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,case_info).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setCase_info(arg0);\r
- }\r
- }\r
- );\r
- resultEl.getChild(thrustcurveURI,prop_info).setEndTextElementListener(\r
- new EndTextElementListener() {\r
- @Override\r
- public void end(String arg0) {\r
- currentMotor.setProp_info(arg0);\r
- }\r
- }\r
- );\r
-\r
-\r
- try {\r
- Xml.parse(in, Xml.Encoding.UTF_8, rootEl.getContentHandler());\r
- } catch (Exception e) {\r
- throw new RuntimeException(e);\r
- }\r
-\r
- return ret;\r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-public abstract class SupportedFileTypes {\r
-\r
- public final static String ROCKSIM_FORMAT = "RockSim";\r
- public final static String RASP_FORMAT = "RASP";\r
- \r
- public static boolean isSupportedFileType( String arg0 ) {\r
- return (ROCKSIM_FORMAT.equals(arg0) || RASP_FORMAT.equals(arg0));\r
- }\r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.Date;\r
-import java.util.Vector;\r
-\r
-public class TCMotor implements Cloneable {\r
-\r
- private Integer motor_id;\r
- private String manufacturer;\r
- private String manufacturer_abbr;\r
- private String designation;\r
- private String brand_name;\r
- private String common_name;\r
- private String impulse_class;\r
- private Float diameter;\r
- private Float length;\r
- private String type;\r
- private String cert_org;\r
- private Float avg_thrust_n;\r
- private Float max_thrust_n;\r
- private Float tot_impulse_ns;\r
- private Float burn_time_s;\r
- private Integer data_files;\r
- private String info_url;\r
- private Double tot_mass_g;\r
- private Double prop_mass_g;\r
- private String delays;\r
- private String case_info;\r
- private String prop_info;\r
- private Date updated_on;\r
- private Vector<Double> burndata;\r
- \r
- public void init() {\r
- motor_id = null;\r
- manufacturer = null;\r
- manufacturer_abbr = null;\r
- designation = null;\r
- brand_name = null;\r
- common_name = null;\r
- impulse_class = null;\r
- diameter = null;\r
- length = null;\r
- type = null;\r
- cert_org = null;\r
- avg_thrust_n = null;\r
- max_thrust_n = null;\r
- tot_impulse_ns = null;\r
- burn_time_s = null;\r
- data_files = null;\r
- info_url = null;\r
- tot_mass_g = null;\r
- prop_mass_g = null;\r
- delays = null;\r
- case_info = null;\r
- prop_info = null;\r
- updated_on = null;\r
- burndata = null;\r
- }\r
- \r
- @Override\r
- public TCMotor clone() {\r
- TCMotor clone = new TCMotor();\r
- clone.motor_id = this.motor_id;\r
- clone.manufacturer = this.manufacturer;\r
- clone.manufacturer_abbr = this.manufacturer_abbr;\r
- clone.designation = this.designation;\r
- clone.brand_name = this.brand_name;\r
- clone.common_name = this.common_name;\r
- clone.impulse_class = this.impulse_class;\r
- clone.diameter = this.diameter;\r
- clone.length = this.length;\r
- clone.type = this.type;\r
- clone.cert_org = this.cert_org;\r
- clone.avg_thrust_n = this.avg_thrust_n;\r
- clone.max_thrust_n = this.max_thrust_n;\r
- clone.tot_impulse_ns = this.tot_impulse_ns;\r
- clone.burn_time_s = this.burn_time_s;\r
- clone.data_files = this.data_files;\r
- clone.info_url = this.info_url;\r
- clone.tot_mass_g = this.tot_mass_g;\r
- clone.prop_mass_g = this.prop_mass_g;\r
- clone.delays = this.delays;\r
- clone.case_info = this.case_info;\r
- clone.prop_info = this.prop_info;\r
- clone.updated_on = this.updated_on;\r
- clone.burndata = this.burndata;\r
- return clone;\r
- }\r
-\r
- public Integer getMotor_id() {\r
- return motor_id;\r
- }\r
-\r
- public void setMotor_id(Integer motor_id) {\r
- this.motor_id = motor_id;\r
- }\r
-\r
- public String getManufacturer() {\r
- return manufacturer;\r
- }\r
-\r
- public void setManufacturer(String manufacturer) {\r
- this.manufacturer = manufacturer;\r
- }\r
-\r
- public String getManufacturer_abbr() {\r
- return manufacturer_abbr;\r
- }\r
-\r
- public void setManufacturer_abbr(String manufacturer_abbr) {\r
- this.manufacturer_abbr = manufacturer_abbr;\r
- }\r
-\r
- public String getDesignation() {\r
- return designation;\r
- }\r
-\r
- public void setDesignation(String designation) {\r
- this.designation = designation;\r
- }\r
-\r
- public String getBrand_name() {\r
- return brand_name;\r
- }\r
-\r
- public void setBrand_name(String brand_name) {\r
- this.brand_name = brand_name;\r
- }\r
-\r
- public String getCommon_name() {\r
- return common_name;\r
- }\r
-\r
- public void setCommon_name(String common_name) {\r
- this.common_name = common_name;\r
- }\r
-\r
- public String getImpulse_class() {\r
- return impulse_class;\r
- }\r
-\r
- public void setImpulse_class(String impulse_class) {\r
- this.impulse_class = impulse_class;\r
- }\r
-\r
- public Float getDiameter() {\r
- return diameter;\r
- }\r
-\r
- public void setDiameter(Float diameter) {\r
- this.diameter = diameter;\r
- }\r
-\r
- public Float getLength() {\r
- return length;\r
- }\r
-\r
- public void setLength(Float length) {\r
- this.length = length;\r
- }\r
-\r
- public String getType() {\r
- return type;\r
- }\r
-\r
- public void setType(String type) {\r
- this.type = type;\r
- }\r
-\r
- public String getCert_org() {\r
- return cert_org;\r
- }\r
-\r
- public void setCert_org(String cert_org) {\r
- this.cert_org = cert_org;\r
- }\r
-\r
- public Float getAvg_thrust_n() {\r
- return avg_thrust_n;\r
- }\r
-\r
- public void setAvg_thrust_n(Float avg_thrust_n) {\r
- this.avg_thrust_n = avg_thrust_n;\r
- }\r
-\r
- public Float getMax_thrust_n() {\r
- return max_thrust_n;\r
- }\r
-\r
- public void setMax_thrust_n(Float max_thrust_n) {\r
- this.max_thrust_n = max_thrust_n;\r
- }\r
-\r
- public Float getTot_impulse_ns() {\r
- return tot_impulse_ns;\r
- }\r
-\r
- public void setTot_impulse_ns(Float tot_impulse_ns) {\r
- this.tot_impulse_ns = tot_impulse_ns;\r
- }\r
-\r
- public Float getBurn_time_s() {\r
- return burn_time_s;\r
- }\r
-\r
- public void setBurn_time_s(Float burn_time_s) {\r
- this.burn_time_s = burn_time_s;\r
- }\r
-\r
- public Integer getData_files() {\r
- return data_files;\r
- }\r
-\r
- public void setData_files(Integer data_files) {\r
- this.data_files = data_files;\r
- }\r
-\r
- public String getInfo_url() {\r
- return info_url;\r
- }\r
-\r
- public void setInfo_url(String info_url) {\r
- this.info_url = info_url;\r
- }\r
-\r
- public Double getTot_mass_g() {\r
- return tot_mass_g;\r
- }\r
-\r
- public void setTot_mass_g(Double tot_mass_g) {\r
- this.tot_mass_g = tot_mass_g;\r
- }\r
-\r
- public Double getProp_mass_g() {\r
- return prop_mass_g;\r
- }\r
-\r
- public void setProp_mass_g(Double prop_mass_g) {\r
- this.prop_mass_g = prop_mass_g;\r
- }\r
-\r
- public String getDelays() {\r
- return delays;\r
- }\r
-\r
- public void setDelays(String delays) {\r
- this.delays = delays;\r
- }\r
-\r
- public String getCase_info() {\r
- return case_info;\r
- }\r
-\r
- public void setCase_info(String case_info) {\r
- this.case_info = case_info;\r
- }\r
-\r
- public String getProp_info() {\r
- return prop_info;\r
- }\r
-\r
- public void setProp_info(String prop_info) {\r
- this.prop_info = prop_info;\r
- }\r
-\r
- public Date getUpdated_on() {\r
- return updated_on;\r
- }\r
-\r
- public void setUpdated_on(Date updated_on) {\r
- this.updated_on = updated_on;\r
- }\r
-\r
- public Vector<Double> getBurndata() {\r
- return burndata;\r
- }\r
-\r
- public void setBurndata(Vector<Double> burndata) {\r
- this.burndata = burndata;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return "TCMotor [motor_id=" + motor_id + ", manufacturer="\r
- + manufacturer + ", manufacturer_abbr=" + manufacturer_abbr\r
- + ", designation=" + designation + ", brand_name=" + brand_name\r
- + ", common_name=" + common_name + ", impulse_class="\r
- + impulse_class + ", diameter=" + diameter + ", length="\r
- + length + ", type=" + type + ", cert_org=" + cert_org\r
- + ", avg_thrust_n=" + avg_thrust_n + ", max_thrust_n="\r
- + max_thrust_n + ", tot_impulse_ns=" + tot_impulse_ns\r
- + ", burn_time_s=" + burn_time_s + ", data_files=" + data_files\r
- + ", info_url=" + info_url + ", tot_mass_g=" + tot_mass_g\r
- + ", prop_mass_g=" + prop_mass_g + ", delays=" + delays\r
- + ", case_info=" + case_info + ", prop_info=" + prop_info\r
- + ", updated_on=" + updated_on + "]";\r
- }\r
- \r
-}\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.util.Vector;\r
-\r
-import net.sf.openrocket.R;\r
-import net.sf.openrocket.android.db.DbAdapter;\r
-import net.sf.openrocket.android.motor.Motor;\r
-import android.app.Activity;\r
-import android.app.AlertDialog;\r
-import android.app.ProgressDialog;\r
-import android.content.DialogInterface;\r
-import android.os.Bundle;\r
-import android.os.Handler;\r
-import android.util.Log;\r
-import android.view.View;\r
-import android.widget.Button;\r
-import android.widget.EditText;\r
-import android.widget.Spinner;\r
-\r
-public class TCQueryActivity extends Activity {\r
-\r
- private static final String TAG = "ThrustCurveQueryActivity";\r
-\r
- private DbAdapter mDbHelper;\r
-\r
- private ProgressDialog progress;\r
- private Thread downloadThread;\r
- private Handler handler;\r
-\r
- @Override\r
- protected void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
- setContentView(R.layout.tcqueryform);\r
-\r
- mDbHelper = new DbAdapter(this);\r
- mDbHelper.open();\r
-\r
- final Spinner manufacturerField = (Spinner) findViewById(R.id.TCMotorSearchFormManufacturerField);\r
- final Spinner impulseField = (Spinner) findViewById(R.id.TCMotorSearchFormImpulseField);\r
- final Spinner diameterField = (Spinner) findViewById(R.id.TCMotorSearchFormDiameterField);\r
- final EditText commonNameField = (EditText) findViewById(R.id.TCMotorSearchFormCommonNameField);\r
-\r
- Button submitButton = (Button) findViewById(R.id.TCMotorSearchFromSubmitButton);\r
- submitButton.setOnClickListener(\r
- new View.OnClickListener() {\r
- @Override\r
- public void onClick( View v ) {\r
- Log.d(TAG,"submit button clicked");\r
-\r
- String commonName = commonNameField.getText().toString();\r
-\r
- SearchRequest r = new SearchRequest();\r
- if ( manufacturerField.getSelectedItemPosition() != 0) {\r
- String m = (String) manufacturerField.getSelectedItem();\r
- Log.d(TAG,"manufacturer = " + m);\r
- r.setManufacturer(m);\r
- }\r
- if ( impulseField.getSelectedItemPosition() != 0 ) {\r
- String impulse = (String) impulseField.getSelectedItem();\r
- Log.d(TAG,"impulse = " + impulse);\r
- r.setImpulse_class(impulse);\r
- }\r
- if ( diameterField.getSelectedItemPosition() != 0 ) {\r
- String diameter = (String)diameterField.getSelectedItem();\r
- Log.d(TAG,"diameter = " + diameter);\r
- r.setDiameter(diameter);\r
- }\r
- r.setCommon_name(commonName);\r
-\r
- Downloader d = new Downloader(r);\r
-\r
- handler = new Handler();\r
- progress = ProgressDialog.show(TCQueryActivity.this, null, "");\r
-\r
- downloadThread = new Thread( d );\r
- downloadThread.start();\r
- }\r
- }\r
- );\r
- }\r
-\r
- @Override\r
- public Object onRetainNonConfigurationInstance() {\r
- return downloadThread;\r
- }\r
-\r
- @Override\r
- protected void onDestroy() {\r
- mDbHelper.close();\r
- if ( progress != null ) {\r
- if ( progress.isShowing() ) {\r
- progress.dismiss();\r
- }\r
- progress = null;\r
- }\r
- super.onDestroy();\r
- }\r
-\r
- private class UpdateMessage implements Runnable {\r
- private String newMessage;\r
- UpdateMessage( String message ) {\r
- this.newMessage = message;\r
- }\r
- @Override\r
- public void run() {\r
- progress.setMessage(newMessage);\r
- }\r
- }\r
-\r
- private class Dismiss implements Runnable {\r
- @Override\r
- public void run() {\r
- progress.dismiss();\r
- TCQueryActivity.this.finish();\r
- }\r
- }\r
-\r
- private class Error implements Runnable {\r
- private String newMessage;\r
- Error( String message ) {\r
- this.newMessage = message;\r
- }\r
- @Override\r
- public void run() {\r
- progress.dismiss();\r
- final AlertDialog dialog = new AlertDialog.Builder(TCQueryActivity.this).create();\r
- dialog.setMessage(newMessage);\r
- dialog.setButton(DialogInterface.BUTTON_NEUTRAL,"Dismiss", new DialogInterface.OnClickListener() {\r
-\r
- @Override\r
- public void onClick(DialogInterface arg0, int arg1) {\r
- dialog.dismiss();\r
- }\r
-\r
- });\r
- dialog.show();\r
- }\r
- }\r
- private class Downloader implements Runnable {\r
-\r
- SearchRequest request;\r
-\r
- Downloader( SearchRequest request ) {\r
- this.request = request;\r
- }\r
-\r
- @Override\r
- public void run() {\r
- try {\r
- handler.post( new UpdateMessage("Quering Thrustcurve"));\r
- SearchResponse res = new ThrustCurveAPI().doSearch(request);\r
-\r
- int total = res.getResults().size();\r
- int count = 1;\r
- for( TCMotor mi : res.getResults() ) {\r
- handler.post(new UpdateMessage("Downloading details " + count + " of " + total));\r
- count++;\r
- if ( mi.getData_files() == null || mi.getData_files().intValue() == 0 ) {\r
- continue;\r
- }\r
-\r
- MotorBurnFile b = new ThrustCurveAPI().downloadData(mi.getMotor_id());\r
-\r
- if ( b != null ) {\r
- if ( b.getLength() != null ) {\r
- mi.setLength( b.getLength() );\r
- }\r
- if ( b.getPropWeightG() != null ) {\r
- mi.setProp_mass_g(b.getPropWeightG());\r
- }\r
- if ( b.getTotWeightG() != null ) {\r
- mi.setTot_mass_g(b.getTotWeightG());\r
- }\r
- if ( b.getDelays() != null ) {\r
- mi.setDelays(b.getDelays());\r
- }\r
- mi.setBurndata(b.getDatapoints());\r
- }\r
- Log.d(TAG, mi.toString());\r
-\r
- // convert to Motors. One per delay.\r
- Motor m = new Motor();\r
- // Base name of motor.\r
- String name = mi.getCommon_name() + "-";\r
-\r
- m.setManufacturer(mi.getManufacturer_abbr());\r
- // Convert impulse class. ThrustCurve puts mmx, 1/4a and 1/2a as A.\r
- m.setImpulseClass(mi.getImpulse_class());\r
- if ( "a".equalsIgnoreCase(mi.getImpulse_class())) {\r
- if( mi.getCommon_name().startsWith("1/2A") ) {\r
- m.setImpulseClass("1/2A");\r
- } else if (mi.getCommon_name().startsWith("1/4A") ) {\r
- m.setImpulseClass("1/4A");\r
- } else if (mi.getCommon_name().startsWith("Micro") ) {\r
- m.setImpulseClass("1/8A");\r
- }\r
- }\r
- m.setAvgThrust(mi.getAvg_thrust_n());\r
- m.setBurndata(mi.getBurndata());\r
- m.setBurnTime(mi.getBurn_time_s());\r
- m.setDiameter(mi.getDiameter() == null ? null : mi.getDiameter().longValue());\r
- m.setLength(mi.getLength());\r
- m.setMaxThrust(mi.getMax_thrust_n());\r
- m.setPropMass(mi.getProp_mass_g());\r
- m.setTotalImpulse(mi.getTot_impulse_ns());\r
- m.setTotMass(mi.getTot_mass_g());\r
- // Convert Case Info.\r
- if ( mi.getCase_info() == null\r
- || "single use".equalsIgnoreCase(mi.getCase_info())\r
- || "single-use".equalsIgnoreCase(mi.getCase_info())) {\r
- m.setCaseInfo(mi.getType()+ " " + mi.getDiameter() + "x" + mi.getLength());\r
- } else {\r
- m.setCaseInfo(mi.getCase_info());\r
- }\r
-\r
- Vector<String> delays = new Vector<String>();\r
- {\r
- String delaysString = mi.getDelays();\r
- if ( delaysString != null ) {\r
- delaysString = delaysString.trim();\r
- }\r
-\r
- if ( delaysString == null || "".equals(delaysString)) {\r
- delays.add("");\r
- } else {\r
- String[] delayString = delaysString.split(",");\r
- for( String d : delayString ) {\r
- delays.add( d.trim() );\r
- }\r
- }\r
- }\r
-\r
- for( String d: delays ) {\r
- if ( "100".equals(d) ) {\r
- m.setName(name + "P");\r
- } else {\r
- m.setName(name + d);\r
- }\r
- mDbHelper.getMotorDao().insertOrUpdateMotor(m);\r
- }\r
- }\r
- if ( total < res.getMatches() ) {\r
- handler.post( new Error( total + " motors downloaded, " + res.getMatches() + " matched. Try restricting the query more.") );\r
- } else {\r
- handler.post( new Dismiss());\r
- }\r
- }\r
- catch( Exception ex){\r
- Log.d(TAG,ex.toString());\r
- handler.post( new Error(ex.toString()) );\r
- }\r
-\r
- }\r
- }\r
-}\r
-\r
+++ /dev/null
-package net.sf.openrocket.android.thrustcurve;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.OutputStream;\r
-import java.net.MalformedURLException;\r
-import java.net.URL;\r
-import java.net.URLConnection;\r
-\r
-import android.util.Log;\r
-\r
-\r
-public class ThrustCurveAPI {\r
-\r
- private final static String TAG = "ThrustCurveAPI";\r
- \r
- private String url_base = "http://www.thrustcurve.org/servlets/";\r
- \r
- public SearchResponse doSearch( SearchRequest request ) throws MalformedURLException, IOException {\r
- \r
- String requestString = request.toString();\r
- \r
- Log.d(TAG, "doSearch: " + requestString);\r
- URL url = new URL(url_base + "search");\r
-\r
- OutputStream stream;\r
-\r
- URLConnection conn = url.openConnection();\r
- conn.setConnectTimeout(2000);\r
- conn.setDoInput(true);\r
- conn.setDoOutput(true);\r
- conn.setUseCaches(false);\r
-\r
- stream = conn.getOutputStream();\r
-\r
- stream.write(requestString.getBytes());\r
- \r
- InputStream is = conn.getInputStream();\r
-\r
- SearchResponse result = SearchResponseParser.parse(is);\r
- Log.d(TAG,result.toString());\r
- \r
- return result;\r
- }\r
-\r
- public MotorBurnFile downloadData( Integer motor_id ) throws MalformedURLException, IOException {\r
-\r
- if ( motor_id == null ) {\r
- return null;\r
- }\r
- DownloadRequest dr = new DownloadRequest();\r
- dr.add(motor_id);\r
-\r
- String requestString = dr.toString();\r
-\r
- Log.d(TAG, "downloadData: " + requestString);\r
- URL url = new URL(url_base + "download");\r
-\r
- OutputStream stream;\r
-\r
- URLConnection conn = url.openConnection();\r
- conn.setDoInput(true);\r
- conn.setDoOutput(true);\r
- conn.setUseCaches(false);\r
-\r
- stream = conn.getOutputStream();\r
-\r
- stream.write(requestString.getBytes());\r
-\r
- InputStream is = conn.getInputStream();\r
-\r
- DownloadResponse downloadResponse = DownloadResponseParser.parse(is);\r
- Log.d(TAG,downloadResponse.toString());\r
-\r
- MotorBurnFile mbf = downloadResponse.getData(motor_id);\r
-\r
- return mbf;\r
-\r
- }\r
-}\r