1d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin/*
2d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Copyright (C) 2012 The Android Open Source Project
3d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin *
4d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * you may not use this file except in compliance with the License.
6d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * You may obtain a copy of the License at
7d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin *
8d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin *
10d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Unless required by applicable law or agreed to in writing, software
11d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * See the License for the specific language governing permissions and
14d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * limitations under the License.
15d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin */
1644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
1744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linpackage com.android.gallery3d.ui;
1844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
1944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.content.Context;
2044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.graphics.Rect;
2144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.LayoutInflater;
2244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.View;
2344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.View.MeasureSpec;
2444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewGroup;
2544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewTreeObserver;
2644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
2744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.AdapterView;
2844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.AdapterView.OnItemClickListener;
2944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.BaseAdapter;
3044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.ListView;
3144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.PopupWindow;
3244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.TextView;
3344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
3444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport com.android.gallery3d.R;
3544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
3644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport java.util.ArrayList;
3744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
3844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linpublic class PopupList {
3944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
4044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public static interface OnPopupItemClickListener {
4144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public boolean onPopupItemClick(int itemId);
4244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
4344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
4444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public static class Item {
4544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public final int id;
4644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public String title;
4744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
4844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public Item(int id, String title) {
4944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            this.id = id;
5044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            this.title = title;
5144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
5244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
5344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public void setTitle(String title) {
5444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            this.title = title;
5544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
5644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
5744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
5844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final Context mContext;
5944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final View mAnchorView;
6044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final ArrayList<Item> mItems = new ArrayList<Item>();
6144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private PopupWindow mPopupWindow;
6244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private ListView mContentList;
6344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private OnPopupItemClickListener mOnPopupItemClickListener;
6444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private int mPopupOffsetX;
6544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private int mPopupOffsetY;
6644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private int mPopupWidth;
6744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private int mPopupHeight;
6844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
6944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public PopupList(Context context, View anchorView) {
7044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mContext = context;
7144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mAnchorView = anchorView;
7244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
7344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
7444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public void setOnPopupItemClickListener(OnPopupItemClickListener listener) {
7544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mOnPopupItemClickListener = listener;
7644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
7744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
7844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public void addItem(int id, String title) {
7944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mItems.add(new Item(id, title));
8044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
8144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
82d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin    public void clearItems() {
83d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin        mItems.clear();
84d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin    }
85d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin
8644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final PopupWindow.OnDismissListener mOnDismissListener =
8744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            new PopupWindow.OnDismissListener() {
8844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @SuppressWarnings("deprecation")
8944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
9044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public void onDismiss() {
9144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (mPopupWindow == null) return;
9244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            mPopupWindow = null;
9344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            ViewTreeObserver observer = mAnchorView.getViewTreeObserver();
9444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (observer.isAlive()) {
9544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                // We used the deprecated function for backward compatibility
9644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                // The new "removeOnGlobalLayoutListener" is introduced in API level 16
9744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                observer.removeGlobalOnLayoutListener(mOnGLobalLayoutListener);
9844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            }
9944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
10044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    };
10144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
10244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final OnItemClickListener mOnItemClickListener =
10344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            new OnItemClickListener() {
10444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
10544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
10644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (mPopupWindow == null) return;
10744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            mPopupWindow.dismiss();
10844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (mOnPopupItemClickListener != null) {
10944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                mOnPopupItemClickListener.onPopupItemClick((int) id);
11044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            }
11144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
11244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    };
11344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
11444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private final OnGlobalLayoutListener mOnGLobalLayoutListener =
11544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            new OnGlobalLayoutListener() {
11644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
11744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public void onGlobalLayout() {
11844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (mPopupWindow == null) return;
11944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            updatePopupLayoutParams();
12044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            // Need to update the position of the popup window
12144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            mPopupWindow.update(mAnchorView,
12244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                    mPopupOffsetX, mPopupOffsetY, mPopupWidth, mPopupHeight);
12344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
12444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    };
12544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
12644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public void show() {
12744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        if (mPopupWindow != null) return;
12844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mAnchorView.getViewTreeObserver()
12944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                .addOnGlobalLayoutListener(mOnGLobalLayoutListener);
13044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupWindow = createPopupWindow();
13144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        updatePopupLayoutParams();
13244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupWindow.setWidth(mPopupWidth);
13344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupWindow.setHeight(mPopupHeight);
13444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupWindow.showAsDropDown(mAnchorView, mPopupOffsetX, mPopupOffsetY);
13544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
13644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
13744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private void updatePopupLayoutParams() {
13844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        ListView content = mContentList;
13944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        PopupWindow popup = mPopupWindow;
14044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
14144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        Rect p = new Rect();
14244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.getBackground().getPadding(p);
14344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
14444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        int maxHeight = mPopupWindow.getMaxAvailableHeight(mAnchorView) - p.top - p.bottom;
14544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mContentList.measure(
14644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
14744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST));
14844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupWidth = content.getMeasuredWidth() + p.top + p.bottom;
14944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupHeight = Math.min(maxHeight, content.getMeasuredHeight() + p.left + p.right);
15044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupOffsetX = -p.left;
15144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mPopupOffsetY = -p.top;
15244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
15344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
15444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private PopupWindow createPopupWindow() {
155d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin        PopupWindow popup = new PopupWindow(mContext);
15644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.setOnDismissListener(mOnDismissListener);
15744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
15844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.setBackgroundDrawable(mContext.getResources().getDrawable(
15944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                R.drawable.menu_dropdown_panel_holo_dark));
1603fa6947fc3909020f3a37cc1fd9a9b9d4d9f93e8Owen Lin
1613fa6947fc3909020f3a37cc1fd9a9b9d4d9f93e8Owen Lin        mContentList = new ListView(mContext, null,
1622abaaf7caa9a83ba1ea759868aabde7f21387184John Reck                android.R.attr.dropDownListViewStyle);
16344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mContentList.setAdapter(new ItemDataAdapter());
16444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        mContentList.setOnItemClickListener(mOnItemClickListener);
16544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.setContentView(mContentList);
16644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.setFocusable(true);
16744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        popup.setOutsideTouchable(true);
16844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
16944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        return popup;
17044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
17144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
17244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    public Item findItem(int id) {
17344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        for (Item item : mItems) {
17444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (item.id == id) return item;
17544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
17644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        return null;
17744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
17844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
17944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    private class ItemDataAdapter extends BaseAdapter {
18044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
18144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public int getCount() {
18244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            return mItems.size();
18344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
18444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
18544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
18644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public Object getItem(int position) {
18744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            return mItems.get(position);
18844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
18944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
19044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
19144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public long getItemId(int position) {
19244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            return mItems.get(position).id;
19344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
19444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin
19544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        @Override
19644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        public View getView(int position, View convertView, ViewGroup parent) {
19744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            if (convertView == null) {
19844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                convertView = LayoutInflater.from(mContext)
19944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin                        .inflate(R.layout.popup_list_item, null);
20044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            }
20144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            TextView text = (TextView) convertView.findViewById(android.R.id.text1);
20244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            text.setText(mItems.get(position).title);
20344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin            return convertView;
20444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin        }
20544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin    }
20644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin}
207