diff options
Diffstat (limited to 'src/com/android/camera/ui')
-rw-r--r-- | src/com/android/camera/ui/BasicIndicator.java | 50 | ||||
-rw-r--r-- | src/com/android/camera/ui/BasicSettingPicker.java | 120 | ||||
-rw-r--r-- | src/com/android/camera/ui/CamcorderHeadUpDisplay.java | 14 | ||||
-rw-r--r-- | src/com/android/camera/ui/ControlPanel.java | 155 | ||||
-rw-r--r-- | src/com/android/camera/ui/GLLinearLayout.java (renamed from src/com/android/camera/ui/LinearLayout.java) | 2 | ||||
-rw-r--r-- | src/com/android/camera/ui/GLListView.java | 27 | ||||
-rw-r--r-- | src/com/android/camera/ui/GLPopupWindow.java (renamed from src/com/android/camera/ui/PopupWindow.java) | 9 | ||||
-rw-r--r-- | src/com/android/camera/ui/GLRootView.java | 10 | ||||
-rw-r--r-- | src/com/android/camera/ui/GLView.java | 24 | ||||
-rw-r--r-- | src/com/android/camera/ui/GpsIndicator.java | 2 | ||||
-rw-r--r-- | src/com/android/camera/ui/HeadUpDisplay.java | 21 | ||||
-rw-r--r-- | src/com/android/camera/ui/IndicatorButton.java | 38 | ||||
-rw-r--r-- | src/com/android/camera/ui/IndicatorWheel.java | 170 | ||||
-rw-r--r-- | src/com/android/camera/ui/RotatePane.java | 8 | ||||
-rw-r--r-- | src/com/android/camera/ui/ZoomIndicator.java | 4 |
15 files changed, 598 insertions, 56 deletions
diff --git a/src/com/android/camera/ui/BasicIndicator.java b/src/com/android/camera/ui/BasicIndicator.java index 7630a8e..9f076b8 100644 --- a/src/com/android/camera/ui/BasicIndicator.java +++ b/src/com/android/camera/ui/BasicIndicator.java @@ -19,31 +19,47 @@ package com.android.camera.ui; import android.content.Context; import com.android.camera.IconListPreference; +import com.android.camera.ListPreference; import com.android.camera.R; import com.android.camera.Util; import com.android.camera.ui.GLListView.OnItemSelectedListener; class BasicIndicator extends AbstractIndicator { + private static final float FONT_SIZE = 18; + private static final int FONT_COLOR = 0xA8FFFFFF; private static final int COLOR_OPTION_ITEM_HIGHLIGHT = 0xFF181818; private final ResourceTexture mIcon[]; - private final IconListPreference mPreference; + private final ListPreference mPreference; protected int mIndex; private GLListView mPopupContent; private PreferenceAdapter mModel; private String mOverride; + private int mTitleIndex; + private StringTexture mTitle; + private final float mFontSize; + private boolean mIsIconListMode; - public BasicIndicator(Context context, IconListPreference preference) { + public BasicIndicator(Context context, ListPreference preference) { super(context); mPreference = preference; - mIcon = new ResourceTexture[preference.getLargeIconIds().length]; mIndex = preference.findIndexOfValue(preference.getValue()); + if (preference instanceof IconListPreference) { + mIsIconListMode = true; + mIcon = new ResourceTexture[((IconListPreference) preference).getLargeIconIds().length]; + mFontSize = 0; + } else { + mIsIconListMode = false; + mIcon = null; + mFontSize = GLRootView.dpToPixel(context, FONT_SIZE); + mTitleIndex = -1; + } } // Set the override and/or reload the value from preferences. private void updateContent(String override, boolean reloadValue) { if (!reloadValue && Util.equals(mOverride, override)) return; - IconListPreference pref = mPreference; + ListPreference pref = mPreference; mOverride = override; int index = pref.findIndexOfValue( override == null ? pref.getValue() : override); @@ -55,7 +71,7 @@ class BasicIndicator extends AbstractIndicator { @Override public void overrideSettings(String key, String settings) { - IconListPreference pref = mPreference; + ListPreference pref = mPreference; if (!pref.getKey().equals(key)) return; updateContent(settings, false); } @@ -104,13 +120,23 @@ class BasicIndicator extends AbstractIndicator { } @Override - protected ResourceTexture getIcon() { - int index = mIndex; - if (mIcon[index] == null) { - Context context = getGLRootView().getContext(); - mIcon[index] = new ResourceTexture( - context, mPreference.getLargeIconIds()[index]); + protected BitmapTexture getIcon() { + if (mIsIconListMode) { + int index = mIndex; + if (mIcon[index] == null) { + Context context = getGLRootView().getContext(); + mIcon[index] = new ResourceTexture( + context, ((IconListPreference) mPreference).getLargeIconIds()[index]); + } + return mIcon[index]; + } else { + if (mTitleIndex != mIndex) { + mTitleIndex = mIndex; + if (mTitle != null) mTitle.deleteFromGL(); + String value = mPreference.getEntry(); + mTitle = StringTexture.newInstance(value, mFontSize, FONT_COLOR); + } + return mTitle; } - return mIcon[index]; } } diff --git a/src/com/android/camera/ui/BasicSettingPicker.java b/src/com/android/camera/ui/BasicSettingPicker.java new file mode 100644 index 0000000..b794f21 --- /dev/null +++ b/src/com/android/camera/ui/BasicSettingPicker.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.camera.IconListPreference; +import com.android.camera.R; +import com.android.camera.Util; +import com.android.camera.ui.GLListView.OnItemSelectedListener; + +public class BasicSettingPicker extends LinearLayout { + private static final String TAG = "BasicSettingPicker"; + private IconListPreference mPreference; + private final Context mContext; + private Listener mListener; + + static public interface Listener { + public void onSharedPreferenceChanged(); + } + + public BasicSettingPicker(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + public void initialize(IconListPreference preference) { + mPreference = preference; + LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + CharSequence[] entries = mPreference.getEntries(); + CharSequence[] values = mPreference.getEntryValues(); + int[] imageIds = mPreference.getImageIds(); + int index = preference.findIndexOfValue(preference.getValue()); + + int pos = 0; + for (int i = 0, n = entries.length; i < n; ++i) { + // Add the image. + ImageView image; + Drawable drawable = mContext.getResources().getDrawable(imageIds[i]); + // Sacle the image if it is too small. + if (drawable.getIntrinsicWidth() >= getLayoutParams().width) { + image = (ImageView) inflater.inflate( + R.layout.setting_image_item, null); + } else { + image = (ImageView) inflater.inflate( + R.layout.setting_scale_image_item, null); + } + image.setImageDrawable(drawable); + image.setClickable(false); + addView(image, pos++); + + // Add the text. + TextView text = (TextView) inflater.inflate( + R.layout.setting_text_item, null); + text.setText(entries[i].toString()); + text.setClickable(false); + if (index == i) text.setPressed(true); + addView(text, pos++); + } + requestLayout(); + } + + public void setSharedPreferenceChangedListener(Listener listener) { + mListener = listener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction(); + if (action == MotionEvent.ACTION_MOVE + || action == MotionEvent.ACTION_DOWN) { + int y = (int) event.getY(); + // Check which child is pressed. + for (int i = 0; i < getChildCount() - 1; i++) { + View v = getChildAt(i); + if (y >= v.getTop() && y <= v.getBottom()) { + int index = i / 2; + CharSequence[] values = mPreference.getEntryValues(); + int oldIndex = mPreference.findIndexOfValue(mPreference.getValue()); + if (oldIndex != index) { + View oldText = getChildAt(oldIndex * 2 + 1); + oldText.setPressed(false); + View text = getChildAt(index * 2 + 1); + text.setPressed(true); + mPreference.setValueIndex(index); + if (mListener != null) { + mListener.onSharedPreferenceChanged(); + } + } + } + } + return true; + } + return false; + } +} diff --git a/src/com/android/camera/ui/CamcorderHeadUpDisplay.java b/src/com/android/camera/ui/CamcorderHeadUpDisplay.java index 8e98100..c69b92b 100644 --- a/src/com/android/camera/ui/CamcorderHeadUpDisplay.java +++ b/src/com/android/camera/ui/CamcorderHeadUpDisplay.java @@ -26,12 +26,19 @@ public class CamcorderHeadUpDisplay extends HeadUpDisplay { private static final String TAG = "CamcorderHeadUpDisplay"; + private boolean mCaptureTimeLapse; private OtherSettingsIndicator mOtherSettings; public CamcorderHeadUpDisplay(Context context) { super(context); } + public void initialize(Context context, PreferenceGroup group, + boolean captureTimeLapse) { + mCaptureTimeLapse = captureTimeLapse; + super.initialize(context, group); + } + @Override protected void initializeIndicatorBar( Context context, PreferenceGroup group) { @@ -57,7 +64,12 @@ public class CamcorderHeadUpDisplay extends HeadUpDisplay { addIndicator(context, group, CameraSettings.KEY_WHITE_BALANCE); addIndicator(context, group, CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE); - addIndicator(context, group, CameraSettings.KEY_VIDEO_QUALITY); + if (mCaptureTimeLapse) { + addIndicator(context, group, CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL); + addIndicator(context, group, CameraSettings.KEY_VIDEO_TIME_LAPSE_QUALITY); + } else { + addIndicator(context, group, CameraSettings.KEY_VIDEO_QUALITY); + } addIndicator(context, group, CameraSettings.KEY_CAMERA_ID); } } diff --git a/src/com/android/camera/ui/ControlPanel.java b/src/com/android/camera/ui/ControlPanel.java new file mode 100644 index 0000000..d9ede52 --- /dev/null +++ b/src/com/android/camera/ui/ControlPanel.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.CameraSettings; +import com.android.camera.ComboPreferences; +import com.android.camera.IconListPreference; +import com.android.camera.PreferenceGroup; +import com.android.camera.R; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.KeyEvent; +import android.view.View; +import android.widget.Button; +import android.widget.ListView; +import android.widget.RelativeLayout; + +public class ControlPanel extends RelativeLayout + implements BasicSettingPicker.Listener, IndicatorWheel.Listener, + View.OnClickListener { + private static final String TAG = "ControlPanel"; + private Context mContext; + private ComboPreferences mSharedPrefs; + private PreferenceGroup mPreferenceGroup; + private String[] mPreferenceKeys; + private Listener mListener; + private IndicatorWheel mIndicatorWheel; + private BasicSettingPicker[] mSettingPickers; + private int mActiveIndicator = -1; + + private ListView mThumbnailList; + + static public interface Listener { + public void onSharedPreferencesChanged(); + } + + public void setListener(Listener listener) { + mListener = listener; + } + + public ControlPanel(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + protected void addIndicator( + Context context, PreferenceGroup group, String key) { + IconListPreference pref = (IconListPreference) group.findPreference(key); + if (pref == null) return; + IndicatorButton b = new IndicatorButton(context, pref); + mIndicatorWheel.addView(b); + } + + private void addOtherSettingIndicator(Context context) { + Button b = new Button(context); + b.setBackgroundResource(R.drawable.ic_viewfinder_settings); + b.setClickable(false); + mIndicatorWheel.addView(b); + } + + public void initialize(Context context, PreferenceGroup group, String[] keys) { + mPreferenceGroup = group; + mPreferenceKeys = keys; + // Add one more for other settings. + mSettingPickers = new BasicSettingPicker[mPreferenceKeys.length + 1]; + mIndicatorWheel = (IndicatorWheel) findViewById(R.id.indicator_wheel); + mThumbnailList = (ListView) findViewById(R.id.thumbnail_list); + mSharedPrefs = ComboPreferences.get(context); + for (int i = 0; i < mPreferenceKeys.length; i++) { + addIndicator(context, group, mPreferenceKeys[i]); + } + addOtherSettingIndicator(context); + requestLayout(); + mIndicatorWheel.setListener(this); + } + + public void onSharedPreferenceChanged() { + mIndicatorWheel.updateIndicator(mActiveIndicator); + if (mListener != null) { + mListener.onSharedPreferencesChanged(); + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.setting_exit: + hideSettingPicker(); + break; + } + } + + public void onIndicatorClicked(int index) { + if (mSettingPickers[index] == null) { + initializeSettingPicker(index); + } + if (!showSettingPicker(index)) { + hideSettingPicker(); + } + } + + private void initializeSettingPicker(int index) { + if (index >= mPreferenceKeys.length) return; + IconListPreference pref = (IconListPreference) + mPreferenceGroup.findPreference(mPreferenceKeys[index]); + + LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.setting_picker, this); + mSettingPickers[index] = (BasicSettingPicker) getChildAt(getChildCount() - 1); + mSettingPickers[index].setSharedPreferenceChangedListener(this); + mSettingPickers[index].initialize(pref); + View v = mSettingPickers[index].findViewById(R.id.setting_exit); + v.setOnClickListener(this); + } + + private boolean showSettingPicker(int index) { + if (mSettingPickers[index] == null) return false; + + mThumbnailList.setVisibility(View.INVISIBLE); + for (int i = 0; i < mSettingPickers.length; i++) { + if (i != index && mSettingPickers[i] != null) { + mSettingPickers[i].setVisibility(View.INVISIBLE); + } + } + mSettingPickers[index].setVisibility(View.VISIBLE); + mActiveIndicator = index; + return true; + } + + public void hideSettingPicker() { + if (mActiveIndicator >= 0) { + mSettingPickers[mActiveIndicator].setVisibility(View.INVISIBLE); + mThumbnailList.setVisibility(View.VISIBLE); + mActiveIndicator = -1; + } + } +} diff --git a/src/com/android/camera/ui/LinearLayout.java b/src/com/android/camera/ui/GLLinearLayout.java index 0e812d8..cb0f064 100644 --- a/src/com/android/camera/ui/LinearLayout.java +++ b/src/com/android/camera/ui/GLLinearLayout.java @@ -19,7 +19,7 @@ package com.android.camera.ui; import android.graphics.Rect; import android.view.View.MeasureSpec; -class LinearLayout extends GLView { +class GLLinearLayout extends GLView { @Override protected void onMeasure(int widthSpec, int heightSpec) { diff --git a/src/com/android/camera/ui/GLListView.java b/src/com/android/camera/ui/GLListView.java index c1bc11a..ed22ea3 100644 --- a/src/com/android/camera/ui/GLListView.java +++ b/src/com/android/camera/ui/GLListView.java @@ -17,10 +17,12 @@ package com.android.camera.ui; import static android.view.View.MeasureSpec.makeMeasureSpec; +import com.android.camera.Util; import android.content.Context; import android.graphics.Rect; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.view.GestureDetector; import android.view.MotionEvent; @@ -30,15 +32,13 @@ import android.view.animation.Animation; import android.view.animation.Transformation; import android.widget.Scroller; -import com.android.camera.Util; - import javax.microedition.khronos.opengles.GL11; class GLListView extends GLView { @SuppressWarnings("unused") private static final String TAG = "GLListView"; private static final int INDEX_NONE = -1; - private static final int SCROLL_BAR_TIMEOUT = 2500; + private static final int SCROLL_BAR_TIMEOUT = 1000; private static final int HIDE_SCROLL_BAR = 1; @@ -77,7 +77,7 @@ class GLListView extends GLView { public GLListView(Context context) { mScroller = new Scroller(context); - mHandler = new Handler() { + mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { GLRootView root = getGLRootView(); @@ -102,13 +102,25 @@ class GLListView extends GLView { context, new MyGestureListener(), mHandler); } + private final Runnable mHideScrollBar = new Runnable() { + public void run() { + setScrollBarVisible(false); + } + }; + @Override protected void onVisibilityChanged(int visibility) { super.onVisibilityChanged(visibility); - if (visibility == GLView.VISIBLE && mScrollHeight > getHeight()) { + if (mScrollHeight > getHeight()) updateScrollBar(visibility); + } + + private void updateScrollBar(int visibility) { + if (isVisible()) { setScrollBarVisible(true); mHandler.sendEmptyMessageDelayed( HIDE_SCROLL_BAR, SCROLL_BAR_TIMEOUT); + } else { + mHandler.removeMessages(HIDE_SCROLL_BAR); } } @@ -294,7 +306,10 @@ class GLListView extends GLView { mIsPressed = true; mHandler.removeMessages(HIDE_SCROLL_BAR); setScrollBarVisible(mScrollHeight > getHeight()); - + if (!mScroller.isFinished()) { + mScroller.forceFinished(true); + break; + } // fallthrough: we need to highlight the item which is pressed case MotionEvent.ACTION_MOVE: if (!mScrollable) { diff --git a/src/com/android/camera/ui/PopupWindow.java b/src/com/android/camera/ui/GLPopupWindow.java index c2bf533..79482ac 100644 --- a/src/com/android/camera/ui/PopupWindow.java +++ b/src/com/android/camera/ui/GLPopupWindow.java @@ -26,7 +26,7 @@ import android.view.animation.ScaleAnimation; import javax.microedition.khronos.opengles.GL11; -class PopupWindow extends GLView { +class GLPopupWindow extends GLView { protected BitmapTexture mAnchor; protected int mAnchorOffset; @@ -38,7 +38,7 @@ class PopupWindow extends GLView { protected Texture mBackground; private boolean mUsingStencil; - public PopupWindow() { + public GLPopupWindow() { super.addComponent(mRotatePane); } @@ -186,11 +186,6 @@ class PopupWindow extends GLView { mRotatePane.setContent(content); } - @Override - public void clearComponents() { - throw new UnsupportedOperationException(); - } - public void popup() { setVisibility(GLView.VISIBLE); diff --git a/src/com/android/camera/ui/GLRootView.java b/src/com/android/camera/ui/GLRootView.java index e7ac5e3..bdb0a8e 100644 --- a/src/com/android/camera/ui/GLRootView.java +++ b/src/com/android/camera/ui/GLRootView.java @@ -30,6 +30,7 @@ import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; +import android.view.View; import android.view.animation.Animation; import android.view.animation.Transformation; @@ -37,7 +38,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Stack; - import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; @@ -728,4 +728,12 @@ public class GLRootView extends GLSurfaceView texture.setTextureSize(newWidth, newHeight); } + @Override + protected void onVisibilityChanged(View changedView, int v) { + super.onVisibilityChanged(changedView, v); + if (mContentView != null) { + mContentView.onVisibilityChanged( + v == View.VISIBLE ? GLView.VISIBLE : GLView.INVISIBLE); + } + } } diff --git a/src/com/android/camera/ui/GLView.java b/src/com/android/camera/ui/GLView.java index 184016e..811527a 100644 --- a/src/com/android/camera/ui/GLView.java +++ b/src/com/android/camera/ui/GLView.java @@ -20,11 +20,11 @@ import android.graphics.Matrix; import android.graphics.Rect; import android.os.SystemClock; import android.view.MotionEvent; +import android.view.View; import android.view.animation.Animation; import android.view.animation.Transformation; import java.util.ArrayList; - import javax.microedition.khronos.opengles.GL11; public class GLView { @@ -81,8 +81,22 @@ public class GLView { } else { mViewFlags |= FLAG_INVISIBLE; } - onVisibilityChanged(visibility); invalidate(); + + // Trigger the onVisibilityChanged() if it is visible on the screen. + if (isVisible()) onVisibilityChanged(visibility); + } + + public boolean isVisible() { + if (mRootView == null || mRootView.getVisibility() != View.VISIBLE) { + return false; + } + GLView parent = mParent; + while (parent != null) { + if (parent.getVisibility() == GLView.INVISIBLE) return false; + parent = parent.mParent; + } + return true; } public int getVisibility() { @@ -141,6 +155,7 @@ public class GLView { } mComponents.add(component); component.onAddToParent(this); + if (isVisible()) component.onVisibilityChanged(VISIBLE); } public boolean removeComponent(GLView component) { @@ -362,10 +377,7 @@ public class GLView { protected void onVisibilityChanged(int visibility) { for (int i = 0, n = getComponentCount(); i < n; ++i) { - GLView child = getComponent(i); - if (child.getVisibility() == GLView.VISIBLE) { - child.onVisibilityChanged(visibility); - } + getComponent(i).onVisibilityChanged(visibility); } } diff --git a/src/com/android/camera/ui/GpsIndicator.java b/src/com/android/camera/ui/GpsIndicator.java index 78a80b8..c1cb2ef 100644 --- a/src/com/android/camera/ui/GpsIndicator.java +++ b/src/com/android/camera/ui/GpsIndicator.java @@ -33,7 +33,7 @@ class GpsIndicator extends BasicIndicator { } @Override - protected ResourceTexture getIcon() { + protected BitmapTexture getIcon() { if (mIndex == GPS_ON_INDEX && !mHasSignal) { if (mNoSignalIcon == null) { Context context = getGLRootView().getContext(); diff --git a/src/com/android/camera/ui/HeadUpDisplay.java b/src/com/android/camera/ui/HeadUpDisplay.java index 1b0415f..074effd 100644 --- a/src/com/android/camera/ui/HeadUpDisplay.java +++ b/src/com/android/camera/ui/HeadUpDisplay.java @@ -17,8 +17,11 @@ package com.android.camera.ui; import static com.android.camera.ui.GLRootView.dpToPixel; - -import java.util.ArrayList; +import com.android.camera.CameraSettings; +import com.android.camera.ComboPreferences; +import com.android.camera.ListPreference; +import com.android.camera.PreferenceGroup; +import com.android.camera.R; import android.content.Context; import android.content.SharedPreferences; @@ -34,12 +37,7 @@ import android.view.View.MeasureSpec; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import com.android.camera.CameraSettings; -import com.android.camera.ComboPreferences; -import com.android.camera.IconListPreference; -import com.android.camera.ListPreference; -import com.android.camera.PreferenceGroup; -import com.android.camera.R; +import java.util.ArrayList; // This is the UI for the on-screen settings. Since the rendering is run in the // GL thread. If any values will be changed in the main thread, it needs to @@ -70,7 +68,7 @@ public class HeadUpDisplay extends GLView { private ComboPreferences mSharedPrefs; private PreferenceGroup mPreferenceGroup; - private PopupWindow mPopupWindow; + private GLPopupWindow mPopupWindow; private GLView mAnchorView; private int mOrientation = 0; @@ -272,7 +270,7 @@ public class HeadUpDisplay extends GLView { } private void initializePopupWindow(Context context) { - mPopupWindow = new PopupWindow(); + mPopupWindow = new GLPopupWindow(); mPopupWindow.setBackground( new NinePatchTexture(context, R.drawable.menu_popup)); mPopupWindow.setAnchor(new ResourceTexture( @@ -329,8 +327,7 @@ public class HeadUpDisplay extends GLView { protected BasicIndicator addIndicator( Context context, PreferenceGroup group, String key) { - IconListPreference iconPref = - (IconListPreference) group.findPreference(key); + ListPreference iconPref = group.findPreference(key); if (iconPref == null) return null; BasicIndicator indicator = new BasicIndicator(context, iconPref); mIndicatorBar.addComponent(indicator); diff --git a/src/com/android/camera/ui/IndicatorButton.java b/src/com/android/camera/ui/IndicatorButton.java new file mode 100644 index 0000000..c4145de --- /dev/null +++ b/src/com/android/camera/ui/IndicatorButton.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.IconListPreference; + +import android.content.Context; +import android.widget.Button; + +public class IndicatorButton extends Button { + private IconListPreference mPreference; + + public IndicatorButton(Context context, IconListPreference pref) { + super(context); + mPreference = pref; + setClickable(false); + reloadPreference(); + } + + public void reloadPreference() { + int index = mPreference.findIndexOfValue(mPreference.getValue()); + setBackgroundResource(mPreference.getLargeIconIds()[index]); + } +} diff --git a/src/com/android/camera/ui/IndicatorWheel.java b/src/com/android/camera/ui/IndicatorWheel.java new file mode 100644 index 0000000..aab41fc --- /dev/null +++ b/src/com/android/camera/ui/IndicatorWheel.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import com.android.camera.ComboPreferences; +import com.android.camera.PreferenceGroup; +import com.android.camera.R; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.widget.Button; +import android.view.MotionEvent; +import android.view.ViewGroup; +import android.view.View; + +import java.lang.Math; + +/** + * A view that contains camera settings and shutter buttons. The settings are + * spreaded around the shutter button. + */ +public class IndicatorWheel extends ViewGroup { + private static final String TAG = "IndicatorWheel"; + private Listener mListener; + private int mCenterX, mCenterY; + private double mShutterButtonRadius; + private double mSectorInitialRadians[]; + + static public interface Listener { + public void onIndicatorClicked(int index); + } + + public void setListener(Listener listener) { + mListener = listener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int count = getChildCount(); + if (mListener == null || count <= 1) return false; + + // Check if any setting is pressed. + int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN + || action == MotionEvent.ACTION_MOVE) { + double dx = event.getX() - mCenterX; + double dy = mCenterY - event.getY(); + double radius = Math.sqrt(dx * dx + dy * dy); + // Ignore the event if it's too near to the shutter button. + if (radius < mShutterButtonRadius) return false; + + double intervalDegrees = 180.0 / (count - 2); + double delta = Math.atan2(dy, dx); + if (delta < 0) delta += Math.PI * 2; + // Check which sector is pressed. + if (delta > mSectorInitialRadians[0]) { + for (int i = 1; i < count; i++) { + if (delta < mSectorInitialRadians[i]) { + mListener.onIndicatorClicked(i - 1); + return true; + } + } + } + } + return false; + } + + public IndicatorWheel(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + // Measure all children. + int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).measure(freeSpec, freeSpec); + } + + // Measure myself. + View shutterButton = getChildAt(0); + int desiredWidth = (int)(shutterButton.getMeasuredWidth() * 2.5); + int desiredHeight = (int)(shutterButton.getMeasuredHeight() * 2.5); + int widthMode = MeasureSpec.getMode(widthSpec); + int heightMode = MeasureSpec.getMode(heightSpec); + int measuredWidth, measuredHeight; + if (widthMode == MeasureSpec.UNSPECIFIED) { + measuredWidth = desiredWidth; + } else if (widthMode == MeasureSpec.AT_MOST) { + measuredWidth = Math.min(desiredWidth, MeasureSpec.getSize(widthSpec)); + } else { // MeasureSpec.EXACTLY + measuredWidth = MeasureSpec.getSize(widthSpec); + } + if (heightMode == MeasureSpec.UNSPECIFIED) { + measuredHeight = desiredHeight; + } else if (heightMode == MeasureSpec.AT_MOST) { + measuredHeight = Math.min(desiredHeight, MeasureSpec.getSize(heightSpec)); + } else { // MeasureSpec.EXACTLY + measuredHeight = MeasureSpec.getSize(heightSpec); + } + setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + protected void onLayout( + boolean changed, int left, int top, int right, int bottom) { + int count = getChildCount(); + if (count == 0) return; + + // Layout the shutter button. + View shutterButton = findViewById(R.id.shutter_button); + int width = shutterButton.getMeasuredWidth(); + mShutterButtonRadius = width / 2.0 + 10; + int height = shutterButton.getMeasuredHeight(); + mCenterX = (right - left) - width / 2; + mCenterY = (bottom - top) / 2; + shutterButton.layout(mCenterX - width / 2, mCenterY - height / 2, + mCenterX + width / 2, mCenterY + height / 2); + + // Layout the settings. The icons are spreaded on the left side of the + // shutter button. So the angle starts from 90 to 270 degrees. + if (count == 1) return; + double radius = shutterButton.getMeasuredWidth(); + double intervalDegrees = 180.0 / (count - 2); + double initialDegrees = 90.0; + int index = 0; + for (int i = 0; i < count; i++) { + View view = getChildAt(i); + if (view == shutterButton) continue; + double degree = initialDegrees + intervalDegrees * index; + double radian = Math.toRadians(degree); + int x = mCenterX + (int)(radius * Math.cos(radian)); + int y = mCenterY - (int)(radius * Math.sin(radian)); + width = view.getMeasuredWidth(); + height = view.getMeasuredHeight(); + view.layout(x - width / 2, y - height / 2, x + width / 2, + y + height / 2); + index++; + } + + // Store the radian intervals for each icon. + mSectorInitialRadians = new double[count]; + mSectorInitialRadians[0] = Math.toRadians( + initialDegrees - intervalDegrees / 2.0); + for (int i = 1; i < count; i++) { + mSectorInitialRadians[i] = mSectorInitialRadians[i - 1] + + Math.toRadians(intervalDegrees); + } + } + + public void updateIndicator(int index) { + IndicatorButton indicator = (IndicatorButton) getChildAt(index + 1); + indicator.reloadPreference(); + } +} diff --git a/src/com/android/camera/ui/RotatePane.java b/src/com/android/camera/ui/RotatePane.java index 9f9effa..45f6a0d 100644 --- a/src/com/android/camera/ui/RotatePane.java +++ b/src/com/android/camera/ui/RotatePane.java @@ -117,8 +117,7 @@ class RotatePane extends GLView { public void setContent(GLView view) { if (mChild == view) return; - - if (mChild != null) super.clearComponents(); + if (mChild != null) super.removeComponent(mChild); mChild = view; if (view != null) super.addComponent(view); requestLayout(); @@ -128,9 +127,4 @@ class RotatePane extends GLView { public void addComponent(GLView view) { throw new UnsupportedOperationException("use setContent(GLView)"); } - - @Override - public void clearComponents() { - throw new UnsupportedOperationException("use setContent(null)"); - } } diff --git a/src/com/android/camera/ui/ZoomIndicator.java b/src/com/android/camera/ui/ZoomIndicator.java index e74cefd..e2decf1 100644 --- a/src/com/android/camera/ui/ZoomIndicator.java +++ b/src/com/android/camera/ui/ZoomIndicator.java @@ -35,7 +35,7 @@ class ZoomIndicator extends AbstractIndicator { private final float mFontSize; private ZoomController mZoomController; - private LinearLayout mPopupContent; + private GLLinearLayout mPopupContent; private ZoomControllerListener mZoomListener; private int mZoomIndex = 0; private int mDrawIndex = -1; @@ -85,7 +85,7 @@ class ZoomIndicator extends AbstractIndicator { mZoomController.setAvailableZoomRatios(mZoomRatios); mZoomController.setPaddings(15, 6, 15, 6); - mPopupContent = new LinearLayout(); + mPopupContent = new GLLinearLayout(); GLOptionHeader header = new GLOptionHeader(context, context.getString(R.string.zoom_control_title)); header.setBackground(new ColorTexture(COLOR_OPTION_HEADER)); |