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 javax.microedition.khronos.opengles.GL11; 20 21 import android.graphics.Rect; 22 import android.view.MotionEvent; 23 import android.view.View.MeasureSpec; 24 import android.view.animation.AlphaAnimation; 25 26 public class IndicatorBar extends GLView { 27 28 public static final int INDEX_NONE = -1; 29 30 private NinePatchTexture mBackground; 31 private NinePatchTexture mHighlight; 32 private int mSelectedIndex = INDEX_NONE; 33 34 private OnItemSelectedListener mSelectedListener; 35 private boolean mActivated = false; 36 37 private boolean mSelectionChanged = false; 38 39 private class Background extends GLView { 40 @Override 41 protected void render(GLRootView root, GL11 gl) { 42 mBackground.setSize(getWidth(), getHeight()); 43 mBackground.draw(root, 0, 0); 44 45 if (mActivated && mSelectedIndex != INDEX_NONE 46 && mHighlight != null) { 47 Rect bounds = IndicatorBar.this.getComponent( 48 mSelectedIndex + 1).mBounds; 49 mHighlight.setSize(bounds.width(), bounds.height()); 50 mHighlight.draw(root, bounds.left, bounds.top); 51 } 52 } 53 } 54 55 public interface OnItemSelectedListener { 56 public void onItemSelected(GLView view, int position); 57 public void onNothingSelected(); 58 } 59 60 public IndicatorBar() { 61 GLView background = new Background(); 62 background.setVisibility(GLView.INVISIBLE); 63 addComponent(background); 64 } 65 66 public void overrideSettings(String key, String value) { 67 for (int i = 1, n = getComponentCount(); i < n; ++i) { 68 AbstractIndicator indicator = (AbstractIndicator) getComponent(i); 69 indicator.overrideSettings(key, value); 70 } 71 } 72 73 public void setOnItemSelectedListener(OnItemSelectedListener l) { 74 mSelectedListener = l; 75 } 76 77 public void setBackground(NinePatchTexture background) { 78 if (mBackground == background) return; 79 mBackground = background; 80 if (background != null) { 81 setPaddings(background.getPaddings()); 82 } else { 83 setPaddings(0, 0, 0, 0); 84 } 85 invalidate(); 86 } 87 88 public void setHighlight(NinePatchTexture highlight) { 89 if (mHighlight == highlight) return; 90 mHighlight = highlight; 91 invalidate(); 92 } 93 94 @Override 95 protected void onMeasure(int widthSpec, int heightSpec) { 96 int width = 0; 97 int height = 0; 98 for (int i = 1, n = getComponentCount(); i < n; ++i) { 99 GLView component = getComponent(i); 100 component.measure( 101 MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 102 width = Math.max(width, component.getMeasuredWidth()); 103 height += component.getMeasuredHeight(); 104 } 105 new MeasureHelper(this) 106 .setPreferredContentSize(width, height) 107 .measure(widthSpec, heightSpec); 108 } 109 110 @Override 111 protected void onLayout( 112 boolean changed, int left, int top, int right, int bottom) { 113 // Background 114 getComponent(0).layout(0, 0, right - left, bottom - top); 115 116 int count = getComponentCount(); 117 Rect p = mPaddings; 118 int cBottom = bottom - top - p.bottom; 119 int cRight = right - left - p.right; 120 int yoffset = mPaddings.top; 121 int xoffset = mPaddings.left; 122 for (int i = 1; i < count; ++i) { 123 int cHeight = (cBottom - yoffset) / (count - i); 124 int nextYoffset = yoffset + cHeight; 125 getComponent(i).layout(xoffset, yoffset, cRight, nextYoffset); 126 yoffset = nextYoffset; 127 } 128 } 129 130 private void setSelectedItem(GLView view, int index) { 131 if (index == mSelectedIndex) return; 132 mSelectionChanged = true; 133 mSelectedIndex = index; 134 if (mSelectedListener != null) { 135 if (index == INDEX_NONE) { 136 mSelectedListener.onNothingSelected(); 137 } else { 138 mSelectedListener.onItemSelected(view, index); 139 } 140 } 141 invalidate(); 142 } 143 144 public void setSelectedIndex(int index) { 145 if (index == mSelectedIndex) return; 146 setSelectedItem(index == INDEX_NONE ? null :getComponent(index), index); 147 } 148 149 public void setActivated(boolean activated) { 150 if (activated == mActivated) return; 151 mActivated = activated; 152 if (activated) { 153 GLView background = getComponent(0); 154 background.setVisibility(GLView.VISIBLE); 155 AlphaAnimation anim = new AlphaAnimation(0, 1); 156 anim.setDuration(200); 157 background.startAnimation(anim); 158 } else { 159 GLView background = getComponent(0); 160 background.setVisibility(GLView.INVISIBLE); 161 AlphaAnimation anim = new AlphaAnimation(1, 0); 162 anim.setDuration(200); 163 background.startAnimation(anim); 164 } 165 } 166 167 public boolean isActivated() { 168 return mActivated; 169 } 170 171 @Override 172 protected boolean dispatchTouchEvent(MotionEvent event) { 173 // Do not pass motion events to children 174 return onTouch(event); 175 } 176 177 @Override @SuppressWarnings("fallthrough") 178 protected boolean onTouch(MotionEvent event) { 179 int y = (int) event.getY(); 180 switch (event.getAction()) { 181 case MotionEvent.ACTION_DOWN: 182 mSelectionChanged = false; 183 setActivated(true); 184 case MotionEvent.ACTION_MOVE: 185 for (int i = 1, n = getComponentCount(); i < n; ++i) { 186 GLView component = getComponent(i); 187 if (y <= component.mBounds.bottom) { 188 setSelectedItem(component, i - 1); 189 return true; 190 } 191 } 192 setSelectedItem(null, INDEX_NONE); 193 break; 194 case MotionEvent.ACTION_UP: 195 if (mSelectionChanged == false) { 196 setSelectedItem(null, INDEX_NONE); 197 } 198 } 199 return true; 200 } 201 202 public void reloadPreferences() { 203 for (int i = 1, n = getComponentCount(); i < n; ++i) { 204 ((AbstractIndicator) getComponent(i)).reloadPreferences(); 205 } 206 } 207 208 public void setOrientation(int orientation) { 209 for (int i = 1, n = getComponentCount(); i < n; ++i) { 210 ((AbstractIndicator) getComponent(i)).setOrientation(orientation); 211 } 212 } 213 214 public int getSelectedIndex() { 215 return mSelectedIndex; 216 } 217 } 218