content: /*
   * Copyright (C) 2008 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.lb.launcher;
  
  import com.lb.launcher.R;
  import android.animation.ValueAnimator;
  import android.animation.ValueAnimator.AnimatorUpdateListener;
  import android.content.res.Resources;
  import android.graphics.Bitmap;
  import android.graphics.Canvas;
  import android.graphics.Paint;
  import android.graphics.Point;
  import android.graphics.PorterDuff;
  import android.graphics.PorterDuffColorFilter;
  import android.graphics.Rect;
  import android.view.View;
  import android.view.animation.DecelerateInterpolator;
  
  public class DragView extends View {
      private static float sDragAlpha = 1f;
  
      private Bitmap mBitmap;
      private Bitmap mCrossFadeBitmap;
      private Paint mPaint;
      private int mRegistrationX;
      private int mRegistrationY;
  
      private Point mDragVisualizeOffset = null;
      private Rect mDragRegion = null;
      private DragLayer mDragLayer = null;
      private boolean mHasDrawn = false;
      private float mCrossFadeProgress = 0f;
  
      ValueAnimator mAnim;
      private float mOffsetX = 0.0f;
      private float mOffsetY = 0.0f;
      private float mInitialScale = 1f;
      // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
      // size.  This is ignored for non-icons.
      private float mIntrinsicIconScale = 1f;
  
      /**
       * Construct the drag view.
       * <p>
       * The registration point is the point inside our view that the touch events should
       * be centered upon.
       *
       * @param launcher The Launcher instance
       * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
       * @param registrationX The x coordinate of the registration point.
       * @param registrationY The y coordinate of the registration point.
       */
      public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
              int left, int top, int width, int height, final float initialScale) {
          super(launcher);
          mDragLayer = launcher.getDragLayer();
          mInitialScale = initialScale;
  
          final Resources res = getResources();
          final float offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
          final float offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
          final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
          final float scale = (width + scaleDps) / width;
  
          // Set the initial scale to avoid any jumps
          setScaleX(initialScale);
          setScaleY(initialScale);
  
          // Animate the view into the correct position
          mAnim = LauncherAnimUtils.ofFloat(this, 0f, 1f);
          mAnim.setDuration(150);
          mAnim.addUpdateListener(new AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                  final float value = (Float) animation.getAnimatedValue();
  
                  final int deltaX = (int) ((value * offsetX) - mOffsetX);
                  final int deltaY = (int) ((value * offsetY) - mOffsetY);
  
                  mOffsetX += deltaX;
                  mOffsetY += deltaY;
                  setScaleX(initialScale + (value * (scale - initialScale)));
                  setScaleY(initialScale + (value * (scale - initialScale)));
                  if (sDragAlpha != 1f) {
                      setAlpha(sDragAlpha * value + (1f - value));
                  }
  
                  if (getParent() == null) {
                      animation.cancel();
                  } else {
                      setTranslationX(getTranslationX() + deltaX);
                      setTranslationY(getTranslationY() + deltaY);
                  }
              }
          });
  
          mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height);
          setDragRegion(new Rect(0, 0, width, height));
  
          // The point in our scaled bitmap that the touch events are located
          mRegistrationX = registrationX;
          mRegistrationY = registrationY;
  
          // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
          int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
          measure(ms, ms);
          mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
      }
  
      /** Sets the scale of the view over the normal workspace icon size. */
      public void setIntrinsicIconScaleFactor(float scale) {
          mIntrinsicIconScale = scale;
      }
  
      public float getIntrinsicIconScaleFactor() {
          return mIntrinsicIconScale;
      }
  
      public float getOffsetY() {
          return mOffsetY;
      }
  
      public int getDragRegionLeft() {
          return mDragRegion.left;
      }
  
      public int getDragRegionTop() {
          return mDragRegion.top;
      }
  
      public int getDragRegionWidth() {
          return mDragRegion.width();
      }
  
      public int getDragRegionHeight() {
          return mDragRegion.height();
      }
  
      public void setDragVisualizeOffset(Point p) {
          mDragVisualizeOffset = p;
      }
  
      public Point getDragVisualizeOffset() {
          return mDragVisualizeOffset;
      }
  
      public void setDragRegion(Rect r) {
          mDragRegion = r;
      }
  
      public Rect getDragRegion() {
          return mDragRegion;
      }
  
      public float getInitialScale() {
          return mInitialScale;
      }
  
      public void updateInitialScaleToCurrentScale() {
          mInitialScale = getScaleX();
      }
  
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight());
      }
  
      @Override
      protected void onDraw(Canvas canvas) {
          @SuppressWarnings("all") // suppress dead code warning
          final boolean debug = false;
          if (debug) {
              Paint p = new Paint();
              p.setStyle(Paint.Style.FILL);
              p.setColor(0x66ffffff);
              canvas.drawRect(0, 0, getWidth(), getHeight(), p);
          }
  
          mHasDrawn = true;
          boolean crossFade = mCrossFadeProgress > 0 && mCrossFadeBitmap != null;
          if (crossFade) {
              int alpha = crossFade ? (int) (255 * (1 - mCrossFadeProgress)) : 255;
              mPaint.setAlpha(alpha);
          }
          canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
          if (crossFade) {
              mPaint.setAlpha((int) (255 * mCrossFadeProgress));
              canvas.save();
              float sX = (mBitmap.getWidth() * 1.0f) / mCrossFadeBitmap.getWidth();
              float sY = (mBitmap.getHeight() * 1.0f) / mCrossFadeBitmap.getHeight();
              canvas.scale(sX, sY);
              canvas.drawBitmap(mCrossFadeBitmap, 0.0f, 0.0f, mPaint);
              canvas.restore();
          }
      }
  
      public void setCrossFadeBitmap(Bitmap crossFadeBitmap) {
          mCrossFadeBitmap = crossFadeBitmap;
      }
  
      public void crossFade(int duration) {
          ValueAnimator va = LauncherAnimUtils.ofFloat(this, 0f, 1f);
          va.setDuration(duration);
          va.setInterpolator(new DecelerateInterpolator(1.5f));
          va.addUpdateListener(new AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                  mCrossFadeProgress = animation.getAnimatedFraction();
              }
          });
          va.start();
      }
  
      public void setColor(int color) {
          if (mPaint == null) {
              mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
          }
          if (color != 0) {
              mPaint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
          } else {
              mPaint.setColorFilter(null);
          }
          invalidate();
      }
  
      public boolean hasDrawn() {
          return mHasDrawn;
      }
  
      @Override
      public void setAlpha(float alpha) {
          super.setAlpha(alpha);
          mPaint.setAlpha((int) (255 * alpha));
          invalidate();
      }
  
      /**
       * Create a window containing this view and show it.
       *
       * @param windowToken obtained from v.getWindowToken() from one of your views
       * @param touchX the x coordinate the user touched in DragLayer coordinates
       * @param touchY the y coordinate the user touched in DragLayer coordinates
       */
      public void show(int touchX, int touchY) {
          mDragLayer.addView(this);
  
          // Start the pick-up animation
          DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
          lp.width = mBitmap.getWidth();
          lp.height = mBitmap.getHeight();
          lp.customPosition = true;
          setLayoutParams(lp);
          setTranslationX(touchX - mRegistrationX);
          setTranslationY(touchY - mRegistrationY);
          // Post the animation to skip other expensive work happening on the first frame
          post(new Runnable() {
                  public void run() {
                      mAnim.start();
                  }
              });
      }
  
      public void cancelAnimation() {
          if (mAnim != null && mAnim.isRunning()) {
              mAnim.cancel();
          }
      }
  
      public void resetLayoutParams() {
          mOffsetX = mOffsetY = 0;
          requestLayout();
      }
  
      /**
       * Move the window containing this view.
       *
       * @param touchX the x coordinate the user touched in DragLayer coordinates
       * @param touchY the y coordinate the user touched in DragLayer coordinates
       */
      void move(int touchX, int touchY) {
          setTranslationX(touchX - mRegistrationX + (int) mOffsetX);
          setTranslationY(touchY - mRegistrationY + (int) mOffsetY);
      }
  
      void remove() {
          if (getParent() != null) {
              mDragLayer.removeView(DragView.this);
          }
      }
  }
  
  