Added Android code
[wl-app.git] / Android / folioreader / src / main / java / com / folioreader / model / quickaction / QuickAction.java
diff --git a/Android/folioreader/src/main/java/com/folioreader/model/quickaction/QuickAction.java b/Android/folioreader/src/main/java/com/folioreader/model/quickaction/QuickAction.java
new file mode 100755 (executable)
index 0000000..c9368a6
--- /dev/null
@@ -0,0 +1,475 @@
+package com.folioreader.model.quickaction;
+
+import com.folioreader.R;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
+import android.widget.PopupWindow.OnDismissListener;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * QuickAction dialog, shows action list as icon and text like the one in Gallery3D app. Currently
+ * supports vertical
+ * and horizontal layout.
+ *
+ * @author Lorensius W. L. T <lorenz@londatiga.net>
+ *
+ *         Contributors:
+ *         - Kevin Peck <kevinwpeck@gmail.com>
+ */
+public class QuickAction extends PopupWindows implements OnDismissListener {
+    private View mRootView;
+    private ImageView mArrowUp;
+    private ImageView mArrowDown;
+    private LayoutInflater mInflater;
+    private ViewGroup mTrack;
+    private ScrollView mScroller;
+    private OnActionItemClickListener mItemClickListener;
+    private OnDismissListener mDismissListener;
+
+    private List<ActionItem> mActionItems = new ArrayList<ActionItem>();
+
+    private boolean mDidAction;
+
+    private int mChildPos;
+    private int mInsertPos;
+    private int mAnimStyle;
+    private int mOrientation;
+    private int mRootWidth = 0;
+
+    public static final int HORIZONTAL = 0;
+    public static final int VERTICAL = 1;
+
+    public static final int ANIM_GROW_FROM_LEFT = 1;
+    public static final int ANIM_GROW_FROM_RIGHT = 2;
+    public static final int ANIM_GROW_FROM_CENTER = 3;
+    public static final int ANIM_REFLECT = 4;
+    public static final int ANIM_AUTO = 5;
+
+    /**
+     * Constructor for default vertical layout
+     *
+     * @param context Context
+     */
+    public QuickAction(Context context) {
+        this(context, VERTICAL);
+    }
+
+    /**
+     * Constructor allowing orientation override
+     *
+     * @param context     Context
+     * @param orientation Layout orientation, can be vartical or horizontal
+     */
+    public QuickAction(Context context, int orientation) {
+        super(context);
+
+        mOrientation = orientation;
+
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        if (mOrientation == HORIZONTAL) {
+            setRootViewId(R.layout.popup_horizontal);
+        } else {
+            setRootViewId(R.layout.popup_vertical);
+        }
+
+        mAnimStyle = ANIM_AUTO;
+        mChildPos = 0;
+    }
+
+    /**
+     * Get action item at an index
+     *
+     * @param index Index of item (position from callback)
+     * @return Action Item at the position
+     */
+    public ActionItem getActionItem(int index) {
+        return mActionItems.get(index);
+    }
+
+    /**
+     * Set root view.
+     *
+     * @param id Layout resource id
+     */
+    public void setRootViewId(int id) {
+        mRootView = (ViewGroup) mInflater.inflate(id, null);
+        mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks);
+
+        mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down);
+        mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up);
+
+        mScroller = (ScrollView) mRootView.findViewById(R.id.scroller);
+
+        //This was previously defined on show()
+        // method, moved here to prevent force close that occured
+        //when tapping fastly on a view to show quickaction dialog.
+        //Thanx to zammbi (github.com/zammbi)
+        mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+                LayoutParams.WRAP_CONTENT));
+
+        setContentView(mRootView);
+    }
+
+    /**
+     * Set animation style
+     *
+     * @param mAnimStyle animation style, default is set to ANIM_AUTO
+     */
+    public void setAnimStyle(int mAnimStyle) {
+        this.mAnimStyle = mAnimStyle;
+    }
+
+    /**
+     * Set listener for action item clicked.
+     *
+     * @param listener Listener
+     */
+    public void setOnActionItemClickListener(OnActionItemClickListener listener) {
+        mItemClickListener = listener;
+    }
+
+    /**
+     * Add action item
+     *
+     * @param action {@link ActionItem}
+     */
+    public void addActionItem(ActionItem action) {
+        mActionItems.add(action);
+
+        String title = action.getTitle();
+        Drawable icon = action.getIcon();
+
+        View container;
+
+        if (mOrientation == HORIZONTAL) {
+            container = mInflater.inflate(R.layout.action_item_horizontal, null);
+        } else {
+            container = mInflater.inflate(R.layout.action_item_vertical, null);
+        }
+
+        ImageView img = (ImageView) container.findViewById(R.id.iv_icon);
+        TextView text = (TextView) container.findViewById(R.id.tv_title);
+
+        if (icon != null) {
+            img.setImageDrawable(icon);
+        } else {
+            img.setVisibility(View.GONE);
+        }
+
+        if (title != null) {
+            text.setText(title);
+        } else {
+            text.setVisibility(View.GONE);
+        }
+
+        final int pos = mChildPos;
+        final int actionId = action.getActionId();
+
+        container.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mItemClickListener != null) {
+                    mItemClickListener.onItemClick(QuickAction.this, pos, actionId);
+                }
+
+                if (!getActionItem(pos).isSticky()) {
+                    mDidAction = true;
+
+                    dismiss();
+                }
+            }
+        });
+
+        container.setFocusable(true);
+        container.setClickable(true);
+
+        if (mOrientation == HORIZONTAL && mChildPos != 0) {
+            View separator = mInflater.inflate(R.layout.horiz_separator, null);
+
+            RelativeLayout.LayoutParams params =
+                    new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
+                            LayoutParams.FILL_PARENT);
+
+            separator.setLayoutParams(params);
+            separator.setPadding(5, 0, 5, 0);
+
+            mTrack.addView(separator, mInsertPos);
+
+            mInsertPos++;
+        }
+
+        mTrack.addView(container, mInsertPos);
+
+        mChildPos++;
+        mInsertPos++;
+    }
+
+    /**
+     * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view.
+     */
+    public void show(View anchor) {
+        preShow();
+
+        int xPos, yPos, arrowPos;
+
+        mDidAction = false;
+
+        int[] location = new int[2];
+
+        anchor.getLocationOnScreen(location);
+
+        Rect anchorRect = new Rect(location[0], location[1], location[0]
+                + anchor.getWidth(), location[1]
+                + anchor.getHeight());
+
+        mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+        int rootHeight = mRootView.getMeasuredHeight();
+
+        if (mRootWidth == 0) {
+            mRootWidth = mRootView.getMeasuredWidth();
+        }
+
+        int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
+        int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
+
+        //automatically get X coord of popup (top left)
+        if ((anchorRect.left + mRootWidth) > screenWidth) {
+            xPos = anchorRect.left - (mRootWidth - anchor.getWidth());
+            xPos = (xPos < 0) ? 0 : xPos;
+
+            arrowPos = anchorRect.centerX() - xPos;
+
+        } else {
+            if (anchor.getWidth() > mRootWidth) {
+                xPos = anchorRect.centerX() - (mRootWidth / 2);
+            } else {
+                xPos = anchorRect.left;
+            }
+
+            arrowPos = anchorRect.centerX() - xPos;
+        }
+
+        int dyTop = anchorRect.top;
+        int dyBottom = screenHeight - anchorRect.bottom;
+
+        boolean onTop = (dyTop > dyBottom) ? true : false;
+
+        if (onTop) {
+            if (rootHeight > dyTop) {
+                yPos = 15;
+                LayoutParams l = mScroller.getLayoutParams();
+                l.height = dyTop - anchor.getHeight();
+            } else {
+                yPos = anchorRect.top - rootHeight;
+            }
+        } else {
+            yPos = anchorRect.bottom;
+
+            if (rootHeight > dyBottom) {
+                LayoutParams l = mScroller.getLayoutParams();
+                l.height = dyBottom;
+            }
+        }
+
+        showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
+
+        setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
+
+        mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
+    }
+
+    public void show(View anchor, int width, int height) {
+        preShow();
+
+        int xPos, yPos, arrowPos;
+        int[] location = new int[2];
+
+        anchor.getLocationOnScreen(location);
+
+        Rect anchorRect =
+                new Rect(location[0], location[1], location[0] + width, location[1] + height);
+
+        mDidAction = false;
+
+        mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+        int rootHeight = mRootView.getMeasuredHeight();
+
+        if (mRootWidth == 0) {
+            mRootWidth = mRootView.getMeasuredWidth();
+        }
+
+        int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
+        int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
+
+        //automatically get X coord of popup (top left)
+        if ((anchorRect.left + mRootWidth) > screenWidth) {
+            xPos = anchorRect.left - (mRootWidth - width);
+            xPos = (xPos < 0) ? 0 : xPos;
+
+            arrowPos = anchorRect.centerX() - xPos;
+
+        } else {
+            if (width > mRootWidth) {
+                xPos = anchorRect.centerX() - (mRootWidth / 2);
+            } else {
+                xPos = anchorRect.left;
+            }
+
+            arrowPos = anchorRect.centerX() - xPos;
+        }
+
+        int dyTop = anchorRect.top;
+        int dyBottom = screenHeight - anchorRect.bottom;
+
+        boolean onTop = (dyTop > dyBottom) ? true : false;
+
+        if (onTop) {
+            if (rootHeight > dyTop) {
+                yPos = 15;
+                LayoutParams l = mScroller.getLayoutParams();
+                l.height = dyTop - height;
+            } else {
+                yPos = anchorRect.top - rootHeight;
+            }
+        } else {
+            yPos = anchorRect.bottom;
+
+            if (rootHeight > dyBottom) {
+                LayoutParams l = mScroller.getLayoutParams();
+                l.height = dyBottom;
+            }
+        }
+
+        showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
+
+        setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
+
+        mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
+    }
+
+    /**
+     * Set animation style
+     *
+     * @param screenWidth screen width
+     * @param requestedX  distance from left edge
+     * @param onTop       flag to indicate where the popup should be displayed. Set TRUE if
+     *                    displayed on top of anchor view
+     *                    and vice versa
+     */
+    private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
+        int arrowPos = requestedX - mArrowUp.getMeasuredWidth() / 2;
+
+        switch (mAnimStyle) {
+            case ANIM_GROW_FROM_LEFT:
+                mWindow.setAnimationStyle((onTop) ?
+                        R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
+                break;
+
+            case ANIM_GROW_FROM_RIGHT:
+                mWindow.setAnimationStyle((onTop) ?
+                        R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
+                break;
+
+            case ANIM_GROW_FROM_CENTER:
+                mWindow.setAnimationStyle((onTop) ?
+                        R.style.Animations_PopUpMenu_Center :
+                        R.style.Animations_PopDownMenu_Center);
+                break;
+
+            case ANIM_REFLECT:
+                mWindow.setAnimationStyle((onTop) ?
+                        R.style.Animations_PopUpMenu_Reflect :
+                        R.style.Animations_PopDownMenu_Reflect);
+                break;
+
+            case ANIM_AUTO:
+                if (arrowPos <= screenWidth / 4) {
+                    mWindow.setAnimationStyle((onTop) ?
+                            R.style.Animations_PopUpMenu_Left :
+                            R.style.Animations_PopDownMenu_Left);
+                } else if (arrowPos > screenWidth / 4 &&
+                        arrowPos < 3 * (screenWidth / 4)) {
+                    mWindow.setAnimationStyle((onTop) ?
+                            R.style.Animations_PopUpMenu_Center :
+                            R.style.Animations_PopDownMenu_Center);
+                } else {
+                    mWindow.setAnimationStyle((onTop) ?
+                            R.style.Animations_PopUpMenu_Right :
+                            R.style.Animations_PopDownMenu_Right);
+                }
+
+                break;
+        }
+    }
+
+    /**
+     * Show arrow
+     *
+     * @param whichArrow arrow type resource id
+     * @param requestedX distance from left screen
+     */
+    private void showArrow(int whichArrow, int requestedX) {
+        final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
+        final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
+
+        final int arrowWidth = mArrowUp.getMeasuredWidth();
+
+        showArrow.setVisibility(View.VISIBLE);
+
+        ViewGroup.MarginLayoutParams param =
+                (ViewGroup.MarginLayoutParams) showArrow.getLayoutParams();
+
+        param.leftMargin = requestedX - arrowWidth / 2;
+
+        hideArrow.setVisibility(View.INVISIBLE);
+    }
+
+    /**
+     * Set listener for window dismissed. This listener will only be fired if the quicakction dialog
+     * is dismissed
+     * by clicking outside the dialog or clicking on sticky item.
+     */
+    public void setOnDismissListener(QuickAction.OnDismissListener listener) {
+        setOnDismissListener(this);
+
+        mDismissListener = listener;
+    }
+
+    @Override
+    public void onDismiss() {
+        if (!mDidAction && mDismissListener != null) {
+            mDismissListener.onDismiss();
+        }
+    }
+
+    /**
+     * Listener for item click
+     */
+    public interface OnActionItemClickListener {
+        public abstract void onItemClick(QuickAction source, int pos, int actionId);
+    }
+
+    /**
+     * Listener for window dismiss
+     */
+    public interface OnDismissListener {
+        public abstract void onDismiss();
+    }
+}
\ No newline at end of file