From: kruland2607 Date: Mon, 30 Jan 2012 03:48:42 +0000 (+0000) Subject: Rewrite MotorBrowser to use a fragment for the list. This is the first step in makin... X-Git-Tag: upstream/12.03~1^2~90 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=21a3aadb34f6de49053e5bef8a1908731cbf3b5e;p=debian%2Fopenrocket Rewrite MotorBrowser to use a fragment for the list. This is the first step in making this portion of the application look and operate better on tables. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@381 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index de2637f0..db3d21f0 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -71,8 +71,8 @@ - - + + diff --git a/android/res/layout/motor_hierarch_list.xml b/android/res/layout/motor_hierarch_list.xml deleted file mode 100644 index 9d17a2c2..00000000 --- a/android/res/layout/motor_hierarch_list.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/android/res/menu/motor_browser_option_menu.xml b/android/res/menu/motor_browser_option_menu.xml index 5c1f1b44..154bd595 100644 --- a/android/res/menu/motor_browser_option_menu.xml +++ b/android/res/menu/motor_browser_option_menu.xml @@ -1,6 +1,12 @@ - - - - + + + + + + \ 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 index bc6db510..aaef2c6f 100644 --- a/android/src/net/sf/openrocket/android/ActivityHelpers.java +++ b/android/src/net/sf/openrocket/android/ActivityHelpers.java @@ -1,6 +1,7 @@ package net.sf.openrocket.android; -import net.sf.openrocket.android.motor.MotorHierarchicalBrowser; +import net.sf.openrocket.android.motor.MotorBrowserActivity; +import net.sf.openrocket.android.thrustcurve.TCQueryActivity; import android.app.Activity; import android.content.Intent; @@ -8,14 +9,18 @@ public abstract class ActivityHelpers { public static void browseMotors( Activity parent ) { - Intent i = new Intent(parent, MotorHierarchicalBrowser.class); + Intent i = new Intent(parent, MotorBrowserActivity.class); parent.startActivity(i); - } public static void startPreferences( Activity parent ) { Intent intent = new Intent(parent, PreferencesActivity.class); parent.startActivity(intent); - } + + public static void downloadFromThrustcurve( Activity parent ) { + Intent i = new Intent(parent, TCQueryActivity.class); + parent.startActivity(i); + } + } diff --git a/android/src/net/sf/openrocket/android/db/ConversionUtils.java b/android/src/net/sf/openrocket/android/db/ConversionUtils.java index a66fc28c..62fbddb9 100644 --- a/android/src/net/sf/openrocket/android/db/ConversionUtils.java +++ b/android/src/net/sf/openrocket/android/db/ConversionUtils.java @@ -8,7 +8,7 @@ import java.io.ObjectOutputStream; import net.sf.openrocket.motor.Motor; import net.sf.openrocket.util.Coordinate; -abstract class ConversionUtils { +public abstract class ConversionUtils { static double[] stringToDelays( String value ) { if (value == null || "".equals(value) ) { @@ -28,7 +28,7 @@ abstract class ConversionUtils { return values; } - static String delaysToString( double[] delays ) { + public static String delaysToString( double[] delays ) { StringBuilder s = new StringBuilder(); boolean first = true; for( double d:delays ) { diff --git a/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java b/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java new file mode 100644 index 00000000..e059da13 --- /dev/null +++ b/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java @@ -0,0 +1,91 @@ +package net.sf.openrocket.android.motor; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.ActivityHelpers; +import net.sf.openrocket.android.PreferencesActivity; +import net.sf.openrocket.android.simulation.SimulationChart; +import net.sf.openrocket.android.simulation.SimulationFragment; +import net.sf.openrocket.android.simulation.SimulationViewActivity; +import net.sf.openrocket.android.thrustcurve.TCQueryActivity; +import net.sf.openrocket.android.util.AndroidLogWrapper; +import net.sf.openrocket.document.Simulation; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + +public class MotorBrowserActivity extends FragmentActivity +implements MotorListFragment.OnMotorSelectedListener +{ + + MotorListFragment motorList; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) { + motorList = MotorListFragment.newInstance(); + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.add(android.R.id.content, motorList); + ft.commit(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.motor_browser_option_menu, menu); + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + AndroidLogWrapper.d(MotorBrowserActivity.class,"onMenuItemSelected" + item.getItemId()); + switch(item.getItemId()) { + case R.id.download_from_thrustcurve_menu_option: + ActivityHelpers.downloadFromThrustcurve(this); + return true; + case R.id.preference_menu_option: + Intent intent = new Intent().setClass(this, PreferencesActivity.class); + this.startActivity(intent); + return true; + } + return super.onMenuItemSelected(featureId, item); + } + + @Override + public void onMotorSelected(long motorId) { + + View sidepane = findViewById(R.id.sidepane); + if ( /* if multi pane */ sidepane != null ) { + /* + Simulation sim = app.getRocketDocument().getSimulation(simulationId); + SimulationChart chart = new SimulationChart(simulationId); + + Fragment graph = SimulationFragment.newInstance(chart); + + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); + // probably only want to update back stack for first time. + ft.addToBackStack("simulationplot"); + ft.replace(R.id.sidepane, graph); + ft.show(graph); + ft.commit(); +*/ + + } else { + Intent i = new Intent(this,MotorDetailsActivity.class); + i.putExtra("Motor", motorId); + startActivity(i); + } + + } + +} diff --git a/android/src/net/sf/openrocket/android/motor/MotorDetails.java b/android/src/net/sf/openrocket/android/motor/MotorDetails.java deleted file mode 100644 index df31f3be..00000000 --- a/android/src/net/sf/openrocket/android/motor/MotorDetails.java +++ /dev/null @@ -1,89 +0,0 @@ -package net.sf.openrocket.android.motor; - -import net.sf.openrocket.R; -import net.sf.openrocket.android.db.DbAdapter; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.ImageView; -import android.widget.SlidingDrawer; - -public class MotorDetails extends FragmentActivity -implements SlidingDrawer.OnDrawerCloseListener, SlidingDrawer.OnDrawerOpenListener { - - private final static String TAG = "MotorDetails"; - - private SlidingDrawer slidingDrawer; - private ImageView handle; - - private ExtendedThrustCurveMotor motor; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState)); - setContentView(R.layout.motor_detail); - - Intent i = getIntent(); - long motorId = i.getLongExtra("Motor",-1); - - DbAdapter mDbHelper = new DbAdapter(this); - mDbHelper.open(); - - try { - motor = mDbHelper.getMotorDao().fetchMotor(motorId); - } catch ( Exception e ) { - - } - - mDbHelper.close(); - - BurnPlotFragment burnPlot = (BurnPlotFragment) getSupportFragmentManager().findFragmentById(R.id.burnPlotFragment); - burnPlot.init(motor); - - MotorDetailsFragment motorDetails = (MotorDetailsFragment) getSupportFragmentManager().findFragmentById(R.id.motorDetailForm); - motorDetails.init(motor); - - slidingDrawer = (SlidingDrawer) findViewById(R.id.drawer); - - slidingDrawer.setOnDrawerOpenListener(this); - slidingDrawer.setOnDrawerCloseListener(this); - - handle = (ImageView) findViewById(R.id.handle); - - } - - @Override - public void onDrawerOpened() { - handle.setImageResource(R.drawable.arrow_down_float); - } - - @Override - public void onDrawerClosed() { - handle.setImageResource(R.drawable.arrow_up_float); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.motor_details_option_menu, menu); - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - switch(item.getItemId()) { - case R.id.save: - // Extract form data to Motor. - // Save motor. - return true; - } - return super.onMenuItemSelected(featureId, item); - } - - -} diff --git a/android/src/net/sf/openrocket/android/motor/MotorDetailsActivity.java b/android/src/net/sf/openrocket/android/motor/MotorDetailsActivity.java new file mode 100644 index 00000000..ed97b837 --- /dev/null +++ b/android/src/net/sf/openrocket/android/motor/MotorDetailsActivity.java @@ -0,0 +1,89 @@ +package net.sf.openrocket.android.motor; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.db.DbAdapter; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.ImageView; +import android.widget.SlidingDrawer; + +public class MotorDetailsActivity extends FragmentActivity +implements SlidingDrawer.OnDrawerCloseListener, SlidingDrawer.OnDrawerOpenListener { + + private final static String TAG = "MotorDetails"; + + private SlidingDrawer slidingDrawer; + private ImageView handle; + + private ExtendedThrustCurveMotor motor; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d(TAG,"onCreate Bundle = "+ String.valueOf(savedInstanceState)); + setContentView(R.layout.motor_detail); + + Intent i = getIntent(); + long motorId = i.getLongExtra("Motor",-1); + + DbAdapter mDbHelper = new DbAdapter(this); + mDbHelper.open(); + + try { + motor = mDbHelper.getMotorDao().fetchMotor(motorId); + } catch ( Exception e ) { + + } + + mDbHelper.close(); + + BurnPlotFragment burnPlot = (BurnPlotFragment) getSupportFragmentManager().findFragmentById(R.id.burnPlotFragment); + burnPlot.init(motor); + + MotorDetailsFragment motorDetails = (MotorDetailsFragment) getSupportFragmentManager().findFragmentById(R.id.motorDetailForm); + motorDetails.init(motor); + + slidingDrawer = (SlidingDrawer) findViewById(R.id.drawer); + + slidingDrawer.setOnDrawerOpenListener(this); + slidingDrawer.setOnDrawerCloseListener(this); + + handle = (ImageView) findViewById(R.id.handle); + + } + + @Override + public void onDrawerOpened() { + handle.setImageResource(R.drawable.arrow_down_float); + } + + @Override + public void onDrawerClosed() { + handle.setImageResource(R.drawable.arrow_up_float); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.motor_details_option_menu, menu); + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + switch(item.getItemId()) { + case R.id.save: + // Extract form data to Motor. + // Save motor. + return true; + } + return super.onMenuItemSelected(featureId, item); + } + + +} diff --git a/android/src/net/sf/openrocket/android/motor/MotorDetailsFragment.java b/android/src/net/sf/openrocket/android/motor/MotorDetailsFragment.java index 874f4343..f9083b64 100644 --- a/android/src/net/sf/openrocket/android/motor/MotorDetailsFragment.java +++ b/android/src/net/sf/openrocket/android/motor/MotorDetailsFragment.java @@ -1,8 +1,7 @@ package net.sf.openrocket.android.motor; -import java.util.Arrays; - import net.sf.openrocket.R; +import net.sf.openrocket.android.db.ConversionUtils; import net.sf.openrocket.motor.ThrustCurveMotor; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -39,7 +38,7 @@ public class MotorDetailsFragment extends Fragment { ThrustCurveMotor tcm = m.getThrustCurveMotor(); manuField.setText( tcm.getManufacturer().getDisplayName()); nameField.setText( tcm.getDesignation() ); - delaysField.setText( Arrays.toString(tcm.getStandardDelays()) ); + delaysField.setText( ConversionUtils.delaysToString(tcm.getStandardDelays()) ); caseField.setText( m.getCaseInfo()); impulseClassField.setText( m.getImpulseClass()); diameterField.setText( String.valueOf(tcm.getDiameter()*1000.0) ); diff --git a/android/src/net/sf/openrocket/android/motor/MotorHierarchicalBrowser.java b/android/src/net/sf/openrocket/android/motor/MotorHierarchicalBrowser.java deleted file mode 100644 index f940e110..00000000 --- a/android/src/net/sf/openrocket/android/motor/MotorHierarchicalBrowser.java +++ /dev/null @@ -1,262 +0,0 @@ -package net.sf.openrocket.android.motor; - -import net.sf.openrocket.R; -import net.sf.openrocket.android.PreferencesActivity; -import net.sf.openrocket.android.db.DbAdapter; -import net.sf.openrocket.android.db.MotorDao; -import net.sf.openrocket.android.thrustcurve.TCQueryActivity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.database.Cursor; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.CursorTreeAdapter; -import android.widget.ExpandableListView; -import android.widget.ResourceCursorTreeAdapter; -import android.widget.TextView; - - -public class MotorHierarchicalBrowser -extends PersistentExpandableListActivity -implements SharedPreferences.OnSharedPreferenceChangeListener -{ - private static final String TAG = "MotorHierarchicalBrowser"; - - private static final int ACTIVITY_DOWNLOAD=0; - - private static final int CONTEXTMENU_DELETE = Menu.FIRST+1; - - private String groupColumnPreferenceKey; - private String groupColumn = MotorDao.CASE_INFO; - - private static final String[] groupColumns = new String[] { - MotorDao.CASE_INFO, - MotorDao.DIAMETER, - MotorDao.IMPULSE_CLASS, - MotorDao.MANUFACTURER - }; - - private CursorTreeAdapter mAdapter; - - private DbAdapter mDbHelper; - - public class MotorHierarchicalListAdapter extends ResourceCursorTreeAdapter - { - - // Note that the constructor does not take a Cursor. This is done to avoid querying the - // database on the main thread. - public MotorHierarchicalListAdapter(Context context, Cursor cursor, int groupLayout, - int childLayout ) { - - super(context, cursor, groupLayout, childLayout); - } - - @Override - protected Cursor getChildrenCursor(Cursor arg0) { - Log.d(TAG,"getChildrenCursor"); - String group = arg0.getString(arg0.getColumnIndex(groupColumn)); - Log.d(TAG," for: "+ groupColumn + " = " + group); - Cursor c = mDbHelper.getMotorDao().fetchAllInGroups(groupColumn,group); - Log.d(TAG," got cursor"); - startManagingCursor(c); - return c; - } - - @Override - public long getGroupId(int groupPosition) { - return groupPosition; - } - - /* (non-Javadoc) - * @see android.widget.CursorTreeAdapter#bindChildView(android.view.View, android.content.Context, android.database.Cursor, boolean) - */ - @Override - protected void bindChildView(View arg0, Context arg1, Cursor arg2, - boolean arg3) { - - TextView manu = (TextView) arg0.findViewById(R.id.motorChildManu); - manu.setText( arg2.getString(arg2.getColumnIndex(MotorDao.MANUFACTURER))); - - TextView desig = (TextView) arg0.findViewById(R.id.motorChildName); - desig.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DESIGNATION))); - - TextView delays = (TextView) arg0.findViewById(R.id.motorChildDelays); - delays.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DELAYS))); - - TextView totImpulse = (TextView) arg0.findViewById(R.id.motorChildImpulse); - totImpulse.setText( arg2.getString(arg2.getColumnIndex(MotorDao.TOTAL_IMPULSE))); - } - - /* (non-Javadoc) - * @see android.widget.CursorTreeAdapter#bindGroupView(android.view.View, android.content.Context, android.database.Cursor, boolean) - */ - @Override - protected void bindGroupView(View view, Context context, Cursor cursor, - boolean isExpanded) { - TextView v = (TextView) view.findViewById(R.id.motorGroup); - if ( MotorDao.DIAMETER.equals(groupColumn)) { - double d = cursor.getDouble( cursor.getColumnIndex(groupColumn)); - v.setText( String.valueOf(Math.round(d * 1000.0)) ); - } else { - v.setText( cursor.getString( cursor.getColumnIndex(groupColumn))); - } - } - - - - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) { - if ( groupColumnPreferenceKey.equals(arg1) ) { - setGroupColumnFromPreferences(arg0); - refreshData(); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mDbHelper = new DbAdapter(this); - mDbHelper.open(); - - Resources resources = this.getResources(); - groupColumnPreferenceKey = resources.getString(R.string.PreferenceMotorBrowserGroupingOption); - SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); - - setGroupColumnFromPreferences(pref); - - pref.registerOnSharedPreferenceChangeListener(this); - - refreshData(); - - registerForContextMenu(getExpandableListView()); - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.motor_browser_option_menu, menu); - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - Log.d(TAG,"onMenuItemSelected" + item.getItemId()); - switch(item.getItemId()) { - case R.id.download_from_thrustcurve_menu_option: - tcDownload(); - return true; - case R.id.preference_menu_option: - Intent intent = new Intent().setClass(this, PreferencesActivity.class); - this.startActivity(intent); - return true; - } - return super.onMenuItemSelected(featureId, item); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { - Log.d(TAG,"onCreateContextMenu " + menuInfo); - Log.d(TAG, "v.getId() = " + v.getId()); - Log.d(TAG, "motorListView = " + R.id.motorListView); - // if (v.getId() == R.id.motorListView) { - ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo; - menu.setHeaderTitle("context menu"); - menu.add(Menu.NONE,CONTEXTMENU_DELETE,CONTEXTMENU_DELETE,"Delete"); - // } - super.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo(); - long motorId = info.id; - Log.d(TAG,"ContextMenu: " + motorId); - switch(item.getItemId()) { - case CONTEXTMENU_DELETE: - mDbHelper.getMotorDao().deleteMotor(motorId); - refreshData(); - return true; - } - return super.onContextItemSelected(item); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); - refreshData(); - } - - - @Override - public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { - super.onChildClick(parent, v, groupPosition, childPosition, id); - //Intent i = new Intent(this, BurnPlotActivity.class); - Intent i = new Intent(this,MotorDetails.class); - i.putExtra("Motor", id); - startActivity(i); - return true; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); - pref.unregisterOnSharedPreferenceChangeListener(this); - - // Null out the group cursor. This will cause the group cursor and all of the child cursors - // to be closed. - mAdapter.changeCursor(null); - mAdapter = null; - - mDbHelper.close(); - } - - private void tcDownload() { - Intent i = new Intent(this, TCQueryActivity.class); - startActivityForResult(i, ACTIVITY_DOWNLOAD); - } - - private void setGroupColumnFromPreferences( SharedPreferences prefs ) { - String indexStr = prefs.getString(groupColumnPreferenceKey, "1"); - int index; - //Dirty hack, you can't use integer-array in ListPreferences - try { - index = Integer.parseInt(indexStr); - } catch ( Exception e ) { - index = 1; - } - if ( index >= groupColumns.length ) { - index = 1; - } - groupColumn = groupColumns[index]; - - } - private void refreshData() { - if (mAdapter != null ) { - mAdapter.changeCursor(null); - } - Cursor motorCursor = mDbHelper.getMotorDao().fetchGroups(groupColumn); - startManagingCursor(motorCursor); - // Set up our adapter - mAdapter = new MotorHierarchicalListAdapter( - this, - motorCursor, - R.layout.motor_list_group, - R.layout.motor_list_child); - setListAdapter(mAdapter); - } -} diff --git a/android/src/net/sf/openrocket/android/motor/MotorListFragment.java b/android/src/net/sf/openrocket/android/motor/MotorListFragment.java new file mode 100644 index 00000000..f7559854 --- /dev/null +++ b/android/src/net/sf/openrocket/android/motor/MotorListFragment.java @@ -0,0 +1,243 @@ +package net.sf.openrocket.android.motor; + +import net.sf.openrocket.R; +import net.sf.openrocket.android.db.DbAdapter; +import net.sf.openrocket.android.db.MotorDao; +import net.sf.openrocket.android.util.AndroidLogWrapper; +import net.sf.openrocket.android.util.PersistentExpandableListFragment; +import net.sf.openrocket.motor.Motor; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.database.Cursor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.CursorTreeAdapter; +import android.widget.ExpandableListView; +import android.widget.ResourceCursorTreeAdapter; +import android.widget.TextView; + + +/* + * TODO - make this work with PersistentExpandableListFragment. + * + */ +public class MotorListFragment extends PersistentExpandableListFragment +implements SharedPreferences.OnSharedPreferenceChangeListener +{ + public interface OnMotorSelectedListener { + public void onMotorSelected( long motorId ); + } + + public static MotorListFragment newInstance( ) { + + MotorListFragment frag = new MotorListFragment(); + return frag; + } + + private static final int CONTEXTMENU_DELETE = Menu.FIRST+1; + + private String groupColumnPreferenceKey; + private String groupColumn = MotorDao.CASE_INFO; + + private static final String[] groupColumns = new String[] { + MotorDao.CASE_INFO, + MotorDao.DIAMETER, + MotorDao.IMPULSE_CLASS, + MotorDao.MANUFACTURER + }; + + private CursorTreeAdapter mAdapter; + + private DbAdapter mDbHelper; + + private OnMotorSelectedListener motorSelectedListener; + + public void setMotorSelectedListener( + OnMotorSelectedListener motorSelectedListener) { + this.motorSelectedListener = motorSelectedListener; + } + + public class MotorHierarchicalListAdapter extends ResourceCursorTreeAdapter + { + + // Note that the constructor does not take a Cursor. This is done to avoid querying the + // database on the main thread. + public MotorHierarchicalListAdapter(Context context, Cursor cursor, int groupLayout, + int childLayout ) { + + super(context, cursor, groupLayout, childLayout); + } + + @Override + protected Cursor getChildrenCursor(Cursor arg0) { + AndroidLogWrapper.d(MotorListFragment.class,"getChildrenCursor"); + String group = arg0.getString(arg0.getColumnIndex(groupColumn)); + AndroidLogWrapper.d(MotorListFragment.class," for: "+ groupColumn + " = " + group); + Cursor c = mDbHelper.getMotorDao().fetchAllInGroups(groupColumn,group); + AndroidLogWrapper.d(MotorListFragment.class," got cursor"); + getActivity().startManagingCursor(c); + return c; + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + /* (non-Javadoc) + * @see android.widget.CursorTreeAdapter#bindChildView(android.view.View, android.content.Context, android.database.Cursor, boolean) + */ + @Override + protected void bindChildView(View arg0, Context arg1, Cursor arg2, + boolean arg3) { + + TextView manu = (TextView) arg0.findViewById(R.id.motorChildManu); + manu.setText( arg2.getString(arg2.getColumnIndex(MotorDao.MANUFACTURER))); + + TextView desig = (TextView) arg0.findViewById(R.id.motorChildName); + desig.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DESIGNATION))); + + TextView delays = (TextView) arg0.findViewById(R.id.motorChildDelays); + delays.setText( arg2.getString(arg2.getColumnIndex(MotorDao.DELAYS))); + + TextView totImpulse = (TextView) arg0.findViewById(R.id.motorChildImpulse); + totImpulse.setText( arg2.getString(arg2.getColumnIndex(MotorDao.TOTAL_IMPULSE))); + } + + /* (non-Javadoc) + * @see android.widget.CursorTreeAdapter#bindGroupView(android.view.View, android.content.Context, android.database.Cursor, boolean) + */ + @Override + protected void bindGroupView(View view, Context context, Cursor cursor, + boolean isExpanded) { + TextView v = (TextView) view.findViewById(R.id.motorGroup); + if ( MotorDao.DIAMETER.equals(groupColumn)) { + double d = cursor.getDouble( cursor.getColumnIndex(groupColumn)); + v.setText( String.valueOf(Math.round(d * 1000.0)) ); + } else { + v.setText( cursor.getString( cursor.getColumnIndex(groupColumn))); + } + } + + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences arg0, String arg1) { + if ( groupColumnPreferenceKey.equals(arg1) ) { + setGroupColumnFromPreferences(arg0); + refreshData(); + } + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + refreshData(); + + registerForContextMenu(getExpandableListView()); + + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mDbHelper = new DbAdapter(getActivity()); + mDbHelper.open(); + + Resources resources = this.getResources(); + groupColumnPreferenceKey = resources.getString(R.string.PreferenceMotorBrowserGroupingOption); + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity()); + + setGroupColumnFromPreferences(pref); + + pref.registerOnSharedPreferenceChangeListener(this); + + if ( activity instanceof OnMotorSelectedListener ) { + motorSelectedListener = (OnMotorSelectedListener) activity; + } + + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + menu.setHeaderTitle("Motor Operations"); + menu.add(Menu.NONE,CONTEXTMENU_DELETE,CONTEXTMENU_DELETE,"Delete"); + super.onCreateContextMenu(menu, v, menuInfo); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo(); + long motorId = info.id; + AndroidLogWrapper.d(MotorListFragment.class,"ContextMenu: " + motorId); + switch(item.getItemId()) { + case CONTEXTMENU_DELETE: + mDbHelper.getMotorDao().deleteMotor(motorId); + refreshData(); + return true; + } + return super.onContextItemSelected(item); + } + + @Override + public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { + super.onChildClick(parent, v, groupPosition, childPosition, id); + //Intent i = new Intent(this, BurnPlotActivity.class); + if( motorSelectedListener != null ) { + motorSelectedListener.onMotorSelected(id); + } + return true; + } + + @Override + public void onDetach() { + super.onDetach(); + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity()); + pref.unregisterOnSharedPreferenceChangeListener(this); + + // Null out the group cursor. This will cause the group cursor and all of the child cursors + // to be closed. + mAdapter.changeCursor(null); + mAdapter = null; + + mDbHelper.close(); + } + + private void setGroupColumnFromPreferences( SharedPreferences prefs ) { + String indexStr = prefs.getString(groupColumnPreferenceKey, "1"); + int index; + //Dirty hack, you can't use integer-array in ListPreferences + try { + index = Integer.parseInt(indexStr); + } catch ( Exception e ) { + index = 1; + } + if ( index >= groupColumns.length ) { + index = 1; + } + groupColumn = groupColumns[index]; + + } + private void refreshData() { + if (mAdapter != null ) { + mAdapter.changeCursor(null); + } + Cursor motorCursor = mDbHelper.getMotorDao().fetchGroups(groupColumn); + getActivity().startManagingCursor(motorCursor); + // Set up our adapter + mAdapter = new MotorHierarchicalListAdapter( + getActivity(), + motorCursor, + R.layout.motor_list_group, + R.layout.motor_list_child); + setListAdapter(mAdapter); + } +} diff --git a/android/src/net/sf/openrocket/android/motor/PersistentExpandableListActivity.java b/android/src/net/sf/openrocket/android/motor/PersistentExpandableListActivity.java deleted file mode 100644 index f179374a..00000000 --- a/android/src/net/sf/openrocket/android/motor/PersistentExpandableListActivity.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.sf.openrocket.android.motor; - -import java.util.ArrayList; -import java.util.List; - -import android.app.ExpandableListActivity; -import android.os.Bundle; -import android.widget.ExpandableListAdapter; -import android.widget.ExpandableListView; - -public class PersistentExpandableListActivity extends ExpandableListActivity { - private long[] expandedIds; - - @Override - protected void onStart() { - super.onStart(); - if (this.expandedIds != null) { - restoreExpandedState(expandedIds); - } - } - - @Override - protected void onStop() { - super.onStop(); - expandedIds = getExpandedIds(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - this.expandedIds = getExpandedIds(); - outState.putLongArray("ExpandedIds", this.expandedIds); - } - - @Override - protected void onRestoreInstanceState(Bundle state) { - super.onRestoreInstanceState(state); - long[] expandedIds = state.getLongArray("ExpandedIds"); - if (expandedIds != null) { - restoreExpandedState(expandedIds); - } - } - - private long[] getExpandedIds() { - ExpandableListView list = getExpandableListView(); - ExpandableListAdapter adapter = getExpandableListAdapter(); - if (adapter != null) { - int length = adapter.getGroupCount(); - ArrayList expandedIds = new ArrayList(); - for(int i=0; i < length; i++) { - if(list.isGroupExpanded(i)) { - expandedIds.add(adapter.getGroupId(i)); - } - } - return toLongArray(expandedIds); - } else { - return null; - } - } - - private void restoreExpandedState(long[] expandedIds) { - this.expandedIds = expandedIds; - if (expandedIds != null) { - ExpandableListView list = getExpandableListView(); - ExpandableListAdapter adapter = getExpandableListAdapter(); - if (adapter != null) { - for (int i=0; i list) { - long[] ret = new long[list.size()]; - int i = 0; - for (Long e : list) - ret[i++] = e.longValue(); - return ret; - } -} diff --git a/android/src/net/sf/openrocket/android/util/AndroidLogWrapper.java b/android/src/net/sf/openrocket/android/util/AndroidLogWrapper.java new file mode 100644 index 00000000..456136a1 --- /dev/null +++ b/android/src/net/sf/openrocket/android/util/AndroidLogWrapper.java @@ -0,0 +1,55 @@ +package net.sf.openrocket.android.util; + +import java.text.MessageFormat; + +import android.util.Log; + +public class AndroidLogWrapper { + + private static final boolean logEnabled = true; + + public static void d( Class clzz, String msg, Object ... args ) { + + if ( logEnabled ) { + String tag = getTagForClass(clzz); + String formatted = MessageFormat.format(msg, args); + Log.d(tag,formatted); + } + } + + public static void e( Class clzz, String msg, Object ... args ) { + if ( logEnabled ) { + String tag = getTagForClass(clzz); + String formatted = MessageFormat.format(msg, args); + Log.e(tag,formatted); + } + } + + public static void i( Class clzz, String msg, Object ... args ) { + if ( logEnabled ) { + String tag = getTagForClass(clzz); + String formatted = MessageFormat.format(msg, args); + Log.i(tag,formatted); + } + } + public static void v( Class clzz, String msg, Object ... args ) { + if ( logEnabled ) { + String tag = getTagForClass(clzz); + String formatted = MessageFormat.format(msg, args); + Log.v(tag,formatted); + } + } + public static void w( Class clzz, String msg, Object ... args ) { + if ( logEnabled ) { + String tag = getTagForClass(clzz); + String formatted = MessageFormat.format(msg, args); + Log.w(tag,formatted); + } + } + + private static String getTagForClass( Class clzz ) { + String s = clzz.getSimpleName(); + return s; + } + +} diff --git a/android/src/net/sf/openrocket/android/util/ExpandableListFragment.java b/android/src/net/sf/openrocket/android/util/ExpandableListFragment.java new file mode 100644 index 00000000..47fc7fe2 --- /dev/null +++ b/android/src/net/sf/openrocket/android/util/ExpandableListFragment.java @@ -0,0 +1,344 @@ +package net.sf.openrocket.android.util; + +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnCreateContextMenuListener; +import android.view.ViewGroup; +import android.view.animation.AnimationUtils; +import android.widget.AdapterView; +import android.widget.ExpandableListAdapter; +import android.widget.ExpandableListView; +import android.widget.FrameLayout; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.TextView; + +/** + * + * Pulled from https://gist.github.com/1316903 + * + * This class has originally been taken from + * http://stackoverflow.com/questions/6051050/expandablelistfragment-with-loadermanager-for-compatibility-package + * and then modified by Manfred Moser to get it to work with the v4 r4 compatibility + * library. With inspirations from the library source. + * + * All ASLv2 licensed. + */ +public class ExpandableListFragment extends Fragment +implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener, +ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener +{ + + static final int INTERNAL_EMPTY_ID = 0x00ff0001; + static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; + + final private Handler mHandler = new Handler(); + + final private Runnable mRequestFocus = new Runnable() { + public void run() { + mList.focusableViewAvailable(mList); + } + }; + + final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView parent, View v, int position, long id) { + onListItemClick((ListView) parent, v, position, id); + } + }; + + ExpandableListAdapter mAdapter; + ExpandableListView mList; + View mEmptyView; + TextView mStandardEmptyView; + View mListContainer; + boolean mSetEmptyText; + boolean mListShown; + boolean mFinishedStart = false; + + public ExpandableListFragment() { + } + + /** + * Provide default implementation to return a simple list view. Subclasses + * can override to replace with their own layout. If doing so, the + * returned view hierarchy must have a ListView whose id + * is {@link android.R.id#list android.R.id.list} and can optionally + * have a sibling view id {@link android.R.id#empty android.R.id.empty} + * that is to be shown when the list is empty. + *

+ *

If you are overriding this method with your own custom content, + * consider including the standard layout {@link android.R.layout#list_content} + * in your layout file, so that you continue to retain all of the standard + * behavior of ListFragment. In particular, this is currently the only + * way to have the built-in indeterminant progress state be shown. + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + FrameLayout root = new FrameLayout(getActivity()); + + FrameLayout lframe = new FrameLayout(getActivity()); + lframe.setId(INTERNAL_LIST_CONTAINER_ID); + + TextView tv = new TextView(getActivity()); + tv.setId(INTERNAL_EMPTY_ID); + tv.setGravity(Gravity.CENTER); + lframe.addView(tv, + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); + + ExpandableListView lv = new ExpandableListView(getActivity()); + lv.setId(android.R.id.list); + lv.setDrawSelectorOnTop(false); + lv.setOnChildClickListener(this); + lv.setOnGroupExpandListener(this); + lv.setOnGroupCollapseListener(this); + + lframe.addView(lv, + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); + + root.addView(lframe, new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); + + ListView.LayoutParams lp = + new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); + root.setLayoutParams(lp); + + return root; + } + + /** + * Attach to list view once the view hierarchy has been created. + */ + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ensureList(); + } + + /** Detach from list view. */ + @Override + public void onDestroyView() { + mHandler.removeCallbacks(mRequestFocus); + mList = null; + super.onDestroyView(); + } + + /** + * This method will be called when an item in the list is selected. + * Subclasses should override. Subclasses can call + * getListView().getItemAtPosition(position) if they need to access the + * data associated with the selected item. + * @param l The ListView where the click happened + * @param v The view that was clicked within the ListView + * @param position The position of the view in the list + * @param id The row id of the item that was clicked + */ + public void onListItemClick(ListView l, View v, int position, long id) { + } + + /** Provide the cursor for the list view. */ + public void setListAdapter(ExpandableListAdapter adapter) { + boolean hadAdapter = mAdapter != null; + mAdapter = adapter; + if (mList != null) { + mList.setAdapter((ExpandableListAdapter) null); + mList.setAdapter(adapter); + if (!mListShown && !hadAdapter) { + // The list was hidden, and previously didn't have an + // adapter. It is now time to show it. + setListShown(true, getView().getWindowToken() != null); + } + } + } + + /** + * Set the currently selected list item to the specified + * position with the adapter's data + */ + public void setSelection(int position) { + ensureList(); + mList.setSelection(position); + } + + public long getSelectedPosition() { + ensureList(); + return mList.getSelectedPosition(); + } + + public long getSelectedId() { + ensureList(); + return mList.getSelectedId(); + } + + public ExpandableListView getExpandableListView() { + ensureList(); + return mList; + } + + /** + * The default content for a ListFragment has a TextView that can + * be shown when the list is empty. If you would like to have it + * shown, call this method to supply the text it should use. + */ + public void setEmptyText(CharSequence text) { + ensureList(); + if (mStandardEmptyView == null) { + throw new IllegalStateException("Can't be used with a custom content view"); + } + mStandardEmptyView.setText(text); + if (!mSetEmptyText) { + mList.setEmptyView(mStandardEmptyView); + mSetEmptyText = true; + } + } + + /** + * Control whether the list is being displayed. You can make it not + * displayed if you are waiting for the initial data to show in it. During + * this time an indeterminant progress indicator will be shown instead. + *

+ *

Applications do not normally need to use this themselves. The default + * behavior of ListFragment is to start with the list not being shown, only + * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}. + * If the list at that point had not been shown, when it does get shown + * it will be do without the user ever seeing the hidden state. + * @param shown If true, the list view is shown; if false, the progress + * indicator. The initial value is true. + */ + public void setListShown(boolean shown) { + setListShown(shown, true); + } + + /** + * Like {@link #setListShown(boolean)}, but no animation is used when + * transitioning from the previous state. + */ + public void setListShownNoAnimation(boolean shown) { + setListShown(shown, false); + } + + /** + * Control whether the list is being displayed. You can make it not + * displayed if you are waiting for the initial data to show in it. During + * this time an indeterminant progress indicator will be shown instead. + * @param shown If true, the list view is shown; if false, the progress + * indicator. The initial value is true. + * @param animate If true, an animation will be used to transition to the + * new state. + */ + private void setListShown(boolean shown, boolean animate) { + ensureList(); + if (mListShown == shown) { + return; + } + mListShown = shown; + if (mListContainer != null) { + if (shown) { + if (animate) { + mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in)); + } + mListContainer.setVisibility(View.VISIBLE); + } else { + if (animate) { + mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out)); + } + mListContainer.setVisibility(View.GONE); + } + } + } + + /** Get the ListAdapter associated with this activity's ListView. */ + public ExpandableListAdapter getExpandableListAdapter() { + return mAdapter; + } + + private void ensureList() { + if (mList != null) { + return; + } + View root = getView(); + if (root == null) { + throw new IllegalStateException("Content view not yet created"); + } + if (root instanceof ExpandableListView) { + mList = (ExpandableListView) root; + } else { + mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID); + if (mStandardEmptyView == null) { + mEmptyView = root.findViewById(android.R.id.empty); + } + mListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID); + View rawListView = root.findViewById(android.R.id.list); + if (!(rawListView instanceof ExpandableListView)) { + if (rawListView == null) { + throw new RuntimeException("Your content must have a ExpandableListView whose id attribute is " + + "'android.R.id.list'"); + } + throw new RuntimeException("Content has view with id attribute 'android.R.id.list' " + + "that is not a ExpandableListView class"); + } + mList = (ExpandableListView) rawListView; + if (mEmptyView != null) { + mList.setEmptyView(mEmptyView); + } + } + mListShown = true; + mList.setOnItemClickListener(mOnClickListener); + if (mAdapter != null) { + setListAdapter(mAdapter); + } else { + // We are starting without an adapter, so assume we won't + // have our data right away and start with the progress indicator. + setListShown(false, false); + } + mHandler.post(mRequestFocus); + } + + @Override + public void onGroupExpand(int arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onGroupCollapse(int arg0) { + // TODO Auto-generated method stub + + } + + @Override + public boolean onChildClick(ExpandableListView arg0, View arg1, int arg2, int arg3, long arg4) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + } + + public void onContentChanged() { + View emptyView = getView().findViewById(android.R.id.empty); + mList = (ExpandableListView) getView().findViewById(android.R.id.list); + if (mList == null) { + throw new RuntimeException( + "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'"); + } + if (emptyView != null) { + mList.setEmptyView(emptyView); + } + mList.setOnChildClickListener(this); + mList.setOnGroupExpandListener(this); + mList.setOnGroupCollapseListener(this); + + if (mFinishedStart) { + setListAdapter(mAdapter); + } + mFinishedStart = true; + } +} + diff --git a/android/src/net/sf/openrocket/android/util/PersistentExpandableListFragment.java b/android/src/net/sf/openrocket/android/util/PersistentExpandableListFragment.java new file mode 100644 index 00000000..1cc8e659 --- /dev/null +++ b/android/src/net/sf/openrocket/android/util/PersistentExpandableListFragment.java @@ -0,0 +1,145 @@ +package net.sf.openrocket.android.util; + +/* + * TODO - this isn't working. + */ +import java.util.ArrayList; +import java.util.List; + +import android.os.Bundle; +import android.widget.ExpandableListAdapter; +import android.widget.ExpandableListView; + +public class PersistentExpandableListFragment extends ExpandableListFragment { + private long[] expandedIds; + + @Override + public void onCreate(Bundle savedInstanceState) { + AndroidLogWrapper.d(PersistentExpandableListFragment.class, "onCreate"); + super.onCreate(savedInstanceState); + if ( savedInstanceState != null ) { + expandedIds = savedInstanceState.getLongArray("ExpandedIds"); + } + } + + @Override + public void onStop() { + AndroidLogWrapper.d(PersistentExpandableListFragment.class, "onStop"); + super.onStop(); + expandedIds = getExpandedIds(); + } + + @Override + public void onStart() { + AndroidLogWrapper.d(PersistentExpandableListFragment.class, "onStart"); + super.onStart(); + if (this.expandedIds != null) { + restoreExpandedState(expandedIds); + } + } + + @Override + public void onPause() { + AndroidLogWrapper.d(PersistentExpandableListFragment.class, "onPause"); + super.onPause(); + expandedIds = getExpandedIds(); + } + + + @Override + public void onResume() { + AndroidLogWrapper.d(PersistentExpandableListFragment.class, "onResume"); + super.onResume(); + if (this.expandedIds != null) { + restoreExpandedState(expandedIds); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + this.expandedIds = getExpandedIds(); + outState.putLongArray("ExpandedIds", this.expandedIds); + } + + /* + @Override + protected void onStart() { + super.onStart(); + if (this.expandedIds != null) { + restoreExpandedState(expandedIds); + } + } + + @Override + protected void onStop() { + super.onStop(); + expandedIds = getExpandedIds(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + this.expandedIds = getExpandedIds(); + outState.putLongArray("ExpandedIds", this.expandedIds); + } + + @Override + protected void onRestoreInstanceState(Bundle state) { + super.onRestoreInstanceState(state); + long[] expandedIds = state.getLongArray("ExpandedIds"); + if (expandedIds != null) { + restoreExpandedState(expandedIds); + } + } + */ + + + private long[] getExpandedIds() { + ExpandableListView list = getExpandableListView(); + ExpandableListAdapter adapter = getExpandableListAdapter(); + if (adapter != null) { + int length = adapter.getGroupCount(); + ArrayList expandedIds = new ArrayList(); + for(int i=0; i < length; i++) { + if(list.isGroupExpanded(i)) { + expandedIds.add(adapter.getGroupId(i)); + } + } + return toLongArray(expandedIds); + } else { + return null; + } + } + + private void restoreExpandedState(long[] expandedIds) { + this.expandedIds = expandedIds; + if (expandedIds != null) { + ExpandableListView list = getExpandableListView(); + ExpandableListAdapter adapter = getExpandableListAdapter(); + if (adapter != null) { + for (int i=0; i list) { + long[] ret = new long[list.size()]; + int i = 0; + for (Long e : list) + ret[i++] = e.longValue(); + return ret; + } +}