14f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay/*
24f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * Copyright (C) 2016 The Android Open Source Project
34f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay *
44f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * Licensed under the Apache License, Version 2.0 (the "License");
54f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * you may not use this file except in compliance with the License.
64f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * You may obtain a copy of the License at
74f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay *
84f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay *      http://www.apache.org/licenses/LICENSE-2.0
94f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay *
104f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * Unless required by applicable law or agreed to in writing, software
114f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * distributed under the License is distributed on an "AS IS" BASIS,
124f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * See the License for the specific language governing permissions and
144f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * limitations under the License.
154f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay */
164f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKaypackage com.android.documentsui.selection;
174f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
184f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport android.os.Parcel;
194f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport android.os.Parcelable;
204f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport android.support.annotation.VisibleForTesting;
214f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
224f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.ArrayList;
234f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.Collection;
244f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.HashMap;
254f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.HashSet;
264f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.Iterator;
274f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.Map;
284f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport java.util.Set;
294f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
304f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport javax.annotation.Nullable;
314f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
324f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay/**
334f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * Object representing the current selection. Provides read only access
344f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay * public access, and private write access.
354f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay */
364f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKaypublic final class Selection implements Iterable<String>, Parcelable {
374f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
384f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // This class tracks selected items by managing two sets: the saved selection, and the total
394f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // selection. Saved selections are those which have been completed by tapping an item or by
404f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // completing a band select operation. Provisional selections are selections which have been
414f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // temporarily created by an in-progress band select operation (once the user releases the
424f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // mouse button during a band select operation, the selected items become saved). The total
434f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // selection is the combination of both the saved selection and the provisional
444f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // selection. Tracking both separately is necessary to ensure that saved selections do not
454f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // become deselected when they are removed from the provisional selection; for example, if
464f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // item A is tapped (and selected), then an in-progress band select covers A then uncovers
474f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // A, A should still be selected as it has been saved. To ensure this behavior, the saved
484f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    // selection must be tracked separately.
494f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    final Set<String> mSelection;
504f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    final Set<String> mProvisionalSelection;
514f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
524f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public Selection() {
534f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection = new HashSet<>();
544f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection = new HashSet<>();
554f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
564f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
574f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
584f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Used by CREATOR.
594f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
604f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    private Selection(Set<String> selection) {
614f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection = selection;
624f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection = new HashSet<>();
634f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
644f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
654f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
664f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * @param id
674f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * @return true if the position is currently selected.
684f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
694f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public boolean contains(@Nullable String id) {
704f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return mSelection.contains(id) || mProvisionalSelection.contains(id);
714f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
724f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
734f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
744f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Returns an {@link Iterator} that iterators over the selection, *excluding*
754f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * any provisional selection.
764f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     *
774f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * {@inheritDoc}
784f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
794f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
804f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public Iterator<String> iterator() {
814f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return mSelection.iterator();
824f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
834f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
844f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
854f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * @return size of the selection including both final and provisional selected items.
864f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
874f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public int size() {
884f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return mSelection.size() + mProvisionalSelection.size();
894f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
904f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
914f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
924f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * @return true if the selection is empty.
934f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
944f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public boolean isEmpty() {
954f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return mSelection.isEmpty() && mProvisionalSelection.isEmpty();
964f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
974f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
984f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
994f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Sets the provisional selection, which is a temporary selection that can be saved,
1004f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * canceled, or adjusted at a later time. When a new provision selection is applied, the old
1014f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * one (if it exists) is abandoned.
1024f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * @return Map of ids added or removed. Added ids have a value of true, removed are false.
1034f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
1044f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
1054f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    protected Map<String, Boolean> setProvisionalSelection(Set<String> newSelection) {
1064f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        Map<String, Boolean> delta = new HashMap<>();
1074f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1084f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        for (String id: mProvisionalSelection) {
1094f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // Mark each item that used to be in the selection but is unsaved and not in the new
1104f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // provisional selection.
1114f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            if (!newSelection.contains(id) && !mSelection.contains(id)) {
1124f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                delta.put(id, false);
1134f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            }
1144f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1154f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1164f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        for (String id: mSelection) {
1174f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // Mark each item that used to be in the selection but is unsaved and not in the new
1184f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // provisional selection.
1194f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            if (!newSelection.contains(id)) {
1204f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                delta.put(id, false);
1214f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            }
1224f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1234f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1244f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        for (String id: newSelection) {
1254f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // Mark each item that was not previously in the selection but is in the new
1264f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            // provisional selection.
1274f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            if (!mSelection.contains(id) && !mProvisionalSelection.contains(id)) {
1284f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                delta.put(id, true);
1294f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            }
1304f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1314f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1324f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        // Now, iterate through the changes and actually add/remove them to/from the current
1334f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        // selection. This could not be done in the previous loops because changing the size of
1344f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        // the selection mid-iteration changes iteration order erroneously.
1354f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        for (Map.Entry<String, Boolean> entry: delta.entrySet()) {
1364f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            String id = entry.getKey();
1374f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            if (entry.getValue()) {
1384f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                mProvisionalSelection.add(id);
1394f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            } else {
1404f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay                mProvisionalSelection.remove(id);
1414f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            }
1424f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1434f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1444f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return delta;
1454f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1464f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1474f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
1484f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Saves the existing provisional selection. Once the provisional selection is saved,
1494f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * subsequent provisional selections which are different from this existing one cannot
1504f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * cause items in this existing provisional selection to become deselected.
1514f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
1524f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
1534f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    protected void applyProvisionalSelection() {
1544f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection.addAll(mProvisionalSelection);
1554f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection.clear();
1564f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1574f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1584f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
1594f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Abandons the existing provisional selection so that all items provisionally selected are
1604f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * now deselected.
1614f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
1624f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
1634f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    void cancelProvisionalSelection() {
1644f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection.clear();
1654f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1664f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1674f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /** @hide */
1684f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
1694f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public boolean add(String id) {
1704f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        if (!mSelection.contains(id)) {
1714f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            mSelection.add(id);
1724f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return true;
1734f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1744f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return false;
1754f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1764f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1774f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /** @hide */
1784f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
1794f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    boolean remove(String id) {
1804f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        if (mSelection.contains(id)) {
1814f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            mSelection.remove(id);
1824f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return true;
1834f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
1844f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return false;
1854f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1864f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1874f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public void clear() {
1884f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection.clear();
1894f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1904f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1914f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    /**
1924f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     * Trims this selection to be the intersection of itself with the set of given IDs.
1934f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay     */
1944f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public void intersect(Collection<String> ids) {
1954f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection.retainAll(ids);
1964f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection.retainAll(ids);
1974f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
1984f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
1994f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @VisibleForTesting
2004f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    void copyFrom(Selection source) {
2014f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection.clear();
2024f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mSelection.addAll(source.mSelection);
2034f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2044f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection.clear();
2054f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        mProvisionalSelection.addAll(source.mProvisionalSelection);
2064f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2074f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2084f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
2094f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public String toString() {
2104f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        if (size() <= 0) {
2114f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return "size=0, items=[]";
2124f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
2134f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2144f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        StringBuilder buffer = new StringBuilder(size() * 28);
2154f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        buffer.append("Selection{")
2164f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            .append("applied{size=" + mSelection.size())
2174f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            .append(", entries=" + mSelection)
2184f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            .append("}, provisional{size=" + mProvisionalSelection.size())
2194f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            .append(", entries=" + mProvisionalSelection)
2204f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            .append("}}");
2214f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return buffer.toString();
2224f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2234f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2244f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
2254f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public int hashCode() {
2264f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return mSelection.hashCode() ^ mProvisionalSelection.hashCode();
2274f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2284f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2294f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
2304f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public boolean equals(Object that) {
2314f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay      if (this == that) {
2324f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay          return true;
2334f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay      }
2344f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2354f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay      if (!(that instanceof Selection)) {
2364f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay          return false;
2374f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay      }
2384f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2394f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay      return mSelection.equals(((Selection) that).mSelection) &&
2404f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay              mProvisionalSelection.equals(((Selection) that).mProvisionalSelection);
2414f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2424f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2434f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
2444f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public int describeContents() {
2454f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        return 0;
2464f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2474f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2484f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    @Override
2494f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public void writeToParcel(Parcel dest, int flags) {
2504f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        dest.writeStringList(new ArrayList<>(mSelection));
2514f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        // We don't include provisional selection since it is
2524f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        // typically coupled to some other runtime state (like a band).
2534f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    }
2544f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2554f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    public static final ClassLoaderCreator<Selection> CREATOR =
2564f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            new ClassLoaderCreator<Selection>() {
2574f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        @Override
2584f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        public Selection createFromParcel(Parcel in) {
2594f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return createFromParcel(in, null);
2604f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
2614f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2624f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        @Override
2634f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        public Selection createFromParcel(Parcel in, ClassLoader loader) {
2644f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            ArrayList<String> selected = new ArrayList<>();
2654f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            in.readStringList(selected);
2664f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2674f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return new Selection(new HashSet<>(selected));
2684f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
2694f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay
2704f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        @Override
2714f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        public Selection[] newArray(int size) {
2724f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay            return new Selection[size];
2734f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay        }
2744f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay    };
2754f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay}