Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1941ce7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move GestureListener to own file."

parents 96fd61cf 2499e8de
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ public final class Events {
        int getItemPosition();
    }

    public static final class MotionInputEvent implements InputEvent {
    public static final class MotionInputEvent implements InputEvent, AutoCloseable {
        private static final String TAG = "MotionInputEvent";

        private static final Pools.SimplePool<MotionInputEvent> sPool = new Pools.SimplePool<>(1);
@@ -199,6 +199,11 @@ public final class Events {
            assert(released);
        }

        @Override
        public void close() {
            recycle();
        }

        @Override
        public boolean isMouseEvent() {
            return Events.isMouseEvent(mEvent);
+4 −8
Original line number Diff line number Diff line
@@ -52,13 +52,13 @@ import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;

import libcore.io.IoUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import libcore.io.IoUtils;

/**
 * Display directories where recent creates took place.
 */
@@ -141,17 +141,13 @@ public class RecentsCreateFragment extends Fragment {
            new RecyclerView.OnItemTouchListener() {
                @Override
                public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                    final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
                    try {
                    try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
                        if (event.isOverItem() && event.isActionUp()) {
                            final DocumentStack stack = mAdapter.getItem(event.getItemPosition());
                            ((BaseActivity) getActivity()).onStackPicked(stack);
                            return true;
                        }

                        return false;
                    } finally {
                        event.recycle();
                    }
                }

@@ -247,7 +243,7 @@ public class RecentsCreateFragment extends Fragment {

          final LayoutInflater inflater = LayoutInflater.from(context);
          return new StackHolder(
                  (View) inflater.inflate(R.layout.item_doc_list, parent, false));
                  inflater.inflate(R.layout.item_doc_list, parent, false));
        }

        @Override
+2 −8
Original line number Diff line number Diff line
@@ -85,21 +85,15 @@ public class BandController extends RecyclerView.OnScrollListener {
                new RecyclerView.OnItemTouchListener() {
                    @Override
                    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                        final MotionInputEvent event = MotionInputEvent.obtain(e, view);
                        try {
                        try (MotionInputEvent event = MotionInputEvent.obtain(e, view)) {
                            return handleEvent(event);
                        } finally {
                            event.recycle();
                        }
                    }
                    @Override
                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
                        if (Events.isMouseEvent(e)) {
                            final MotionInputEvent event = MotionInputEvent.obtain(e, view);
                            try {
                            try (MotionInputEvent event = MotionInputEvent.obtain(e, view)) {
                                processInputEvent(event);
                            } finally {
                                event.recycle();
                            }
                        }
                    }
+46 −125
Original line number Diff line number Diff line
@@ -58,13 +58,11 @@ import android.util.SparseArray;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -74,11 +72,9 @@ import android.widget.Toolbar;
import com.android.documentsui.BaseActivity;
import com.android.documentsui.DirectoryLoader;
import com.android.documentsui.DirectoryResult;
import com.android.documentsui.UrisSupplier;
import com.android.documentsui.DocumentClipper;
import com.android.documentsui.DocumentsActivity;
import com.android.documentsui.DocumentsApplication;
import com.android.documentsui.Events;
import com.android.documentsui.Events.MotionInputEvent;
import com.android.documentsui.ItemDragListener;
import com.android.documentsui.MenuManager;
@@ -94,6 +90,7 @@ import com.android.documentsui.Shared;
import com.android.documentsui.Snackbars;
import com.android.documentsui.State;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.UrisSupplier;
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
@@ -295,22 +292,27 @@ public class DirectoryFragment extends Fragment
        }
        mRecView.setLayoutManager(mLayout);

        mGestureDetector =
                new ListeningGestureDetector(this.getContext(), mDragHelper, new GestureListener());

        mRecView.addOnItemTouchListener(mGestureDetector);
        mEmptyView.setOnTouchListener(mGestureDetector);

        // TODO: instead of inserting the view into the constructor, extract listener-creation code
        // and set the listener on the view after the fact.  Then the view doesn't need to be passed
        // into the selection manager.
        mSelectionManager = new MultiSelectManager(
                mRecView,
                mAdapter,
                state.allowMultiple
                    ? MultiSelectManager.MODE_MULTIPLE
                    : MultiSelectManager.MODE_SINGLE,
                null);
                    : MultiSelectManager.MODE_SINGLE);

        GestureListener gestureListener = new GestureListener(
                mSelectionManager,
                mRecView,
                this::getTarget,
                this::onDoubleTap,
                this::onRightClick);

        mGestureDetector =
                new ListeningGestureDetector(this.getContext(), mDragHelper, gestureListener);

        mRecView.addOnItemTouchListener(mGestureDetector);
        mEmptyView.setOnTouchListener(mGestureDetector);

        if (state.allowMultiple) {
            mBandController = new BandController(mRecView, mAdapter, mSelectionManager);
@@ -426,12 +428,9 @@ public class DirectoryFragment extends Fragment
        return false;
    }

    protected boolean onRightClick(MotionEvent e) {
        // First get target to see if it's a blank window or a file/doc
        final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
        try {
            if (event.getItemPosition() != RecyclerView.NO_POSITION) {
                final DocumentHolder holder = getTarget(event);
    protected boolean onRightClick(MotionInputEvent e) {
        if (e.getItemPosition() != RecyclerView.NO_POSITION) {
            final DocumentHolder holder = getTarget(e);
            String modelId = getModelId(holder.itemView);
            if (!mSelectionManager.getSelection().contains(modelId)) {
                mSelectionManager.clearSelection();
@@ -462,9 +461,6 @@ public class DirectoryFragment extends Fragment
            mRecView.showContextMenu(e.getX(), e.getY());
            unregisterForContextMenu(mRecView);
        }
        } finally {
            event.recycle();
        }
        return true;
    }

@@ -1554,81 +1550,6 @@ public class DirectoryFragment extends Fragment
        return mTuner.canSelectType(docMimeType, docFlags);
    }

    /**
     * The gesture listener for items in the list/grid view. Interprets gestures and sends the
     * events to the target DocumentHolder, whence they are routed to the appropriate listener.
     */
    class GestureListener extends GestureDetector.SimpleOnGestureListener {
        // From the RecyclerView, we get two events sent to
        // ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
        // ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
        // the mouse click. ACTION_UP event doesn't have information regarding the button (primary
        // vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
        // it later. The ACTION_DOWN event doesn't get forwarded to GestureListener, so we have open
        // up a public set method to set it.
        private int mLastButtonState = -1;

        public void setLastButtonState(int state) {
            mLastButtonState = state;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            // Single tap logic:
            // We first see if it's a mouse event, and if it was right click by checking on
            // @{code ListeningGestureDetector#mLastButtonState}
            // If the selection manager is active, it gets first whack at handling tap
            // events. Otherwise, tap events are routed to the target DocumentHolder.
            if (Events.isMouseEvent(e) && mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
                mLastButtonState = -1;
                return onRightClick(e);
            }

            final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
            try {
                boolean handled = mSelectionManager.onSingleTapUp(event);

                if (handled) {
                    return handled;
                }

                // Give the DocumentHolder a crack at the event.
                DocumentHolder holder = DirectoryFragment.this.getTarget(event);
                if (holder != null) {
                    handled = holder.onSingleTapUp(e);
                }

                return handled;
            } finally {
                event.recycle();
            }
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // Long-press events get routed directly to the selection manager. They can be
            // changed to route through the DocumentHolder if necessary.
            final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
            try {
                mSelectionManager.onLongPress(event);
            } finally {
                event.recycle();
            }
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            // Double-tap events are handled directly by the DirectoryFragment. They can be changed
            // to route through the DocumentHolder if necessary.
            final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
            return DirectoryFragment.this.onDoubleTap(event);
        }

        public boolean onRightClick(MotionEvent e) {
            return DirectoryFragment.this.onRightClick(e);
        }
    }

    public static void showDirectory(
            FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
        create(fm, TYPE_NORMAL, root, doc, null, anim);
+118 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.android.documentsui.dirlist;

import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;

import com.android.documentsui.Events;
import com.android.documentsui.Events.MotionInputEvent;

import java.util.function.Function;
import java.util.function.Predicate;

/**
 * The gesture listener for items in the directly list, interprets gestures, and sends the
 * events to the target DocumentHolder, whence they are routed to the appropriate listener.
 */
final class GestureListener extends GestureDetector.SimpleOnGestureListener {
    // From the RecyclerView, we get two events sent to
    // ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
    // ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
    // the mouse click. ACTION_UP event doesn't have information regarding the button (primary
    // vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
    // it later. The ACTION_DOWN event doesn't get forwarded to GestureListener, so we have open
    // up a public set method to set it.
    private int mLastButtonState = -1;
    private MultiSelectManager mSelectionMgr;
    private RecyclerView mRecView;
    private Function<MotionInputEvent, DocumentHolder> mDocFinder;
    private Predicate<MotionInputEvent> mDoubleTapHandler;
    private Predicate<MotionInputEvent> mRightClickHandler;

    public GestureListener(
            MultiSelectManager selectionMgr,
            RecyclerView recView,
            Function<MotionInputEvent, DocumentHolder> docFinder,
            Predicate<MotionInputEvent> doubleTapHandler,
            Predicate<MotionInputEvent> rightClickHandler) {
        mSelectionMgr = selectionMgr;
        mRecView = recView;
        mDocFinder = docFinder;
        mDoubleTapHandler = doubleTapHandler;
        mRightClickHandler = rightClickHandler;
    }

    public void setLastButtonState(int state) {
        mLastButtonState = state;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        // Single tap logic:
        // We first see if it's a mouse event, and if it was right click by checking on
        // @{code ListeningGestureDetector#mLastButtonState}
        // If the selection manager is active, it gets first whack at handling tap
        // events. Otherwise, tap events are routed to the target DocumentHolder.
        if (Events.isMouseEvent(e) && mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
            mLastButtonState = -1;
            return onRightClick(e);
        }

        try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
            boolean handled = mSelectionMgr.onSingleTapUp(event);

            if (handled) {
                return handled;
            }

            // Give the DocumentHolder a crack at the event.
            DocumentHolder holder = mDocFinder.apply(event);
            if (holder != null) {
                handled = holder.onSingleTapUp(e);
            }

            return handled;
        }
    }

    @Override
    public void onLongPress(MotionEvent e) {
        // Long-press events get routed directly to the selection manager. They can be
        // changed to route through the DocumentHolder if necessary.
        try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
            mSelectionMgr.onLongPress(event);
        }
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        // Double-tap events are handled directly by the DirectoryFragment. They can be changed
        // to route through the DocumentHolder if necessary.

        try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
            return mDoubleTapHandler.test(event);
        }
    }

    public boolean onRightClick(MotionEvent e) {
        try (MotionInputEvent event = MotionInputEvent.obtain(e, mRecView)) {
            return mRightClickHandler.test(event);
        }
    }
}
 No newline at end of file
Loading