mobile/android/base/prompts/PromptInput.java

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:7c797f2bd21a
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.prompts;
7
8 import java.text.SimpleDateFormat;
9 import java.util.Calendar;
10 import java.util.GregorianCalendar;
11
12 import org.json.JSONObject;
13 import org.mozilla.gecko.widget.AllCapsTextView;
14 import org.mozilla.gecko.widget.DateTimePicker;
15
16 import android.content.Context;
17 import android.content.res.Configuration;
18 import android.os.Build;
19 import android.text.Html;
20 import android.text.InputType;
21 import android.text.TextUtils;
22 import android.text.format.DateFormat;
23 import android.util.Log;
24 import android.view.View;
25 import android.view.ViewGroup.LayoutParams;
26 import android.view.inputmethod.InputMethodManager;
27 import android.widget.ArrayAdapter;
28 import android.widget.CheckBox;
29 import android.widget.DatePicker;
30 import android.widget.EditText;
31 import android.widget.LinearLayout;
32 import android.widget.Spinner;
33 import android.widget.TextView;
34 import android.widget.TimePicker;
35
36 public class PromptInput {
37 protected final String mLabel;
38 protected final String mType;
39 protected final String mId;
40 protected final String mValue;
41 protected OnChangeListener mListener;
42 protected View mView;
43 public static final String LOGTAG = "GeckoPromptInput";
44
45 public interface OnChangeListener {
46 public void onChange(PromptInput input);
47 }
48
49 public void setListener(OnChangeListener listener) {
50 mListener = listener;
51 }
52
53 public static class EditInput extends PromptInput {
54 protected final String mHint;
55 protected final boolean mAutofocus;
56 public static final String INPUT_TYPE = "textbox";
57
58 public EditInput(JSONObject object) {
59 super(object);
60 mHint = object.optString("hint");
61 mAutofocus = object.optBoolean("autofocus");
62 }
63
64 public View getView(final Context context) throws UnsupportedOperationException {
65 EditText input = new EditText(context);
66 input.setInputType(InputType.TYPE_CLASS_TEXT);
67 input.setText(mValue);
68
69 if (!TextUtils.isEmpty(mHint)) {
70 input.setHint(mHint);
71 }
72
73 if (mAutofocus) {
74 input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
75 @Override
76 public void onFocusChange(View v, boolean hasFocus) {
77 if (hasFocus) {
78 ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(v, 0);
79 }
80 }
81 });
82 input.requestFocus();
83 }
84
85 mView = (View)input;
86 return mView;
87 }
88
89 @Override
90 public Object getValue() {
91 EditText edit = (EditText)mView;
92 return edit.getText();
93 }
94 }
95
96 public static class NumberInput extends EditInput {
97 public static final String INPUT_TYPE = "number";
98 public NumberInput(JSONObject obj) {
99 super(obj);
100 }
101
102 public View getView(final Context context) throws UnsupportedOperationException {
103 EditText input = (EditText) super.getView(context);
104 input.setRawInputType(Configuration.KEYBOARD_12KEY);
105 input.setInputType(InputType.TYPE_CLASS_NUMBER |
106 InputType.TYPE_NUMBER_FLAG_SIGNED);
107 return input;
108 }
109 }
110
111 public static class PasswordInput extends EditInput {
112 public static final String INPUT_TYPE = "password";
113 public PasswordInput(JSONObject obj) {
114 super(obj);
115 }
116
117 public View getView(Context context) throws UnsupportedOperationException {
118 EditText input = (EditText) super.getView(context);
119 input.setInputType(InputType.TYPE_CLASS_TEXT |
120 InputType.TYPE_TEXT_VARIATION_PASSWORD |
121 InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
122 return input;
123 }
124
125 @Override
126 public Object getValue() {
127 EditText edit = (EditText)mView;
128 return edit.getText();
129 }
130 }
131
132 public static class CheckboxInput extends PromptInput {
133 public static final String INPUT_TYPE = "checkbox";
134 private boolean mChecked;
135
136 public CheckboxInput(JSONObject obj) {
137 super(obj);
138 mChecked = obj.optBoolean("checked");
139 }
140
141 public View getView(Context context) throws UnsupportedOperationException {
142 CheckBox checkbox = new CheckBox(context);
143 checkbox.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
144 checkbox.setText(mLabel);
145 checkbox.setChecked(mChecked);
146 mView = (View)checkbox;
147 return mView;
148 }
149
150 @Override
151 public Object getValue() {
152 CheckBox checkbox = (CheckBox)mView;
153 return checkbox.isChecked() ? Boolean.TRUE : Boolean.FALSE;
154 }
155 }
156
157 public static class DateTimeInput extends PromptInput {
158 public static final String[] INPUT_TYPES = new String[] {
159 "date",
160 "week",
161 "time",
162 "datetime-local",
163 "datetime",
164 "month"
165 };
166
167 public DateTimeInput(JSONObject obj) {
168 super(obj);
169 }
170
171 public View getView(Context context) throws UnsupportedOperationException {
172 if (mType.equals("date")) {
173 try {
174 DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd", mValue,
175 DateTimePicker.PickersState.DATE);
176 input.toggleCalendar(true);
177 mView = (View)input;
178 } catch (UnsupportedOperationException ex) {
179 // We can't use our custom version of the DatePicker widget because the sdk is too old.
180 // But we can fallback on the native one.
181 DatePicker input = new DatePicker(context);
182 try {
183 if (!TextUtils.isEmpty(mValue)) {
184 GregorianCalendar calendar = new GregorianCalendar();
185 calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(mValue));
186 input.updateDate(calendar.get(Calendar.YEAR),
187 calendar.get(Calendar.MONTH),
188 calendar.get(Calendar.DAY_OF_MONTH));
189 }
190 } catch (Exception e) {
191 Log.e(LOGTAG, "error parsing format string: " + e);
192 }
193 mView = (View)input;
194 }
195 } else if (mType.equals("week")) {
196 DateTimePicker input = new DateTimePicker(context, "yyyy-'W'ww", mValue,
197 DateTimePicker.PickersState.WEEK);
198 mView = (View)input;
199 } else if (mType.equals("time")) {
200 TimePicker input = new TimePicker(context);
201 input.setIs24HourView(DateFormat.is24HourFormat(context));
202
203 GregorianCalendar calendar = new GregorianCalendar();
204 if (!TextUtils.isEmpty(mValue)) {
205 try {
206 calendar.setTime(new SimpleDateFormat("HH:mm").parse(mValue));
207 } catch (Exception e) { }
208 }
209 input.setCurrentHour(calendar.get(GregorianCalendar.HOUR_OF_DAY));
210 input.setCurrentMinute(calendar.get(GregorianCalendar.MINUTE));
211 mView = (View)input;
212 } else if (mType.equals("datetime-local") || mType.equals("datetime")) {
213 DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd HH:mm", mValue,
214 DateTimePicker.PickersState.DATETIME);
215 input.toggleCalendar(true);
216 mView = (View)input;
217 } else if (mType.equals("month")) {
218 DateTimePicker input = new DateTimePicker(context, "yyyy-MM", mValue,
219 DateTimePicker.PickersState.MONTH);
220 mView = (View)input;
221 }
222 return mView;
223 }
224
225 private static String formatDateString(String dateFormat, Calendar calendar) {
226 return new SimpleDateFormat(dateFormat).format(calendar.getTime());
227 }
228
229 @Override
230 public Object getValue() {
231 if (Build.VERSION.SDK_INT < 11 && mType.equals("date")) {
232 // We can't use the custom DateTimePicker with a sdk older than 11.
233 // Fallback on the native DatePicker.
234 DatePicker dp = (DatePicker)mView;
235 GregorianCalendar calendar =
236 new GregorianCalendar(dp.getYear(),dp.getMonth(),dp.getDayOfMonth());
237 return formatDateString("yyyy-MM-dd",calendar);
238 } else if (mType.equals("time")) {
239 TimePicker tp = (TimePicker)mView;
240 GregorianCalendar calendar =
241 new GregorianCalendar(0,0,0,tp.getCurrentHour(),tp.getCurrentMinute());
242 return formatDateString("HH:mm",calendar);
243 } else {
244 DateTimePicker dp = (DateTimePicker)mView;
245 GregorianCalendar calendar = new GregorianCalendar();
246 calendar.setTimeInMillis(dp.getTimeInMillis());
247 if (mType.equals("date")) {
248 return formatDateString("yyyy-MM-dd",calendar);
249 } else if (mType.equals("week")) {
250 return formatDateString("yyyy-'W'ww",calendar);
251 } else if (mType.equals("datetime-local")) {
252 return formatDateString("yyyy-MM-dd HH:mm",calendar);
253 } else if (mType.equals("datetime")) {
254 calendar.set(GregorianCalendar.ZONE_OFFSET,0);
255 calendar.setTimeInMillis(dp.getTimeInMillis());
256 return formatDateString("yyyy-MM-dd HH:mm",calendar);
257 } else if (mType.equals("month")) {
258 return formatDateString("yyyy-MM",calendar);
259 }
260 }
261 return super.getValue();
262 }
263 }
264
265 public static class MenulistInput extends PromptInput {
266 public static final String INPUT_TYPE = "menulist";
267 private static String[] mListitems;
268 private static int mSelected;
269
270 public Spinner spinner;
271 public AllCapsTextView textView;
272
273 public MenulistInput(JSONObject obj) {
274 super(obj);
275 mListitems = Prompt.getStringArray(obj, "values");
276 mSelected = obj.optInt("selected");
277 }
278
279 public View getView(final Context context) throws UnsupportedOperationException {
280 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
281 spinner = new Spinner(context);
282 } else {
283 spinner = new Spinner(context, Spinner.MODE_DIALOG);
284 }
285 try {
286 if (mListitems.length > 0) {
287 ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, mListitems);
288 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
289
290 spinner.setAdapter(adapter);
291 spinner.setSelection(mSelected);
292 }
293 } catch(Exception ex) { }
294
295 if (!TextUtils.isEmpty(mLabel)) {
296 LinearLayout container = new LinearLayout(context);
297 container.setOrientation(LinearLayout.VERTICAL);
298
299 textView = new AllCapsTextView(context, null);
300 textView.setText(mLabel);
301 container.addView(textView);
302
303 container.addView(spinner);
304 return container;
305 }
306
307 return spinner;
308 }
309
310 @Override
311 public Object getValue() {
312 return new Integer(spinner.getSelectedItemPosition());
313 }
314 }
315
316 public static class LabelInput extends PromptInput {
317 public static final String INPUT_TYPE = "label";
318 public LabelInput(JSONObject obj) {
319 super(obj);
320 }
321
322 public View getView(Context context) throws UnsupportedOperationException {
323 // not really an input, but a way to add labels and such to the dialog
324 TextView view = new TextView(context);
325 view.setText(Html.fromHtml(mLabel));
326 mView = view;
327 return mView;
328 }
329 }
330
331 public PromptInput(JSONObject obj) {
332 mLabel = obj.optString("label");
333 mType = obj.optString("type");
334 String id = obj.optString("id");
335 mId = TextUtils.isEmpty(id) ? mType : id;
336 mValue = obj.optString("value");
337 }
338
339 public static PromptInput getInput(JSONObject obj) {
340 String type = obj.optString("type");
341 if (EditInput.INPUT_TYPE.equals(type)) {
342 return new EditInput(obj);
343 } else if (NumberInput.INPUT_TYPE.equals(type)) {
344 return new NumberInput(obj);
345 } else if (PasswordInput.INPUT_TYPE.equals(type)) {
346 return new PasswordInput(obj);
347 } else if (CheckboxInput.INPUT_TYPE.equals(type)) {
348 return new CheckboxInput(obj);
349 } else if (MenulistInput.INPUT_TYPE.equals(type)) {
350 return new MenulistInput(obj);
351 } else if (LabelInput.INPUT_TYPE.equals(type)) {
352 return new LabelInput(obj);
353 } else if (IconGridInput.INPUT_TYPE.equals(type)) {
354 return new IconGridInput(obj);
355 } else if (ColorPickerInput.INPUT_TYPE.equals(type)) {
356 return new ColorPickerInput(obj);
357 } else if (TabInput.INPUT_TYPE.equals(type)) {
358 return new TabInput(obj);
359 } else {
360 for (String dtType : DateTimeInput.INPUT_TYPES) {
361 if (dtType.equals(type)) {
362 return new DateTimeInput(obj);
363 }
364 }
365 }
366 return null;
367 }
368
369 public View getView(Context context) throws UnsupportedOperationException {
370 return null;
371 }
372
373 public String getId() {
374 return mId;
375 }
376
377 public Object getValue() {
378 return null;
379 }
380
381 public boolean getScrollable() {
382 return false;
383 }
384
385 public boolean canApplyInputStyle() {
386 return true;
387 }
388
389 protected void notifyListeners(String val) {
390 if (mListener != null) {
391 mListener.onChange(this);
392 }
393 }
394 }

mercurial