1ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin/* 2ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * Copyright (C) 2010 The Android Open Source Project 3ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * 4ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * you may not use this file except in compliance with the License. 6ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * You may obtain a copy of the License at 7ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * 8ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * 10ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * Unless required by applicable law or agreed to in writing, software 11ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * See the License for the specific language governing permissions and 14ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin * limitations under the License. 15ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin */ 16ec1dfcb7314d10ff243a922fe4eff66ea699dd77Owen Lin 174de149ceb47f2c251f646419907424bfb67d2b64Owen Linpackage com.android.camera.ui; 184de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 19281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Linimport static com.android.camera.ui.GLRootView.dpToPixel; 201aaf351f6bbaa0b1dc6c08bd5a590e1930e2ef07Owen Lin 211aaf351f6bbaa0b1dc6c08bd5a590e1930e2ef07Owen Linimport java.util.ArrayList; 221aaf351f6bbaa0b1dc6c08bd5a590e1930e2ef07Owen Lin 234de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.content.Context; 24c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Linimport android.content.SharedPreferences; 25c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Linimport android.content.SharedPreferences.Editor; 26c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Linimport android.content.SharedPreferences.OnSharedPreferenceChangeListener; 274de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.graphics.Rect; 28706bd006d25aa8f322a9807eda6183a3941ad2c6Owen Linimport android.hardware.Camera.Parameters; 294de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.os.Handler; 304de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.os.Message; 314de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.util.DisplayMetrics; 324de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.view.MotionEvent; 334de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.view.View.MeasureSpec; 344de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.view.animation.AlphaAnimation; 354de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport android.view.animation.Animation; 364de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 374de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport com.android.camera.CameraSettings; 381ef634d277d550ed55b5b7089dfd56ed71815bd6Chih-Chung Changimport com.android.camera.ComboPreferences; 394de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport com.android.camera.IconListPreference; 404de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport com.android.camera.ListPreference; 414de149ceb47f2c251f646419907424bfb67d2b64Owen Linimport com.android.camera.PreferenceGroup; 426988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Linimport com.android.camera.R; 434de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 440d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin// This is the UI for the on-screen settings. Since the rendering is run in the 450d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin// GL thread. If any values will be changed in the main thread, it needs to 460d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin// synchronize on the <code>GLRootView</code> instance. 474de149ceb47f2c251f646419907424bfb67d2b64Owen Linpublic class HeadUpDisplay extends GLView { 48c557947a5897106421fec68b082539317e4b25d0Owen Lin private static final int INDICATOR_BAR_TIMEOUT = 5500; 49c557947a5897106421fec68b082539317e4b25d0Owen Lin private static final int POPUP_WINDOW_TIMEOUT = 5000; 50281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static final int INDICATOR_BAR_RIGHT_MARGIN = 10; 51281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static final int POPUP_WINDOW_OVERLAP = 20; 52281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static final int POPUP_TRIANGLE_OFFSET = 16; 53281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 54bef57e1d1fbb1881a7e3a22bb7567e8e7c2f0795Owen Lin private static final int COLOR_ICONBAR_HIGHLIGHT = 0x9A2B2B2B; 55bef57e1d1fbb1881a7e3a22bb7567e8e7c2f0795Owen Lin 5673304ce337208aa372836afa6edc4222a6dedde7Wu-cheng Li private static final float MAX_HEIGHT_RATIO = 0.85f; 574de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private static final float MAX_WIDTH_RATIO = 0.8f; 584de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 59c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin private static final int DESELECT_INDICATOR = 0; 604de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private static final int DEACTIVATE_INDICATOR_BAR = 1; 61281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 62281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static int sIndicatorBarRightMargin = -1; 63281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static int sPopupWindowOverlap; 64281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static int sPopupTriangleOffset; 65281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 667b783cb800a90b3f301374f354750292bb75f7aaOwen Lin private static final String TAG = "HeadUpDisplay"; 674de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 68469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin protected IndicatorBar mIndicatorBar; 6933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 701ef634d277d550ed55b5b7089dfd56ed71815bd6Chih-Chung Chang private ComboPreferences mSharedPrefs; 71469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin private PreferenceGroup mPreferenceGroup; 724de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 734de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private PopupWindow mPopupWindow; 744de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 756988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin private GLView mAnchorView; 764de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private int mOrientation = 0; 77f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin private boolean mEnabled = true; 784de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 79469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin protected Listener mListener; 804de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 810d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin private Handler mHandler = new Handler() { 820d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin @Override 830d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin public void handleMessage(Message msg) { 840d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin GLRootView root = getGLRootView(); 850d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (root != null) { 860d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin synchronized (root) { 870d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin handleMessageLocked(msg); 880d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 890d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } else { 900d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin handleMessageLocked(msg); 910d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 920d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 930d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin 940d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin private void handleMessageLocked(Message msg) { 950d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin switch(msg.what) { 960d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin case DESELECT_INDICATOR: 970d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.setSelectedIndex(IndicatorBar.INDEX_NONE); 980d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin break; 990d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin case DEACTIVATE_INDICATOR_BAR: 1000d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (mIndicatorBar != null) { 1010d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.setActivated(false); 1020d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1030d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin break; 1040d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1050d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1060d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin }; 1074de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 108c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin private final OnSharedPreferenceChangeListener mSharedPreferenceChangeListener = 109c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin new OnSharedPreferenceChangeListener() { 110c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin public void onSharedPreferenceChanged( 111c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin SharedPreferences sharedPreferences, String key) { 112c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin if (mListener != null) { 113c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mListener.onSharedPreferencesChanged(); 114c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 115c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 116c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin }; 117c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin 118281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin public HeadUpDisplay(Context context) { 119281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin initializeStaticVariables(context); 120c557947a5897106421fec68b082539317e4b25d0Owen Lin } 1214de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 122281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin private static void initializeStaticVariables(Context context) { 123281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin if (sIndicatorBarRightMargin >= 0) return; 124281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 125281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin sIndicatorBarRightMargin = dpToPixel(context, INDICATOR_BAR_RIGHT_MARGIN); 126281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin sPopupWindowOverlap = dpToPixel(context, POPUP_WINDOW_OVERLAP); 127281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin sPopupTriangleOffset = dpToPixel(context, POPUP_TRIANGLE_OFFSET); 128281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin } 129281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 130c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin /** 131c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin * The callback interface. All the callbacks will be called from the 132c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin * GLThread. 133c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin */ 1344de149ceb47f2c251f646419907424bfb67d2b64Owen Lin static public interface Listener { 1354de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public void onPopupWindowVisibilityChanged(int visibility); 136c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin public void onRestorePreferencesClicked(); 137c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin public void onSharedPreferencesChanged(); 1384de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1394de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1404de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public void overrideSettings(final String ... keyvalues) { 1414de149ceb47f2c251f646419907424bfb67d2b64Owen Lin GLRootView root = getGLRootView(); 1424de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (root != null) { 1430d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin synchronized (root) { 1440d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin overrideSettingsLocked(keyvalues); 1454de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1460d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } else { 1470d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin overrideSettingsLocked(keyvalues); 1480d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1490d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1500d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin 1510d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin public void overrideSettingsLocked(final String ... keyvalues) { 1520d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (keyvalues.length % 2 != 0) { 1530d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin throw new IllegalArgumentException(); 1540d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 1550d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin for (int i = 0, n = keyvalues.length; i < n; i += 2) { 1560d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.overrideSettings(keyvalues[i], keyvalues[i + 1]); 1574de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1584de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1594de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1604de149ceb47f2c251f646419907424bfb67d2b64Owen Lin @Override 1614de149ceb47f2c251f646419907424bfb67d2b64Owen Lin protected void onLayout( 1624de149ceb47f2c251f646419907424bfb67d2b64Owen Lin boolean changed, int left, int top, int right, int bottom) { 1634de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int width = right - left; 1644de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int height = bottom - top; 1654de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.measure( 1664de149ceb47f2c251f646419907424bfb67d2b64Owen Lin MeasureSpec.makeMeasureSpec(width / 3, MeasureSpec.AT_MOST), 1674de149ceb47f2c251f646419907424bfb67d2b64Owen Lin MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 1684de149ceb47f2c251f646419907424bfb67d2b64Owen Lin DisplayMetrics metrics = getGLRootView().getDisplayMetrics(); 1694de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int rightMargin = (int) (metrics.density * INDICATOR_BAR_RIGHT_MARGIN); 1704de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1714de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.layout( 1724de149ceb47f2c251f646419907424bfb67d2b64Owen Lin width - mIndicatorBar.getMeasuredWidth() - rightMargin, 0, 1734de149ceb47f2c251f646419907424bfb67d2b64Owen Lin width - rightMargin, height); 1744de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1754de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if(mPopupWindow != null 1764de149ceb47f2c251f646419907424bfb67d2b64Owen Lin && mPopupWindow.getVisibility() == GLView.VISIBLE) { 1776988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin layoutPopupWindow(mAnchorView); 1784de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1794de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1804de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1814de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public void initialize(Context context, PreferenceGroup preferenceGroup) { 18233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin mPreferenceGroup = preferenceGroup; 1831ef634d277d550ed55b5b7089dfd56ed71815bd6Chih-Chung Chang mSharedPrefs = ComboPreferences.get(context); 1848eaa6919f0d5c10c95c99f2f937d57ea5c4a5bbaWu-cheng Li mPopupWindow = null; 1858eaa6919f0d5c10c95c99f2f937d57ea5c4a5bbaWu-cheng Li clearComponents(); 1864de149ceb47f2c251f646419907424bfb67d2b64Owen Lin initializeIndicatorBar(context, preferenceGroup); 1878eaa6919f0d5c10c95c99f2f937d57ea5c4a5bbaWu-cheng Li requestLayout(); 1884de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 1894de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1906988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin private void layoutPopupWindow(GLView anchorView) { 1916988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin 1926988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin mAnchorView = anchorView; 1936988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin Rect rect = new Rect(); 1946988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin getBoundsOf(anchorView, rect); 1956988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin 1966988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin int anchorX = rect.left + sPopupWindowOverlap; 1976988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin int anchorY = (rect.top + rect.bottom) / 2; 1984de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 1994de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int width = (int) (getWidth() * MAX_WIDTH_RATIO + .5); 2004de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int height = (int) (getHeight() * MAX_HEIGHT_RATIO + .5); 2014de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2024de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.measure( 2034de149ceb47f2c251f646419907424bfb67d2b64Owen Lin MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 2044de149ceb47f2c251f646419907424bfb67d2b64Owen Lin MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); 2054de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2064de149ceb47f2c251f646419907424bfb67d2b64Owen Lin width = mPopupWindow.getMeasuredWidth(); 2074de149ceb47f2c251f646419907424bfb67d2b64Owen Lin height = mPopupWindow.getMeasuredHeight(); 2084de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2094de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int xoffset = Math.max(anchorX - width, 0); 2104de149ceb47f2c251f646419907424bfb67d2b64Owen Lin int yoffset = Math.max(0, anchorY - height / 2); 2114de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2124de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (yoffset + height > getHeight()) { 2134de149ceb47f2c251f646419907424bfb67d2b64Owen Lin yoffset = getHeight() - height; 2144de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2154de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setAnchorPosition(anchorY - yoffset); 2164de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.layout( 2174de149ceb47f2c251f646419907424bfb67d2b64Owen Lin xoffset, yoffset, xoffset + width, yoffset + height); 2184de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2194de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2206988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin private void showPopupWindow(GLView anchorView) { 2216988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin layoutPopupWindow(anchorView); 2224de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.popup(); 223c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mSharedPrefs.registerOnSharedPreferenceChangeListener( 224c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mSharedPreferenceChangeListener); 2254de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mListener != null) { 2264de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mListener.onPopupWindowVisibilityChanged(GLView.VISIBLE); 2274de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2284de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2294de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 230c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin private void hidePopupWindow() { 231c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mPopupWindow.popoff(); 23298e0be90b938b42814d3ee34e638a3f46c06fed4Wu-cheng Li // Unregister is important to avoid leaking activities. 23398e0be90b938b42814d3ee34e638a3f46c06fed4Wu-cheng Li // ComboPreference.sMap->ComboPreference->HeadUpDisplay->Activity 234c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mSharedPrefs.unregisterOnSharedPreferenceChangeListener( 235c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mSharedPreferenceChangeListener); 236c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin if (mListener != null) { 237c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mListener.onPopupWindowVisibilityChanged(GLView.INVISIBLE); 238c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 239c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 240c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin 2414de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private void scheduleDeactiviateIndicatorBar() { 242c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mHandler.removeMessages(DESELECT_INDICATOR); 243f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin mHandler.sendEmptyMessageDelayed( 244f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin DESELECT_INDICATOR, POPUP_WINDOW_TIMEOUT); 2454de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mHandler.removeMessages(DEACTIVATE_INDICATOR_BAR); 246f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin mHandler.sendEmptyMessageDelayed( 247f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin DEACTIVATE_INDICATOR_BAR, INDICATOR_BAR_TIMEOUT); 2484de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2494de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2500d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin public void setOrientation(int orientation) { 2510d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin GLRootView root = getGLRootView(); 2520d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (root != null) { 2530d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin synchronized (root) { 2540d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin setOrientationLocked(orientation); 2550d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 2560d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } else { 2570d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin setOrientationLocked(orientation); 2580d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 2594de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2604de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2610d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin private void setOrientationLocked(int orientation) { 2624de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mOrientation = orientation; 2636988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin mIndicatorBar.setOrientation(orientation); 2644de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mPopupWindow == null) return; 2654de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mPopupWindow.getVisibility() == GLView.VISIBLE) { 2666988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin Animation alpha = new AlphaAnimation(0.2f, 1); 2674de149ceb47f2c251f646419907424bfb67d2b64Owen Lin alpha.setDuration(250); 2684de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.startAnimation(alpha); 2694de149ceb47f2c251f646419907424bfb67d2b64Owen Lin scheduleDeactiviateIndicatorBar(); 2704de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2714de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setOrientation(orientation); 2724de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2734de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2744de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private void initializePopupWindow(Context context) { 2757b783cb800a90b3f301374f354750292bb75f7aaOwen Lin mPopupWindow = new PopupWindow(); 2764de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setBackground( 2774de149ceb47f2c251f646419907424bfb67d2b64Owen Lin new NinePatchTexture(context, R.drawable.menu_popup)); 2784de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setAnchor(new ResourceTexture( 279281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin context, R.drawable.menu_popup_triangle), sPopupTriangleOffset); 2804de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setVisibility(GLView.INVISIBLE); 2814de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setOrientation(mOrientation); 2824de149ceb47f2c251f646419907424bfb67d2b64Owen Lin addComponent(mPopupWindow); 2834de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2844de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2854de149ceb47f2c251f646419907424bfb67d2b64Owen Lin @Override 2864de149ceb47f2c251f646419907424bfb67d2b64Owen Lin protected boolean dispatchTouchEvent(MotionEvent event) { 287f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin if (mEnabled && super.dispatchTouchEvent(event)) { 2884de149ceb47f2c251f646419907424bfb67d2b64Owen Lin scheduleDeactiviateIndicatorBar(); 2894de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return true; 2904de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2914de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return false; 2924de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2934de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 294f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin public void setEnabled(boolean enabled) { 2950d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // The mEnabled variable is not related to the rendering thread, so we 2960d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // don't need to synchronize on the GLRootView. 297f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin if (mEnabled == enabled) return; 298f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin mEnabled = enabled; 299f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin } 300f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin 3014de149ceb47f2c251f646419907424bfb67d2b64Owen Lin @Override 3024de149ceb47f2c251f646419907424bfb67d2b64Owen Lin protected boolean onTouch(MotionEvent event) { 3034de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mPopupWindow == null 3044de149ceb47f2c251f646419907424bfb67d2b64Owen Lin || mPopupWindow.getVisibility() == GLView.INVISIBLE) { 3054de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return false; 3064de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3074de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3084de149ceb47f2c251f646419907424bfb67d2b64Owen Lin switch (event.getAction()) { 3094de149ceb47f2c251f646419907424bfb67d2b64Owen Lin case MotionEvent.ACTION_UP: 310c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin hidePopupWindow(); 3114de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.setSelectedIndex(IndicatorBar.INDEX_NONE); 3124de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.setActivated(false); 3134de149ceb47f2c251f646419907424bfb67d2b64Owen Lin break; 3144de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3154de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return true; 3164de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3174de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 318469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin protected static ListPreference[] getListPreferences( 3194de149ceb47f2c251f646419907424bfb67d2b64Owen Lin PreferenceGroup group, String ... prefKeys) { 3204de149ceb47f2c251f646419907424bfb67d2b64Owen Lin ArrayList<ListPreference> list = new ArrayList<ListPreference>(); 3214de149ceb47f2c251f646419907424bfb67d2b64Owen Lin for (String key : prefKeys) { 3224de149ceb47f2c251f646419907424bfb67d2b64Owen Lin ListPreference pref = group.findPreference(key); 3234de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (pref != null && pref.getEntries().length > 0) { 3244de149ceb47f2c251f646419907424bfb67d2b64Owen Lin list.add(pref); 3254de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3264de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3274de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return list.toArray(new ListPreference[list.size()]); 3284de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3294de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 330469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin protected BasicIndicator addIndicator( 331469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin Context context, PreferenceGroup group, String key) { 3324de149ceb47f2c251f646419907424bfb67d2b64Owen Lin IconListPreference iconPref = 3334de149ceb47f2c251f646419907424bfb67d2b64Owen Lin (IconListPreference) group.findPreference(key); 3344de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (iconPref == null) return null; 3358eaa6919f0d5c10c95c99f2f937d57ea5c4a5bbaWu-cheng Li BasicIndicator indicator = new BasicIndicator(context, iconPref); 336469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin mIndicatorBar.addComponent(indicator); 3374de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return indicator; 3384de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3394de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 340469a9ef839e38630e1e652d182f7e0ee5882e277Owen Lin protected void initializeIndicatorBar( 3414de149ceb47f2c251f646419907424bfb67d2b64Owen Lin Context context, PreferenceGroup group) { 3424de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar = new IndicatorBar(); 3434de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3444de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.setBackground(new NinePatchTexture( 3454de149ceb47f2c251f646419907424bfb67d2b64Owen Lin context, R.drawable.ic_viewfinder_iconbar)); 346bef57e1d1fbb1881a7e3a22bb7567e8e7c2f0795Owen Lin mIndicatorBar.setHighlight(new ColorTexture(COLOR_ICONBAR_HIGHLIGHT)); 3474de149ceb47f2c251f646419907424bfb67d2b64Owen Lin addComponent(mIndicatorBar); 3484de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mIndicatorBar.setOnItemSelectedListener(new IndicatorBarListener()); 3494de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3504de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3514de149ceb47f2c251f646419907424bfb67d2b64Owen Lin private class IndicatorBarListener 3524de149ceb47f2c251f646419907424bfb67d2b64Owen Lin implements IndicatorBar.OnItemSelectedListener { 3534de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3544de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public void onItemSelected(GLView view, int position) { 3554de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3564de149ceb47f2c251f646419907424bfb67d2b64Owen Lin AbstractIndicator indicator = (AbstractIndicator) view; 3574de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mPopupWindow == null) { 3584de149ceb47f2c251f646419907424bfb67d2b64Owen Lin initializePopupWindow(getGLRootView().getContext()); 3594de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3604de149ceb47f2c251f646419907424bfb67d2b64Owen Lin mPopupWindow.setContent(indicator.getPopupContent()); 3614de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3624de149ceb47f2c251f646419907424bfb67d2b64Owen Lin if (mPopupWindow.getVisibility() == GLView.VISIBLE) { 3636988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin layoutPopupWindow(indicator); 3644de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } else { 3656988d4e2ef8d14d8bf3ee81c8eb3175bbf1b88ecOwen Lin showPopupWindow(indicator); 3664de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3674de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3684de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 3694de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public void onNothingSelected() { 370c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin hidePopupWindow(); 3714de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 3724de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 37333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 3740d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin public boolean collapse() { 3750d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // We don't need to synchronize on GLRootView, since both the 3760d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // <code>isActivated()</code> and rendering thread are read-only to 3770d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // the variables inside. 3780d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (!mIndicatorBar.isActivated()) return false; 3790d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mHandler.removeMessages(DESELECT_INDICATOR); 3800d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mHandler.removeMessages(DEACTIVATE_INDICATOR_BAR); 3810d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin GLRootView root = getGLRootView(); 3820d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (root != null) { 3830d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin synchronized (root) { 3840d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.setSelectedIndex(IndicatorBar.INDEX_NONE); 3850d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.setActivated(false); 3860d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 3870d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } else { 388f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin mIndicatorBar.setSelectedIndex(IndicatorBar.INDEX_NONE); 389f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin mIndicatorBar.setActivated(false); 390f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin } 3910d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin return true; 392c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 393c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin 394c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin public void setListener(Listener listener) { 3950d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // No synchronization: mListener won't be accessed in rendering thread 396c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin mListener = listener; 397c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin } 398c24155c65b45f554ffc29c523d7ea8e63ea10d33Owen Lin 399706bd006d25aa8f322a9807eda6183a3941ad2c6Owen Lin public void restorePreferences(final Parameters param) { 4000d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // Do synchronization in "reloadPreferences()" 4010d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin 4020d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin OnSharedPreferenceChangeListener l = 4030d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mSharedPreferenceChangeListener; 4040d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // Unregister the listener since "upgrade preference" will 4050d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // change bunch of preferences. We can handle them with one 4060d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin // onSharedPreferencesChanged(); 4070d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mSharedPrefs.unregisterOnSharedPreferenceChangeListener(l); 4080d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin Context context = getGLRootView().getContext(); 4090d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin Editor editor = mSharedPrefs.edit(); 4100d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin editor.clear(); 4114714a1cf1d211aad2d8cf1802f85f649e744beb0Wu-cheng Li editor.apply(); 4121ef634d277d550ed55b5b7089dfd56ed71815bd6Chih-Chung Chang CameraSettings.upgradeAllPreferences(mSharedPrefs); 4130d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin CameraSettings.initialCameraPictureSize(context, param); 4140d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin reloadPreferences(); 4150d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (mListener != null) { 4160d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mListener.onSharedPreferencesChanged(); 4170d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 4180d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mSharedPrefs.registerOnSharedPreferenceChangeListener(l); 41933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 420f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin 421f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin public void reloadPreferences() { 4220d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin GLRootView root = getGLRootView(); 4230d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin if (root != null) { 4240d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin synchronized (root) { 4250d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mPreferenceGroup.reloadValue(); 4260d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.reloadPreferences(); 4270d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 4280d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } else { 4290d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mPreferenceGroup.reloadValue(); 4300d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin mIndicatorBar.reloadPreferences(); 4310d73bccf89870682007dd32d4a84bcdb812e2cc7Owen Lin } 432f5876dbd29607a0e9762f88e9db6fa35ffb20067Owen Lin } 4334de149ceb47f2c251f646419907424bfb67d2b64Owen Lin} 434