mobile/android/base/prompts/PromptInput.java

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial