package net.sf.openrocket.android.rocket;\r
\r
\r
-import java.io.File;\r
+import java.io.IOException;\r
\r
import net.sf.openrocket.R;\r
-import net.sf.openrocket.aerodynamics.AerodynamicCalculator;\r
-import net.sf.openrocket.aerodynamics.BarrowmanCalculator;\r
-import net.sf.openrocket.aerodynamics.FlightConditions;\r
-import net.sf.openrocket.aerodynamics.WarningSet;\r
-import net.sf.openrocket.android.Application;\r
-import net.sf.openrocket.android.PreferencesActivity;\r
-import net.sf.openrocket.android.motor.MotorHierarchicalBrowser;\r
-import net.sf.openrocket.android.rocket.RocketComponentTreeAdapter.RocketComponentWithId;\r
-import net.sf.openrocket.android.simulation.SimulationViewer;\r
+import net.sf.openrocket.android.ActivityHelpers;\r
+import net.sf.openrocket.android.CurrentRocketHolder;\r
+import net.sf.openrocket.android.simulation.SimulationChart;\r
+import net.sf.openrocket.android.simulation.SimulationViewActivity;\r
+import net.sf.openrocket.android.simulation.SimulationViewFragment;\r
+import net.sf.openrocket.android.util.AndroidLogWrapper;\r
import net.sf.openrocket.document.OpenRocketDocument;\r
import net.sf.openrocket.document.Simulation;\r
-import net.sf.openrocket.masscalc.BasicMassCalculator;\r
-import net.sf.openrocket.masscalc.MassCalculator;\r
-import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;\r
-import net.sf.openrocket.rocketcomponent.Configuration;\r
-import net.sf.openrocket.rocketcomponent.Rocket;\r
-import net.sf.openrocket.rocketcomponent.RocketComponent;\r
-import net.sf.openrocket.rocketcomponent.RocketUtils;\r
-import net.sf.openrocket.unit.Unit;\r
-import net.sf.openrocket.unit.UnitGroup;\r
-import net.sf.openrocket.util.Coordinate;\r
-import pl.polidea.treeview.InMemoryTreeStateManager;\r
-import pl.polidea.treeview.TreeBuilder;\r
-import pl.polidea.treeview.TreeStateManager;\r
-import pl.polidea.treeview.TreeViewList;\r
-import android.app.Activity;\r
-import android.app.ProgressDialog;\r
+import android.app.AlertDialog;\r
import android.content.Intent;\r
-import android.content.SharedPreferences;\r
-import android.net.Uri;\r
import android.os.Bundle;\r
-import android.preference.PreferenceManager;\r
-import android.util.Log;\r
-import android.view.LayoutInflater;\r
-import android.view.Menu;\r
-import android.view.MenuInflater;\r
-import android.view.MenuItem;\r
+import android.support.v4.app.Fragment;\r
+import android.support.v4.app.FragmentManager;\r
+import android.support.v4.app.FragmentPagerAdapter;\r
+import android.support.v4.app.FragmentTransaction;\r
+import android.support.v4.view.ViewPager;\r
import android.view.View;\r
-import android.view.ViewGroup;\r
-import android.widget.AdapterView;\r
-import android.widget.AdapterView.OnItemClickListener;\r
-import android.widget.ArrayAdapter;\r
-import android.widget.ListAdapter;\r
-import android.widget.ListView;\r
-import android.widget.Spinner;\r
-import android.widget.TabHost;\r
-import android.widget.TextView;\r
\r
-public class OpenRocketViewer extends Activity\r
-implements SharedPreferences.OnSharedPreferenceChangeListener\r
-{\r
+import com.actionbarsherlock.view.Menu;\r
+import com.actionbarsherlock.view.MenuInflater;\r
+import com.actionbarsherlock.view.MenuItem;\r
\r
- private static final String TAG = "OpenRocketViewer";\r
+public class OpenRocketViewer extends OpenRocketLoaderActivity\r
+implements Simulations.OnSimulationSelectedListener\r
+{\r
\r
- private ProgressDialog progress;\r
+ private final static int OVERVIEW_POS = 0;\r
+ private final static int COMPONENT_POS = 1;\r
+ private final static int SIMS_POS = 2;\r
+ private final static int CONFIGS_POS = 3;\r
+ private final static int TABSIZE = 4;\r
\r
- private Spinner configurationSpinner;\r
- private TreeViewList componentTree;\r
- private ListView simulationList;\r
+ private OpenRocketViewerPagerAdapter viewPagerAdapter;\r
\r
- /* Calculation of CP and CG */\r
- private AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator();\r
- private MassCalculator massCalculator = new BasicMassCalculator();\r
-\r
- OpenRocketDocument rocketDocument;\r
- Configuration rocketConfiguration;\r
-\r
- private Application app;\r
+ private MenuItem saveAction;\r
\r
- private final static int PICK_ORK_FILE_RESULT = 1;\r
-\r
- /* (non-Javadoc)\r
- * @see android.app.Activity#onCreate(android.os.Bundle)\r
- */\r
@Override\r
protected void onCreate(Bundle savedInstanceState) {\r
super.onCreate(savedInstanceState);\r
\r
- Log.d(TAG,"In onCreate");\r
-\r
- app = (Application) this.getApplication();\r
+ // If the application sleeps for a long time, the CurrentRocketHolder might get cleaned\r
+ // up. When this happens, we cannot restore this state, so instead we just\r
+ // go home.\r
+ OpenRocketDocument rocDoc = CurrentRocketHolder.getCurrentRocket().getRocketDocument();\r
+ if ( rocDoc == null ) {\r
+ AndroidLogWrapper.d(OpenRocketViewer.class, "No document - go home");\r
+ ActivityHelpers.goHome(this);\r
+ finish();\r
+ return;\r
+ }\r
+ setTitle(rocDoc.getRocket().getName());\r
+ getSupportActionBar().setHomeButtonEnabled(true);\r
\r
setContentView(R.layout.openrocketviewer);\r
+ ViewPager viewPager = (ViewPager)findViewById(R.id.pager);\r
+ viewPagerAdapter = new OpenRocketViewerPagerAdapter( this.getSupportFragmentManager() );\r
+ viewPager.setAdapter( viewPagerAdapter );\r
+ }\r
\r
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);\r
- prefs.registerOnSharedPreferenceChangeListener(this);\r
-\r
- TabHost tabs=(TabHost)findViewById(R.id.openrocketviewerTabHost);\r
-\r
- tabs.setup();\r
-\r
- TabHost.TabSpec spec=tabs.newTabSpec("tag1");\r
-\r
- spec.setContent(R.id.openrocketviewerOverview);\r
- spec.setIndicator("Overview");\r
- tabs.addTab(spec);\r
-\r
- spec=tabs.newTabSpec("tag2");\r
- spec.setContent(R.id.openrocketviewerComponentTree);\r
- spec.setIndicator("Components");\r
- tabs.addTab(spec); \r
-\r
- spec=tabs.newTabSpec("tag3");\r
- spec.setContent(R.id.openrocketviewerSimulationList);\r
- spec.setIndicator("Simulations");\r
- tabs.addTab(spec); \r
-\r
- configurationSpinner = (Spinner) findViewById(R.id.openrocketviewerConfigurationSpinner);\r
- componentTree = (TreeViewList) findViewById(R.id.openrocketviewerComponentTree);\r
- simulationList = (ListView) findViewById(R.id.openrocketviewerSimulationList);\r
-\r
- Intent i = getIntent();\r
- Uri file = i.getData();\r
-\r
- if ( file == null ) {\r
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);\r
- intent.setType("file/*");\r
- startActivityForResult(intent,PICK_ORK_FILE_RESULT);\r
+ @Override\r
+ protected void onPause() {\r
+ CurrentRocketHolder.getCurrentRocket().setHandler(null);\r
+ super.onPause();\r
+ }\r
\r
- } else {\r
- loadOrkFile(file);\r
- }\r
+ @Override\r
+ protected void onResume() {\r
+ RocketChangedEventHandler handler = new RocketChangedEventHandler();\r
+ CurrentRocketHolder.getCurrentRocket().setHandler(handler);\r
+ super.onResume();\r
}\r
\r
@Override\r
- protected void onDestroy() {\r
- if ( progress != null ) {\r
- if ( progress.isShowing() ) {\r
- progress.dismiss();\r
- }\r
- progress = null;\r
- }\r
- super.onDestroy();\r
+ public boolean onCreateOptionsMenu(Menu menu) {\r
+ MenuInflater inflater = getSupportMenuInflater();\r
+ inflater.inflate(R.menu.rocket_viewer_option_menu, menu);\r
+ saveAction = menu.findItem(R.id.menu_save);\r
+ return true;\r
}\r
\r
@Override\r
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {\r
- // TODO Auto-generated method stub\r
- switch(requestCode){\r
- case PICK_ORK_FILE_RESULT:\r
- if(resultCode==RESULT_OK){\r
- Uri file = data.getData();\r
- loadOrkFile(file);\r
+ public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
+ AndroidLogWrapper.d(OpenRocketViewer.class,"onMenuItemSelected" + item.getItemId());\r
+ switch(item.getItemId()) {\r
+ case R.id.menu_load:\r
+ // FIXME - Might want to prompt for save here.\r
+ pickOrkFiles();\r
+ return true;\r
+ case R.id.menu_save:\r
+ // FIXME - Probably want to open a dialog here.\r
+ try {\r
+ CurrentRocketHolder.getCurrentRocket().saveOpenRocketDocument();\r
+ saveAction.setVisible(false);\r
+ invalidateOptionsMenu();\r
+ } catch ( IOException iex ) {\r
+ AndroidLogWrapper.d(OpenRocketViewer.class, iex.getMessage());\r
}\r
- break;\r
+ return true;\r
+ case android.R.id.home:\r
+ ActivityHelpers.goHome(this);\r
+ return true;\r
+ case R.id.motor_list_menu_option:\r
+ ActivityHelpers.browseMotors(this);\r
+ return true;\r
+ case R.id.preference_menu_option:\r
+ ActivityHelpers.startPreferences(this);\r
+ return true;\r
+ case R.id.menu_about:\r
+ ActivityHelpers.showAbout(this);\r
+ return true;\r
}\r
+ return super.onMenuItemSelected(featureId, item);\r
}\r
\r
- private void loadOrkFile( Uri file ) {\r
- Log.d(TAG,"Use ork file: " + file);\r
- String path = file.getPath();\r
- File orkFile = new File(path);\r
- progress = ProgressDialog.show(this, "Loading file", "");\r
-\r
- final OpenRocketLoaderTask task = new OpenRocketLoaderTask() {\r
+ @Override\r
+ public void onSimulationSelected(int simulationId) {\r
+\r
+ Simulation sim = CurrentRocketHolder.getCurrentRocket().getRocketDocument().getSimulation(simulationId);\r
+ // Check if there is data for this simulation.\r
+ if ( sim.getSimulatedData() == null || sim.getSimulatedData().getBranchCount() == 0 ) {\r
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);\r
+ builder.setMessage("The selected simulation does not have saved data.");\r
+ builder.setCancelable(true);\r
+ builder.show();\r
+ return;\r
+ }\r
\r
- /* (non-Javadoc)\r
- * @see android.os.AsyncTask#onPostExecute(java.lang.Object)\r
- */\r
- @Override\r
- protected void onPostExecute(OpenRocketDocument result) {\r
- super.onPostExecute(result);\r
- app.setRocketDocument( result );\r
- updateContents();\r
- }\r
+ View sidepane = findViewById(R.id.sidepane);\r
+ if ( /* if multi pane */ sidepane != null ) {\r
+ SimulationChart chart = new SimulationChart(simulationId);\r
\r
- };\r
+ Fragment graph = SimulationViewFragment.newInstance(chart);\r
\r
- task.execute(orkFile);\r
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();\r
+ ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);\r
+ // probably only want to update back stack for first time.\r
+ ft.addToBackStack("simulationplot");\r
+ ft.replace(R.id.sidepane, graph);\r
+ ft.show(graph);\r
+ ft.commit();\r
\r
- }\r
\r
- /* (non-Javadoc)\r
- * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences, java.lang.String)\r
- */\r
- @Override\r
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r
- // just in case the user changed the units, we redraw.\r
- PreferencesActivity.initializePreferences(getApplication(), PreferenceManager.getDefaultSharedPreferences(this));\r
- updateContents();\r
+ } else {\r
+ Intent i = new Intent(this, SimulationViewActivity.class);\r
+ i.putExtra("Simulation",simulationId);\r
+ startActivity(i);\r
+ }\r
}\r
\r
- private void updateContents() {\r
-\r
- rocketDocument = app.getRocketDocument();\r
- rocketConfiguration = rocketDocument.getDefaultConfiguration();\r
- Rocket rocket = rocketDocument.getRocket();\r
-\r
- setTitle(rocket.getName());\r
-\r
- String[] motorConfigs = rocket.getMotorConfigurationIDs();\r
- ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item);\r
- for( String config: motorConfigs ) {\r
- spinnerAdapter.add(rocket.getMotorConfigurationNameOrDescription(config));\r
- }\r
+ private class RocketChangedEventHandler extends net.sf.openrocket.android.RocketChangedEventHandler {\r
\r
- configurationSpinner.setAdapter(spinnerAdapter);\r
- configurationSpinner.setOnItemSelectedListener( new AdapterView.OnItemSelectedListener() {\r
-\r
- /* (non-Javadoc)\r
- * @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int, long)\r
- */\r
- @Override\r
- public void onItemSelected(AdapterView<?> arg0, View arg1,\r
- int arg2, long arg3) {\r
-\r
- String selectedConfigId = rocketDocument.getRocket().getMotorConfigurationIDs()[arg2];\r
- rocketConfiguration.setMotorConfigurationID(selectedConfigId);\r
- Coordinate cp = aerodynamicCalculator.getWorstCP(rocketConfiguration,\r
- new FlightConditions(rocketConfiguration),\r
- new WarningSet());\r
- \r
- Coordinate cg = massCalculator.getCG(rocketConfiguration, MassCalcType.LAUNCH_MASS);\r
-\r
- Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();\r
- Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit();\r
- Unit stabilityUnit = UnitGroup.stabilityUnits(rocketConfiguration).getDefaultUnit();\r
-\r
- ((TextView)findViewById(R.id.openrocketviewerCP)).setText(lengthUnit.toStringUnit(cp.x));\r
- ((TextView)findViewById(R.id.openrocketviewerCG)).setText(lengthUnit.toStringUnit(cg.x));\r
- ((TextView)findViewById(R.id.openrocketviewerLiftOffWeight)).setText(massUnit.toStringUnit(cg.weight));\r
- ((TextView)findViewById(R.id.openrocketviewerStabilityMargin)).setText(stabilityUnit.toStringUnit(cp.x-cg.x));\r
-\r
+ @Override\r
+ protected void doSimsChanged() {\r
+ if (saveAction != null ) {\r
+ saveAction.setVisible(true);\r
+ invalidateOptionsMenu();\r
}\r
-\r
- /* (non-Javadoc)\r
- * @see android.widget.AdapterView.OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)\r
- */\r
- @Override\r
- public void onNothingSelected(AdapterView<?> arg0) {\r
- ((TextView)findViewById(R.id.openrocketviewerCP)).setText("");\r
- ((TextView)findViewById(R.id.openrocketviewerCG)).setText("");\r
- ((TextView)findViewById(R.id.openrocketviewerLiftOffWeight)).setText("");\r
- ((TextView)findViewById(R.id.openrocketviewerStabilityMargin)).setText("");\r
+ Simulations sims = (Simulations) viewPagerAdapter.getFragmentAtPos(SIMS_POS);\r
+ if ( sims != null ) {\r
+ sims.refreshSimulationList();\r
}\r
- \r
- });\r
- \r
- Unit lengthUnit = UnitGroup.UNITS_LENGTH.getDefaultUnit();\r
- Unit massUnit = UnitGroup.UNITS_MASS.getDefaultUnit();\r
-\r
- Coordinate cg = RocketUtils.getCG(rocket, MassCalcType.NO_MOTORS);\r
- double length = RocketUtils.getLength(rocket);\r
- ((TextView)findViewById(R.id.openrocketviewerDesigner)).setText(rocket.getDesigner());\r
- ((TextView)findViewById(R.id.openrocketviewerLength)).setText(lengthUnit.toStringUnit(length));\r
- ((TextView)findViewById(R.id.openrocketviewerMass)).setText(massUnit.toStringUnit(cg.weight));\r
- ((TextView)findViewById(R.id.openrocketviewerStageCount)).setText(String.valueOf(rocket.getStageCount()));\r
-\r
- \r
- ArrayAdapter<Simulation> sims = new ArrayAdapter<Simulation>(this,android.R.layout.simple_list_item_2,rocketDocument.getSimulations()) {\r
+ }\r
\r
- @Override\r
- public View getView(int position, View convertView, ViewGroup parent) {\r
- View v = convertView;\r
- if ( v == null ) {\r
- LayoutInflater li = getLayoutInflater();\r
- v = li.inflate(android.R.layout.simple_list_item_2,null);\r
- }\r
- Simulation sim = this.getItem(position);\r
- ((TextView)v.findViewById(android.R.id.text1)).setText( sim.getName() );\r
- ((TextView)v.findViewById(android.R.id.text2)).setText( "motors: " + sim.getConfiguration().getMotorConfigurationDescription() + " apogee: " + sim.getSimulatedData().getMaxAltitude() + "m time: " + sim.getSimulatedData().getFlightTime() + "s");\r
- return v;\r
+ @Override\r
+ protected void doMotorConfigsChanged() {\r
+ if (saveAction != null ) {\r
+ saveAction.setVisible(true);\r
+ invalidateOptionsMenu();\r
}\r
-\r
- };\r
- simulationList.setOnItemClickListener( new OnItemClickListener() {\r
- @Override\r
- public void onItemClick(AdapterView l, View v, int position, long id) {\r
- Intent i = new Intent(OpenRocketViewer.this, SimulationViewer.class);\r
- Log.d(TAG,"onItemClick simulation number " + id );\r
- i.putExtra("Simulation",(int)id);\r
- startActivityForResult(i, 1/*magic*/);\r
+ Configurations configs = (Configurations) viewPagerAdapter.getFragmentAtPos(CONFIGS_POS);\r
+ if ( configs != null ) {\r
+ configs.refreshConfigsList();\r
}\r
-\r
- });\r
- simulationList.setAdapter(sims);\r
-\r
- componentTree.setAdapter( buildAdapter( rocket ) );\r
-\r
- if ( progress.isShowing() ) {\r
- progress.dismiss();\r
}\r
- }\r
-\r
- @Override\r
- public boolean onCreateOptionsMenu(Menu menu) {\r
- MenuInflater inflater = getMenuInflater();\r
- inflater.inflate(R.menu.rocket_viewer_option_menu, menu);\r
- return true;\r
- }\r
\r
- @Override\r
- public boolean onMenuItemSelected(int featureId, MenuItem item) {\r
- Log.d(TAG,"onMenuItemSelected" + item.getItemId());\r
- switch(item.getItemId()) {\r
- case R.id.motor_list_menu_option:\r
- startMotorBrowser();\r
- return true;\r
- case R.id.preference_menu_option:\r
- Intent intent = new Intent().setClass(this, PreferencesActivity.class);\r
- this.startActivity(intent);\r
- return true;\r
- }\r
- return super.onMenuItemSelected(featureId, item);\r
- }\r
+ };\r
\r
- public void startMotorBrowser() {\r
- Log.d(TAG,"motorBrowserButton clicked");\r
- Intent i = new Intent(OpenRocketViewer.this, MotorHierarchicalBrowser.class);\r
- startActivity(i);\r
- }\r
\r
- private ListAdapter buildAdapter( Rocket rocket ) {\r
- /*\r
- final int[] DEMO_NODES = new int[] { 0, 0, 1, 1, 1, 2, 2, 1,\r
- 1, 2, 1, 0, 0, 0, 1, 2, 3, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1 };\r
- final int LEVEL_NUMBER = 4;\r
+ private class OpenRocketViewerPagerAdapter extends FragmentPagerAdapter {\r
\r
- TreeStateManager<Long> manager = new InMemoryTreeStateManager<Long>();\r
- final TreeBuilder<Long> treeBuilder = new TreeBuilder<Long>(manager);\r
- for (int i = 0; i < DEMO_NODES.length; i++) {\r
- treeBuilder.sequentiallyAddNextNode((long) i, DEMO_NODES[i]);\r
+ public OpenRocketViewerPagerAdapter( FragmentManager fm ) {\r
+ super(fm);\r
}\r
-\r
- return new SimpleStandardAdapter(this, manager, LEVEL_NUMBER);\r
- */\r
- \r
- TreeStateManager<RocketComponentWithId> manager = new InMemoryTreeStateManager<RocketComponentWithId>();\r
- TreeBuilder<RocketComponentWithId> treeBuilder = new TreeBuilder<RocketComponentWithId>(manager);\r
- \r
- int depth = buildRecursive( rocket, treeBuilder, 0 );\r
- return new RocketComponentTreeAdapter(this, manager, depth+1);\r
- }\r
- \r
- long id = 0;\r
- private int buildRecursive( RocketComponent comp, TreeBuilder<RocketComponentWithId> builder, int depth ) {\r
- \r
- \r
- int maxDepth = depth;\r
- \r
- RocketComponentWithId rcid = new RocketComponentWithId(comp, id++);\r
- \r
- // Add this component.\r
- builder.sequentiallyAddNextNode(rcid, depth);\r
- \r
- if ( comp.allowsChildren() ) {\r
- \r
- for( RocketComponent child : comp.getChildren() ) {\r
- int childDepth = buildRecursive( child, builder, depth+1);\r
- if ( childDepth > maxDepth) {\r
- maxDepth = childDepth;\r
- }\r
+ @Override\r
+ public int getCount() {\r
+ return TABSIZE;\r
+ }\r
+ @Override\r
+ public Fragment getItem( int position ) {\r
+ switch (position) {\r
+ case OVERVIEW_POS:\r
+ return new Overview();\r
+ case COMPONENT_POS:\r
+ return new Component();\r
+ case SIMS_POS:\r
+ return new Simulations();\r
+ case CONFIGS_POS:\r
+ return new Configurations();\r
}\r
- \r
+ return null;\r
+ }\r
+ @Override\r
+ public CharSequence getPageTitle(int position) {\r
+ switch (position) {\r
+ case OVERVIEW_POS:\r
+ return "Overview";\r
+ case COMPONENT_POS:\r
+ return "Components";\r
+ case SIMS_POS:\r
+ return "Simulations";\r
+ case CONFIGS_POS:\r
+ return "Configurations";\r
+ }\r
+ return null;\r
}\r
- \r
- return maxDepth;\r
- }\r
\r
+ public Fragment getFragmentAtPos( int pos ) {\r
+ String tag = "android:switcher:"+R.id.pager+":"+pos;\r
+ Fragment f = OpenRocketViewer.this.getSupportFragmentManager().findFragmentByTag(tag);\r
+ return f;\r
+ }\r
+ }\r
\r
}\r