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