18872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/*
28872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Copyright (C) 2012 The Android Open Source Project
38872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
48872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * you may not use this file except in compliance with the License.
68872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * You may obtain a copy of the License at
78872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
88872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Unless required by applicable law or agreed to in writing, software
118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * See the License for the specific language governing permissions and
148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * limitations under the License.
158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpackage com.android.camera.ui;
188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Context;
208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.graphics.Canvas;
218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.util.AttributeSet;
228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.MotionEvent;
238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.View;
248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.widget.FrameLayout;
258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
266432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport com.android.camera.PreviewGestures;
27fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu
288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport java.util.ArrayList;
298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport java.util.List;
308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpublic class RenderOverlay extends FrameLayout {
328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private static final String TAG = "CAM_Overlay";
348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    interface Renderer {
368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public boolean handlesTouch();
388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public boolean onTouchEvent(MotionEvent evt);
398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void setOverlay(RenderOverlay overlay);
408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void layout(int left, int top, int right, int bottom);
418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void draw(Canvas canvas);
428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private RenderView mRenderView;
468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private List<Renderer> mClients;
476432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private PreviewGestures mGestures;
488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // reverse list of touch clients
498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private List<Renderer> mTouchClients;
508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private int[] mPosition = new int[2];
518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public RenderOverlay(Context context, AttributeSet attrs) {
538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super(context, attrs);
548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mRenderView = new RenderView(context);
558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        addView(mRenderView, new LayoutParams(LayoutParams.MATCH_PARENT,
568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                LayoutParams.MATCH_PARENT));
578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mClients = new ArrayList<Renderer>(10);
588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mTouchClients = new ArrayList<Renderer>(10);
598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        setWillNotDraw(false);
608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
626432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void setGestures(PreviewGestures gestures) {
63fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu        mGestures = gestures;
64fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu    }
65fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu
668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void addRenderer(Renderer renderer) {
678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mClients.add(renderer);
688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        renderer.setOverlay(this);
698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (renderer.handlesTouch()) {
708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mTouchClients.add(0, renderer);
718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        renderer.layout(getLeft(), getTop(), getRight(), getBottom());
738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void addRenderer(int pos, Renderer renderer) {
768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mClients.add(pos, renderer);
778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        renderer.setOverlay(this);
788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        renderer.layout(getLeft(), getTop(), getRight(), getBottom());
798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void remove(Renderer renderer) {
828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mClients.remove(renderer);
838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        renderer.setOverlay(null);
848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public int getClientSize() {
878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mClients.size();
888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean dispatchTouchEvent(MotionEvent m) {
92a52f04c1ff32b2f529c21b49861a62ad34359e28Doris Liu        if (mGestures != null) {
93a52f04c1ff32b2f529c21b49861a62ad34359e28Doris Liu            if (!mGestures.isEnabled()) return false;
94a52f04c1ff32b2f529c21b49861a62ad34359e28Doris Liu            mGestures.dispatchTouch(m);
95a52f04c1ff32b2f529c21b49861a62ad34359e28Doris Liu        }
96fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu        return true;
978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean directDispatchTouch(MotionEvent m, Renderer target) {
1008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mRenderView.setTouchTarget(target);
101fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu        boolean res = mRenderView.dispatchTouchEvent(m);
1028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mRenderView.setTouchTarget(null);
1038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return res;
1048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private void adjustPosition() {
1078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        getLocationInWindow(mPosition);
1088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public int getWindowPositionX() {
1118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mPosition[0];
1128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public int getWindowPositionY() {
1158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mPosition[1];
1168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void update() {
1198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mRenderView.invalidate();
1208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private class RenderView extends View {
1238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        private Renderer mTouchTarget;
1258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public RenderView(Context context) {
1278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super(context);
1288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            setWillNotDraw(false);
1298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void setTouchTarget(Renderer target) {
1328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mTouchTarget = target;
1338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
136fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu        public boolean dispatchTouchEvent(MotionEvent evt) {
137fb57df15a87f95ce8b2f861e54d960602912e03cDoris Liu
1388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mTouchTarget != null) {
1398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                return mTouchTarget.onTouchEvent(evt);
1408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mTouchClients != null) {
1428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                boolean res = false;
1438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                for (Renderer client : mTouchClients) {
1448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    res |= client.onTouchEvent(evt);
1458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                }
1468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                return res;
1478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            return false;
1498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onLayout(boolean changed, int left, int top, int right, int bottom) {
1538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            adjustPosition();
1548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super.onLayout(changed, left,  top, right, bottom);
1558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mClients == null) return;
1568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            for (Renderer renderer : mClients) {
1578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                renderer.layout(left, top, right, bottom);
1588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void draw(Canvas canvas) {
1638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super.draw(canvas);
1648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (mClients == null) return;
1658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            boolean redraw = false;
1668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            for (Renderer renderer : mClients) {
1678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                renderer.draw(canvas);
1688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                redraw = redraw || ((OverlayRenderer) renderer).isVisible();
1698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (redraw) {
1718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                invalidate();
1728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb}
177