1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.email.provider;
19
20import android.app.AlertDialog;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.content.DialogInterface.OnCancelListener;
24import android.content.DialogInterface.OnClickListener;
25import android.content.DialogInterface.OnMultiChoiceClickListener;
26import android.database.Cursor;
27import android.net.Uri;
28import android.view.View;
29import android.widget.AdapterView;
30import android.widget.Button;
31
32import com.android.mail.R;
33import com.android.mail.providers.Folder;
34import com.android.mail.providers.UIProvider;
35import com.android.mail.ui.FolderSelectorAdapter;
36import com.android.mail.ui.FolderSelectorAdapter.FolderRow;
37import com.android.mail.ui.SeparatedFolderListAdapter;
38
39import java.util.HashMap;
40import java.util.HashSet;
41import java.util.Map.Entry;
42
43public class FolderPickerDialog implements OnClickListener, OnMultiChoiceClickListener,
44        OnCancelListener {
45    private final AlertDialog mDialog;
46    private final HashMap<Folder, Boolean> mCheckedState;
47    private final SeparatedFolderListAdapter mAdapter;
48    private final FolderPickerCallback mCallback;
49
50    public FolderPickerDialog(final Context context, Uri uri,
51            FolderPickerCallback callback, String header, boolean cancelable) {
52        mCallback = callback;
53        // Mapping of a folder's uri to its checked state
54        mCheckedState = new HashMap<Folder, Boolean>();
55        AlertDialog.Builder builder = new AlertDialog.Builder(context);
56        builder.setTitle(header);
57        builder.setPositiveButton(R.string.ok, this);
58        builder.setCancelable(cancelable);
59        builder.setOnCancelListener(this);
60        // TODO: Do this on a background thread
61        final Cursor foldersCursor = context.getContentResolver().query(
62                uri, UIProvider.FOLDERS_PROJECTION, null, null, null);
63        try {
64            mAdapter = new SeparatedFolderListAdapter();
65            String[] headers = context.getResources()
66                    .getStringArray(R.array.moveto_folder_sections);
67            mAdapter.addSection(new FolderPickerSelectorAdapter(context, foldersCursor,
68                    new HashSet<String>(), R.layout.radiobutton_single_folders_view, headers[2]));
69            builder.setAdapter(mAdapter, this);
70        } finally {
71            foldersCursor.close();
72        }
73        mDialog = builder.create();
74    }
75
76    public void show() {
77        mDialog.show();
78        mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
79            @Override
80            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
81                final Object item = mAdapter.getItem(position);
82                if (item instanceof FolderRow) {
83                    update((FolderRow) item);
84                }
85            }
86        });
87
88        final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE);
89        if (mCheckedState.size() == 0) {
90            // No items are selected, so disable the OK button.
91            button.setEnabled(false);
92        }
93    }
94
95    /**
96     * Call this to update the state of folders as a result of them being
97     * selected / de-selected.
98     *
99     * @param row The item being updated.
100     */
101    public void update(FolderSelectorAdapter.FolderRow row) {
102        // Update the UI
103        final boolean add = !row.isPresent();
104        if (!add) {
105            // This would remove the check on a single radio button, so just
106            // return.
107            return;
108        }
109        // Clear any other checked items.
110        mAdapter.getCount();
111        for (int i = 0; i < mAdapter.getCount(); i++) {
112            Object item = mAdapter.getItem(i);
113            if (item instanceof FolderRow) {
114                ((FolderRow)item).setIsPresent(false);
115            }
116        }
117        mCheckedState.clear();
118        row.setIsPresent(add);
119        mAdapter.notifyDataSetChanged();
120        mCheckedState.put(row.getFolder(), add);
121
122        // Since we know that an item is selected in the list, enable the OK button
123        final Button button = mDialog.getButton(AlertDialog.BUTTON_POSITIVE);
124        button.setEnabled(true);
125    }
126
127    @Override
128    public void onClick(DialogInterface dialog, int which) {
129        switch (which) {
130            case DialogInterface.BUTTON_POSITIVE:
131                Folder folder = null;
132                for (Entry<Folder, Boolean> entry : mCheckedState.entrySet()) {
133                    if (entry.getValue()) {
134                        folder = entry.getKey();
135                        break;
136                    }
137                }
138                mCallback.select(folder);
139                break;
140            default:
141                onClick(dialog, which, true);
142                break;
143        }
144    }
145
146    @Override
147    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
148        final FolderRow row = (FolderRow) mAdapter.getItem(which);
149        // Clear any other checked items.
150        mCheckedState.clear();
151        isChecked = true;
152        mCheckedState.put(row.getFolder(), isChecked);
153        mDialog.getListView().setItemChecked(which, false);
154    }
155
156    @Override
157    public void onCancel(DialogInterface dialog) {
158        mCallback.cancel();
159    }
160}
161