Added Configuration tab to the rocket viewer which displays all the motor configurati...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 22 May 2012 19:34:11 +0000 (19:34 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Tue, 22 May 2012 19:34:11 +0000 (19:34 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@709 180e2498-e6e9-4542-8430-84ac67f01cd8

13 files changed:
android/res/layout/motor_config_delay_dialog.xml [new file with mode: 0644]
android/res/layout/motor_config_item.xml [new file with mode: 0644]
android/res/layout/motor_list_dialog.xml [new file with mode: 0644]
android/res/layout/rocket_configurations.xml [new file with mode: 0644]
android/res/layout/simulation_condition_dialog.xml [new file with mode: 0644]
android/res/values/strings.xml
android/src/net/sf/openrocket/android/motor/MotorDelayDialogFragment.java [new file with mode: 0644]
android/src/net/sf/openrocket/android/motor/MotorListDialogFragment.java [new file with mode: 0644]
android/src/net/sf/openrocket/android/rocket/Configurations.java [new file with mode: 0644]
android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java
android/src/net/sf/openrocket/android/simulation/SimulationRunActivity.java [new file with mode: 0644]
android/src/net/sf/openrocket/android/simulation/SimulationRunFragment.java [new file with mode: 0644]
android/src/net/sf/openrocket/android/util/PersistentExpandableListView.java [new file with mode: 0644]

diff --git a/android/res/layout/motor_config_delay_dialog.xml b/android/res/layout/motor_config_delay_dialog.xml
new file mode 100644 (file)
index 0000000..b328001
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+    android:layout_width="match_parent"\r
+    android:layout_height="match_parent"\r
+    android:orientation="vertical" >
+\r
+    <EditText\r
+        android:id="@+id/motor_config_delay_diag_edit"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:ems="10"\r
+        android:inputType="number" >\r
+\r
+        <requestFocus />\r
+    </EditText>
+\r
+    <ListView\r
+        android:id="@+id/motor_config_delay_diag_list"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content" >\r
+    </ListView>\r
+\r
+</LinearLayout>
\ No newline at end of file
diff --git a/android/res/layout/motor_config_item.xml b/android/res/layout/motor_config_item.xml
new file mode 100644 (file)
index 0000000..46b07a2
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+    android:layout_width="match_parent"\r
+    android:layout_height="match_parent"\r
+    android:focusable="false" >\r
+\r
+    <TextView\r
+        android:id="@+id/motor_config_motor_mount_name"\r
+        style="@style/labelTextStyle"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:focusable="false"\r
+        android:text="Stage" />\r
+\r\r
+    <Button\r
+        android:id="@+id/motor_config_motor_desc"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:layout_below="@id/motor_config_motor_mount_name"\r
+        android:layout_margin="0dp"\r
+        android:layout_toLeftOf="@+id/motor_config_motor_dash"\r
+        android:text="@string/select_motor"\r
+        android:textAppearance="@style/valueTextStyle" />\r
+\r
+    <TextView\r
+        android:id="@+id/motor_config_motor_dash"\r
+        style="@style/valueTextStyle"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:layout_alignBaseline="@id/motor_config_motor_desc"\r
+        android:layout_below="@id/motor_config_motor_mount_name"\r
+        android:layout_toLeftOf="@+id/motor_config_motor_delay"\r
+        android:gravity="right"\r
+        android:text="-" />\r
+\r\r
+    <Button\r
+        android:id="@+id/motor_config_motor_delay"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:layout_alignBaseline="@id/motor_config_motor_desc"\r
+        android:layout_alignParentRight="true"\r
+        android:layout_below="@id/motor_config_motor_mount_name"\r
+        android:text="@string/select_delay"\r
+        android:textAppearance="@style/valueTextStyle" />\r
+\r
+</RelativeLayout>
\ No newline at end of file
diff --git a/android/res/layout/motor_list_dialog.xml b/android/res/layout/motor_list_dialog.xml
new file mode 100644 (file)
index 0000000..ff18b98
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+    android:layout_width="match_parent"\r
+    android:layout_height="match_parent"\r
+    android:orientation="vertical" >\r
+\r
+    <fragment\r
+        android:id="@+id/motor_list"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="match_parent"\r
+        class="net.sf.openrocket.motor.MotorListFragment" />\r
+\r
+</LinearLayout>
\ No newline at end of file
diff --git a/android/res/layout/rocket_configurations.xml b/android/res/layout/rocket_configurations.xml
new file mode 100644 (file)
index 0000000..51b976b
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+    android:layout_width="match_parent"\r
+    android:layout_height="match_parent"\r
+    android:orientation="vertical" >\r
+\r
+    <LinearLayout\r
+        android:layout_width="match_parent"\r
+        android:layout_height="0dp"\r
+        android:layout_weight="1"\r
+        android:orientation="vertical" >\r
+\r
+        <!--  Note because my implementation of ExpandableListFragment is stupid, the id\r
+        of the ExpandableListView must be @android:id/list -->\r
+        <ExpandableListView\r
+            android:id="@android:id/list"\r
+            android:layout_width="match_parent"\r
+            android:layout_height="wrap_content" />\r
+    </LinearLayout>\r
+\r
+    <Button\r
+        android:id="@+id/openrocketviewerAddConfiguration"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:layout_gravity="center_horizontal"\r
+        android:text="Add" />\r
+\r
+</LinearLayout>
\ No newline at end of file
diff --git a/android/res/layout/simulation_condition_dialog.xml b/android/res/layout/simulation_condition_dialog.xml
new file mode 100644 (file)
index 0000000..8e53119
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+    android:layout_width="match_parent"\r
+    android:layout_height="match_parent"\r
+    android:orientation="vertical" >\r
+\r
+    <TextView\r
+        style="@style/labelTextStyle"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:text="@string/simulationConditionWind" />\r
+\r
+    <EditText\r
+        android:id="@+id/simulation_condition_windspeed"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:ems="10"\r
+        android:gravity="right"\r
+        android:inputType="number"\r
+        android:text="0" >\r
+\r
+        <requestFocus />\r
+    </EditText>\r
+\r
+    <TextView\r
+        style="@style/labelTextStyle"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:text="@string/simulationConditionsRodLength" />\r
+\r
+    <EditText\r
+        android:id="@+id/simulation_condition_rodlength"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:ems="10"\r
+        android:gravity="right"\r
+        android:inputType="number"\r
+        android:text="0" />\r
+\r
+    <TextView\r
+        style="@style/labelTextStyle"\r
+        android:layout_width="wrap_content"\r
+        android:layout_height="wrap_content"\r
+        android:text="@string/simulationConditionsLaunchRodAngle" />\r
+\r
+    <EditText\r
+        android:id="@+id/simulation_condition_rodangle"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:ems="10"\r
+        android:gravity="right"\r
+        android:inputType="number"\r
+        android:text="0" />\r
+\r
+    <Spinner\r
+        android:id="@+id/simulationConditionConfigurationSpinner"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:prompt="@string/simulationConditionSelectMotors" />\r
+\r
+</LinearLayout>
\ No newline at end of file
index 8eb5b45976d550cc373c218a610a1b6331b43c5f..4e96aedc150bc6e6299f5af0193bfa06ad9b4bd5 100644 (file)
         <string name="motor_impulseclass">Impulse Class</string>\r
         <string name="motor_diameter">Diameter</string>\r
         <string name="motor_length">Length</string>\r
+        <string name="simulationConditionSelectMotors">Select Motors</string>\r
+        <string name="simulationConditionWind">Wind speed</string>\r
+        <string name="simulationConditionsRodLength">Launch Rod Length</string>\r
+        <string name="simulationConditionsLaunchRodAngle">Launch Rod Angle</string>\r
+        <string name="select_motor">Select Motor</string>\r
+        <string name="select_delay">Delay</string>\r
 \r
 </resources>
\ No newline at end of file
diff --git a/android/src/net/sf/openrocket/android/motor/MotorDelayDialogFragment.java b/android/src/net/sf/openrocket/android/motor/MotorDelayDialogFragment.java
new file mode 100644 (file)
index 0000000..99d1f60
--- /dev/null
@@ -0,0 +1,112 @@
+package net.sf.openrocket.android.motor;\r
+\r
+import java.util.ArrayList;\r
+\r
+import net.sf.openrocket.R;\r
+import android.app.AlertDialog;\r
+import android.app.Dialog;\r
+import android.os.Bundle;\r
+import android.support.v4.app.DialogFragment;\r
+import android.view.KeyEvent;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.ArrayAdapter;\r
+import android.widget.EditText;\r
+import android.widget.ListView;\r
+import android.widget.TextView;\r
+\r
+public class MotorDelayDialogFragment extends DialogFragment \r
+implements View.OnClickListener, TextView.OnEditorActionListener {\r
+\r
+       public interface OnDelaySelectedListener {\r
+               public void onDelaySelected( double delay );\r
+       }\r
+\r
+       private OnDelaySelectedListener delaySelectedListener;\r
+\r
+       public void setDelaySelectedListener(OnDelaySelectedListener delaySelectedListener) {\r
+               this.delaySelectedListener = delaySelectedListener;\r
+       }\r
+\r
+       private final static String delaysArg = "delaysArg";\r
+       \r
+       public static MotorDelayDialogFragment newInstance( double[] delays ) {\r
+               MotorDelayDialogFragment f = new MotorDelayDialogFragment();\r
+               Bundle b = new Bundle();\r
+               b.putDoubleArray(delaysArg, delays);\r
+               f.setArguments(b);\r
+               return f;\r
+       }\r
+\r
+       @Override\r
+       public void onClick(View v) {\r
+               String s = ((TextView)v).getText().toString();\r
+               long value = Long.parseLong(s);\r
+               if ( delaySelectedListener != null ) {\r
+                       delaySelectedListener.onDelaySelected(value);\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {\r
+               if ( event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_ENTER ) {\r
+                       String s = v.getText().toString();\r
+                       if ( s != null ) { // note requires ems=10\r
+                               long value = Long.parseLong(s);\r
+                               if ( delaySelectedListener != null ) {\r
+                                       delaySelectedListener.onDelaySelected(value);\r
+                               }\r
+                       }\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       @Override\r
+       public Dialog onCreateDialog(Bundle savedInstanceState) {\r
+               \r
+               if (savedInstanceState == null ) {\r
+                       savedInstanceState = getArguments();\r
+               }\r
+               double[] delays = savedInstanceState.getDoubleArray(delaysArg);\r
+               ArrayList<Long> delayList = new ArrayList<Long>(delays.length);\r
+               for( int i =0; i< delays.length; i++ ) {\r
+                       delayList.add( Math.round(delays[i]) );\r
+               }\r
+               \r
+               AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());\r
+               builder.setTitle("Enter or Choose Delay");\r
+               \r
+               LayoutInflater li = getActivity().getLayoutInflater();\r
+               View v = li.inflate(R.layout.motor_config_delay_dialog, null);\r
+               builder.setView(v);\r
+               \r
+               ArrayAdapter<Long> listAdapter = new ArrayAdapter<Long>(getActivity(),android.R.layout.simple_list_item_1,delayList) {\r
+\r
+                       @Override\r
+                       public View getView(int position, View convertView, ViewGroup parent) {\r
+                               if ( convertView == null ) {\r
+                                       convertView = getActivity().getLayoutInflater().inflate( android.R.layout.simple_list_item_1, null);\r
+                               }\r
+                               TextView tv = (TextView) convertView.findViewById(android.R.id.text1);\r
+                               tv.setText( String.valueOf(getItem(position)) );\r
+                               tv.setOnClickListener( MotorDelayDialogFragment.this );\r
+                               return convertView;\r
+                       }\r
+                       \r
+                       \r
+               };\r
+               \r
+               ListView lv = (ListView) v.findViewById(R.id.motor_config_delay_diag_list);\r
+               lv.setAdapter(listAdapter);\r
+               \r
+               EditText et = (EditText) v.findViewById(R.id.motor_config_delay_diag_edit);\r
+               et.setOnEditorActionListener(MotorDelayDialogFragment.this);\r
+               return builder.create();\r
+               \r
+       }\r
+       \r
+       \r
+       \r
+}\r
diff --git a/android/src/net/sf/openrocket/android/motor/MotorListDialogFragment.java b/android/src/net/sf/openrocket/android/motor/MotorListDialogFragment.java
new file mode 100644 (file)
index 0000000..fcacba1
--- /dev/null
@@ -0,0 +1,154 @@
+package net.sf.openrocket.android.motor;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.db.DbAdapter;\r
+import net.sf.openrocket.android.db.MotorDao;\r
+import net.sf.openrocket.android.util.AndroidLogWrapper;\r
+import net.sf.openrocket.android.util.PersistentExpandableListView;\r
+import android.app.AlertDialog;\r
+import android.app.Dialog;\r
+import android.content.Context;\r
+import android.database.Cursor;\r
+import android.os.Bundle;\r
+import android.support.v4.app.DialogFragment;\r
+import android.view.View;\r
+import android.widget.ExpandableListView;\r
+import android.widget.ResourceCursorTreeAdapter;\r
+import android.widget.TextView;\r
+\r
+public class MotorListDialogFragment extends DialogFragment \r
+implements ExpandableListView.OnChildClickListener\r
+{\r
+\r
+       public interface OnMotorSelectedListener {\r
+               public void onMotorSelected( long motorId );\r
+       }\r
+\r
+       private final static String groupColumn = MotorDao.DIAMETER;\r
+\r
+       private DbAdapter mDbHelper;\r
+\r
+       private ExpandableListView list;\r
+\r
+       private OnMotorSelectedListener motorSelectedListener;\r
+\r
+       public void setMotorSelectedListener(\r
+                       OnMotorSelectedListener motorSelectedListener) {\r
+               this.motorSelectedListener = motorSelectedListener;\r
+       }\r
+\r
+       @Override\r
+       public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {\r
+               if( motorSelectedListener != null ) {\r
+                       motorSelectedListener.onMotorSelected(id);\r
+               }\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public Dialog onCreateDialog(Bundle savedInstanceState) {\r
+               AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());\r
+               builder.setTitle("Select Motor");\r
+               list = new PersistentExpandableListView(getActivity());\r
+               list.setOnChildClickListener( this );\r
+               refreshData();\r
+               builder.setView( list );\r
+               return builder.create();\r
+       }\r
+\r
+       @Override\r
+       public void onPause() {\r
+               super.onPause();\r
+               mDbHelper.close();\r
+       }\r
+\r
+       public void refreshData() {\r
+               if ( mDbHelper == null ) {\r
+                       mDbHelper = new DbAdapter(getActivity());\r
+               }\r
+               mDbHelper.open();\r
+\r
+               Cursor motorCounter = mDbHelper.getMotorDao().fetchAllMotors();\r
+               int motorCount = motorCounter.getCount();\r
+               motorCounter.close();\r
+               \r
+               if ( motorCount == 0 ) {\r
+                       AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());\r
+                       builder.setTitle("No Motors Found");\r
+                       builder.setMessage("Motors can be downloaded from thrustcurve");\r
+                       builder.setCancelable(true);\r
+                       builder.create().show();\r
+               }\r
+\r
+               Cursor motorCursor = mDbHelper.getMotorDao().fetchGroups(groupColumn);\r
+               MotorHierarchicalListAdapter mAdapter = new MotorHierarchicalListAdapter( \r
+                               getActivity(),\r
+                               motorCursor,\r
+                               R.layout.motor_list_group,\r
+                               R.layout.motor_list_child);\r
+               list.setAdapter(mAdapter);\r
+       }\r
+\r
+       public class MotorHierarchicalListAdapter extends ResourceCursorTreeAdapter\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 ) {\r
+\r
+                       super(context, cursor, groupLayout, childLayout);\r
+               }\r
+\r
+               @Override\r
+               protected Cursor getChildrenCursor(Cursor arg0) {\r
+                       AndroidLogWrapper.d(MotorListFragment.class,"getChildrenCursor");\r
+                       String group = arg0.getString(arg0.getColumnIndex(groupColumn));\r
+                       Cursor c = mDbHelper.getMotorDao().fetchAllInGroups(groupColumn,group);\r
+                       return c;\r
+               }\r
+\r
+               @Override\r
+               public long getGroupId(int groupPosition) {\r
+                       return groupPosition;\r
+               }\r
+\r
+               /* (non-Javadoc)\r
+                * @see android.widget.CursorTreeAdapter#bindChildView(android.view.View, android.content.Context, android.database.Cursor, boolean)\r
+                */\r
+               @Override\r
+               protected void bindChildView(View arg0, Context arg1, Cursor arg2,\r
+                               boolean arg3) {\r
+\r
+                       TextView manu = (TextView) arg0.findViewById(R.id.motorChildManu);\r
+                       manu.setText( arg2.getString(arg2.getColumnIndex(MotorDao.MANUFACTURER)));\r
+\r
+                       TextView desig = (TextView) arg0.findViewById(R.id.motorChildName);\r
+                       desig.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DESIGNATION)));\r
+\r
+                       TextView delays = (TextView) arg0.findViewById(R.id.motorChildDelays);\r
+                       delays.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DELAYS)));\r
+\r
+                       TextView totImpulse = (TextView) arg0.findViewById(R.id.motorChildImpulse);\r
+                       totImpulse.setText( arg2.getString(arg2.getColumnIndex(MotorDao.TOTAL_IMPULSE)));\r
+               }\r
+\r
+               /* (non-Javadoc)\r
+                * @see android.widget.CursorTreeAdapter#bindGroupView(android.view.View, android.content.Context, android.database.Cursor, boolean)\r
+                */\r
+               @Override\r
+               protected void bindGroupView(View view, Context context, Cursor cursor,\r
+                               boolean isExpanded) {\r
+                       TextView v = (TextView) view.findViewById(R.id.motorGroup);\r
+                       if ( MotorDao.DIAMETER.equals(groupColumn)) {\r
+                               double d = cursor.getDouble( cursor.getColumnIndex(groupColumn));\r
+                               v.setText( String.valueOf(Math.round(d * 1000.0)) + " mm");\r
+                       } else {\r
+                               v.setText( cursor.getString( cursor.getColumnIndex(groupColumn)));\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+\r
+}\r
diff --git a/android/src/net/sf/openrocket/android/rocket/Configurations.java b/android/src/net/sf/openrocket/android/rocket/Configurations.java
new file mode 100644 (file)
index 0000000..b986a91
--- /dev/null
@@ -0,0 +1,280 @@
+package net.sf.openrocket.android.rocket;\r
+\r
+import java.util.List;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.Application;\r
+import net.sf.openrocket.android.db.DbAdapter;\r
+import net.sf.openrocket.android.motor.ExtendedThrustCurveMotor;\r
+import net.sf.openrocket.android.motor.MotorDelayDialogFragment;\r
+import net.sf.openrocket.android.motor.MotorListDialogFragment;\r
+import net.sf.openrocket.android.util.AndroidLogWrapper;\r
+import net.sf.openrocket.android.util.ExpandableListFragment;\r
+import net.sf.openrocket.document.OpenRocketDocument;\r
+import net.sf.openrocket.motor.Motor;\r
+import net.sf.openrocket.rocketcomponent.MotorMount;\r
+import net.sf.openrocket.rocketcomponent.RocketComponent;\r
+import net.sf.openrocket.unit.UnitGroup;\r
+import android.os.Bundle;\r
+import android.support.v4.app.FragmentTransaction;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.BaseExpandableListAdapter;\r
+import android.widget.Button;\r
+import android.widget.ExpandableListAdapter;\r
+import android.widget.TextView;\r
+\r
+public class Configurations extends ExpandableListFragment {\r
+\r
+       private final static String wizardFrag = "wizardFrag";\r
+       \r
+       @Override\r
+       public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
+                       Bundle savedInstanceState) {\r
+               View v = inflater.inflate(R.layout.rocket_configurations, container, false);\r
+\r
+               Button b = (Button) v.findViewById(R.id.openrocketviewerAddConfiguration);\r
+\r
+               b.setOnClickListener( new View.OnClickListener() {\r
+\r
+                       @Override\r
+                       public void onClick(View v) {\r
+                               ((Application)getActivity().getApplication()).getRocketDocument().getRocket().newMotorConfigurationID();\r
+                               Configurations.this.setup();\r
+                       }\r
+               });\r
+\r
+               return v;\r
+       }\r
+\r
+       @Override\r
+       public void onActivityCreated(Bundle savedInstanceState) {\r
+               super.onActivityCreated(savedInstanceState);\r
+\r
+               setup();\r
+\r
+       }\r
+\r
+       private static class MotorMountInfo {\r
+\r
+               private RocketComponent mmt;\r
+               private String config;\r
+               private ExtendedThrustCurveMotor motor;\r
+               private double delay;\r
+\r
+               String getMotorMountDescription() {\r
+                       String mmtDesc = mmt.getComponentName();\r
+                       mmtDesc += " (" + UnitGroup.UNITS_MOTOR_DIMENSIONS.toStringUnit( ((MotorMount)mmt).getMotorMountDiameter()) + ")";\r
+                       return mmtDesc;\r
+               }\r
+\r
+               String getMotorDescription() {\r
+                       return motor.getManufacturer().getDisplayName() + " " + motor.getDesignation();\r
+               }\r
+\r
+       }\r
+\r
+       class ChildViewHolder {\r
+               MotorMountInfo info;\r
+               TextView motorMountName;\r
+               Button motorDescription;\r
+               Button motorDelay;\r
+               void setMotor( ExtendedThrustCurveMotor motor ) {\r
+                       this.info.motor = motor;\r
+                       ((MotorMount)info.mmt).setMotor(info.config, motor);\r
+               }\r
+               void setDelay( double delay ) {\r
+                       this.info.delay = delay;\r
+                       ((MotorMount)info.mmt).setMotorDelay(info.config, delay);\r
+               }\r
+       }\r
+\r
+       private void setup() {\r
+               final OpenRocketDocument rocketDocument = ((Application)getActivity().getApplication()).getRocketDocument();\r
+\r
+               ExpandableListAdapter configurationAdapter = new BaseExpandableListAdapter() {\r
+\r
+                       List<MotorMount> mmts = rocketDocument.getRocket().getMotorMounts();\r
+\r
+                       @Override\r
+                       public int getGroupCount() {\r
+                               return rocketDocument.getRocket().getMotorConfigurationIDs().length;\r
+                       }\r
+\r
+                       @Override\r
+                       public int getChildrenCount(int groupPosition) {\r
+                               return mmts.size();\r
+                       }\r
+\r
+                       @Override\r
+                       public Object getGroup(int groupPosition) {\r
+                               String config = rocketDocument.getRocket().getMotorConfigurationIDs()[groupPosition];\r
+                               return config;\r
+                       }\r
+\r
+                       @Override\r
+                       public Object getChild(int groupPosition, int childPosition) {\r
+                               MotorMountInfo info = new MotorMountInfo();\r
+                               info.mmt = (RocketComponent)(mmts.get(childPosition));\r
+\r
+                               String config = (String) getGroup(groupPosition);\r
+                               info.config = config;\r
+                               info.motor = (ExtendedThrustCurveMotor) ((MotorMount)info.mmt).getMotor(config);\r
+\r
+                               if ( info.motor != null ) {\r
+                                       info.delay = ((MotorMount)info.mmt).getMotorDelay(config);\r
+                               } else {\r
+                                       info.delay = -1;\r
+                               }\r
+\r
+                               return info;\r
+                       }\r
+\r
+                       @Override\r
+                       public long getGroupId(int groupPosition) {\r
+                               // TODO Auto-generated method stub\r
+                               return 0;\r
+                       }\r
+\r
+                       @Override\r
+                       public long getChildId(int groupPosition, int childPosition) {\r
+                               // TODO Auto-generated method stub\r
+                               return 0;\r
+                       }\r
+\r
+                       @Override\r
+                       public boolean hasStableIds() {\r
+                               // TODO Auto-generated method stub\r
+                               return false;\r
+                       }\r
+\r
+                       @Override\r
+                       public View getGroupView(int groupPosition, boolean isExpanded,\r
+                                       View convertView, ViewGroup parent) {\r
+                               if ( convertView == null ) {\r
+                                       convertView = getActivity().getLayoutInflater().inflate(android.R.layout.simple_expandable_list_item_1,null);\r
+                               }\r
+                               String configDescription = rocketDocument.getRocket().getMotorConfigurationNameOrDescription((String) getGroup(groupPosition));\r
+                               ((TextView)convertView.findViewById(android.R.id.text1)).setText( configDescription );\r
+                               return convertView;\r
+                       }\r
+\r
+                       @Override\r
+                       public View getChildView(int groupPosition, int childPosition,\r
+                                       boolean isLastChild, View convertView, ViewGroup parent) {\r
+                               if ( convertView == null ) {\r
+                                       convertView = getActivity().getLayoutInflater().inflate(R.layout.motor_config_item,null);\r
+                                       ChildViewHolder holder = new ChildViewHolder();\r
+                                       holder.motorMountName = (TextView) convertView.findViewById(R.id.motor_config_motor_mount_name);\r
+                                       holder.motorDescription = (Button) convertView.findViewById(R.id.motor_config_motor_desc);\r
+                                       holder.motorDelay = (Button) convertView.findViewById(R.id.motor_config_motor_delay);\r
+                                       holder.info = (MotorMountInfo) getChild(groupPosition,childPosition);\r
+                                       convertView.setTag(holder);\r
+                               }\r
+\r
+                               ChildViewHolder cvHolder = (ChildViewHolder) convertView.getTag();\r
+\r
+                               cvHolder.motorMountName.setText(cvHolder.info.getMotorMountDescription());\r
+                               cvHolder.motorDescription.setOnClickListener( new MotorWizardOnClickListener() );\r
+                               if ( cvHolder.info.motor == null ) {\r
+                                       cvHolder.motorDelay.setClickable(false);\r
+                                       cvHolder.motorDelay.setOnClickListener(null);\r
+                                       cvHolder.motorDescription.setText(R.string.select_motor);\r
+                               } else {\r
+                                       cvHolder.motorDelay.setClickable(true);\r
+                                       cvHolder.motorDelay.setOnClickListener( new MotorDelayOnClickListener(cvHolder.info.motor) );\r
+                                       cvHolder.motorDescription.setText(cvHolder.info.getMotorDescription());\r
+                               }\r
+                               if( cvHolder.info.delay >=0 ) {\r
+                                       if( cvHolder.info.delay == Motor.PLUGGED ) {\r
+                                               cvHolder.motorDelay.setText("P");\r
+                                       } else {\r
+                                               cvHolder.motorDelay.setText( String.valueOf(Math.round(cvHolder.info.delay)));\r
+                                       }\r
+                               } else {\r
+                                       cvHolder.motorDelay.setText(R.string.select_delay);\r
+                               }\r
+\r
+                               return convertView;\r
+                       }\r
+\r
+                       @Override\r
+                       public boolean isChildSelectable(int groupPosition,\r
+                                       int childPosition) {\r
+                               // TODO Auto-generated method stub\r
+                               return false;\r
+                       }\r
+\r
+               };\r
+\r
+               setListAdapter(configurationAdapter);\r
+       }\r
+\r
+       private class MotorWizardOnClickListener implements View.OnClickListener {\r
+               @Override\r
+               public void onClick(View v) {\r
+                       final ViewGroup parent = (ViewGroup) v.getParent();\r
+                       final ChildViewHolder cvHolder = (ChildViewHolder) parent.getTag();\r
+                       final MotorListDialogFragment f = new MotorListDialogFragment();\r
+                       f.setMotorSelectedListener( new MotorListDialogFragment.OnMotorSelectedListener() {\r
+\r
+                               @Override\r
+                               public void onMotorSelected(long motorId) {\r
+                                       DbAdapter mdbHelper = new DbAdapter(getActivity());\r
+                                       mdbHelper.open();\r
+                                       try {\r
+                                               ExtendedThrustCurveMotor motor = mdbHelper.getMotorDao().fetchMotor(motorId);\r
+                                               cvHolder.setMotor( motor );\r
+                                               ((BaseExpandableListAdapter)Configurations.this.getExpandableListAdapter()).notifyDataSetInvalidated();\r
+                                       } catch (Exception ex) {\r
+                                               AndroidLogWrapper.d(Configurations.class, "BlewUp looking for motor", ex);\r
+                                       } finally {\r
+                                               mdbHelper.close();\r
+                                       }\r
+                                       FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();\r
+                                       ft.remove(f);\r
+                                       ft.commit();\r
+\r
+                               }\r
+                       });\r
+                       FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();\r
+                       ft.add(f, wizardFrag);\r
+                       ft.commit();\r
+               }\r
+\r
+       }\r
+\r
+       private class MotorDelayOnClickListener implements View.OnClickListener {\r
+\r
+               double[] standardDelays;\r
+\r
+               public MotorDelayOnClickListener(ExtendedThrustCurveMotor motor) {\r
+                       super();\r
+                       this.standardDelays = motor.getStandardDelays();\r
+               }\r
+\r
+               @Override\r
+               public void onClick(View v) {\r
+                       final View parent = (View) v.getParent();\r
+                       final ChildViewHolder cvHolder = (ChildViewHolder) parent.getTag();\r
+                       final MotorDelayDialogFragment f = MotorDelayDialogFragment.newInstance(standardDelays);\r
+                       f.setDelaySelectedListener( new MotorDelayDialogFragment.OnDelaySelectedListener() {\r
+\r
+                               @Override\r
+                               public void onDelaySelected(double delay) {\r
+                                       cvHolder.setDelay( delay );\r
+                                       ((BaseExpandableListAdapter)Configurations.this.getExpandableListAdapter()).notifyDataSetInvalidated();\r
+                                       FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();\r
+                                       ft.remove(f);\r
+                                       ft.commit();\r
+\r
+                               }\r
+                       });\r
+                       FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();\r
+                       ft.add(f, wizardFrag);\r
+                       ft.commit();\r
+               }\r
+\r
+       }\r
+}\r
index 42aaff12ff95e378acf4d8de3ae5dd76a6ab4e50..c1535d47353970a01244e213defc41b16f109c23 100644 (file)
@@ -123,7 +123,7 @@ implements Simulations.OnSimulationSelectedListener
                }\r
                @Override\r
                public int getCount() {\r
-                       return 3;\r
+                       return 4;\r
                }\r
                @Override\r
                public Fragment getItem( int position ) {\r
@@ -134,6 +134,8 @@ implements Simulations.OnSimulationSelectedListener
                                return new Component();\r
                        case 2:\r
                                return new Simulations();\r
+                       case 3:\r
+                               return new Configurations();\r
                        }\r
                        return null;\r
                }\r
