blob: 09c8cd2f864da36e4f7003a9816c8fd79622bc12 [file] [log] [blame]
Daniel Sandler524f5682010-10-13 12:13:33 -04001/*
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.ObjectAnimator;
20import android.content.Context;
21import android.util.Slog;
22import android.view.View;
23import android.util.AttributeSet;
24import android.widget.ImageView;
25import android.widget.TextView;
26import android.view.DragEvent;
27import android.view.MotionEvent;
28import android.content.ClipData;
29import android.content.ClipDescription;
30import android.graphics.Paint;
31import android.graphics.Bitmap;
32import android.graphics.Canvas;
33import android.graphics.Point;
34import android.view.WindowManager;
35import android.widget.FrameLayout;
36import android.view.WindowManagerImpl;
37import android.graphics.PixelFormat;
38import android.view.Gravity;
39
40import com.android.systemui.R;
41
42public class ShirtPocket extends FrameLayout {
43 private static final boolean DEBUG = false;
44 private static final String TAG = "StatusBar/ShirtPocket";
45
46 private ClipData mClipping = null;
47
48 private View mWindow = null;
49 private ImageView mIcon;
50 private ImageView mPreviewIcon;
51 private TextView mDescription;
52 private TextView mAltText;
53
54 public ShirtPocket(Context context, AttributeSet attrs) {
55 super(context, attrs);
56 setupWindow();
57 }
58
59 // TODO: "pin area" panel, dragging things out
60 ObjectAnimator mAnimHide, mAnimShow;
61
62 protected void onAttachedToWindow() {
63 // Drag API notes: we must be visible to receive drag events
64 setVisibility(View.VISIBLE);
65
66 mIcon = (ImageView) findViewById(R.id.pocket_icon);
67 refreshStatusIcon();
68
69 setOnClickListener(new View.OnClickListener() {
70 public void onClick(View v) {
71 if (mClipping != null) {
72 if (mWindow.getVisibility() == View.VISIBLE) hideWindow();
73 else showWindow();
74 }
75 }
76 });
77 }
78
79 private void refreshStatusIcon() {
80 setClickable(mClipping != null);
81 mIcon.setImageResource(mClipping == null
82 ? R.drawable.ic_sysbar_pocket_hidden
83 : R.drawable.ic_sysbar_pocket_holding);
84 mIcon.setVisibility(mClipping == null ? View.INVISIBLE : View.VISIBLE);
85 }
86
87 private void showWindow() {
88 getHandler().post(new Runnable() {
89 public void run() {
90 mWindow.setVisibility(View.VISIBLE);
91 refreshStatusIcon();
92 }
93 });
94 }
95
96 private void hideWindow() {
97 getHandler().post(new Runnable() {
98 public void run() {
99 mWindow.setVisibility(View.GONE);
100 refreshStatusIcon();
101 }
102 });
103 }
104
105 private void hideWindowInJustASec() {
106 getHandler().postDelayed(new Runnable() {
107 public void run() {
108 mWindow.setVisibility(View.GONE);
109 refreshStatusIcon();
110 }
111 },
112 250);
113 }
114
115 private void stash(ClipData clipping) {
116 mClipping = clipping;
117 if (mClipping != null) {
118 Bitmap icon = mClipping.getIcon();
Dianne Hackbornf834dfa2010-10-26 12:43:57 -0700119 mDescription.setText(mClipping.getDescription().getLabel());
Daniel Sandler524f5682010-10-13 12:13:33 -0400120 if (icon != null) {
121 mPreviewIcon.setImageBitmap(icon);
122 mPreviewIcon.setVisibility(View.VISIBLE);
123 mAltText.setVisibility(View.GONE);
124 } else {
125 mPreviewIcon.setVisibility(View.GONE);
126 mAltText.setVisibility(View.VISIBLE);
127 if (mClipping.getItemCount() > 0) {
128 // TODO: figure out how to visualize every kind of ClipData!
129 mAltText.setText(mClipping.getItem(0).coerceToText(getContext()));
130 }
131 }
132 }
133 }
134
135 private boolean isInViewContentArea(View v, int x, int y) {
136 final int l = v.getPaddingLeft();
137 final int r = v.getWidth() - v.getPaddingRight();
138 final int t = v.getPaddingTop();
139 final int b = v.getHeight() - v.getPaddingBottom();
140 return x >= l && x < r && y >= t && y < b;
141 }
142
143 View.OnTouchListener mWindowTouchListener = new View.OnTouchListener() {
144 public boolean onTouch(View v, MotionEvent ev) {
145 final int action = ev.getAction();
146 if (action == MotionEvent.ACTION_OUTSIDE
147 || (action == MotionEvent.ACTION_DOWN
148 && !isInViewContentArea(mWindow, (int)ev.getX(), (int)ev.getY()))) {
149 hideWindow();
150 return true;
151 } else if (action == MotionEvent.ACTION_DOWN) {
152 Slog.d(TAG, "ACTION_DOWN");
153 final ClipData clip = mClipping;
154 if (clip != null) {
155 final Bitmap icon = clip.getIcon();
156 DragThumbnailBuilder thumb;
157 if (icon != null) {
158 thumb = new DragThumbnailBuilder(v) {
159 public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
160 thumbnailSize.set(icon.getWidth(), icon.getHeight());
161 thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
162 }
163 public void onDrawThumbnail(Canvas canvas) {
164 canvas.drawBitmap(icon, 0, 0, new Paint());
165 }
166 };
167 } else {
168 // uhhh, what now?
169 thumb = new DragThumbnailBuilder(mWindow.findViewById(R.id.preview));
170 }
171
Chris Tate213b30e2010-10-22 19:11:18 -0700172 v.startDrag(clip, thumb, false);
Daniel Sandler524f5682010-10-13 12:13:33 -0400173
174 // TODO: only discard the clipping if it was accepted
175 stash(null);
176
177 hideWindowInJustASec(); // will refresh the icon
178
179 return true;
180 }
181 }
182 return false;
183 }
184 };
185
186 private void setupWindow() {
187 mWindow = View.inflate(getContext(), R.layout.sysbar_panel_pocket, null);
188
189 mPreviewIcon = (ImageView) mWindow.findViewById(R.id.icon);
190 mDescription = (TextView) mWindow.findViewById(R.id.description);
191 mAltText = (TextView) mWindow.findViewById(R.id.alt);
192
193 mWindow.setVisibility(View.GONE);
194 mWindow.setOnTouchListener(mWindowTouchListener);
195 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
196 400,
197 250,
198 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
199 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
Jeff Brown46e75292010-11-10 16:53:45 -0800200 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
201 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Daniel Sandler524f5682010-10-13 12:13:33 -0400202 PixelFormat.TRANSLUCENT);
203 lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
204// int pos[] = new int[2];
205// getLocationOnScreen(pos);
206// lp.x = pos[1];
207// lp.y = 0;
208 lp.setTitle("ShirtPocket");
209 lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
210
211 WindowManagerImpl.getDefault().addView(mWindow, lp);
212
213 }
214
215 public boolean onDragEvent(DragEvent event) {
216 if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
217 if (mIcon != null) {
218 switch (event.getAction()) {
219 // We want to appear whenever a potential drag takes off from anywhere in the UI.
220 case DragEvent.ACTION_DRAG_STARTED:
221 mIcon.setImageResource(mClipping == null
222 ? R.drawable.ic_sysbar_pocket
223 : R.drawable.ic_sysbar_pocket_holding);
224 mIcon.setVisibility(View.VISIBLE);
225 break;
226 case DragEvent.ACTION_DRAG_ENTERED:
227 if (DEBUG) Slog.d(TAG, "entered!");
228 mIcon.setImageResource(R.drawable.ic_sysbar_pocket_drag);
229 break;
230 case DragEvent.ACTION_DRAG_EXITED:
231 if (DEBUG) Slog.d(TAG, "exited!");
232 mIcon.setImageResource(mClipping == null
233 ? R.drawable.ic_sysbar_pocket
234 : R.drawable.ic_sysbar_pocket_holding);
235 break;
236 case DragEvent.ACTION_DROP:
237 if (DEBUG) Slog.d(TAG, "dropped!");
238 stash(event.getClipData());
239 refreshStatusIcon();
240 break;
241 case DragEvent.ACTION_DRAG_ENDED:
242 refreshStatusIcon();
243 break;
244 }
245 }
246 return true; // we want everything, thank you
247 }
248}
249