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