diff options
author | Sascha Haeberling <haeberling@google.com> | 2013-08-08 11:27:09 -0700 |
---|---|---|
committer | Sascha Haeberling <haeberling@google.com> | 2013-08-08 18:31:53 -0700 |
commit | 723bf81990245a07739146ac10357703c9839de1 (patch) | |
tree | 0c86a8a133077db5191907a760d5f4b3ab441b77 /src/com/android/camera/ui | |
parent | a6b80cccafe0a4c2de575ec69d1960c3c0d88062 (diff) | |
download | android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.tar.gz android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.tar.bz2 android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.zip |
Remove Camera from Gallery2.
Change-Id: I89adebffcacd1269217d7bd8c630c2f78886f590
Diffstat (limited to 'src/com/android/camera/ui')
38 files changed, 0 insertions, 7601 deletions
diff --git a/src/com/android/camera/ui/AbstractSettingPopup.java b/src/com/android/camera/ui/AbstractSettingPopup.java deleted file mode 100644 index 783b6c771..000000000 --- a/src/com/android/camera/ui/AbstractSettingPopup.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.util.AttributeSet; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.android.gallery3d.R; - -// A popup window that shows one or more camera settings. -abstract public class AbstractSettingPopup extends RotateLayout { - protected ViewGroup mSettingList; - protected TextView mTitle; - - public AbstractSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - mTitle = (TextView) findViewById(R.id.title); - mSettingList = (ViewGroup) findViewById(R.id.settingList); - } - - abstract public void reloadPreference(); -} diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java deleted file mode 100644 index 7fa6890a7..000000000 --- a/src/com/android/camera/ui/CameraControls.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2013 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.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -public class CameraControls extends RotatableLayout { - - private static final String TAG = "CAM_Controls"; - - private View mBackgroundView; - private View mShutter; - private View mSwitcher; - private View mMenu; - private View mIndicators; - private View mPreview; - - public CameraControls(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CameraControls(Context context) { - super(context); - } - - @Override - public void onFinishInflate() { - super.onFinishInflate(); - mBackgroundView = findViewById(R.id.blocker); - mSwitcher = findViewById(R.id.camera_switcher); - mShutter = findViewById(R.id.shutter_button); - mMenu = findViewById(R.id.menu); - mIndicators = findViewById(R.id.on_screen_indicators); - mPreview = findViewById(R.id.preview_thumb); - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - int orientation = getResources().getConfiguration().orientation; - int size = getResources().getDimensionPixelSize(R.dimen.camera_controls_size); - int rotation = getUnifiedRotation(); - adjustBackground(); - // As l,t,r,b are positions relative to parents, we need to convert them - // to child's coordinates - r = r - l; - b = b - t; - l = 0; - t = 0; - for (int i = 0; i < getChildCount(); i++) { - View v = getChildAt(i); - v.layout(l, t, r, b); - } - Rect shutter = new Rect(); - topRight(mPreview, l, t, r, b); - if (size > 0) { - // restrict controls to size - switch (rotation) { - case 0: - case 180: - l = (l + r - size) / 2; - r = l + size; - break; - case 90: - case 270: - t = (t + b - size) / 2; - b = t + size; - break; - } - } - center(mShutter, l, t, r, b, orientation, rotation, shutter); - center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect()); - toLeft(mSwitcher, shutter, rotation); - toRight(mMenu, shutter, rotation); - toRight(mIndicators, shutter, rotation); - View retake = findViewById(R.id.btn_retake); - if (retake != null) { - center(retake, shutter, rotation); - View cancel = findViewById(R.id.btn_cancel); - toLeft(cancel, shutter, rotation); - View done = findViewById(R.id.btn_done); - toRight(done, shutter, rotation); - } - } - - private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - switch (rotation) { - case 0: - // phone portrait; controls bottom - result.left = (r + l) / 2 - tw / 2 + lp.leftMargin; - result.right = (r + l) / 2 + tw / 2 - lp.rightMargin; - result.bottom = b - lp.bottomMargin; - result.top = b - th + lp.topMargin; - break; - case 90: - // phone landscape: controls right - result.right = r - lp.rightMargin; - result.left = r - tw + lp.leftMargin; - result.top = (b + t) / 2 - th / 2 + lp.topMargin; - result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin; - break; - case 180: - // phone upside down: controls top - result.left = (r + l) / 2 - tw / 2 + lp.leftMargin; - result.right = (r + l) / 2 + tw / 2 - lp.rightMargin; - result.top = t + lp.topMargin; - result.bottom = t + th - lp.bottomMargin; - break; - case 270: - // reverse landscape: controls left - result.left = l + lp.leftMargin; - result.right = l + tw - lp.rightMargin; - result.top = (b + t) / 2 - th / 2 + lp.topMargin; - result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin; - break; - } - v.layout(result.left, result.top, result.right, result.bottom); - } - - private void center(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - v.layout(cx - tw / 2 + lp.leftMargin, - cy - th / 2 + lp.topMargin, - cx + tw / 2 - lp.rightMargin, - cy + th / 2 - lp.bottomMargin); - } - - private void toLeft(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - int l = 0, r = 0, t = 0, b = 0; - switch (rotation) { - case 0: - // portrait, to left of anchor at bottom - l = other.left - tw + lp.leftMargin; - r = other.left - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 90: - // phone landscape: below anchor on right - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.bottom + lp.topMargin; - b = other.bottom + th - lp.bottomMargin; - break; - case 180: - // phone upside down: right of anchor at top - l = other.right + lp.leftMargin; - r = other.right + tw - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 270: - // reverse landscape: above anchor on left - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.top - th + lp.topMargin; - b = other.top - lp.bottomMargin; - break; - } - v.layout(l, t, r, b); - } - - private void toRight(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - int l = 0, r = 0, t = 0, b = 0; - switch (rotation) { - case 0: - l = other.right + lp.leftMargin; - r = other.right + tw - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 90: - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.top - th + lp.topMargin; - b = other.top - lp.bottomMargin; - break; - case 180: - l = other.left - tw + lp.leftMargin; - r = other.left - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 270: - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.bottom + lp.topMargin; - b = other.bottom + th - lp.bottomMargin; - break; - } - v.layout(l, t, r, b); - } - - private void topRight(View v, int l, int t, int r, int b) { - // layout using the specific margins; the rotation code messes up the others - int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top); - int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right); - v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight()); - } - - private void adjustBackground() { - int rotation = getUnifiedRotation(); - // remove current drawable and reset rotation - mBackgroundView.setBackgroundDrawable(null); - mBackgroundView.setRotationX(0); - mBackgroundView.setRotationY(0); - // if the switcher background is top aligned we need to flip the background - // drawable vertically; if left aligned, flip horizontally - switch (rotation) { - case 180: - mBackgroundView.setRotationX(180); - break; - case 270: - mBackgroundView.setRotationY(180); - break; - default: - break; - } - mBackgroundView.setBackgroundResource(R.drawable.switcher_bg); - } - -} diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java deleted file mode 100644 index adda70697..000000000 --- a/src/com/android/camera/ui/CameraRootView.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2013 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.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.hardware.display.DisplayManager; -import android.hardware.display.DisplayManager.DisplayListener; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.Util; -import com.android.gallery3d.common.ApiHelper; - -public class CameraRootView extends FrameLayout { - - private int mTopMargin = 0; - private int mBottomMargin = 0; - private int mLeftMargin = 0; - private int mRightMargin = 0; - private Rect mCurrentInsets; - private int mOffset = 0; - private Object mDisplayListener; - private MyDisplayListener mListener; - public interface MyDisplayListener { - public void onDisplayChanged(); - } - - public CameraRootView(Context context, AttributeSet attrs) { - super(context, attrs); - initDisplayListener(); - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - - @Override - protected boolean fitSystemWindows(Rect insets) { - super.fitSystemWindows(insets); - mCurrentInsets = insets; - // insets include status bar, navigation bar, etc - // In this case, we are only concerned with the size of nav bar - if (mOffset > 0) return true; - - if (insets.bottom > 0) { - mOffset = insets.bottom; - } else if (insets.right > 0) { - mOffset = insets.right; - } - return true; - } - - public void initDisplayListener() { - if (ApiHelper.HAS_DISPLAY_LISTENER) { - mDisplayListener = new DisplayListener() { - - @Override - public void onDisplayAdded(int arg0) {} - - @Override - public void onDisplayChanged(int arg0) { - mListener.onDisplayChanged(); - } - - @Override - public void onDisplayRemoved(int arg0) {} - }; - } - } - - public void setDisplayChangeListener(MyDisplayListener listener) { - mListener = listener; - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - if (ApiHelper.HAS_DISPLAY_LISTENER) { - ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE)) - .registerDisplayListener((DisplayListener) mDisplayListener, null); - } - } - - @Override - public void onDetachedFromWindow () { - super.onDetachedFromWindow(); - if (ApiHelper.HAS_DISPLAY_LISTENER) { - ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE)) - .unregisterDisplayListener((DisplayListener) mDisplayListener); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int rotation = Util.getDisplayRotation((Activity) getContext()); - // all the layout code assumes camera device orientation to be portrait - // adjust rotation for landscape - int orientation = getResources().getConfiguration().orientation; - int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT - : Configuration.ORIENTATION_LANDSCAPE; - if (camOrientation != orientation) { - rotation = (rotation + 90) % 360; - } - // calculate margins - mLeftMargin = 0; - mRightMargin = 0; - mBottomMargin = 0; - mTopMargin = 0; - switch (rotation) { - case 0: - mBottomMargin += mOffset; - break; - case 90: - mRightMargin += mOffset; - break; - case 180: - mTopMargin += mOffset; - break; - case 270: - mLeftMargin += mOffset; - break; - } - if (mCurrentInsets != null) { - if (mCurrentInsets.right > 0) { - // navigation bar on the right - mRightMargin = mRightMargin > 0 ? mRightMargin : mCurrentInsets.right; - } else { - // navigation bar on the bottom - mBottomMargin = mBottomMargin > 0 ? mBottomMargin : mCurrentInsets.bottom; - } - } - // make sure all the children are resized - super.onMeasure(widthMeasureSpec - mLeftMargin - mRightMargin, - heightMeasureSpec - mTopMargin - mBottomMargin); - setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - r -= l; - b -= t; - l = 0; - t = 0; - int orientation = getResources().getConfiguration().orientation; - // Lay out children - for (int i = 0; i < getChildCount(); i++) { - View v = getChildAt(i); - if (v instanceof CameraControls) { - // Lay out camera controls to center on the short side of the screen - // so that they stay in place during rotation - int width = v.getMeasuredWidth(); - int height = v.getMeasuredHeight(); - if (orientation == Configuration.ORIENTATION_PORTRAIT) { - int left = (l + r - width) / 2; - v.layout(left, t + mTopMargin, left + width, b - mBottomMargin); - } else { - int top = (t + b - height) / 2; - v.layout(l + mLeftMargin, top, r - mRightMargin, top + height); - } - } else { - v.layout(l + mLeftMargin, t + mTopMargin, r - mRightMargin, b - mBottomMargin); - } - } - } -} diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java deleted file mode 100644 index 6e4321571..000000000 --- a/src/com/android/camera/ui/CameraSwitcher.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2012 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.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.AnimatorListenerAdapter; -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnTouchListener; -import android.view.ViewGroup; -import android.widget.FrameLayout.LayoutParams; -import android.widget.LinearLayout; - -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.UsageStatistics; - -public class CameraSwitcher extends RotateImageView - implements OnClickListener, OnTouchListener { - - private static final String TAG = "CAM_Switcher"; - private static final int SWITCHER_POPUP_ANIM_DURATION = 200; - - public static final int PHOTO_MODULE_INDEX = 0; - public static final int VIDEO_MODULE_INDEX = 1; - public static final int LIGHTCYCLE_MODULE_INDEX = 2; - public static final int REFOCUS_MODULE_INDEX = 3; - private static final int[] DRAW_IDS = { - R.drawable.ic_switch_camera, - R.drawable.ic_switch_video, - R.drawable.ic_switch_photosphere, - R.drawable.ic_switch_refocus - }; - public interface CameraSwitchListener { - public void onCameraSelected(int i); - public void onShowSwitcherPopup(); - } - - private CameraSwitchListener mListener; - private int mCurrentIndex; - private int[] mModuleIds; - private int[] mDrawIds; - private int mItemSize; - private View mPopup; - private View mParent; - private boolean mShowingPopup; - private boolean mNeedsAnimationSetup; - private Drawable mIndicator; - - private float mTranslationX = 0; - private float mTranslationY = 0; - - private AnimatorListener mHideAnimationListener; - private AnimatorListener mShowAnimationListener; - - public CameraSwitcher(Context context) { - super(context); - init(context); - } - - public CameraSwitcher(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - private void init(Context context) { - mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size); - setOnClickListener(this); - mIndicator = context.getResources().getDrawable(R.drawable.ic_switcher_menu_indicator); - initializeDrawables(context); - } - - public void initializeDrawables(Context context) { - int totaldrawid = (LightCycleHelper.hasLightCycleCapture(context) - ? DRAW_IDS.length : DRAW_IDS.length - 1); - - int[] drawids = new int[totaldrawid]; - int[] moduleids = new int[totaldrawid]; - int ix = 0; - for (int i = 0; i < DRAW_IDS.length; i++) { - if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(context)) { - continue; // not enabled, so don't add to UI - } - moduleids[ix] = i; - drawids[ix++] = DRAW_IDS[i]; - } - setIds(moduleids, drawids); - } - - public void setIds(int[] moduleids, int[] drawids) { - mDrawIds = drawids; - mModuleIds = moduleids; - } - - public void setCurrentIndex(int i) { - mCurrentIndex = i; - setImageResource(mDrawIds[i]); - } - - public void setSwitchListener(CameraSwitchListener l) { - mListener = l; - } - - @Override - public void onClick(View v) { - showSwitcher(); - mListener.onShowSwitcherPopup(); - } - - private void onCameraSelected(int ix) { - hidePopup(); - if ((ix != mCurrentIndex) && (mListener != null)) { - UsageStatistics.onEvent("CameraModeSwitch", null, null); - UsageStatistics.setPendingTransitionCause( - UsageStatistics.TRANSITION_MENU_TAP); - setCurrentIndex(ix); - mListener.onCameraSelected(mModuleIds[ix]); - } - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - mIndicator.setBounds(getDrawable().getBounds()); - mIndicator.draw(canvas); - } - - private void initPopup() { - mParent = LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup, - (ViewGroup) getParent()); - LinearLayout content = (LinearLayout) mParent.findViewById(R.id.content); - mPopup = content; - // Set the gravity of the popup, so that it shows up at the right position - // on screen - LayoutParams lp = ((LayoutParams) mPopup.getLayoutParams()); - lp.gravity = ((LayoutParams) mParent.findViewById(R.id.camera_switcher) - .getLayoutParams()).gravity; - mPopup.setLayoutParams(lp); - - mPopup.setVisibility(View.INVISIBLE); - mNeedsAnimationSetup = true; - for (int i = mDrawIds.length - 1; i >= 0; i--) { - RotateImageView item = new RotateImageView(getContext()); - item.setImageResource(mDrawIds[i]); - item.setBackgroundResource(R.drawable.bg_pressed); - final int index = i; - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (showsPopup()) onCameraSelected(index); - } - }); - switch (mDrawIds[i]) { - case R.drawable.ic_switch_camera: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_camera)); - break; - case R.drawable.ic_switch_video: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_video)); - break; - case R.drawable.ic_switch_photosphere: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_new_panorama)); - break; - case R.drawable.ic_switch_refocus: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_refocus)); - break; - default: - break; - } - content.addView(item, new LinearLayout.LayoutParams(mItemSize, mItemSize)); - } - mPopup.measure(MeasureSpec.makeMeasureSpec(mParent.getWidth(), MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(mParent.getHeight(), MeasureSpec.AT_MOST)); - } - - public boolean showsPopup() { - return mShowingPopup; - } - - public boolean isInsidePopup(MotionEvent evt) { - if (!showsPopup()) return false; - int topLeft[] = new int[2]; - mPopup.getLocationOnScreen(topLeft); - int left = topLeft[0]; - int top = topLeft[1]; - int bottom = top + mPopup.getHeight(); - int right = left + mPopup.getWidth(); - return evt.getX() >= left && evt.getX() < right - && evt.getY() >= top && evt.getY() < bottom; - } - - private void hidePopup() { - mShowingPopup = false; - setVisibility(View.VISIBLE); - if (mPopup != null && !animateHidePopup()) { - mPopup.setVisibility(View.INVISIBLE); - } - mParent.setOnTouchListener(null); - } - - @Override - public void onConfigurationChanged(Configuration config) { - if (showsPopup()) { - ((ViewGroup) mParent).removeView(mPopup); - mPopup = null; - initPopup(); - mPopup.setVisibility(View.VISIBLE); - } - } - - private void showSwitcher() { - mShowingPopup = true; - if (mPopup == null) { - initPopup(); - } - layoutPopup(); - mPopup.setVisibility(View.VISIBLE); - if (!animateShowPopup()) { - setVisibility(View.INVISIBLE); - } - mParent.setOnTouchListener(this); - } - - @Override - public boolean onTouch(View v, MotionEvent event) { - closePopup(); - return true; - } - - public void closePopup() { - if (showsPopup()) { - hidePopup(); - } - } - - @Override - public void setOrientation(int degree, boolean animate) { - super.setOrientation(degree, animate); - ViewGroup content = (ViewGroup) mPopup; - if (content == null) return; - for (int i = 0; i < content.getChildCount(); i++) { - RotateImageView iv = (RotateImageView) content.getChildAt(i); - iv.setOrientation(degree, animate); - } - } - - private void layoutPopup() { - int orientation = Util.getDisplayRotation((Activity) getContext()); - int w = mPopup.getMeasuredWidth(); - int h = mPopup.getMeasuredHeight(); - if (orientation == 0) { - mPopup.layout(getRight() - w, getBottom() - h, getRight(), getBottom()); - mTranslationX = 0; - mTranslationY = h / 3; - } else if (orientation == 90) { - mTranslationX = w / 3; - mTranslationY = - h / 3; - mPopup.layout(getRight() - w, getTop(), getRight(), getTop() + h); - } else if (orientation == 180) { - mTranslationX = - w / 3; - mTranslationY = - h / 3; - mPopup.layout(getLeft(), getTop(), getLeft() + w, getTop() + h); - } else { - mTranslationX = - w / 3; - mTranslationY = h - getHeight(); - mPopup.layout(getLeft(), getBottom() - h, getLeft() + w, getBottom()); - } - } - - @Override - public void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (mPopup != null) { - layoutPopup(); - } - } - - private void popupAnimationSetup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return; - } - layoutPopup(); - mPopup.setScaleX(0.3f); - mPopup.setScaleY(0.3f); - mPopup.setTranslationX(mTranslationX); - mPopup.setTranslationY(mTranslationY); - mNeedsAnimationSetup = false; - } - - private boolean animateHidePopup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return false; - } - if (mHideAnimationListener == null) { - mHideAnimationListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // Verify that we weren't canceled - if (!showsPopup() && mPopup != null) { - mPopup.setVisibility(View.INVISIBLE); - ((ViewGroup) mParent).removeView(mPopup); - mPopup = null; - } - } - }; - } - mPopup.animate() - .alpha(0f) - .scaleX(0.3f).scaleY(0.3f) - .translationX(mTranslationX) - .translationY(mTranslationY) - .setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(mHideAnimationListener); - animate().alpha(1f).setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(null); - return true; - } - - private boolean animateShowPopup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return false; - } - if (mNeedsAnimationSetup) { - popupAnimationSetup(); - } - if (mShowAnimationListener == null) { - mShowAnimationListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // Verify that we weren't canceled - if (showsPopup()) { - setVisibility(View.INVISIBLE); - // request layout to make sure popup is laid out correctly on ICS - mPopup.requestLayout(); - } - } - }; - } - mPopup.animate() - .alpha(1f) - .scaleX(1f).scaleY(1f) - .translationX(0) - .translationY(0) - .setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(null); - animate().alpha(0f).setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(mShowAnimationListener); - return true; - } -} diff --git a/src/com/android/camera/ui/CheckedLinearLayout.java b/src/com/android/camera/ui/CheckedLinearLayout.java deleted file mode 100644 index 4e7750499..000000000 --- a/src/com/android/camera/ui/CheckedLinearLayout.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012 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.util.AttributeSet; -import android.widget.Checkable; -import android.widget.LinearLayout; - -public class CheckedLinearLayout extends LinearLayout implements Checkable { - private static final int[] CHECKED_STATE_SET = { - android.R.attr.state_checked - }; - private boolean mChecked; - - public CheckedLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean isChecked() { - return mChecked; - } - - @Override - public void setChecked(boolean checked) { - if (mChecked != checked) { - mChecked = checked; - refreshDrawableState(); - } - } - - @Override - public void toggle() { - setChecked(!mChecked); - } - - @Override - public int[] onCreateDrawableState(int extraSpace) { - final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); - if (mChecked) { - mergeDrawableStates(drawableState, CHECKED_STATE_SET); - } - return drawableState; - } -} diff --git a/src/com/android/camera/ui/CountDownView.java b/src/com/android/camera/ui/CountDownView.java deleted file mode 100644 index 907d33508..000000000 --- a/src/com/android/camera/ui/CountDownView.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2012 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 java.util.Locale; - -import android.content.Context; -import android.media.AudioManager; -import android.media.SoundPool; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.FrameLayout; -import android.widget.TextView; - -import com.android.gallery3d.R; - -public class CountDownView extends FrameLayout { - - private static final String TAG = "CAM_CountDownView"; - private static final int SET_TIMER_TEXT = 1; - private TextView mRemainingSecondsView; - private int mRemainingSecs = 0; - private OnCountDownFinishedListener mListener; - private Animation mCountDownAnim; - private SoundPool mSoundPool; - private int mBeepTwice; - private int mBeepOnce; - private boolean mPlaySound; - private final Handler mHandler = new MainHandler(); - - public CountDownView(Context context, AttributeSet attrs) { - super(context, attrs); - mCountDownAnim = AnimationUtils.loadAnimation(context, R.anim.count_down_exit); - // Load the beeps - mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); - mBeepOnce = mSoundPool.load(context, R.raw.beep_once, 1); - mBeepTwice = mSoundPool.load(context, R.raw.beep_twice, 1); - } - - public boolean isCountingDown() { - return mRemainingSecs > 0; - }; - - public interface OnCountDownFinishedListener { - public void onCountDownFinished(); - } - - private void remainingSecondsChanged(int newVal) { - mRemainingSecs = newVal; - if (newVal == 0) { - // Countdown has finished - setVisibility(View.INVISIBLE); - mListener.onCountDownFinished(); - } else { - Locale locale = getResources().getConfiguration().locale; - String localizedValue = String.format(locale, "%d", newVal); - mRemainingSecondsView.setText(localizedValue); - // Fade-out animation - mCountDownAnim.reset(); - mRemainingSecondsView.clearAnimation(); - mRemainingSecondsView.startAnimation(mCountDownAnim); - - // Play sound effect for the last 3 seconds of the countdown - if (mPlaySound) { - if (newVal == 1) { - mSoundPool.play(mBeepTwice, 1.0f, 1.0f, 0, 0, 1.0f); - } else if (newVal <= 3) { - mSoundPool.play(mBeepOnce, 1.0f, 1.0f, 0, 0, 1.0f); - } - } - // Schedule the next remainingSecondsChanged() call in 1 second - mHandler.sendEmptyMessageDelayed(SET_TIMER_TEXT, 1000); - } - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mRemainingSecondsView = (TextView) findViewById(R.id.remaining_seconds); - } - - public void setCountDownFinishedListener(OnCountDownFinishedListener listener) { - mListener = listener; - } - - public void startCountDown(int sec, boolean playSound) { - if (sec <= 0) { - Log.w(TAG, "Invalid input for countdown timer: " + sec + " seconds"); - return; - } - setVisibility(View.VISIBLE); - mPlaySound = playSound; - remainingSecondsChanged(sec); - } - - public void cancelCountDown() { - if (mRemainingSecs > 0) { - mRemainingSecs = 0; - mHandler.removeMessages(SET_TIMER_TEXT); - setVisibility(View.INVISIBLE); - } - } - - private class MainHandler extends Handler { - @Override - public void handleMessage(Message message) { - if (message.what == SET_TIMER_TEXT) { - remainingSecondsChanged(mRemainingSecs -1); - } - } - } -}
\ No newline at end of file diff --git a/src/com/android/camera/ui/CountdownTimerPopup.java b/src/com/android/camera/ui/CountdownTimerPopup.java deleted file mode 100644 index 7c3572b55..000000000 --- a/src/com/android/camera/ui/CountdownTimerPopup.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2012 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.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.NumberPicker; -import android.widget.NumberPicker.OnValueChangeListener; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.Locale; - -/** - * This is a popup window that allows users to specify a countdown timer - */ - -public class CountdownTimerPopup extends AbstractSettingPopup { - private static final String TAG = "TimerSettingPopup"; - private NumberPicker mNumberSpinner; - private String[] mDurations; - private ListPreference mTimer; - private ListPreference mBeep; - private Listener mListener; - private Button mConfirmButton; - private View mPickerTitle; - private CheckBox mTimerSound; - private View mSoundTitle; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public CountdownTimerPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void initialize(ListPreference timer, ListPreference beep) { - mTimer = timer; - mBeep = beep; - // Set title. - mTitle.setText(mTimer.getTitle()); - - // Duration - CharSequence[] entries = mTimer.getEntryValues(); - mDurations = new String[entries.length]; - Locale locale = getResources().getConfiguration().locale; - mDurations[0] = getResources().getString(R.string.setting_off); // Off - for (int i = 1; i < entries.length; i++) - mDurations[i] = String.format(locale, "%d", Integer.parseInt(entries[i].toString())); - int durationCount = mDurations.length; - mNumberSpinner = (NumberPicker) findViewById(R.id.duration); - mNumberSpinner.setMinValue(0); - mNumberSpinner.setMaxValue(durationCount - 1); - mNumberSpinner.setDisplayedValues(mDurations); - mNumberSpinner.setWrapSelectorWheel(false); - mNumberSpinner.setOnValueChangedListener(new OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldValue, int newValue) { - setTimeSelectionEnabled(newValue != 0); - } - }); - mConfirmButton = (Button) findViewById(R.id.timer_set_button); - mPickerTitle = findViewById(R.id.set_time_interval_title); - - // Disable focus on the spinners to prevent keyboard from coming up - mNumberSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - - mConfirmButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - updateInputState(); - } - }); - mTimerSound = (CheckBox) findViewById(R.id.sound_check_box); - mSoundTitle = findViewById(R.id.beep_title); - } - - private void restoreSetting() { - int index = mTimer.findIndexOfValue(mTimer.getValue()); - if (index == -1) { - Log.e(TAG, "Invalid preference value."); - mTimer.print(); - throw new IllegalArgumentException(); - } else { - setTimeSelectionEnabled(index != 0); - mNumberSpinner.setValue(index); - } - boolean checked = mBeep.findIndexOfValue(mBeep.getValue()) != 0; - mTimerSound.setChecked(checked); - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Set the number pickers and on/off switch to be consistent - // with the preference - restoreSetting(); - } - } - super.setVisibility(visibility); - } - - protected void setTimeSelectionEnabled(boolean enabled) { - mPickerTitle.setVisibility(enabled ? VISIBLE : INVISIBLE); - mTimerSound.setEnabled(enabled); - mSoundTitle.setEnabled(enabled); - } - - @Override - public void reloadPreference() { - } - - private void updateInputState() { - mTimer.setValueIndex(mNumberSpinner.getValue()); - mBeep.setValueIndex(mTimerSound.isChecked() ? 1 : 0); - if (mListener != null) { - mListener.onListPrefChanged(mTimer); - mListener.onListPrefChanged(mBeep); - } - } -} diff --git a/src/com/android/camera/ui/EffectSettingPopup.java b/src/com/android/camera/ui/EffectSettingPopup.java deleted file mode 100644 index 568781a01..000000000 --- a/src/com/android/camera/ui/EffectSettingPopup.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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.annotation.TargetApi; -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.AdapterView; -import android.widget.GridView; -import android.widget.SimpleAdapter; - -import com.android.camera.IconListPreference; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.HashMap; - -// A popup window that shows video effect setting. It has two grid view. -// One shows the goofy face effects. The other shows the background replacer -// effects. -public class EffectSettingPopup extends AbstractSettingPopup implements - AdapterView.OnItemClickListener, View.OnClickListener { - private static final String TAG = "EffectSettingPopup"; - private String mNoEffect; - private IconListPreference mPreference; - private Listener mListener; - private View mClearEffects; - private GridView mSillyFacesGrid; - private GridView mBackgroundGrid; - - // Data for silly face items. (text, image, and preference value) - ArrayList<HashMap<String, Object>> mSillyFacesItem = - new ArrayList<HashMap<String, Object>>(); - - // Data for background replacer items. (text, image, and preference value) - ArrayList<HashMap<String, Object>> mBackgroundItem = - new ArrayList<HashMap<String, Object>>(); - - - static public interface Listener { - public void onSettingChanged(); - } - - public EffectSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - mNoEffect = context.getString(R.string.pref_video_effect_default); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mClearEffects = findViewById(R.id.clear_effects); - mClearEffects.setOnClickListener(this); - mSillyFacesGrid = (GridView) findViewById(R.id.effect_silly_faces); - mBackgroundGrid = (GridView) findViewById(R.id.effect_background); - } - - public void initialize(IconListPreference preference) { - mPreference = preference; - Context context = getContext(); - CharSequence[] entries = mPreference.getEntries(); - CharSequence[] entryValues = mPreference.getEntryValues(); - int[] iconIds = mPreference.getImageIds(); - if (iconIds == null) { - iconIds = mPreference.getLargeIconIds(); - } - - // Set title. - mTitle.setText(mPreference.getTitle()); - - for(int i = 0; i < entries.length; ++i) { - String value = entryValues[i].toString(); - if (value.equals(mNoEffect)) continue; // no effect, skip it. - HashMap<String, Object> map = new HashMap<String, Object>(); - map.put("value", value); - map.put("text", entries[i].toString()); - if (iconIds != null) map.put("image", iconIds[i]); - if (value.startsWith("goofy_face")) { - mSillyFacesItem.add(map); - } else if (value.startsWith("backdropper")) { - mBackgroundItem.add(map); - } - } - - boolean hasSillyFaces = mSillyFacesItem.size() > 0; - boolean hasBackground = mBackgroundItem.size() > 0; - - // Initialize goofy face if it is supported. - if (hasSillyFaces) { - findViewById(R.id.effect_silly_faces_title).setVisibility(View.VISIBLE); - findViewById(R.id.effect_silly_faces_title_separator).setVisibility(View.VISIBLE); - mSillyFacesGrid.setVisibility(View.VISIBLE); - SimpleAdapter sillyFacesItemAdapter = new SimpleAdapter(context, - mSillyFacesItem, R.layout.effect_setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - mSillyFacesGrid.setAdapter(sillyFacesItemAdapter); - mSillyFacesGrid.setOnItemClickListener(this); - } - - if (hasSillyFaces && hasBackground) { - findViewById(R.id.effect_background_separator).setVisibility(View.VISIBLE); - } - - // Initialize background replacer if it is supported. - if (hasBackground) { - findViewById(R.id.effect_background_title).setVisibility(View.VISIBLE); - findViewById(R.id.effect_background_title_separator).setVisibility(View.VISIBLE); - mBackgroundGrid.setVisibility(View.VISIBLE); - SimpleAdapter backgroundItemAdapter = new SimpleAdapter(context, - mBackgroundItem, R.layout.effect_setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - mBackgroundGrid.setAdapter(backgroundItemAdapter); - mBackgroundGrid.setOnItemClickListener(this); - } - - reloadPreference(); - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Do not show or hide "Clear effects" button when the popup - // is already visible. Otherwise it looks strange. - boolean noEffect = mPreference.getValue().equals(mNoEffect); - mClearEffects.setVisibility(noEffect ? View.GONE : View.VISIBLE); - } - reloadPreference(); - } - super.setVisibility(visibility); - } - - // The value of the preference may have changed. Update the UI. - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public void reloadPreference() { - mBackgroundGrid.setItemChecked(mBackgroundGrid.getCheckedItemPosition(), false); - mSillyFacesGrid.setItemChecked(mSillyFacesGrid.getCheckedItemPosition(), false); - - String value = mPreference.getValue(); - if (value.equals(mNoEffect)) return; - - for (int i = 0; i < mSillyFacesItem.size(); i++) { - if (value.equals(mSillyFacesItem.get(i).get("value"))) { - mSillyFacesGrid.setItemChecked(i, true); - return; - } - } - - for (int i = 0; i < mBackgroundItem.size(); i++) { - if (value.equals(mBackgroundItem.get(i).get("value"))) { - mBackgroundGrid.setItemChecked(i, true); - return; - } - } - - Log.e(TAG, "Invalid preference value: " + value); - mPreference.print(); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, - int index, long id) { - String value; - if (parent == mSillyFacesGrid) { - value = (String) mSillyFacesItem.get(index).get("value"); - } else if (parent == mBackgroundGrid) { - value = (String) mBackgroundItem.get(index).get("value"); - } else { - return; - } - - // Tapping the selected effect will deselect it (clear effects). - if (value.equals(mPreference.getValue())) { - mPreference.setValue(mNoEffect); - } else { - mPreference.setValue(value); - } - reloadPreference(); - if (mListener != null) mListener.onSettingChanged(); - } - - @Override - public void onClick(View v) { - // Clear the effect. - mPreference.setValue(mNoEffect); - reloadPreference(); - if (mListener != null) mListener.onSettingChanged(); - } -} diff --git a/src/com/android/camera/ui/ExpandedGridView.java b/src/com/android/camera/ui/ExpandedGridView.java deleted file mode 100644 index 13cf58f34..000000000 --- a/src/com/android/camera/ui/ExpandedGridView.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 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.util.AttributeSet; -import android.widget.GridView; - -public class ExpandedGridView extends GridView { - public ExpandedGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // If UNSPECIFIED is passed to GridView, it will show only one row. - // Here GridView is put in a ScrollView, so pass it a very big size with - // AT_MOST to show all the rows. - heightMeasureSpec = MeasureSpec.makeMeasureSpec(65536, MeasureSpec.AT_MOST); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } -} diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java deleted file mode 100644 index 7d66dc079..000000000 --- a/src/com/android/camera/ui/FaceView.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2011 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.annotation.TargetApi; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.RectF; -import android.hardware.Camera.Face; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; - -import com.android.camera.PhotoUI; -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -@TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) -public class FaceView extends View - implements FocusIndicator, Rotatable, - PhotoUI.SurfaceTextureSizeChangedListener { - private static final String TAG = "CAM FaceView"; - private final boolean LOGV = false; - // The value for android.hardware.Camera.setDisplayOrientation. - private int mDisplayOrientation; - // The orientation compensation for the face indicator to make it look - // correctly in all device orientations. Ex: if the value is 90, the - // indicator should be rotated 90 degrees counter-clockwise. - private int mOrientation; - private boolean mMirror; - private boolean mPause; - private Matrix mMatrix = new Matrix(); - private RectF mRect = new RectF(); - // As face detection can be flaky, we add a layer of filtering on top of it - // to avoid rapid changes in state (eg, flickering between has faces and - // not having faces) - private Face[] mFaces; - private Face[] mPendingFaces; - private int mColor; - private final int mFocusingColor; - private final int mFocusedColor; - private final int mFailColor; - private Paint mPaint; - private volatile boolean mBlocked; - - private int mUncroppedWidth; - private int mUncroppedHeight; - private static final int MSG_SWITCH_FACES = 1; - private static final int SWITCH_DELAY = 70; - private boolean mStateSwitchPending = false; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_SWITCH_FACES: - mStateSwitchPending = false; - mFaces = mPendingFaces; - invalidate(); - break; - } - } - }; - - public FaceView(Context context, AttributeSet attrs) { - super(context, attrs); - Resources res = getResources(); - mFocusingColor = res.getColor(R.color.face_detect_start); - mFocusedColor = res.getColor(R.color.face_detect_success); - mFailColor = res.getColor(R.color.face_detect_fail); - mColor = mFocusingColor; - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setStyle(Style.STROKE); - mPaint.setStrokeWidth(res.getDimension(R.dimen.face_circle_stroke)); - } - - @Override - public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight) { - mUncroppedWidth = uncroppedWidth; - mUncroppedHeight = uncroppedHeight; - } - - public void setFaces(Face[] faces) { - if (LOGV) Log.v(TAG, "Num of faces=" + faces.length); - if (mPause) return; - if (mFaces != null) { - if ((faces.length > 0 && mFaces.length == 0) - || (faces.length == 0 && mFaces.length > 0)) { - mPendingFaces = faces; - if (!mStateSwitchPending) { - mStateSwitchPending = true; - mHandler.sendEmptyMessageDelayed(MSG_SWITCH_FACES, SWITCH_DELAY); - } - return; - } - } - if (mStateSwitchPending) { - mStateSwitchPending = false; - mHandler.removeMessages(MSG_SWITCH_FACES); - } - mFaces = faces; - invalidate(); - } - - public void setDisplayOrientation(int orientation) { - mDisplayOrientation = orientation; - if (LOGV) Log.v(TAG, "mDisplayOrientation=" + orientation); - } - - @Override - public void setOrientation(int orientation, boolean animation) { - mOrientation = orientation; - invalidate(); - } - - public void setMirror(boolean mirror) { - mMirror = mirror; - if (LOGV) Log.v(TAG, "mMirror=" + mirror); - } - - public boolean faceExists() { - return (mFaces != null && mFaces.length > 0); - } - - @Override - public void showStart() { - mColor = mFocusingColor; - invalidate(); - } - - // Ignore the parameter. No autofocus animation for face detection. - @Override - public void showSuccess(boolean timeout) { - mColor = mFocusedColor; - invalidate(); - } - - // Ignore the parameter. No autofocus animation for face detection. - @Override - public void showFail(boolean timeout) { - mColor = mFailColor; - invalidate(); - } - - @Override - public void clear() { - // Face indicator is displayed during preview. Do not clear the - // drawable. - mColor = mFocusingColor; - mFaces = null; - invalidate(); - } - - public void pause() { - mPause = true; - } - - public void resume() { - mPause = false; - } - - public void setBlockDraw(boolean block) { - mBlocked = block; - } - - @Override - protected void onDraw(Canvas canvas) { - if (!mBlocked && (mFaces != null) && (mFaces.length > 0)) { - int rw, rh; - rw = mUncroppedWidth; - rh = mUncroppedHeight; - // Prepare the matrix. - if (((rh > rw) && ((mDisplayOrientation == 0) || (mDisplayOrientation == 180))) - || ((rw > rh) && ((mDisplayOrientation == 90) || (mDisplayOrientation == 270)))) { - int temp = rw; - rw = rh; - rh = temp; - } - Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, rw, rh); - int dx = (getWidth() - rw) / 2; - int dy = (getHeight() - rh) / 2; - - // Focus indicator is directional. Rotate the matrix and the canvas - // so it looks correctly in all orientations. - canvas.save(); - mMatrix.postRotate(mOrientation); // postRotate is clockwise - canvas.rotate(-mOrientation); // rotate is counter-clockwise (for canvas) - for (int i = 0; i < mFaces.length; i++) { - // Filter out false positives. - if (mFaces[i].score < 50) continue; - - // Transform the coordinates. - mRect.set(mFaces[i].rect); - if (LOGV) Util.dumpRect(mRect, "Original rect"); - mMatrix.mapRect(mRect); - if (LOGV) Util.dumpRect(mRect, "Transformed rect"); - mPaint.setColor(mColor); - mRect.offset(dx, dy); - canvas.drawOval(mRect, mPaint); - } - canvas.restore(); - } - super.onDraw(canvas); - } -} diff --git a/src/com/android/camera/ui/FilmStripGestureRecognizer.java b/src/com/android/camera/ui/FilmStripGestureRecognizer.java deleted file mode 100644 index f870b5829..000000000 --- a/src/com/android/camera/ui/FilmStripGestureRecognizer.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 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.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; - -// This class aggregates three gesture detectors: GestureDetector, -// ScaleGestureDetector. -public class FilmStripGestureRecognizer { - @SuppressWarnings("unused") - private static final String TAG = "FilmStripGestureRecognizer"; - - public interface Listener { - boolean onSingleTapUp(float x, float y); - boolean onDoubleTap(float x, float y); - boolean onScroll(float x, float y, float dx, float dy); - boolean onFling(float velocityX, float velocityY); - boolean onScaleBegin(float focusX, float focusY); - boolean onScale(float focusX, float focusY, float scale); - boolean onDown(float x, float y); - boolean onUp(float x, float y); - void onScaleEnd(); - } - - private final GestureDetector mGestureDetector; - private final ScaleGestureDetector mScaleDetector; - private final Listener mListener; - - public FilmStripGestureRecognizer(Context context, Listener listener) { - mListener = listener; - mGestureDetector = new GestureDetector(context, new MyGestureListener(), - null, true /* ignoreMultitouch */); - mScaleDetector = new ScaleGestureDetector( - context, new MyScaleListener()); - } - - public void onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); - mScaleDetector.onTouchEvent(event); - if (event.getAction() == MotionEvent.ACTION_UP) { - mListener.onUp(event.getX(), event.getY()); - } - } - - private class MyGestureListener - extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onSingleTapUp(MotionEvent e) { - return mListener.onSingleTapUp(e.getX(), e.getY()); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return mListener.onDoubleTap(e.getX(), e.getY()); - } - - @Override - public boolean onScroll( - MotionEvent e1, MotionEvent e2, float dx, float dy) { - return mListener.onScroll(e2.getX(), e2.getY(), dx, dy); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - return mListener.onFling(velocityX, velocityY); - } - - @Override - public boolean onDown(MotionEvent e) { - mListener.onDown(e.getX(), e.getY()); - return super.onDown(e); - } - } - - private class MyScaleListener - extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - return mListener.onScaleBegin( - detector.getFocusX(), detector.getFocusY()); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mListener.onScale(detector.getFocusX(), - detector.getFocusY(), detector.getScaleFactor()); - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mListener.onScaleEnd(); - } - } -} diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java deleted file mode 100644 index 8bc46b0d4..000000000 --- a/src/com/android/camera/ui/FilmStripView.java +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * Copyright (C) 2013 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.animation.Animator; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.DecelerateInterpolator; -import android.widget.FrameLayout; -import android.widget.ImageButton; -import android.widget.Scroller; - -import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback; -import com.android.gallery3d.R; -import com.android.gallery3d.util.PanoramaViewHelper; - -public class FilmStripView extends ViewGroup { - @SuppressWarnings("unused") - private static final String TAG = "CAM_FilmStripView"; - - private static final int BUFFER_SIZE = 5; - private static final int DURATION_GEOMETRY_ADJUST = 200; - private static final float FILM_STRIP_SCALE = 0.6f; - private static final float FULLSCREEN_SCALE = 1f; - // Only check for intercepting touch events within first 500ms - private static final int SWIPE_TIME_OUT = 500; - - private Context mContext; - private FilmStripGestureRecognizer mGestureRecognizer; - private DataAdapter mDataAdapter; - private int mViewGap; - private final Rect mDrawArea = new Rect(); - - private final int mCurrentInfo = (BUFFER_SIZE - 1) / 2; - private float mScale; - private MyController mController; - private int mCenterX = -1; - private ViewInfo[] mViewInfo = new ViewInfo[BUFFER_SIZE]; - - private Listener mListener; - - private MotionEvent mDown; - private boolean mCheckToIntercept = true; - private View mCameraView; - private int mSlop; - private TimeInterpolator mViewAnimInterpolator; - - private ImageButton mViewPhotoSphereButton; - private PanoramaViewHelper mPanoramaViewHelper; - private long mLastItemId = -1; - - // This is used to resolve the misalignment problem when the device - // orientation is changed. If the current item is in fullscreen, it might - // be shifted because mCenterX is not adjusted with the orientation. - // Set this to true when onSizeChanged is called to make sure we adjust - // mCenterX accordingly. - private boolean mAnchorPending; - - /** - * Common interface for all images in the filmstrip. - */ - public interface ImageData { - /** - * Interface that is used to tell the caller whether an image is a photo - * sphere. - */ - public static interface PanoramaSupportCallback { - /** - * Called then photo sphere info has been loaded. - * - * @param isPanorama whether the image is a valid photo sphere - * @param isPanorama360 whether the photo sphere is a full 360 - * degree horizontal panorama - */ - void panoramaInfoAvailable(boolean isPanorama, - boolean isPanorama360); - } - - // Image data types. - public static final int TYPE_NONE = 0; - public static final int TYPE_CAMERA_PREVIEW = 1; - public static final int TYPE_PHOTO = 2; - - // Actions allowed to be performed on the image data. - // The actions are defined bit-wise so we can use bit operations like - // | and &. - public static final int ACTION_NONE = 0; - public static final int ACTION_PROMOTE = 1; - public static final int ACTION_DEMOTE = (1 << 1); - - /** - * SIZE_FULL can be returned by {@link ImageData#getWidth()} and - * {@link ImageData#getHeight()}. - * When SIZE_FULL is returned for width/height, it means the the - * width or height will be disregarded when deciding the view size - * of this ImageData, just use full screen size. - */ - public static final int SIZE_FULL = -2; - - /** - * Returns the width of the image. The final layout of the view returned - * by {@link DataAdapter#getView(android.content.Context, int)} will - * preserve the aspect ratio of - * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and - * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}. - */ - public int getWidth(); - - - /** - * Returns the width of the image. The final layout of the view returned - * by {@link DataAdapter#getView(android.content.Context, int)} will - * preserve the aspect ratio of - * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and - * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}. - */ - public int getHeight(); - - /** Returns the image data type */ - public int getType(); - - /** - * Checks if the UI action is supported. - * - * @param action The UI actions to check. - * @return {@code false} if at least one of the actions is not - * supported. {@code true} otherwise. - */ - public boolean isUIActionSupported(int action); - - /** - * Gives the data a hint when its view is going to be displayed. - * {@code FilmStripView} should always call this function before - * showing its corresponding view every time. - */ - public void prepare(); - - /** - * Gives the data a hint when its view is going to be removed from the - * view hierarchy. {@code FilmStripView} should always call this - * function after its corresponding view is removed from the view - * hierarchy. - */ - public void recycle(); - - /** - * Asynchronously checks if the image is a photo sphere. Notified the - * callback when the results are available. - */ - public void isPhotoSphere(Context context, PanoramaSupportCallback callback); - - /** - * If the item is a valid photo sphere panorama, this method will launch - * the viewer. - */ - public void viewPhotoSphere(PanoramaViewHelper helper); - } - - /** - * An interfaces which defines the interactions between the - * {@link ImageData} and the {@link FilmStripView}. - */ - public interface DataAdapter { - /** - * An interface which defines the update report used to return to - * the {@link com.android.camera.ui.FilmStripView.Listener}. - */ - public interface UpdateReporter { - /** Checks if the data of dataID is removed. */ - public boolean isDataRemoved(int dataID); - - /** Checks if the data of dataID is updated. */ - public boolean isDataUpdated(int dataID); - } - - /** - * An interface which defines the listener for data events over - * {@link ImageData}. - */ - public interface Listener { - // Called when the whole data loading is done. No any assumption - // on previous data. - public void onDataLoaded(); - - // Only some of the data is changed. The listener should check - // if any thing needs to be updated. - public void onDataUpdated(UpdateReporter reporter); - - public void onDataInserted(int dataID, ImageData data); - - public void onDataRemoved(int dataID, ImageData data); - } - - /** Returns the total number of image data */ - public int getTotalNumber(); - - /** - * Returns the view to visually present the image data. - * - * @param context The {@link Context} to create the view. - * @param dataID The ID of the image data to be presented. - * @return The view representing the image data. Null if - * unavailable or the {@code dataID} is out of range. - */ - public View getView(Context context, int dataID); - - /** - * Returns the {@link ImageData} specified by the ID. - * - * @param dataID The ID of the {@link ImageData}. - * @return The specified {@link ImageData}. Null if not available. - */ - public ImageData getImageData(int dataID); - - /** - * Suggests the data adapter the maximum possible size of the layout - * so the {@link DataAdapter} can optimize the view returned for the - * {@link ImageData}. - * - * @param w Maximum width. - * @param h Maximum height. - */ - public void suggestViewSizeBound(int w, int h); - - /** - * Sets the listener for data events over the ImageData. - * - * @param listener The listener to use. - */ - public void setListener(Listener listener); - - /** - * The callback when the item enters/leaves full-screen. - * TODO: Call this function actually. - * - * @param dataID The ID of the image data. - * @param fullScreen {@code true} if the data is entering full-screen. - * {@code false} otherwise. - */ - public void onDataFullScreen(int dataID, boolean fullScreen); - - /** - * Returns {@code true} if the view of the data can be moved by swipe - * gesture when in full-screen. - * - * @param dataID The ID of the data. - * @return {@code true} if the view can be moved, - * {@code false} otherwise. - */ - public boolean canSwipeInFullScreen(int dataID); - } - - /** - * An interface which defines the FilmStripView UI action listener. - */ - public interface Listener { - /** - * Callback when the data is promoted. - * - * @param dataID The ID of the promoted data. - */ - public void onDataPromoted(int dataID); - - /** - * Callback when the data is demoted. - * - * @param dataID The ID of the demoted data. - */ - public void onDataDemoted(int dataID); - - public void onDataFullScreenChange(int dataID, boolean full); - - /** - * Callback when entering/leaving camera mode. - * - * @param toCamera {@code true} if entering camera mode. Otherwise, - * {@code false} - */ - public void onSwitchMode(boolean toCamera); - - /** - * The callback when the item is centered/off-centered. - * - * @param dataID The ID of the image data. - * @param current {@code true} if the data is the current one. - * {@code false} otherwise. - */ - public void onCurrentDataChanged(int dataID, boolean current); - } - - /** - * An interface which defines the controller of {@link FilmStripView}. - */ - public interface Controller { - public boolean isScalling(); - - public void scroll(float deltaX); - - public void fling(float velocity); - - public void scrollTo(int position, int duration, boolean interruptible); - - public boolean stopScrolling(); - - public boolean isScrolling(); - - public void lockAtCurrentView(); - - public void unlockPosition(); - - public void gotoCameraFullScreen(); - - public void gotoFilmStrip(); - - public void gotoFullScreen(); - } - - /** - * A helper class to tract and calculate the view coordination. - */ - private static class ViewInfo { - private int mDataID; - /** The position of the left of the view in the whole filmstrip. */ - private int mLeftPosition; - private View mView; - private RectF mViewArea; - - public ViewInfo(int id, View v) { - v.setPivotX(0f); - v.setPivotY(0f); - mDataID = id; - mView = v; - mLeftPosition = -1; - mViewArea = new RectF(); - } - - public int getID() { - return mDataID; - } - - public void setID(int id) { - mDataID = id; - } - - public void setLeftPosition(int pos) { - mLeftPosition = pos; - } - - public int getLeftPosition() { - return mLeftPosition; - } - - public float getTranslationY(float scale) { - return mView.getTranslationY() / scale; - } - - public float getTranslationX(float scale) { - return mView.getTranslationX(); - } - - public void setTranslationY(float transY, float scale) { - mView.setTranslationY(transY * scale); - } - - public void setTranslationX(float transX, float scale) { - mView.setTranslationX(transX * scale); - } - - public void translateXBy(float transX, float scale) { - mView.setTranslationX(mView.getTranslationX() + transX * scale); - } - - public int getCenterX() { - return mLeftPosition + mView.getWidth() / 2; - } - - public View getView() { - return mView; - } - - private void layoutAt(int left, int top) { - mView.layout(left, top, left + mView.getMeasuredWidth(), - top + mView.getMeasuredHeight()); - } - - public void layoutIn(Rect drawArea, int refCenter, float scale) { - // drawArea is where to layout in. - // refCenter is the absolute horizontal position of the center of - // drawArea. - int left = (int) (drawArea.centerX() + (mLeftPosition - refCenter) * scale); - int top = (int) (drawArea.centerY() - (mView.getMeasuredHeight() / 2) * scale); - layoutAt(left, top); - mView.setScaleX(scale); - mView.setScaleY(scale); - - // update mViewArea for touch detection. - int l = mView.getLeft(); - int t = mView.getTop(); - mViewArea.set(l, t, - l + mView.getWidth() * scale, - t + mView.getHeight() * scale); - } - - public boolean areaContains(float x, float y) { - return mViewArea.contains(x, y); - } - } - - /** Constructor. */ - public FilmStripView(Context context) { - super(context); - init(context); - } - - /** Constructor. */ - public FilmStripView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - /** Constructor. */ - public FilmStripView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context); - } - - private void init(Context context) { - // This is for positioning camera controller at the same place in - // different orientations. - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - - setWillNotDraw(false); - mContext = context; - mScale = 1.0f; - mController = new MyController(context); - mViewAnimInterpolator = new DecelerateInterpolator(); - mGestureRecognizer = - new FilmStripGestureRecognizer(context, new MyGestureReceiver()); - mSlop = (int) getContext().getResources().getDimension(R.dimen.pie_touch_slop); - } - - /** - * Returns the controller. - * - * @return The {@code Controller}. - */ - public Controller getController() { - return mController; - } - - public void setListener(Listener l) { - mListener = l; - } - - public void setViewGap(int viewGap) { - mViewGap = viewGap; - } - - /** - * Sets the helper that's to be used to open photo sphere panoramas. - */ - public void setPanoramaViewHelper(PanoramaViewHelper helper) { - mPanoramaViewHelper = helper; - } - - public float getScale() { - return mScale; - } - - public boolean isAnchoredTo(int id) { - if (mViewInfo[mCurrentInfo].getID() == id - && mViewInfo[mCurrentInfo].getCenterX() == mCenterX) { - return true; - } - return false; - } - - private int getCurrentType() { - if (mDataAdapter == null) { - return ImageData.TYPE_NONE; - } - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) { - return ImageData.TYPE_NONE; - } - return mDataAdapter.getImageData(curr.getID()).getType(); - } - - @Override - public void onDraw(Canvas c) { - if (mController.hasNewGeometry()) { - layoutChildren(); - } - } - - /** Returns [width, height] preserving image aspect ratio. */ - private int[] calculateChildDimension( - int imageWidth, int imageHeight, - int boundWidth, int boundHeight) { - - if (imageWidth == ImageData.SIZE_FULL - || imageHeight == ImageData.SIZE_FULL) { - imageWidth = boundWidth; - imageHeight = boundHeight; - } - - int[] ret = new int[2]; - ret[0] = boundWidth; - ret[1] = boundHeight; - - if (imageWidth * ret[1] > ret[0] * imageHeight) { - ret[1] = imageHeight * ret[0] / imageWidth; - } else { - ret[0] = imageWidth * ret[1] / imageHeight; - } - - return ret; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int boundWidth = MeasureSpec.getSize(widthMeasureSpec); - int boundHeight = MeasureSpec.getSize(heightMeasureSpec); - if (boundWidth == 0 || boundHeight == 0) { - // Either width or height is unknown, can't measure children yet. - return; - } - - if (mDataAdapter != null) { - mDataAdapter.suggestViewSizeBound(boundWidth / 2, boundHeight / 2); - } - - for (ViewInfo info : mViewInfo) { - if (info == null) continue; - - int id = info.getID(); - int[] dim = calculateChildDimension( - mDataAdapter.getImageData(id).getWidth(), - mDataAdapter.getImageData(id).getHeight(), - boundWidth, boundHeight); - - info.getView().measure( - MeasureSpec.makeMeasureSpec( - dim[0], MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec( - dim[1], MeasureSpec.EXACTLY)); - } - } - - @Override - protected boolean fitSystemWindows(Rect insets) { - if (mViewPhotoSphereButton != null) { - // Set the position of the "View Photo Sphere" button. - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mViewPhotoSphereButton - .getLayoutParams(); - params.bottomMargin = insets.bottom; - mViewPhotoSphereButton.setLayoutParams(params); - } - - return super.fitSystemWindows(insets); - } - - private int findTheNearestView(int pointX) { - - int nearest = 0; - // Find the first non-null ViewInfo. - while (nearest < BUFFER_SIZE - && (mViewInfo[nearest] == null || mViewInfo[nearest].getLeftPosition() == -1)) { - nearest++; - } - // No existing available ViewInfo - if (nearest == BUFFER_SIZE) { - return -1; - } - int min = Math.abs(pointX - mViewInfo[nearest].getCenterX()); - - for (int infoID = nearest + 1; infoID < BUFFER_SIZE && mViewInfo[infoID] != null; infoID++) { - // Not measured yet. - if (mViewInfo[infoID].getLeftPosition() == -1) - continue; - - int c = mViewInfo[infoID].getCenterX(); - int dist = Math.abs(pointX - c); - if (dist < min) { - min = dist; - nearest = infoID; - } - } - return nearest; - } - - private ViewInfo buildInfoFromData(int dataID) { - ImageData data = mDataAdapter.getImageData(dataID); - if (data == null) { - return null; - } - data.prepare(); - View v = mDataAdapter.getView(mContext, dataID); - if (v == null) { - return null; - } - ViewInfo info = new ViewInfo(dataID, v); - v = info.getView(); - if (v != mCameraView) { - addView(info.getView()); - } else { - v.setVisibility(View.VISIBLE); - } - return info; - } - - private void removeInfo(int infoID) { - if (infoID >= mViewInfo.length || mViewInfo[infoID] == null) { - return; - } - - ImageData data = mDataAdapter.getImageData(mViewInfo[infoID].getID()); - checkForRemoval(data, mViewInfo[infoID].getView()); - mViewInfo[infoID] = null; - } - - /** - * We try to keep the one closest to the center of the screen at position - * mCurrentInfo. - */ - private void stepIfNeeded() { - if (!inFilmStrip() && !inFullScreen()) { - // The good timing to step to the next view is when everything is - // not in transition. - return; - } - int nearest = findTheNearestView(mCenterX); - // no change made. - if (nearest == -1 || nearest == mCurrentInfo) - return; - - // Going to change the current info, notify the listener. - if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), false); - } - int adjust = nearest - mCurrentInfo; - if (adjust > 0) { - for (int k = 0; k < adjust; k++) { - removeInfo(k); - } - for (int k = 0; k + adjust < BUFFER_SIZE; k++) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = BUFFER_SIZE - adjust; k < BUFFER_SIZE; k++) { - mViewInfo[k] = null; - if (mViewInfo[k - 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k - 1].getID() + 1); - } - } - } else { - for (int k = BUFFER_SIZE - 1; k >= BUFFER_SIZE + adjust; k--) { - removeInfo(k); - } - for (int k = BUFFER_SIZE - 1; k + adjust >= 0; k--) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = -1 - adjust; k >= 0; k--) { - mViewInfo[k] = null; - if (mViewInfo[k + 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k + 1].getID() - 1); - } - } - } - if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), true); - } - } - - /** Don't go beyond the bound. */ - private void clampCenterX() { - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) { - return; - } - - if (curr.getID() == 0 && mCenterX < curr.getCenterX()) { - mCenterX = curr.getCenterX(); - if (mController.isScrolling()) { - mController.stopScrolling(); - } - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW - && !mController.isScalling() - && mScale != FULLSCREEN_SCALE) { - mController.gotoFullScreen(); - } - } - if (curr.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterX > curr.getCenterX()) { - mCenterX = curr.getCenterX(); - if (!mController.isScrolling()) { - mController.stopScrolling(); - } - } - } - - private void adjustChildZOrder() { - for (int i = BUFFER_SIZE - 1; i >= 0; i--) { - if (mViewInfo[i] == null) - continue; - bringChildToFront(mViewInfo[i].getView()); - } - } - - /** - * If the current photo is a photo sphere, this will launch the Photo Sphere - * panorama viewer. - */ - private void showPhotoSphere() { - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr != null) { - mDataAdapter.getImageData(curr.getID()).viewPhotoSphere(mPanoramaViewHelper); - } - } - - /** - * @return The ID of the current item, or -1. - */ - public int getCurrentId() { - ViewInfo current = mViewInfo[mCurrentInfo]; - if (current == null) { - return -1; - } - return current.getID(); - } - - /** - * Updates the visibility of the View Photo Sphere button. - */ - private void updatePhotoSphereViewButton() { - if (mViewPhotoSphereButton == null) { - mViewPhotoSphereButton = (ImageButton) ((View) getParent()) - .findViewById(R.id.filmstrip_bottom_control_panorama); - mViewPhotoSphereButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - showPhotoSphere(); - } - }); - } - final int requestId = getCurrentId(); - - // Check if the item has changed since the last time we updated the - // visibility status. Only then check of the current image is a photo - // sphere. - if (requestId == mLastItemId || requestId < 0) { - return; - } - - ImageData data = mDataAdapter.getImageData(requestId); - data.isPhotoSphere(mContext, new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(final boolean isPanorama, - boolean isPanorama360) { - // Make sure the returned data is for the current image. - if (requestId == getCurrentId()) { - mViewPhotoSphereButton.post(new Runnable() { - @Override - public void run() { - mViewPhotoSphereButton.setVisibility(isPanorama ? View.VISIBLE - : View.GONE); - } - }); - } - } - }); - } - - private void layoutChildren() { - if (mAnchorPending) { - mCenterX = mViewInfo[mCurrentInfo].getCenterX(); - mAnchorPending = false; - } - - if (mController.hasNewGeometry()) { - mCenterX = mController.getNewPosition(); - mScale = mController.getNewScale(); - } - - clampCenterX(); - - mViewInfo[mCurrentInfo].layoutIn(mDrawArea, mCenterX, mScale); - - int currentViewLeft = mViewInfo[mCurrentInfo].getLeftPosition(); - int currentViewCenter = mViewInfo[mCurrentInfo].getCenterX(); - int fullScreenWidth = mDrawArea.width() + mViewGap; - float scaleFraction = mViewAnimInterpolator.getInterpolation( - (mScale - FILM_STRIP_SCALE) / (FULLSCREEN_SCALE - FILM_STRIP_SCALE)); - - // images on the left - for (int infoID = mCurrentInfo - 1; infoID >= 0; infoID--) { - ViewInfo curr = mViewInfo[infoID]; - if (curr == null) { - continue; - } - - ViewInfo next = mViewInfo[infoID + 1]; - int myLeft = - next.getLeftPosition() - curr.getView().getMeasuredWidth() - mViewGap; - curr.setLeftPosition(myLeft); - curr.layoutIn(mDrawArea, mCenterX, mScale); - curr.getView().setAlpha(1f); - int infoDiff = mCurrentInfo - infoID; - curr.setTranslationX( - (currentViewCenter - - fullScreenWidth * infoDiff - curr.getCenterX()) * scaleFraction, - mScale); - } - - // images on the right - for (int infoID = mCurrentInfo + 1; infoID < BUFFER_SIZE; infoID++) { - ViewInfo curr = mViewInfo[infoID]; - if (curr == null) { - continue; - } - - ViewInfo prev = mViewInfo[infoID - 1]; - int myLeft = - prev.getLeftPosition() + prev.getView().getMeasuredWidth() + mViewGap; - curr.setLeftPosition(myLeft); - curr.layoutIn(mDrawArea, mCenterX, mScale); - if (infoID == mCurrentInfo + 1) { - curr.getView().setAlpha(1f - scaleFraction); - } else { - if (scaleFraction == 0f) { - curr.getView().setAlpha(1f); - } else { - curr.getView().setAlpha(0f); - } - } - curr.setTranslationX((currentViewLeft - myLeft) * scaleFraction, mScale); - } - - stepIfNeeded(); - adjustChildZOrder(); - invalidate(); - updatePhotoSphereViewButton(); - mLastItemId = getCurrentId(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (mViewInfo[mCurrentInfo] == null) { - return; - } - - mDrawArea.left = l; - mDrawArea.top = t; - mDrawArea.right = r; - mDrawArea.bottom = b; - - layoutChildren(); - } - - // Keeps the view in the view hierarchy if it's camera preview. - // Remove from the hierarchy otherwise. - private void checkForRemoval(ImageData data, View v) { - if (data.getType() != ImageData.TYPE_CAMERA_PREVIEW) { - removeView(v); - data.recycle(); - } else { - v.setVisibility(View.INVISIBLE); - if (mCameraView != null && mCameraView != v) { - removeView(mCameraView); - } - mCameraView = v; - } - } - - private void slideViewBack(View v) { - v.animate().translationX(0) - .alpha(1f) - .setDuration(DURATION_GEOMETRY_ADJUST) - .setInterpolator(mViewAnimInterpolator) - .start(); - } - - private void updateRemoval(int dataID, final ImageData data) { - int removedInfo = findInfoByDataID(dataID); - - // adjust the data id to be consistent - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() <= dataID) { - continue; - } - mViewInfo[i].setID(mViewInfo[i].getID() - 1); - } - if (removedInfo == -1) { - return; - } - - final View removedView = mViewInfo[removedInfo].getView(); - final int offsetX = removedView.getMeasuredWidth() + mViewGap; - - for (int i = removedInfo + 1; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setLeftPosition(mViewInfo[i].getLeftPosition() - offsetX); - } - } - - if (removedInfo >= mCurrentInfo - && mViewInfo[removedInfo].getID() < mDataAdapter.getTotalNumber()) { - // Fill the removed info by left shift when the current one or - // anyone on the right is removed, and there's more data on the - // right available. - for (int i = removedInfo; i < BUFFER_SIZE - 1; i++) { - mViewInfo[i] = mViewInfo[i + 1]; - } - - // pull data out from the DataAdapter for the last one. - int curr = BUFFER_SIZE - 1; - int prev = curr - 1; - if (mViewInfo[prev] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[prev].getID() + 1); - } - - // Translate the views to their original places. - for (int i = removedInfo; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); - } - } - - // The end of the filmstrip might have been changed. - // The mCenterX might be out of the bound. - ViewInfo currInfo = mViewInfo[mCurrentInfo]; - if (currInfo.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterX > currInfo.getCenterX()) { - int adjustDiff = currInfo.getCenterX() - mCenterX; - mCenterX = currInfo.getCenterX(); - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].translateXBy(adjustDiff, mScale); - } - } - } - } else { - // fill the removed place by right shift - mCenterX -= offsetX; - - for (int i = removedInfo; i > 0; i--) { - mViewInfo[i] = mViewInfo[i - 1]; - } - - // pull data out from the DataAdapter for the first one. - int curr = 0; - int next = curr + 1; - if (mViewInfo[next] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[next].getID() - 1); - } - - // Translate the views to their original places. - for (int i = removedInfo; i >= 0; i--) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); - } - } - } - - // Now, slide every one back. - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getTranslationX(mScale) != 0f) { - slideViewBack(mViewInfo[i].getView()); - } - } - - int transY = getHeight() / 8; - if (removedView.getTranslationY() < 0) { - transY = -transY; - } - removedView.animate() - .alpha(0f) - .translationYBy(transY) - .setInterpolator(mViewAnimInterpolator) - .setDuration(DURATION_GEOMETRY_ADJUST) - .withEndAction(new Runnable() { - @Override - public void run() { - checkForRemoval(data, removedView); - } - }) - .start(); - layoutChildren(); - } - - // returns -1 on failure. - private int findInfoByDataID(int dataID) { - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getID() == dataID) { - return i; - } - } - return -1; - } - - private void updateInsertion(int dataID) { - int insertedInfo = findInfoByDataID(dataID); - if (insertedInfo == -1) { - // Not in the current info buffers. Check if it's inserted - // at the end. - if (dataID == mDataAdapter.getTotalNumber() - 1) { - int prev = findInfoByDataID(dataID - 1); - if (prev >= 0 && prev < BUFFER_SIZE - 1) { - // The previous data is in the buffer and we still - // have room for the inserted data. - insertedInfo = prev + 1; - } - } - } - - // adjust the data id to be consistent - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() < dataID) { - continue; - } - mViewInfo[i].setID(mViewInfo[i].getID() + 1); - } - if (insertedInfo == -1) { - return; - } - - final ImageData data = mDataAdapter.getImageData(dataID); - int[] dim = calculateChildDimension( - data.getWidth(), data.getHeight(), - getMeasuredWidth(), getMeasuredHeight()); - final int offsetX = dim[0] + mViewGap; - ViewInfo viewInfo = buildInfoFromData(dataID); - - if (insertedInfo >= mCurrentInfo) { - if (insertedInfo == mCurrentInfo) { - viewInfo.setLeftPosition(mViewInfo[mCurrentInfo].getLeftPosition()); - } - // Shift right to make rooms for newly inserted item. - removeInfo(BUFFER_SIZE - 1); - for (int i = BUFFER_SIZE - 1; i > insertedInfo; i--) { - mViewInfo[i] = mViewInfo[i - 1]; - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); - } - } - } else { - // Shift left. Put the inserted data on the left instead of the - // found position. - --insertedInfo; - if (insertedInfo < 0) { - return; - } - removeInfo(0); - for (int i = 1; i <= insertedInfo; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); - mViewInfo[i - 1] = mViewInfo[i]; - } - } - } - - mViewInfo[insertedInfo] = viewInfo; - View insertedView = mViewInfo[insertedInfo].getView(); - insertedView.setAlpha(0f); - insertedView.setTranslationY(getHeight() / 8); - insertedView.animate() - .alpha(1f) - .translationY(0f) - .setInterpolator(mViewAnimInterpolator) - .setDuration(DURATION_GEOMETRY_ADJUST) - .start(); - invalidate(); - } - - public void setDataAdapter(DataAdapter adapter) { - mDataAdapter = adapter; - mDataAdapter.suggestViewSizeBound(getMeasuredWidth(), getMeasuredHeight()); - mDataAdapter.setListener(new DataAdapter.Listener() { - @Override - public void onDataLoaded() { - reload(); - } - - @Override - public void onDataUpdated(DataAdapter.UpdateReporter reporter) { - update(reporter); - } - - @Override - public void onDataInserted(int dataID, ImageData data) { - if (mViewInfo[mCurrentInfo] == null) { - // empty now, simply do a reload. - reload(); - return; - } - updateInsertion(dataID); - } - - @Override - public void onDataRemoved(int dataID, ImageData data) { - updateRemoval(dataID, data); - } - }); - } - - public boolean inFilmStrip() { - return (mScale == FILM_STRIP_SCALE); - } - - public boolean inFullScreen() { - return (mScale == FULLSCREEN_SCALE); - } - - public boolean inCameraFullscreen() { - return isAnchoredTo(0) && inFullScreen() - && (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (inFilmStrip()) { - return true; - } - - if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { - mCheckToIntercept = true; - mDown = MotionEvent.obtain(ev); - ViewInfo viewInfo = mViewInfo[mCurrentInfo]; - // Do not intercept touch if swipe is not enabled - if (viewInfo != null && !mDataAdapter.canSwipeInFullScreen(viewInfo.getID())) { - mCheckToIntercept = false; - } - return false; - } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { - // Do not intercept touch once child is in zoom mode - mCheckToIntercept = false; - return false; - } else { - if (!mCheckToIntercept) { - return false; - } - if (ev.getEventTime() - ev.getDownTime() > SWIPE_TIME_OUT) { - return false; - } - int deltaX = (int) (ev.getX() - mDown.getX()); - int deltaY = (int) (ev.getY() - mDown.getY()); - if (ev.getActionMasked() == MotionEvent.ACTION_MOVE - && deltaX < mSlop * (-1)) { - // intercept left swipe - if (Math.abs(deltaX) >= Math.abs(deltaY) * 2) { - return true; - } - } - } - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mGestureRecognizer.onTouchEvent(ev); - return true; - } - - private void updateViewInfo(int infoID) { - ViewInfo info = mViewInfo[infoID]; - removeView(info.getView()); - mViewInfo[infoID] = buildInfoFromData(info.getID()); - } - - /** Some of the data is changed. */ - private void update(DataAdapter.UpdateReporter reporter) { - // No data yet. - if (mViewInfo[mCurrentInfo] == null) { - reload(); - return; - } - - // Check the current one. - ViewInfo curr = mViewInfo[mCurrentInfo]; - int dataID = curr.getID(); - if (reporter.isDataRemoved(dataID)) { - mCenterX = -1; - reload(); - return; - } - if (reporter.isDataUpdated(dataID)) { - updateViewInfo(mCurrentInfo); - } - - // Check left - for (int i = mCurrentInfo - 1; i >= 0; i--) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo next = mViewInfo[i + 1]; - if (next != null) { - mViewInfo[i] = buildInfoFromData(next.getID() - 1); - } - } - } - - // Check right - for (int i = mCurrentInfo + 1; i < BUFFER_SIZE; i++) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo prev = mViewInfo[i - 1]; - if (prev != null) { - mViewInfo[i] = buildInfoFromData(prev.getID() + 1); - } - } - } - } - - /** - * The whole data might be totally different. Flush all and load from the - * start. - */ - private void reload() { - removeAllViews(); - int dataNumber = mDataAdapter.getTotalNumber(); - if (dataNumber == 0) { - return; - } - - mViewInfo[mCurrentInfo] = buildInfoFromData(0); - mViewInfo[mCurrentInfo].setLeftPosition(0); - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW) { - // we are in camera mode by default. - mController.lockAtCurrentView(); - } - for (int i = 1; mCurrentInfo + i < BUFFER_SIZE || mCurrentInfo - i >= 0; i++) { - int infoID = mCurrentInfo + i; - if (infoID < BUFFER_SIZE && mViewInfo[infoID - 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID - 1].getID() + 1); - } - infoID = mCurrentInfo - i; - if (infoID >= 0 && mViewInfo[infoID + 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID + 1].getID() - 1); - } - } - layoutChildren(); - } - - private void promoteData(int infoID, int dataID) { - if (mListener != null) { - mListener.onDataPromoted(dataID); - } - } - - private void demoteData(int infoID, int dataID) { - if (mListener != null) { - mListener.onDataDemoted(dataID); - } - } - - /** - * MyController controls all the geometry animations. It passively tells the - * geometry information on demand. - */ - private class MyController implements - Controller, - ValueAnimator.AnimatorUpdateListener, - Animator.AnimatorListener { - - private ValueAnimator mScaleAnimator; - private boolean mHasNewScale; - private float mNewScale; - - private Scroller mScroller; - private boolean mHasNewPosition; - private DecelerateInterpolator mDecelerateInterpolator; - - private boolean mCanStopScroll; - - private boolean mIsPositionLocked; - private int mLockedViewInfo; - - MyController(Context context) { - mScroller = new Scroller(context); - mHasNewPosition = false; - mScaleAnimator = new ValueAnimator(); - mScaleAnimator.addUpdateListener(MyController.this); - mScaleAnimator.addListener(MyController.this); - mDecelerateInterpolator = new DecelerateInterpolator(); - mCanStopScroll = true; - mHasNewScale = false; - } - - @Override - public boolean isScrolling() { - return !mScroller.isFinished(); - } - - @Override - public boolean isScalling() { - return mScaleAnimator.isRunning(); - } - - boolean hasNewGeometry() { - mHasNewPosition = mScroller.computeScrollOffset(); - if (!mHasNewPosition) { - mCanStopScroll = true; - } - // If the position is locked, then we always return true to force - // the position value to use the locked value. - return (mHasNewPosition || mHasNewScale || mIsPositionLocked); - } - - /** - * Always call {@link #hasNewGeometry()} before getting the new scale - * value. - */ - float getNewScale() { - if (!mHasNewScale) { - return mScale; - } - mHasNewScale = false; - return mNewScale; - } - - /** - * Always call {@link #hasNewGeometry()} before getting the new position - * value. - */ - int getNewPosition() { - if (mIsPositionLocked) { - if (mViewInfo[mLockedViewInfo] == null) - return mCenterX; - return mViewInfo[mLockedViewInfo].getCenterX(); - } - if (!mHasNewPosition) - return mCenterX; - return mScroller.getCurrX(); - } - - @Override - public void lockAtCurrentView() { - mIsPositionLocked = true; - mLockedViewInfo = mCurrentInfo; - } - - @Override - public void unlockPosition() { - if (mIsPositionLocked) { - // only when the position is previously locked we set the - // current position to make it consistent. - if (mViewInfo[mLockedViewInfo] != null) { - mCenterX = mViewInfo[mLockedViewInfo].getCenterX(); - } - mIsPositionLocked = false; - } - } - - private int estimateMinX(int dataID, int leftPos, int viewWidth) { - return leftPos - (dataID + 100) * (viewWidth + mViewGap); - } - - private int estimateMaxX(int dataID, int leftPos, int viewWidth) { - return leftPos - + (mDataAdapter.getTotalNumber() - dataID + 100) - * (viewWidth + mViewGap); - } - - @Override - public void scroll(float deltaX) { - if (mController.isScrolling()) { - return; - } - mCenterX += deltaX; - } - - @Override - public void fling(float velocityX) { - if (!stopScrolling() || mIsPositionLocked) { - return; - } - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info == null) { - return; - } - - float scaledVelocityX = velocityX / mScale; - if (inCameraFullscreen() && scaledVelocityX < 0) { - // Swipe left in camera preview. - gotoFilmStrip(); - } - - int w = getWidth(); - // Estimation of possible length on the left. To ensure the - // velocity doesn't become too slow eventually, we add a huge number - // to the estimated maximum. - int minX = estimateMinX(info.getID(), info.getLeftPosition(), w); - // Estimation of possible length on the right. Likewise, exaggerate - // the possible maximum too. - int maxX = estimateMaxX(info.getID(), info.getLeftPosition(), w); - mScroller.fling(mCenterX, 0, (int) -velocityX, 0, minX, maxX, 0, 0); - - layoutChildren(); - } - - @Override - public boolean stopScrolling() { - if (!mCanStopScroll) - return false; - mScroller.forceFinished(true); - mHasNewPosition = false; - return true; - } - - private void stopScale() { - mScaleAnimator.cancel(); - mHasNewScale = false; - } - - @Override - public void scrollTo(int position, int duration, boolean interruptible) { - if (!stopScrolling() || mIsPositionLocked) - return; - mCanStopScroll = interruptible; - stopScrolling(); - mScroller.startScroll(mCenterX, 0, position - mCenterX, - 0, duration); - invalidate(); - } - - private void scaleTo(float scale, int duration) { - stopScale(); - mScaleAnimator.setDuration(duration); - mScaleAnimator.setFloatValues(mScale, scale); - mScaleAnimator.setInterpolator(mDecelerateInterpolator); - mScaleAnimator.start(); - mHasNewScale = true; - layoutChildren(); - } - - @Override - public void gotoFilmStrip() { - unlockPosition(); - scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST); - if (mListener != null) { - mListener.onSwitchMode(false); - } - } - - @Override - public void gotoFullScreen() { - if (mViewInfo[mCurrentInfo] != null) { - mController.scrollTo(mViewInfo[mCurrentInfo].getCenterX(), - DURATION_GEOMETRY_ADJUST, false); - } - enterFullScreen(); - } - - private void enterFullScreen() { - if (mListener != null) { - // TODO: After full size images snapping to fill the screen at - // the end of a scroll/fling is implemented, we should only make - // this call when the view on the center of the screen is - // camera preview - mListener.onSwitchMode(true); - } - if (inFullScreen()) { - return; - } - scaleTo(1f, DURATION_GEOMETRY_ADJUST); - } - - @Override - public void gotoCameraFullScreen() { - if (mDataAdapter.getImageData(0).getType() - != ImageData.TYPE_CAMERA_PREVIEW) { - return; - } - gotoFullScreen(); - scrollTo( - estimateMinX(mViewInfo[mCurrentInfo].getID(), - mViewInfo[mCurrentInfo].getLeftPosition(), - getWidth()), - DURATION_GEOMETRY_ADJUST, false); - } - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mHasNewScale = true; - mNewScale = (Float) animation.getAnimatedValue(); - layoutChildren(); - } - - @Override - public void onAnimationStart(Animator anim) { - } - - @Override - public void onAnimationEnd(Animator anim) { - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info != null && mCenterX == info.getCenterX()) { - if (inFullScreen()) { - lockAtCurrentView(); - } else if (inFilmStrip()) { - unlockPosition(); - } - } - } - - @Override - public void onAnimationCancel(Animator anim) { - } - - @Override - public void onAnimationRepeat(Animator anim) { - } - } - - private class MyGestureReceiver implements FilmStripGestureRecognizer.Listener { - // Indicating the current trend of scaling is up (>1) or down (<1). - private float mScaleTrend; - - @Override - public boolean onSingleTapUp(float x, float y) { - if (inFilmStrip()) { - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) { - continue; - } - - if (mViewInfo[i].areaContains(x, y)) { - mController.scrollTo(mViewInfo[i].getCenterX(), - DURATION_GEOMETRY_ADJUST, false); - return true; - } - } - } - return false; - } - - @Override - public boolean onDoubleTap(float x, float y) { - if (inFilmStrip()) { - ViewInfo centerInfo = mViewInfo[mCurrentInfo]; - if (centerInfo != null && centerInfo.areaContains(x, y)) { - mController.gotoFullScreen(); - return true; - } - } else if (inFullScreen()) { - mController.gotoFilmStrip(); - return true; - } - return false; - } - - @Override - public boolean onDown(float x, float y) { - if (mController.isScrolling()) { - mController.stopScrolling(); - } - return true; - } - - @Override - public boolean onUp(float x, float y) { - float halfH = getHeight() / 2; - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) { - continue; - } - float transY = mViewInfo[i].getTranslationY(mScale); - if (transY == 0) { - continue; - } - int id = mViewInfo[i].getID(); - - if (mDataAdapter.getImageData(id) - .isUIActionSupported(ImageData.ACTION_DEMOTE) - && transY > halfH) { - demoteData(i, id); - } else if (mDataAdapter.getImageData(id) - .isUIActionSupported(ImageData.ACTION_PROMOTE) - && transY < -halfH) { - promoteData(i, id); - } else { - // put the view back. - mViewInfo[i].getView().animate() - .translationY(0f) - .alpha(1f) - .setDuration(DURATION_GEOMETRY_ADJUST) - .start(); - } - } - return false; - } - - @Override - public boolean onScroll(float x, float y, float dx, float dy) { - int deltaX = (int) (dx / mScale); - if (inFilmStrip()) { - if (Math.abs(dx) > Math.abs(dy)) { - if (deltaX > 0 && inCameraFullscreen()) { - mController.gotoFilmStrip(); - } - mController.scroll(deltaX); - } else { - // Vertical part. Promote or demote. - // int scaledDeltaY = (int) (dy * mScale); - int hit = 0; - Rect hitRect = new Rect(); - for (; hit < BUFFER_SIZE; hit++) { - if (mViewInfo[hit] == null) { - continue; - } - mViewInfo[hit].getView().getHitRect(hitRect); - if (hitRect.contains((int) x, (int) y)) { - break; - } - } - if (hit == BUFFER_SIZE) { - return false; - } - - ImageData data = mDataAdapter.getImageData(mViewInfo[hit].getID()); - float transY = mViewInfo[hit].getTranslationY(mScale) - dy / mScale; - if (!data.isUIActionSupported(ImageData.ACTION_DEMOTE) && transY > 0f) { - transY = 0f; - } - if (!data.isUIActionSupported(ImageData.ACTION_PROMOTE) && transY < 0f) { - transY = 0f; - } - mViewInfo[hit].setTranslationY(transY, mScale); - } - } else if (inFullScreen()) { - if (deltaX > 0 && inCameraFullscreen()) { - mController.gotoFilmStrip(); - } - mController.scroll(deltaX); - } - layoutChildren(); - - return true; - } - - @Override - public boolean onFling(float velocityX, float velocityY) { - if (Math.abs(velocityX) > Math.abs(velocityY)) { - mController.fling(velocityX); - } else { - // ignore vertical fling. - } - return true; - } - - @Override - public boolean onScaleBegin(float focusX, float focusY) { - if (inCameraFullscreen()) { - return false; - } - mScaleTrend = 1f; - return true; - } - - @Override - public boolean onScale(float focusX, float focusY, float scale) { - if (inCameraFullscreen()) { - return false; - } - - mScaleTrend = mScaleTrend * 0.3f + scale * 0.7f; - mScale *= scale; - if (mScale <= FILM_STRIP_SCALE) { - mScale = FILM_STRIP_SCALE; - } - if (mScale >= FULLSCREEN_SCALE) { - mScale = FULLSCREEN_SCALE; - } - layoutChildren(); - return true; - } - - @Override - public void onScaleEnd() { - if (mScaleTrend >= 1f) { - mController.gotoFullScreen(); - } else { - mController.gotoFilmStrip(); - } - mScaleTrend = 1f; - } - } -} diff --git a/src/com/android/camera/ui/FocusIndicator.java b/src/com/android/camera/ui/FocusIndicator.java deleted file mode 100644 index e06057041..000000000 --- a/src/com/android/camera/ui/FocusIndicator.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 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; - -public interface FocusIndicator { - public void showStart(); - public void showSuccess(boolean timeout); - public void showFail(boolean timeout); - public void clear(); -} diff --git a/src/com/android/camera/ui/InLineSettingCheckBox.java b/src/com/android/camera/ui/InLineSettingCheckBox.java deleted file mode 100644 index c1aa5a91c..000000000 --- a/src/com/android/camera/ui/InLineSettingCheckBox.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 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.util.AttributeSet; -import android.view.accessibility.AccessibilityEvent; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; - - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/* A check box setting control which turns on/off the setting. */ -public class InLineSettingCheckBox extends InLineSettingItem { - private CheckBox mCheckBox; - - OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean desiredState) { - changeIndex(desiredState ? 1 : 0); - } - }; - - public InLineSettingCheckBox(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mCheckBox = (CheckBox) findViewById(R.id.setting_check_box); - mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener); - } - - @Override - public void initialize(ListPreference preference) { - super.initialize(preference); - // Add content descriptions for the increment and decrement buttons. - mCheckBox.setContentDescription(getContext().getResources().getString( - R.string.accessibility_check_box, mPreference.getTitle())); - } - - @Override - protected void updateView() { - mCheckBox.setOnCheckedChangeListener(null); - if (mOverrideValue == null) { - mCheckBox.setChecked(mIndex == 1); - } else { - int index = mPreference.findIndexOfValue(mOverrideValue); - mCheckBox.setChecked(index == 1); - } - mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener); - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - event.getText().add(mPreference.getTitle()); - return true; - } - - @Override - public void setEnabled(boolean enable) { - if (mTitle != null) mTitle.setEnabled(enable); - if (mCheckBox != null) mCheckBox.setEnabled(enable); - } -} diff --git a/src/com/android/camera/ui/InLineSettingItem.java b/src/com/android/camera/ui/InLineSettingItem.java deleted file mode 100644 index 839a77fd0..000000000 --- a/src/com/android/camera/ui/InLineSettingItem.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2011 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.util.AttributeSet; -import android.view.accessibility.AccessibilityEvent; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/** - * A one-line camera setting could be one of three types: knob, switch or restore - * preference button. The setting includes a title for showing the preference - * title which is initialized in the SimpleAdapter. A knob also includes - * (ex: Picture size), a previous button, the current value (ex: 5MP), - * and a next button. A switch, i.e. the preference RecordLocationPreference, - * has only two values on and off which will be controlled in a switch button. - * Other setting popup window includes several InLineSettingItem items with - * different types if possible. - */ -public abstract class InLineSettingItem extends LinearLayout { - private Listener mListener; - protected ListPreference mPreference; - protected int mIndex; - // Scene mode can override the original preference value. - protected String mOverrideValue; - protected TextView mTitle; - - static public interface Listener { - public void onSettingChanged(ListPreference pref); - } - - public InLineSettingItem(Context context, AttributeSet attrs) { - super(context, attrs); - } - - protected void setTitle(ListPreference preference) { - mTitle = ((TextView) findViewById(R.id.title)); - mTitle.setText(preference.getTitle()); - } - - public void initialize(ListPreference preference) { - setTitle(preference); - if (preference == null) return; - mPreference = preference; - reloadPreference(); - } - - protected abstract void updateView(); - - protected boolean changeIndex(int index) { - if (index >= mPreference.getEntryValues().length || index < 0) return false; - mIndex = index; - mPreference.setValueIndex(mIndex); - if (mListener != null) { - mListener.onSettingChanged(mPreference); - } - updateView(); - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - return true; - } - - // The value of the preference may have changed. Update the UI. - public void reloadPreference() { - mIndex = mPreference.findIndexOfValue(mPreference.getValue()); - updateView(); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public void overrideSettings(String value) { - mOverrideValue = value; - updateView(); - } -} diff --git a/src/com/android/camera/ui/InLineSettingMenu.java b/src/com/android/camera/ui/InLineSettingMenu.java deleted file mode 100644 index 8e45c3e38..000000000 --- a/src/com/android/camera/ui/InLineSettingMenu.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2011 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.util.AttributeSet; -import android.util.Log; -import android.view.accessibility.AccessibilityEvent; -import android.widget.TextView; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/* Setting menu item that will bring up a menu when you click on it. */ -public class InLineSettingMenu extends InLineSettingItem { - private static final String TAG = "InLineSettingMenu"; - // The view that shows the current selected setting. Ex: 5MP - private TextView mEntry; - - public InLineSettingMenu(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mEntry = (TextView) findViewById(R.id.current_setting); - } - - @Override - public void initialize(ListPreference preference) { - super.initialize(preference); - //TODO: add contentDescription - } - - @Override - protected void updateView() { - if (mOverrideValue == null) { - mEntry.setText(mPreference.getEntry()); - } else { - int index = mPreference.findIndexOfValue(mOverrideValue); - if (index != -1) { - mEntry.setText(mPreference.getEntries()[index]); - } else { - // Avoid the crash if camera driver has bugs. - Log.e(TAG, "Fail to find override value=" + mOverrideValue); - mPreference.print(); - } - } - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - event.getText().add(mPreference.getTitle() + mPreference.getEntry()); - return true; - } - - @Override - public void setEnabled(boolean enable) { - super.setEnabled(enable); - if (mTitle != null) mTitle.setEnabled(enable); - if (mEntry != null) mEntry.setEnabled(enable); - } -} diff --git a/src/com/android/camera/ui/LayoutChangeHelper.java b/src/com/android/camera/ui/LayoutChangeHelper.java deleted file mode 100644 index ef4eb6a7a..000000000 --- a/src/com/android/camera/ui/LayoutChangeHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 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.view.View; - -public class LayoutChangeHelper implements LayoutChangeNotifier { - private LayoutChangeNotifier.Listener mListener; - private boolean mFirstTimeLayout; - private View mView; - - public LayoutChangeHelper(View v) { - mView = v; - mFirstTimeLayout = true; - } - - @Override - public void setOnLayoutChangeListener(LayoutChangeNotifier.Listener listener) { - mListener = listener; - } - - public void onLayout(boolean changed, int l, int t, int r, int b) { - if (mListener == null) return; - if (mFirstTimeLayout || changed) { - mFirstTimeLayout = false; - mListener.onLayoutChange(mView, l, t, r, b); - } - } -} diff --git a/src/com/android/camera/ui/LayoutChangeNotifier.java b/src/com/android/camera/ui/LayoutChangeNotifier.java deleted file mode 100644 index 6261d34f6..000000000 --- a/src/com/android/camera/ui/LayoutChangeNotifier.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 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.view.View; - -public interface LayoutChangeNotifier { - public interface Listener { - // Invoked only when the layout has changed or it is the first layout. - public void onLayoutChange(View v, int l, int t, int r, int b); - } - - public void setOnLayoutChangeListener(LayoutChangeNotifier.Listener listener); -} diff --git a/src/com/android/camera/ui/LayoutNotifyView.java b/src/com/android/camera/ui/LayoutNotifyView.java deleted file mode 100644 index 6e118fc3a..000000000 --- a/src/com/android/camera/ui/LayoutNotifyView.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 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.util.AttributeSet; -import android.view.View; - -/* - * Customized view to support onLayoutChange() at or before API 10. - */ -public class LayoutNotifyView extends View implements LayoutChangeNotifier { - private LayoutChangeHelper mLayoutChangeHelper = new LayoutChangeHelper(this); - - public LayoutNotifyView(Context context) { - super(context); - } - - public LayoutNotifyView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void setOnLayoutChangeListener( - LayoutChangeNotifier.Listener listener) { - mLayoutChangeHelper.setOnLayoutChangeListener(listener); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - mLayoutChangeHelper.onLayout(changed, l, t, r, b); - } -} diff --git a/src/com/android/camera/ui/ListPrefSettingPopup.java b/src/com/android/camera/ui/ListPrefSettingPopup.java deleted file mode 100644 index cfef73f49..000000000 --- a/src/com/android/camera/ui/ListPrefSettingPopup.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.ListView; -import android.widget.AdapterView; -import android.widget.ImageView; -import android.widget.SimpleAdapter; - -import com.android.camera.IconListPreference; -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// A popup window that shows one camera setting. The title is the name of the -// setting (ex: white-balance). The entries are the supported values (ex: -// daylight, incandescent, etc). If initialized with an IconListPreference, -// the entries will contain both text and icons. Otherwise, entries will be -// shown in text. -public class ListPrefSettingPopup extends AbstractSettingPopup implements - AdapterView.OnItemClickListener { - private static final String TAG = "ListPrefSettingPopup"; - private ListPreference mPreference; - private Listener mListener; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public ListPrefSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - private class ListPrefSettingAdapter extends SimpleAdapter { - ListPrefSettingAdapter(Context context, List<? extends Map<String, ?>> data, - int resource, String[] from, int[] to) { - super(context, data, resource, from, to); - } - - @Override - public void setViewImage(ImageView v, String value) { - if ("".equals(value)) { - // Some settings have no icons. Ex: exposure compensation. - v.setVisibility(View.GONE); - } else { - super.setViewImage(v, value); - } - } - } - - public void initialize(ListPreference preference) { - mPreference = preference; - Context context = getContext(); - CharSequence[] entries = mPreference.getEntries(); - int[] iconIds = null; - if (preference instanceof IconListPreference) { - iconIds = ((IconListPreference) mPreference).getImageIds(); - if (iconIds == null) { - iconIds = ((IconListPreference) mPreference).getLargeIconIds(); - } - } - // Set title. - mTitle.setText(mPreference.getTitle()); - - // Prepare the ListView. - ArrayList<HashMap<String, Object>> listItem = - new ArrayList<HashMap<String, Object>>(); - for(int i = 0; i < entries.length; ++i) { - HashMap<String, Object> map = new HashMap<String, Object>(); - map.put("text", entries[i].toString()); - if (iconIds != null) map.put("image", iconIds[i]); - listItem.add(map); - } - SimpleAdapter listItemAdapter = new ListPrefSettingAdapter(context, listItem, - R.layout.setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - ((ListView) mSettingList).setAdapter(listItemAdapter); - ((ListView) mSettingList).setOnItemClickListener(this); - reloadPreference(); - } - - // The value of the preference may have changed. Update the UI. - @Override - public void reloadPreference() { - int index = mPreference.findIndexOfValue(mPreference.getValue()); - if (index != -1) { - ((ListView) mSettingList).setItemChecked(index, true); - } else { - Log.e(TAG, "Invalid preference value."); - mPreference.print(); - } - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, - int index, long id) { - mPreference.setValueIndex(index); - if (mListener != null) mListener.onListPrefChanged(mPreference); - } -} diff --git a/src/com/android/camera/ui/MoreSettingPopup.java b/src/com/android/camera/ui/MoreSettingPopup.java deleted file mode 100644 index 5900058df..000000000 --- a/src/com/android/camera/ui/MoreSettingPopup.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import com.android.camera.ListPreference; -import com.android.camera.PreferenceGroup; -import com.android.gallery3d.R; - -import java.util.ArrayList; - -/* A popup window that contains several camera settings. */ -public class MoreSettingPopup extends AbstractSettingPopup - implements InLineSettingItem.Listener, - AdapterView.OnItemClickListener { - @SuppressWarnings("unused") - private static final String TAG = "MoreSettingPopup"; - - private Listener mListener; - private ArrayList<ListPreference> mListItem = new ArrayList<ListPreference>(); - - // Keep track of which setting items are disabled - // e.g. White balance will be disabled when scene mode is set to non-auto - private boolean[] mEnabled; - - static public interface Listener { - public void onSettingChanged(ListPreference pref); - public void onPreferenceClicked(ListPreference pref); - } - - private class MoreSettingAdapter extends ArrayAdapter<ListPreference> { - LayoutInflater mInflater; - String mOnString; - String mOffString; - MoreSettingAdapter() { - super(MoreSettingPopup.this.getContext(), 0, mListItem); - Context context = getContext(); - mInflater = LayoutInflater.from(context); - mOnString = context.getString(R.string.setting_on); - mOffString = context.getString(R.string.setting_off); - } - - private int getSettingLayoutId(ListPreference pref) { - - if (isOnOffPreference(pref)) { - return R.layout.in_line_setting_check_box; - } - return R.layout.in_line_setting_menu; - } - - private boolean isOnOffPreference(ListPreference pref) { - CharSequence[] entries = pref.getEntries(); - if (entries.length != 2) return false; - String str1 = entries[0].toString(); - String str2 = entries[1].toString(); - return ((str1.equals(mOnString) && str2.equals(mOffString)) || - (str1.equals(mOffString) && str2.equals(mOnString))); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView != null) return convertView; - - ListPreference pref = mListItem.get(position); - - int viewLayoutId = getSettingLayoutId(pref); - InLineSettingItem view = (InLineSettingItem) - mInflater.inflate(viewLayoutId, parent, false); - - view.initialize(pref); // no init for restore one - view.setSettingChangedListener(MoreSettingPopup.this); - if (position >= 0 && position < mEnabled.length) { - view.setEnabled(mEnabled[position]); - } else { - Log.w(TAG, "Invalid input: enabled list length, " + mEnabled.length - + " position " + position); - } - return view; - } - - @Override - public boolean isEnabled(int position) { - if (position >= 0 && position < mEnabled.length) { - return mEnabled[position]; - } - return true; - } - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public MoreSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void initialize(PreferenceGroup group, String[] keys) { - // Prepare the setting items. - for (int i = 0; i < keys.length; ++i) { - ListPreference pref = group.findPreference(keys[i]); - if (pref != null) mListItem.add(pref); - } - - ArrayAdapter<ListPreference> mListItemAdapter = new MoreSettingAdapter(); - ((ListView) mSettingList).setAdapter(mListItemAdapter); - ((ListView) mSettingList).setOnItemClickListener(this); - ((ListView) mSettingList).setSelector(android.R.color.transparent); - // Initialize mEnabled - mEnabled = new boolean[mListItem.size()]; - for (int i = 0; i < mEnabled.length; i++) { - mEnabled[i] = true; - } - } - - // When preferences are disabled, we will display them grayed out. Users - // will not be able to change the disabled preferences, but they can still see - // the current value of the preferences - public void setPreferenceEnabled(String key, boolean enable) { - int count = mEnabled == null ? 0 : mEnabled.length; - for (int j = 0; j < count; j++) { - ListPreference pref = mListItem.get(j); - if (pref != null && key.equals(pref.getKey())) { - mEnabled[j] = enable; - break; - } - } - } - - public void onSettingChanged(ListPreference pref) { - if (mListener != null) { - mListener.onSettingChanged(pref); - } - } - - // Scene mode can override other camera settings (ex: flash mode). - public void overrideSettings(final String ... keyvalues) { - int count = mEnabled == null ? 0 : mEnabled.length; - for (int i = 0; i < keyvalues.length; i += 2) { - String key = keyvalues[i]; - String value = keyvalues[i + 1]; - for (int j = 0; j < count; j++) { - ListPreference pref = mListItem.get(j); - if (pref != null && key.equals(pref.getKey())) { - // Change preference - if (value != null) pref.setValue(value); - // If the preference is overridden, disable the preference - boolean enable = value == null; - mEnabled[j] = enable; - if (mSettingList.getChildCount() > j) { - mSettingList.getChildAt(j).setEnabled(enable); - } - } - } - } - reloadPreference(); - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, - long id) { - if (mListener != null) { - ListPreference pref = mListItem.get(position); - mListener.onPreferenceClicked(pref); - } - } - - @Override - public void reloadPreference() { - int count = mSettingList.getChildCount(); - for (int i = 0; i < count; i++) { - ListPreference pref = mListItem.get(i); - if (pref != null) { - InLineSettingItem settingItem = - (InLineSettingItem) mSettingList.getChildAt(i); - settingItem.reloadPreference(); - } - } - } -} diff --git a/src/com/android/camera/ui/OnIndicatorEventListener.java b/src/com/android/camera/ui/OnIndicatorEventListener.java deleted file mode 100644 index 566f5c7a8..000000000 --- a/src/com/android/camera/ui/OnIndicatorEventListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2011 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; - -public interface OnIndicatorEventListener { - public static int EVENT_ENTER_SECOND_LEVEL_INDICATOR_BAR = 0; - public static int EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR = 1; - public static int EVENT_ENTER_ZOOM_CONTROL = 2; - public static int EVENT_LEAVE_ZOOM_CONTROL = 3; - void onIndicatorEvent(int event); -} diff --git a/src/com/android/camera/ui/OverlayRenderer.java b/src/com/android/camera/ui/OverlayRenderer.java deleted file mode 100644 index 417e219aa..000000000 --- a/src/com/android/camera/ui/OverlayRenderer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 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.Canvas; -import android.view.MotionEvent; - -public abstract class OverlayRenderer implements RenderOverlay.Renderer { - - private static final String TAG = "CAM OverlayRenderer"; - protected RenderOverlay mOverlay; - - protected int mLeft, mTop, mRight, mBottom; - - protected boolean mVisible; - - public void setVisible(boolean vis) { - mVisible = vis; - update(); - } - - public boolean isVisible() { - return mVisible; - } - - // default does not handle touch - @Override - public boolean handlesTouch() { - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent evt) { - return false; - } - - public abstract void onDraw(Canvas canvas); - - public void draw(Canvas canvas) { - if (mVisible) { - onDraw(canvas); - } - } - - @Override - public void setOverlay(RenderOverlay overlay) { - mOverlay = overlay; - } - - @Override - public void layout(int left, int top, int right, int bottom) { - mLeft = left; - mRight = right; - mTop = top; - mBottom = bottom; - } - - protected Context getContext() { - if (mOverlay != null) { - return mOverlay.getContext(); - } else { - return null; - } - } - - public int getWidth() { - return mRight - mLeft; - } - - public int getHeight() { - return mBottom - mTop; - } - - protected void update() { - if (mOverlay != null) { - mOverlay.update(); - } - } - -} diff --git a/src/com/android/camera/ui/PieItem.java b/src/com/android/camera/ui/PieItem.java deleted file mode 100644 index 47fe06758..000000000 --- a/src/com/android/camera/ui/PieItem.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2012 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.Canvas; -import android.graphics.Path; -import android.graphics.drawable.Drawable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Pie menu item - */ -public class PieItem { - - public static interface OnClickListener { - void onClick(PieItem item); - } - - private Drawable mDrawable; - private int level; - - private boolean mSelected; - private boolean mEnabled; - private List<PieItem> mItems; - private Path mPath; - private OnClickListener mOnClickListener; - private float mAlpha; - private CharSequence mLabel; - - // Gray out the view when disabled - private static final float ENABLED_ALPHA = 1; - private static final float DISABLED_ALPHA = (float) 0.3; - private boolean mChangeAlphaWhenDisabled = true; - - public PieItem(Drawable drawable, int level) { - mDrawable = drawable; - this.level = level; - if (drawable != null) { - setAlpha(1f); - } - mEnabled = true; - } - - public void setLabel(CharSequence txt) { - mLabel = txt; - } - - public CharSequence getLabel() { - return mLabel; - } - - public boolean hasItems() { - return mItems != null; - } - - public List<PieItem> getItems() { - return mItems; - } - - public void addItem(PieItem item) { - if (mItems == null) { - mItems = new ArrayList<PieItem>(); - } - mItems.add(item); - } - - public void clearItems() { - mItems = null; - } - - public void setLevel(int level) { - this.level = level; - } - - public void setPath(Path p) { - mPath = p; - } - - public Path getPath() { - return mPath; - } - - public void setChangeAlphaWhenDisabled (boolean enable) { - mChangeAlphaWhenDisabled = enable; - } - - public void setAlpha(float alpha) { - mAlpha = alpha; - mDrawable.setAlpha((int) (255 * alpha)); - } - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - if (mChangeAlphaWhenDisabled) { - if (mEnabled) { - setAlpha(ENABLED_ALPHA); - } else { - setAlpha(DISABLED_ALPHA); - } - } - } - - public boolean isEnabled() { - return mEnabled; - } - - public void setSelected(boolean s) { - mSelected = s; - } - - public boolean isSelected() { - return mSelected; - } - - public int getLevel() { - return level; - } - - - public void setOnClickListener(OnClickListener listener) { - mOnClickListener = listener; - } - - public void performClick() { - if (mOnClickListener != null) { - mOnClickListener.onClick(this); - } - } - - public int getIntrinsicWidth() { - return mDrawable.getIntrinsicWidth(); - } - - public int getIntrinsicHeight() { - return mDrawable.getIntrinsicHeight(); - } - - public void setBounds(int left, int top, int right, int bottom) { - mDrawable.setBounds(left, top, right, bottom); - } - - public void draw(Canvas canvas) { - mDrawable.draw(canvas); - } - - public void setImageResource(Context context, int resId) { - Drawable d = context.getResources().getDrawable(resId).mutate(); - d.setBounds(mDrawable.getBounds()); - mDrawable = d; - setAlpha(mAlpha); - } - -} diff --git a/src/com/android/camera/ui/PieMenuButton.java b/src/com/android/camera/ui/PieMenuButton.java deleted file mode 100644 index 0e23226b2..000000000 --- a/src/com/android/camera/ui/PieMenuButton.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 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.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -public class PieMenuButton extends View { - private boolean mPressed; - private boolean mReadyToClick = false; - public PieMenuButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - mPressed = isPressed(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - boolean handled = super.onTouchEvent(event); - if (MotionEvent.ACTION_UP == event.getAction() && mPressed) { - // Perform a customized click as soon as the ACTION_UP event - // is received. The reason for doing this is that Framework - // delays the performClick() call after ACTION_UP. But we do not - // want the delay because it affects an important state change - // for PieRenderer. - mReadyToClick = true; - performClick(); - } - return handled; - } - - @Override - public boolean performClick() { - if (mReadyToClick) { - // We only respond to our customized click which happens right - // after ACTION_UP event is received, with no delay. - mReadyToClick = false; - return super.performClick(); - } - return false; - } -};
\ No newline at end of file diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java deleted file mode 100644 index c78107ce9..000000000 --- a/src/com/android/camera/ui/PieRenderer.java +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * Copyright (C) 2012 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.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.ValueAnimator; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.PointF; -import android.graphics.RectF; -import android.os.Handler; -import android.os.Message; -import android.util.FloatMath; -import android.view.MotionEvent; -import android.view.ViewConfiguration; -import android.view.animation.Animation; -import android.view.animation.Transformation; - -import com.android.camera.drawable.TextDrawable; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.List; - -public class PieRenderer extends OverlayRenderer - implements FocusIndicator { - - private static final String TAG = "CAM Pie"; - - // Sometimes continuous autofocus starts and stops several times quickly. - // These states are used to make sure the animation is run for at least some - // time. - private volatile int mState; - private ScaleAnimation mAnimation = new ScaleAnimation(); - private static final int STATE_IDLE = 0; - private static final int STATE_FOCUSING = 1; - private static final int STATE_FINISHING = 2; - private static final int STATE_PIE = 8; - - private static final float MATH_PI_2 = (float)(Math.PI / 2); - - private Runnable mDisappear = new Disappear(); - private Animation.AnimationListener mEndAction = new EndAction(); - private static final int SCALING_UP_TIME = 600; - private static final int SCALING_DOWN_TIME = 100; - private static final int DISAPPEAR_TIMEOUT = 200; - private static final int DIAL_HORIZONTAL = 157; - // fade out timings - private static final int PIE_FADE_OUT_DURATION = 600; - - private static final long PIE_FADE_IN_DURATION = 200; - private static final long PIE_XFADE_DURATION = 200; - private static final long PIE_SELECT_FADE_DURATION = 300; - private static final long PIE_OPEN_SUB_DELAY = 400; - private static final long PIE_SLICE_DURATION = 80; - - private static final int MSG_OPEN = 0; - private static final int MSG_CLOSE = 1; - private static final int MSG_OPENSUBMENU = 2; - - protected static float CENTER = (float) Math.PI / 2; - protected static float RAD24 = (float)(24 * Math.PI / 180); - protected static final float SWEEP_SLICE = 0.14f; - protected static final float SWEEP_ARC = 0.23f; - - // geometry - private int mRadius; - private int mRadiusInc; - - // the detection if touch is inside a slice is offset - // inbounds by this amount to allow the selection to show before the - // finger covers it - private int mTouchOffset; - - private List<PieItem> mOpen; - - private Paint mSelectedPaint; - private Paint mSubPaint; - private Paint mMenuArcPaint; - - // touch handling - private PieItem mCurrentItem; - - private Paint mFocusPaint; - private int mSuccessColor; - private int mFailColor; - private int mCircleSize; - private int mFocusX; - private int mFocusY; - private int mCenterX; - private int mCenterY; - private int mArcCenterY; - private int mSliceCenterY; - private int mPieCenterX; - private int mPieCenterY; - private int mSliceRadius; - private int mArcRadius; - private int mArcOffset; - - private int mDialAngle; - private RectF mCircle; - private RectF mDial; - private Point mPoint1; - private Point mPoint2; - private int mStartAnimationAngle; - private boolean mFocused; - private int mInnerOffset; - private int mOuterStroke; - private int mInnerStroke; - private boolean mTapMode; - private boolean mBlockFocus; - private int mTouchSlopSquared; - private Point mDown; - private boolean mOpening; - private ValueAnimator mXFade; - private ValueAnimator mFadeIn; - private ValueAnimator mFadeOut; - private ValueAnimator mSlice; - private volatile boolean mFocusCancelled; - private PointF mPolar = new PointF(); - private TextDrawable mLabel; - private int mDeadZone; - private int mAngleZone; - private float mCenterAngle; - - - - private Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - switch(msg.what) { - case MSG_OPEN: - if (mListener != null) { - mListener.onPieOpened(mPieCenterX, mPieCenterY); - } - break; - case MSG_CLOSE: - if (mListener != null) { - mListener.onPieClosed(); - } - break; - case MSG_OPENSUBMENU: - onEnterOpen(); - break; - } - - } - }; - - private PieListener mListener; - - static public interface PieListener { - public void onPieOpened(int centerX, int centerY); - public void onPieClosed(); - } - - public void setPieListener(PieListener pl) { - mListener = pl; - } - - public PieRenderer(Context context) { - init(context); - } - - private void init(Context ctx) { - setVisible(false); - mOpen = new ArrayList<PieItem>(); - mOpen.add(new PieItem(null, 0)); - Resources res = ctx.getResources(); - mRadius = (int) res.getDimensionPixelSize(R.dimen.pie_radius_start); - mRadiusInc = (int) res.getDimensionPixelSize(R.dimen.pie_radius_increment); - mCircleSize = mRadius - res.getDimensionPixelSize(R.dimen.focus_radius_offset); - mTouchOffset = (int) res.getDimensionPixelSize(R.dimen.pie_touch_offset); - mSelectedPaint = new Paint(); - mSelectedPaint.setColor(Color.argb(255, 51, 181, 229)); - mSelectedPaint.setAntiAlias(true); - mSubPaint = new Paint(); - mSubPaint.setAntiAlias(true); - mSubPaint.setColor(Color.argb(200, 250, 230, 128)); - mFocusPaint = new Paint(); - mFocusPaint.setAntiAlias(true); - mFocusPaint.setColor(Color.WHITE); - mFocusPaint.setStyle(Paint.Style.STROKE); - mSuccessColor = Color.GREEN; - mFailColor = Color.RED; - mCircle = new RectF(); - mDial = new RectF(); - mPoint1 = new Point(); - mPoint2 = new Point(); - mInnerOffset = res.getDimensionPixelSize(R.dimen.focus_inner_offset); - mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke); - mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke); - mState = STATE_IDLE; - mBlockFocus = false; - mTouchSlopSquared = ViewConfiguration.get(ctx).getScaledTouchSlop(); - mTouchSlopSquared = mTouchSlopSquared * mTouchSlopSquared; - mDown = new Point(); - mMenuArcPaint = new Paint(); - mMenuArcPaint.setAntiAlias(true); - mMenuArcPaint.setColor(Color.argb(140, 255, 255, 255)); - mMenuArcPaint.setStrokeWidth(10); - mMenuArcPaint.setStyle(Paint.Style.STROKE); - mSliceRadius = res.getDimensionPixelSize(R.dimen.pie_item_radius); - mArcRadius = res.getDimensionPixelSize(R.dimen.pie_arc_radius); - mArcOffset = res.getDimensionPixelSize(R.dimen.pie_arc_offset); - mLabel = new TextDrawable(res); - mLabel.setDropShadow(true); - mDeadZone = res.getDimensionPixelSize(R.dimen.pie_deadzone_width); - mAngleZone = res.getDimensionPixelSize(R.dimen.pie_anglezone_width); - } - - private PieItem getRoot() { - return mOpen.get(0); - } - - public boolean showsItems() { - return mTapMode; - } - - public void addItem(PieItem item) { - // add the item to the pie itself - getRoot().addItem(item); - } - - public void clearItems() { - getRoot().clearItems(); - } - - public void showInCenter() { - if ((mState == STATE_PIE) && isVisible()) { - mTapMode = false; - show(false); - } else { - if (mState != STATE_IDLE) { - cancelFocus(); - } - mState = STATE_PIE; - resetPieCenter(); - setCenter(mPieCenterX, mPieCenterY); - mTapMode = true; - show(true); - } - } - - public void hide() { - show(false); - } - - /** - * guaranteed has center set - * @param show - */ - private void show(boolean show) { - if (show) { - if (mXFade != null) { - mXFade.cancel(); - } - mState = STATE_PIE; - // ensure clean state - mCurrentItem = null; - PieItem root = getRoot(); - for (PieItem openItem : mOpen) { - if (openItem.hasItems()) { - for (PieItem item : openItem.getItems()) { - item.setSelected(false); - } - } - } - mLabel.setText(""); - mOpen.clear(); - mOpen.add(root); - layoutPie(); - fadeIn(); - } else { - mState = STATE_IDLE; - mTapMode = false; - if (mXFade != null) { - mXFade.cancel(); - } - if (mLabel != null) { - mLabel.setText(""); - } - } - setVisible(show); - mHandler.sendEmptyMessage(show ? MSG_OPEN : MSG_CLOSE); - } - - public boolean isOpen() { - return mState == STATE_PIE && isVisible(); - } - - private void fadeIn() { - mFadeIn = new ValueAnimator(); - mFadeIn.setFloatValues(0f, 1f); - mFadeIn.setDuration(PIE_FADE_IN_DURATION); - // linear interpolation - mFadeIn.setInterpolator(null); - mFadeIn.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - mFadeIn = null; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mFadeIn.start(); - } - - public void setCenter(int x, int y) { - mPieCenterX = x; - mPieCenterY = y; - mSliceCenterY = y + mSliceRadius - mArcOffset; - mArcCenterY = y - mArcOffset + mArcRadius; - } - - @Override - public void layout(int l, int t, int r, int b) { - super.layout(l, t, r, b); - mCenterX = (r - l) / 2; - mCenterY = (b - t) / 2; - - mFocusX = mCenterX; - mFocusY = mCenterY; - resetPieCenter(); - setCircle(mFocusX, mFocusY); - if (isVisible() && mState == STATE_PIE) { - setCenter(mPieCenterX, mPieCenterY); - layoutPie(); - } - } - - private void resetPieCenter() { - mPieCenterX = mCenterX; - mPieCenterY = (int) (getHeight() - 2.5f * mDeadZone); - } - - private void layoutPie() { - mCenterAngle = getCenterAngle(); - layoutItems(0, getRoot().getItems()); - layoutLabel(getLevel()); - } - - private void layoutLabel(int level) { - int x = mPieCenterX - (int) (FloatMath.sin(mCenterAngle - CENTER) - * (mArcRadius + (level + 2) * mRadiusInc)); - int y = mArcCenterY - mArcRadius - (level + 2) * mRadiusInc; - int w = mLabel.getIntrinsicWidth(); - int h = mLabel.getIntrinsicHeight(); - mLabel.setBounds(x - w/2, y - h/2, x + w/2, y + h/2); - } - - private void layoutItems(int level, List<PieItem> items) { - int extend = 1; - Path path = makeSlice(getDegrees(0) + extend, getDegrees(SWEEP_ARC) - extend, - mArcRadius, mArcRadius + mRadiusInc + mRadiusInc / 4, - mPieCenterX, mArcCenterY - level * mRadiusInc); - final int count = items.size(); - int pos = 0; - for (PieItem item : items) { - // shared between items - item.setPath(path); - float angle = getArcCenter(item, pos, count); - int w = item.getIntrinsicWidth(); - int h = item.getIntrinsicHeight(); - // move views to outer border - int r = mArcRadius + mRadiusInc * 2 / 3; - int x = (int) (r * Math.cos(angle)); - int y = mArcCenterY - (level * mRadiusInc) - (int) (r * Math.sin(angle)) - h / 2; - x = mPieCenterX + x - w / 2; - item.setBounds(x, y, x + w, y + h); - item.setLevel(level); - if (item.hasItems()) { - layoutItems(level + 1, item.getItems()); - } - pos++; - } - } - - private Path makeSlice(float start, float end, int inner, int outer, int cx, int cy) { - RectF bb = - new RectF(cx - outer, cy - outer, cx + outer, - cy + outer); - RectF bbi = - new RectF(cx - inner, cy - inner, cx + inner, - cy + inner); - Path path = new Path(); - path.arcTo(bb, start, end - start, true); - path.arcTo(bbi, end, start - end); - path.close(); - return path; - } - - private float getArcCenter(PieItem item, int pos, int count) { - return getCenter(pos, count, SWEEP_ARC); - } - - private float getSliceCenter(PieItem item, int pos, int count) { - float center = (getCenterAngle() - CENTER) * 0.5f + CENTER; - return center + (count - 1) * SWEEP_SLICE / 2f - - pos * SWEEP_SLICE; - } - - private float getCenter(int pos, int count, float sweep) { - return mCenterAngle + (count - 1) * sweep / 2f - pos * sweep; - } - - private float getCenterAngle() { - float center = CENTER; - if (mPieCenterX < mDeadZone + mAngleZone) { - center = CENTER - (mAngleZone - mPieCenterX + mDeadZone) * RAD24 - / (float) mAngleZone; - } else if (mPieCenterX > getWidth() - mDeadZone - mAngleZone) { - center = CENTER + (mPieCenterX - (getWidth() - mDeadZone - mAngleZone)) * RAD24 - / (float) mAngleZone; - } - return center; - } - - /** - * converts a - * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock) - * @return skia angle - */ - private float getDegrees(double angle) { - return (float) (360 - 180 * angle / Math.PI); - } - - private void startFadeOut(final PieItem item) { - if (mFadeIn != null) { - mFadeIn.cancel(); - } - if (mXFade != null) { - mXFade.cancel(); - } - mFadeOut = new ValueAnimator(); - mFadeOut.setFloatValues(1f, 0f); - mFadeOut.setDuration(PIE_FADE_OUT_DURATION); - mFadeOut.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - } - - @Override - public void onAnimationEnd(Animator animator) { - item.performClick(); - mFadeOut = null; - deselect(); - show(false); - mOverlay.setAlpha(1); - } - - @Override - public void onAnimationRepeat(Animator animator) { - } - - @Override - public void onAnimationCancel(Animator animator) { - } - - }); - mFadeOut.start(); - } - - // root does not count - private boolean hasOpenItem() { - return mOpen.size() > 1; - } - - // pop an item of the open item stack - private PieItem closeOpenItem() { - PieItem item = getOpenItem(); - mOpen.remove(mOpen.size() -1); - return item; - } - - private PieItem getOpenItem() { - return mOpen.get(mOpen.size() - 1); - } - - // return the children either the root or parent of the current open item - private PieItem getParent() { - return mOpen.get(Math.max(0, mOpen.size() - 2)); - } - - private int getLevel() { - return mOpen.size() - 1; - } - - @Override - public void onDraw(Canvas canvas) { - float alpha = 1; - if (mXFade != null) { - alpha = (Float) mXFade.getAnimatedValue(); - } else if (mFadeIn != null) { - alpha = (Float) mFadeIn.getAnimatedValue(); - } else if (mFadeOut != null) { - alpha = (Float) mFadeOut.getAnimatedValue(); - } - int state = canvas.save(); - if (mFadeIn != null) { - float sf = 0.9f + alpha * 0.1f; - canvas.scale(sf, sf, mPieCenterX, mPieCenterY); - } - if (mState != STATE_PIE) { - drawFocus(canvas); - } - if (mState == STATE_FINISHING) { - canvas.restoreToCount(state); - return; - } - if (mState != STATE_PIE) return; - if (!hasOpenItem() || (mXFade != null)) { - // draw base menu - drawArc(canvas, getLevel(), getParent()); - List<PieItem> items = getParent().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem item : getParent().getItems()) { - drawItem(Math.max(0, mOpen.size() - 2), pos, count, canvas, item, alpha); - pos++; - } - mLabel.draw(canvas); - } - if (hasOpenItem()) { - int level = getLevel(); - drawArc(canvas, level, getOpenItem()); - List<PieItem> items = getOpenItem().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem inner : items) { - if (mFadeOut != null) { - drawItem(level, pos, count, canvas, inner, alpha); - } else { - drawItem(level, pos, count, canvas, inner, (mXFade != null) ? (1 - 0.5f * alpha) : 1); - } - pos++; - } - mLabel.draw(canvas); - } - canvas.restoreToCount(state); - } - - private void drawArc(Canvas canvas, int level, PieItem item) { - // arc - if (mState == STATE_PIE) { - final int count = item.getItems().size(); - float start = mCenterAngle + (count * SWEEP_ARC / 2f); - float end = mCenterAngle - (count * SWEEP_ARC / 2f); - int cy = mArcCenterY - level * mRadiusInc; - canvas.drawArc(new RectF(mPieCenterX - mArcRadius, cy - mArcRadius, - mPieCenterX + mArcRadius, cy + mArcRadius), - getDegrees(end), getDegrees(start) - getDegrees(end), false, mMenuArcPaint); - } - } - - private void drawItem(int level, int pos, int count, Canvas canvas, PieItem item, float alpha) { - if (mState == STATE_PIE) { - if (item.getPath() != null) { - int y = mArcCenterY - level * mRadiusInc; - if (item.isSelected()) { - Paint p = mSelectedPaint; - int state = canvas.save(); - float angle = 0; - if (mSlice != null) { - angle = (Float) mSlice.getAnimatedValue(); - } else { - angle = getArcCenter(item, pos, count) - SWEEP_ARC / 2f; - } - angle = getDegrees(angle); - canvas.rotate(angle, mPieCenterX, y); - if (mFadeOut != null) { - p.setAlpha((int)(255 * alpha)); - } - canvas.drawPath(item.getPath(), p); - if (mFadeOut != null) { - p.setAlpha(255); - } - canvas.restoreToCount(state); - } - if (mFadeOut == null) { - alpha = alpha * (item.isEnabled() ? 1 : 0.3f); - // draw the item view - item.setAlpha(alpha); - } - item.draw(canvas); - } - } - } - - @Override - public boolean onTouchEvent(MotionEvent evt) { - float x = evt.getX(); - float y = evt.getY(); - int action = evt.getActionMasked(); - getPolar(x, y, !mTapMode, mPolar); - if (MotionEvent.ACTION_DOWN == action) { - if ((x < mDeadZone) || (x > getWidth() - mDeadZone)) { - return false; - } - mDown.x = (int) evt.getX(); - mDown.y = (int) evt.getY(); - mOpening = false; - if (mTapMode) { - PieItem item = findItem(mPolar); - if ((item != null) && (mCurrentItem != item)) { - mState = STATE_PIE; - onEnter(item); - } - } else { - setCenter((int) x, (int) y); - show(true); - } - return true; - } else if (MotionEvent.ACTION_UP == action) { - if (isVisible()) { - PieItem item = mCurrentItem; - if (mTapMode) { - item = findItem(mPolar); - if (mOpening) { - mOpening = false; - return true; - } - } - if (item == null) { - mTapMode = false; - show(false); - } else if (!mOpening && !item.hasItems()) { - startFadeOut(item); - mTapMode = false; - } else { - mTapMode = true; - } - return true; - } - } else if (MotionEvent.ACTION_CANCEL == action) { - if (isVisible() || mTapMode) { - show(false); - } - deselect(); - mHandler.removeMessages(MSG_OPENSUBMENU); - return false; - } else if (MotionEvent.ACTION_MOVE == action) { - if (pulledToCenter(mPolar)) { - mHandler.removeMessages(MSG_OPENSUBMENU); - if (hasOpenItem()) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - closeOpenItem(); - mCurrentItem = null; - } else { - deselect(); - } - mLabel.setText(""); - return false; - } - PieItem item = findItem(mPolar); - boolean moved = hasMoved(evt); - if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) { - mHandler.removeMessages(MSG_OPENSUBMENU); - // only select if we didn't just open or have moved past slop - if (moved) { - // switch back to swipe mode - mTapMode = false; - } - onEnterSelect(item); - mHandler.sendEmptyMessageDelayed(MSG_OPENSUBMENU, PIE_OPEN_SUB_DELAY); - } - } - return false; - } - - private boolean pulledToCenter(PointF polarCoords) { - return polarCoords.y < mArcRadius - mRadiusInc; - } - - private boolean inside(PointF polar, PieItem item, int pos, int count) { - float start = getSliceCenter(item, pos, count) - SWEEP_SLICE / 2f; - boolean res = (mArcRadius < polar.y) - && (start < polar.x) - && (start + SWEEP_SLICE > polar.x) - && (!mTapMode || (mArcRadius + mRadiusInc > polar.y)); - return res; - } - - private void getPolar(float x, float y, boolean useOffset, PointF res) { - // get angle and radius from x/y - res.x = (float) Math.PI / 2; - x = x - mPieCenterX; - float y1 = mSliceCenterY - getLevel() * mRadiusInc - y; - float y2 = mArcCenterY - getLevel() * mRadiusInc - y; - res.y = (float) Math.sqrt(x * x + y2 * y2); - if (x != 0) { - res.x = (float) Math.atan2(y1, x); - if (res.x < 0) { - res.x = (float) (2 * Math.PI + res.x); - } - } - res.y = res.y + (useOffset ? mTouchOffset : 0); - } - - private boolean hasMoved(MotionEvent e) { - return mTouchSlopSquared < (e.getX() - mDown.x) * (e.getX() - mDown.x) - + (e.getY() - mDown.y) * (e.getY() - mDown.y); - } - - private void onEnterSelect(PieItem item) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (item != null && item.isEnabled()) { - moveSelection(mCurrentItem, item); - item.setSelected(true); - mCurrentItem = item; - mLabel.setText(mCurrentItem.getLabel()); - layoutLabel(getLevel()); - } else { - mCurrentItem = null; - } - } - - private void onEnterOpen() { - if ((mCurrentItem != null) && (mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) { - openCurrentItem(); - } - } - - /** - * enter a slice for a view - * updates model only - * @param item - */ - private void onEnter(PieItem item) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (item != null && item.isEnabled()) { - item.setSelected(true); - mCurrentItem = item; - mLabel.setText(mCurrentItem.getLabel()); - if ((mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) { - openCurrentItem(); - layoutLabel(getLevel()); - } - } else { - mCurrentItem = null; - } - } - - private void deselect() { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (hasOpenItem()) { - PieItem item = closeOpenItem(); - onEnter(item); - } else { - mCurrentItem = null; - } - } - - private int getItemPos(PieItem target) { - List<PieItem> items = getOpenItem().getItems(); - return items.indexOf(target); - } - - private int getCurrentCount() { - return getOpenItem().getItems().size(); - } - - private void moveSelection(PieItem from, PieItem to) { - final int count = getCurrentCount(); - final int fromPos = getItemPos(from); - final int toPos = getItemPos(to); - if (fromPos != -1 && toPos != -1) { - float startAngle = getArcCenter(from, getItemPos(from), count) - - SWEEP_ARC / 2f; - float endAngle = getArcCenter(to, getItemPos(to), count) - - SWEEP_ARC / 2f; - mSlice = new ValueAnimator(); - mSlice.setFloatValues(startAngle, endAngle); - // linear interpolater - mSlice.setInterpolator(null); - mSlice.setDuration(PIE_SLICE_DURATION); - mSlice.addListener(new AnimatorListener() { - @Override - public void onAnimationEnd(Animator arg0) { - mSlice = null; - } - - @Override - public void onAnimationRepeat(Animator arg0) { - } - - @Override - public void onAnimationStart(Animator arg0) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mSlice.start(); - } - } - - private void openCurrentItem() { - if ((mCurrentItem != null) && mCurrentItem.hasItems()) { - mOpen.add(mCurrentItem); - layoutLabel(getLevel()); - mOpening = true; - if (mFadeIn != null) { - mFadeIn.cancel(); - } - mXFade = new ValueAnimator(); - mXFade.setFloatValues(1f, 0f); - mXFade.setDuration(PIE_XFADE_DURATION); - // Linear interpolation - mXFade.setInterpolator(null); - final PieItem ci = mCurrentItem; - mXFade.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - mXFade = null; - ci.setSelected(false); - mOpening = false; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mXFade.start(); - } - } - - /** - * @param polar x: angle, y: dist - * @return the item at angle/dist or null - */ - private PieItem findItem(PointF polar) { - // find the matching item: - List<PieItem> items = getOpenItem().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem item : items) { - if (inside(polar, item, pos, count)) { - return item; - } - pos++; - } - return null; - } - - - @Override - public boolean handlesTouch() { - return true; - } - - // focus specific code - - public void setBlockFocus(boolean blocked) { - mBlockFocus = blocked; - if (blocked) { - clear(); - } - } - - public void setFocus(int x, int y) { - mFocusX = x; - mFocusY = y; - setCircle(mFocusX, mFocusY); - } - - public void alignFocus(int x, int y) { - mOverlay.removeCallbacks(mDisappear); - mAnimation.cancel(); - mAnimation.reset(); - mFocusX = x; - mFocusY = y; - mDialAngle = DIAL_HORIZONTAL; - setCircle(x, y); - mFocused = false; - } - - public int getSize() { - return 2 * mCircleSize; - } - - private int getRandomRange() { - return (int)(-60 + 120 * Math.random()); - } - - private void setCircle(int cx, int cy) { - mCircle.set(cx - mCircleSize, cy - mCircleSize, - cx + mCircleSize, cy + mCircleSize); - mDial.set(cx - mCircleSize + mInnerOffset, cy - mCircleSize + mInnerOffset, - cx + mCircleSize - mInnerOffset, cy + mCircleSize - mInnerOffset); - } - - public void drawFocus(Canvas canvas) { - if (mBlockFocus) return; - mFocusPaint.setStrokeWidth(mOuterStroke); - canvas.drawCircle((float) mFocusX, (float) mFocusY, (float) mCircleSize, mFocusPaint); - if (mState == STATE_PIE) return; - int color = mFocusPaint.getColor(); - if (mState == STATE_FINISHING) { - mFocusPaint.setColor(mFocused ? mSuccessColor : mFailColor); - } - mFocusPaint.setStrokeWidth(mInnerStroke); - drawLine(canvas, mDialAngle, mFocusPaint); - drawLine(canvas, mDialAngle + 45, mFocusPaint); - drawLine(canvas, mDialAngle + 180, mFocusPaint); - drawLine(canvas, mDialAngle + 225, mFocusPaint); - canvas.save(); - // rotate the arc instead of its offset to better use framework's shape caching - canvas.rotate(mDialAngle, mFocusX, mFocusY); - canvas.drawArc(mDial, 0, 45, false, mFocusPaint); - canvas.drawArc(mDial, 180, 45, false, mFocusPaint); - canvas.restore(); - mFocusPaint.setColor(color); - } - - private void drawLine(Canvas canvas, int angle, Paint p) { - convertCart(angle, mCircleSize - mInnerOffset, mPoint1); - convertCart(angle, mCircleSize - mInnerOffset + mInnerOffset / 3, mPoint2); - canvas.drawLine(mPoint1.x + mFocusX, mPoint1.y + mFocusY, - mPoint2.x + mFocusX, mPoint2.y + mFocusY, p); - } - - private static void convertCart(int angle, int radius, Point out) { - double a = 2 * Math.PI * (angle % 360) / 360; - out.x = (int) (radius * Math.cos(a) + 0.5); - out.y = (int) (radius * Math.sin(a) + 0.5); - } - - @Override - public void showStart() { - if (mState == STATE_PIE) return; - cancelFocus(); - mStartAnimationAngle = 67; - int range = getRandomRange(); - startAnimation(SCALING_UP_TIME, - false, mStartAnimationAngle, mStartAnimationAngle + range); - mState = STATE_FOCUSING; - } - - @Override - public void showSuccess(boolean timeout) { - if (mState == STATE_FOCUSING) { - startAnimation(SCALING_DOWN_TIME, - timeout, mStartAnimationAngle); - mState = STATE_FINISHING; - mFocused = true; - } - } - - @Override - public void showFail(boolean timeout) { - if (mState == STATE_FOCUSING) { - startAnimation(SCALING_DOWN_TIME, - timeout, mStartAnimationAngle); - mState = STATE_FINISHING; - mFocused = false; - } - } - - private void cancelFocus() { - mFocusCancelled = true; - mOverlay.removeCallbacks(mDisappear); - if (mAnimation != null && !mAnimation.hasEnded()) { - mAnimation.cancel(); - } - mFocusCancelled = false; - mFocused = false; - mState = STATE_IDLE; - } - - @Override - public void clear() { - if (mState == STATE_PIE) return; - cancelFocus(); - mOverlay.post(mDisappear); - } - - private void startAnimation(long duration, boolean timeout, - float toScale) { - startAnimation(duration, timeout, mDialAngle, - toScale); - } - - private void startAnimation(long duration, boolean timeout, - float fromScale, float toScale) { - setVisible(true); - mAnimation.reset(); - mAnimation.setDuration(duration); - mAnimation.setScale(fromScale, toScale); - mAnimation.setAnimationListener(timeout ? mEndAction : null); - mOverlay.startAnimation(mAnimation); - update(); - } - - private class EndAction implements Animation.AnimationListener { - @Override - public void onAnimationEnd(Animation animation) { - // Keep the focus indicator for some time. - if (!mFocusCancelled) { - mOverlay.postDelayed(mDisappear, DISAPPEAR_TIMEOUT); - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - - @Override - public void onAnimationStart(Animation animation) { - } - } - - private class Disappear implements Runnable { - @Override - public void run() { - if (mState == STATE_PIE) return; - setVisible(false); - mFocusX = mCenterX; - mFocusY = mCenterY; - mState = STATE_IDLE; - setCircle(mFocusX, mFocusY); - mFocused = false; - } - } - - private class ScaleAnimation extends Animation { - private float mFrom = 1f; - private float mTo = 1f; - - public ScaleAnimation() { - setFillAfter(true); - } - - public void setScale(float from, float to) { - mFrom = from; - mTo = to; - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - mDialAngle = (int)(mFrom + (mTo - mFrom) * interpolatedTime); - } - } - -} diff --git a/src/com/android/camera/ui/PopupManager.java b/src/com/android/camera/ui/PopupManager.java deleted file mode 100644 index 0dcf34fd7..000000000 --- a/src/com/android/camera/ui/PopupManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2011 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.view.View; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * A manager which notifies the event of a new popup in order to dismiss the - * old popup if exists. - */ -public class PopupManager { - private static HashMap<Context, PopupManager> sMap = - new HashMap<Context, PopupManager>(); - - public interface OnOtherPopupShowedListener { - public void onOtherPopupShowed(); - } - - private PopupManager() {} - - private ArrayList<OnOtherPopupShowedListener> mListeners = new ArrayList<OnOtherPopupShowedListener>(); - - public void notifyShowPopup(View view) { - for (OnOtherPopupShowedListener listener : mListeners) { - if ((View) listener != view) { - listener.onOtherPopupShowed(); - } - } - } - - public void setOnOtherPopupShowedListener(OnOtherPopupShowedListener listener) { - mListeners.add(listener); - } - - public static PopupManager getInstance(Context context) { - PopupManager instance = sMap.get(context); - if (instance == null) { - instance = new PopupManager(); - sMap.put(context, instance); - } - return instance; - } - - public static void removeInstance(Context context) { - PopupManager instance = sMap.get(context); - sMap.remove(context); - } -} diff --git a/src/com/android/camera/ui/PreviewSurfaceView.java b/src/com/android/camera/ui/PreviewSurfaceView.java deleted file mode 100644 index 9a428e23c..000000000 --- a/src/com/android/camera/ui/PreviewSurfaceView.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 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.util.AttributeSet; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.ViewGroup; - -import com.android.gallery3d.common.ApiHelper; - -public class PreviewSurfaceView extends SurfaceView { - public PreviewSurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - setZOrderMediaOverlay(true); - getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - } - - public void shrink() { - setLayoutSize(1); - } - - public void expand() { - setLayoutSize(ViewGroup.LayoutParams.MATCH_PARENT); - } - - private void setLayoutSize(int size) { - ViewGroup.LayoutParams p = getLayoutParams(); - if (p.width != size || p.height != size) { - p.width = size; - p.height = size; - setLayoutParams(p); - } - } -} diff --git a/src/com/android/camera/ui/RenderOverlay.java b/src/com/android/camera/ui/RenderOverlay.java deleted file mode 100644 index d82ce18b6..000000000 --- a/src/com/android/camera/ui/RenderOverlay.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2012 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.Canvas; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.PreviewGestures; - -import java.util.ArrayList; -import java.util.List; - -public class RenderOverlay extends FrameLayout { - - private static final String TAG = "CAM_Overlay"; - - interface Renderer { - - public boolean handlesTouch(); - public boolean onTouchEvent(MotionEvent evt); - public void setOverlay(RenderOverlay overlay); - public void layout(int left, int top, int right, int bottom); - public void draw(Canvas canvas); - - } - - private RenderView mRenderView; - private List<Renderer> mClients; - private PreviewGestures mGestures; - // reverse list of touch clients - private List<Renderer> mTouchClients; - private int[] mPosition = new int[2]; - - public RenderOverlay(Context context, AttributeSet attrs) { - super(context, attrs); - mRenderView = new RenderView(context); - addView(mRenderView, new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - mClients = new ArrayList<Renderer>(10); - mTouchClients = new ArrayList<Renderer>(10); - setWillNotDraw(false); - } - - public void setGestures(PreviewGestures gestures) { - mGestures = gestures; - } - - public void addRenderer(Renderer renderer) { - mClients.add(renderer); - renderer.setOverlay(this); - if (renderer.handlesTouch()) { - mTouchClients.add(0, renderer); - } - renderer.layout(getLeft(), getTop(), getRight(), getBottom()); - } - - public void addRenderer(int pos, Renderer renderer) { - mClients.add(pos, renderer); - renderer.setOverlay(this); - renderer.layout(getLeft(), getTop(), getRight(), getBottom()); - } - - public void remove(Renderer renderer) { - mClients.remove(renderer); - renderer.setOverlay(null); - } - - public int getClientSize() { - return mClients.size(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent m) { - if (mGestures != null) { - if (!mGestures.isEnabled()) return false; - mGestures.dispatchTouch(m); - } - return true; - } - - public boolean directDispatchTouch(MotionEvent m, Renderer target) { - mRenderView.setTouchTarget(target); - boolean res = mRenderView.dispatchTouchEvent(m); - mRenderView.setTouchTarget(null); - return res; - } - - private void adjustPosition() { - getLocationInWindow(mPosition); - } - - public int getWindowPositionX() { - return mPosition[0]; - } - - public int getWindowPositionY() { - return mPosition[1]; - } - - public void update() { - mRenderView.invalidate(); - } - - private class RenderView extends View { - - private Renderer mTouchTarget; - - public RenderView(Context context) { - super(context); - setWillNotDraw(false); - } - - public void setTouchTarget(Renderer target) { - mTouchTarget = target; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent evt) { - - if (mTouchTarget != null) { - return mTouchTarget.onTouchEvent(evt); - } - if (mTouchClients != null) { - boolean res = false; - for (Renderer client : mTouchClients) { - res |= client.onTouchEvent(evt); - } - return res; - } - return false; - } - - @Override - public void onLayout(boolean changed, int left, int top, int right, int bottom) { - adjustPosition(); - super.onLayout(changed, left, top, right, bottom); - if (mClients == null) return; - for (Renderer renderer : mClients) { - renderer.layout(left, top, right, bottom); - } - } - - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - if (mClients == null) return; - boolean redraw = false; - for (Renderer renderer : mClients) { - renderer.draw(canvas); - redraw = redraw || ((OverlayRenderer) renderer).isVisible(); - } - if (redraw) { - invalidate(); - } - } - } - -} diff --git a/src/com/android/camera/ui/Rotatable.java b/src/com/android/camera/ui/Rotatable.java deleted file mode 100644 index 6d428b8c6..000000000 --- a/src/com/android/camera/ui/Rotatable.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2011 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; - -public interface Rotatable { - // Set parameter 'animation' to true to have animation when rotation. - public void setOrientation(int orientation, boolean animation); -} diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java deleted file mode 100644 index 965d62a90..000000000 --- a/src/com/android/camera/ui/RotatableLayout.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2013 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.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.android.camera.Util; - -/* RotatableLayout rotates itself as well as all its children when orientation - * changes. Specifically, when going from portrait to landscape, camera - * controls move from the bottom of the screen to right side of the screen - * (i.e. counter clockwise). Similarly, when the screen changes to portrait, we - * need to move the controls from right side to the bottom of the screen, which - * is a clockwise rotation. - */ - -public class RotatableLayout extends FrameLayout { - - private static final String TAG = "RotatableLayout"; - // Initial orientation of the layout (ORIENTATION_PORTRAIT, or ORIENTATION_LANDSCAPE) - private int mInitialOrientation; - private int mPrevRotation; - private RotationListener mListener = null; - public interface RotationListener { - public void onRotation(int rotation); - } - public RotatableLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - public RotatableLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - public RotatableLayout(Context context) { - super(context); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - @Override - public void onAttachedToWindow() { - mPrevRotation = Util.getDisplayRotation((Activity) getContext()); - // check if there is any rotation before the view is attached to window - int currentOrientation = getResources().getConfiguration().orientation; - int orientation = getUnifiedRotation(); - if (mInitialOrientation == currentOrientation && orientation < 180) { - return; - } - - if (mInitialOrientation == Configuration.ORIENTATION_LANDSCAPE - && currentOrientation == Configuration.ORIENTATION_PORTRAIT) { - rotateLayout(true); - } else if (mInitialOrientation == Configuration.ORIENTATION_PORTRAIT - && currentOrientation == Configuration.ORIENTATION_LANDSCAPE) { - rotateLayout(false); - } - // In reverse landscape and reverse portrait, camera controls will be laid out - // on the wrong side of the screen. We need to make adjustment to move the controls - // to the USB side - if (orientation >= 180) { - flipChildren(); - } - } - - protected int getUnifiedRotation() { - // all the layout code assumes camera device orientation to be portrait - // adjust rotation for landscape - int orientation = getResources().getConfiguration().orientation; - int rotation = Util.getDisplayRotation((Activity) getContext()); - int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT - : Configuration.ORIENTATION_LANDSCAPE; - if (camOrientation != orientation) { - return (rotation + 90) % 360; - } - return rotation; - } - - public void checkLayoutFlip() { - int currentRotation = Util.getDisplayRotation((Activity) getContext()); - if ((currentRotation - mPrevRotation + 360) % 360 == 180) { - mPrevRotation = currentRotation; - flipChildren(); - getParent().requestLayout(); - } - } - - @Override - public void onWindowVisibilityChanged(int visibility) { - if (visibility == View.VISIBLE) { - // Make sure when coming back from onPause, the layout is rotated correctly - checkLayoutFlip(); - } - } - - @Override - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - int rotation = Util.getDisplayRotation((Activity) getContext()); - int diff = (rotation - mPrevRotation + 360) % 360; - if ( diff == 0) { - // No rotation - return; - } else if (diff == 180) { - // 180-degree rotation - mPrevRotation = rotation; - flipChildren(); - return; - } - // 90 or 270-degree rotation - boolean clockwise = isClockWiseRotation(mPrevRotation, rotation); - mPrevRotation = rotation; - rotateLayout(clockwise); - } - - protected void rotateLayout(boolean clockwise) { - // Change the size of the layout - ViewGroup.LayoutParams lp = getLayoutParams(); - int width = lp.width; - int height = lp.height; - lp.height = width; - lp.width = height; - setLayoutParams(lp); - - // rotate all the children - rotateChildren(clockwise); - } - - protected void rotateChildren(boolean clockwise) { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - rotate(child, clockwise); - } - if (mListener != null) mListener.onRotation(clockwise ? 90 : 270); - } - - protected void flipChildren() { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - flip(child); - } - if (mListener != null) mListener.onRotation(180); - } - - public void setRotationListener(RotationListener listener) { - mListener = listener; - } - - public static boolean isClockWiseRotation(int prevRotation, int currentRotation) { - if (prevRotation == (currentRotation + 90) % 360) { - return true; - } - return false; - } - - public static void rotate(View view, boolean isClockwise) { - if (isClockwise) { - rotateClockwise(view); - } else { - rotateCounterClockwise(view); - } - } - - private static boolean contains(int value, int mask) { - return (value & mask) == mask; - } - - public static void rotateClockwise(View view) { - if (view == null) return; - LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int gravity = lp.gravity; - int ngravity = 0; - // rotate gravity - if (contains(gravity, Gravity.LEFT)) { - ngravity |= Gravity.TOP; - } - if (contains(gravity, Gravity.RIGHT)) { - ngravity |= Gravity.BOTTOM; - } - if (contains(gravity, Gravity.TOP)) { - ngravity |= Gravity.RIGHT; - } - if (contains(gravity, Gravity.BOTTOM)) { - ngravity |= Gravity.LEFT; - } - if (contains(gravity, Gravity.CENTER)) { - ngravity |= Gravity.CENTER; - } - if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { - ngravity |= Gravity.CENTER_VERTICAL; - } - if (contains(gravity, Gravity.CENTER_VERTICAL)) { - ngravity |= Gravity.CENTER_HORIZONTAL; - } - lp.gravity = ngravity; - int ml = lp.leftMargin; - int mr = lp.rightMargin; - int mt = lp.topMargin; - int mb = lp.bottomMargin; - lp.leftMargin = mb; - lp.rightMargin = mt; - lp.topMargin = ml; - lp.bottomMargin = mr; - int width = lp.width; - int height = lp.height; - lp.width = height; - lp.height = width; - view.setLayoutParams(lp); - } - - public static void rotateCounterClockwise(View view) { - if (view == null) return; - LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int gravity = lp.gravity; - int ngravity = 0; - // change gravity - if (contains(gravity, Gravity.RIGHT)) { - ngravity |= Gravity.TOP; - } - if (contains(gravity, Gravity.LEFT)) { - ngravity |= Gravity.BOTTOM; - } - if (contains(gravity, Gravity.TOP)) { - ngravity |= Gravity.LEFT; - } - if (contains(gravity, Gravity.BOTTOM)) { - ngravity |= Gravity.RIGHT; - } - if (contains(gravity, Gravity.CENTER)) { - ngravity |= Gravity.CENTER; - } - if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { - ngravity |= Gravity.CENTER_VERTICAL; - } - if (contains(gravity, Gravity.CENTER_VERTICAL)) { - ngravity |= Gravity.CENTER_HORIZONTAL; - } - lp.gravity = ngravity; - int ml = lp.leftMargin; - int mr = lp.rightMargin; - int mt = lp.topMargin; - int mb = lp.bottomMargin; - lp.leftMargin = mt; - lp.rightMargin = mb; - lp.topMargin = mr; - lp.bottomMargin = ml; - int width = lp.width; - int height = lp.height; - lp.width = height; - lp.height = width; - view.setLayoutParams(lp); - } - - // Rotate a given view 180 degrees - public static void flip(View view) { - rotateClockwise(view); - rotateClockwise(view); - } -}
\ No newline at end of file diff --git a/src/com/android/camera/ui/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java deleted file mode 100644 index 05e1a7c5b..000000000 --- a/src/com/android/camera/ui/RotateImageView.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2009 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.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.TransitionDrawable; -import android.media.ThumbnailUtils; -import android.util.AttributeSet; -import android.view.ViewGroup.LayoutParams; -import android.view.animation.AnimationUtils; -import android.widget.ImageView; - -/** - * A @{code ImageView} which can rotate it's content. - */ -public class RotateImageView extends TwoStateImageView implements Rotatable { - - @SuppressWarnings("unused") - private static final String TAG = "RotateImageView"; - - private static final int ANIMATION_SPEED = 270; // 270 deg/sec - - private int mCurrentDegree = 0; // [0, 359] - private int mStartDegree = 0; - private int mTargetDegree = 0; - - private boolean mClockwise = false, mEnableAnimation = true; - - private long mAnimationStartTime = 0; - private long mAnimationEndTime = 0; - - public RotateImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RotateImageView(Context context) { - super(context); - } - - protected int getDegree() { - return mTargetDegree; - } - - // Rotate the view counter-clockwise - @Override - public void setOrientation(int degree, boolean animation) { - mEnableAnimation = animation; - // make sure in the range of [0, 359] - degree = degree >= 0 ? degree % 360 : degree % 360 + 360; - if (degree == mTargetDegree) return; - - mTargetDegree = degree; - if (mEnableAnimation) { - mStartDegree = mCurrentDegree; - mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis(); - - int diff = mTargetDegree - mCurrentDegree; - diff = diff >= 0 ? diff : 360 + diff; // make it in range [0, 359] - - // Make it in range [-179, 180]. That's the shorted distance between the - // two angles - diff = diff > 180 ? diff - 360 : diff; - - mClockwise = diff >= 0; - mAnimationEndTime = mAnimationStartTime - + Math.abs(diff) * 1000 / ANIMATION_SPEED; - } else { - mCurrentDegree = mTargetDegree; - } - - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - Drawable drawable = getDrawable(); - if (drawable == null) return; - - Rect bounds = drawable.getBounds(); - int w = bounds.right - bounds.left; - int h = bounds.bottom - bounds.top; - - if (w == 0 || h == 0) return; // nothing to draw - - if (mCurrentDegree != mTargetDegree) { - long time = AnimationUtils.currentAnimationTimeMillis(); - if (time < mAnimationEndTime) { - int deltaTime = (int)(time - mAnimationStartTime); - int degree = mStartDegree + ANIMATION_SPEED - * (mClockwise ? deltaTime : -deltaTime) / 1000; - degree = degree >= 0 ? degree % 360 : degree % 360 + 360; - mCurrentDegree = degree; - invalidate(); - } else { - mCurrentDegree = mTargetDegree; - } - } - - int left = getPaddingLeft(); - int top = getPaddingTop(); - int right = getPaddingRight(); - int bottom = getPaddingBottom(); - int width = getWidth() - left - right; - int height = getHeight() - top - bottom; - - int saveCount = canvas.getSaveCount(); - - // Scale down the image first if required. - if ((getScaleType() == ImageView.ScaleType.FIT_CENTER) && - ((width < w) || (height < h))) { - float ratio = Math.min((float) width / w, (float) height / h); - canvas.scale(ratio, ratio, width / 2.0f, height / 2.0f); - } - canvas.translate(left + width / 2, top + height / 2); - canvas.rotate(-mCurrentDegree); - canvas.translate(-w / 2, -h / 2); - drawable.draw(canvas); - canvas.restoreToCount(saveCount); - } - - private Bitmap mThumb; - private Drawable[] mThumbs; - private TransitionDrawable mThumbTransition; - - public void setBitmap(Bitmap bitmap) { - // Make sure uri and original are consistently both null or both - // non-null. - if (bitmap == null) { - mThumb = null; - mThumbs = null; - setImageDrawable(null); - setVisibility(GONE); - return; - } - - LayoutParams param = getLayoutParams(); - final int miniThumbWidth = param.width - - getPaddingLeft() - getPaddingRight(); - final int miniThumbHeight = param.height - - getPaddingTop() - getPaddingBottom(); - mThumb = ThumbnailUtils.extractThumbnail( - bitmap, miniThumbWidth, miniThumbHeight); - Drawable drawable; - if (mThumbs == null || !mEnableAnimation) { - mThumbs = new Drawable[2]; - mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); - setImageDrawable(mThumbs[1]); - } else { - mThumbs[0] = mThumbs[1]; - mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); - mThumbTransition = new TransitionDrawable(mThumbs); - setImageDrawable(mThumbTransition); - mThumbTransition.startTransition(500); - } - setVisibility(VISIBLE); - } -} diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java deleted file mode 100644 index 86f5c814d..000000000 --- a/src/com/android/camera/ui/RotateLayout.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.annotation.TargetApi; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.MotionEventHelper; - -// A RotateLayout is designed to display a single item and provides the -// capabilities to rotate the item. -public class RotateLayout extends ViewGroup implements Rotatable { - @SuppressWarnings("unused") - private static final String TAG = "RotateLayout"; - private int mOrientation; - private Matrix mMatrix = new Matrix(); - protected View mChild; - - public RotateLayout(Context context, AttributeSet attrs) { - super(context, attrs); - // The transparent background here is a workaround of the render issue - // happened when the view is rotated as the device's orientation - // changed. The view looks fine in landscape. After rotation, the view - // is invisible. - setBackgroundResource(android.R.color.transparent); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - protected void onFinishInflate() { - mChild = getChildAt(0); - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - mChild.setPivotX(0); - mChild.setPivotY(0); - } - } - - @Override - protected void onLayout( - boolean change, int left, int top, int right, int bottom) { - int width = right - left; - int height = bottom - top; - switch (mOrientation) { - case 0: - case 180: - mChild.layout(0, 0, width, height); - break; - case 90: - case 270: - mChild.layout(0, 0, height, width); - break; - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (!ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - final int w = getMeasuredWidth(); - final int h = getMeasuredHeight(); - switch (mOrientation) { - case 0: - mMatrix.setTranslate(0, 0); - break; - case 90: - mMatrix.setTranslate(0, -h); - break; - case 180: - mMatrix.setTranslate(-w, -h); - break; - case 270: - mMatrix.setTranslate(-w, 0); - break; - } - mMatrix.postRotate(mOrientation); - event = MotionEventHelper.transformEvent(event, mMatrix); - } - return super.dispatchTouchEvent(event); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - super.dispatchDraw(canvas); - } else { - canvas.save(); - int w = getMeasuredWidth(); - int h = getMeasuredHeight(); - switch (mOrientation) { - case 0: - canvas.translate(0, 0); - break; - case 90: - canvas.translate(0, h); - break; - case 180: - canvas.translate(w, h); - break; - case 270: - canvas.translate(w, 0); - break; - } - canvas.rotate(-mOrientation, 0, 0); - super.dispatchDraw(canvas); - canvas.restore(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - protected void onMeasure(int widthSpec, int heightSpec) { - int w = 0, h = 0; - switch(mOrientation) { - case 0: - case 180: - measureChild(mChild, widthSpec, heightSpec); - w = mChild.getMeasuredWidth(); - h = mChild.getMeasuredHeight(); - break; - case 90: - case 270: - measureChild(mChild, heightSpec, widthSpec); - w = mChild.getMeasuredHeight(); - h = mChild.getMeasuredWidth(); - break; - } - setMeasuredDimension(w, h); - - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - switch (mOrientation) { - case 0: - mChild.setTranslationX(0); - mChild.setTranslationY(0); - break; - case 90: - mChild.setTranslationX(0); - mChild.setTranslationY(h); - break; - case 180: - mChild.setTranslationX(w); - mChild.setTranslationY(h); - break; - case 270: - mChild.setTranslationX(w); - mChild.setTranslationY(0); - break; - } - mChild.setRotation(-mOrientation); - } - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - // Rotate the view counter-clockwise - @Override - public void setOrientation(int orientation, boolean animation) { - orientation = orientation % 360; - if (mOrientation == orientation) return; - mOrientation = orientation; - requestLayout(); - } - - public int getOrientation() { - return mOrientation; - } - - @Override - public ViewParent invalidateChildInParent(int[] location, Rect r) { - if (!ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES && mOrientation != 0) { - // The workaround invalidates the entire rotate layout. After - // rotation, the correct area to invalidate may be larger than the - // size of the child. Ex: ListView. There is no way to invalidate - // only the necessary area. - r.set(0, 0, getWidth(), getHeight()); - } - return super.invalidateChildInParent(location, r); - } -} diff --git a/src/com/android/camera/ui/RotateTextToast.java b/src/com/android/camera/ui/RotateTextToast.java deleted file mode 100644 index c78a258b0..000000000 --- a/src/com/android/camera/ui/RotateTextToast.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 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.app.Activity; -import android.os.Handler; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.android.camera.Util; -import com.android.gallery3d.R; - -public class RotateTextToast { - private static final int TOAST_DURATION = 5000; // milliseconds - ViewGroup mLayoutRoot; - RotateLayout mToast; - Handler mHandler; - - public RotateTextToast(Activity activity, int textResourceId, int orientation) { - mLayoutRoot = (ViewGroup) activity.getWindow().getDecorView(); - LayoutInflater inflater = activity.getLayoutInflater(); - View v = inflater.inflate(R.layout.rotate_text_toast, mLayoutRoot); - mToast = (RotateLayout) v.findViewById(R.id.rotate_toast); - TextView tv = (TextView) mToast.findViewById(R.id.message); - tv.setText(textResourceId); - mToast.setOrientation(orientation, false); - mHandler = new Handler(); - } - - private final Runnable mRunnable = new Runnable() { - @Override - public void run() { - Util.fadeOut(mToast); - mLayoutRoot.removeView(mToast); - mToast = null; - } - }; - - public void show() { - mToast.setVisibility(View.VISIBLE); - mHandler.postDelayed(mRunnable, TOAST_DURATION); - } -} diff --git a/src/com/android/camera/ui/Switch.java b/src/com/android/camera/ui/Switch.java deleted file mode 100644 index ac21758a7..000000000 --- a/src/com/android/camera/ui/Switch.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2012 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.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.ViewConfiguration; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; -import android.widget.CompoundButton; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.Arrays; - -/** - * A Switch is a two-state toggle switch widget that can select between two - * options. The user may drag the "thumb" back and forth to choose the selected option, - * or simply tap to toggle as if it were a checkbox. - */ -public class Switch extends CompoundButton { - private static final int TOUCH_MODE_IDLE = 0; - private static final int TOUCH_MODE_DOWN = 1; - private static final int TOUCH_MODE_DRAGGING = 2; - - private Drawable mThumbDrawable; - private Drawable mTrackDrawable; - private int mThumbTextPadding; - private int mSwitchMinWidth; - private int mSwitchTextMaxWidth; - private int mSwitchPadding; - private CharSequence mTextOn; - private CharSequence mTextOff; - - private int mTouchMode; - private int mTouchSlop; - private float mTouchX; - private float mTouchY; - private VelocityTracker mVelocityTracker = VelocityTracker.obtain(); - private int mMinFlingVelocity; - - private float mThumbPosition; - private int mSwitchWidth; - private int mSwitchHeight; - private int mThumbWidth; // Does not include padding - - private int mSwitchLeft; - private int mSwitchTop; - private int mSwitchRight; - private int mSwitchBottom; - - private TextPaint mTextPaint; - private ColorStateList mTextColors; - private Layout mOnLayout; - private Layout mOffLayout; - - @SuppressWarnings("hiding") - private final Rect mTempRect = new Rect(); - - private static final int[] CHECKED_STATE_SET = { - android.R.attr.state_checked - }; - - /** - * Construct a new Switch with default styling, overriding specific style - * attributes as requested. - * - * @param context The Context that will determine this widget's theming. - * @param attrs Specification of attributes that should deviate from default styling. - */ - public Switch(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.switchStyle); - } - - /** - * Construct a new Switch with a default style determined by the given theme attribute, - * overriding specific style attributes as requested. - * - * @param context The Context that will determine this widget's theming. - * @param attrs Specification of attributes that should deviate from the default styling. - * @param defStyle An attribute ID within the active theme containing a reference to the - * default style for this widget. e.g. android.R.attr.switchStyle. - */ - public Switch(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - Resources res = getResources(); - DisplayMetrics dm = res.getDisplayMetrics(); - mTextPaint.density = dm.density; - mThumbDrawable = res.getDrawable(R.drawable.switch_inner_holo_dark); - mTrackDrawable = res.getDrawable(R.drawable.switch_track_holo_dark); - mTextOn = res.getString(R.string.capital_on); - mTextOff = res.getString(R.string.capital_off); - mThumbTextPadding = res.getDimensionPixelSize(R.dimen.thumb_text_padding); - mSwitchMinWidth = res.getDimensionPixelSize(R.dimen.switch_min_width); - mSwitchTextMaxWidth = res.getDimensionPixelSize(R.dimen.switch_text_max_width); - mSwitchPadding = res.getDimensionPixelSize(R.dimen.switch_padding); - setSwitchTextAppearance(context, android.R.style.TextAppearance_Holo_Small); - - ViewConfiguration config = ViewConfiguration.get(context); - mTouchSlop = config.getScaledTouchSlop(); - mMinFlingVelocity = config.getScaledMinimumFlingVelocity(); - - // Refresh display with current params - refreshDrawableState(); - setChecked(isChecked()); - } - - /** - * Sets the switch text color, size, style, hint color, and highlight color - * from the specified TextAppearance resource. - */ - public void setSwitchTextAppearance(Context context, int resid) { - Resources res = getResources(); - mTextColors = getTextColors(); - int ts = res.getDimensionPixelSize(R.dimen.thumb_text_size); - if (ts != mTextPaint.getTextSize()) { - mTextPaint.setTextSize(ts); - requestLayout(); - } - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - if (mOnLayout == null) { - mOnLayout = makeLayout(mTextOn, mSwitchTextMaxWidth); - } - if (mOffLayout == null) { - mOffLayout = makeLayout(mTextOff, mSwitchTextMaxWidth); - } - - mTrackDrawable.getPadding(mTempRect); - final int maxTextWidth = Math.min(mSwitchTextMaxWidth, - Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())); - final int switchWidth = Math.max(mSwitchMinWidth, - maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right); - final int switchHeight = mTrackDrawable.getIntrinsicHeight(); - - mThumbWidth = maxTextWidth + mThumbTextPadding * 2; - - mSwitchWidth = switchWidth; - mSwitchHeight = switchHeight; - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - final int measuredHeight = getMeasuredHeight(); - final int measuredWidth = getMeasuredWidth(); - if (measuredHeight < switchHeight) { - setMeasuredDimension(measuredWidth, switchHeight); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - super.onPopulateAccessibilityEvent(event); - CharSequence text = isChecked() ? mOnLayout.getText() : mOffLayout.getText(); - if (!TextUtils.isEmpty(text)) { - event.getText().add(text); - } - } - - private Layout makeLayout(CharSequence text, int maxWidth) { - int actual_width = (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)); - StaticLayout l = new StaticLayout(text, 0, text.length(), mTextPaint, - actual_width, - Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true, - TextUtils.TruncateAt.END, - (int) Math.min(actual_width, maxWidth)); - return l; - } - - /** - * @return true if (x, y) is within the target area of the switch thumb - */ - private boolean hitThumb(float x, float y) { - mThumbDrawable.getPadding(mTempRect); - final int thumbTop = mSwitchTop - mTouchSlop; - final int thumbLeft = mSwitchLeft + (int) (mThumbPosition + 0.5f) - mTouchSlop; - final int thumbRight = thumbLeft + mThumbWidth + - mTempRect.left + mTempRect.right + mTouchSlop; - final int thumbBottom = mSwitchBottom + mTouchSlop; - return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mVelocityTracker.addMovement(ev); - final int action = ev.getActionMasked(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - if (isEnabled() && hitThumb(x, y)) { - mTouchMode = TOUCH_MODE_DOWN; - mTouchX = x; - mTouchY = y; - } - break; - } - - case MotionEvent.ACTION_MOVE: { - switch (mTouchMode) { - case TOUCH_MODE_IDLE: - // Didn't target the thumb, treat normally. - break; - - case TOUCH_MODE_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - if (Math.abs(x - mTouchX) > mTouchSlop || - Math.abs(y - mTouchY) > mTouchSlop) { - mTouchMode = TOUCH_MODE_DRAGGING; - getParent().requestDisallowInterceptTouchEvent(true); - mTouchX = x; - mTouchY = y; - return true; - } - break; - } - - case TOUCH_MODE_DRAGGING: { - final float x = ev.getX(); - final float dx = x - mTouchX; - float newPos = Math.max(0, - Math.min(mThumbPosition + dx, getThumbScrollRange())); - if (newPos != mThumbPosition) { - mThumbPosition = newPos; - mTouchX = x; - invalidate(); - } - return true; - } - } - break; - } - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: { - if (mTouchMode == TOUCH_MODE_DRAGGING) { - stopDrag(ev); - return true; - } - mTouchMode = TOUCH_MODE_IDLE; - mVelocityTracker.clear(); - break; - } - } - - return super.onTouchEvent(ev); - } - - private void cancelSuperTouch(MotionEvent ev) { - MotionEvent cancel = MotionEvent.obtain(ev); - cancel.setAction(MotionEvent.ACTION_CANCEL); - super.onTouchEvent(cancel); - cancel.recycle(); - } - - /** - * Called from onTouchEvent to end a drag operation. - * - * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL - */ - private void stopDrag(MotionEvent ev) { - mTouchMode = TOUCH_MODE_IDLE; - // Up and not canceled, also checks the switch has not been disabled during the drag - boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled(); - - cancelSuperTouch(ev); - - if (commitChange) { - boolean newState; - mVelocityTracker.computeCurrentVelocity(1000); - float xvel = mVelocityTracker.getXVelocity(); - if (Math.abs(xvel) > mMinFlingVelocity) { - newState = xvel > 0; - } else { - newState = getTargetCheckedState(); - } - animateThumbToCheckedState(newState); - } else { - animateThumbToCheckedState(isChecked()); - } - } - - private void animateThumbToCheckedState(boolean newCheckedState) { - setChecked(newCheckedState); - } - - private boolean getTargetCheckedState() { - return mThumbPosition >= getThumbScrollRange() / 2; - } - - private void setThumbPosition(boolean checked) { - mThumbPosition = checked ? getThumbScrollRange() : 0; - } - - @Override - public void setChecked(boolean checked) { - super.setChecked(checked); - setThumbPosition(checked); - invalidate(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - setThumbPosition(isChecked()); - - int switchRight; - int switchLeft; - - switchRight = getWidth() - getPaddingRight(); - switchLeft = switchRight - mSwitchWidth; - - int switchTop = 0; - int switchBottom = 0; - switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) { - default: - case Gravity.TOP: - switchTop = getPaddingTop(); - switchBottom = switchTop + mSwitchHeight; - break; - - case Gravity.CENTER_VERTICAL: - switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 - - mSwitchHeight / 2; - switchBottom = switchTop + mSwitchHeight; - break; - - case Gravity.BOTTOM: - switchBottom = getHeight() - getPaddingBottom(); - switchTop = switchBottom - mSwitchHeight; - break; - } - - mSwitchLeft = switchLeft; - mSwitchTop = switchTop; - mSwitchBottom = switchBottom; - mSwitchRight = switchRight; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - // Draw the switch - int switchLeft = mSwitchLeft; - int switchTop = mSwitchTop; - int switchRight = mSwitchRight; - int switchBottom = mSwitchBottom; - - mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom); - mTrackDrawable.draw(canvas); - - canvas.save(); - - mTrackDrawable.getPadding(mTempRect); - int switchInnerLeft = switchLeft + mTempRect.left; - int switchInnerTop = switchTop + mTempRect.top; - int switchInnerRight = switchRight - mTempRect.right; - int switchInnerBottom = switchBottom - mTempRect.bottom; - canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom); - - mThumbDrawable.getPadding(mTempRect); - final int thumbPos = (int) (mThumbPosition + 0.5f); - int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos; - int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right; - - mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom); - mThumbDrawable.draw(canvas); - - // mTextColors should not be null, but just in case - if (mTextColors != null) { - mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(), - mTextColors.getDefaultColor())); - } - mTextPaint.drawableState = getDrawableState(); - - Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; - - canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getEllipsizedWidth() / 2, - (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2); - switchText.draw(canvas); - - canvas.restore(); - } - - @Override - public int getCompoundPaddingRight() { - int padding = super.getCompoundPaddingRight() + mSwitchWidth; - if (!TextUtils.isEmpty(getText())) { - padding += mSwitchPadding; - } - return padding; - } - - private int getThumbScrollRange() { - if (mTrackDrawable == null) { - return 0; - } - mTrackDrawable.getPadding(mTempRect); - return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right; - } - - @Override - protected int[] onCreateDrawableState(int extraSpace) { - final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); - - if (isChecked()) { - mergeDrawableStates(drawableState, CHECKED_STATE_SET); - } - return drawableState; - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - - int[] myDrawableState = getDrawableState(); - - // Set the state of the Drawable - // Drawable may be null when checked state is set from XML, from super constructor - if (mThumbDrawable != null) mThumbDrawable.setState(myDrawableState); - if (mTrackDrawable != null) mTrackDrawable.setState(myDrawableState); - - invalidate(); - } - - @Override - protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable; - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - mThumbDrawable.jumpToCurrentState(); - mTrackDrawable.jumpToCurrentState(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(Switch.class.getName()); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(Switch.class.getName()); - CharSequence switchText = isChecked() ? mTextOn : mTextOff; - if (!TextUtils.isEmpty(switchText)) { - CharSequence oldText = info.getText(); - if (TextUtils.isEmpty(oldText)) { - info.setText(switchText); - } else { - StringBuilder newText = new StringBuilder(); - newText.append(oldText).append(' ').append(switchText); - info.setText(newText); - } - } - } -} diff --git a/src/com/android/camera/ui/TimeIntervalPopup.java b/src/com/android/camera/ui/TimeIntervalPopup.java deleted file mode 100644 index 18ad9f5da..000000000 --- a/src/com/android/camera/ui/TimeIntervalPopup.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 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.content.res.Resources; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.NumberPicker; -import android.widget.Switch; -import android.widget.TextView; - -import com.android.camera.IconListPreference; -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/** - * This is a popup window that allows users to turn on/off time lapse feature, - * and to select a time interval for taking a time lapse video. - */ -public class TimeIntervalPopup extends AbstractSettingPopup { - private static final String TAG = "TimeIntervalPopup"; - private NumberPicker mNumberSpinner; - private NumberPicker mUnitSpinner; - private Switch mTimeLapseSwitch; - private final String[] mUnits; - private final String[] mDurations; - private IconListPreference mPreference; - private Listener mListener; - private Button mConfirmButton; - private TextView mHelpText; - private View mTimePicker; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public TimeIntervalPopup(Context context, AttributeSet attrs) { - super(context, attrs); - - Resources res = context.getResources(); - mUnits = res.getStringArray(R.array.pref_video_time_lapse_frame_interval_units); - mDurations = res - .getStringArray(R.array.pref_video_time_lapse_frame_interval_duration_values); - } - - public void initialize(IconListPreference preference) { - mPreference = preference; - - // Set title. - mTitle.setText(mPreference.getTitle()); - - // Duration - int durationCount = mDurations.length; - mNumberSpinner = (NumberPicker) findViewById(R.id.duration); - mNumberSpinner.setMinValue(0); - mNumberSpinner.setMaxValue(durationCount - 1); - mNumberSpinner.setDisplayedValues(mDurations); - mNumberSpinner.setWrapSelectorWheel(false); - - // Units for duration (i.e. seconds, minutes, etc) - mUnitSpinner = (NumberPicker) findViewById(R.id.duration_unit); - mUnitSpinner.setMinValue(0); - mUnitSpinner.setMaxValue(mUnits.length - 1); - mUnitSpinner.setDisplayedValues(mUnits); - mUnitSpinner.setWrapSelectorWheel(false); - - mTimePicker = findViewById(R.id.time_interval_picker); - mTimeLapseSwitch = (Switch) findViewById(R.id.time_lapse_switch); - mHelpText = (TextView) findViewById(R.id.set_time_interval_help_text); - mConfirmButton = (Button) findViewById(R.id.time_lapse_interval_set_button); - - // Disable focus on the spinners to prevent keyboard from coming up - mNumberSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - mUnitSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - - mTimeLapseSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - setTimeSelectionEnabled(isChecked); - } - }); - mConfirmButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - updateInputState(); - } - }); - } - - private void restoreSetting() { - int index = mPreference.findIndexOfValue(mPreference.getValue()); - if (index == -1) { - Log.e(TAG, "Invalid preference value."); - mPreference.print(); - throw new IllegalArgumentException(); - } else if (index == 0) { - // default choice: time lapse off - mTimeLapseSwitch.setChecked(false); - setTimeSelectionEnabled(false); - } else { - mTimeLapseSwitch.setChecked(true); - setTimeSelectionEnabled(true); - int durationCount = mNumberSpinner.getMaxValue() + 1; - int unit = (index - 1) / durationCount; - int number = (index - 1) % durationCount; - mUnitSpinner.setValue(unit); - mNumberSpinner.setValue(number); - } - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Set the number pickers and on/off switch to be consistent - // with the preference - restoreSetting(); - } - } - super.setVisibility(visibility); - } - - protected void setTimeSelectionEnabled(boolean enabled) { - mHelpText.setVisibility(enabled ? GONE : VISIBLE); - mTimePicker.setVisibility(enabled ? VISIBLE : GONE); - } - - @Override - public void reloadPreference() { - } - - private void updateInputState() { - if (mTimeLapseSwitch.isChecked()) { - int newId = mUnitSpinner.getValue() * (mNumberSpinner.getMaxValue() + 1) - + mNumberSpinner.getValue() + 1; - mPreference.setValueIndex(newId); - } else { - mPreference.setValueIndex(0); - } - - if (mListener != null) { - mListener.onListPrefChanged(mPreference); - } - } -} diff --git a/src/com/android/camera/ui/TwoStateImageView.java b/src/com/android/camera/ui/TwoStateImageView.java deleted file mode 100644 index cd5b27fc1..000000000 --- a/src/com/android/camera/ui/TwoStateImageView.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 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.util.AttributeSet; -import android.widget.ImageView; - -/** - * A @{code ImageView} which change the opacity of the icon if disabled. - */ -public class TwoStateImageView extends ImageView { - private static final int ENABLED_ALPHA = 255; - private static final int DISABLED_ALPHA = (int) (255 * 0.4); - private boolean mFilterEnabled = true; - - public TwoStateImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public TwoStateImageView(Context context) { - this(context, null); - } - - @SuppressWarnings("deprecation") - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (mFilterEnabled) { - if (enabled) { - setAlpha(ENABLED_ALPHA); - } else { - setAlpha(DISABLED_ALPHA); - } - } - } - - public void enableFilter(boolean enabled) { - mFilterEnabled = enabled; - } -} diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java deleted file mode 100644 index 86b82b459..000000000 --- a/src/com/android/camera/ui/ZoomRenderer.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2012 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.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.view.ScaleGestureDetector; - -import com.android.gallery3d.R; - -public class ZoomRenderer extends OverlayRenderer - implements ScaleGestureDetector.OnScaleGestureListener { - - private static final String TAG = "CAM_Zoom"; - - private int mMaxZoom; - private int mMinZoom; - private OnZoomChangedListener mListener; - - private ScaleGestureDetector mDetector; - private Paint mPaint; - private Paint mTextPaint; - private int mCircleSize; - private int mCenterX; - private int mCenterY; - private float mMaxCircle; - private float mMinCircle; - private int mInnerStroke; - private int mOuterStroke; - private int mZoomSig; - private int mZoomFraction; - private Rect mTextBounds; - - public interface OnZoomChangedListener { - void onZoomStart(); - void onZoomEnd(); - void onZoomValueChanged(int index); // only for immediate zoom - } - - public ZoomRenderer(Context ctx) { - Resources res = ctx.getResources(); - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setColor(Color.WHITE); - mPaint.setStyle(Paint.Style.STROKE); - mTextPaint = new Paint(mPaint); - mTextPaint.setStyle(Paint.Style.FILL); - mTextPaint.setTextSize(res.getDimensionPixelSize(R.dimen.zoom_font_size)); - mTextPaint.setTextAlign(Paint.Align.LEFT); - mTextPaint.setAlpha(192); - mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke); - mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke); - mDetector = new ScaleGestureDetector(ctx, this); - mMinCircle = res.getDimensionPixelSize(R.dimen.zoom_ring_min); - mTextBounds = new Rect(); - setVisible(false); - } - - // set from module - public void setZoomMax(int zoomMaxIndex) { - mMaxZoom = zoomMaxIndex; - mMinZoom = 0; - } - - public void setZoom(int index) { - mCircleSize = (int) (mMinCircle + index * (mMaxCircle - mMinCircle) / (mMaxZoom - mMinZoom)); - } - - public void setZoomValue(int value) { - value = value / 10; - mZoomSig = value / 10; - mZoomFraction = value % 10; - } - - public void setOnZoomChangeListener(OnZoomChangedListener listener) { - mListener = listener; - } - - @Override - public void layout(int l, int t, int r, int b) { - super.layout(l, t, r, b); - mCenterX = (r - l) / 2; - mCenterY = (b - t) / 2; - mMaxCircle = Math.min(getWidth(), getHeight()); - mMaxCircle = (mMaxCircle - mMinCircle) / 2; - } - - public boolean isScaling() { - return mDetector.isInProgress(); - } - - @Override - public void onDraw(Canvas canvas) { - mPaint.setStrokeWidth(mInnerStroke); - canvas.drawCircle(mCenterX, mCenterY, mMinCircle, mPaint); - canvas.drawCircle(mCenterX, mCenterY, mMaxCircle, mPaint); - canvas.drawLine(mCenterX - mMinCircle, mCenterY, - mCenterX - mMaxCircle - 4, mCenterY, mPaint); - mPaint.setStrokeWidth(mOuterStroke); - canvas.drawCircle((float) mCenterX, (float) mCenterY, - (float) mCircleSize, mPaint); - String txt = mZoomSig+"."+mZoomFraction+"x"; - mTextPaint.getTextBounds(txt, 0, txt.length(), mTextBounds); - canvas.drawText(txt, mCenterX - mTextBounds.centerX(), mCenterY - mTextBounds.centerY(), - mTextPaint); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - final float sf = detector.getScaleFactor(); - float circle = (int) (mCircleSize * sf * sf); - circle = Math.max(mMinCircle, circle); - circle = Math.min(mMaxCircle, circle); - if (mListener != null && (int) circle != mCircleSize) { - mCircleSize = (int) circle; - int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle)); - mListener.onZoomValueChanged(zoom); - } - return true; - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - setVisible(true); - if (mListener != null) { - mListener.onZoomStart(); - } - update(); - return true; - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - setVisible(false); - if (mListener != null) { - mListener.onZoomEnd(); - } - } - -} |