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