• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.android_scripting.facade.ui;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.AlertDialog.Builder;
22 import android.content.DialogInterface;
23 import android.text.method.PasswordTransformationMethod;
24 import android.widget.EditText;
25 
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.TreeSet;
32 
33 import org.json.JSONArray;
34 import org.json.JSONException;
35 
36 /**
37  * Wrapper class for alert dialog running in separate thread.
38  *
39  */
40 class AlertDialogTask extends DialogTask {
41 
42   private final String mTitle;
43   private final String mMessage;
44 
45   private final List<String> mItems;
46   private final Set<Integer> mSelectedItems;
47   private final Map<String, Object> mResultMap;
48   private InputType mInputType;
49   private int mEditInputType = 0;
50 
51   private String mPositiveButtonText;
52   private String mNegativeButtonText;
53   private String mNeutralButtonText;
54 
55   private EditText mEditText;
56   private String mDefaultText;
57 
58   private enum InputType {
59     DEFAULT, MENU, SINGLE_CHOICE, MULTI_CHOICE, PLAIN_TEXT, PASSWORD;
60   }
61 
AlertDialogTask(String title, String message)62   public AlertDialogTask(String title, String message) {
63     mTitle = title;
64     mMessage = message;
65     mInputType = InputType.DEFAULT;
66     mItems = new ArrayList<String>();
67     mSelectedItems = new TreeSet<Integer>();
68     mResultMap = new HashMap<String, Object>();
69   }
70 
setPositiveButtonText(String text)71   public void setPositiveButtonText(String text) {
72     mPositiveButtonText = text;
73   }
74 
setNegativeButtonText(String text)75   public void setNegativeButtonText(String text) {
76     mNegativeButtonText = text;
77   }
78 
setNeutralButtonText(String text)79   public void setNeutralButtonText(String text) {
80     mNeutralButtonText = text;
81   }
82 
83   /**
84    * Set list items.
85    *
86    * @param items
87    */
setItems(JSONArray items)88   public void setItems(JSONArray items) {
89     mItems.clear();
90     for (int i = 0; i < items.length(); i++) {
91       try {
92         mItems.add(items.getString(i));
93       } catch (JSONException e) {
94         throw new RuntimeException(e);
95       }
96     }
97     mInputType = InputType.MENU;
98   }
99 
100   /**
101    * Set single choice items.
102    *
103    * @param items
104    *          a list of items as {@link String}s to display
105    * @param selected
106    *          the index of the item that is selected by default
107    */
setSingleChoiceItems(JSONArray items, int selected)108   public void setSingleChoiceItems(JSONArray items, int selected) {
109     setItems(items);
110     mSelectedItems.clear();
111     mSelectedItems.add(selected);
112     mInputType = InputType.SINGLE_CHOICE;
113   }
114 
115   /**
116    * Set multi choice items.
117    *
118    * @param items
119    *          a list of items as {@link String}s to display
120    * @param selected
121    *          a list of indices for items that should be selected by default
122    * @throws JSONException
123    */
setMultiChoiceItems(JSONArray items, JSONArray selected)124   public void setMultiChoiceItems(JSONArray items, JSONArray selected) throws JSONException {
125     setItems(items);
126     mSelectedItems.clear();
127     if (selected != null) {
128       for (int i = 0; i < selected.length(); i++) {
129         mSelectedItems.add(selected.getInt(i));
130       }
131     }
132     mInputType = InputType.MULTI_CHOICE;
133   }
134 
135   /**
136    * Returns the list of selected items.
137    */
getSelectedItems()138   public Set<Integer> getSelectedItems() {
139     return mSelectedItems;
140   }
141 
setTextInput(String defaultText)142   public void setTextInput(String defaultText) {
143     mDefaultText = defaultText;
144     mInputType = InputType.PLAIN_TEXT;
145     setEditInputType("text");
146   }
147 
setEditInputType(String editInputType)148   public void setEditInputType(String editInputType) {
149     String[] list = editInputType.split("\\|");
150     Map<String, Integer> types = ViewInflater.getInputTypes();
151     mEditInputType = 0;
152     for (String flag : list) {
153       Integer v = types.get(flag.trim());
154       if (v != null) {
155         mEditInputType |= v;
156       }
157     }
158     if (mEditInputType == 0) {
159       mEditInputType = android.text.InputType.TYPE_CLASS_TEXT;
160     }
161   }
162 
setPasswordInput()163   public void setPasswordInput() {
164     mInputType = InputType.PASSWORD;
165   }
166 
167   @Override
onCreate()168   public void onCreate() {
169     super.onCreate();
170     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
171     if (mTitle != null) {
172       builder.setTitle(mTitle);
173     }
174     // Can't display both a message and items. We'll elect to show the items instead.
175     if (mMessage != null && mItems.isEmpty()) {
176       builder.setMessage(mMessage);
177     }
178     switch (mInputType) {
179     // Add single choice menu items to dialog.
180     case SINGLE_CHOICE:
181       builder.setSingleChoiceItems(getItemsAsCharSequenceArray(), mSelectedItems.iterator().next(),
182           new DialogInterface.OnClickListener() {
183             @Override
184             public void onClick(DialogInterface dialog, int item) {
185               mSelectedItems.clear();
186               mSelectedItems.add(item);
187             }
188           });
189       break;
190     // Add multiple choice items to the dialog.
191     case MULTI_CHOICE:
192       boolean[] selectedItems = new boolean[mItems.size()];
193       for (int i : mSelectedItems) {
194         selectedItems[i] = true;
195       }
196       builder.setMultiChoiceItems(getItemsAsCharSequenceArray(), selectedItems,
197           new DialogInterface.OnMultiChoiceClickListener() {
198             @Override
199             public void onClick(DialogInterface dialog, int item, boolean isChecked) {
200               if (isChecked) {
201                 mSelectedItems.add(item);
202               } else {
203                 mSelectedItems.remove(item);
204               }
205             }
206           });
207       break;
208     // Add standard, menu-like, items to dialog.
209     case MENU:
210       builder.setItems(getItemsAsCharSequenceArray(), new DialogInterface.OnClickListener() {
211         public void onClick(DialogInterface dialog, int item) {
212           Map<String, Integer> result = new HashMap<String, Integer>();
213           result.put("item", item);
214           dismissDialog();
215           setResult(result);
216         }
217       });
218       break;
219     case PLAIN_TEXT:
220       mEditText = new EditText(getActivity());
221       if (mDefaultText != null) {
222         mEditText.setText(mDefaultText);
223       }
224       mEditText.setInputType(mEditInputType);
225       builder.setView(mEditText);
226       break;
227     case PASSWORD:
228       mEditText = new EditText(getActivity());
229       mEditText.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
230       mEditText.setTransformationMethod(new PasswordTransformationMethod());
231       builder.setView(mEditText);
232       break;
233     default:
234       // No input type specified.
235     }
236     configureButtons(builder, getActivity());
237     addOnCancelListener(builder, getActivity());
238     mDialog = builder.show();
239     mShowLatch.countDown();
240   }
241 
getItemsAsCharSequenceArray()242   private CharSequence[] getItemsAsCharSequenceArray() {
243     return mItems.toArray(new CharSequence[mItems.size()]);
244   }
245 
addOnCancelListener(final AlertDialog.Builder builder, final Activity activity)246   private Builder addOnCancelListener(final AlertDialog.Builder builder, final Activity activity) {
247     return builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
248       @Override
249       public void onCancel(DialogInterface dialog) {
250         mResultMap.put("canceled", true);
251         setResult();
252       }
253     });
254   }
255 
256   private void configureButtons(final AlertDialog.Builder builder, final Activity activity) {
257     DialogInterface.OnClickListener buttonListener = new DialogInterface.OnClickListener() {
258       @Override
259       public void onClick(DialogInterface dialog, int which) {
260         switch (which) {
261         case DialogInterface.BUTTON_POSITIVE:
262           mResultMap.put("which", "positive");
263           break;
264         case DialogInterface.BUTTON_NEGATIVE:
265           mResultMap.put("which", "negative");
266           break;
267         case DialogInterface.BUTTON_NEUTRAL:
268           mResultMap.put("which", "neutral");
269 
270           break;
271         }
272         setResult();
273       }
274     };
275     if (mNegativeButtonText != null) {
276       builder.setNegativeButton(mNegativeButtonText, buttonListener);
277     }
278     if (mPositiveButtonText != null) {
279       builder.setPositiveButton(mPositiveButtonText, buttonListener);
280     }
281     if (mNeutralButtonText != null) {
282       builder.setNeutralButton(mNeutralButtonText, buttonListener);
283     }
284   }
285 
286   private void setResult() {
287     dismissDialog();
288     if (mInputType == InputType.PLAIN_TEXT || mInputType == InputType.PASSWORD) {
289       mResultMap.put("value", mEditText.getText().toString());
290     }
291     setResult(mResultMap);
292   }
293 
294 }
295