163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay/*
263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Copyright 2017 The Android Open Source Project
363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay *
463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Licensed under the Apache License, Version 2.0 (the "License");
563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * you may not use this file except in compliance with the License.
663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * You may obtain a copy of the License at
763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay *
863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay *      http://www.apache.org/licenses/LICENSE-2.0
963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay *
1063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Unless required by applicable law or agreed to in writing, software
1163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * distributed under the License is distributed on an "AS IS" BASIS,
1263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * See the License for the specific language governing permissions and
1463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * limitations under the License.
1563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay */
1663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
1763d2846409d84487d4856d3b8d18cc4684352e29Steve McKaypackage com.example.android.supportv7.widget.selection.simple;
1863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
1963d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.content.Context;
2063d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.os.Bundle;
2163d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.util.Log;
2263d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.view.Menu;
2363d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.view.MenuItem;
2463d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.view.MotionEvent;
2563d2846409d84487d4856d3b8d18cc4684352e29Steve McKayimport android.widget.Toast;
2663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
27def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.annotation.CallSuper;
28def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.appcompat.app.AppCompatActivity;
292a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.ItemDetailsLookup.ItemDetails;
302a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.ItemKeyProvider;
312a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.SelectionPredicates;
322a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.SelectionTracker;
332a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.SelectionTracker.SelectionObserver;
342a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.StableIdKeyProvider;
352a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikasimport androidx.recyclerview.selection.StorageStrategy;
36def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.GridLayoutManager;
37def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport androidx.recyclerview.widget.RecyclerView;
38def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikas
39def582a5836579a3fadabfdbe4413cb1652bf098Aurimas Liutikasimport com.example.android.supportv7.R;
4063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
4163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay/**
4263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * ContentPager demo activity.
4363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay */
4463d2846409d84487d4856d3b8d18cc4684352e29Steve McKaypublic class SimpleSelectionDemoActivity extends AppCompatActivity {
4563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
4663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private static final String TAG = "SelectionDemos";
4763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private static final String EXTRA_COLUMN_COUNT = "demo-column-count";
4863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
4963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private SimpleSelectionDemoAdapter mAdapter;
507fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay    private SelectionTracker<Long> mSelectionTracker;
5163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
5263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private GridLayoutManager mLayout;
5363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private int mColumnCount = 1;  // This will get updated when layout changes.
5463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
5563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
5663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    protected void onCreate(Bundle savedInstanceState) {
5763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        super.onCreate(savedInstanceState);
5863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
5963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        setContentView(R.layout.selection_demo_layout);
6063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        RecyclerView recView = (RecyclerView) findViewById(R.id.list);
6163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
6263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // keyProvider depends on mAdapter.setHasStableIds(true).
6363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        ItemKeyProvider<Long> keyProvider = new StableIdKeyProvider(recView);
6463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
6563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        mLayout = new GridLayoutManager(this, mColumnCount);
6663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        recView.setLayoutManager(mLayout);
6763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
6863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        mAdapter = new SimpleSelectionDemoAdapter(this, keyProvider);
6963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // The adapter is paired with a key provider that supports
7063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // the native RecyclerView stableId. For this to work correctly
7163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // the adapter must report that it supports stable ids.
7263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        mAdapter.setHasStableIds(true);
7363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
7463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        recView.setAdapter(mAdapter);
7563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
767fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        SelectionTracker.Builder<Long> builder = new SelectionTracker.Builder<>(
777fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                "simple-demo",
7863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                recView,
7963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                keyProvider,
807fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                new DemoDetailsLookup(recView),
817fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                StorageStrategy.createLongStorage());
8263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
8363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // Override default behaviors and build in multi select mode.
847fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        // Call .withSelectionPredicate(SelectionTracker.SelectionPredicate.SINGLE_ANYTHING)
8563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // for single selection mode.
867fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mSelectionTracker = builder
877fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                .withSelectionPredicate(SelectionPredicates.createSelectAnything())
887fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                .withOnDragInitiatedListener(new OnDragInitiatedListener(this))
897fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                .withOnContextClickListener(new OnContextClickListener(this))
907fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                .withOnItemActivatedListener(new OnItemActivatedListener(this))
917fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                .withFocusDelegate(new FocusDelegate(this))
9263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                .withBandOverlay(R.drawable.selection_demo_band_overlay)
9363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                .build();
9463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
957fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        // Lazily bind SelectionTracker. Allows us to defer initialization of the
967fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        // SelectionTracker dependency until after the adapter is created.
977fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mAdapter.bindSelectionHelper(mSelectionTracker);
9863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
9963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // TODO: Glue selection to ActionMode, since that'll be a common practice.
1007fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mSelectionTracker.addObserver(
10163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                new SelectionObserver<Long>() {
10263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                    @Override
10363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                    public void onSelectionChanged() {
1047fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay                        Log.i(TAG, "Selection changed to: " + mSelectionTracker.getSelection());
10563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                    }
10663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                });
10763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
10863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        // Restore selection from saved state.
10963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        updateFromSavedState(savedInstanceState);
11063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
11163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
11263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
11363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    protected void onSaveInstanceState(Bundle state) {
11463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        super.onSaveInstanceState(state);
1157fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mSelectionTracker.onSaveInstanceState(state);
11663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        state.putInt(EXTRA_COLUMN_COUNT, mColumnCount);
11763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
11863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
11963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private void updateFromSavedState(Bundle state) {
1207fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mSelectionTracker.onRestoreInstanceState(state);
12163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
12263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        if (state != null) {
12363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            if (state.containsKey(EXTRA_COLUMN_COUNT)) {
12463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                mColumnCount = state.getInt(EXTRA_COLUMN_COUNT);
12563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                mLayout.setSpanCount(mColumnCount);
12663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            }
12763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
12863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
12963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
13063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
13163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    public boolean onCreateOptionsMenu(Menu menu) {
13263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        boolean showMenu = super.onCreateOptionsMenu(menu);
13363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        getMenuInflater().inflate(R.menu.selection_demo_actions, menu);
13463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        return showMenu;
13563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
13663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
13763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
13863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @CallSuper
13963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    public boolean onPrepareOptionsMenu(Menu menu) {
14063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        super.onPrepareOptionsMenu(menu);
14163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        menu.findItem(R.id.option_menu_add_column).setEnabled(mColumnCount <= 3);
14263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        menu.findItem(R.id.option_menu_remove_column).setEnabled(mColumnCount > 1);
14363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        return true;
14463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
14563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
14663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
14763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    public boolean onOptionsItemSelected(MenuItem item) {
14863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        switch (item.getItemId()) {
14963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            case R.id.option_menu_add_column:
15063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                // TODO: Add columns
15163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                mLayout.setSpanCount(++mColumnCount);
15263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                return true;
15363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
15463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            case R.id.option_menu_remove_column:
15563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                mLayout.setSpanCount(--mColumnCount);
15663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                return true;
15763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
15863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            default:
15963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay                return super.onOptionsItemSelected(item);
16063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
16163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
16263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
16363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
16463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    public void onBackPressed() {
1657fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        if (mSelectionTracker.clearSelection()) {
16663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return;
16763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        } else {
16863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            super.onBackPressed();
16963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
17063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
17163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
17263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    private static void toast(Context context, String msg) {
17363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
17463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
17563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
17663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
17763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    protected void onDestroy() {
1787fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        mSelectionTracker.clearSelection();
17963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        super.onDestroy();
18063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
18163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
18263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    @Override
18363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    protected void onStart() {
18463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        super.onStart();
18563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        mAdapter.loadData();
18663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
18763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
18863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    // Implementation of MouseInputHandler.Callbacks allows handling
18963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    // of higher level events, like onActivated.
1907fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay    private static final class OnItemActivatedListener implements
1912a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikas            androidx.recyclerview.selection.OnItemActivatedListener<Long> {
19263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
19363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        private final Context mContext;
19463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
1957fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        OnItemActivatedListener(Context context) {
19663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            mContext = context;
19763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
19863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
19963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
20063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public boolean onItemActivated(ItemDetails<Long> item, MotionEvent e) {
20163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            toast(mContext, "Activate item: " + item.getSelectionKey());
20263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return true;
20363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
20463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
20563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
2067fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay    private static final class FocusDelegate extends
2072a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikas            androidx.recyclerview.selection.FocusDelegate<Long> {
20863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
20963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        private final Context mContext;
21063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
2117fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        private FocusDelegate(Context context) {
21263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            mContext = context;
21363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
21463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
21563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
21663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public void focusItem(ItemDetails<Long> item) {
21763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            toast(mContext, "Focused item: " + item.getSelectionKey());
21863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
21963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
22063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
22163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public boolean hasFocusedItem() {
22263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return false;
22363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
22463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
22563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
22663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public int getFocusedPosition() {
22763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return 0;
22863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
22963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
23063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
23163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public void clearFocus() {
23263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            toast(mContext, "Cleared focus.");
23363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
23463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
23563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
23663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    // Implementation of MouseInputHandler.Callbacks allows handling
23763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    // of higher level events, like onActivated.
2387fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay    private static final class OnContextClickListener implements
2392a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikas            androidx.recyclerview.selection.OnContextClickListener {
24063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
24163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        private final Context mContext;
24263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
2437fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        OnContextClickListener(Context context) {
24463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            mContext = context;
24563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
24663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
24763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        @Override
24863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public boolean onContextClick(MotionEvent e) {
24963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            toast(mContext, "Context click received.");
25063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return true;
25163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
25263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    };
25363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
2547fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay    private static final class OnDragInitiatedListener implements
2552a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikas            androidx.recyclerview.selection.OnDragInitiatedListener {
25663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
25763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        private final Context mContext;
25863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
2597fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay        private OnDragInitiatedListener(Context context) {
26063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            mContext = context;
26163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
26263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay
26363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        public boolean onDragInitiated(MotionEvent e) {
26463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            toast(mContext, "onDragInitiated received.");
26563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay            return true;
26663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay        }
26763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay    }
26863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay}
269