OSDN Git Service

Fix review button placement
[android-x86/packages-apps-Gallery2.git] / src / com / android / camera / ui / CameraControls.java
1 /*
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
17 package com.android.camera.ui;
18
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.res.Configuration;
22 import android.graphics.Rect;
23 import android.hardware.display.DisplayManager;
24 import android.hardware.display.DisplayManager.DisplayListener;
25 import android.util.AttributeSet;
26 import android.view.View;
27 import android.widget.FrameLayout;
28
29 import com.android.camera.Util;
30 import com.android.gallery3d.R;
31 import com.android.gallery3d.common.ApiHelper;
32
33 public class CameraControls extends RotatableLayout {
34
35     private static final String TAG = "CAM_Controls";
36
37     private View mBackgroundView;
38     private View mShutter;
39     private View mSwitcher;
40     private View mMenu;
41     private View mIndicators;
42     private View mPreview;
43     private Object mDisplayListener = null;
44     private int mLastRotation = 0;
45
46     public CameraControls(Context context, AttributeSet attrs) {
47         super(context, attrs);
48         initDisplayListener();
49     }
50
51     public CameraControls(Context context) {
52         super(context);
53         initDisplayListener();
54     }
55
56     public void initDisplayListener() {
57         if (ApiHelper.HAS_DISPLAY_LISTENER) {
58             mDisplayListener = new DisplayListener() {
59
60                 @Override
61                 public void onDisplayAdded(int arg0) {}
62
63                 @Override
64                 public void onDisplayChanged(int arg0) {
65                     checkLayoutFlip();
66                 }
67
68                 @Override
69                 public void onDisplayRemoved(int arg0) {}
70             };
71         }
72     }
73
74     private void checkLayoutFlip() {
75         int currentRotation = Util.getDisplayRotation((Activity) getContext());
76         if ((currentRotation - mLastRotation + 360) % 360 == 180) {
77             mLastRotation = currentRotation;
78             flipChildren();
79             getParent().requestLayout();
80         }
81     }
82
83     @Override
84     public void onFinishInflate() {
85         super.onFinishInflate();
86         mBackgroundView = findViewById(R.id.blocker);
87         mSwitcher = findViewById(R.id.camera_switcher);
88         mShutter = findViewById(R.id.shutter_button);
89         mMenu = findViewById(R.id.menu);
90         mIndicators = findViewById(R.id.on_screen_indicators);
91         mPreview = findViewById(R.id.preview_thumb);
92     }
93
94     @Override
95     public void onAttachedToWindow() {
96         super.onAttachedToWindow();
97         adjustControlsToRightPosition();
98         mLastRotation = Util.getDisplayRotation((Activity) getContext());
99         if (ApiHelper.HAS_DISPLAY_LISTENER) {
100             ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE))
101             .registerDisplayListener((DisplayListener) mDisplayListener, null);
102         }
103     }
104
105     @Override
106     public void onWindowVisibilityChanged(int visibility) {
107         if (visibility == View.VISIBLE) {
108             // Make sure when coming back from onPause, the layout is rotated correctly
109             checkLayoutFlip();
110         }
111     }
112
113     @Override
114     public void onDetachedFromWindow () {
115         super.onDetachedFromWindow();
116         if (ApiHelper.HAS_DISPLAY_LISTENER) {
117             ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE))
118             .unregisterDisplayListener((DisplayListener) mDisplayListener);
119         }
120     }
121
122     @Override
123     public void onLayout(boolean changed, int l, int t, int r, int b) {
124         mLastRotation = Util.getDisplayRotation((Activity) getContext());
125         int orientation = getResources().getConfiguration().orientation;
126         int size = getResources().getDimensionPixelSize(R.dimen.camera_controls_size);
127         int rotation = getUnifiedRotation();
128         adjustBackground();
129         // As l,t,r,b are positions relative to parents, we need to convert them
130         // to child's coordinates
131         r = r - l;
132         b = b - t;
133         l = 0;
134         t = 0;
135         for (int i = 0; i < getChildCount(); i++) {
136             View v = getChildAt(i);
137             v.layout(l, t, r, b);
138         }
139         Rect shutter = new Rect();
140         topRight(mPreview, l, t, r, b);
141         if (size > 0) {
142             // restrict controls to size
143             switch (rotation) {
144             case 0:
145             case 180:
146                 l = (l + r - size) / 2;
147                 r = l + size;
148                 break;
149             case 90:
150             case 270:
151                 t = (t + b - size) / 2;
152                 b = t + size;
153                 break;
154             }
155         }
156         center(mShutter, l, t, r, b, orientation, rotation, shutter);
157         center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect());
158         toLeft(mSwitcher, shutter, rotation);
159         toRight(mMenu, shutter, rotation);
160         toRight(mIndicators, shutter, rotation);
161         View retake = findViewById(R.id.btn_retake);
162         if (retake != null) {
163             center(retake, shutter, rotation);
164             View cancel = findViewById(R.id.btn_cancel);
165             toLeft(cancel, shutter, rotation);
166             View done = findViewById(R.id.btn_done);
167             toRight(done, shutter, rotation);
168         }
169     }
170
171     private int getUnifiedRotation() {
172         // all the layout code assumes camera device orientation to be portrait
173         // adjust rotation for landscape
174         int orientation = getResources().getConfiguration().orientation;
175         int rotation = Util.getDisplayRotation((Activity) getContext());
176         int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT
177                 : Configuration.ORIENTATION_LANDSCAPE;
178         if (camOrientation != orientation) {
179             return (rotation + 90) % 360;
180         }
181         return rotation;
182     }
183
184     private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) {
185         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
186         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
187         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
188         switch (rotation) {
189         case 0:
190             // phone portrait; controls bottom
191             result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
192             result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
193             result.bottom = b - lp.bottomMargin;
194             result.top = b - th + lp.topMargin;
195             break;
196         case 90:
197             // phone landscape: controls right
198             result.right = r - lp.rightMargin;
199             result.left = r - tw + lp.leftMargin;
200             result.top = (b + t) / 2 - th / 2 + lp.topMargin;
201             result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
202             break;
203         case 180:
204             // phone upside down: controls top
205             result.left = (r + l) / 2 - tw / 2 + lp.leftMargin;
206             result.right = (r + l) / 2 + tw / 2 - lp.rightMargin;
207             result.top = t + lp.topMargin;
208             result.bottom = t + th - lp.bottomMargin;
209             break;
210         case 270:
211             // reverse landscape: controls left
212             result.left = l + lp.leftMargin;
213             result.right = l + tw - lp.rightMargin;
214             result.top = (b + t) / 2 - th / 2 + lp.topMargin;
215             result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin;
216             break;
217         }
218         v.layout(result.left, result.top, result.right, result.bottom);
219     }
220
221     private void center(View v, Rect other, int rotation) {
222         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
223         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
224         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
225         int cx = (other.left + other.right) / 2;
226         int cy = (other.top + other.bottom) / 2;
227         v.layout(cx - tw / 2 + lp.leftMargin,
228                 cy - th / 2 + lp.topMargin,
229                 cx + tw / 2 - lp.rightMargin,
230                 cy + th / 2 - lp.bottomMargin);
231     }
232
233     private void toLeft(View v, Rect other, int rotation) {
234         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
235         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
236         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
237         int cx = (other.left + other.right) / 2;
238         int cy = (other.top + other.bottom) / 2;
239         int l = 0, r = 0, t = 0, b = 0;
240         switch (rotation) {
241         case 0:
242             // portrait, to left of anchor at bottom
243             l = other.left - tw + lp.leftMargin;
244             r = other.left - lp.rightMargin;
245             t = cy - th / 2 + lp.topMargin;
246             b = cy + th / 2 - lp.bottomMargin;
247             break;
248         case 90:
249             // phone landscape: below anchor on right
250             l = cx - tw / 2 + lp.leftMargin;
251             r = cx + tw / 2 - lp.rightMargin;
252             t = other.bottom + lp.topMargin;
253             b = other.bottom + th - lp.bottomMargin;
254             break;
255         case 180:
256             // phone upside down: right of anchor at top
257             l = other.right + lp.leftMargin;
258             r = other.right + tw - lp.rightMargin;
259             t = cy - th / 2 + lp.topMargin;
260             b = cy + th / 2 - lp.bottomMargin;
261             break;
262         case 270:
263             // reverse landscape: above anchor on left
264             l = cx - tw / 2 + lp.leftMargin;
265             r = cx + tw / 2 - lp.rightMargin;
266             t = other.top - th + lp.topMargin;
267             b = other.top - lp.bottomMargin;
268             break;
269         }
270         v.layout(l, t, r, b);
271     }
272
273     private void toRight(View v, Rect other, int rotation) {
274         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
275         int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin;
276         int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin;
277         int cx = (other.left + other.right) / 2;
278         int cy = (other.top + other.bottom) / 2;
279         int l = 0, r = 0, t = 0, b = 0;
280         switch (rotation) {
281         case 0:
282             l = other.right + lp.leftMargin;
283             r = other.right + tw - lp.rightMargin;
284             t = cy - th / 2 + lp.topMargin;
285             b = cy + th / 2 - lp.bottomMargin;
286             break;
287         case 90:
288             l = cx - tw / 2 + lp.leftMargin;
289             r = cx + tw / 2 - lp.rightMargin;
290             t = other.top - th + lp.topMargin;
291             b = other.top - lp.bottomMargin;
292             break;
293         case 180:
294             l = other.left - tw + lp.leftMargin;
295             r = other.left - lp.rightMargin;
296             t = cy - th / 2 + lp.topMargin;
297             b = cy + th / 2 - lp.bottomMargin;
298             break;
299         case 270:
300             l = cx - tw / 2 + lp.leftMargin;
301             r = cx + tw / 2 - lp.rightMargin;
302             t = other.bottom + lp.topMargin;
303             b = other.bottom + th - lp.bottomMargin;
304             break;
305         }
306         v.layout(l, t, r, b);
307     }
308
309     private void topRight(View v, int l, int t, int r, int b) {
310         // layout using the specific margins; the rotation code messes up the others
311         int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top);
312         int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right);
313         v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight());
314     }
315
316     // In reverse landscape and reverse portrait, camera controls will be laid out
317     // on the wrong side of the screen. We need to make adjustment to move the controls
318     // to the USB side
319     public void adjustControlsToRightPosition() {
320         int orientation = Util.getDisplayRotation((Activity) getContext());
321         if (orientation >= 180) {
322             flipChildren();
323         }
324     }
325
326     private void adjustBackground() {
327         int rotation = getUnifiedRotation();
328         // remove current drawable and reset rotation
329         mBackgroundView.setBackgroundDrawable(null);
330         mBackgroundView.setRotationX(0);
331         mBackgroundView.setRotationY(0);
332         // if the switcher background is top aligned we need to flip the background
333         // drawable vertically; if left aligned, flip horizontally
334         switch (rotation) {
335             case 180:
336                 mBackgroundView.setRotationX(180);
337                 break;
338             case 270:
339                 mBackgroundView.setRotationY(180);
340                 break;
341             default:
342                 break;
343         }
344         mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);
345     }
346
347 }