1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2  * This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 package org.mozilla.gecko;
7 
8 import java.util.ArrayList;
9 import java.util.List;
10 
11 import org.mozilla.gecko.db.RemoteClient;
12 
13 import android.app.AlertDialog;
14 import android.app.AlertDialog.Builder;
15 import android.app.Dialog;
16 import android.content.DialogInterface;
17 import android.os.Bundle;
18 import android.support.v4.app.DialogFragment;
19 import android.support.v4.app.Fragment;
20 import android.util.SparseBooleanArray;
21 
22 /**
23  * A dialog fragment that displays a list of remote clients.
24  * <p>
25  * The dialog allows both single (one tap) and multiple (checkbox) selection.
26  * The dialog's results are communicated via the {@link RemoteClientsListener}
27  * interface. Either the dialog fragment's <i>target fragment</i> (see
28  * {@link Fragment#setTargetFragment(Fragment, int)}), or the containing
29  * <i>activity</i>, must implement that interface. See
30  * {@link #notifyListener(List)} for details.
31  */
32 public class RemoteClientsDialogFragment extends DialogFragment {
33     private static final String KEY_TITLE = "title";
34     private static final String KEY_CHOICE_MODE = "choice_mode";
35     private static final String KEY_POSITIVE_BUTTON_TEXT = "positive_button_text";
36     private static final String KEY_CLIENTS = "clients";
37 
38     public interface RemoteClientsListener {
39         // Always called on the main UI thread.
onClients(List<RemoteClient> clients)40         public void onClients(List<RemoteClient> clients);
41     }
42 
43     public enum ChoiceMode {
44         SINGLE,
45         MULTIPLE,
46     }
47 
newInstance(String title, String positiveButtonText, ChoiceMode choiceMode, ArrayList<RemoteClient> clients)48     public static RemoteClientsDialogFragment newInstance(String title, String positiveButtonText, ChoiceMode choiceMode, ArrayList<RemoteClient> clients) {
49         final RemoteClientsDialogFragment dialog = new RemoteClientsDialogFragment();
50         final Bundle args = new Bundle();
51         args.putString(KEY_TITLE, title);
52         args.putString(KEY_POSITIVE_BUTTON_TEXT, positiveButtonText);
53         args.putInt(KEY_CHOICE_MODE, choiceMode.ordinal());
54         args.putParcelableArrayList(KEY_CLIENTS, clients);
55         dialog.setArguments(args);
56         return dialog;
57     }
58 
RemoteClientsDialogFragment()59     public RemoteClientsDialogFragment() {
60         // Empty constructor is required for DialogFragment.
61     }
62 
63     @Override
onDestroy()64     public void onDestroy() {
65         super.onDestroy();
66 
67         GeckoApplication.watchReference(getActivity(), this);
68     }
69 
notifyListener(List<RemoteClient> clients)70     protected void notifyListener(List<RemoteClient> clients) {
71         RemoteClientsListener listener;
72         try {
73             listener = (RemoteClientsListener) getTargetFragment();
74         } catch (ClassCastException e) {
75             try {
76                 listener = (RemoteClientsListener) getActivity();
77             } catch (ClassCastException f) {
78                 throw new ClassCastException(getTargetFragment() + " or " + getActivity()
79                         + " must implement RemoteClientsListener");
80             }
81         }
82         listener.onClients(clients);
83     }
84 
85     @Override
onCreateDialog(Bundle savedInstanceState)86     public Dialog onCreateDialog(Bundle savedInstanceState) {
87         final String title = getArguments().getString(KEY_TITLE);
88         final String positiveButtonText = getArguments().getString(KEY_POSITIVE_BUTTON_TEXT);
89         final ChoiceMode choiceMode = ChoiceMode.values()[getArguments().getInt(KEY_CHOICE_MODE)];
90         final ArrayList<RemoteClient> clients = getArguments().getParcelableArrayList(KEY_CLIENTS);
91 
92         final Builder builder = new AlertDialog.Builder(getActivity());
93         builder.setTitle(title);
94 
95         final String[] clientNames = new String[clients.size()];
96         for (int i = 0; i < clients.size(); i++) {
97             clientNames[i] = clients.get(i).name;
98         }
99 
100         if (choiceMode == ChoiceMode.MULTIPLE) {
101             builder.setMultiChoiceItems(clientNames, null, null);
102             builder.setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
103                 @Override
104                 public void onClick(DialogInterface dialogInterface, int which) {
105                     if (which != Dialog.BUTTON_POSITIVE) {
106                         return;
107                     }
108 
109                     final AlertDialog dialog = (AlertDialog) dialogInterface;
110                     final SparseBooleanArray checkedItemPositions = dialog.getListView().getCheckedItemPositions();
111                     final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>();
112                     for (int i = 0; i < clients.size(); i++) {
113                         if (checkedItemPositions.get(i)) {
114                             checked.add(clients.get(i));
115                         }
116                     }
117                     notifyListener(checked);
118                 }
119             });
120         } else {
121             builder.setItems(clientNames, new DialogInterface.OnClickListener() {
122                 @Override
123                 public void onClick(DialogInterface dialog, int index) {
124                     final ArrayList<RemoteClient> checked = new ArrayList<RemoteClient>();
125                     checked.add(clients.get(index));
126                     notifyListener(checked);
127                 }
128             });
129         }
130 
131         return builder.create();
132     }
133 }
134