blob: f7af52c2862d3579f556b3bcbd85775abcfa965a [file] [log] [blame]
Doris Liu048a61c2013-04-02 17:48:56 -07001/*
2 * Copyright (C) 2013 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
17package com.android.camera.ui;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.res.Configuration;
Michael Kolbb22b8522013-04-22 10:22:21 -070022import android.graphics.Rect;
Doris Liu048a61c2013-04-02 17:48:56 -070023import android.util.AttributeSet;
24import android.view.Gravity;
25import android.view.View;
Michael Kolbb22b8522013-04-22 10:22:21 -070026import android.widget.FrameLayout;
Doris Liu048a61c2013-04-02 17:48:56 -070027
28import com.android.camera.Util;
29import com.android.gallery3d.R;
30
Michael Kolbb22b8522013-04-22 10:22:21 -070031public class CameraControls extends RotatableLayout {
32
33 private static final String TAG = "CAM_Controls";
34
Doris Liu048a61c2013-04-02 17:48:56 -070035 private View mBackgroundView;
Michael Kolbb22b8522013-04-22 10:22:21 -070036 private View mShutter;
37 private View mSwitcher;
38 private View mMenu;
39 private View mIndicators;
Michael Kolbc43e5b62013-04-30 15:34:19 -070040 private View mPreview;
Michael Kolbb22b8522013-04-22 10:22:21 -070041
Doris Liu048a61c2013-04-02 17:48:56 -070042 public CameraControls(Context context, AttributeSet attrs) {
43 super(context, attrs);
44 }
45
46 public CameraControls(Context context) {
47 super(context);
48 }
49
50 @Override
51 public void onConfigurationChanged(Configuration config) {
52 super.onConfigurationChanged(config);
53 adjustBackground();
54 }
55
56 @Override
57 public void onFinishInflate() {
58 super.onFinishInflate();
59 mBackgroundView = findViewById(R.id.blocker);
Michael Kolbb22b8522013-04-22 10:22:21 -070060 mSwitcher = findViewById(R.id.camera_switcher);
61 mShutter = findViewById(R.id.shutter_button);
62 mMenu = findViewById(R.id.menu);
63 mIndicators = findViewById(R.id.on_screen_indicators);
Michael Kolbc43e5b62013-04-30 15:34:19 -070064 mPreview = findViewById(R.id.preview_thumb);
Michael Kolbb22b8522013-04-22 10:22:21 -070065 }
66
67 @Override
68 public void onLayout(boolean changed, int l, int t, int r, int b) {
69 int orientation = getResources().getConfiguration().orientation;
70 int rotation = Util.getDisplayRotation((Activity) getContext());
Michael Kolbf2c86c12013-05-01 13:28:24 -070071 int size = getResources().getDimensionPixelSize(R.dimen.camera_controls_size);
Michael Kolbb22b8522013-04-22 10:22:21 -070072 rotation = correctRotation(rotation, orientation);
73 super.onLayout(changed, l, t, r, b);
74 Rect shutter = new Rect();
Michael Kolbf2c86c12013-05-01 13:28:24 -070075 topRight(mPreview, l, t, r, b, orientation, rotation);
76 if (size > 0) {
77 // restrict controls to size
78 switch (rotation) {
79 case 0:
80 case 180:
81 l = (l + r - size) / 2;
82 r = l + size;
83 break;
84 case 90:
85 case 270:
86 t = (t + b - size) / 2;
87 b = t + size;
88 break;
89 }
90 }
Michael Kolbb22b8522013-04-22 10:22:21 -070091 center(mShutter, l, t, r, b, orientation, rotation, shutter);
92 center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect());
93 toLeft(mSwitcher, l, t, r, b, orientation, rotation, shutter);
94 toRight(mMenu, l, t, r, b, orientation, rotation, shutter);
95 toRight(mIndicators, l, t, r, b, orientation, rotation, shutter);
Michael Kolb574e68d2013-04-30 13:46:17 -070096 View retake = findViewById(R.id.btn_retake);
97 if (retake != null) {
98 Rect retakeRect = new Rect();
99 center(retake, l, t, r, b, orientation, rotation, retakeRect);
100 View cancel = findViewById(R.id.btn_cancel);
101 toLeft(cancel, l, t, r, b, orientation, rotation, shutter);
102 View done = findViewById(R.id.btn_done);
103 toRight(done, l, t, r, b, orientation, rotation, shutter);
104 }
Michael Kolbb22b8522013-04-22 10:22:21 -0700105 }
106
107 private int correctRotation(int rotation, int orientation) {
108 // all the layout code assumes camera device orientation to be portrait
109 // adjust rotation for landscape
110 int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT
111 : Configuration.ORIENTATION_LANDSCAPE;
112 if (camOrientation != orientation) {
113 return (rotation + 90) % 360;
114 }
115 return rotation;
116 }
Michael Kolbc43e5b62013-04-30 15:34:19 -0700117
Michael Kolbb22b8522013-04-22 10:22:21 -0700118 private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) {
119 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
120 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
121 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
122 switch (rotation) {
123 case 0:
124 // phone portrait; controls bottom
Michael Kolbf2c86c12013-05-01 13:28:24 -0700125 result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
126 result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
Michael Kolbb22b8522013-04-22 10:22:21 -0700127 result.bottom = b - lp.bottomMargin;
128 result.top = b - th + lp.topMargin;
129 break;
130 case 90:
131 // phone landscape: controls right
132 result.right = r - lp.rightMargin;
133 result.left = r - tw + lp.leftMargin;
Michael Kolbf2c86c12013-05-01 13:28:24 -0700134 result.top = (b + t) / 2 - th / 2 + lp.topMargin;
135 result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
Michael Kolbb22b8522013-04-22 10:22:21 -0700136 break;
137 case 180:
138 // phone upside down: controls top
Michael Kolbf2c86c12013-05-01 13:28:24 -0700139 result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
140 result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
Michael Kolbb22b8522013-04-22 10:22:21 -0700141 result.top = t + lp.topMargin;
142 result.bottom = t + th - lp.bottomMargin;
143 break;
144 case 270:
145 // reverse landscape: controls left
146 result.left = l + lp.leftMargin;
147 result.right = l + tw - lp.rightMargin;
Michael Kolbf2c86c12013-05-01 13:28:24 -0700148 result.top = (b + t) / 2 - th / 2 + lp.topMargin;
149 result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
Michael Kolbb22b8522013-04-22 10:22:21 -0700150 break;
151 }
152 v.layout(result.left, result.top, result.right, result.bottom);
153 }
154
155 private void toLeft(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
156 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
157 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
158 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
159 Rect result = new Rect();
160 switch (rotation) {
161 case 0:
162 // portrait, to left of anchor at bottom
163 result.right = anchor.left - lp.rightMargin;
164 result.left = anchor.left - tw + lp.leftMargin;
165 result.bottom = b - lp.bottomMargin;
166 result.top = b - th + lp.topMargin;
167 break;
168 case 90:
169 // phone landscape: below anchor on right
170 result.right = r - lp.rightMargin;
171 result.left = r - tw + lp.leftMargin;
172 result.top = anchor.bottom + lp.topMargin;
173 result.bottom = anchor.bottom + th - lp.bottomMargin;
174 break;
175 case 180:
176 // phone upside down: right of anchor at top
177 result.left = anchor.right + lp.leftMargin;
178 result.right = anchor.right + tw - lp.rightMargin;
179 result.top = t + lp.topMargin;
180 result.bottom = t + th - lp.bottomMargin;
181 break;
182 case 270:
183 // reverse landscape: above anchor on left
184 result.left = l + lp.leftMargin;
185 result.right = l + tw - lp.rightMargin;
186 result.bottom = anchor.top - lp.bottomMargin;
187 result.top = anchor.top - th + lp.topMargin;
188 break;
189 }
190 v.layout(result.left, result.top, result.right, result.bottom);
191 }
192
193 private void toRight(View v, int l, int t, int r, int b, int orientation, int rotation, Rect anchor) {
194 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
195 int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
196 int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
197 Rect result = new Rect();
198 switch (rotation) {
199 case 0:
200 // portrait, right of anchor at bottom
201 result.left = anchor.right + lp.leftMargin;
202 result.right = anchor.right + tw - lp.rightMargin;
203 result.bottom = b - lp.bottomMargin;
204 result.top = b - th + lp.topMargin;
205 break;
206 case 90:
207 // phone landscape: above anchor on right
208 result.right = r - lp.rightMargin;
Michael Kolbef878662013-04-29 14:50:41 -0700209 result.left = r - tw + lp.leftMargin;
Michael Kolbb22b8522013-04-22 10:22:21 -0700210 result.bottom = anchor.top - lp.bottomMargin;
211 result.top = anchor.top - th + lp.topMargin;
212 break;
213 case 180:
214 // phone upside down: left of anchor at top
215 result.right = anchor.left - lp.rightMargin;
216 result.left = anchor.left - tw + lp.leftMargin;
217 result.top = t + lp.topMargin;
218 result.bottom = t + th - lp.bottomMargin;
219 break;
220 case 270:
221 // reverse landscape: below anchor on left
222 result.left = l + lp.leftMargin;
223 result.right = l + tw - lp.rightMargin;
224 result.top = anchor.bottom + lp.topMargin;
225 result.bottom = anchor.bottom + th - lp.bottomMargin;
226 break;
227 }
228 v.layout(result.left, result.top, result.right, result.bottom);
Doris Liu048a61c2013-04-02 17:48:56 -0700229 }
230
Michael Kolbc43e5b62013-04-30 15:34:19 -0700231 private void topRight(View v, int l, int t, int r, int b, int orientation, int rotation) {
232 // layout using the specific margins; the rotation code messes up the others
233 int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top);
234 int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right);
235 v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight());
236 }
237
Doris Liu048a61c2013-04-02 17:48:56 -0700238 // In reverse landscape and reverse portrait, camera controls will be laid out
239 // on the wrong side of the screen. We need to make adjustment to move the controls
240 // to the USB side
241 public void adjustControlsToRightPosition() {
242 Configuration config = getResources().getConfiguration();
243 int orientation = Util.getDisplayRotation((Activity) getContext());
244 if (orientation == 270 && config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
245 flipChildren();
246 }
247 if (orientation == 180 && config.orientation == Configuration.ORIENTATION_PORTRAIT) {
248 flipChildren();
249 }
250 adjustBackground();
251 }
252
253 private void adjustBackground() {
254 // remove current drawable and reset rotation
255 mBackgroundView.setBackgroundDrawable(null);
256 mBackgroundView.setRotationX(0);
257 mBackgroundView.setRotationY(0);
258 // if the switcher background is top aligned we need to flip the background
259 // drawable vertically; if left aligned, flip horizontally
260 int gravity = ((LayoutParams) mBackgroundView.getLayoutParams()).gravity;
261 if ((gravity & Gravity.TOP) == Gravity.TOP) {
262 mBackgroundView.setRotationX(180);
263 } else if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
264 mBackgroundView.setRotationY(180);
265 }
266 mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);
267 }
Michael Kolbb22b8522013-04-22 10:22:21 -0700268
Doris Liu048a61c2013-04-02 17:48:56 -0700269}