gt:                 final LayoutParams lp = (LayoutParams) flp;
context: /*
   * 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.lesikapk.opengelplus;
  
  import java.util.ArrayList;
  
  import android.animation.Animator;
  import android.animation.AnimatorListenerAdapter;
  import android.animation.TimeInterpolator;
  import android.animation.ValueAnimator;
  import android.animation.ValueAnimator.AnimatorUpdateListener;
  import android.content.Context;
  import android.content.res.Resources;
  import android.graphics.Canvas;
  import android.graphics.Rect;
  import android.graphics.drawable.Drawable;
  import android.util.AttributeSet;
  import android.view.KeyEvent;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.accessibility.AccessibilityEvent;
  import android.view.accessibility.AccessibilityManager;
  import android.view.animation.DecelerateInterpolator;
  import android.view.animation.Interpolator;
  import android.widget.FrameLayout;
  import android.widget.TextView;
  
  /**
   * A ViewGroup that coordinates dragging across its descendants
   */
  public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
      private DragController mDragController;
      private int[] mTmpXY = new int[2];
  
      private int mXDown, mYDown;
      private Launcher mLauncher;
  
      // Variables relating to resizing widgets
      private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
              new ArrayList<AppWidgetResizeFrame>();
      private AppWidgetResizeFrame mCurrentResizeFrame;
  
      // Variables relating to animation of views after drop
      private ValueAnimator mDropAnim = null;
      private ValueAnimator mFadeOutAnim = null;
      private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
      private DragView mDropView = null;
      private int mAnchorViewInitialScrollX = 0;
      private View mAnchorView = null;
  
      private boolean mHoverPointClosesFolder = false;
      private Rect mHitRect = new Rect();
      private int mWorkspaceIndex = -1;
      private int mQsbIndex = -1;
      public static final int ANIMATION_END_DISAPPEAR = 0;
      public static final int ANIMATION_END_FADE_OUT = 1;
      public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
  
      private TouchCompleteListener mTouchCompleteListener;
  
      private final Rect mInsets = new Rect();
  
      /**
       * Used to create a new DragLayer from XML.
       *
       * @param context The application's context.
       * @param attrs The attributes set containing the Workspace's customization values.
       */
      public DragLayer(Context context, AttributeSet attrs) {
          super(context, attrs);
  
          // Disable multitouch across the workspace/all apps/customize tray
          setMotionEventSplittingEnabled(false);
          setChildrenDrawingOrderEnabled(true);
          setOnHierarchyChangeListener(this);
  
          mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo);
          mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo);
      }
  
      public void setup(Launcher launcher, DragController controller) {
          mLauncher = launcher;
          mDragController = controller;
      }
  
      @Override
      public boolean dispatchKeyEvent(KeyEvent event) {
          return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
      }
  
      @Override
      protected boolean fitSystemWindows(Rect insets) {
          final int n = getChildCount();
          for (int i = 0; i < n; i++) {
              final View child = getChildAt(i);
              final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
              if (child instanceof Insettable) {
                  ((Insettable)child).setInsets(insets);
              } else {
                  flp.topMargin += (insets.top - mInsets.top);
                  flp.leftMargin += (insets.left - mInsets.left);
                  flp.rightMargin += (insets.right - mInsets.right);
                  flp.bottomMargin += (insets.bottom - mInsets.bottom);
              }
              child.setLayoutParams(flp);
          }
          mInsets.set(insets);
          return true; // I'll take it from here
      }
  
      private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
          getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
          if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
              return true;
          }
          return false;
      }
  
      private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
          getDescendantRectRelativeToSelf(folder, mHitRect);
          if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
              return true;
          }
          return false;
      }
  
      private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
          Rect hitRect = new Rect();
          int x = (int) ev.getX();
          int y = (int) ev.getY();
  
          for (AppWidgetResizeFrame child: mResizeFrames) {
              child.getHitRect(hitRect);
              if (hitRect.contains(x, y)) {
                  if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
                      mCurrentResizeFrame = child;
                      mXDown = x;
                      mYDown = y;
                      requestDisallowInterceptTouchEvent(true);
                      return true;
                  }
              }
          }
  
          Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
          if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
              if (currentFolder.isEditingName()) {
                  if (!isEventOverFolderTextRegion(currentFolder, ev)) {
                      currentFolder.dismissEditingName();
                      return true;
                  }
              }
  
              getDescendantRectRelativeToSelf(currentFolder, hitRect);
              if (!isEventOverFolder(currentFolder, ev)) {
                  mLauncher.closeFolder();
                  return true;
              }
          }
          return false;
      }
  
      @Override
      public boolean onInterceptTouchEvent(MotionEvent ev) {
          int action = ev.getAction();
  
          if (action == MotionEvent.ACTION_DOWN) {
              if (handleTouchDown(ev, true)) {
                  return true;
              }
          } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
              if (mTouchCompleteListener != null) {
                  mTouchCompleteListener.onTouchComplete();
              }
              mTouchCompleteListener = null;
          }
          clearAllResizeFrames();
          return mDragController.onInterceptTouchEvent(ev);
      }
  
      @Override
      public boolean onInterceptHoverEvent(MotionEvent ev) {
          if (mLauncher == null || mLauncher.getWorkspace() == null) {
              return false;
          }
          Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
          if (currentFolder == null) {
              return false;
          } else {
                  AccessibilityManager accessibilityManager = (AccessibilityManager)
                          getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
              if (accessibilityManager.isTouchExplorationEnabled()) {
                  final int action = ev.getAction();
                  boolean isOverFolder;
                  switch (action) {
                      case MotionEvent.ACTION_HOVER_ENTER:
                          isOverFolder = isEventOverFolder(currentFolder, ev);
                          if (!isOverFolder) {
                              sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
                              mHoverPointClosesFolder = true;
                              return true;
                          } else if (isOverFolder) {
                              mHoverPointClosesFolder = false;
                          } else {
                              return true;
                          }
                      case MotionEvent.ACTION_HOVER_MOVE:
                          isOverFolder = isEventOverFolder(currentFolder, ev);
                          if (!isOverFolder && !mHoverPointClosesFolder) {
                              sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
                              mHoverPointClosesFolder = true;
                              return true;
                          } else if (isOverFolder) {
                              mHoverPointClosesFolder = false;
                          } else {
                              return true;
                          }
                  }
              }
          }
          return false;
      }
  
      private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
          AccessibilityManager accessibilityManager = (AccessibilityManager)
                  getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
          if (accessibilityManager.isEnabled()) {
              int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
              AccessibilityEvent event = AccessibilityEvent.obtain(
                      AccessibilityEvent.TYPE_VIEW_FOCUSED);
              onInitializeAccessibilityEvent(event);
              event.getText().add(getContext().getString(stringId));
              accessibilityManager.sendAccessibilityEvent(event);
          }
      }
  
      @Override
      public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
          Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
          if (currentFolder != null) {
              if (child == currentFolder) {
                  return super.onRequestSendAccessibilityEvent(child, event);
              }
              // Skip propagating onRequestSendAccessibilityEvent all for other children
              // when a folder is open
              return false;
          }
          return super.onRequestSendAccessibilityEvent(child, event);
      }
  
      @Override
      public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
          Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
          if (currentFolder != null) {
              // Only add the folder as a child for accessibility when it is open
              childrenForAccessibility.add(currentFolder);
          } else {
              super.addChildrenForAccessibility(childrenForAccessibility);
          }
      }
  
      @Override
      public boolean onHoverEvent(MotionEvent ev) {
          // If we've received this, we've already done the necessary handling
          // in onInterceptHoverEvent. Return true to consume the event.
          return false;
      }
  
      @Override
      public boolean onTouchEvent(MotionEvent ev) {
          boolean handled = false;
          int action = ev.getAction();
  
          int x = (int) ev.getX();
          int y = (int) ev.getY();
  
          if (action == MotionEvent.ACTION_DOWN) {
              if (handleTouchDown(ev, false)) {
                  return true;
              }
          } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
              if (mTouchCompleteListener != null) {
                  mTouchCompleteListener.onTouchComplete();
              }
              mTouchCompleteListener = null;
          }
  
          if (mCurrentResizeFrame != null) {
              handled = true;
              switch (action) {
                  case MotionEvent.ACTION_MOVE:
                      mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
                      break;
                  case MotionEvent.ACTION_CANCEL:
                  case MotionEvent.ACTION_UP:
                      mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
                      mCurrentResizeFrame.onTouchUp();
                      mCurrentResizeFrame = null;
              }
          }
          if (handled) return true;
          return mDragController.onTouchEvent(ev);
      }
  
      /**
       * Determine the rect of the descendant in this DragLayer's coordinates
       *
       * @param descendant The descendant whose coordinates we want to find.
       * @param r The rect into which to place the results.
       * @return The factor by which this descendant is scaled relative to this DragLayer.
       */
      public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
          mTmpXY[0] = 0;
          mTmpXY[1] = 0;
          float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
  
          r.set(mTmpXY[0], mTmpXY[1],
                  (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
                  (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
          return scale;
      }
  
      public float getLocationInDragLayer(View child, int[] loc) {
          loc[0] = 0;
          loc[1] = 0;
          return getDescendantCoordRelativeToSelf(child, loc);
      }
  
      public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
          return getDescendantCoordRelativeToSelf(descendant, coord, false);
      }
  
      /**
       * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
       * coordinates.
       *
       * @param descendant The descendant to which the passed coordinate is relative.
       * @param coord The coordinate that we want mapped.
       * @param includeRootScroll Whether or not to account for the scroll of the root descendant:
       *          sometimes this is relevant as in a child's coordinates within the root descendant.
       * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
       *         this scale factor is assumed to be equal in X and Y, and so if at any point this
       *         assumption fails, we will need to return a pair of scale factors.
       */
      public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
              boolean includeRootScroll) {
          return Utilities.getDescendantCoordRelativeToParent(descendant, this,
                  coord, includeRootScroll);
      }
  
      /**
       * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
       */
      public float mapCoordInSelfToDescendent(View descendant, int[] coord) {
          return Utilities.mapCoordInSelfToDescendent(descendant, this, coord);
      }
  
      public void getViewRectRelativeToSelf(View v, Rect r) {
          int[] loc = new int[2];
          getLocationInWindow(loc);
          int x = loc[0];
          int y = loc[1];
  
          v.getLocationInWindow(loc);
          int vX = loc[0];
          int vY = loc[1];
  
          int left = vX - x;
          int top = vY - y;
          r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
      }
  
      @Override
      public boolean dispatchUnhandledMove(View focused, int direction) {
          return mDragController.dispatchUnhandledMove(focused, direction);
      }
  
      public static class LayoutParams extends FrameLayout.LayoutParams {
          public int x, y;
          public boolean customPosition = false;
  
          /**
           * {@inheritDoc}
           */
          public LayoutParams(int width, int height) {
              super(width, height);
          }
  
          public void setWidth(int width) {
              this.width = width;
          }
  
          public int getWidth() {
              return width;
          }
  
          public void setHeight(int height) {
              this.height = height;
          }
  
          public int getHeight() {
              return height;
          }
  
          public void setX(int x) {
              this.x = x;
          }
  
          public int getX() {
              return x;
          }
  
          public void setY(int y) {
              this.y = y;
          }
  
          public int getY() {
              return y;
          }
      }
  
      protected void onLayout(boolean changed, int l, int t, int r, int b) {
          super.onLayout(changed, l, t, r, b);
          int count = getChildCount();
          for (int i = 0; i < count; i++) {
              View child = getChildAt(i);
              final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
              if (flp instanceof LayoutParams) {
  