11acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb/*
21acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * Copyright (C) 2011 The Android Open Source Project
31acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb *
41acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
51acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * you may not use this file except in compliance with the License.
61acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * You may obtain a copy of the License at
71acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb *
81acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
91acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb *
101acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * Unless required by applicable law or agreed to in writing, software
111acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
121acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * See the License for the specific language governing permissions and
141acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * limitations under the License.
151acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb */
161acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
171acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbpackage com.android.browser.view;
181acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
191acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport android.database.DataSetObserver;
201acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport android.graphics.Canvas;
211acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport android.view.MotionEvent;
221acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport android.view.View;
231acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport android.widget.Adapter;
241acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
251acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbimport java.util.ArrayList;
261acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
271acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb/**
281acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb * common code for pie views
291acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb */
301acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolbpublic abstract class BasePieView implements PieMenu.PieView {
311acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
321acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected Adapter mAdapter;
331acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    private DataSetObserver mObserver;
341acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected ArrayList<View> mViews;
351acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
36eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    protected OnLayoutListener mListener;
37eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb
381acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mCurrent;
391acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mChildWidth;
401acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mChildHeight;
411acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mWidth;
421acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mHeight;
431acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mLeft;
441acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected int mTop;
451acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
461acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public BasePieView() {
471acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
481acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
49eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    public void setLayoutListener(OnLayoutListener l) {
50eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb        mListener = l;
51eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    }
52eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb
531acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public void setAdapter(Adapter adapter) {
541acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        mAdapter = adapter;
551acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        if (adapter == null) {
561acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            if (mAdapter != null) {
571acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mAdapter.unregisterDataSetObserver(mObserver);
581acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            }
591acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mViews = null;
601acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mCurrent = -1;
611acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        } else {
621acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mObserver = new DataSetObserver() {
631acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                @Override
641acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                public void onChanged() {
651acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                    buildViews();
661acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                }
671acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
681acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                @Override
691acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                public void onInvalidated() {
701acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                    mViews.clear();
711acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                }
721acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            };
731acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mAdapter.registerDataSetObserver(mObserver);
741acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            setCurrent(0);
751acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        }
761acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
771acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
781acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public void setCurrent(int ix) {
791acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        mCurrent = ix;
801acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
811acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
821acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public Adapter getAdapter() {
831acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        return mAdapter;
841acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
851acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
861acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected void buildViews() {
871acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        if (mAdapter != null) {
881acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            final int n = mAdapter.getCount();
891acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            if (mViews == null) {
901acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mViews = new ArrayList<View>(n);
911acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            } else {
921acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mViews.clear();
931acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            }
941acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mChildWidth = 0;
951acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            mChildHeight = 0;
961acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            for (int i = 0; i < n; i++) {
971acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                View view = mAdapter.getView(i, null, null);
981acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                view.measure(View.MeasureSpec.UNSPECIFIED,
991acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                        View.MeasureSpec.UNSPECIFIED);
1001acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mChildWidth = Math.max(mChildWidth, view.getMeasuredWidth());
1011acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mChildHeight = Math.max(mChildHeight, view.getMeasuredHeight());
1021acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mViews.add(view);
1031acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            }
1041acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        }
1051acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
1061acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1071acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    /**
1081acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb     * this will be called before the first draw call
1091acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb     * needs to set top, left, width, height
1101acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb     */
1111acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    @Override
112a4befac241ec69791fd30e11355ed3dc10d7fb37Michael Kolb    public void layout(int anchorX, int anchorY, boolean left, float angle,
113a4befac241ec69791fd30e11355ed3dc10d7fb37Michael Kolb            int parentHeight) {
114eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb        if (mListener != null) {
115eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb            mListener.onLayout(anchorX, anchorY, left);
116eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb        }
117eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb    }
118eb95db48b01b3db935601f25bd1a2358674b76daMichael Kolb
1191acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1201acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    @Override
1211acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public abstract void draw(Canvas canvas);
1221acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1231acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected void drawView(View view, Canvas canvas) {
1241acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        final int state = canvas.save();
1251acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        canvas.translate(view.getLeft(), view.getTop());
1261acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        view.draw(canvas);
1271acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        canvas.restoreToCount(state);
1281acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
1291acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1301acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    protected abstract int findChildAt(int y);
1311acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1321acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    @Override
1331acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    public boolean onTouchEvent(MotionEvent evt) {
1341acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        int action = evt.getActionMasked();
1351acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        int evtx = (int) evt.getX();
1361acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        int evty = (int) evt.getY();
1371acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        if ((evtx < mLeft) || (evtx >= mLeft + mWidth)
1381acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                || (evty < mTop) || (evty >= mTop + mHeight)) {
1391acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            return false;
1401acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        }
1411acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        switch (action) {
1421acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            case MotionEvent.ACTION_MOVE:
1431acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                View v = mViews.get(mCurrent);
1441acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                setCurrent(Math.max(0, Math.min(mViews.size() -1,
1451acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                        findChildAt(evty))));
1461acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                View v1 = mViews.get(mCurrent);
1471acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                if (v != v1) {
1481acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                    v.setPressed(false);
1491acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                    v1.setPressed(true);
1501acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                }
1511acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                break;
1521acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            case MotionEvent.ACTION_UP:
1531acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mViews.get(mCurrent).performClick();
1541acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                mViews.get(mCurrent).setPressed(false);
1551acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                break;
1561acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb            default:
1571acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb                break;
1581acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        }
1591acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb        return true;
1601acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb    }
1611acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb
1621acef69ffc079d1bc029ff7eb1f5043f7efd7f36Michael Kolb}
163