SwipeableListView.java revision 1ef988f0c8be136fda75ed207c222413db1d3f0c
1f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira/*
2f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Copyright (C) 2012 Google Inc.
3f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed to The Android Open Source Project.
4f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira *
5f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
6f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * you may not use this file except in compliance with the License.
7f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * You may obtain a copy of the License at
8f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira *
9f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira *      http://www.apache.org/licenses/LICENSE-2.0
10f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira *
11f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * Unless required by applicable law or agreed to in writing, software
12f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
13f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * See the License for the specific language governing permissions and
15f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira * limitations under the License.
16f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira */
17f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
18f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereirapackage com.android.mail.ui;
19f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
2007118a01f7183645957010779222b84930f75b4eMindy Pereiraimport android.animation.Animator;
2107118a01f7183645957010779222b84930f75b4eMindy Pereiraimport android.animation.AnimatorListenerAdapter;
22f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.content.Context;
23f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.content.res.Configuration;
248db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport android.net.Uri;
25f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.util.AttributeSet;
26f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.MotionEvent;
27f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.view.View;
28f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereiraimport android.view.ViewConfiguration;
29f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport android.widget.ListView;
30f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
31f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.R;
32bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrookimport com.android.mail.browse.ConversationCursor;
33f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.browse.ConversationItemView;
341ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereiraimport com.android.mail.browse.SwipeableConversationItemView;
35f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.providers.Conversation;
3606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereiraimport com.android.mail.providers.Folder;
37f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport com.android.mail.ui.SwipeHelper.Callback;
38b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag;
39f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
40866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereiraimport java.util.ArrayList;
41f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereiraimport java.util.Collection;
428db7e407109532557718c6b8064792f2df7a073dMindy Pereiraimport java.util.HashMap;
43f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
448937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereirapublic class SwipeableListView extends ListView implements Callback {
45f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    private SwipeHelper mSwipeHelper;
46ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    private boolean mEnableSwipe = false;
47489dd22c64c718b6953b4bd6acef925e82c53c87Andy Huang
48b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook    public static final String LOG_TAG = LogTag.getLogTag();
49f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
50866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    private ConversationSelectionSet mConvSelectionSet;
516c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    private int mSwipeAction;
5206642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    private Folder mFolder;
53866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
54f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context) {
55f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, null);
56f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
57f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
58f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs) {
59f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        this(context, attrs, -1);
60f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
61f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
62f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public SwipeableListView(Context context, AttributeSet attrs, int defStyle) {
63f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        super(context, attrs, defStyle);
64f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
65f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
66866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        float scrollSlop = context.getResources().getInteger(R.integer.swipeScrollSlop);
67cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        float minSwipe = context.getResources().getDimension(R.dimen.min_swipe);
68cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        float minVert = context.getResources().getDimension(R.dimen.min_vert);
69cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        float minLock = context.getResources().getDimension(R.dimen.min_lock);
70f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop,
71cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira                scrollSlop, minSwipe, minVert, minLock);
72f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
73f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
74f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    @Override
75f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    protected void onConfigurationChanged(Configuration newConfig) {
76f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        super.onConfigurationChanged(newConfig);
77f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float densityScale = getResources().getDisplayMetrics().density;
78f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setDensityScale(densityScale);
79f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
80f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
81f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira    }
82f913894d3f1fa80b7174477999074b813e1deb12Mindy Pereira
83ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    /**
84ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     * Enable swipe gestures.
85ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira     */
86ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    public void enableSwipe(boolean enable) {
87ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        mEnableSwipe = enable;
88ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira    }
89ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira
90f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    public boolean isSwipeEnabled() {
91f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira        return mEnableSwipe;
92f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira    }
93f07269fdfbc0ca2607dad50bfc15c2c041c1faddMindy Pereira
946c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void setSwipeAction(int action) {
956c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        mSwipeAction = action;
96f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
97f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
98de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    public int getSwipeAction() {
99de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira        return mSwipeAction;
100de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    }
101de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira
102866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public void setSelectionSet(ConversationSelectionSet set) {
103866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        mConvSelectionSet = set;
104866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
105866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
10606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    public void setCurrentFolder(Folder folder) {
10706642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira        mFolder = folder;
10806642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira    }
10906642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira
110866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    @Override
111866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    public ConversationSelectionSet getSelectionSet() {
112866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira        return mConvSelectionSet;
113866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
114866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
115f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
116f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onInterceptTouchEvent(MotionEvent ev) {
117ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        if (mEnableSwipe) {
11819bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return mSwipeHelper.onInterceptTouchEvent(ev)
11919bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira                    || super.onInterceptTouchEvent(ev);
12019bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        } else {
12119bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return super.onInterceptTouchEvent(ev);
12219bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        }
123f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
124f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
125f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
126f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public boolean onTouchEvent(MotionEvent ev) {
127ff9aff3c28c4c20c7866ebfaaa642997e324f274Mindy Pereira        if (mEnableSwipe) {
12819bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev);
12919bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        } else {
13019bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira            return super.onTouchEvent(ev);
13119bf5f5a4944f5bb4e62e1f32c47dce87f662cbdMindy Pereira        }
132f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
133f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
134f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
135f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public View getChildAtPosition(MotionEvent ev) {
136f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // find the view under the pointer, accounting for GONE views
137f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        final int count = getChildCount();
138f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        int touchY = (int) ev.getY();
139f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        int childIdx = 0;
140f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        View slidingChild;
141f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        for (; childIdx < count; childIdx++) {
142f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            slidingChild = getChildAt(childIdx);
143f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            if (slidingChild.getVisibility() == GONE) {
144f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira                continue;
145f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira            }
146866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            if (touchY >= slidingChild.getTop() && touchY <= slidingChild.getBottom()) {
1471ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                if (slidingChild instanceof SwipeableConversationItemView) {
1481ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                    return ((SwipeableConversationItemView) slidingChild).getSwipeableItemView();
1491ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                }
150866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira                return slidingChild;
151866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira            }
152f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        }
153f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        return null;
154f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
155f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
156f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
1576c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public boolean canChildBeDismissed(SwipeableItemView v) {
1586c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        View view = v.getView();
1596c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        return view instanceof ConversationItemView || view instanceof LeaveBehindItem;
160f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
161f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
162f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
1636c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onChildDismissed(SwipeableItemView v) {
1646c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        View view = v.getView();
1656c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        if (view instanceof ConversationItemView) {
1666c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        dismissChildren((ConversationItemView) v, null);
1676c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        } else if (view instanceof LeaveBehindItem) {
1686c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            ((LeaveBehindItem)view).commit();
1696c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        }
170f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
171f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
1728937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // Call this whenever a new action is taken; this forces a commit of any
1738937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    // existing destructive actions.
1748937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    public void commitDestructiveActions() {
1750fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
1768937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        if (adapter != null) {
1778937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira            adapter.commitLeaveBehindItems();
1788937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        }
1798937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
1808937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira
181f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
1826c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onChildrenDismissed(SwipeableItemView target,
1836c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            Collection<ConversationItemView> views) {
1846c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        assert(target instanceof ConversationItemView);
1856c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        dismissChildren((ConversationItemView) target.getView(), views);
186866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
187866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
1886c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    private void dismissChildren(final ConversationItemView target,
1896c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            final Collection<ConversationItemView> conversationViews) {
1906c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        final Context context = getContext();
1910fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
192d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira        final ToastBarOperation undoOp;
1936c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        if (conversationViews != null) {
1946c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            final ArrayList<Conversation> conversations = new ArrayList<Conversation>(
1956c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                    conversationViews.size());
19606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira            Conversation conversation;
1976c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            for (ConversationItemView view : conversationViews) {
1986c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                if (view.getConversation().id != target.getConversation().id) {
19906642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                    conversation = view.getConversation();
20006642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                    conversation.localDeleteOnUpdate = true;
20106642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                    conversations.add(conversation);
2026c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                }
2036c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            }
204d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira            undoOp = new ToastBarOperation(conversationViews != null ?
205d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira                    (conversations.size() + 1) : 1, mSwipeAction, ToastBarOperation.UNDO);
2066c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            handleLeaveBehind(target, undoOp, context);
20709a4bfe3f81ee216b5c4a4e2d083432a4e387abdVikram Aggarwal            adapter.delete(conversations, new DestructiveAction() {
208bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                @Override
20909a4bfe3f81ee216b5c4a4e2d083432a4e387abdVikram Aggarwal                public void performAction() {
2108db7e407109532557718c6b8064792f2df7a073dMindy Pereira                    ConversationCursor cc = (ConversationCursor) adapter.getCursor();
2116c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                    switch (mSwipeAction) {
2126c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                        case R.id.archive:
213bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                            cc.archive(context, conversations);
2146c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                            break;
21506642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                        case R.id.change_folder:
2168db7e407109532557718c6b8064792f2df7a073dMindy Pereira                            FolderOperation folderOp = new FolderOperation(mFolder, false);
2178db7e407109532557718c6b8064792f2df7a073dMindy Pereira                            // For each conversation, for each operation, remove
2188db7e407109532557718c6b8064792f2df7a073dMindy Pereira                            // the current folder.
2198db7e407109532557718c6b8064792f2df7a073dMindy Pereira                            for (Conversation target : conversations) {
2208db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                HashMap<Uri, Folder> targetFolders = Folder
2218db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                        .hashMapForFoldersString(target.rawFolders);
2228db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                targetFolders.remove(folderOp.mFolder.uri);
2238db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                target.folderList = Folder.getUriString(targetFolders.values());
2248db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                target.rawFolders = Folder.getSerializedFolderString(mFolder,
2258db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                        targetFolders.values());
2268db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                cc.updateStrings(context, Conversation.listOf(target),
2278db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                        Conversation.UPDATE_FOLDER_COLUMNS, new String[] {
2288db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                                target.folderList, target.rawFolders
2298db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                        });
2308db7e407109532557718c6b8064792f2df7a073dMindy Pereira                            }
23106642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                            break;
2326c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                        case R.id.delete:
233bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook                            cc.delete(context, conversations);
2346c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                            break;
2356c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                    }
2366c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                }
2376c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            });
2386c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        } else {
239d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira            undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO);
2404cda97978c9f2c4b7e4a645268040223b8dbc83eMindy Pereira            target.getConversation().position = target.getParent() != null ?
2414cda97978c9f2c4b7e4a645268040223b8dbc83eMindy Pereira                    getPositionForView(target) : -1;
2426c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            handleLeaveBehind(target, undoOp, context);
243f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        }
244866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira    }
245866d319dd23ec8b7b7d5476c65f7f83469d55d2dMindy Pereira
246d3367499e56116854ed637b1036fd71057ac0f49Mindy Pereira    private void handleLeaveBehind(ConversationItemView target, ToastBarOperation undoOp,
2476c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            Context context) {
2486c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        Conversation conv = target.getConversation();
2490fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        final AnimatedAdapter adapter = getAnimatedAdapter();
25009f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        if (adapter == null) {
25109f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira            return;
25209f1ae9a9f209436c0c6b44a6e76b32b27937a01Mindy Pereira        }
2536c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        adapter.setupLeaveBehind(conv, undoOp, conv.position);
254bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook        ConversationCursor cc = (ConversationCursor)adapter.getCursor();
2556c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        switch (mSwipeAction) {
25606642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira            case R.id.change_folder:
2578db7e407109532557718c6b8064792f2df7a073dMindy Pereira                FolderOperation folderOp = new FolderOperation(mFolder, false);
2588db7e407109532557718c6b8064792f2df7a073dMindy Pereira                HashMap<Uri, Folder> targetFolders = Folder
2598db7e407109532557718c6b8064792f2df7a073dMindy Pereira                        .hashMapForFoldersString(conv.rawFolders);
2608db7e407109532557718c6b8064792f2df7a073dMindy Pereira                targetFolders.remove(folderOp.mFolder.uri);
2618db7e407109532557718c6b8064792f2df7a073dMindy Pereira                conv.folderList = Folder.getUriString(targetFolders.values());
2628db7e407109532557718c6b8064792f2df7a073dMindy Pereira                conv.rawFolders = Folder.getSerializedFolderString(mFolder, targetFolders.values());
2638db7e407109532557718c6b8064792f2df7a073dMindy Pereira                cc.mostlyDestructiveUpdate(context, Conversation.listOf(conv),
2648db7e407109532557718c6b8064792f2df7a073dMindy Pereira                        Conversation.UPDATE_FOLDER_COLUMNS, new String[] {
2658db7e407109532557718c6b8064792f2df7a073dMindy Pereira                                conv.folderList, conv.rawFolders
266ebdfd98264104cb5a6888acd663970b7c0b31382Mindy Pereira                        });
26706642fab1bf4ab95b5dd97a65b262845cf60c865Mindy Pereira                break;
2686c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            case R.id.archive:
269a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                cc.mostlyArchive(context, Conversation.listOf(conv));
2706c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                break;
2716c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira            case R.id.delete:
272a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                cc.mostlyDelete(context, Conversation.listOf(conv));
2736c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira                break;
2746c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        }
2756c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira        adapter.notifyDataSetChanged();
276a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira        if (mConvSelectionSet != null && !mConvSelectionSet.isEmpty()
277a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira                && mConvSelectionSet.contains(conv)) {
278a8ead90ce1e6c66e4ecacdf7cfa25c2cafc9bb3bMindy Pereira            mConvSelectionSet.toggle(null, conv);
279cff4a2b2e92258c6c85ed4af15bc13101aa71170Mindy Pereira        }
280f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
281f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
282f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
283f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public void onBeginDrag(View v) {
284f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // We do this so the underlying ScrollView knows that it won't get
285f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        // the chance to intercept events anymore
286f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        requestDisallowInterceptTouchEvent(true);
2871ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        SwipeableConversationItemView view = null;
2881ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        if (v instanceof ConversationItemView) {
2891ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            view = (SwipeableConversationItemView)v.getParent();
2901ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        }
2911ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        if (view != null) {
2921ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            view.addBackground(getContext(), getSwipeActionText());
2931ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            view.setBackgroundVisibility(View.VISIBLE);
2941ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        }
295f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
296f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
297f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    @Override
2986c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira    public void onDragCancelled(SwipeableItemView v) {
299f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
300f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira
30107118a01f7183645957010779222b84930f75b4eMindy Pereira    /**
30207118a01f7183645957010779222b84930f75b4eMindy Pereira     * Archive items using the swipe away animation before shrinking them away.
30307118a01f7183645957010779222b84930f75b4eMindy Pereira     */
304de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira    public void destroyItems(ArrayList<ConversationItemView> views,
30509a4bfe3f81ee216b5c4a4e2d083432a4e387abdVikram Aggarwal            final DestructiveAction listener) {
30607118a01f7183645957010779222b84930f75b4eMindy Pereira        if (views == null || views.size() == 0) {
30707118a01f7183645957010779222b84930f75b4eMindy Pereira            return;
30807118a01f7183645957010779222b84930f75b4eMindy Pereira        }
30907118a01f7183645957010779222b84930f75b4eMindy Pereira        final ArrayList<Conversation> conversations = new ArrayList<Conversation>();
31007118a01f7183645957010779222b84930f75b4eMindy Pereira        for (ConversationItemView view : views) {
311de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira            Conversation conv = view.getConversation();
312de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira            conv.position = view.getParent() != null ? getPositionForView(view) : -1;
313de3e74a82043733243c7391d7f983a5af8842891Mindy Pereira            conversations.add(conv);
31407118a01f7183645957010779222b84930f75b4eMindy Pereira        }
31507118a01f7183645957010779222b84930f75b4eMindy Pereira        mSwipeHelper.dismissChildren(views.get(0), views, new AnimatorListenerAdapter() {
31607118a01f7183645957010779222b84930f75b4eMindy Pereira            @Override
31707118a01f7183645957010779222b84930f75b4eMindy Pereira            public void onAnimationEnd(Animator animation) {
3180fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira                AnimatedAdapter adapter = getAnimatedAdapter();
3190fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira                if (adapter != null) {
3200fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira                    adapter.delete(conversations, listener);
3210fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira                }
32207118a01f7183645957010779222b84930f75b4eMindy Pereira            }
32307118a01f7183645957010779222b84930f75b4eMindy Pereira        });
32407118a01f7183645957010779222b84930f75b4eMindy Pereira    }
32507118a01f7183645957010779222b84930f75b4eMindy Pereira
3260fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    private AnimatedAdapter getAnimatedAdapter() {
3270fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira        return (AnimatedAdapter) getAdapter();
3280fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira    }
3290fb551891757ecddccb299d9df770bb1675e3fd2Mindy Pereira
330f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    public interface SwipeCompleteListener {
331f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira        public void onSwipeComplete(Collection<Conversation> conversations);
332f6a6b50c6b45f36b9317e1688f8b87310a67b037Mindy Pereira    }
3338937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira
3348937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    @Override
3358937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    public boolean performItemClick(View view, int pos, long id) {
3368937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        // Commit any existing destructive actions when the user selects a conversation to view.
3378937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        commitDestructiveActions();
3388937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira        return super.performItemClick(view, pos, id);
3398937bf1552a86853efc798a4d8df34c01115cdfdMindy Pereira    }
3401ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira
3411ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira    /**
3421ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira     * Get the text resource corresponding to the result of a swipe.
3431ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira     */
3441ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira    public int getSwipeActionText() {
3451ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        switch (mSwipeAction) {
3461ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            case R.id.archive:
3471ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                return R.string.archive;
3481ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            case R.id.delete:
3491ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                return R.string.delete;
3501ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira            case R.id.change_folder:
3511ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira                return R.string.remove_label;
3521ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        }
3531ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira        return -1;
3541ef988f0c8be136fda75ed207c222413db1d3f0cMindy Pereira    }
3556c72a787b58a0bc3afcb71093eddf8c29d1cf5edMindy Pereira}