1 package com.cooliris.media;
3 import java.util.ArrayList;
5 import javax.microedition.khronos.opengles.GL11;
7 import android.graphics.Typeface;
8 import android.view.MotionEvent;
10 public final class PathBarLayer extends Layer {
11 private static final StringTexture.Config sPathFormat = new StringTexture.Config();
12 private final ArrayList<Component> mComponents = new ArrayList<Component>();
13 private static final int FILL = R.drawable.pathbar_bg;
14 private static final int JOIN = R.drawable.pathbar_join;
15 private static final int CAP = R.drawable.pathbar_cap;
16 private Component mTouchItem = null;
19 sPathFormat.fontSize = 18f * Gallery.PIXEL_DENSITY;
22 public PathBarLayer() {
25 public void pushLabel(int icon, String label, Runnable action) {
26 mComponents.add(new Component(icon, label, action, 0));
27 recomputeComponents();
30 public void setAnimatedIcons(final int[] icons) {
31 final int numComponents = mComponents.size();
32 for (int i = 0; i < numComponents; ++i) {
33 final Component component = mComponents.get(i);
34 if (component != null) {
35 if (component.animatedIcons != null) {
36 component.animatedIcons = null;
38 if (i == numComponents - 1) {
39 component.animatedIcons = icons;
45 public void changeLabel(String label) {
46 if (label == null || label.length() == 0)
48 Component component = popLabel();
49 if (component != null) {
50 pushLabel(component.icon, label, component.action);
54 public String getCurrentLabel() {
55 final ArrayList<Component> components = mComponents;
56 int lastIndex = components.size() - 1;
60 Component retVal = components.get(lastIndex);
61 return retVal.origString;
64 public Component popLabel() {
65 final ArrayList<Component> components = mComponents;
66 int lastIndex = components.size() - 1;
70 Component retVal = components.get(lastIndex);
71 components.remove(lastIndex);
75 private static final class Component {
76 public String origString;
78 public Runnable action;
79 public StringTexture texture;
81 public float animWidth;
83 public int[] animatedIcons;
84 public float timeElapsed;
85 private static final float ICON_WIDTH = 38.0f;
87 Component(int icon, String label, Runnable action, float widthLeft) {
91 computeLabel(widthLeft);
94 public final void computeLabel(float widthLeft) {
95 Typeface typeface = sPathFormat.bold ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT;
97 if (origString != null) {
98 label = origString.substring(0, StringTexture.lengthToFit(sPathFormat.fontSize, widthLeft, typeface, origString));
99 if (label.length() != origString.length()) {
103 this.texture = new StringTexture(label, sPathFormat);
106 public final boolean update(float timeElapsed) {
107 this.timeElapsed += timeElapsed;
108 if (animWidth == 0.0f) {
111 animWidth = FloatUtils.animate(animWidth, width, timeElapsed);
112 if (animatedIcons != null && animatedIcons.length > 1)
114 if (animWidth == width) {
121 public float getIconWidth() {
122 return ICON_WIDTH * Gallery.PIXEL_DENSITY;
127 public void generate(RenderView view, RenderView.Lists lists) {
128 lists.blendedList.add(this);
129 lists.hitTestList.add(this);
130 lists.updateList.add(this);
133 private void layout() {
134 int numComponents = mComponents.size();
135 for (int i = 0; i < numComponents; ++i) {
136 Component component = mComponents.get(i);
137 float iconWidth = (component.icon == 0) ? 0 : component.getIconWidth();
138 if (iconWidth == 0) {
139 iconWidth = 8 * Gallery.PIXEL_DENSITY;
141 float offset = 5 * Gallery.PIXEL_DENSITY;
142 float thisComponentWidth = (i != numComponents - 1) ? iconWidth + offset : component.texture.computeTextWidth()
143 + iconWidth + offset;
144 component.width = thisComponentWidth;
149 public boolean update(RenderView view, float timeElapsed) {
151 boolean retVal = false;
152 int numComponents = mComponents.size();
153 for (int i = 0; i < numComponents; i++) {
154 Component component = mComponents.get(i);
155 retVal |= component.update(timeElapsed);
161 public void renderBlended(RenderView view, GL11 gl) {
163 final Texture fill = view.getResource(FILL);
164 final Texture join = view.getResource(JOIN);
165 final Texture cap = view.getResource(CAP);
166 final float y = mY + 3;
167 int x = (int) (3 * Gallery.PIXEL_DENSITY);
168 float height = mHeight;
169 int numComponents = mComponents.size();
170 for (int i = 0; i < numComponents; ++i) {
171 Component component = mComponents.get(i);
173 // Draw the left join if not the first component, and the fill.
174 // TODO: Draw the pressed background for mTouchItem.
175 final int width = (int) component.animWidth;
177 view.draw2D(join, x - join.getWidth(), y);
178 if (view.bind(fill)) {
179 view.draw2D(x, y, 0f, width, height);
181 } else if (view.bind(fill)) {
182 view.draw2D(0f, y, 0f, x + width, height);
185 if (i == numComponents - 1) {
186 // Draw the cap on the right edge.
187 view.draw2D(cap, x + width, y);
189 float xOffset = 5 * Gallery.PIXEL_DENSITY;
191 final int[] icons = component.animatedIcons;
193 // Cycles animated icons.
194 final int iconId = (icons != null && icons.length > 0) ? icons[(int) (component.timeElapsed * 20.0f)
195 % icons.length] : component.icon;
196 final Texture icon = view.getResource(iconId);
198 view.loadTexture(icon);
199 view.draw2D(icon, x + xOffset, y - 2 * Gallery.PIXEL_DENSITY);
201 if (i == numComponents - 1) {
202 final StringTexture texture = component.texture;
203 view.loadTexture(texture);
204 float iconWidth = component.getIconWidth();
205 if (texture.computeTextWidth() <= (width - iconWidth)) {
206 float textOffset = (iconWidth == 0) ? 8 * Gallery.PIXEL_DENSITY : iconWidth;
207 view.draw2D(texture, x + textOffset, y + 5);
210 x += (int) (width + (21 * Gallery.PIXEL_DENSITY + 0.5f));
214 private Component hitTestItems(float x, float y) {
215 if (y >= mY && y < mY + mHeight) {
216 int numComponents = mComponents.size();
217 for (int i = 0; i < numComponents; i++) {
218 final Component component = mComponents.get(i);
219 float componentx = component.x;
220 if (x >= componentx && x < componentx + component.width) {
229 public boolean onTouchEvent(MotionEvent event) {
230 final float x = event.getX();
231 final float y = event.getY();
232 switch (event.getAction()) {
233 case MotionEvent.ACTION_DOWN:
234 mTouchItem = hitTestItems(x, y);
236 case MotionEvent.ACTION_MOVE:
238 case MotionEvent.ACTION_UP:
239 if (mTouchItem != null) {
240 mTouchItem.action.run();
242 case MotionEvent.ACTION_CANCEL:
249 public void recomputeComponents() {
250 float width = mWidth;
251 width -= 20f * Gallery.PIXEL_DENSITY;
252 int numComponents = mComponents.size();
253 for (int i = 0; i < numComponents; i++) {
254 Component component = mComponents.get(i);
255 width -= (component.getIconWidth() + 20.0f * Gallery.PIXEL_DENSITY);
256 component.computeLabel(width);
260 public int getNumLevels() {
261 return mComponents.size();
264 public void clear() {