From: kruland2607 Date: Sat, 11 Feb 2012 20:17:39 +0000 (+0000) Subject: Many style and navigation changes. Pulled in ActionBarCompat from Android sample... X-Git-Tag: upstream/12.03~1^2~62 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=6771676f0d4c8699bbcfc302d456e017298523d0;p=debian%2Fopenrocket Many style and navigation changes. Pulled in ActionBarCompat from Android sample sources to provide an action bar paradigm on pre-gingerbread devices. Changed the OpenRocket Viewer activity to use a viewpager with sliding tabs since it looks much nicer. Updated to the newest android-support-v4 jar. git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@409 180e2498-e6e9-4542-8430-84ac67f01cd8 --- diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 010f71bd..5d8e6376 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -6,7 +6,7 @@ + android:targetSdkVersion="15" /> @@ -16,10 +16,11 @@ android:debuggable="true" android:icon="@drawable/or_launcher" android:killAfterRestore="true" - android:label="@string/app_name" > + android:label="@string/app_name" + android:theme="@style/AppTheme" > + android:theme="@style/AppTheme.NoTitleBar" > @@ -28,14 +29,14 @@ + android:theme="@style/AppTheme.NoTitleBar" > @@ -61,9 +62,7 @@ android:scheme="file" /> - + @@ -72,9 +71,13 @@ - + - + diff --git a/android/libs/android-support-v4.jar b/android/libs/android-support-v4.jar index b9a42793..d006198e 100644 Binary files a/android/libs/android-support-v4.jar and b/android/libs/android-support-v4.jar differ diff --git a/android/lint.xml b/android/lint.xml new file mode 100644 index 00000000..ee0eead5 --- /dev/null +++ b/android/lint.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/android/project.properties b/android/project.properties index f049142c..8da376af 100644 --- a/android/project.properties +++ b/android/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-10 +target=android-15 diff --git a/android/res/drawable-hdpi/actionbar_shadow.9.png b/android/res/drawable-hdpi/actionbar_shadow.9.png new file mode 100644 index 00000000..3c80a3fc Binary files /dev/null and b/android/res/drawable-hdpi/actionbar_shadow.9.png differ diff --git a/android/res/drawable-mdpi/actionbar_shadow.9.png b/android/res/drawable-mdpi/actionbar_shadow.9.png new file mode 100644 index 00000000..cae1778f Binary files /dev/null and b/android/res/drawable-mdpi/actionbar_shadow.9.png differ diff --git a/android/res/drawable-mdpi/ic_home_carat.png b/android/res/drawable-mdpi/ic_home_carat.png new file mode 100644 index 00000000..22dad56d Binary files /dev/null and b/android/res/drawable-mdpi/ic_home_carat.png differ diff --git a/android/res/drawable-mdpi/or_launcher.png b/android/res/drawable-mdpi/or_launcher.png new file mode 100644 index 00000000..849b6f1f Binary files /dev/null and b/android/res/drawable-mdpi/or_launcher.png differ diff --git a/android/res/drawable-xhdpi/actionbar_shadow.9.png b/android/res/drawable-xhdpi/actionbar_shadow.9.png new file mode 100644 index 00000000..30778e3f Binary files /dev/null and b/android/res/drawable-xhdpi/actionbar_shadow.9.png differ diff --git a/android/res/drawable-xhdpi/or_launcher.png b/android/res/drawable-xhdpi/or_launcher.png new file mode 100644 index 00000000..77464db0 Binary files /dev/null and b/android/res/drawable-xhdpi/or_launcher.png differ diff --git a/android/res/drawable/actionbar_compat_item.xml b/android/res/drawable/actionbar_compat_item.xml new file mode 100644 index 00000000..4b3960cf --- /dev/null +++ b/android/res/drawable/actionbar_compat_item.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/android/res/drawable/actionbar_compat_item_focused.xml b/android/res/drawable/actionbar_compat_item_focused.xml new file mode 100644 index 00000000..04811d33 --- /dev/null +++ b/android/res/drawable/actionbar_compat_item_focused.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/android/res/drawable/actionbar_compat_item_pressed.xml b/android/res/drawable/actionbar_compat_item_pressed.xml new file mode 100644 index 00000000..72ff4b4f --- /dev/null +++ b/android/res/drawable/actionbar_compat_item_pressed.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/android/res/drawable/home_item.xml b/android/res/drawable/home_item.xml new file mode 100644 index 00000000..9afcd5a0 --- /dev/null +++ b/android/res/drawable/home_item.xml @@ -0,0 +1,4 @@ + + + diff --git a/android/res/drawable/or_launcher.png b/android/res/drawable/or_launcher.png deleted file mode 100644 index 77464db0..00000000 Binary files a/android/res/drawable/or_launcher.png and /dev/null differ diff --git a/android/res/layout-v11/actionbar_indeterminate_progress.xml b/android/res/layout-v11/actionbar_indeterminate_progress.xml new file mode 100644 index 00000000..c05750e0 --- /dev/null +++ b/android/res/layout-v11/actionbar_indeterminate_progress.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/android/res/layout-xlarge-land/openrocketviewer.xml b/android/res/layout-xlarge-land/openrocketviewer.xml index 5ecb9d73..64816245 100644 --- a/android/res/layout-xlarge-land/openrocketviewer.xml +++ b/android/res/layout-xlarge-land/openrocketviewer.xml @@ -4,42 +4,23 @@ android:layout_height="match_parent" android:orientation="horizontal" > - - - - + android:layout_gravity="top" /> + - - - - - - - + android:layout_weight="1" + android:orientation="vertical" /> \ No newline at end of file diff --git a/android/res/layout-xlarge-port/openrocketviewer.xml b/android/res/layout-xlarge-port/openrocketviewer.xml index 055b9748..f0b7ac93 100644 --- a/android/res/layout-xlarge-port/openrocketviewer.xml +++ b/android/res/layout-xlarge-port/openrocketviewer.xml @@ -4,42 +4,23 @@ android:layout_height="match_parent" android:orientation="vertical" > - + android:layout_height="match_parent" + android:layout_weight="3" > - + android:layout_gravity="top" /> + - - - - - - - - - + android:layout_weight="1" + android:orientation="vertical" /> \ No newline at end of file diff --git a/android/res/layout/actionbar_compat.xml b/android/res/layout/actionbar_compat.xml new file mode 100644 index 00000000..7e504d91 --- /dev/null +++ b/android/res/layout/actionbar_compat.xml @@ -0,0 +1,22 @@ + + + diff --git a/android/res/layout/motor_burn.xml b/android/res/layout/motor_burn.xml index 5b8e3a1a..a51b1291 100644 --- a/android/res/layout/motor_burn.xml +++ b/android/res/layout/motor_burn.xml @@ -3,8 +3,8 @@ android:id="@+id/xyplot" android:layout_width="fill_parent" android:layout_height="fill_parent" - android:layout_marginLeft="0px" - android:layout_marginRight="0px" - android:layout_marginTop="5px" - title="plot" + android:layout_marginLeft="2dp" + android:layout_marginRight="2dp" + android:layout_marginTop="5dp" + title=" " /> diff --git a/android/res/layout/openrocketviewer.xml b/android/res/layout/openrocketviewer.xml index efb2b6be..105284ef 100644 --- a/android/res/layout/openrocketviewer.xml +++ b/android/res/layout/openrocketviewer.xml @@ -1,33 +1,18 @@ - + android:layout_height="match_parent" + android:orientation="vertical" > - + android:layout_height="match_parent" > - + android:layout_height="match_parent" + android:layout_gravity="top"/> + - - - - - - + \ No newline at end of file diff --git a/android/res/layout/rocket_overview.xml b/android/res/layout/rocket_overview.xml index 7eca8962..a9cb3ffa 100644 --- a/android/res/layout/rocket_overview.xml +++ b/android/res/layout/rocket_overview.xml @@ -10,44 +10,52 @@ android:orientation="vertical" > + android:layout_height="wrap_content" + android:prompt="@string/overviewConfigurationSpinnerPrompt" /> - - diff --git a/android/res/menu/main_menu.xml b/android/res/menu/main_menu.xml index f378ed0f..1e40af72 100644 --- a/android/res/menu/main_menu.xml +++ b/android/res/menu/main_menu.xml @@ -1,15 +1,10 @@ - - + android:icon="@drawable/ic_menu_preferences" + android:showAsAction="always"/> \ 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 154bd595..05b6e96b 100644 --- a/android/res/menu/motor_browser_option_menu.xml +++ b/android/res/menu/motor_browser_option_menu.xml @@ -7,6 +7,7 @@ + android:title="@string/Preferences" + /> \ 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 4ebd72d4..0afdcd14 100644 --- a/android/res/menu/rocket_viewer_option_menu.xml +++ b/android/res/menu/rocket_viewer_option_menu.xml @@ -3,7 +3,8 @@ + android:title="Motor List" + android:showAsAction="always"/> + + + + + + + + + + \ No newline at end of file diff --git a/android/res/values-v13/styles.xml b/android/res/values-v13/styles.xml new file mode 100644 index 00000000..69466f34 --- /dev/null +++ b/android/res/values-v13/styles.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/android/res/values/actionbar_attrs.xml b/android/res/values/actionbar_attrs.xml new file mode 100644 index 00000000..d7319291 --- /dev/null +++ b/android/res/values/actionbar_attrs.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/android/res/values/actionbar_colors.xml b/android/res/values/actionbar_colors.xml new file mode 100644 index 00000000..57488174 --- /dev/null +++ b/android/res/values/actionbar_colors.xml @@ -0,0 +1,8 @@ + + + + + #FFFFFF + #ff000000 + + diff --git a/android/res/values/actionbar_dimens.xml b/android/res/values/actionbar_dimens.xml new file mode 100644 index 00000000..d0960f0d --- /dev/null +++ b/android/res/values/actionbar_dimens.xml @@ -0,0 +1,21 @@ + + + + 48dp + 48dp + 40dp + diff --git a/android/res/values/actionbar_ids.xml b/android/res/values/actionbar_ids.xml new file mode 100644 index 00000000..d0c08970 --- /dev/null +++ b/android/res/values/actionbar_ids.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/android/res/values/actionbar_styles.xml b/android/res/values/actionbar_styles.xml new file mode 100644 index 00000000..81effec9 --- /dev/null +++ b/android/res/values/actionbar_styles.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index eeb1b494..46a5104f 100644 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -88,12 +88,13 @@ Submit Download from ThrustCurve + Select Configuration Series 1 Series 2 Motor Browser Grouping Use Internal File Browser - uncheck to use system file browser if available + Check to use built in file browser instead of external file browser Millimeters diff --git a/android/res/values/styles.xml b/android/res/values/styles.xml index 005c6007..761a4e1f 100644 --- a/android/res/values/styles.xml +++ b/android/res/values/styles.xml @@ -1,7 +1,17 @@ - - + + + + \ No newline at end of file diff --git a/android/src/net/sf/openrocket/android/Main.java b/android/src/net/sf/openrocket/android/Main.java index 8dacde3a..ee76e9a8 100644 --- a/android/src/net/sf/openrocket/android/Main.java +++ b/android/src/net/sf/openrocket/android/Main.java @@ -51,12 +51,6 @@ public class Main extends FragmentActivity { @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; diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarActivity.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarActivity.java new file mode 100644 index 00000000..a3bad47a --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarActivity.java @@ -0,0 +1,83 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; + +/** + * A base activity that defers common functionality across app activities to an {@link + * ActionBarHelper}. + * + * NOTE: dynamically marking menu items as invisible/visible is not currently supported. + * + * NOTE: this may used with the Android Compatibility Package by extending + * android.support.v4.app.FragmentActivity instead of {@link Activity}. + */ +public abstract class ActionBarActivity extends Activity { + final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this); + + /** + * Returns the {@link ActionBarHelper} for this activity. + */ + protected ActionBarHelper getActionBarHelper() { + return mActionBarHelper; + } + + /**{@inheritDoc}*/ + @Override + public MenuInflater getMenuInflater() { + return mActionBarHelper.getMenuInflater(super.getMenuInflater()); + } + + /**{@inheritDoc}*/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mActionBarHelper.onCreate(savedInstanceState); + } + + /**{@inheritDoc}*/ + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mActionBarHelper.onPostCreate(savedInstanceState); + } + + /** + * Base action bar-aware implementation for + * {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * Note: marking menu items as invisible/visible is not currently supported. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + boolean retValue = false; + retValue |= mActionBarHelper.onCreateOptionsMenu(menu); + retValue |= super.onCreateOptionsMenu(menu); + return retValue; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + mActionBarHelper.onTitleChanged(title, color); + super.onTitleChanged(title, color); + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarFragmentActivity.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarFragmentActivity.java new file mode 100644 index 00000000..526c9622 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarFragmentActivity.java @@ -0,0 +1,84 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.view.Menu; +import android.view.MenuInflater; + +/** + * A base activity that defers common functionality across app activities to an {@link + * ActionBarHelper}. + * + * NOTE: dynamically marking menu items as invisible/visible is not currently supported. + * + * NOTE: this may used with the Android Compatibility Package by extending + * android.support.v4.app.FragmentActivity instead of {@link Activity}. + */ +public abstract class ActionBarFragmentActivity extends FragmentActivity { + final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this); + + /** + * Returns the {@link ActionBarHelper} for this activity. + */ + protected ActionBarHelper getActionBarHelper() { + return mActionBarHelper; + } + + /**{@inheritDoc}*/ + @Override + public MenuInflater getMenuInflater() { + return mActionBarHelper.getMenuInflater(super.getMenuInflater()); + } + + /**{@inheritDoc}*/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mActionBarHelper.onCreate(savedInstanceState); + } + + /**{@inheritDoc}*/ + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mActionBarHelper.onPostCreate(savedInstanceState); + } + + /** + * Base action bar-aware implementation for + * {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * Note: marking menu items as invisible/visible is not currently supported. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + boolean retValue = false; + retValue |= mActionBarHelper.onCreateOptionsMenu(menu); + retValue |= super.onCreateOptionsMenu(menu); + return retValue; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + mActionBarHelper.onTitleChanged(title, color); + super.onTitleChanged(title, color); + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelper.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelper.java new file mode 100644 index 00000000..e0595d8f --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelper.java @@ -0,0 +1,102 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import net.sf.openrocket.R; +import android.app.Activity; +import android.os.Build; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; + +/** + * An abstract class that handles some common action bar-related functionality in the app. This + * class provides functionality useful for both phones and tablets, and does not require any Android + * 3.0-specific features, although it uses them if available. + * + * Two implementations of this class are {@link ActionBarHelperBase} for a pre-Honeycomb version of + * the action bar, and {@link ActionBarHelperHoneycomb}, which uses the built-in ActionBar features + * in Android 3.0 and later. + */ +public abstract class ActionBarHelper { + protected Activity mActivity; + + /** + * Factory method for creating {@link ActionBarHelper} objects for a + * given activity. Depending on which device the app is running, either a basic helper or + * Honeycomb-specific helper will be returned. + */ + public static ActionBarHelper createInstance(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return new ActionBarHelperICS(activity); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return new ActionBarHelperHoneycomb(activity); + } else { + return new ActionBarHelperBase(activity); + } + } + + protected ActionBarHelper(Activity activity) { + mActivity = activity; + } + + /** + * Action bar helper code to be run in {@link Activity#onCreate(android.os.Bundle)}. + */ + public void onCreate(Bundle savedInstanceState) { + } + + /** + * Action bar helper code to be run in {@link Activity#onPostCreate(android.os.Bundle)}. + */ + public void onPostCreate(Bundle savedInstanceState) { + } + + /** + * Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * NOTE: Setting the visibility of menu items in menu is not currently supported. + */ + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + /** + * Action bar helper code to be run in {@link Activity#onTitleChanged(CharSequence, int)}. + */ + protected void onTitleChanged(CharSequence title, int color) { + } + + /** + * Sets the indeterminate loading state of the item with ID {@link R.id.menu_refresh}. + * (where the item ID was menu_refresh). + */ + public abstract void setRefreshActionItemState(boolean refreshing); + + /** + * Returns a {@link MenuInflater} for use when inflating menus. The implementation of this + * method in {@link ActionBarHelperBase} returns a wrapped menu inflater that can read + * action bar metadata from a menu resource pre-Honeycomb. + */ + public MenuInflater getMenuInflater(MenuInflater superMenuInflater) { + return superMenuInflater; + } + + public abstract void setDisplayHomeAsUpEnabled( boolean enabled ); + + public abstract void hide(); +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperBase.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperBase.java new file mode 100644 index 00000000..6c8054f7 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperBase.java @@ -0,0 +1,331 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import net.sf.openrocket.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.app.Activity; +import android.content.Context; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.view.Gravity; +import android.view.InflateException; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +/** + * A class that implements the action bar pattern for pre-Honeycomb devices. + */ +public class ActionBarHelperBase extends ActionBarHelper { + private static final String MENU_RES_NAMESPACE = "http://schemas.android.com/apk/res/android"; + private static final String MENU_ATTR_ID = "id"; + private static final String MENU_ATTR_SHOW_AS_ACTION = "showAsAction"; + + private boolean showHomeAsUpEnabled = false; + + protected Set mActionItemIds = new HashSet(); + + protected ActionBarHelperBase(Activity activity) { + super(activity); + } + + /**{@inheritDoc}*/ + @Override + public void onCreate(Bundle savedInstanceState) { + mActivity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); + } + + /**{@inheritDoc}*/ + @Override + public void onPostCreate(Bundle savedInstanceState) { + mActivity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, + R.layout.actionbar_compat); + setupActionBar(); + + SimpleMenu menu = new SimpleMenu(mActivity); + mActivity.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu); + mActivity.onPrepareOptionsMenu(menu); + for (int i = 0; i < menu.size(); i++) { + MenuItem item = menu.getItem(i); + if (mActionItemIds.contains(item.getItemId())) { + addActionItemCompatFromMenuItem(item); + } + } + } + + /** + * Sets up the compatibility action bar with the given title. + */ + private void setupActionBar() { + final ViewGroup actionBarCompat = getActionBarCompat(); + if (actionBarCompat == null) { + return; + } + + LinearLayout.LayoutParams springLayoutParams = new LinearLayout.LayoutParams( + 0, ViewGroup.LayoutParams.FILL_PARENT); + springLayoutParams.weight = 1; + + // Add Home as Up Carat + ImageButton homeAsUp = new ImageButton(mActivity,null, R.attr.actionbarCompatHomeAsUpStyle); + homeAsUp.setId(R.id.actionbar_home_as_up); + LinearLayout.LayoutParams centerVerticalParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + centerVerticalParams.gravity = Gravity.CENTER_VERTICAL; + homeAsUp.setLayoutParams(centerVerticalParams); + homeAsUp.setVisibility( showHomeAsUpEnabled ? View.VISIBLE : View.INVISIBLE ); + actionBarCompat.addView(homeAsUp); + + // Add Home button + SimpleMenu tempMenu = new SimpleMenu(mActivity); + SimpleMenuItem homeItem = new SimpleMenuItem( + tempMenu, android.R.id.home, 0, mActivity.getString(R.string.app_name)); + homeItem.setIcon(R.drawable.home_item); + addActionItemCompatFromMenuItem(homeItem); + + // Add title text + TextView titleText = new TextView(mActivity, null, R.attr.actionbarCompatTitleStyle); + titleText.setLayoutParams(springLayoutParams); + titleText.setText(mActivity.getTitle()); + actionBarCompat.addView(titleText); + + } + + /**{@inheritDoc}*/ + @Override + public void setRefreshActionItemState(boolean refreshing) { + View refreshButton = mActivity.findViewById(R.id.actionbar_compat_item_refresh); + View refreshIndicator = mActivity.findViewById( + R.id.actionbar_compat_item_refresh_progress); + + if (refreshButton != null) { + refreshButton.setVisibility(refreshing ? View.GONE : View.VISIBLE); + } + if (refreshIndicator != null) { + refreshIndicator.setVisibility(refreshing ? View.VISIBLE : View.GONE); + } + } + + /** + * Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * NOTE: This code will mark on-screen menu items as invisible. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Hides on-screen action items from the options menu. + for (Integer id : mActionItemIds) { + menu.findItem(id).setVisible(false); + } + return true; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + TextView titleView = (TextView) mActivity.findViewById(R.id.actionbar_compat_title); + if (titleView != null) { + titleView.setText(title); + } + } + + /** + * Returns a {@link android.view.MenuInflater} that can read action bar metadata on + * pre-Honeycomb devices. + */ + public MenuInflater getMenuInflater(MenuInflater superMenuInflater) { + return new WrappedMenuInflater(mActivity, superMenuInflater); + } + + @Override + public void setDisplayHomeAsUpEnabled(boolean enabled) { + showHomeAsUpEnabled = enabled; + View v = mActivity.findViewById(R.id.actionbar_home_as_up); + if ( v != null ) { + v.setVisibility( showHomeAsUpEnabled ? View.VISIBLE : View.INVISIBLE ); + } + + } + + @Override + public void hide() { + ViewGroup actionbar = getActionBarCompat(); + actionbar.setVisibility(View.GONE); + } + /** + * Returns the {@link android.view.ViewGroup} for the action bar on phones (compatibility action + * bar). Can return null, and will return null on Honeycomb. + */ + private ViewGroup getActionBarCompat() { + return (ViewGroup) mActivity.findViewById(R.id.actionbar_compat); + } + + /** + * Adds an action button to the compatibility action bar, using menu information from a {@link + * android.view.MenuItem}. If the menu item ID is menu_refresh, the menu item's + * state can be changed to show a loading spinner using + * {@link com.example.android.actionbarcompat.ActionBarHelperBase#setRefreshActionItemState(boolean)}. + */ + private View addActionItemCompatFromMenuItem(final MenuItem item) { + final int itemId = item.getItemId(); + + final ViewGroup actionBar = getActionBarCompat(); + if (actionBar == null) { + return null; + } + + // Create the button + ImageButton actionButton = new ImageButton(mActivity, null, + itemId == android.R.id.home + ? R.attr.actionbarCompatItemHomeStyle + : R.attr.actionbarCompatItemStyle); + actionButton.setLayoutParams(new ViewGroup.LayoutParams( + (int) mActivity.getResources().getDimension( + itemId == android.R.id.home + ? R.dimen.actionbar_compat_button_home_width + : R.dimen.actionbar_compat_button_width), + ViewGroup.LayoutParams.FILL_PARENT)); + if (itemId == R.id.menu_refresh) { + actionButton.setId(R.id.actionbar_compat_item_refresh); + } + actionButton.setImageDrawable(item.getIcon()); + actionButton.setScaleType(ImageView.ScaleType.CENTER); + actionButton.setContentDescription(item.getTitle()); + actionButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + mActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); + } + }); + + actionBar.addView(actionButton); + + if (item.getItemId() == R.id.menu_refresh) { + // Refresh buttons should be stateful, and allow for indeterminate progress indicators, + // so add those. + ProgressBar indicator = new ProgressBar(mActivity, null, + R.attr.actionbarCompatProgressIndicatorStyle); + + final int buttonWidth = mActivity.getResources().getDimensionPixelSize( + R.dimen.actionbar_compat_button_width); + final int buttonHeight = mActivity.getResources().getDimensionPixelSize( + R.dimen.actionbar_compat_height); + final int progressIndicatorWidth = buttonWidth / 2; + + LinearLayout.LayoutParams indicatorLayoutParams = new LinearLayout.LayoutParams( + progressIndicatorWidth, progressIndicatorWidth); + indicatorLayoutParams.setMargins( + (buttonWidth - progressIndicatorWidth) / 2, + (buttonHeight - progressIndicatorWidth) / 2, + (buttonWidth - progressIndicatorWidth) / 2, + 0); + indicator.setLayoutParams(indicatorLayoutParams); + indicator.setVisibility(View.GONE); + indicator.setId(R.id.actionbar_compat_item_refresh_progress); + actionBar.addView(indicator); + } + + return actionButton; + } + + /** + * A {@link android.view.MenuInflater} that reads action bar metadata. + */ + private class WrappedMenuInflater extends MenuInflater { + MenuInflater mInflater; + + public WrappedMenuInflater(Context context, MenuInflater inflater) { + super(context); + mInflater = inflater; + } + + @Override + public void inflate(int menuRes, Menu menu) { + loadActionBarMetadata(menuRes); + mInflater.inflate(menuRes, menu); + } + + /** + * Loads action bar metadata from a menu resource, storing a list of menu item IDs that + * should be shown on-screen (i.e. those with showAsAction set to always or ifRoom). + * @param menuResId + */ + private void loadActionBarMetadata(int menuResId) { + XmlResourceParser parser = null; + try { + parser = mActivity.getResources().getXml(menuResId); + + int eventType = parser.getEventType(); + int itemId; + int showAsAction; + + boolean eof = false; + while (!eof) { + switch (eventType) { + case XmlPullParser.START_TAG: + if (!parser.getName().equals("item")) { + break; + } + + itemId = parser.getAttributeResourceValue(MENU_RES_NAMESPACE, + MENU_ATTR_ID, 0); + if (itemId == 0) { + break; + } + + showAsAction = parser.getAttributeIntValue(MENU_RES_NAMESPACE, + MENU_ATTR_SHOW_AS_ACTION, -1); + if (showAsAction == MenuItem.SHOW_AS_ACTION_ALWAYS || + showAsAction == MenuItem.SHOW_AS_ACTION_IF_ROOM) { + mActionItemIds.add(itemId); + } + break; + + case XmlPullParser.END_DOCUMENT: + eof = true; + break; + } + + eventType = parser.next(); + } + } catch (XmlPullParserException e) { + throw new InflateException("Error inflating menu XML", e); + } catch (IOException e) { + throw new InflateException("Error inflating menu XML", e); + } finally { + if (parser != null) { + parser.close(); + } + } + } + + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperHoneycomb.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperHoneycomb.java new file mode 100644 index 00000000..e31a4f91 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperHoneycomb.java @@ -0,0 +1,90 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import net.sf.openrocket.R; +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +/** + * An extension of {@link ActionBarHelper} that provides Android 3.0-specific functionality for + * Honeycomb tablets. It thus requires API level 11. + */ +public class ActionBarHelperHoneycomb extends ActionBarHelper { + private Menu mOptionsMenu; + private View mRefreshIndeterminateProgressView = null; + + protected ActionBarHelperHoneycomb(Activity activity) { + super(activity); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + mOptionsMenu = menu; + return super.onCreateOptionsMenu(menu); + } + + @Override + public void setRefreshActionItemState(boolean refreshing) { + // On Honeycomb, we can set the state of the refresh button by giving it a custom + // action view. + if (mOptionsMenu == null) { + return; + } + + final MenuItem refreshItem = mOptionsMenu.findItem(R.id.menu_refresh); + if (refreshItem != null) { + if (refreshing) { + if (mRefreshIndeterminateProgressView == null) { + LayoutInflater inflater = (LayoutInflater) + getActionBarThemedContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + mRefreshIndeterminateProgressView = inflater.inflate( + R.layout.actionbar_indeterminate_progress, null); + } + + refreshItem.setActionView(mRefreshIndeterminateProgressView); + } else { + refreshItem.setActionView(null); + } + } + } + + /** + * Returns a {@link Context} suitable for inflating layouts for the action bar. The + * implementation for this method in {@link ActionBarHelperICS} asks the action bar for a + * themed context. + */ + protected Context getActionBarThemedContext() { + return mActivity; + } + + @Override + public void setDisplayHomeAsUpEnabled(boolean enabled) { + mActivity.getActionBar().setDisplayHomeAsUpEnabled(enabled); + } + + @Override + public void hide() { + mActivity.getActionBar().hide(); + } + +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperICS.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperICS.java new file mode 100644 index 00000000..7d006129 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarHelperICS.java @@ -0,0 +1,35 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import android.app.Activity; +import android.content.Context; + +/** + * An extension of {@link com.example.android.actionbarcompat.ActionBarHelper} that provides Android + * 4.0-specific functionality for IceCreamSandwich devices. It thus requires API level 14. + */ +public class ActionBarHelperICS extends ActionBarHelperHoneycomb { + protected ActionBarHelperICS(Activity activity) { + super(activity); + } + + @Override + protected Context getActionBarThemedContext() { + return mActivity.getActionBar().getThemedContext(); + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarListActivity.java b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarListActivity.java new file mode 100644 index 00000000..b8132089 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/ActionBarListActivity.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2006 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import android.app.Activity; +import android.app.ListActivity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; + +public abstract class ActionBarListActivity extends ListActivity { + final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this); + + /** + * Returns the {@link ActionBarHelper} for this activity. + */ + protected ActionBarHelper getActionBarHelper() { + return mActionBarHelper; + } + + /**{@inheritDoc}*/ + @Override + public MenuInflater getMenuInflater() { + return mActionBarHelper.getMenuInflater(super.getMenuInflater()); + } + + /**{@inheritDoc}*/ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mActionBarHelper.onCreate(savedInstanceState); + } + + /**{@inheritDoc}*/ + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + mActionBarHelper.onPostCreate(savedInstanceState); + } + + /** + * Base action bar-aware implementation for + * {@link Activity#onCreateOptionsMenu(android.view.Menu)}. + * + * Note: marking menu items as invisible/visible is not currently supported. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + boolean retValue = false; + retValue |= mActionBarHelper.onCreateOptionsMenu(menu); + retValue |= super.onCreateOptionsMenu(menu); + return retValue; + } + + /**{@inheritDoc}*/ + @Override + protected void onTitleChanged(CharSequence title, int color) { + mActionBarHelper.onTitleChanged(title, color); + super.onTitleChanged(title, color); + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenu.java b/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenu.java new file mode 100644 index 00000000..fb9a48f3 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenu.java @@ -0,0 +1,203 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import java.util.ArrayList; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +/** + * A really dumb implementation of the {@link android.view.Menu} interface, that's only + * useful for our actionbar-compat purposes. See + * com.android.internal.view.menu.MenuBuilder in AOSP for a more complete + * implementation. + */ +public class SimpleMenu implements Menu { + + private Context mContext; + private Resources mResources; + + private ArrayList mItems; + + public SimpleMenu(Context context) { + mContext = context; + mResources = context.getResources(); + mItems = new ArrayList(); + } + + public Context getContext() { + return mContext; + } + + public Resources getResources() { + return mResources; + } + + public MenuItem add(CharSequence title) { + return addInternal(0, 0, title); + } + + public MenuItem add(int titleRes) { + return addInternal(0, 0, mResources.getString(titleRes)); + } + + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + return addInternal(itemId, order, title); + } + + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return addInternal(itemId, order, mResources.getString(titleRes)); + } + + /** + * Adds an item to the menu. The other add methods funnel to this. + */ + private MenuItem addInternal(int itemId, int order, CharSequence title) { + final SimpleMenuItem item = new SimpleMenuItem(this, itemId, order, title); + mItems.add(findInsertIndex(mItems, order), item); + return item; + } + + private static int findInsertIndex(ArrayList items, int order) { + for (int i = items.size() - 1; i >= 0; i--) { + MenuItem item = items.get(i); + if (item.getOrder() <= order) { + return i + 1; + } + } + + return 0; + } + + public int findItemIndex(int id) { + final int size = size(); + + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return i; + } + } + + return -1; + } + + public void removeItem(int itemId) { + removeItemAtInt(findItemIndex(itemId)); + } + + private void removeItemAtInt(int index) { + if ((index < 0) || (index >= mItems.size())) { + return; + } + mItems.remove(index); + } + + public void clear() { + mItems.clear(); + } + + public MenuItem findItem(int id) { + final int size = size(); + for (int i = 0; i < size; i++) { + SimpleMenuItem item = mItems.get(i); + if (item.getItemId() == id) { + return item; + } + } + + return null; + } + + public int size() { + return mItems.size(); + } + + public MenuItem getItem(int index) { + return mItems.get(index); + } + + // Unsupported operations. + + public SubMenu addSubMenu(CharSequence charSequence) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public int addIntentOptions(int i, int i1, int i2, ComponentName componentName, + Intent[] intents, Intent intent, int i3, MenuItem[] menuItems) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void removeGroup(int i) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupCheckable(int i, boolean b, boolean b1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupVisible(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setGroupEnabled(int i, boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean hasVisibleItems() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void close() { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performShortcut(int i, KeyEvent keyEvent, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean isShortcutKey(int i, KeyEvent keyEvent) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public boolean performIdentifierAction(int i, int i1) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } + + public void setQwertyMode(boolean b) { + throw new UnsupportedOperationException("This operation is not supported for SimpleMenu"); + } +} diff --git a/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenuItem.java b/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenuItem.java new file mode 100644 index 00000000..8af4c5d7 --- /dev/null +++ b/android/src/net/sf/openrocket/android/actionbarcompat/SimpleMenuItem.java @@ -0,0 +1,260 @@ +/* + * Copyright 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. + */ + +package net.sf.openrocket.android.actionbarcompat; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ActionProvider; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.SubMenu; +import android.view.View; + +/** + * A really dumb implementation of the {@link android.view.MenuItem} interface, that's only + * useful for our actionbar-compat purposes. See + * com.android.internal.view.menu.MenuItemImpl in AOSP for a more complete + * implementation. + */ +public class SimpleMenuItem implements MenuItem { + + private SimpleMenu mMenu; + + private final int mId; + private final int mOrder; + private CharSequence mTitle; + private CharSequence mTitleCondensed; + private Drawable mIconDrawable; + private int mIconResId = 0; + private boolean mEnabled = true; + + public SimpleMenuItem(SimpleMenu menu, int id, int order, CharSequence title) { + mMenu = menu; + mId = id; + mOrder = order; + mTitle = title; + } + + public int getItemId() { + return mId; + } + + public int getOrder() { + return mOrder; + } + + public MenuItem setTitle(CharSequence title) { + mTitle = title; + return this; + } + + public MenuItem setTitle(int titleRes) { + return setTitle(mMenu.getContext().getString(titleRes)); + } + + public CharSequence getTitle() { + return mTitle; + } + + public MenuItem setTitleCondensed(CharSequence title) { + mTitleCondensed = title; + return this; + } + + public CharSequence getTitleCondensed() { + return mTitleCondensed != null ? mTitleCondensed : mTitle; + } + + public MenuItem setIcon(Drawable icon) { + mIconResId = 0; + mIconDrawable = icon; + return this; + } + + public MenuItem setIcon(int iconResId) { + mIconDrawable = null; + mIconResId = iconResId; + return this; + } + + public Drawable getIcon() { + if (mIconDrawable != null) { + return mIconDrawable; + } + + if (mIconResId != 0) { + return mMenu.getResources().getDrawable(mIconResId); + } + + return null; + } + + public MenuItem setEnabled(boolean enabled) { + mEnabled = enabled; + return this; + } + + public boolean isEnabled() { + return mEnabled; + } + + // No-op operations. We use no-ops to allow inflation from menu XML. + + public int getGroupId() { + // Noop + return 0; + } + + public View getActionView() { + // Noop + return null; + } + + public MenuItem setActionProvider(ActionProvider actionProvider) { + // Noop + return this; + } + + public ActionProvider getActionProvider() { + // Noop + return null; + } + + public boolean expandActionView() { + // Noop + return false; + } + + public boolean collapseActionView() { + // Noop + return false; + } + + public boolean isActionViewExpanded() { + // Noop + return false; + } + + public MenuItem setOnActionExpandListener(OnActionExpandListener onActionExpandListener) { + // Noop + return this; + } + + public MenuItem setIntent(Intent intent) { + // Noop + return this; + } + + public Intent getIntent() { + // Noop + return null; + } + + public MenuItem setShortcut(char c, char c1) { + // Noop + return this; + } + + public MenuItem setNumericShortcut(char c) { + // Noop + return this; + } + + public char getNumericShortcut() { + // Noop + return 0; + } + + public MenuItem setAlphabeticShortcut(char c) { + // Noop + return this; + } + + public char getAlphabeticShortcut() { + // Noop + return 0; + } + + public MenuItem setCheckable(boolean b) { + // Noop + return this; + } + + public boolean isCheckable() { + // Noop + return false; + } + + public MenuItem setChecked(boolean b) { + // Noop + return this; + } + + public boolean isChecked() { + // Noop + return false; + } + + public MenuItem setVisible(boolean b) { + // Noop + return this; + } + + public boolean isVisible() { + // Noop + return true; + } + + public boolean hasSubMenu() { + // Noop + return false; + } + + public SubMenu getSubMenu() { + // Noop + return null; + } + + public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) { + // Noop + return this; + } + + public ContextMenu.ContextMenuInfo getMenuInfo() { + // Noop + return null; + } + + public void setShowAsAction(int i) { + // Noop + } + + public MenuItem setShowAsActionFlags(int i) { + // Noop + return null; + } + + public MenuItem setActionView(View view) { + // Noop + return this; + } + + public MenuItem setActionView(int i) { + // Noop + return this; + } +} diff --git a/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java b/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java index 853f4889..1c4ff406 100644 --- a/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java +++ b/android/src/net/sf/openrocket/android/filebrowser/SimpleFileBrowser.java @@ -9,8 +9,8 @@ import java.util.Comparator; import java.util.List; import net.sf.openrocket.R; +import net.sf.openrocket.android.actionbarcompat.ActionBarListActivity; import android.app.AlertDialog; -import android.app.ListActivity; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; @@ -19,14 +19,12 @@ import android.os.Environment; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; -import android.widget.TextView; -public class SimpleFileBrowser extends ListActivity { +public class SimpleFileBrowser extends ActionBarListActivity { private List item = null; private List path = null; private String root = "/"; - private TextView myPath; private static final OrkFileFilter filter = new OrkFileFilter(); private static final Collator sorter = Collator.getInstance(); @@ -40,7 +38,6 @@ public class SimpleFileBrowser extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simplefilebrowser); - myPath = (TextView) findViewById(R.id.path); getDir( Environment.getExternalStorageDirectory().getAbsolutePath() ); } @@ -88,7 +85,7 @@ public class SimpleFileBrowser extends ListActivity { } private void getDir(String dirPath) { - myPath.setText("Location: " + dirPath); + setTitle(dirPath); item = new ArrayList(); path = new ArrayList(); diff --git a/android/src/net/sf/openrocket/android/motor/BurnPlotActivity.java b/android/src/net/sf/openrocket/android/motor/BurnPlotActivity.java index f1d00cf3..03aa88f3 100644 --- a/android/src/net/sf/openrocket/android/motor/BurnPlotActivity.java +++ b/android/src/net/sf/openrocket/android/motor/BurnPlotActivity.java @@ -19,5 +19,5 @@ public class BurnPlotActivity extends FragmentActivity { getSupportFragmentManager().beginTransaction().replace(android.R.id.content, burnPlot).commit(); } - + } diff --git a/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java b/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java index 7600f2a0..1f0c7225 100644 --- a/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java +++ b/android/src/net/sf/openrocket/android/motor/BurnPlotFragment.java @@ -8,6 +8,7 @@ import net.sf.openrocket.R; import net.sf.openrocket.android.db.DbAdapter; import net.sf.openrocket.android.util.AndroidLogWrapper; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.PointF; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -48,25 +49,25 @@ public class BurnPlotFragment extends Fragment implements OnTouchListener { frag.setArguments(bundle); return frag; } - + @Override public void onCreate(Bundle savedInstanceState) { AndroidLogWrapper.d(BurnPlotFragment.class,"onCreate"); - + if ( savedInstanceState!= null) { motorId = savedInstanceState.getLong("motorId",-1); } else { Bundle b = getArguments(); motorId = b.getLong("motorId"); } - + DbAdapter mDbHelper = new DbAdapter(getActivity()); mDbHelper.open(); try { motor = mDbHelper.getMotorDao().fetchMotor(motorId); } catch ( Exception e ) { - + } mDbHelper.close(); @@ -98,22 +99,25 @@ public class BurnPlotFragment extends Fragment implements OnTouchListener { } return l; } - + private void init( ExtendedThrustCurveMotor motor ) { mySimpleXYPlot.setUserDomainOrigin(0); mySimpleXYPlot.setUserRangeOrigin(0); mySimpleXYPlot.setRangeLabel("impuse (n)"); mySimpleXYPlot.setDomainLabel("time (s)"); - mySimpleXYPlot.addMarker(new YValueMarker(motor.getThrustCurveMotor().getAverageThrustEstimate(),"average" )); + YValueMarker average = new YValueMarker(motor.getThrustCurveMotor().getAverageThrustEstimate(),"average" ); + average.getLinePaint().setColor(Color.BLACK); + average.getTextPaint().setColor(Color.BLACK); + mySimpleXYPlot.addMarker( average ); mySimpleXYPlot.disableAllMarkup(); - try { mySeries = new SimpleXYSeries( fromArray(motor.getThrustCurveMotor().getTimePoints()), - fromArray(motor.getThrustCurveMotor().getThrustPoints()), - motor.getThrustCurveMotor().getDesignation()); + fromArray(motor.getThrustCurveMotor().getThrustPoints()), + motor.getThrustCurveMotor().getManufacturer().getDisplayName() + " " + motor.getThrustCurveMotor().getDesignation() + ); } catch ( Exception ex ) { Vector data = new Vector(); @@ -124,8 +128,11 @@ public class BurnPlotFragment extends Fragment implements OnTouchListener { mySeries = new SimpleXYSeries(data, SimpleXYSeries.ArrayFormat.XY_VALS_INTERLEAVED,"no data"); } - mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class, - new LineAndPointFormatter(Color.rgb(0, 255, 0), Color.rgb(200, 0, 0), null)); + LineAndPointFormatter formatter= new LineAndPointFormatter(Color.RED, Color.GREEN, Color.GREEN); + + formatter.getLinePaint().setShadowLayer(0, 0, 0, 0); + formatter.getVertexPaint().setShadowLayer(0, 0, 0, 0); + mySimpleXYPlot.addSeries(mySeries, LineAndPointRenderer.class,formatter); //Set of internal variables for keeping track of the boundaries mySimpleXYPlot.calculateMinMaxVals(); diff --git a/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java b/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java index 282baec2..34a92b98 100644 --- a/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java +++ b/android/src/net/sf/openrocket/android/motor/MotorBrowserActivity.java @@ -3,18 +3,18 @@ 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.actionbarcompat.ActionBarFragmentActivity; import net.sf.openrocket.android.util.AndroidLogWrapper; 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 +public class MotorBrowserActivity extends ActionBarFragmentActivity implements MotorListFragment.OnMotorSelectedListener { @@ -27,6 +27,7 @@ implements MotorListFragment.OnMotorSelectedListener public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.motorbrowser); + getActionBarHelper().setDisplayHomeAsUpEnabled(true); getSupportFragmentManager().beginTransaction().add( R.id.motorBrowserList, new MotorListFragment()).commit(); } @@ -41,6 +42,9 @@ implements MotorListFragment.OnMotorSelectedListener public boolean onMenuItemSelected(int featureId, MenuItem item) { AndroidLogWrapper.d(MotorBrowserActivity.class,"onMenuItemSelected" + item.getItemId()); switch(item.getItemId()) { + case android.R.id.home: + finish(); + return true; case R.id.download_from_thrustcurve_menu_option: ActivityHelpers.downloadFromThrustcurve(this,DOWNLOAD_REQUEST_CODE); return true; diff --git a/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java b/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java index 9362c8bf..5ea79827 100644 --- a/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java +++ b/android/src/net/sf/openrocket/android/rocket/OpenRocketViewer.java @@ -4,72 +4,45 @@ package net.sf.openrocket.android.rocket; import net.sf.openrocket.R; import net.sf.openrocket.android.ActivityHelpers; import net.sf.openrocket.android.Application; +import net.sf.openrocket.android.actionbarcompat.ActionBarFragmentActivity; 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.util.AndroidLogWrapper; -import net.sf.openrocket.android.util.TabsAdapter; -import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.Simulation; -import net.sf.openrocket.rocketcomponent.Configuration; 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.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.TabHost; -public class OpenRocketViewer extends FragmentActivity +public class OpenRocketViewer extends ActionBarFragmentActivity implements Simulations.OnSimulationSelectedListener { - OpenRocketDocument rocketDocument; - Configuration rocketConfiguration; - private Application app; - TabHost mTabHost; - ViewPager mViewPager; - TabsAdapter mTabsAdapter; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = (Application) this.getApplication(); - setContentView(R.layout.openrocketviewer); - - mTabHost = (TabHost)findViewById(android.R.id.tabhost); - mTabHost.setup(); - - mViewPager = (ViewPager)findViewById(R.id.pager); - - mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager); - - 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); - - if (savedInstanceState != null) { - mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); - } + ViewPager viewPager = (ViewPager)findViewById(R.id.pager); + viewPager.setAdapter( new OpenRocketViewerPager( this.getSupportFragmentManager())); + + setTitle(app.getRocketDocument().getRocket().getName()); + + getActionBarHelper().setDisplayHomeAsUpEnabled(true); + } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString("tab", mTabHost.getCurrentTabTag()); - } - + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); @@ -81,6 +54,9 @@ implements Simulations.OnSimulationSelectedListener public boolean onMenuItemSelected(int featureId, MenuItem item) { AndroidLogWrapper.d(OpenRocketViewer.class,"onMenuItemSelected" + item.getItemId()); switch(item.getItemId()) { + case android.R.id.home: + finish(); + return true; case R.id.motor_list_menu_option: ActivityHelpers.browseMotors(this); return true; @@ -116,4 +92,39 @@ implements Simulations.OnSimulationSelectedListener } } + private class OpenRocketViewerPager extends FragmentPagerAdapter { + + public OpenRocketViewerPager( FragmentManager fm ) { + super(fm); + } + @Override + public int getCount() { + return 3; + } + @Override + public Fragment getItem( int position ) { + switch (position) { + case 0: + return new Overview(); + case 1: + return new Component(); + case 2: + return new Simulations(); + } + return null; + } + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Overview"; + case 1: + return "Components"; + case 2: + return "Simulations"; + } + return null; + } + } + } diff --git a/android/src/net/sf/openrocket/android/util/TabsAdapter.java b/android/src/net/sf/openrocket/android/util/TabsAdapter.java deleted file mode 100644 index e8d8c6a8..00000000 --- a/android/src/net/sf/openrocket/android/util/TabsAdapter.java +++ /dev/null @@ -1,140 +0,0 @@ -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) { - } -}