| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.camera.ui; |
| |
| import com.android.camera.IconListPreference; |
| import com.android.camera.PreferenceGroup; |
| import com.android.camera.R; |
| import com.android.camera.Util; |
| |
| import android.content.Context; |
| import android.util.AttributeSet; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.widget.ImageView; |
| |
| /** |
| * A view that contains camera setting indicators which are spread over a |
| * vertical bar in preview frame. |
| */ |
| public class SecondLevelIndicatorControlBar extends IndicatorControl implements |
| View.OnClickListener, AbstractIndicatorButton.IndicatorChangeListener { |
| private static final String TAG = "SecondLevelIndicatorControlBar"; |
| private static int ICON_SPACING = Util.dpToPixel(16); |
| private View mCloseIcon; |
| private View mDivider; // the divider line |
| private View mPopupedIndicator; |
| int mOrientation = 0; |
| int mSelectedIndex = -1; |
| // There are some views in the ViewGroup before adding the indicator buttons, |
| // such as Close icon, divider line and the hightlight bar, we need to |
| // remember the count of the non-indicator buttons for getTouchViewIndex(). |
| int mNonIndicatorButtonCount; |
| |
| public SecondLevelIndicatorControlBar(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| } |
| |
| @Override |
| protected void onFinishInflate() { |
| mDivider = findViewById(R.id.divider); |
| mCloseIcon = findViewById(R.id.back_to_first_level); |
| mCloseIcon.setOnClickListener(this); |
| } |
| |
| public void initialize(Context context, PreferenceGroup group, |
| String[] keys, String[] otherSettingKeys) { |
| |
| setPreferenceGroup(group); |
| mNonIndicatorButtonCount = getChildCount(); |
| addControls(keys, otherSettingKeys); |
| if (mOrientation != 0) setOrientation(mOrientation); |
| } |
| |
| public void onClick(View view) { |
| dismissSettingPopup(); |
| mOnIndicatorEventListener.onIndicatorEvent( |
| OnIndicatorEventListener.EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR); |
| } |
| |
| private int getTouchViewIndex(int x, int width) { |
| // If the current touch location is on close icon and above. |
| if (x > mCloseIcon.getLeft()) return indexOfChild(mCloseIcon); |
| |
| // Calculate if the touch event is on the indicator buttons. |
| int count = getChildCount(); |
| if (count == mNonIndicatorButtonCount) return -1; |
| // The baseline will be the first indicator button's top minus spacing. |
| View firstIndicatorButton = getChildAt(mNonIndicatorButtonCount); |
| int baselineX = firstIndicatorButton.getRight() + (ICON_SPACING / 2); |
| if (x > baselineX) return -1; |
| int iconWidth = firstIndicatorButton.getMeasuredWidth(); |
| int buttonRange = iconWidth + ICON_SPACING; |
| return (mNonIndicatorButtonCount + ((baselineX - x) / buttonRange)); |
| } |
| |
| private void dispatchRelativeTouchEvent(View view, MotionEvent event) { |
| event.offsetLocation(-view.getLeft(), -view.getTop()); |
| view.dispatchTouchEvent(event); |
| event.offsetLocation(view.getLeft(), view.getTop()); |
| } |
| |
| @Override |
| public boolean dispatchTouchEvent(MotionEvent event) { |
| if (!onFilterTouchEventForSecurity(event)) return false; |
| |
| int action = event.getAction(); |
| if (!isEnabled()) return false; |
| |
| double x = (double) event.getX(); |
| int width = getWidth(); |
| if (width == 0) return false; // the event is sent before onMeasure() |
| if (x > width) x = width; |
| |
| int index = getTouchViewIndex((int) x, width); |
| |
| // Cancel the previous target if we moved out of it |
| if ((mSelectedIndex != -1) && (index != mSelectedIndex)) { |
| View p = getChildAt(mSelectedIndex); |
| |
| int oldAction = event.getAction(); |
| event.setAction(MotionEvent.ACTION_CANCEL); |
| dispatchRelativeTouchEvent(p, event); |
| event.setAction(oldAction); |
| |
| if (p instanceof AbstractIndicatorButton) { |
| AbstractIndicatorButton b = (AbstractIndicatorButton) p; |
| b.dismissPopup(); |
| } |
| } |
| |
| // Send event to the target |
| View v = getChildAt(index); |
| if (v == null) return true; |
| |
| // Change MOVE to DOWN if this is a new target |
| if (mSelectedIndex != index && action == MotionEvent.ACTION_MOVE) { |
| event.setAction(MotionEvent.ACTION_DOWN); |
| } |
| dispatchRelativeTouchEvent(v, event); |
| mSelectedIndex = index; |
| return true; |
| } |
| |
| @Override |
| public IndicatorButton addIndicator(Context context, IconListPreference pref) { |
| IndicatorButton b = super.addIndicator(context, pref); |
| b.setBackgroundResource(R.drawable.bg_pressed); |
| b.setIndicatorChangeListener(this); |
| return b; |
| } |
| |
| @Override |
| public OtherSettingIndicatorButton addOtherSettingIndicator(Context context, |
| int resId, String[] keys) { |
| OtherSettingIndicatorButton b = |
| super.addOtherSettingIndicator(context, resId, keys); |
| b.setBackgroundResource(R.drawable.bg_pressed); |
| b.setIndicatorChangeListener(this); |
| return b; |
| } |
| |
| @Override |
| public void onShowIndicator(View view, boolean showed) { |
| // Ignore those events if not current popup. |
| if (!showed && (mPopupedIndicator != view)) return; |
| mPopupedIndicator = (showed ? view : null); |
| // Show or dismiss the side indicator highlight. |
| requestLayout(); |
| } |
| |
| @Override |
| public void setOrientation(int orientation) { |
| mOrientation = orientation; |
| super.setOrientation(orientation); |
| } |
| |
| @Override |
| protected void onLayout( |
| boolean changed, int left, int top, int right, int bottom) { |
| int count = getChildCount(); |
| if (count == 0) return; |
| int width = right - left; |
| int height = bottom - top; |
| int iconWidth = mCloseIcon.getMeasuredWidth(); |
| int padding = getPaddingLeft(); |
| |
| // Layout from the last icon up. |
| int offsetX = padding; |
| int increment = iconWidth + ICON_SPACING; |
| for (int i = count - 1; i >= mNonIndicatorButtonCount; --i) { |
| getChildAt(i).layout(offsetX, 0, offsetX + iconWidth, height); |
| offsetX += increment; |
| } |
| |
| // And layout the divider line. |
| offsetX = width - iconWidth - 2 * padding; |
| mDivider.layout(offsetX, padding, (offsetX + mDivider.getMeasuredWidth()), |
| (height - padding)); |
| |
| offsetX = width - iconWidth - padding; |
| // The first icon is close button. |
| mCloseIcon.layout(offsetX, 0, (offsetX + iconWidth), height); |
| } |
| |
| @Override |
| public void setEnabled(boolean enabled) { |
| super.setEnabled(enabled); |
| if (mCurrentMode == MODE_VIDEO) { |
| mCloseIcon.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); |
| } |
| mCloseIcon.setEnabled(enabled); |
| } |
| } |