1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.ui.focus; 18 19 import android.graphics.RectF; 20 21 import com.android.camera.async.MainThread; 22 import com.android.camera.debug.Log; 23 import com.android.camera.debug.Log.Tag; 24 import com.android.camera.one.OneCamera.FocusDistanceListener; 25 import com.android.camera.ui.motion.LinearScale; 26 27 /** 28 * The focus controller interacts with the focus ring UI element. 29 */ 30 public class FocusController implements FocusDistanceListener { 31 private static final Tag TAG = new Tag("FocusController"); 32 33 private final FocusRing mFocusRing; 34 private final FocusSound mFocusSound; 35 private final MainThread mMainThread; 36 37 public FocusController(FocusRing focusRing, FocusSound focusSound, MainThread mainThread) { 38 mFocusRing = focusRing; 39 mFocusSound = focusSound; 40 mMainThread = mainThread; 41 } 42 43 /** 44 * Show a passive focus animation at the center of the active area. 45 * This will likely be different than the view bounds due to varying image 46 * ratios and dimensions. 47 */ 48 public void showPassiveFocusAtCenter() { 49 mMainThread.execute(new Runnable() { 50 @Override 51 public void run() { 52 Log.v(TAG, "Running showPassiveFocusAtCenter()"); 53 mFocusRing.startPassiveFocus(); 54 mFocusRing.centerFocusLocation(); 55 } 56 }); 57 } 58 59 /** 60 * Show a passive focus animation at the given viewX and viewY position. 61 * This is usually indicates the camera subsystem kicked off an auto-focus 62 * at the given screen position. 63 * 64 * @param viewX the view's x coordinate 65 * @param viewY the view's y coordinate 66 */ 67 public void showPassiveFocusAt(final int viewX, final int viewY) { 68 mMainThread.execute(new Runnable() { 69 @Override 70 public void run() { 71 Log.v(TAG, "Running showPassiveFocusAt(" + viewX + ", " + viewY + ")"); 72 mFocusRing.startPassiveFocus(); 73 mFocusRing.setFocusLocation(viewX, viewY); 74 } 75 }); 76 } 77 78 /** 79 * Show an active focus animation at the given viewX and viewY position. 80 * This is normally initiated by the user touching the screen at a given 81 * point. 82 * 83 * @param viewX the view's x coordinate 84 * @param viewY the view's y coordinate 85 */ 86 public void showActiveFocusAt(final int viewX, final int viewY) { 87 mMainThread.execute(new Runnable() { 88 @Override 89 public void run() { 90 Log.v(TAG, "showActiveFocusAt(" + viewX + ", " + viewY + ")"); 91 mFocusRing.startActiveFocus(); 92 mFocusRing.setFocusLocation(viewX, viewY); 93 94 // TODO: Enable focus sound when better audio controls exist. 95 // mFocusSound.play(); 96 } 97 }); 98 } 99 100 /** 101 * Stop any currently executing focus animation. 102 */ 103 public void clearFocusIndicator() { 104 mMainThread.execute(new Runnable() { 105 @Override 106 public void run() { 107 Log.v(TAG, "clearFocusIndicator()"); 108 mFocusRing.stopFocusAnimations(); 109 } 110 }); 111 } 112 113 /** 114 * Computing the correct location for the focus ring requires knowing 115 * the screen position and size of the preview area so the drawing 116 * operations can be clipped correctly. 117 */ 118 public void configurePreviewDimensions(final RectF previewArea) { 119 mMainThread.execute(new Runnable() { 120 @Override 121 public void run() { 122 Log.v(TAG, "configurePreviewDimensions(" + previewArea + ")"); 123 mFocusRing.configurePreviewDimensions(previewArea); 124 } 125 }); 126 } 127 128 /** 129 * Set the radius of the focus ring as a radius between 0 and 1. 130 * This will map to the min and max values computed for the UI. 131 */ 132 public void setFocusRatio(final float ratio) { 133 mMainThread.execute(new Runnable() { 134 @Override 135 public void run() { 136 if (mFocusRing.isPassiveFocusRunning() || 137 mFocusRing.isActiveFocusRunning()) { 138 mFocusRing.setRadiusRatio(ratio); 139 } 140 } 141 }); 142 } 143 144 @Override 145 public void onFocusDistance(float lensDistance, LinearScale lensRange) { 146 if (lensRange.isInDomain(lensDistance)) { 147 setFocusRatio(lensRange.scale(lensDistance)); 148 } 149 } 150 } 151