From 3cdaf29f3018779f7429823a628b63cad8f901b1 Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Sun, 22 Jan 2012 02:44:17 +0000 Subject: [PATCH] Various changes to android application. Separate the loading of an ork file into the OpenRocketLoader activity. Changed OpenRocketViewer to use Fragments for each of the tab contents. Added Component, Overview and Simulations fragments for the tabs in OpenRocketViewer. Modified the graphics on the UI. Have the PreferencesActivity pack the changed preferences into the application onStop(). git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@363 180e2498-e6e9-4542-8430-84ac67f01cd8 --- android/AndroidManifest.xml | 17 +- android/res/drawable/ic_menu_preferences.png | Bin 0 -> 2144 bytes android/res/drawable/or_launcher.png | Bin 64713 -> 6148 bytes android/res/layout/openrocketviewer.xml | 159 ++------- android/res/layout/rocket_component.xml | 7 + android/res/layout/rocket_overview.xml | 106 ++++++ android/res/layout/rocket_simulations.xml | 12 + android/res/menu/main_menu.xml | 15 + .../res/menu/rocket_viewer_option_menu.xml | 12 +- android/res/values/pref_strings.xml | 54 +++ android/res/values/strings.xml | 49 +-- android/res/xml/preferences.xml | 77 ++-- .../openrocket/android/ActivityHelpers.java | 21 ++ .../src/net/sf/openrocket/android/Main.java | 70 +++- .../android/PreferencesActivity.java | 8 + .../android/motor/BurnPlotFragment.java | 6 - .../openrocket/android/rocket/Component.java | 76 ++++ .../android/rocket/OpenRocketLoader.java | 79 ++++ .../android/rocket/OpenRocketViewer.java | 336 +++--------------- .../openrocket/android/rocket/Overview.java | 123 +++++++ .../android/rocket/Simulations.java | 77 ++++ .../openrocket/android/util/TabsAdapter.java | 140 ++++++++ 22 files changed, 901 insertions(+), 543 deletions(-) create mode 100644 android/res/drawable/ic_menu_preferences.png create mode 100644 android/res/layout/rocket_component.xml create mode 100644 android/res/layout/rocket_overview.xml create mode 100644 android/res/layout/rocket_simulations.xml create mode 100644 android/res/menu/main_menu.xml create mode 100644 android/res/values/pref_strings.xml create mode 100644 android/src/net/sf/openrocket/android/ActivityHelpers.java create mode 100644 android/src/net/sf/openrocket/android/rocket/Component.java create mode 100644 android/src/net/sf/openrocket/android/rocket/OpenRocketLoader.java create mode 100644 android/src/net/sf/openrocket/android/rocket/Overview.java create mode 100644 android/src/net/sf/openrocket/android/rocket/Simulations.java create mode 100644 android/src/net/sf/openrocket/android/util/TabsAdapter.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 6ae3d51f..e0b9dba3 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 0000000000000000000000000000000000000000..b8e71412d8abd068d6c02fb237ada60b2919598f GIT binary patch literal 2144 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 Wka062q6>`x00006cD6qknW*|`SJbM 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 - + 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 00000000..40c3ba2c --- /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 00000000..7eca8962 --- /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 00000000..e856d1e9 --- /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 00000000..f378ed0f --- /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 6d4f5c6f..4ebd72d4 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 00000000..5bf18212 --- /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 5d7b232f..eeb1b494 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 d229d6ef..77b1cdef 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 00000000..bc6db510 --- /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 cdb7366a..ff5fd8de 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 5b14bf23..9680c9e8 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 96ff0845..49373762 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 00000000..a19f2e7c --- /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 00000000..ee35ba00 --- /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 6985c934..a79beb6e 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); - - tabs.setup(); - - TabHost.TabSpec spec=tabs.newTabSpec("tag1"); + mTabHost = (TabHost)findViewById(android.R.id.tabhost); + mTabHost.setup(); - spec.setContent(R.id.openrocketviewerOverview); - spec.setIndicator("Overview"); - tabs.addTab(spec); + mViewPager = (ViewPager)findViewById(R.id.pager); - spec=tabs.newTabSpec("tag2"); - spec.setContent(R.id.openrocketviewerComponentTree); - spec.setIndicator("Components"); - tabs.addTab(spec); + mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); - spec=tabs.newTabSpec("tag3"); - spec.setContent(R.id.openrocketviewerSimulationList); - spec.setIndicator("Simulations"); - 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); - 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 00000000..69a35ef7 --- /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 00000000..231c50da --- /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 00000000..e8d8c6a8 --- /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) { + } +} -- 2.47.2