Second checkpoint commit of OpenRocketLoader to make it orientation change safe. Changed Main.java to register onclick listeners in java instead of the layout. Store the WarningSet in Application so it doesn't need to be serialized if the OpenRocketLoaderActivity is recreated during an orientation change. Fix the MissingMotorDialogFragment to only have the string and not the whole WarningSet. Finally completely rewrote the OpenRocketLoaderTask into a Fragment managing its own dialog.

This commit is contained in:
Kevin Ruland 2012-02-08 02:22:45 +00:00
parent 3f37586278
commit 4780fb36b0
8 changed files with 215 additions and 111 deletions

View File

@ -13,34 +13,31 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" > android:orientation="vertical" >
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:text="Welcome to OpenRocket" /> android:text="Welcome to OpenRocket" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="horizontal" > android:orientation="horizontal" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:onClick="pickOrkFiles"
android:text="View ork file" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:onClick="browseMotors"
android:text="View motors" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_open"
android:text="View ork file" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/main_browse"
android:text="View motors" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -27,13 +27,13 @@
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="pickOrkFiles" android:id="@+id/main_open"
android:text="View ork file" /> android:text="View ork file" />
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:onClick="browseMotors" android:id="@+id/main_browse"
android:text="View motors" /> android:text="View motors" />
</LinearLayout> </LinearLayout>

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.android;
import java.util.Locale; import java.util.Locale;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.android.util.AndroidLogWrapper; import net.sf.openrocket.android.util.AndroidLogWrapper;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.l10n.DebugTranslator; import net.sf.openrocket.l10n.DebugTranslator;
@ -12,6 +13,7 @@ import android.preference.PreferenceManager;
public class Application extends android.app.Application { public class Application extends android.app.Application {
private OpenRocketDocument rocketDocument; private OpenRocketDocument rocketDocument;
private WarningSet warnings;
// Big B boolean so I can synchronize on it. // Big B boolean so I can synchronize on it.
private static Boolean initialized = false; private static Boolean initialized = false;
@ -71,6 +73,14 @@ public class Application extends android.app.Application {
public void setRocketDocument(OpenRocketDocument rocketDocument) { public void setRocketDocument(OpenRocketDocument rocketDocument) {
this.rocketDocument = rocketDocument; this.rocketDocument = rocketDocument;
} }
public WarningSet getWarnings() {
return warnings;
}
public void setWarnings(WarningSet warnings) {
this.warnings = warnings;
}

View File

@ -14,6 +14,7 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.Button;
public class Main extends FragmentActivity { public class Main extends FragmentActivity {
@ -24,6 +25,20 @@ public class Main extends FragmentActivity {
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
setContentView(R.layout.main); setContentView(R.layout.main);
((Button) findViewById(R.id.main_open)).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Main.this.pickOrkFiles();
}
});
((Button) findViewById(R.id.main_browse)).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityHelpers.browseMotors(Main.this);
}
});
} }
@Override @Override

View File

