Home | History | Annotate | Download | only in ui
      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.mail.ui;
     19 
     20 import android.content.Context;
     21 import android.content.DialogInterface;
     22 import android.database.Cursor;
     23 import android.net.Uri;
     24 
     25 import com.android.mail.R;
     26 import com.android.mail.providers.Account;
     27 import com.android.mail.providers.Conversation;
     28 import com.android.mail.providers.Folder;
     29 import com.android.mail.providers.UIProvider;
     30 import com.android.mail.providers.UIProvider.FolderType;
     31 import com.android.mail.ui.FolderSelectorAdapter.FolderRow;
     32 import com.android.mail.utils.Utils;
     33 import com.google.common.collect.ImmutableSet;
     34 
     35 import java.util.Arrays;
     36 import java.util.Collection;
     37 import java.util.HashMap;
     38 import java.util.HashSet;
     39 import java.util.List;
     40 
     41 /**
     42  * Displays a folder selection dialog for the conversation provided. It allows
     43  * the user to mark folders to assign that conversation to.
     44  */
     45 public class MultiFoldersSelectionDialog extends FolderSelectionDialog {
     46     private final boolean mSingle;
     47     private final HashMap<Uri, FolderOperation> mOperations;
     48 
     49     /**
     50      * Create a new {@link MultiFoldersSelectionDialog}. It is displayed when
     51      * the {@link #show()} method is called.
     52      * @param context
     53      * @param account the current account
     54      * @param updater
     55      * @param target conversations that are impacted
     56      * @param isBatch whether the dialog is shown during Contextual Action Bar
     57      *            (CAB) mode
     58      * @param currentFolder the current folder that the
     59      *            {@link FolderListFragment} is showing
     60      */
     61     public MultiFoldersSelectionDialog(final Context context, final Account account,
     62             final ConversationUpdater updater, final Collection<Conversation> target,
     63             final boolean isBatch, final Folder currentFolder) {
     64         super(context, account, updater, target, isBatch, currentFolder);
     65         mSingle = !account
     66                 .supportsCapability(UIProvider.AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV);
     67         mOperations = new HashMap<Uri, FolderOperation>();
     68 
     69         mBuilder.setTitle(R.string.change_folders_selection_dialog_title);
     70         mBuilder.setPositiveButton(R.string.ok, this);
     71     }
     72 
     73     @Override
     74     protected void updateAdapterInBackground(Context context) {
     75         Cursor foldersCursor = null;
     76         try {
     77             foldersCursor = context.getContentResolver().query(
     78                     !Utils.isEmpty(mAccount.fullFolderListUri) ? mAccount.fullFolderListUri
     79                             : mAccount.folderListUri, UIProvider.FOLDERS_PROJECTION, null, null,
     80                             null);
     81             /** All the folders that this conversations is assigned to. */
     82             final HashSet<String> checked = new HashSet<String>();
     83             for (final Conversation conversation : mTarget) {
     84                 final List<Folder> rawFolders = conversation.getRawFolders();
     85                 if (rawFolders != null && rawFolders.size() > 0) {
     86                     // Parse the raw folders and get all the uris.
     87                     checked.addAll(Arrays.asList(Folder.getUriArray(rawFolders)));
     88                 } else {
     89                     // There are no folders for this conversation, so it must
     90                     // belong to the folder we are currently looking at.
     91                     checked.add(mCurrentFolder.folderUri.fullUri.toString());
     92                 }
     93             }
     94             // TODO(mindyp) : bring this back in UR8 when Email providers
     95             // will have divided folder sections.
     96             /* final String[] headers = mContext.getResources()
     97              .getStringArray(R.array.moveto_folder_sections);
     98              // Currently, the number of adapters are assumed to match the
     99              // number of headers in the string array.
    100              mAdapter.addSection(new SystemFolderSelectorAdapter(mContext,
    101              foldersCursor, checked, R.layout.multi_folders_view, null));
    102 
    103             // TODO(mindyp): we currently do not support frequently moved to
    104             // folders, at headers[1]; need to define what that means.*/
    105             mAdapter.addSection(new AddableFolderSelectorAdapter(context,
    106                     AddableFolderSelectorAdapter.filterFolders(foldersCursor,
    107                             ImmutableSet.of(FolderType.INBOX_SECTION)), checked,
    108                     R.layout.multi_folders_view, null));
    109             mBuilder.setAdapter(mAdapter, MultiFoldersSelectionDialog.this);
    110         } finally {
    111             if (foldersCursor != null) {
    112                 foldersCursor.close();
    113             }
    114         }
    115     }
    116 
    117     @Override
    118     protected void onListItemClick(int position) {
    119         final Object item = mAdapter.getItem(position);
    120         if (item instanceof FolderRow) {
    121             update((FolderRow) item);
    122         }
    123     }
    124 
    125     /**
    126      * Call this to update the state of folders as a result of them being
    127      * selected / de-selected.
    128      *
    129      * @param row The item being updated.
    130      */
    131     private final void update(FolderSelectorAdapter.FolderRow row) {
    132         final boolean add = !row.isPresent();
    133         if (mSingle) {
    134             if (!add) {
    135                 // This would remove the check on a single radio button, so just
    136                 // return.
    137                 return;
    138             }
    139             // Clear any other checked items.
    140             for (int i = 0, size = mAdapter.getCount(); i < size; i++) {
    141                 final Object item = mAdapter.getItem(i);
    142                 if (item instanceof FolderRow) {
    143                    ((FolderRow)item).setIsPresent(false);
    144                    final Folder folder = ((FolderRow)item).getFolder();
    145                    mOperations.put(folder.folderUri.fullUri,
    146                            new FolderOperation(folder, false));
    147                 }
    148             }
    149         }
    150         row.setIsPresent(add);
    151         mAdapter.notifyDataSetChanged();
    152         final Folder folder = row.getFolder();
    153         mOperations.put(folder.folderUri.fullUri, new FolderOperation(folder, add));
    154     }
    155 
    156     @Override
    157     public void onClick(DialogInterface dialog, int which) {
    158         switch (which) {
    159             case DialogInterface.BUTTON_POSITIVE:
    160                 if (mUpdater != null) {
    161                     mUpdater.assignFolder(mOperations.values(), mTarget, mBatch,
    162                             true /* showUndo */, false /* isMoveTo */);
    163                 }
    164                 break;
    165             case DialogInterface.BUTTON_NEGATIVE:
    166                 break;
    167             default:
    168                 break;
    169         }
    170     }
    171 }
    172