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 18 package com.android.email.provider; 19 20 import android.app.AlertDialog; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.DialogInterface.OnCancelListener; 24 import android.content.DialogInterface.OnClickListener; 25 import android.content.DialogInterface.OnMultiChoiceClickListener; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.view.View; 29 import android.widget.AdapterView; 30 import android.widget.Button; 31 32 import com.android.mail.R; 33 import com.android.mail.providers.Folder; 34 import com.android.mail.providers.UIProvider; 35 import com.android.mail.ui.FolderSelectorAdapter; 36 import com.android.mail.ui.FolderSelectorAdapter.FolderRow; 37 import com.android.mail.ui.SeparatedFolderListAdapter; 38 39 import java.util.HashMap; 40 import java.util.HashSet; 41 import java.util.Map.Entry; 42 43 public 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