Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.ui;
     18 
     19 import com.android.camera.IconListPreference;
     20 import com.android.camera.PreferenceGroup;
     21 import com.android.camera.R;
     22 import com.android.camera.Util;
     23 
     24 import android.content.Context;
     25 import android.util.AttributeSet;
     26 import android.view.MotionEvent;
     27 import android.view.View;
     28 import android.widget.ImageView;
     29 
     30 /**
     31  * A view that contains camera setting indicators which are spread over a
     32  * vertical bar in preview frame.
     33  */
     34 public class SecondLevelIndicatorControlBar extends IndicatorControl implements
     35         View.OnClickListener, AbstractIndicatorButton.IndicatorChangeListener {
     36     private static final String TAG = "SecondLevelIndicatorControlBar";
     37     private static int ICON_SPACING = Util.dpToPixel(16);
     38     private View mCloseIcon;
     39     private View mDivider; // the divider line
     40     private View mPopupedIndicator;
     41     int mOrientation = 0;
     42     int mSelectedIndex = -1;
     43     // There are some views in the ViewGroup before adding the indicator buttons,
     44     // such as Close icon, divider line and the hightlight bar, we need to
     45     // remember the count of the non-indicator buttons for getTouchViewIndex().
     46     int mNonIndicatorButtonCount;
     47 
     48     public SecondLevelIndicatorControlBar(Context context, AttributeSet attrs) {
     49         super(context, attrs);
     50     }
     51 
     52     @Override
     53     protected void onFinishInflate() {
     54         mDivider = findViewById(R.id.divider);
     55         mCloseIcon = findViewById(R.id.back_to_first_level);
     56         mCloseIcon.setOnClickListener(this);
     57     }
     58 
     59     public void initialize(Context context, PreferenceGroup group,
     60             String[] keys, String[] otherSettingKeys) {
     61 
     62         setPreferenceGroup(group);
     63         mNonIndicatorButtonCount = getChildCount();
     64         addControls(keys, otherSettingKeys);
     65         if (mOrientation != 0) setOrientation(mOrientation);
     66     }
     67 
     68     public void onClick(View view) {
     69         dismissSettingPopup();
     70         mOnIndicatorEventListener.onIndicatorEvent(
     71                     OnIndicatorEventListener.EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR);
     72     }
     73 
     74     private int getTouchViewIndex(int x, int width) {
     75         // If the current touch location is on close icon and above.
     76         if (x > mCloseIcon.getLeft()) return indexOfChild(mCloseIcon);
     77 
     78         // Calculate if the touch event is on the indicator buttons.
     79         int count = getChildCount();
     80         if (count == mNonIndicatorButtonCount) return -1;
     81         // The baseline will be the first indicator button's top minus spacing.
     82         View firstIndicatorButton = getChildAt(mNonIndicatorButtonCount);
     83         int baselineX = firstIndicatorButton.getRight() + (ICON_SPACING / 2);
     84         if (x > baselineX) return -1;
     85         int iconWidth = firstIndicatorButton.getMeasuredWidth();
     86         int buttonRange = iconWidth + ICON_SPACING;
     87         return (mNonIndicatorButtonCount + ((baselineX - x) / buttonRange));
     88     }
     89 
     90     private void dispatchRelativeTouchEvent(View view, MotionEvent event) {
     91         event.offsetLocation(-view.getLeft(), -view.getTop());
     92         view.dispatchTouchEvent(event);
     93         event.offsetLocation(view.getLeft(), view.getTop());
     94     }
     95 
     96     @Override
     97     public boolean dispatchTouchEvent(MotionEvent event) {
     98         if (!onFilterTouchEventForSecurity(event)) return false;
     99 
    100         int action = event.getAction();
    101         if (!isEnabled()) return false;
    102 
    103         double x = (double) event.getX();
    104         int width = getWidth();
    105         if (width == 0) return false; // the event is sent before onMeasure()
    106         if (x > width) x = width;
    107 
    108         int index = getTouchViewIndex((int) x, width);
    109 
    110         // Cancel the previous target if we moved out of it
    111         if ((mSelectedIndex != -1) && (index != mSelectedIndex)) {
    112             View p = getChildAt(mSelectedIndex);
    113 
    114             int oldAction = event.getAction();
    115             event.setAction(MotionEvent.ACTION_CANCEL);
    116             dispatchRelativeTouchEvent(p, event);
    117             event.setAction(oldAction);
    118 
    119             if (p instanceof AbstractIndicatorButton) {
    120                 AbstractIndicatorButton b = (AbstractIndicatorButton) p;
    121                 b.dismissPopup();
    122             }
    123         }
    124 
    125         // Send event to the target
    126         View v = getChildAt(index);
    127         if (v == null) return true;
    128 
    129         // Change MOVE to DOWN if this is a new target
    130         if (mSelectedIndex != index && action == MotionEvent.ACTION_MOVE) {
    131             event.setAction(MotionEvent.ACTION_DOWN);
    132         }
    133         dispatchRelativeTouchEvent(v, event);
    134         mSelectedIndex = index;
    135         return true;
    136     }
    137 
    138     @Override
    139     public IndicatorButton addIndicator(Context context, IconListPreference pref) {
    140         IndicatorButton b = super.addIndicator(context, pref);
    141         b.setBackgroundResource(R.drawable.bg_pressed);
    142         b.setIndicatorChangeListener(this);
    143         return b;
    144     }
    145 
    146     @Override
    147     public OtherSettingIndicatorButton addOtherSettingIndicator(Context context,
    148             int resId, String[] keys) {
    149         OtherSettingIndicatorButton b =
    150                 super.addOtherSettingIndicator(context, resId, keys);
    151         b.setBackgroundResource(R.drawable.bg_pressed);
    152         b.setIndicatorChangeListener(this);
    153         return b;
    154     }
    155 
    156     @Override
    157     public void onShowIndicator(View view, boolean showed) {
    158         // Ignore those events if not current popup.
    159         if (!showed && (mPopupedIndicator != view)) return;
    160         mPopupedIndicator = (showed ? view : null);
    161         // Show or dismiss the side indicator highlight.
    162         requestLayout();
    163     }
    164 
    165     @Override
    166     public void setOrientation(int orientation) {
    167         mOrientation = orientation;
    168         super.setOrientation(orientation);
    169     }
    170 
    171     @Override
    172     protected void onLayout(
    173             boolean changed, int left, int top, int right, int bottom) {
    174         int count = getChildCount();
    175         if (count == 0) return;
    176         int width = right - left;
    177         int height = bottom - top;
    178         int iconWidth = mCloseIcon.getMeasuredWidth();
    179         int padding = getPaddingLeft();
    180 
    181         // Layout from the last icon up.
    182         int offsetX = padding;
    183         int increment = iconWidth + ICON_SPACING;
    184         for (int i = count - 1; i >= mNonIndicatorButtonCount; --i) {
    185             getChildAt(i).layout(offsetX, 0, offsetX + iconWidth, height);
    186             offsetX += increment;
    187         }
    188 
    189         // And layout the divider line.
    190         offsetX = width - iconWidth - 2 * padding;
    191         mDivider.layout(offsetX, padding, (offsetX + mDivider.getMeasuredWidth()),
    192                 (height - padding));
    193 
    194         offsetX = width - iconWidth - padding;
    195         // The first icon is close button.
    196         mCloseIcon.layout(offsetX, 0, (offsetX + iconWidth), height);
    197    }
    198 
    199     @Override
    200     public void setEnabled(boolean enabled) {
    201         super.setEnabled(enabled);
    202         if (mCurrentMode == MODE_VIDEO) {
    203             mCloseIcon.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
    204         }
    205         mCloseIcon.setEnabled(enabled);
    206     }
    207 }
    208