1c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank/*
2c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Copyright (C) 2012 Google Inc.
3c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Licensed to The Android Open Source Project.
4c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank *
5c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Licensed under the Apache License, Version 2.0 (the "License");
6c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * you may not use this file except in compliance with the License.
7c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * You may obtain a copy of the License at
8c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank *
9c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank *      http://www.apache.org/licenses/LICENSE-2.0
10c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank *
11c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * Unless required by applicable law or agreed to in writing, software
12c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * distributed under the License is distributed on an "AS IS" BASIS,
13c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * See the License for the specific language governing permissions and
15c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank * limitations under the License.
16c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank */
17c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
18c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankpackage com.android.email.provider;
19c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
20c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.app.AlertDialog;
21c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.Context;
22c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface;
2326164054710375519ba7468987971a7a3340ba7eMarc Blankimport android.content.DialogInterface.OnCancelListener;
24c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface.OnClickListener;
25c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.content.DialogInterface.OnMultiChoiceClickListener;
26c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.database.Cursor;
2726164054710375519ba7468987971a7a3340ba7eMarc Blankimport android.net.Uri;
28c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.view.View;
29c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport android.widget.AdapterView;
309439595e582803ede8c4bb8634cf93457681edd7Paul Westbrookimport android.widget.Button;
31c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
32c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.R;
33c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.providers.Folder;
34c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.providers.UIProvider;
35c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.FolderSelectorAdapter;
36c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.FolderSelectorAdapter.FolderRow;
37c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport com.android.mail.ui.SeparatedFolderListAdapter;
38c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
39c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.HashMap;
40c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.HashSet;
41c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blankimport java.util.Map.Entry;
42c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
43266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blankpublic class FolderPickerDialog implements OnClickListener, OnMultiChoiceClickListener,
44266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank        OnCancelListener {
459439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook    private final AlertDialog mDialog;
469439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook    private final HashMap<Folder, Boolean> mCheckedState;
479439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook    private final SeparatedFolderListAdapter mAdapter;
489439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook    private final FolderPickerCallback mCallback;
49c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
50266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank    public FolderPickerDialog(final Context context, Uri uri,
51266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank            FolderPickerCallback callback, String header, boolean cancelable) {
52c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCallback = callback;
53c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        // Mapping of a folder's uri to its checked state
54c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCheckedState = new HashMap<Folder, Boolean>();
55c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        AlertDialog.Builder builder = new AlertDialog.Builder(context);
5626164054710375519ba7468987971a7a3340ba7eMarc Blank        builder.setTitle(header);
57c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        builder.setPositiveButton(R.string.ok, this);
58266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank        builder.setCancelable(cancelable);
59266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank        builder.setOnCancelListener(this);
6026164054710375519ba7468987971a7a3340ba7eMarc Blank        // TODO: Do this on a background thread
61c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        final Cursor foldersCursor = context.getContentResolver().query(
6226164054710375519ba7468987971a7a3340ba7eMarc Blank                uri, UIProvider.FOLDERS_PROJECTION, null, null, null);
63c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        try {
644f32213ebebb59d5316e0dd4ca9d78dc1c170879Tony Mantler            mAdapter = new SeparatedFolderListAdapter();
658ff282a260eef699c3e22e8809075191706a171amindyp            mAdapter.addSection(new FolderPickerSelectorAdapter(context, foldersCursor,
66c07a44240311eb0ce44654284b010e6df8b08e86Andrew Sapperstein                    new HashSet<String>(), R.layout.multi_folders_view));
67c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            builder.setAdapter(mAdapter, this);
68c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        } finally {
69c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            foldersCursor.close();
70c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        }
71c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mDialog = builder.create();
72c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    }
73c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
74c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    public void show() {
75c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mDialog.show();
76c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
77c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            @Override
78c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
799439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook                final Object item = mAdapter.getItem(position);
80c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                if (item instanceof FolderRow) {
81c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                    update((FolderRow) item);
82c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                }
83c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            }
84c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        });
859439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook
869439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE);
879439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        if (mCheckedState.size() == 0) {
889439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook            // No items are selected, so disable the OK button.
899439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook            button.setEnabled(false);
909439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        }
91c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    }
92c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
93c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    /**
94c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank     * Call this to update the state of folders as a result of them being
95c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank     * selected / de-selected.
96c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank     *
97c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank     * @param row The item being updated.
98c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank     */
99c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    public void update(FolderSelectorAdapter.FolderRow row) {
100c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        // Update the UI
101cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao        final boolean add = !row.isSelected();
102c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        if (!add) {
103c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            // This would remove the check on a single radio button, so just
104c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            // return.
105c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            return;
106c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        }
107c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        // Clear any other checked items.
108c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mAdapter.getCount();
109c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        for (int i = 0; i < mAdapter.getCount(); i++) {
110c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            Object item = mAdapter.getItem(i);
111c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            if (item instanceof FolderRow) {
112cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao                ((FolderRow)item).setIsSelected(false);
113c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            }
114c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        }
115c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCheckedState.clear();
116cd4a94b7e1ff89961c422682d562149744dac0e7Jin Cao        row.setIsSelected(add);
117c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mAdapter.notifyDataSetChanged();
118c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCheckedState.put(row.getFolder(), add);
1199439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook
1209439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        // Since we know that an item is selected in the list, enable the OK button
1219439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE);
1229439595e582803ede8c4bb8634cf93457681edd7Paul Westbrook        button.setEnabled(true);
123c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    }
124c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
125c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    @Override
126c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    public void onClick(DialogInterface dialog, int which) {
127c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        switch (which) {
128c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            case DialogInterface.BUTTON_POSITIVE:
129c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                Folder folder = null;
130c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                for (Entry<Folder, Boolean> entry : mCheckedState.entrySet()) {
131c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                    if (entry.getValue()) {
132c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                        folder = entry.getKey();
133c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                        break;
134c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                    }
135c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                }
136c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                mCallback.select(folder);
137c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                break;
138c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank            default:
139c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                onClick(dialog, which, true);
140c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank                break;
141c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        }
142c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    }
143c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank
144c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    @Override
145c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
146c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        final FolderRow row = (FolderRow) mAdapter.getItem(which);
147c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        // Clear any other checked items.
148c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCheckedState.clear();
149c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        isChecked = true;
150c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mCheckedState.put(row.getFolder(), isChecked);
151c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank        mDialog.getListView().setItemChecked(which, false);
152c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank    }
153266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank
154266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank    @Override
155266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank    public void onCancel(DialogInterface dialog) {
156266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank        mCallback.cancel();
157266064bcc7c6ed7318a284d59bb83d53edbf1921Marc Blank    }
158c6089bc01f2ae49fb11904a4b4f222811358254fMarc Blank}
159