diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 6ae3d51fd..e0b9dba35 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -27,7 +27,7 @@ @@ -61,6 +61,9 @@ android:scheme="file" /> + @@ -68,16 +71,12 @@ - + - + - + \ No newline at end of file diff --git a/android/res/drawable/ic_menu_preferences.png b/android/res/drawable/ic_menu_preferences.png new file mode 100644 index 000000000..b8e71412d Binary files /dev/null and b/android/res/drawable/ic_menu_preferences.png differ diff --git a/android/res/drawable/or_launcher.png b/android/res/drawable/or_launcher.png index c2170d358..77464db04 100644 Binary files a/android/res/drawable/or_launcher.png and b/android/res/drawable/or_launcher.png differ diff --git a/android/res/layout/openrocketviewer.xml b/android/res/layout/openrocketviewer.xml index 25d7d9b42..efb2b6be5 100644 --- a/android/res/layout/openrocketviewer.xml +++ b/android/res/layout/openrocketviewer.xml @@ -1,144 +1,33 @@ - + android:layout_height="match_parent"> - + android:layout_height="match_parent"> - + android:layout_height="wrap_content" + android:layout_weight="0"/> - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/android/res/layout/rocket_component.xml b/android/res/layout/rocket_component.xml new file mode 100644 index 000000000..40c3ba2cd --- /dev/null +++ b/android/res/layout/rocket_component.xml @@ -0,0 +1,7 @@ + + diff --git a/android/res/layout/rocket_overview.xml b/android/res/layout/rocket_overview.xml new file mode 100644 index 000000000..7eca8962d --- /dev/null +++ b/android/res/layout/rocket_overview.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/res/layout/rocket_simulations.xml b/android/res/layout/rocket_simulations.xml new file mode 100644 index 000000000..e856d1e97 --- /dev/null +++ b/android/res/layout/rocket_simulations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/android/res/menu/main_menu.xml b/android/res/menu/main_menu.xml new file mode 100644 index 000000000..f378ed0f9 --- /dev/null +++ b/android/res/menu/main_menu.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/android/res/menu/rocket_viewer_option_menu.xml b/android/res/menu/rocket_viewer_option_menu.xml index 6d4f5c6f4..4ebd72d47 100644 --- a/android/res/menu/rocket_viewer_option_menu.xml +++ b/android/res/menu/rocket_viewer_option_menu.xml @@ -1,8 +1,12 @@ - - - - + + + \ No newline at end of file diff --git a/android/res/values/pref_strings.xml b/android/res/values/pref_strings.xml new file mode 100644 index 000000000..5bf182126 --- /dev/null +++ b/android/res/values/pref_strings.xml @@ -0,0 +1,54 @@ + + + + PreferenceMotorBrowserGroupingOption + + PreferenceUseInternalFileBrowserOpion + + + 0 + 1 + 2 + 3 + + + PreferenceUnitLengthOption + + + mm + cm + m + in + ft + + + PreferenceUnitMassOption + + + g + kg + oz + lb + + + PreferenceUnitVelocityOption + + + m/s + km/h + ft/s + mph + + + PreferenceUnitDistanceOption + + + m + km + ft + yd + mi + nmi + + + \ No newline at end of file diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 5d7b232f0..eeb1b4944 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -4,7 +4,7 @@ OpenRocket Save Motor List - PreferenceMotorBrowserGroupingOption + Preferences Case @@ -12,12 +12,6 @@ Impulse Manufacturer - - 0 - 1 - 2 - 3 - Impulse @@ -96,8 +90,11 @@ Download from ThrustCurve Series 1 Series 2 - PreferenceUnitLengthOption + Motor Browser Grouping + Use Internal File Browser + uncheck to use system file browser if available + Millimeters Centimeters @@ -105,46 +102,18 @@ Inches Feet - - mm - cm - m - in - ft - - - PreferenceUnitMassOption - Grams Kilograms Ounces Pounds - - g - kg - oz - lb - - - PreferenceUnitVelocityOption - Meters/Second Kilometers/Hour Feet/Second Miles/Hour - - m/s - km/h - ft/s - mph - - - PreferenceUnitDistanceOption - Meters Kilometers @@ -153,13 +122,5 @@ Miles Nautical Miles - - m - km - ft - yd - mi - nmi - \ No newline at end of file diff --git a/android/res/xml/preferences.xml b/android/res/xml/preferences.xml index d229d6efc..77b1cdefb 100644 --- a/android/res/xml/preferences.xml +++ b/android/res/xml/preferences.xml @@ -1,50 +1,55 @@ - android:key="preferences" android:title="Pref Title" android:summary="pref summary" - - + android:title="@string/motorbrowsergrouptitle" /> - - - - - + + + + + + + + \ No newline at end of file diff --git a/android/src/net/sf/openrocket/android/ActivityHelpers.java b/android/src/net/sf/openrocket/android/ActivityHelpers.java new file mode 100644 index 000000000..bc6db510b --- /dev/null +++ b/android/src/net/sf/openrocket/android/ActivityHelpers.java @@ -0,0 +1,21 @@ +package net.sf.openrocket.android; + +import net.sf.openrocket.android.motor.MotorHierarchicalBrowser; +import android.app.Activity; +import android.content.Intent; + +public abstract class ActivityHelpers { + + + public static void browseMotors( Activity parent ) { + Intent i = new Intent(parent, MotorHierarchicalBrowser.class); + parent.startActivity(i); + + } + + public static void startPreferences( Activity parent ) { + Intent intent = new Intent(parent, PreferencesActivity.class); + parent.startActivity(intent); + + } +} diff --git a/android/src/net/sf/openrocket/android/Main.java b/android/src/net/sf/openrocket/android/Main.java index cdb7366a0..ff5fd8deb 100644 --- a/android/src/net/sf/openrocket/android/Main.java +++ b/android/src/net/sf/openrocket/android/Main.java @@ -2,15 +2,20 @@ package net.sf.openrocket.android; import net.sf.openrocket.R; import net.sf.openrocket.android.filebrowser.SimpleFileBrowser; -import net.sf.openrocket.android.motor.MotorHierarchicalBrowser; -import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; -public class Main extends Activity { +public class Main extends FragmentActivity { private static final int PICK_ORK_FILE_RESULT = 1; @@ -21,6 +26,29 @@ public class Main extends Activity { setContentView(R.layout.main); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch( item.getItemId() ) { + case R.id.main_menu_motor: + ActivityHelpers.browseMotors(this); + return true; + case R.id.main_menu_open: + pickOrkFiles(); + return true; + case R.id.main_menu_preferences: + ActivityHelpers.startPreferences(this); + return true; + } + return super.onOptionsItemSelected(item); + } + /* (non-Javadoc) * @see android.app.Activity#onActivityResult(int, int, android.content.Intent) */ @@ -39,21 +67,37 @@ public class Main extends Activity { super.onActivityResult(requestCode, resultCode, data); } - public void pickOrkFiles( View v ) { - try { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("file/*"); - startActivityForResult(intent,PICK_ORK_FILE_RESULT); - } catch ( ActivityNotFoundException ex ) { - // No activity for ACTION_GET_CONTENT use internal file browser + private void pickOrkFiles( ) { + Resources resources = this.getResources(); + String key = resources.getString(R.string.PreferenceUseInternalFileBrowserOption); + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); + + boolean useinternalbrowser = pref.getBoolean(key, false); + + if ( useinternalbrowser ) { Intent intent = new Intent(Main.this, SimpleFileBrowser.class); startActivityForResult(intent,PICK_ORK_FILE_RESULT); - } + } else { + try { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("file/*"); + startActivityForResult(intent,PICK_ORK_FILE_RESULT); + } catch ( ActivityNotFoundException ex ) { + // No activity for ACTION_GET_CONTENT use internal file browser + // update the preference value. + pref.edit().putBoolean(key, false).commit(); + // fire our browser + Intent intent = new Intent(Main.this, SimpleFileBrowser.class); + startActivityForResult(intent,PICK_ORK_FILE_RESULT); + } + } + } + public void pickOrkFiles( View v ) { + pickOrkFiles(); } public void browseMotors( View v ) { - Intent i = new Intent(Main.this, MotorHierarchicalBrowser.class); - startActivity(i); + ActivityHelpers.browseMotors(this); } } diff --git a/android/src/net/sf/openrocket/android/PreferencesActivity.java b/android/src/net/sf/openrocket/android/PreferencesActivity.java index 5b14bf23f..9680c9e85 100644 --- a/android/src/net/sf/openrocket/android/PreferencesActivity.java +++ b/android/src/net/sf/openrocket/android/PreferencesActivity.java @@ -52,5 +52,13 @@ implements SharedPreferences.OnSharedPreferenceChangeListener { UnitGroup.UNITS_DISTANCE.setDefaultUnit( distance ); } + + @Override + protected void onStop() { + initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this)); + super.onStop(); + } + + } diff --git a/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java b/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java index 96ff0845b..493737627 100644 --- a/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java +++ b/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java @@ -42,12 +42,6 @@ public class BurnPlotFragment extends Fragment implements OnTouchListener { private ScaleGestureDetector mScaleDetector; private float mScaleFactor = 1.f; - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - Log.d(TAG,"onAttach"); - } - @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG,"onCreate"); diff --git a/android/src/net/sf/openrocket/android/rocket/Component.java b/android/src/net/sf/openrocket/android/rocket/Component.java new file mode 100644 index 000000000..a19f2e7c6 --- /dev/null +++ b/android/src/net/sf/openrocket/android/rocket/Component.java @@ -0,0 +1,76 @@ +package net.sf.openrocket.android.rocket; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.Application; +import net.sf.openrocket.android.rocket.RocketComponentTreeAdapter.RocketComponentWithId; +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import pl.polidea.treeview.InMemoryTreeStateManager; +import pl.polidea.treeview.TreeBuilder; +import pl.polidea.treeview.TreeStateManager; +import pl.polidea.treeview.TreeViewList; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; + +public class Component extends Fragment { + + private TreeViewList componentTree; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.rocket_component, container, false); + componentTree = (TreeViewList) v.findViewById(R.id.openrocketviewerComponentTree); + + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final OpenRocketDocument rocketDocument = ((Application)getActivity().getApplication()).getRocketDocument(); + componentTree.setAdapter( buildAdapter( rocketDocument.getRocket() ) ); + } + + private ListAdapter buildAdapter( Rocket rocket ) { + + TreeStateManager manager = new InMemoryTreeStateManager(); + TreeBuilder treeBuilder = new TreeBuilder(manager); + + int depth = buildRecursive( rocket, treeBuilder, 0 ); + return new RocketComponentTreeAdapter(this.getActivity(), manager, depth+1); + } + + long id = 0; + private int buildRecursive( RocketComponent comp, TreeBuilder builder, int depth ) { + + + int maxDepth = depth; + + RocketComponentWithId rcid = new RocketComponentWithId(comp, id++); + + // Add this component. + builder.sequentiallyAddNextNode(rcid, depth); + + if ( comp.allowsChildren() ) { + + for( RocketComponent child : comp.getChildren() ) { + int childDepth = buildRecursive( child, builder, depth+1); + if ( childDepth > maxDepth) { + maxDepth = childDepth; + } + } + + } + + return maxDepth; + } + + +} diff --git a/android/src/net/sf/openrocket/android/rocket/OpenRocketLoader.java b/android/src/net/sf/openrocket/android/rocket/OpenRocketLoader.java new file mode 100644 index 000000000..ee35ba00d --- /dev/null +++ b/android/src/net/sf/openrocket/android/rocket/OpenRocketLoader.java @@ -0,0 +1,79 @@ +package net.sf.openrocket.android.rocket; + +import java.io.File; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.Application; +import net.sf.openrocket.document.OpenRocketDocument; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +public class OpenRocketLoader extends FragmentActivity { + private static final String TAG = "OpenRocketLoader"; + + private ProgressDialog progress; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + Intent i = getIntent(); + Uri file = i.getData(); + loadOrkFile(file); + } + + @Override + protected void onDestroy() { + if ( progress != null ) { + if ( progress.isShowing() ) { + progress.dismiss(); + } + progress = null; + } + super.onDestroy(); + } + + private void loadOrkFile( Uri file ) { + Log.d(TAG,"Use ork file: " + file); + String path = file.getPath(); + File orkFile = new File(path); + progress = ProgressDialog.show(this, "Loading file", ""); + + final OpenRocketLoaderTask task = new OpenRocketLoaderTask() { + + /* (non-Javadoc) + * @see android.os.AsyncTask#onPostExecute(java.lang.Object) + */ + @Override + protected void onPostExecute(OpenRocketDocument result) { + super.onPostExecute(result); + ((Application)OpenRocketLoader.this.getApplication()).setRocketDocument( result ); + Log.d(TAG,"Finished loading " + OpenRocketLoader.this); + finishedLoading(); + } + + }; + + task.execute(orkFile); + + } + + private void finishedLoading() { + if ( progress.isShowing() ) { + progress.dismiss(); + } + + Intent i = new Intent(this,OpenRocketViewer.class); + startActivity(i); + finish(); + } + + +} diff --git a/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java b/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java index 6985c9348..a79beb6e3 100644 --- a/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java +++ b/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java @@ -1,89 +1,42 @@ package net.sf.openrocket.android.rocket; -import java.io.File; - import net.sf.openrocket.R; -import net.sf.openrocket.aerodynamics.AerodynamicCalculator; -import net.sf.openrocket.aerodynamics.BarrowmanCalculator; -import net.sf.openrocket.aerodynamics.FlightConditions; -import net.sf.openrocket.aerodynamics.WarningSet; +import net.sf.openrocket.android.ActivityHelpers; import net.sf.openrocket.android.Application; -import net.sf.openrocket.android.PreferencesActivity; -import net.sf.openrocket.android.motor.MotorHierarchicalBrowser; -import net.sf.openrocket.android.rocket.RocketComponentTreeAdapter.RocketComponentWithId; -import net.sf.openrocket.android.simulation.SimulationViewer; +import net.sf.openrocket.android.util.TabsAdapter; import net.sf.openrocket.document.OpenRocketDocument; -import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.masscalc.BasicMassCalculator; -import net.sf.openrocket.masscalc.MassCalculator; -import net.sf.openrocket.masscalc.MassCalculator.MassCalcType; import net.sf.openrocket.rocketcomponent.Configuration; -import net.sf.openrocket.rocketcomponent.Rocket; -import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.rocketcomponent.RocketUtils; -import net.sf.openrocket.unit.Unit; -import net.sf.openrocket.unit.UnitGroup; -import net.sf.openrocket.util.Coordinate; -import pl.polidea.treeview.InMemoryTreeStateManager; -import pl.polidea.treeview.TreeBuilder; -import pl.polidea.treeview.TreeStateManager; -import pl.polidea.treeview.TreeViewList; -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; import android.content.SharedPreferences; -import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; +import android.support.v4.view.ViewPager; import android.util.Log; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.Spinner; import android.widget.TabHost; -import android.widget.TextView; -public class OpenRocketViewer extends Activity +public class OpenRocketViewer extends FragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "OpenRocketViewer"; - private ProgressDialog progress; - - private Spinner configurationSpinner; - private TreeViewList componentTree; - private ListView simulationList; - - /* Calculation of CP and CG */ - private AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator(); - private MassCalculator massCalculator = new BasicMassCalculator(); - OpenRocketDocument rocketDocument; Configuration rocketConfiguration; private Application app; - private final static int PICK_ORK_FILE_RESULT = 1; + TabHost mTabHost; + ViewPager mViewPager; + TabsAdapter mTabsAdapter; - /* (non-Javadoc) - * @see android.app.Activity#onCreate(android.os.Bundle) - */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Log.d(TAG,"In onCreate"); - app = (Application) this.getApplication(); setContentView(R.layout.openrocketviewer); @@ -91,89 +44,29 @@ implements SharedPreferences.OnSharedPreferenceChangeListener SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); - TabHost tabs=(TabHost)findViewById(R.id.openrocketviewerTabHost); + mTabHost = (TabHost)findViewById(android.R.id.tabhost); + mTabHost.setup(); - tabs.setup(); + mViewPager = (ViewPager)findViewById(R.id.pager); - TabHost.TabSpec spec=tabs.newTabSpec("tag1"); + mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); - spec.setContent(R.id.openrocketviewerOverview); - spec.setIndicator("Overview"); - tabs.addTab(spec); + mTabsAdapter.addTab(mTabHost.newTabSpec("overview").setIndicator("Overview"), + Overview.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("components").setIndicator("Components"), + Component.class, null); + mTabsAdapter.addTab(mTabHost.newTabSpec("simulations").setIndicator("Simulations"), + Simulations.class, null); - spec=tabs.newTabSpec("tag2"); - spec.setContent(R.id.openrocketviewerComponentTree); - spec.setIndicator("Components"); - tabs.addTab(spec); - - spec=tabs.newTabSpec("tag3"); - spec.setContent(R.id.openrocketviewerSimulationList); - spec.setIndicator("Simulations"); - tabs.addTab(spec); - - configurationSpinner = (Spinner) findViewById(R.id.openrocketviewerConfigurationSpinner); - componentTree = (TreeViewList) findViewById(R.id.openrocketviewerComponentTree); - simulationList = (ListView) findViewById(R.id.openrocketviewerSimulationList); - - Intent i = getIntent(); - Uri file = i.getData(); - - if ( file == null ) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("file/*"); - startActivityForResult(intent,PICK_ORK_FILE_RESULT); - - } else { - loadOrkFile(file); + if (savedInstanceState != null) { + mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); } } @Override - protected void onDestroy() { - if ( progress != null ) { - if ( progress.isShowing() ) { - progress.dismiss(); - } - progress = null; - } - super.onDestroy(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // TODO Auto-generated method stub - switch(requestCode){ - case PICK_ORK_FILE_RESULT: - if(resultCode==RESULT_OK){ - Uri file = data.getData(); - loadOrkFile(file); - } - break; - } - } - - private void loadOrkFile( Uri file ) { - Log.d(TAG,"Use ork file: " + file); - String path = file.getPath(); - File orkFile = new File(path); - progress = ProgressDialog.show(this, "Loading file", ""); - - final OpenRocketLoaderTask task = new OpenRocketLoaderTask() { - - /* (non-Javadoc) - * @see android.os.AsyncTask#onPostExecute(java.lang.Object) - */ - @Override - protected void onPostExecute(OpenRocketDocument result) { - super.onPostExecute(result); - app.setRocketDocument( result ); - updateContents(); - } - - }; - - task.execute(orkFile); - + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("tab", mTabHost.getCurrentTabTag()); } /* (non-Javadoc) @@ -182,115 +75,7 @@ implements SharedPreferences.OnSharedPreferenceChangeListener @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // just in case the user changed the units, we redraw. - PreferencesActivity.initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this)); - updateContents(); - } - - private void updateContents() { - - rocketDocument = app.getRocketDocument(); - rocketConfiguration = rocketDocument.getDefaultConfiguration(); - Rocket rocket = rocketDocument.getRocket(); - - setTitle(rocket.getName()); - - String[] motorConfigs = rocket.getMotorConfigurationIDs(); - ArrayAdapter spinnerAdapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item); - for( String config: motorConfigs ) { - spinnerAdapter.add(rocket.getMotorConfigurationNameOrDescription(config)); - } - - configurationSpinner.setAdapter(spinnerAdapter); - configurationSpinner.setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() { - - /* (non-Javadoc) - * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long) - */ - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int arg2, long arg3) { - - String selectedConfigId = rocketDocument.getRocket().getMotorConfigurationIDs()[arg2]; - rocketConfiguration.setMotorConfigurationID(selectedConfigId); - Coordinate cp = aerodynamicCalculator.getWorstCP(rocketConfiguration, - new FlightConditions(rocketConfiguration), - new WarningSet()); - - Coordinate cg = massCalculator.getCG(rocketConfiguration, MassCalcType.LAUNCH_MASS); - - Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit(); - Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit(); - Unit stabilityUnit = UnitGroup.stabilityUnits(rocketConfiguration).getDefaultUnit(); - - ((TextView)findViewById(R.id.openrocketviewerCP)).setText(lengthUnit.toStringUnit(cp.x)); - ((TextView)findViewById(R.id.openrocketviewerCG)).setText(lengthUnit.toStringUnit(cg.x)); - ((TextView)findViewById(R.id.openrocketviewerLiftOffWeight)).setText(massUnit.toStringUnit(cg.weight)); - ((TextView)findViewById(R.id.openrocketviewerStabilityMargin)).setText(stabilityUnit.toStringUnit(cp.x-cg.x)); - - } - - /* (non-Javadoc) - * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView) - */ - @Override - public void onNothingSelected(AdapterView arg0) { - ((TextView)findViewById(R.id.openrocketviewerCP)).setText(""); - ((TextView)findViewById(R.id.openrocketviewerCG)).setText(""); - ((TextView)findViewById(R.id.openrocketviewerLiftOffWeight)).setText(""); - ((TextView)findViewById(R.id.openrocketviewerStabilityMargin)).setText(""); - } - - }); - - Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit(); - Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit(); - - Coordinate cg = RocketUtils.getCG(rocket, MassCalcType.NO_MOTORS); - double length = RocketUtils.getLength(rocket); - ((TextView)findViewById(R.id.openrocketviewerDesigner)).setText(rocket.getDesigner()); - ((TextView)findViewById(R.id.openrocketviewerLength)).setText(lengthUnit.toStringUnit(length)); - ((TextView)findViewById(R.id.openrocketviewerMass)).setText(massUnit.toStringUnit(cg.weight)); - ((TextView)findViewById(R.id.openrocketviewerStageCount)).setText(String.valueOf(rocket.getStageCount())); - - - ArrayAdapter sims = new ArrayAdapter(this,android.R.layout.simple_list_item_2,rocketDocument.getSimulations()) { - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if ( v == null ) { - LayoutInflater li = getLayoutInflater(); - v = li.inflate(android.R.layout.simple_list_item_2,null); - } - Simulation sim = this.getItem(position); - ((TextView)v.findViewById(android.R.id.text1)).setText( sim.getName() ); - StringBuilder sb = new StringBuilder(); - sb.append("motors: ").append(sim.getConfiguration().getMotorConfigurationDescription()); - Unit distanceUnit = UnitGroup.UNITS_DISTANCE.getDefaultUnit(); - sb.append(" apogee: ").append( distanceUnit.toStringUnit(sim.getSimulatedData().getMaxAltitude())); - sb.append(" time: ").append(sim.getSimulatedData().getFlightTime()).append("s"); - ((TextView)v.findViewById(android.R.id.text2)).setText( sb.toString() ); - return v; - } - - }; - simulationList.setOnItemClickListener( new OnItemClickListener() { - @Override - public void onItemClick(AdapterView l, View v, int position, long id) { - Intent i = new Intent(OpenRocketViewer.this, SimulationViewer.class); - Log.d(TAG,"onItemClick simulation number " + id ); - i.putExtra("Simulation",(int)id); - startActivity(i); - } - - }); - simulationList.setAdapter(sims); - - componentTree.setAdapter( buildAdapter( rocket ) ); - - if ( progress.isShowing() ) { - progress.dismiss(); - } + // TODO = updateContents(); redraw all children.. } @Override @@ -300,73 +85,32 @@ implements SharedPreferences.OnSharedPreferenceChangeListener return true; } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch ( item.getItemId() ) { + /* case android.R.id.home: + Intent i = new Intent( this, Main.class ); + i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(i); + return true; + */ + default: + return super.onOptionsItemSelected(item); + } + } + @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { Log.d(TAG,"onMenuItemSelected" + item.getItemId()); switch(item.getItemId()) { case R.id.motor_list_menu_option: - startMotorBrowser(); + ActivityHelpers.browseMotors(this); return true; case R.id.preference_menu_option: - Intent intent = new Intent().setClass(this, PreferencesActivity.class); - this.startActivity(intent); + ActivityHelpers.startPreferences(this); return true; } return super.onMenuItemSelected(featureId, item); } - public void startMotorBrowser() { - Log.d(TAG,"motorBrowserButton clicked"); - Intent i = new Intent(OpenRocketViewer.this, MotorHierarchicalBrowser.class); - startActivity(i); - } - - private ListAdapter buildAdapter( Rocket rocket ) { - /* - final int[] DEMO_NODES = new int[] { 0, 0, 1, 1, 1, 2, 2, 1, - 1, 2, 1, 0, 0, 0, 1, 2, 3, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1 }; - final int LEVEL_NUMBER = 4; - - TreeStateManager manager = new InMemoryTreeStateManager(); - final TreeBuilder treeBuilder = new TreeBuilder(manager); - for (int i = 0; i < DEMO_NODES.length; i++) { - treeBuilder.sequentiallyAddNextNode((long) i, DEMO_NODES[i]); - } - - return new SimpleStandardAdapter(this, manager, LEVEL_NUMBER); - */ - - TreeStateManager manager = new InMemoryTreeStateManager(); - TreeBuilder treeBuilder = new TreeBuilder(manager); - - int depth = buildRecursive( rocket, treeBuilder, 0 ); - return new RocketComponentTreeAdapter(this, manager, depth+1); - } - - long id = 0; - private int buildRecursive( RocketComponent comp, TreeBuilder builder, int depth ) { - - - int maxDepth = depth; - - RocketComponentWithId rcid = new RocketComponentWithId(comp, id++); - - // Add this component. - builder.sequentiallyAddNextNode(rcid, depth); - - if ( comp.allowsChildren() ) { - - for( RocketComponent child : comp.getChildren() ) { - int childDepth = buildRecursive( child, builder, depth+1); - if ( childDepth > maxDepth) { - maxDepth = childDepth; - } - } - - } - - return maxDepth; - } - - } diff --git a/android/src/net/sf/openrocket/android/rocket/Overview.java b/android/src/net/sf/openrocket/android/rocket/Overview.java new file mode 100644 index 000000000..69a35ef7c --- /dev/null +++ b/android/src/net/sf/openrocket/android/rocket/Overview.java @@ -0,0 +1,123 @@ +package net.sf.openrocket.android.rocket; + +import net.sf.openrocket.R; +import net.sf.openrocket.aerodynamics.AerodynamicCalculator; +import net.sf.openrocket.aerodynamics.BarrowmanCalculator; +import net.sf.openrocket.aerodynamics.FlightConditions; +import net.sf.openrocket.aerodynamics.WarningSet; +import net.sf.openrocket.android.Application; +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.masscalc.BasicMassCalculator; +import net.sf.openrocket.masscalc.MassCalculator; +import net.sf.openrocket.masscalc.MassCalculator.MassCalcType; +import net.sf.openrocket.rocketcomponent.Configuration; +import net.sf.openrocket.rocketcomponent.Rocket; +import net.sf.openrocket.rocketcomponent.RocketUtils; +import net.sf.openrocket.unit.Unit; +import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.Coordinate; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Spinner; +import android.widget.TextView; + +public class Overview extends Fragment { + + /* Calculation of CP and CG */ + private AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator(); + private MassCalculator massCalculator = new BasicMassCalculator(); + + private Spinner configurationSpinner; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + Log.d("Overview", "Created View"); + View v = inflater.inflate(R.layout.rocket_overview, container, false); + configurationSpinner = (Spinner) v.findViewById(R.id.openrocketviewerConfigurationSpinner); + + return v; + } + + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final OpenRocketDocument rocketDocument = ((Application)getActivity().getApplication()).getRocketDocument(); + final Configuration rocketConfiguration = rocketDocument.getDefaultConfiguration(); + Rocket rocket = rocketDocument.getRocket(); + + String[] motorConfigs = rocket.getMotorConfigurationIDs(); + ArrayAdapter spinnerAdapter = new ArrayAdapter(getActivity(),android.R.layout.simple_spinner_item); + for( String config: motorConfigs ) { + spinnerAdapter.add(rocket.getMotorConfigurationNameOrDescription(config)); + } + + Log.d("Overview", "spinnerAdapter = " + spinnerAdapter); + Log.d("Overview", "configurationSpinner = " + configurationSpinner); + + configurationSpinner.setAdapter(spinnerAdapter); + configurationSpinner.setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() { + + /* (non-Javadoc) + * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long) + */ + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int arg2, long arg3) { + + String selectedConfigId = rocketDocument.getRocket().getMotorConfigurationIDs()[arg2]; + rocketConfiguration.setMotorConfigurationID(selectedConfigId); + Coordinate cp = aerodynamicCalculator.getWorstCP(rocketConfiguration, + new FlightConditions(rocketConfiguration), + new WarningSet()); + + Coordinate cg = massCalculator.getCG(rocketConfiguration, MassCalcType.LAUNCH_MASS); + + Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit(); + Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit(); + Unit stabilityUnit = UnitGroup.stabilityUnits(rocketConfiguration).getDefaultUnit(); + + ((TextView)getActivity().findViewById(R.id.openrocketviewerCP)).setText(lengthUnit.toStringUnit(cp.x)); + ((TextView)getActivity().findViewById(R.id.openrocketviewerCG)).setText(lengthUnit.toStringUnit(cg.x)); + ((TextView)getActivity().findViewById(R.id.openrocketviewerLiftOffWeight)).setText(massUnit.toStringUnit(cg.weight)); + ((TextView)getActivity().findViewById(R.id.openrocketviewerStabilityMargin)).setText(stabilityUnit.toStringUnit(cp.x-cg.x)); + + } + + /* (non-Javadoc) + * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView) + */ + @Override + public void onNothingSelected(AdapterView arg0) { + ((TextView)getActivity().findViewById(R.id.openrocketviewerCP)).setText(""); + ((TextView)getActivity().findViewById(R.id.openrocketviewerCG)).setText(""); + ((TextView)getActivity().findViewById(R.id.openrocketviewerLiftOffWeight)).setText(""); + ((TextView)getActivity().findViewById(R.id.openrocketviewerStabilityMargin)).setText(""); + } + + }); + + Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit(); + Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit(); + + Coordinate cg = RocketUtils.getCG(rocket, MassCalcType.NO_MOTORS); + double length = RocketUtils.getLength(rocket); + ((TextView)getActivity().findViewById(R.id.openrocketviewerDesigner)).setText(rocket.getDesigner()); + ((TextView)getActivity().findViewById(R.id.openrocketviewerLength)).setText(lengthUnit.toStringUnit(length)); + ((TextView)getActivity().findViewById(R.id.openrocketviewerMass)).setText(massUnit.toStringUnit(cg.weight)); + ((TextView)getActivity().findViewById(R.id.openrocketviewerStageCount)).setText(String.valueOf(rocket.getStageCount())); + + + } + + +} diff --git a/android/src/net/sf/openrocket/android/rocket/Simulations.java b/android/src/net/sf/openrocket/android/rocket/Simulations.java new file mode 100644 index 000000000..231c50da1 --- /dev/null +++ b/android/src/net/sf/openrocket/android/rocket/Simulations.java @@ -0,0 +1,77 @@ +package net.sf.openrocket.android.rocket; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.Application; +import net.sf.openrocket.android.simulation.SimulationViewer; +import net.sf.openrocket.document.OpenRocketDocument; +import net.sf.openrocket.document.Simulation; +import net.sf.openrocket.unit.Unit; +import net.sf.openrocket.unit.UnitGroup; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +public class Simulations extends Fragment { + + private ListView simulationList; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.rocket_simulations, container, false); + simulationList = (ListView) v.findViewById(R.id.openrocketviewerSimulationList); + + return v; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final OpenRocketDocument rocketDocument = ((Application)getActivity().getApplication()).getRocketDocument(); + Log.d("sim","activity = " + this.getActivity()); + + ArrayAdapter sims = new ArrayAdapter(this.getActivity(),android.R.layout.simple_list_item_2,rocketDocument.getSimulations()) { + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View v = convertView; + if ( v == null ) { + LayoutInflater li = getActivity().getLayoutInflater(); + v = li.inflate(android.R.layout.simple_list_item_2,null); + } + Simulation sim = this.getItem(position); + ((TextView)v.findViewById(android.R.id.text1)).setText( sim.getName() ); + StringBuilder sb = new StringBuilder(); + sb.append("motors: ").append(sim.getConfiguration().getMotorConfigurationDescription()); + Unit distanceUnit = UnitGroup.UNITS_DISTANCE.getDefaultUnit(); + sb.append(" apogee: ").append( distanceUnit.toStringUnit(sim.getSimulatedData().getMaxAltitude())); + sb.append(" time: ").append(sim.getSimulatedData().getFlightTime()).append("s"); + ((TextView)v.findViewById(android.R.id.text2)).setText( sb.toString() ); + return v; + } + + }; + simulationList.setOnItemClickListener( new OnItemClickListener() { + @Override + public void onItemClick(AdapterView l, View v, int position, long id) { + Intent i = new Intent(getActivity(), SimulationViewer.class); + i.putExtra("Simulation",(int)id); + startActivity(i); + } + + }); + simulationList.setAdapter(sims); + + } + +} diff --git a/android/src/net/sf/openrocket/android/util/TabsAdapter.java b/android/src/net/sf/openrocket/android/util/TabsAdapter.java new file mode 100644 index 000000000..e8d8c6a80 --- /dev/null +++ b/android/src/net/sf/openrocket/android/util/TabsAdapter.java @@ -0,0 +1,140 @@ +package net.sf.openrocket.android.util; + +import java.util.ArrayList; + +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TabHost; +import android.widget.TabWidget; + +//This class was copied from: +//http://developer.android.com/resources/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabsPager.html +//With the following copyright & license. + +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** + * This is a helper class that implements the management of tabs and all + * details of connecting a ViewPager with associated TabHost. It relies on a + * trick. Normally a tab host has a simple API for supplying a View or + * Intent that each tab will show. This is not sufficient for switching + * between pages. So instead we make the content part of the tab host + * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy + * view to show as the tab content. It listens to changes in tabs, and takes + * care of switch to the correct paged in the ViewPager whenever the selected + * tab changes. + */ +public class TabsAdapter extends FragmentPagerAdapter + implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener { + private final Context mContext; + private final TabHost mTabHost; + private final ViewPager mViewPager; + private final ArrayList mTabs = new ArrayList(); + + static final class TabInfo { + private final String tag; + private final Class clss; + private final Bundle args; + + TabInfo(String _tag, Class _class, Bundle _args) { + tag = _tag; + clss = _class; + args = _args; + } + } + + static class DummyTabFactory implements TabHost.TabContentFactory { + private final Context mContext; + + public DummyTabFactory(Context context) { + mContext = context; + } + + @Override + public View createTabContent(String tag) { + View v = new View(mContext); + v.setMinimumWidth(0); + v.setMinimumHeight(0); + return v; + } + } + + public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) { + super(activity.getSupportFragmentManager()); + mContext = activity; + mTabHost = tabHost; + mViewPager = pager; + mTabHost.setOnTabChangedListener(this); + mViewPager.setAdapter(this); + mViewPager.setOnPageChangeListener(this); + } + + public void addTab(TabHost.TabSpec tabSpec, Class clss, Bundle args) { + tabSpec.setContent(new DummyTabFactory(mContext)); + String tag = tabSpec.getTag(); + + TabInfo info = new TabInfo(tag, clss, args); + mTabs.add(info); + mTabHost.addTab(tabSpec); + notifyDataSetChanged(); + } + + @Override + public int getCount() { + return mTabs.size(); + } + + @Override + public Fragment getItem(int position) { + TabInfo info = mTabs.get(position); + return Fragment.instantiate(mContext, info.clss.getName(), info.args); + } + + @Override + public void onTabChanged(String tabId) { + int position = mTabHost.getCurrentTab(); + mViewPager.setCurrentItem(position); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageSelected(int position) { + // Unfortunately when TabHost changes the current tab, it kindly + // also takes care of putting focus on it when not in touch mode. + // The jerk. + // This hack tries to prevent this from pulling focus out of our + // ViewPager. + TabWidget widget = mTabHost.getTabWidget(); + int oldFocusability = widget.getDescendantFocusability(); + widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + mTabHost.setCurrentTab(position); + widget.setDescendantFocusability(oldFocusability); + } + + @Override + public void onPageScrollStateChanged(int state) { + } +}