1/*
2 * Copyright (C) 2008 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
18package com.android.launcher2;
19
20import android.content.Context;
21import android.content.res.TypedArray;
22import android.graphics.Bitmap;
23import android.graphics.Canvas;
24import android.graphics.Matrix;
25import android.graphics.Paint;
26import android.graphics.PixelFormat;
27import android.graphics.Point;
28import android.os.IBinder;
29import android.util.AttributeSet;
30import android.util.Log;
31import android.view.Gravity;
32import android.view.View;
33import android.view.ViewGroup;
34import android.view.KeyEvent;
35import android.view.WindowManager;
36import android.view.WindowManagerImpl;
37
38public class DragView extends View implements TweenCallback {
39    // Number of pixels to add to the dragged item for scaling.  Should be even for pixel alignment.
40    private static final int DRAG_SCALE = 40;
41
42    private Bitmap mBitmap;
43    private Paint mPaint;
44    private int mRegistrationX;
45    private int mRegistrationY;
46
47    SymmetricalLinearTween mTween;
48    private float mScale;
49    private float mAnimationScale = 1.0f;
50
51    private WindowManager.LayoutParams mLayoutParams;
52    private WindowManager mWindowManager;
53
54    /**
55     * Construct the drag view.
56     * <p>
57     * The registration point is the point inside our view that the touch events should
58     * be centered upon.
59     *
60     * @param context A context
61     * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
62     * @param registrationX The x coordinate of the registration point.
63     * @param registrationY The y coordinate of the registration point.
64     */
65    public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY,
66            int left, int top, int width, int height) {
67        super(context);
68
69        mWindowManager = WindowManagerImpl.getDefault();
70
71        mTween = new SymmetricalLinearTween(false, 110 /*ms duration*/, this);
72
73        Matrix scale = new Matrix();
74        float scaleFactor = width;
75        scaleFactor = mScale = (scaleFactor + DRAG_SCALE) / scaleFactor;
76        scale.setScale(scaleFactor, scaleFactor);
77
78        mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
79
80        // The point in our scaled bitmap that the touch events are located
81        mRegistrationX = registrationX + (DRAG_SCALE / 2);
82        mRegistrationY = registrationY + (DRAG_SCALE / 2);
83    }
84
85    @Override
86    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
87        setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight());
88    }
89
90    @Override
91    protected void onDraw(Canvas canvas) {
92        if (false) {
93            // for debugging
94            Paint p = new Paint();
95            p.setStyle(Paint.Style.FILL);
96            p.setColor(0xaaffffff);
97            canvas.drawRect(0, 0, getWidth(), getHeight(), p);
98        }
99        float scale = mAnimationScale;
100        if (scale < 0.999f) { // allow for some float error
101            float width = mBitmap.getWidth();
102            float offset = (width-(width*scale))/2;
103            canvas.translate(offset, offset);
104            canvas.scale(scale, scale);
105        }
106        canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
107    }
108
109    @Override
110    protected void onDetachedFromWindow() {
111        super.onDetachedFromWindow();
112        mBitmap.recycle();
113    }
114
115    public void onTweenValueChanged(float value, float oldValue) {
116        mAnimationScale = (1.0f+((mScale-1.0f)*value))/mScale;
117        invalidate();
118    }
119
120    public void onTweenStarted() {
121    }
122
123    public void onTweenFinished() {
124    }
125
126    public void setPaint(Paint paint) {
127        mPaint = paint;
128        invalidate();
129    }
130
131    /**
132     * Create a window containing this view and show it.
133     *
134     * @param windowToken obtained from v.getWindowToken() from one of your views
135     * @param touchX the x coordinate the user touched in screen coordinates
136     * @param touchY the y coordinate the user touched in screen coordinates
137     */
138    public void show(IBinder windowToken, int touchX, int touchY) {
139        WindowManager.LayoutParams lp;
140        int pixelFormat;
141
142        pixelFormat = PixelFormat.TRANSLUCENT;
143
144        lp = new WindowManager.LayoutParams(
145                ViewGroup.LayoutParams.WRAP_CONTENT,
146                ViewGroup.LayoutParams.WRAP_CONTENT,
147                touchX-mRegistrationX, touchY-mRegistrationY,
148                WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
149                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
150                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
151                    /*| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM*/,
152                pixelFormat);
153//        lp.token = mStatusBarView.getWindowToken();
154        lp.gravity = Gravity.LEFT | Gravity.TOP;
155        lp.token = windowToken;
156        lp.setTitle("DragView");
157        mLayoutParams = lp;
158
159        mWindowManager.addView(this, lp);
160
161        mAnimationScale = 1.0f/mScale;
162        mTween.start(true);
163    }
164
165    /**
166     * Move the window containing this view.
167     *
168     * @param touchX the x coordinate the user touched in screen coordinates
169     * @param touchY the y coordinate the user touched in screen coordinates
170     */
171    void move(int touchX, int touchY) {
172        WindowManager.LayoutParams lp = mLayoutParams;
173        lp.x = touchX - mRegistrationX;
174        lp.y = touchY - mRegistrationY;
175        mWindowManager.updateViewLayout(this, lp);
176    }
177
178    void remove() {
179        mWindowManager.removeView(this);
180    }
181}
182
183