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