From: drizea Date: Mon, 23 Jul 2012 09:39:02 +0000 (+0300) Subject: added action bar compatibility support X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=e5628afd09f4b13ef5bac7267b916cfc7bbc77cc;p=working%2FEvergreen.git added action bar compatibility support --- diff --git a/Open-ILS/src/Android/AndroidManifest.xml b/Open-ILS/src/Android/AndroidManifest.xml index c4b2e87940..940c6f7614 100644 --- a/Open-ILS/src/Android/AndroidManifest.xml +++ b/Open-ILS/src/Android/AndroidManifest.xml @@ -4,13 +4,13 @@ android:versionCode="1" android:versionName="1.0" > - + + + + + + + diff --git a/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_focused.xml b/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_focused.xml new file mode 100644 index 0000000000..04811d3340 --- /dev/null +++ b/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_focused.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_pressed.xml b/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_pressed.xml new file mode 100644 index 0000000000..72ff4b4f96 --- /dev/null +++ b/Open-ILS/src/Android/res/drawable-mdpi/actionbar_compat_item_pressed.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/Open-ILS/src/Android/res/drawable/actionbar_compat_item.xml b/Open-ILS/src/Android/res/drawable/actionbar_compat_item.xml new file mode 100644 index 0000000000..4b3960cf46 --- /dev/null +++ b/Open-ILS/src/Android/res/drawable/actionbar_compat_item.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/Open-ILS/src/Android/res/drawable/actionbar_compat_item_focused.xml b/Open-ILS/src/Android/res/drawable/actionbar_compat_item_focused.xml new file mode 100644 index 0000000000..04811d3340 --- /dev/null +++ b/Open-ILS/src/Android/res/drawable/actionbar_compat_item_focused.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/Open-ILS/src/Android/res/drawable/actionbar_compat_item_pressed.xml b/Open-ILS/src/Android/res/drawable/actionbar_compat_item_pressed.xml new file mode 100644 index 0000000000..72ff4b4f96 --- /dev/null +++ b/Open-ILS/src/Android/res/drawable/actionbar_compat_item_pressed.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/Open-ILS/src/Android/res/layout/actionbar_compat.xml b/Open-ILS/src/Android/res/layout/actionbar_compat.xml new file mode 100644 index 0000000000..73cbd03997 --- /dev/null +++ b/Open-ILS/src/Android/res/layout/actionbar_compat.xml @@ -0,0 +1,21 @@ + + + diff --git a/Open-ILS/src/Android/res/layout/actionbar_indeterminate_progress.xml b/Open-ILS/src/Android/res/layout/actionbar_indeterminate_progress.xml new file mode 100644 index 0000000000..c05750e00a --- /dev/null +++ b/Open-ILS/src/Android/res/layout/actionbar_indeterminate_progress.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/Open-ILS/src/Android/res/menu/checkout_menu.xml b/Open-ILS/src/Android/res/menu/checkout_menu.xml new file mode 100644 index 0000000000..36f930e8ec --- /dev/null +++ b/Open-ILS/src/Android/res/menu/checkout_menu.xml @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/Open-ILS/src/Android/res/values/attrs.xml b/Open-ILS/src/Android/res/values/attrs.xml new file mode 100644 index 0000000000..c59822c67b --- /dev/null +++ b/Open-ILS/src/Android/res/values/attrs.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/Android/res/values/colors.xml b/Open-ILS/src/Android/res/values/colors.xml index b406692076..4fa2bb5d7a 100644 --- a/Open-ILS/src/Android/res/values/colors.xml +++ b/Open-ILS/src/Android/res/values/colors.xml @@ -35,4 +35,7 @@ #ffffff #1e90ff #ff0000 + + #224894 + diff --git a/Open-ILS/src/Android/res/values/dimens.xml b/Open-ILS/src/Android/res/values/dimens.xml index b31f993a07..707fabdd2f 100644 --- a/Open-ILS/src/Android/res/values/dimens.xml +++ b/Open-ILS/src/Android/res/values/dimens.xml @@ -19,4 +19,9 @@ 14sp 18sp 22sp + + 48dp + 48dp + 56dp + diff --git a/Open-ILS/src/Android/res/values/ids.xml b/Open-ILS/src/Android/res/values/ids.xml new file mode 100644 index 0000000000..e0a4745b22 --- /dev/null +++ b/Open-ILS/src/Android/res/values/ids.xml @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/Open-ILS/src/Android/res/values/styles.xml b/Open-ILS/src/Android/res/values/styles.xml index 62ba8d7df2..d827306fbb 100644 --- a/Open-ILS/src/Android/res/values/styles.xml +++ b/Open-ILS/src/Android/res/values/styles.xml @@ -37,6 +37,8 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java b/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java index 1acd68ad70..346a8fa0cd 100644 --- a/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java +++ b/Open-ILS/src/Android/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java @@ -10,6 +10,7 @@ import org.evergreen.android.accountAccess.SessionNotFoundException; import org.evergreen.android.globals.NoAccessToServer; import org.evergreen.android.globals.NoNetworkAccessException; import org.evergreen.android.globals.Utils; +import org.evergreen.android.utils.ui.actionbar.ActionBarActivity; import android.app.Activity; import android.app.ProgressDialog; @@ -17,6 +18,9 @@ import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; @@ -25,7 +29,7 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -public class ItemsCheckOutListView extends Activity{ +public class ItemsCheckOutListView extends ActionBarActivity{ private String TAG = "ItemsCheckOutListView"; @@ -47,6 +51,7 @@ public class ItemsCheckOutListView extends Activity{ super.onCreate(savedInstanceState); setContentView(R.layout.checkout_list); + setTitle("Checkout items"); context = this; accountAccess = AccountAccess.getAccountAccess(); @@ -113,6 +118,44 @@ public class ItemsCheckOutListView extends Activity{ } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.checkout_menu, menu); + return super.onCreateOptionsMenu(menu); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + Toast.makeText(this, "Tapped home", Toast.LENGTH_SHORT).show(); + break; + + case R.id.menu_refresh: + Toast.makeText(this, "Fake refreshing...", Toast.LENGTH_SHORT).show(); + getActionBarHelper().setRefreshActionItemState(true); + getWindow().getDecorView().postDelayed( + new Runnable() { + @Override + public void run() { + getActionBarHelper().setRefreshActionItemState(false); + } + }, 1000); + break; + + case R.id.menu_search: + Toast.makeText(this, "Tapped search", Toast.LENGTH_SHORT).show(); + break; + + case R.id.menu_share: + Toast.makeText(this, "Tapped share", Toast.LENGTH_SHORT).show(); + break; + } + return super.onOptionsItemSelected(item); + } + class CheckOutArrayAdapter extends ArrayAdapter { private static final String tag = "CheckoutArrayAdapter"; diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarActivity.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarActivity.java new file mode 100644 index 0000000000..7c8239734b --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/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 org.evergreen.android.utils.ui.actionbar; + +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/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelper.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelper.java new file mode 100644 index 0000000000..df08423753 --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelper.java @@ -0,0 +1,97 @@ +/* + * 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 org.evergreen.android.utils.ui.actionbar; + +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; + } +} diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperBase.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperBase.java new file mode 100644 index 0000000000..e17439d3e9 --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperBase.java @@ -0,0 +1,302 @@ +/* + * 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 org.evergreen.android.utils.ui.actionbar; + +import org.evergreen.android.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.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; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +/** + * 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"; + + 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 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.ic_home); + 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); + } + + /** + * 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/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperHoneycomb.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperHoneycomb.java new file mode 100644 index 0000000000..442c0c536c --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperHoneycomb.java @@ -0,0 +1,82 @@ +/* + * 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 org.evergreen.android.utils.ui.actionbar; + +import org.evergreen.android.R; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +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; + } +} diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperICS.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperICS.java new file mode 100644 index 0000000000..efe9d18bea --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/ActionBarHelperICS.java @@ -0,0 +1,37 @@ +/* + * 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 org.evergreen.android.utils.ui.actionbar; + +import android.app.Activity; +import android.content.Context; +import android.view.Menu; +import android.view.MenuItem; + +/** + * 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/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/SimpleMenu.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/SimpleMenu.java new file mode 100644 index 0000000000..b8fd6629fe --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/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 org.evergreen.android.utils.ui.actionbar; + +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; + +import java.util.ArrayList; + +/** + * 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/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/SimpleMenuItem.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/SimpleMenuItem.java new file mode 100644 index 0000000000..378cdb4925 --- /dev/null +++ b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/actionbar/SimpleMenuItem.java @@ -0,0 +1,261 @@ +/* + * 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 org.evergreen.android.utils.ui.actionbar; + +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; + } + + @Override + 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; + } +}