X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff..269195b3729c1bdc22e9053ee4ebca667ea8549d:/Android/webViewMarker/src/main/java/com/blahti/drag/DragController.java?ds=inline diff --git a/Android/webViewMarker/src/main/java/com/blahti/drag/DragController.java b/Android/webViewMarker/src/main/java/com/blahti/drag/DragController.java new file mode 100755 index 0000000..86ab1bc --- /dev/null +++ b/Android/webViewMarker/src/main/java/com/blahti/drag/DragController.java @@ -0,0 +1,366 @@ +/* + * This is a modified version of a class from the Android + * Open Source Project. The original copyright and license information follows. + * + * 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.blahti.drag; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.os.IBinder; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.View; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; + +import java.util.ArrayList; + +/** + * This class is used to initiate a drag within a view or across multiple views. + * When a drag starts it creates a special view (a DragView) that moves around the screen + * until the user ends the drag. As feedback to the user, this object causes the device to + * vibrate as the drag begins. + * + */ + +public class DragController { + public enum DragBehavior { + MOVE, // indicates the drag is move + COPY // indicates the drag is copy + } + public static final String TAG = "DragController"; + + private Context mContext; + private Rect mRectTemp = new Rect(); + private final int[] mCoordinatesTemp = new int[2]; + private boolean mDragging; + private float mMotionDownX; + private float mMotionDownY; + private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); + + /** Original view that is being dragged. */ + private View mOriginator; + + /** X offset from the upper-left corner of the cell to where we touched. */ + private float mTouchOffsetX; + + /** Y offset from the upper-left corner of the cell to where we touched. */ + private float mTouchOffsetY; + + /** Where the drag originated */ + private DragSource mDragSource; + + /** The data associated with the object being dragged */ + private Object mDragInfo; + + /** The view that moves around while you drag. */ + private DragView mDragView; + + /** Who can receive drop events */ + private ArrayList mDropTargets = new ArrayList(); + + private DragListener mListener; + + /** The window token used as the parent for the DragView. */ + private IBinder mWindowToken; + + private View mMoveTarget; + + private DropTarget mLastDropTarget; + + private InputMethodManager mInputMethodManager; + + + /** + * Used to create a new DragLayer from XML. + * + * @param context The application's context. + */ + public DragController(Context context) { + mContext = context; + } + + /** + * Starts a drag. + * It creates a bitmap of the view being dragged. That bitmap is what you see moving. + * The actual view can be repositioned if that is what the onDrop handle chooses to do. + * + * @param v The view that is being dragged + * @param source An object representing where the drag originated + * @param dragInfo The data associated with the object that is being dragged + * @param dragAction The drag behavior: move or copy + */ + public void startDrag(View v, DragSource source, Object dragInfo, DragBehavior dragBehavior) { + if (source.allowDrag()) { + mOriginator = v; + final Bitmap b = getViewBitmap(v); + if (b != null) { + final int[] loc = mCoordinatesTemp; + v.getLocationOnScreen(loc); + final int screenX = loc[0]; + final int screenY = loc[1]; + startDrag(b, screenX, screenY, 0, 0, b.getWidth(), b.getHeight(), source, dragInfo, dragBehavior); + b.recycle(); + if (dragBehavior == DragBehavior.MOVE) { + v.setVisibility(View.GONE); + } + } + } + } + + /** + * Starts a drag. + * + * @param b The bitmap to display as the drag image. It will be re-scaled to the + * enlarged size. + * @param screenX The x position on screen of the left-top of the bitmap. + * @param screenY The y position on screen of the left-top of the bitmap. + * @param textureLeft The left edge of the region inside b to use. + * @param textureTop The top edge of the region inside b to use. + * @param textureWidth The width of the region inside b to use. + * @param textureHeight The height of the region inside b to use. + * @param source An object representing where the drag originated + * @param dragInfo The data associated with the object that is being dragged + * @param dragBehavior The drag action: move or copy + */ + private void startDrag(Bitmap b, int screenX, int screenY, int textureLeft, int textureTop, int textureWidth, int textureHeight, DragSource source, Object dragInfo, DragBehavior dragBehavior) { + if (mInputMethodManager == null) { + mInputMethodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + } + mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0); + if (mListener != null) { + mListener.onDragStart(source, dragInfo, dragBehavior); + } + final int registrationX = ((int)mMotionDownX) - screenX; + final int registrationY = ((int)mMotionDownY) - screenY; + mTouchOffsetX = mMotionDownX - screenX; + mTouchOffsetY = mMotionDownY - screenY; + mDragging = true; + mDragSource = source; + mDragInfo = dragInfo; + mDragView = new DragView(mContext, b, registrationX, registrationY, textureLeft, textureTop, textureWidth, textureHeight); + mDragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY); + } + + /** + * Draw the view into a bitmap. + */ + private Bitmap getViewBitmap(View v) { + v.clearFocus(); + v.setPressed(false); + + boolean willNotCache = v.willNotCacheDrawing(); + v.setWillNotCacheDrawing(false); + + // Reset the drawing cache background color to fully transparent + // for the duration of this operation + int color = v.getDrawingCacheBackgroundColor(); + v.setDrawingCacheBackgroundColor(0); + + if (color != 0) { + v.destroyDrawingCache(); + } + v.buildDrawingCache(); + Bitmap cacheBitmap = v.getDrawingCache(); + if (cacheBitmap == null) { + Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException()); + return null; + } + + Bitmap bitmap = Bitmap.createBitmap(cacheBitmap); + + // Restore the view + v.destroyDrawingCache(); + v.setWillNotCacheDrawing(willNotCache); + v.setDrawingCacheBackgroundColor(color); + + return bitmap; + } + + public boolean dispatchKeyEvent(KeyEvent event) { + return mDragging; + } + + public void cancelDrag() { + endDrag(); + } + + private void endDrag() { + if (mDragging) { + mDragging = false; + if (mOriginator != null) { + mOriginator.setVisibility(View.VISIBLE); + } + if (mListener != null) { + mListener.onDragEnd(); + } + if (mDragView != null) { + mDragView.remove(); + mDragView = null; + } + } + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + recordScreenSize(); + } + final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels); + final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels); + switch (action) { + case MotionEvent.ACTION_MOVE: + break; + case MotionEvent.ACTION_DOWN: + mMotionDownX = screenX; + mMotionDownY = screenY; + mLastDropTarget = null; + break; + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (mDragging) { + drop(screenX, screenY); + } + endDrag(); + break; + } + return mDragging; + } + + /** + * Sets the view that should handle move events. + */ + void setMoveTarget(View view) { + mMoveTarget = view; + } + + public boolean dispatchUnhandledMove(View focused, int direction) { + return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction); + } + + public boolean onTouchEvent(MotionEvent ev) { + if (!mDragging) { + return false; + } + + final int action = ev.getAction(); + final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels); + final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels); + + switch (action) { + case MotionEvent.ACTION_DOWN: + mMotionDownX = screenX; + mMotionDownY = screenY; + break; + case MotionEvent.ACTION_MOVE: + mDragView.move((int)ev.getRawX(), (int)ev.getRawY()); + final int[] coordinates = mCoordinatesTemp; + DropTarget dropTarget = findDropTarget(screenX, screenY, coordinates); + if (dropTarget != null) { + if (mLastDropTarget == dropTarget) { + dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1], (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + } + else { + if (mLastDropTarget != null) { + mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); + } + dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1], (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + } + } + else { + if (mLastDropTarget != null) { + mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + } + } + mLastDropTarget = dropTarget; + break; + case MotionEvent.ACTION_UP: + if (mDragging) { + drop(screenX, screenY); + } + endDrag(); + break; + case MotionEvent.ACTION_CANCEL: + cancelDrag(); + } + + return true; + } + + private boolean drop(float x, float y) { + final int[] coordinates = mCoordinatesTemp; + final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates); + if (dropTarget != null) { + dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1], (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) { + dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1], (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo); + mDragSource.onDropCompleted((View)dropTarget, true); + } + else { + mDragSource.onDropCompleted((View)dropTarget, false); + } + return true; + } + return false; + } + private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) { + final Rect r = mRectTemp; + final ArrayList dropTargets = mDropTargets; + final int count = dropTargets.size(); + for (int i = count - 1; i >= 0; i--) { + final DropTarget target = dropTargets.get(i); + target.getHitRect(r); + target.getLocationOnScreen(dropCoordinates); + r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop()); + if (r.contains(x, y)) { + dropCoordinates[0] = x - dropCoordinates[0]; + dropCoordinates[1] = y - dropCoordinates[1]; + return target; + } + } + return null; + } + + private void recordScreenSize() { + ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(mDisplayMetrics); + } + private static int clamp(int val, int min, int max) { + if (val < min) { + return min; + } + else if (val >= max) { + return max - 1; + } + else { + return val; + } + } + + public void setDragListener(DragListener listener) { + mListener = listener; + } + public void addDropTarget(DropTarget target) { + mDropTargets.add(target); + } + public void removeDropTarget(DropTarget target) { + mDropTargets.remove(target); + } +}