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.gallery3d.ui; 18 19 import com.android.gallery3d.R; 20 import com.android.gallery3d.anim.AlphaAnimation; 21 import com.android.gallery3d.app.AlbumDataAdapter; 22 import com.android.gallery3d.app.GalleryActivity; 23 import com.android.gallery3d.data.MediaItem; 24 import com.android.gallery3d.data.MediaSet; 25 import com.android.gallery3d.data.Path; 26 27 import android.content.Context; 28 import android.view.MotionEvent; 29 import android.view.View.MeasureSpec; 30 31 public class FilmStripView extends GLView implements ScrollBarView.Listener, 32 UserInteractionListener { 33 @SuppressWarnings("unused") 34 private static final String TAG = "FilmStripView"; 35 36 private static final int HIDE_ANIMATION_DURATION = 300; // 0.3 sec 37 38 public interface Listener { 39 // Returns false if it cannot jump to the specified index at this time. 40 boolean onSlotSelected(int slotIndex); 41 } 42 43 private int mTopMargin, mMidMargin, mBottomMargin; 44 private int mContentSize, mBarSize, mGripSize; 45 private AlbumView mAlbumView; 46 private ScrollBarView mScrollBarView; 47 private AlbumDataAdapter mAlbumDataAdapter; 48 private StripDrawer mStripDrawer; 49 private Listener mListener; 50 private UserInteractionListener mUIListener; 51 private NinePatchTexture mBackgroundTexture; 52 53 // The layout of FileStripView is 54 // topMargin 55 // ----+----+ 56 // / +----+--\ 57 // contentSize | | thumbSize 58 // \ +----+--/ 59 // ----+----+ 60 // midMargin 61 // ----+----+ 62 // / +----+--\ 63 // barSize | | gripSize 64 // \ +----+--/ 65 // ----+----+ 66 // bottomMargin 67 public FilmStripView(GalleryActivity activity, MediaSet mediaSet, 68 int topMargin, int midMargin, int bottomMargin, int contentSize, 69 int thumbSize, int barSize, int gripSize, int gripWidth) { 70 mTopMargin = topMargin; 71 mMidMargin = midMargin; 72 mBottomMargin = bottomMargin; 73 mContentSize = contentSize; 74 mBarSize = barSize; 75 mGripSize = gripSize; 76 77 mStripDrawer = new StripDrawer((Context) activity); 78 SlotView.Spec spec = new SlotView.Spec(); 79 spec.slotWidth = thumbSize; 80 spec.slotHeight = thumbSize; 81 mAlbumView = new AlbumView(activity, spec, thumbSize); 82 mAlbumView.setOverscrollEffect(SlotView.OVERSCROLL_NONE); 83 mAlbumView.setSelectionDrawer(mStripDrawer); 84 mAlbumView.setListener(new SlotView.SimpleListener() { 85 @Override 86 public void onDown(int index) { 87 FilmStripView.this.onDown(index); 88 } 89 @Override 90 public void onUp() { 91 FilmStripView.this.onUp(); 92 } 93 @Override 94 public void onSingleTapUp(int slotIndex) { 95 FilmStripView.this.onSingleTapUp(slotIndex); 96 } 97 @Override 98 public void onLongTap(int slotIndex) { 99 FilmStripView.this.onLongTap(slotIndex); 100 } 101 @Override 102 public void onScrollPositionChanged(int position, int total) { 103 FilmStripView.this.onScrollPositionChanged(position, total); 104 } 105 }); 106 mAlbumView.setUserInteractionListener(this); 107 mAlbumDataAdapter = new AlbumDataAdapter(activity, mediaSet); 108 addComponent(mAlbumView); 109 mScrollBarView = new ScrollBarView(activity.getAndroidContext(), 110 mGripSize, gripWidth); 111 mScrollBarView.setListener(this); 112 addComponent(mScrollBarView); 113 114 mAlbumView.setModel(mAlbumDataAdapter); 115 mBackgroundTexture = new NinePatchTexture(activity.getAndroidContext(), 116 R.drawable.navstrip_translucent); 117 } 118 119 public void setListener(Listener listener) { 120 mListener = listener; 121 } 122 123 public void setUserInteractionListener(UserInteractionListener listener) { 124 mUIListener = listener; 125 } 126 127 public void show() { 128 if (getVisibility() == GLView.VISIBLE) return; 129 startAnimation(null); 130 setVisibility(GLView.VISIBLE); 131 } 132 133 public void hide() { 134 if (getVisibility() == GLView.INVISIBLE) return; 135 AlphaAnimation animation = new AlphaAnimation(1, 0); 136 animation.setDuration(HIDE_ANIMATION_DURATION); 137 startAnimation(animation); 138 setVisibility(GLView.INVISIBLE); 139 } 140 141 @Override 142 protected void onVisibilityChanged(int visibility) { 143 super.onVisibilityChanged(visibility); 144 if (visibility == GLView.VISIBLE) { 145 onUserInteraction(); 146 } 147 } 148 149 @Override 150 protected void onMeasure(int widthSpec, int heightSpec) { 151 int height = mTopMargin + mContentSize + mMidMargin + mBarSize + mBottomMargin; 152 MeasureHelper.getInstance(this) 153 .setPreferredContentSize(MeasureSpec.getSize(widthSpec), height) 154 .measure(widthSpec, heightSpec); 155 } 156 157 @Override 158 protected void onLayout( 159 boolean changed, int left, int top, int right, int bottom) { 160 if (!changed) return; 161 mAlbumView.layout(0, mTopMargin, right - left, mTopMargin + mContentSize); 162 int barStart = mTopMargin + mContentSize + mMidMargin; 163 mScrollBarView.layout(0, barStart, right - left, barStart + mBarSize); 164 int width = right - left; 165 int height = bottom - top; 166 } 167 168 @Override 169 protected boolean onTouch(MotionEvent event) { 170 // consume all touch events on the "gray area", so they don't go to 171 // the photo view below. (otherwise you can scroll the picture through 172 // it). 173 return true; 174 } 175 176 @Override 177 protected boolean dispatchTouchEvent(MotionEvent event) { 178 switch (event.getAction()) { 179 case MotionEvent.ACTION_DOWN: 180 case MotionEvent.ACTION_MOVE: 181 onUserInteractionBegin(); 182 break; 183 case MotionEvent.ACTION_UP: 184 case MotionEvent.ACTION_CANCEL: 185 onUserInteractionEnd(); 186 break; 187 } 188 189 return super.dispatchTouchEvent(event); 190 } 191 192 @Override 193 protected void render(GLCanvas canvas) { 194 mBackgroundTexture.draw(canvas, 0, 0, getWidth(), getHeight()); 195 super.render(canvas); 196 } 197 198 private void onDown(int index) { 199 MediaItem item = mAlbumDataAdapter.get(index); 200 Path path = (item == null) ? null : item.getPath(); 201 mStripDrawer.setPressedPath(path); 202 mAlbumView.invalidate(); 203 } 204 205 private void onUp() { 206 mStripDrawer.setPressedPath(null); 207 mAlbumView.invalidate(); 208 } 209 210 private void onSingleTapUp(int slotIndex) { 211 if (mListener.onSlotSelected(slotIndex)) { 212 mAlbumView.setFocusIndex(slotIndex); 213 } 214 } 215 216 private void onLongTap(int slotIndex) { 217 onSingleTapUp(slotIndex); 218 } 219 220 private void onScrollPositionChanged(int position, int total) { 221 mScrollBarView.setContentPosition(position, total); 222 } 223 224 // Called by AlbumView 225 @Override 226 public void onUserInteractionBegin() { 227 mUIListener.onUserInteractionBegin(); 228 } 229 230 // Called by AlbumView 231 @Override 232 public void onUserInteractionEnd() { 233 mUIListener.onUserInteractionEnd(); 234 } 235 236 // Called by AlbumView 237 @Override 238 public void onUserInteraction() { 239 mUIListener.onUserInteraction(); 240 } 241 242 // Called by ScrollBarView 243 @Override 244 public void onScrollBarPositionChanged(int position) { 245 mAlbumView.setScrollPosition(position); 246 } 247 248 public void setFocusIndex(int slotIndex) { 249 mAlbumView.setFocusIndex(slotIndex); 250 mAlbumView.makeSlotVisible(slotIndex); 251 } 252 253 public void setStartIndex(int slotIndex) { 254 mAlbumView.setStartIndex(slotIndex); 255 } 256 257 public void pause() { 258 mAlbumView.pause(); 259 mAlbumDataAdapter.pause(); 260 } 261 262 public void resume() { 263 mAlbumView.resume(); 264 mAlbumDataAdapter.resume(); 265 } 266 } 267