@@ -146,6 +148,8 @@ implements Simulations.OnSimulationSelectedListener
                                return "Components";\r
                        case 2:\r
                                return "Simulations";\r
+                       case 3:\r
+                               return "Configurations";\r
                        }\r
                        return null;\r
                }\r
diff --git a/android/src/net/sf/openrocket/android/simulation/SimulationRunActivity.java b/android/src/net/sf/openrocket/android/simulation/SimulationRunActivity.java
new file mode 100644 (file)
index 0000000..a8e3b18
--- /dev/null
@@ -0,0 +1,46 @@
+package net.sf.openrocket.android.simulation;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.ActivityHelpers;\r
+import android.os.Bundle;\r
+import android.support.v4.app.Fragment;\r
+import android.support.v4.app.FragmentActivity;\r
+import android.support.v4.app.FragmentTransaction;\r
+import android.view.Menu;\r
+import android.view.MenuItem;\r
+\r
+/**\r
+ * An activity that encapsulates a graphical view of the chart.\r
+ */\r
+public class SimulationRunActivity extends FragmentActivity {\r
+\r
+       @Override\r
+       protected void onCreate(Bundle savedInstanceState) {\r
+               super.onCreate(savedInstanceState);\r
+               int simulationNumber = getIntent().getIntExtra("Simulation", -1);\r
+\r
+               Fragment graph = SimulationRunFragment.newInstance(simulationNumber);\r
+\r
+               FragmentTransaction ft = getSupportFragmentManager().beginTransaction();\r
+               ft.replace(android.R.id.content, graph);\r
+               ft.commit();\r
+       }\r
+\r
+       @Override\r
+       public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
+               switch (item.getItemId()) {\r
+               case R.id.preference_menu_option:\r
+                       ActivityHelpers.startPreferences(this);\r
+                       return true;\r
+               }\r
+               return super.onMenuItemSelected(featureId, item);\r
+       }\r
+\r
+       @Override\r
+       public boolean onCreateOptionsMenu(Menu menu) {\r
+               MenuItem prefItem = menu.add(Menu.NONE, R.id.preference_menu_option, Menu.CATEGORY_SYSTEM, R.string.Preferences);\r
+               prefItem.setIcon(R.drawable.ic_menu_preferences);\r
+               return true;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/android/src/net/sf/openrocket/android/simulation/SimulationRunFragment.java b/android/src/net/sf/openrocket/android/simulation/SimulationRunFragment.java
new file mode 100644 (file)
index 0000000..758b23e
--- /dev/null
@@ -0,0 +1,90 @@
+\r
+package net.sf.openrocket.android.simulation;\r
+\r
+import net.sf.openrocket.R;\r
+import net.sf.openrocket.android.Application;\r
+import net.sf.openrocket.android.rocket.MotorConfigSpinnerAdapter;\r
+import net.sf.openrocket.document.OpenRocketDocument;\r
+import net.sf.openrocket.document.Simulation;\r
+import net.sf.openrocket.unit.UnitGroup;\r
+import android.os.Bundle;\r
+import android.support.v4.app.DialogFragment;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.EditText;\r
+import android.widget.Spinner;\r
+\r
+/**\r
+ * An activity that encapsulates a graphical view of the chart.\r
+ */\r
+public class SimulationRunFragment extends DialogFragment {\r
+       \r
+       int simulationId;\r
+\r
+       EditText windspeedField;\r
+       EditText rodlengthField;\r
+       EditText rodangleField;\r
+       Spinner motorSpinner;\r
+\r
+       public static SimulationRunFragment newInstance( int simulationId ) {\r
+               SimulationRunFragment frag = new SimulationRunFragment();\r
+               Bundle b = new Bundle();\r
+               b.putInt("simulationId", simulationId);\r
+               frag.setArguments(b);\r
+               return frag;\r
+       }\r
+\r
+       @Override\r
+       public void onCreate(Bundle savedInstanceState) {\r
+               super.onCreate(savedInstanceState);\r
+               setStyle(DialogFragment.STYLE_NO_TITLE,getTheme());\r
+\r
+               if ( savedInstanceState != null ) {\r
+                       simulationId = savedInstanceState.getInt("simulationId");\r
+               } else {\r
+                       Bundle b = getArguments();\r
+                       simulationId = b.getInt("simulationId");\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
+                       Bundle savedInstanceState) {\r
+               View v = inflater.inflate(R.layout.simulation_condition_dialog, container, false);\r
+               windspeedField = (EditText) v.findViewById(R.id.simulation_condition_windspeed);\r
+               rodlengthField = (EditText) v.findViewById(R.id.simulation_condition_rodlength);\r
+               rodangleField = (EditText) v.findViewById(R.id.simulation_condition_rodangle);\r
+               \r
+               motorSpinner = (Spinner) v.findViewById(R.id.simulationConditionConfigurationSpinner);\r
+               \r
+               OpenRocketDocument rocketDocument = ((Application)getActivity().getApplication()).getRocketDocument();\r
+\r
+               Simulation sim = rocketDocument.getSimulation(simulationId);\r
+               \r
+               windspeedField.setText( UnitGroup.UNITS_VELOCITY.toString(sim.getSimulatedConditions().getWindSpeedAverage()) );\r
+               rodlengthField.setText( UnitGroup.UNITS_LENGTH.toString(sim.getSimulatedConditions().getLaunchRodLength()));\r
+               rodangleField.setText( String.valueOf( sim.getSimulatedConditions().getLaunchRodLength() ));\r
+\r
+               MotorConfigSpinnerAdapter spinnerAdapter = new MotorConfigSpinnerAdapter(getActivity(),rocketDocument.getRocket());\r
+               motorSpinner.setAdapter(spinnerAdapter);\r
+               /* TODO - enable saving.\r
+               ((Button) v.findViewById(R.id.motorDetailsSaveButton)).setOnClickListener(\r
+                               new View.OnClickListener() {\r
+                                       @Override\r
+                                       public void onClick(View v) {\r
+                                               MotorDetailsFragment.this.saveChanges();\r
+                                       }\r
+                               });\r
+                               */\r
+               return v;\r
+       }\r
+\r
+       @Override\r
+       public void onSaveInstanceState(Bundle outState) {\r
+               super.onSaveInstanceState(outState);\r
+               outState.putInt("simulationId", simulationId);\r
+\r
+       }\r
+       \r
+}
\ No newline at end of file
diff --git a/android/src/net/sf/openrocket/android/util/PersistentExpandableListView.java b/android/src/net/sf/openrocket/android/util/PersistentExpandableListView.java
new file mode 100644 (file)
index 0000000..a22c586
--- /dev/null
@@ -0,0 +1,89 @@
+package net.sf.openrocket.android.util;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import android.content.Context;\r
+import android.os.Bundle;\r
+import android.os.Parcelable;\r
+import android.util.AttributeSet;\r
+import android.widget.ExpandableListAdapter;\r
+import android.widget.ExpandableListView;\r
+\r
+public class PersistentExpandableListView extends ExpandableListView {\r
+\r
+       public PersistentExpandableListView(Context context, AttributeSet attrs,\r
+                       int defStyle) {\r
+               super(context, attrs, defStyle);\r
+       }\r
+\r
+       public PersistentExpandableListView(Context context, AttributeSet attrs) {\r
+               super(context, attrs);\r
+       }\r
+\r
+       public PersistentExpandableListView(Context context) {\r
+               super(context);\r
+       }\r
+\r
+       @Override\r
+       public Parcelable onSaveInstanceState() {\r
+               Bundle b = new Bundle();\r
+               long[] expandedIds = getExpandedIds();\r
+               b.putLongArray("ExpandedIds", expandedIds);\r
+               return b;\r
+       }\r
+\r
+       @Override\r
+       public void onRestoreInstanceState(Parcelable state) {\r
+               Bundle b = (Bundle) state;\r
+               long[] expandedIds = b.getLongArray("ExpandedIds");\r
+               restoreExpandedState(expandedIds);\r
+       }\r
+\r
+       private long[] getExpandedIds() {\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(this.isGroupExpanded(i)) {\r
+                                       expandedIds.add(adapter.getGroupId(i));\r
+                               }\r
+                       }\r
+                       return toLongArray(expandedIds);\r
+               } else {\r
+                       return null;\r
+               }\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
+       private void restoreExpandedState(long[] expandedIds) {\r
+               if (expandedIds != null) {\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)) this.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
+\r
+}\r