@ -10,28 +10,44 @@ import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
public class MissingMotorDialogFragment extends DialogFragment { public class MissingMotorDialogFragment extends DialogFragment {
Set<ThrustCurveMotorPlaceholder> missingMotors; private final static String MESSAGE_ARG_KEY = "message";
public static MissingMotorDialogFragment newInstance( Set<ThrustCurveMotorPlaceholder> missingMotors ) { public static MissingMotorDialogFragment newInstance( Set<ThrustCurveMotorPlaceholder> missingMotors ) {
MissingMotorDialogFragment frag = new MissingMotorDialogFragment(); MissingMotorDialogFragment frag = new MissingMotorDialogFragment();
frag.missingMotors = missingMotors; Bundle b = new Bundle();
b.putString(MESSAGE_ARG_KEY, buildMessage(missingMotors));
frag.setArguments(b);
return frag; return frag;
} }
@Override private static String buildMessage( Set<ThrustCurveMotorPlaceholder> missingMotors ) {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// .setIcon(android.R.drawable.alert_dialog_icon)
builder.setTitle("Missing Motors");
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("The following motors are missing:"); sb.append("The following motors are missing:");
for( ThrustCurveMotorPlaceholder m : missingMotors ) { for( ThrustCurveMotorPlaceholder m : missingMotors ) {
sb.append("\n").append(m.getManufacturer()).append(" ").append(m.getDesignation()); sb.append("\n").append(m.getManufacturer()).append(" ").append(m.getDesignation());
} }
sb.append("\nWould you like to download them from Thrustcurve?"); sb.append("\nWould you like to download them from Thrustcurve?");
builder.setMessage(sb.toString()); return sb.toString();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setCancelable(false);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String message = getArguments().getString(MESSAGE_ARG_KEY);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// .setIcon(android.R.drawable.alert_dialog_icon)
builder.setTitle("Missing Motors");
builder.setMessage(message);
builder.setPositiveButton("OK", builder.setPositiveButton("OK",
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { public void onClick(DialogInterface dialog, int whichButton) {
@ -48,5 +64,18 @@ public class MissingMotorDialogFragment extends DialogFragment {
); );
return builder.create(); return builder.create();
} }
/**
* Work around for dialog getting dismissed on orientation change. See code.google.com/p/android/issues/detail?id=17423
*/
@Override
public void onDestroyView() {
if ( getDialog() != null && getRetainInstance() ) {
getDialog().setDismissMessage(null);
}
super.onDestroyView();
}
} }

View File

@ -10,7 +10,7 @@ import net.sf.openrocket.android.thrustcurve.TCMissingMotorDownloadAction;
import net.sf.openrocket.android.thrustcurve.TCQueryAction; import net.sf.openrocket.android.thrustcurve.TCQueryAction;
import net.sf.openrocket.android.util.AndroidLogWrapper; import net.sf.openrocket.android.util.AndroidLogWrapper;
import net.sf.openrocket.motor.ThrustCurveMotorPlaceholder; import net.sf.openrocket.motor.ThrustCurveMotorPlaceholder;
import android.app.ProgressDialog; import net.sf.openrocket.rocketcomponent.Rocket;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -18,15 +18,11 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
public class OpenRocketLoaderActivity extends FragmentActivity public class OpenRocketLoaderActivity extends FragmentActivity
implements TCQueryAction.OnComplete implements TCQueryAction.OnComplete, OpenRocketLoaderFragment.OnOpenRocketFileLoaded
{ {
private OpenRocketLoaderResult result; private final static String MISSING_MOTOR_DIAG_FRAGMENT_TAG = "missingmotordialog";
private Set<ThrustCurveMotorPlaceholder> missingMotors;
private OpenRocketLoaderTask task;
private ProgressDialog progress;
private DialogFragment missingMotorDialog;
private TCMissingMotorDownloadAction missingMotorDownloadAction; private TCMissingMotorDownloadAction missingMotorDownloadAction;
@Override @Override
@ -39,7 +35,6 @@ implements TCQueryAction.OnComplete
Uri file = i.getData(); Uri file = i.getData();
loadOrkFile(file); loadOrkFile(file);
} else { } else {
progress = ProgressDialog.show(this, "Loading file", "");
} }
} }
@ -51,12 +46,6 @@ implements TCQueryAction.OnComplete
@Override @Override
protected void onDestroy() { protected void onDestroy() {
if ( progress != null ) {
if ( progress.isShowing() ) {
progress.dismiss();
}
progress = null;
}
if ( missingMotorDownloadAction != null ) { if ( missingMotorDownloadAction != null ) {
missingMotorDownloadAction.dismiss(); missingMotorDownloadAction.dismiss();
} }
@ -68,12 +57,9 @@ implements TCQueryAction.OnComplete
AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Use ork file: " + file); AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Use ork file: " + file);
String path = file.getPath(); String path = file.getPath();
File orkFile = new File(path); File orkFile = new File(path);
progress = ProgressDialog.show(this, "Loading file", "");
getSupportFragmentManager().beginTransaction().add( OpenRocketLoaderFragment.newInstance(orkFile), "loader").commit();
task = new OpenRocketLoaderTask(this);
task.execute(orkFile);
} }
/** /**
@ -82,23 +68,21 @@ implements TCQueryAction.OnComplete
* *
* @param result * @param result
*/ */
void finishedLoading(OpenRocketLoaderResult result) { public void onOpenRocketFileLoaded(OpenRocketLoaderResult result) {
if ( progress != null && progress.isShowing() ) {
progress.dismiss();
}
this.result = result;
((Application)OpenRocketLoaderActivity.this.getApplication()).setRocketDocument( result.rocket ); ((Application)OpenRocketLoaderActivity.this.getApplication()).setRocketDocument( result.rocket );
((Application)OpenRocketLoaderActivity.this.getApplication()).setWarnings( result.warnings );
updateMissingMotors(); updateMissingMotors();
} }
private void updateMissingMotors() { private void updateMissingMotors() {
missingMotors = MissingMotorHelpers.findMissingMotors(result.rocket.getRocket()); Rocket rocket = ((Application)OpenRocketLoaderActivity.this.getApplication()).getRocketDocument().getRocket();
Set<ThrustCurveMotorPlaceholder> missingMotors = MissingMotorHelpers.findMissingMotors(rocket);
if ( missingMotors.size() > 0 ) { if ( missingMotors.size() > 0 ) {
missingMotorDialog = MissingMotorDialogFragment.newInstance( missingMotors ); DialogFragment missingMotorDialog = MissingMotorDialogFragment.newInstance( missingMotors );
missingMotorDialog.show(getSupportFragmentManager(), "missing motors"); getSupportFragmentManager().beginTransaction().add(missingMotorDialog, MISSING_MOTOR_DIAG_FRAGMENT_TAG).commit();
return; return;
} }
@ -111,14 +95,16 @@ implements TCQueryAction.OnComplete
@Override @Override
public void onComplete() { public void onComplete() {
Rocket rocket = ((Application)OpenRocketLoaderActivity.this.getApplication()).getRocketDocument().getRocket();
WarningSet warnings = ((Application)OpenRocketLoaderActivity.this.getApplication()).getWarnings();
// Need to update the motor references. // Need to update the motor references.
MissingMotorHelpers.updateMissingMotors(result.rocket.getRocket(), result.warnings); MissingMotorHelpers.updateMissingMotors(rocket, warnings);
displayWarningDialog(); displayWarningDialog();
} }
private void displayWarningDialog() { private void displayWarningDialog() {
WarningSet warnings = result.warnings; WarningSet warnings = ((Application)OpenRocketLoaderActivity.this.getApplication()).getWarnings();
if (warnings == null || warnings.isEmpty()) { if (warnings == null || warnings.isEmpty()) {
} else { } else {
// TODO - Build a warning listing dialog // TODO - Build a warning listing dialog
@ -131,8 +117,8 @@ implements TCQueryAction.OnComplete
} }
public void doFixMissingMotors() { public void doFixMissingMotors() {
Rocket rocket = ((Application)OpenRocketLoaderActivity.this.getApplication()).getRocketDocument().getRocket();
missingMotorDialog.dismiss(); Set<ThrustCurveMotorPlaceholder> missingMotors = MissingMotorHelpers.findMissingMotors(rocket);
missingMotorDownloadAction.setMissingMotors(missingMotors); missingMotorDownloadAction.setMissingMotors(missingMotors);
missingMotorDownloadAction.start(); missingMotorDownloadAction.start();
@ -140,7 +126,6 @@ implements TCQueryAction.OnComplete
} }
public void doNotFixMissingMotors() { public void doNotFixMissingMotors() {
missingMotorDialog.dismiss();
displayWarningDialog(); displayWarningDialog();
} }

View File

@ -0,0 +1,117 @@
package net.sf.openrocket.android.rocket;
import java.io.File;
import net.sf.openrocket.android.util.AndroidLogWrapper;
import net.sf.openrocket.android.util.ProgressDialogFragment;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DatabaseMotorFinderWithMissingMotors;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class OpenRocketLoaderFragment extends Fragment {
private final static String FILE_ARG_KEY = "file";
private final static String LOADING_MESSAGE = "Loading file...";
public interface OnOpenRocketFileLoaded {
public void onOpenRocketFileLoaded( OpenRocketLoaderResult result );
}
private File file;
private OpenRocketLoaderTask task;
private OnOpenRocketFileLoaded listener;
public static OpenRocketLoaderFragment newInstance(File file) {
OpenRocketLoaderFragment frag = new OpenRocketLoaderFragment();
Bundle b = new Bundle();
b.putSerializable(FILE_ARG_KEY, file);
frag.setArguments(b);
return frag;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
Bundle b = getArguments();
file = (File) b.getSerializable(FILE_ARG_KEY);
if ( task == null ) {
// since we retain instance state, task will be non-null if it is already loading.
task = new OpenRocketLoaderTask();
task.execute(file);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return null;
}
@Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
Activity parent = getActivity();
if ( parent instanceof OnOpenRocketFileLoaded ) {
listener = (OnOpenRocketFileLoaded) parent;
}
}
public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketLoaderResult> {
private final static String PROGRESS_DIALOG_TAG = "progress_dialog";
@Override
protected void onPreExecute() {
super.onPreExecute();
DialogFragment newFragment = ProgressDialogFragment.newInstance("", LOADING_MESSAGE);
newFragment.show(getFragmentManager(), PROGRESS_DIALOG_TAG);
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected OpenRocketLoaderResult doInBackground(File... arg0) {
AndroidLogWrapper.d(OpenRocketLoaderTask.class, "doInBackgroud");
OpenRocketLoader rocketLoader = new OpenRocketLoader();
try {
OpenRocketLoaderResult result = new OpenRocketLoaderResult();
OpenRocketDocument rocket = rocketLoader.load(arg0[0], new DatabaseMotorFinderWithMissingMotors());
result.rocket = rocket;
result.warnings = rocketLoader.getWarnings();
return result;
} catch (RocketLoadException ex) {
AndroidLogWrapper.e(OpenRocketLoaderTask.class, "doInBackground rocketLaoder.load threw", ex);
}
return null;
}
@Override
protected void onPostExecute(OpenRocketLoaderResult result) {
super.onPostExecute(result);
AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Finished loading " + OpenRocketLoaderTask.this);
Fragment progress = getActivity().getSupportFragmentManager().findFragmentByTag(PROGRESS_DIALOG_TAG);
if ( progress != null ) {
((DialogFragment)progress).dismiss();
}
if ( listener != null ) {
listener.onOpenRocketFileLoaded(result);
}
}
}
}

View File

@ -1,49 +0,0 @@
package net.sf.openrocket.android.rocket;
import java.io.File;
import net.sf.openrocket.android.util.AndroidLogWrapper;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.file.DatabaseMotorFinderWithMissingMotors;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
import android.app.Activity;
import android.os.AsyncTask;
public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketLoaderResult> {
private OpenRocketLoaderActivity parent;
public OpenRocketLoaderTask( OpenRocketLoaderActivity parent ) {
this.parent = parent;
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected OpenRocketLoaderResult doInBackground(File... arg0) {
AndroidLogWrapper.d(OpenRocketLoaderTask.class, "doInBackgroud");
OpenRocketLoader rocketLoader = new OpenRocketLoader();
try {
OpenRocketLoaderResult result = new OpenRocketLoaderResult();
OpenRocketDocument rocket = rocketLoader.load(arg0[0], new DatabaseMotorFinderWithMissingMotors());
result.rocket = rocket;
result.warnings = result.warnings;
return result;
} catch (RocketLoadException ex) {
AndroidLogWrapper.e(OpenRocketLoaderTask.class, "doInBackground rocketLaoder.load threw", ex);
}
return null;
}
@Override
protected void onPostExecute(OpenRocketLoaderResult result) {
super.onPostExecute(result);
AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Finished loading " + OpenRocketLoaderTask.this);
parent.finishedLoading(result);
}
}