1 /* 2 * Copyright (C) 2011 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; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.util.AttributeSet; 22 import android.view.MotionEvent; 23 import android.view.View; 24 25 import com.android.camera.CameraPreference.OnPreferenceChangedListener; 26 import com.android.camera.PreferenceGroup; 27 import com.android.camera.R; 28 import com.android.camera.Util; 29 30 /** 31 * On the tablet UI, we have IndicatorControlWheelContainer which contains a 32 * ShutterButton, an IndicatorControlWheel(which combines first-level and 33 * second-level indicators and a ZoomControlWheel). 34 */ 35 public class IndicatorControlWheelContainer extends IndicatorControlContainer { 36 @SuppressWarnings("unused") 37 private static final String TAG = "IndicatorControlWheelContainer"; 38 39 // From center outwards, the indicator control wheel 40 // (e.g. res/drawable-sw640dp-hdpi/btn_camera_shutter_holo.png) is composed 41 // of a center colored button (could be blue, red or green), a light-black 42 // circle band, a thin gray circle strip and a dark-black circle band. 43 // The STROKE_WIDTH is the width of the outer-most dark-black circle band. 44 // The SHUTTER_BUTTON_RADIUS is the radius of the circle containing the 45 // center colored button and the light-black circle band. 46 public static final int STROKE_WIDTH = 87; // in dp 47 public static final int SHUTTER_BUTTON_RADIUS = 74; // in dp 48 // The indicator control wheel is cut by a secant. The secant is at the 49 // right edge for landscape orientation and at bottom edge for portrait 50 // orientation. This constant is the distance from the wheel center to the 51 // secant. 52 public static final int WHEEL_CENTER_TO_SECANT = 93; // in dp 53 54 private View mShutterButton; 55 private double mShutterButtonRadius; // in pixels 56 private IndicatorControlWheel mIndicatorControlWheel; 57 // The center of the shutter button. 58 private int mCenterX, mCenterY; 59 60 public IndicatorControlWheelContainer(Context context, AttributeSet attrs) { 61 super(context, attrs); 62 } 63 64 @Override 65 protected void onFinishInflate() { 66 mShutterButton = findViewById(R.id.shutter_button); 67 mShutterButtonRadius = Util.dpToPixel(SHUTTER_BUTTON_RADIUS); 68 69 mIndicatorControlWheel = (IndicatorControlWheel) findViewById( 70 R.id.indicator_control_wheel); 71 } 72 73 @Override 74 public void initialize(Context context, PreferenceGroup group, 75 boolean isZoomSupported, String[] keys, String[] otherSettingKeys) { 76 mIndicatorControlWheel.initialize(context, group, isZoomSupported, 77 keys, otherSettingKeys); 78 } 79 80 @Override 81 public void onIndicatorEvent(int event) { 82 } 83 84 @Override 85 public boolean dispatchTouchEvent(MotionEvent event) { 86 if (!onFilterTouchEventForSecurity(event)) return false; 87 88 int action = event.getAction(); 89 90 double dx = event.getX() - mCenterX; 91 double dy = mCenterY - event.getY(); 92 double radius = Math.sqrt(dx * dx + dy * dy); 93 94 // Check if the event should be dispatched to the shutter button. 95 if (radius <= mShutterButtonRadius) { 96 if (mIndicatorControlWheel.getVisibility() == View.VISIBLE) { 97 mIndicatorControlWheel.onTouchOutBound(); 98 } 99 if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) { 100 return mShutterButton.dispatchTouchEvent(event); 101 } 102 return false; 103 } 104 105 if (mShutterButton.isPressed()) { 106 // Send cancel to the shutter button if it was pressed. 107 event.setAction(MotionEvent.ACTION_CANCEL); 108 mShutterButton.dispatchTouchEvent(event); 109 return true; 110 } 111 112 return mIndicatorControlWheel.dispatchTouchEvent(event); 113 } 114 115 @Override 116 protected void onLayout( 117 boolean changed, int left, int top, int right, int bottom) { 118 119 // Layout the shutter button. 120 int shutterButtonWidth = mShutterButton.getMeasuredWidth(); 121 int shutterButtonHeight = mShutterButton.getMeasuredHeight(); 122 if (getResources().getConfiguration().orientation 123 == Configuration.ORIENTATION_LANDSCAPE) { 124 mCenterX = right - left - Util.dpToPixel(WHEEL_CENTER_TO_SECANT); 125 mCenterY = (bottom - top) / 2; 126 mShutterButton.layout(right - left - shutterButtonWidth, 127 mCenterY - shutterButtonHeight / 2, 128 right - left, 129 mCenterY + shutterButtonHeight / 2); 130 } else { 131 mCenterX = (right - left) / 2; 132 mCenterY = bottom - top - Util.dpToPixel(WHEEL_CENTER_TO_SECANT); 133 mShutterButton.layout(mCenterX - shutterButtonWidth / 2, 134 bottom - top - shutterButtonHeight, 135 mCenterX + shutterButtonWidth / 2, 136 bottom - top); 137 } 138 139 // Layout the control wheel. 140 mIndicatorControlWheel.layout(0, 0, right - left, bottom - top); 141 } 142 143 @Override 144 protected void onMeasure(int widthSpec, int heightSpec) { 145 // Measure all children. 146 int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 147 mShutterButton.measure(freeSpec, freeSpec); 148 mIndicatorControlWheel.measure(freeSpec, freeSpec); 149 150 // Measure myself. Add some buffer for highlight arc. 151 int desiredWidth = mShutterButton.getMeasuredWidth() 152 + IndicatorControlWheel.HIGHLIGHT_WIDTH * 4; 153 int desiredHeight = mShutterButton.getMeasuredHeight() 154 + IndicatorControlWheel.HIGHLIGHT_WIDTH * 4; 155 int widthMode = MeasureSpec.getMode(widthSpec); 156 int heightMode = MeasureSpec.getMode(heightSpec); 157 int measuredWidth, measuredHeight; 158 if (widthMode == MeasureSpec.UNSPECIFIED) { 159 measuredWidth = desiredWidth; 160 } else if (widthMode == MeasureSpec.AT_MOST) { 161 measuredWidth = Math.min(desiredWidth, MeasureSpec.getSize(widthSpec)); 162 } else { // MeasureSpec.EXACTLY 163 measuredWidth = MeasureSpec.getSize(widthSpec); 164 } 165 if (heightMode == MeasureSpec.UNSPECIFIED) { 166 measuredHeight = desiredHeight; 167 } else if (heightMode == MeasureSpec.AT_MOST) { 168 measuredHeight = Math.min(desiredHeight, MeasureSpec.getSize(heightSpec)); 169 } else { // MeasureSpec.EXACTLY 170 measuredHeight = MeasureSpec.getSize(heightSpec); 171 } 172 setMeasuredDimension(measuredWidth, measuredHeight); 173 } 174 175 @Override 176 public void setListener(OnPreferenceChangedListener listener) { 177 mIndicatorControlWheel.setListener(listener); 178 } 179 180 @Override 181 public void reloadPreferences() { 182 mIndicatorControlWheel.reloadPreferences(); 183 } 184 185 @Override 186 public View getActiveSettingPopup() { 187 return mIndicatorControlWheel.getActiveSettingPopup(); 188 } 189 190 @Override 191 public boolean dismissSettingPopup() { 192 return mIndicatorControlWheel.dismissSettingPopup(); 193 } 194 195 @Override 196 public void setOrientation(int orientation, boolean animation) { 197 mIndicatorControlWheel.setOrientation(orientation, animation); 198 } 199 200 @Override 201 public void startTimeLapseAnimation(int timeLapseInterval, long startTime) { 202 mIndicatorControlWheel.startTimeLapseAnimation( 203 timeLapseInterval, startTime); 204 } 205 206 @Override 207 public void stopTimeLapseAnimation() { 208 mIndicatorControlWheel.stopTimeLapseAnimation(); 209 } 210 211 @Override 212 public void setEnabled(boolean enabled) { 213 mIndicatorControlWheel.setEnabled(enabled); 214 } 215 216 @Override 217 public void enableZoom(boolean enabled) { 218 mIndicatorControlWheel.enableZoom(enabled); 219 } 220 221 @Override 222 public void overrideSettings(final String ... keyvalues) { 223 mIndicatorControlWheel.overrideSettings(keyvalues); 224 } 225 226 @Override 227 public void dismissSecondLevelIndicator() { 228 mIndicatorControlWheel.dismissSecondLevelIndicator(); 229 } 230 231 @Override 232 public void enableFilter(boolean enabled) { 233 mIndicatorControlWheel.setupFilter(enabled); 234 } 235 } 236