1 /* 2 * Copyright (C) 2012 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 android.content.Context; 20 import android.view.MotionEvent; 21 22 import com.android.gallery3d.R; 23 import com.android.gallery3d.common.Utils; 24 import com.android.gallery3d.glrenderer.GLCanvas; 25 import com.android.gallery3d.glrenderer.NinePatchTexture; 26 import com.android.gallery3d.glrenderer.ResourceTexture; 27 import com.android.gallery3d.glrenderer.StringTexture; 28 import com.android.gallery3d.util.GalleryUtils; 29 30 public class UndoBarView extends GLView { 31 @SuppressWarnings("unused") 32 private static final String TAG = "UndoBarView"; 33 34 private static final int WHITE = 0xFFFFFFFF; 35 private static final int GRAY = 0xFFAAAAAA; 36 37 private final NinePatchTexture mPanel; 38 private final StringTexture mUndoText; 39 private final StringTexture mDeletedText; 40 private final ResourceTexture mUndoIcon; 41 private final int mBarHeight; 42 private final int mBarMargin; 43 private final int mUndoTextMargin; 44 private final int mIconSize; 45 private final int mIconMargin; 46 private final int mSeparatorTopMargin; 47 private final int mSeparatorBottomMargin; 48 private final int mSeparatorRightMargin; 49 private final int mSeparatorWidth; 50 private final int mDeletedTextMargin; 51 private final int mClickRegion; 52 53 private OnClickListener mOnClickListener; 54 private boolean mDownOnButton; 55 56 // This is the layout of UndoBarView. The unit is dp. 57 // 58 // +-+----+----------------+-+--+----+-+------+--+-+ 59 // 48 | | | Deleted | | | <- | | UNDO | | | 60 // +-+----+----------------+-+--+----+-+------+--+-+ 61 // 4 16 1 12 32 8 16 4 UndoBarView(Context context)62 public UndoBarView(Context context) { 63 mBarHeight = GalleryUtils.dpToPixel(48); 64 mBarMargin = GalleryUtils.dpToPixel(4); 65 mUndoTextMargin = GalleryUtils.dpToPixel(16); 66 mIconMargin = GalleryUtils.dpToPixel(8); 67 mIconSize = GalleryUtils.dpToPixel(32); 68 mSeparatorRightMargin = GalleryUtils.dpToPixel(12); 69 mSeparatorTopMargin = GalleryUtils.dpToPixel(10); 70 mSeparatorBottomMargin = GalleryUtils.dpToPixel(10); 71 mSeparatorWidth = GalleryUtils.dpToPixel(1); 72 mDeletedTextMargin = GalleryUtils.dpToPixel(16); 73 74 mPanel = new NinePatchTexture(context, R.drawable.panel_undo_holo); 75 mUndoText = StringTexture.newInstance(context.getString(R.string.undo), 76 GalleryUtils.dpToPixel(12), GRAY, 0, true); 77 mDeletedText = StringTexture.newInstance( 78 context.getString(R.string.deleted), 79 GalleryUtils.dpToPixel(16), WHITE); 80 mUndoIcon = new ResourceTexture( 81 context, R.drawable.ic_menu_revert_holo_dark); 82 mClickRegion = mBarMargin + mUndoTextMargin + mUndoText.getWidth() 83 + mIconMargin + mIconSize + mSeparatorRightMargin; 84 } 85 setOnClickListener(OnClickListener listener)86 public void setOnClickListener(OnClickListener listener) { 87 mOnClickListener = listener; 88 } 89 90 @Override onMeasure(int widthSpec, int heightSpec)91 protected void onMeasure(int widthSpec, int heightSpec) { 92 setMeasuredSize(0 /* unused */, mBarHeight); 93 } 94 95 @Override render(GLCanvas canvas)96 protected void render(GLCanvas canvas) { 97 super.render(canvas); 98 advanceAnimation(); 99 100 canvas.save(GLCanvas.SAVE_FLAG_ALPHA); 101 canvas.multiplyAlpha(mAlpha); 102 103 int w = getWidth(); 104 int h = getHeight(); 105 mPanel.draw(canvas, mBarMargin, 0, w - mBarMargin * 2, mBarHeight); 106 107 int x = w - mBarMargin; 108 int y; 109 110 x -= mUndoTextMargin + mUndoText.getWidth(); 111 y = (mBarHeight - mUndoText.getHeight()) / 2; 112 mUndoText.draw(canvas, x, y); 113 114 x -= mIconMargin + mIconSize; 115 y = (mBarHeight - mIconSize) / 2; 116 mUndoIcon.draw(canvas, x, y, mIconSize, mIconSize); 117 118 x -= mSeparatorRightMargin + mSeparatorWidth; 119 y = mSeparatorTopMargin; 120 canvas.fillRect(x, y, mSeparatorWidth, 121 mBarHeight - mSeparatorTopMargin - mSeparatorBottomMargin, GRAY); 122 123 x = mBarMargin + mDeletedTextMargin; 124 y = (mBarHeight - mDeletedText.getHeight()) / 2; 125 mDeletedText.draw(canvas, x, y); 126 127 canvas.restore(); 128 } 129 130 @Override onTouch(MotionEvent event)131 protected boolean onTouch(MotionEvent event) { 132 switch (event.getAction()) { 133 case MotionEvent.ACTION_DOWN: 134 mDownOnButton = inUndoButton(event); 135 break; 136 case MotionEvent.ACTION_UP: 137 if (mDownOnButton) { 138 if (mOnClickListener != null && inUndoButton(event)) { 139 mOnClickListener.onClick(this); 140 } 141 mDownOnButton = false; 142 } 143 break; 144 case MotionEvent.ACTION_CANCEL: 145 mDownOnButton = false; 146 break; 147 } 148 return true; 149 } 150 151 // Check if the event is on the right of the separator inUndoButton(MotionEvent event)152 private boolean inUndoButton(MotionEvent event) { 153 float x = event.getX(); 154 float y = event.getY(); 155 int w = getWidth(); 156 int h = getHeight(); 157 return (x >= w - mClickRegion && x < w && y >= 0 && y < h); 158 } 159 160 //////////////////////////////////////////////////////////////////////////// 161 // Alpha Animation 162 //////////////////////////////////////////////////////////////////////////// 163 164 private static final long NO_ANIMATION = -1; 165 private static long ANIM_TIME = 200; 166 private long mAnimationStartTime = NO_ANIMATION; 167 private float mFromAlpha, mToAlpha; 168 private float mAlpha; 169 getTargetAlpha(int visibility)170 private static float getTargetAlpha(int visibility) { 171 return (visibility == VISIBLE) ? 1f : 0f; 172 } 173 174 @Override setVisibility(int visibility)175 public void setVisibility(int visibility) { 176 mAlpha = getTargetAlpha(visibility); 177 mAnimationStartTime = NO_ANIMATION; 178 super.setVisibility(visibility); 179 invalidate(); 180 } 181 animateVisibility(int visibility)182 public void animateVisibility(int visibility) { 183 float target = getTargetAlpha(visibility); 184 if (mAnimationStartTime == NO_ANIMATION && mAlpha == target) return; 185 if (mAnimationStartTime != NO_ANIMATION && mToAlpha == target) return; 186 187 mFromAlpha = mAlpha; 188 mToAlpha = target; 189 mAnimationStartTime = AnimationTime.startTime(); 190 191 super.setVisibility(VISIBLE); 192 invalidate(); 193 } 194 advanceAnimation()195 private void advanceAnimation() { 196 if (mAnimationStartTime == NO_ANIMATION) return; 197 198 float delta = (float) (AnimationTime.get() - mAnimationStartTime) / 199 ANIM_TIME; 200 mAlpha = mFromAlpha + ((mToAlpha > mFromAlpha) ? delta : -delta); 201 mAlpha = Utils.clamp(mAlpha, 0f, 1f); 202 203 if (mAlpha == mToAlpha) { 204 mAnimationStartTime = NO_ANIMATION; 205 if (mAlpha == 0) { 206 super.setVisibility(INVISIBLE); 207 } 208 } 209 invalidate(); 210 } 211 } 212