ShirtPocket.java revision 98365d7663cbd82979a5700faf0050220b01084d
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 17package com.android.systemui.statusbar.tablet; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ObjectAnimator; 22import android.content.ClipData; 23import android.content.ClipDescription; 24import android.content.Context; 25import android.graphics.Bitmap; 26import android.graphics.Canvas; 27import android.graphics.Paint; 28import android.graphics.PixelFormat; 29import android.graphics.Point; 30import android.util.AttributeSet; 31import android.util.Slog; 32import android.view.DragEvent; 33import android.view.Gravity; 34import android.view.MotionEvent; 35import android.view.View; 36import android.view.WindowManager; 37import android.widget.FrameLayout; 38import android.widget.ImageView; 39import android.widget.TextView; 40 41import com.android.systemui.R; 42 43public class ShirtPocket extends ImageView { 44 private static final boolean DEBUG = false; 45 private static final String TAG = "StatusBar/ShirtPocket"; 46 47 private ClipData mClipping = null; 48 49 private ImageView mPreviewIcon; 50 51 public static class DropZone extends View { 52 ShirtPocket mPocket; 53 public DropZone(Context context, AttributeSet attrs) { 54 super(context, attrs); 55 } 56 public void setPocket(ShirtPocket p) { 57 mPocket = p; 58 } 59 60 public void onAttachedToWindow() { 61 super.onAttachedToWindow(); 62 if (mPocket.holding()) { 63 show(false); 64 } else { 65 hide(false); 66 } 67 } 68 69 // Drag API notes: we must be visible to receive drag events 70 private void show(boolean animate) { 71 setTranslationY(0f); 72 if (animate) { 73 setAlpha(0f); 74 ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).start(); 75 } else { 76 setAlpha(1f); 77 } 78 } 79 80 private void hide(boolean animate) { 81 AnimatorListenerAdapter onEnd = new AnimatorListenerAdapter() { 82 @Override 83 public void onAnimationEnd(Animator _a) { 84 DropZone.this.setTranslationY(getHeight() + 2); 85 DropZone.this.setAlpha(0f); 86 } 87 }; 88 if (animate) { 89 Animator a = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), 0f); 90 a.addListener(onEnd); 91 a.start(); 92 } else { 93 onEnd.onAnimationEnd(null); 94 } 95 } 96 97 @Override 98 public boolean onDragEvent(DragEvent event) { 99 if (DEBUG) Slog.d(TAG, "onDragEvent: " + event); 100 switch (event.getAction()) { 101 // We want to appear whenever a potential drag takes off from anywhere in the UI. 102 case DragEvent.ACTION_DRAG_STARTED: 103 show(true); 104 break; 105 case DragEvent.ACTION_DRAG_ENTERED: 106 if (DEBUG) Slog.d(TAG, "entered!"); 107 // XXX: TODO 108 break; 109 case DragEvent.ACTION_DRAG_EXITED: 110 if (DEBUG) Slog.d(TAG, "exited!"); 111 break; 112 case DragEvent.ACTION_DROP: 113 if (DEBUG) Slog.d(TAG, "dropped!"); 114 mPocket.stash(event.getClipData()); 115 break; 116 case DragEvent.ACTION_DRAG_ENDED: 117 hide(true); 118 break; 119 } 120 return true; // we want everything, thank you 121 } 122 } 123 124 public ShirtPocket(Context context, AttributeSet attrs) { 125 super(context, attrs); 126 } 127 128 // TODO: "pin area" panel, dragging things out 129 ObjectAnimator mAnimHide, mAnimShow; 130 131 protected void onAttachedToWindow() { 132 } 133 134 public boolean holding() { 135 return (mClipping != null); 136 } 137 138 private void stash(ClipData clipping) { 139 mClipping = clipping; 140 if (mClipping != null) { 141 setVisibility(View.VISIBLE); 142 Bitmap icon = mClipping.getIcon(); 143// mDescription.setText(mClipping.getDescription().getLabel()); 144 if (icon != null) { 145 setImageBitmap(icon); 146 } else { 147 if (mClipping.getItemCount() > 0) { 148 // TODO: figure out how to visualize every kind of ClipData! 149 //mAltText.setText(mClipping.getItemAt(0).coerceToText(getContext())); 150 } 151 } 152 } else { 153 setVisibility(View.GONE); 154 } 155 } 156 157 @Override 158 public boolean onTouchEvent(MotionEvent ev) { 159 final int action = ev.getAction(); 160 if (action == MotionEvent.ACTION_DOWN) { 161 final ClipData clip = mClipping; 162 if (clip != null) { 163 final Bitmap icon = clip.getIcon(); 164 DragShadowBuilder shadow; 165 if (icon != null) { 166 shadow = new DragShadowBuilder(this) { 167 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 168 shadowSize.set(icon.getWidth(), icon.getHeight()); 169 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 170 } 171 public void onDrawShadow(Canvas canvas) { 172 canvas.drawBitmap(icon, 0, 0, new Paint()); 173 } 174 }; 175 } else { 176 // uhhh, what now? 177 shadow = new DragShadowBuilder(this); 178 } 179 180 startDrag(clip, shadow, null, 0); 181 182 // TODO: only discard the clipping if it was accepted 183 stash(null); 184 185 return true; 186 } 187 } 188 return false; 189 } 190 191 /* 192 private boolean isInViewContentArea(View v, int x, int y) { 193 final int l = v.getPaddingLeft(); 194 final int r = v.getWidth() - v.getPaddingRight(); 195 final int t = v.getPaddingTop(); 196 final int b = v.getHeight() - v.getPaddingBottom(); 197 return x >= l && x < r && y >= t && y < b; 198 } 199 200 View.OnTouchListener mWindowTouchListener = new View.OnTouchListener() { 201 public boolean onTouch(View v, MotionEvent ev) { 202 final int action = ev.getAction(); 203 if (action == MotionEvent.ACTION_OUTSIDE 204 || (action == MotionEvent.ACTION_DOWN 205 && !isInViewContentArea(mWindow, (int)ev.getX(), (int)ev.getY()))) { 206 hideWindow(); 207 return true; 208 } else if (action == MotionEvent.ACTION_DOWN) { 209 final ClipData clip = mClipping; 210 if (clip != null) { 211 final Bitmap icon = clip.getIcon(); 212 DragShadowBuilder shadow; 213 if (icon != null) { 214 shadow = new DragShadowBuilder(v) { 215 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 216 shadowSize.set(icon.getWidth(), icon.getHeight()); 217 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 218 } 219 public void onDrawShadow(Canvas canvas) { 220 canvas.drawBitmap(icon, 0, 0, new Paint()); 221 } 222 }; 223 } else { 224 // uhhh, what now? 225 shadow = new DragShadowBuilder(mWindow.findViewById(R.id.preview)); 226 } 227 228 v.startDrag(clip, shadow, null, 0); 229 230 // TODO: only discard the clipping if it was accepted 231 stash(null); 232 233 return true; 234 } 235 } 236 return false; 237 } 238 }; 239 */ 240} 241 242