Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / android-libraries / ActionBarSherlock / src / com / actionbarsherlock / internal / view / menu / BaseMenuPresenter.java
diff --git a/android-libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java b/android-libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java
new file mode 100644 (file)
index 0000000..6da26f2
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+
+package com.actionbarsherlock.internal.view.menu;
+
+import java.util.ArrayList;
+import android.content.Context;
+import android.os.Build;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Base class for MenuPresenters that have a consistent container view and item
+ * views. Behaves similarly to an AdapterView in that existing item views will
+ * be reused if possible when items change.
+ */
+public abstract class BaseMenuPresenter implements MenuPresenter {
+    private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
+
+    protected Context mSystemContext;
+    protected Context mContext;
+    protected MenuBuilder mMenu;
+    protected LayoutInflater mSystemInflater;
+    protected LayoutInflater mInflater;
+    private Callback mCallback;
+
+    private int mMenuLayoutRes;
+    private int mItemLayoutRes;
+
+    protected MenuView mMenuView;
+
+    private int mId;
+
+    /**
+     * Construct a new BaseMenuPresenter.
+     *
+     * @param context Context for generating system-supplied views
+     * @param menuLayoutRes Layout resource ID for the menu container view
+     * @param itemLayoutRes Layout resource ID for a single item view
+     */
+    public BaseMenuPresenter(Context context, int menuLayoutRes, int itemLayoutRes) {
+        mSystemContext = context;
+        mSystemInflater = LayoutInflater.from(context);
+        mMenuLayoutRes = menuLayoutRes;
+        mItemLayoutRes = itemLayoutRes;
+    }
+
+    @Override
+    public void initForMenu(Context context, MenuBuilder menu) {
+        mContext = context;
+        mInflater = LayoutInflater.from(mContext);
+        mMenu = menu;
+    }
+
+    @Override
+    public MenuView getMenuView(ViewGroup root) {
+        if (mMenuView == null) {
+            mMenuView = (MenuView) mSystemInflater.inflate(mMenuLayoutRes, root, false);
+            mMenuView.initialize(mMenu);
+            updateMenuView(true);
+        }
+
+        return mMenuView;
+    }
+
+    /**
+     * Reuses item views when it can
+     */
+    public void updateMenuView(boolean cleared) {
+        final ViewGroup parent = (ViewGroup) mMenuView;
+        if (parent == null) return;
+
+        int childIndex = 0;
+        if (mMenu != null) {
+            mMenu.flagActionItems();
+            ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
+            final int itemCount = visibleItems.size();
+            for (int i = 0; i < itemCount; i++) {
+                MenuItemImpl item = visibleItems.get(i);
+                if (shouldIncludeItem(childIndex, item)) {
+                    final View convertView = parent.getChildAt(childIndex);
+                    final MenuItemImpl oldItem = convertView instanceof MenuView.ItemView ?
+                            ((MenuView.ItemView) convertView).getItemData() : null;
+                    final View itemView = getItemView(item, convertView, parent);
+                    if (item != oldItem) {
+                        // Don't let old states linger with new data.
+                        itemView.setPressed(false);
+                        if (IS_HONEYCOMB) itemView.jumpDrawablesToCurrentState();
+                    }
+                    if (itemView != convertView) {
+                        addItemView(itemView, childIndex);
+                    }
+                    childIndex++;
+                }
+            }
+        }
+
+        // Remove leftover views.
+        while (childIndex < parent.getChildCount()) {
+            if (!filterLeftoverView(parent, childIndex)) {
+                childIndex++;
+            }
+        }
+    }
+
+    /**
+     * Add an item view at the given index.
+     *
+     * @param itemView View to add
+     * @param childIndex Index within the parent to insert at
+     */
+    protected void addItemView(View itemView, int childIndex) {
+        final ViewGroup currentParent = (ViewGroup) itemView.getParent();
+        if (currentParent != null) {
+            currentParent.removeView(itemView);
+        }
+        ((ViewGroup) mMenuView).addView(itemView, childIndex);
+    }
+
+    /**
+     * Filter the child view at index and remove it if appropriate.
+     * @param parent Parent to filter from
+     * @param childIndex Index to filter
+     * @return true if the child view at index was removed
+     */
+    protected boolean filterLeftoverView(ViewGroup parent, int childIndex) {
+        parent.removeViewAt(childIndex);
+        return true;
+    }
+
+    public void setCallback(Callback cb) {
+        mCallback = cb;
+    }
+
+    /**
+     * Create a new item view that can be re-bound to other item data later.
+     *
+     * @return The new item view
+     */
+    public MenuView.ItemView createItemView(ViewGroup parent) {
+        return (MenuView.ItemView) mSystemInflater.inflate(mItemLayoutRes, parent, false);
+    }
+
+    /**
+     * Prepare an item view for use. See AdapterView for the basic idea at work here.
+     * This may require creating a new item view, but well-behaved implementations will
+     * re-use the view passed as convertView if present. The returned view will be populated
+     * with data from the item parameter.
+     *
+     * @param item Item to present
+     * @param convertView Existing view to reuse
+     * @param parent Intended parent view - use for inflation.
+     * @return View that presents the requested menu item
+     */
+    public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) {
+        MenuView.ItemView itemView;
+        if (convertView instanceof MenuView.ItemView) {
+            itemView = (MenuView.ItemView) convertView;
+        } else {
+            itemView = createItemView(parent);
+        }
+        bindItemView(item, itemView);
+        return (View) itemView;
+    }
+
+    /**
+     * Bind item data to an existing item view.
+     *
+     * @param item Item to bind
+     * @param itemView View to populate with item data
+     */
+    public abstract void bindItemView(MenuItemImpl item, MenuView.ItemView itemView);
+
+    /**
+     * Filter item by child index and item data.
+     *
+     * @param childIndex Indended presentation index of this item
+     * @param item Item to present
+     * @return true if this item should be included in this menu presentation; false otherwise
+     */
+    public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) {
+        return true;
+    }
+
+    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+        if (mCallback != null) {
+            mCallback.onCloseMenu(menu, allMenusAreClosing);
+        }
+    }
+
+    public boolean onSubMenuSelected(SubMenuBuilder menu) {
+        if (mCallback != null) {
+            return mCallback.onOpenSubMenu(menu);
+        }
+        return false;
+    }
+
+    public boolean flagActionItems() {
+        return false;
+    }
+
+    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
+    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
+    public int getId() {
+        return mId;
+    }
+
+    public void setId(int id) {
+        mId = id;
+    }
+}