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