mobile/android/base/prompts/PromptInput.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/prompts/PromptInput.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,394 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko.prompts;
    1.10 +
    1.11 +import java.text.SimpleDateFormat;
    1.12 +import java.util.Calendar;
    1.13 +import java.util.GregorianCalendar;
    1.14 +
    1.15 +import org.json.JSONObject;
    1.16 +import org.mozilla.gecko.widget.AllCapsTextView;
    1.17 +import org.mozilla.gecko.widget.DateTimePicker;
    1.18 +
    1.19 +import android.content.Context;
    1.20 +import android.content.res.Configuration;
    1.21 +import android.os.Build;
    1.22 +import android.text.Html;
    1.23 +import android.text.InputType;
    1.24 +import android.text.TextUtils;
    1.25 +import android.text.format.DateFormat;
    1.26 +import android.util.Log;
    1.27 +import android.view.View;
    1.28 +import android.view.ViewGroup.LayoutParams;
    1.29 +import android.view.inputmethod.InputMethodManager;
    1.30 +import android.widget.ArrayAdapter;
    1.31 +import android.widget.CheckBox;
    1.32 +import android.widget.DatePicker;
    1.33 +import android.widget.EditText;
    1.34 +import android.widget.LinearLayout;
    1.35 +import android.widget.Spinner;
    1.36 +import android.widget.TextView;
    1.37 +import android.widget.TimePicker;
    1.38 +
    1.39 +public class PromptInput {
    1.40 +    protected final String mLabel;
    1.41 +    protected final String mType;
    1.42 +    protected final String mId;
    1.43 +    protected final String mValue;
    1.44 +    protected OnChangeListener mListener;
    1.45 +    protected View mView;
    1.46 +    public static final String LOGTAG = "GeckoPromptInput";
    1.47 +
    1.48 +    public interface OnChangeListener {
    1.49 +        public void onChange(PromptInput input);
    1.50 +    }
    1.51 +
    1.52 +    public void setListener(OnChangeListener listener) {
    1.53 +        mListener = listener;
    1.54 +    }
    1.55 +
    1.56 +    public static class EditInput extends PromptInput {
    1.57 +        protected final String mHint;
    1.58 +        protected final boolean mAutofocus;
    1.59 +        public static final String INPUT_TYPE = "textbox";
    1.60 +
    1.61 +        public EditInput(JSONObject object) {
    1.62 +            super(object);
    1.63 +            mHint = object.optString("hint");
    1.64 +            mAutofocus = object.optBoolean("autofocus");
    1.65 +        }
    1.66 +
    1.67 +        public View getView(final Context context) throws UnsupportedOperationException {
    1.68 +            EditText input = new EditText(context);
    1.69 +            input.setInputType(InputType.TYPE_CLASS_TEXT);
    1.70 +            input.setText(mValue);
    1.71 +
    1.72 +            if (!TextUtils.isEmpty(mHint)) {
    1.73 +                input.setHint(mHint);
    1.74 +            }
    1.75 +
    1.76 +            if (mAutofocus) {
    1.77 +                input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    1.78 +                    @Override
    1.79 +                    public void onFocusChange(View v, boolean hasFocus) {
    1.80 +                        if (hasFocus) {
    1.81 +                            ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(v, 0);
    1.82 +                        }
    1.83 +                    }
    1.84 +                });
    1.85 +                input.requestFocus();
    1.86 +            }
    1.87 +
    1.88 +            mView = (View)input;
    1.89 +            return mView;
    1.90 +        }
    1.91 +
    1.92 +        @Override
    1.93 +        public Object getValue() {
    1.94 +            EditText edit = (EditText)mView;
    1.95 +            return edit.getText();
    1.96 +        }
    1.97 +    }
    1.98 +
    1.99 +    public static class NumberInput extends EditInput {
   1.100 +        public static final String INPUT_TYPE = "number";
   1.101 +        public NumberInput(JSONObject obj) {
   1.102 +            super(obj);
   1.103 +        }
   1.104 +
   1.105 +        public View getView(final Context context) throws UnsupportedOperationException {
   1.106 +            EditText input = (EditText) super.getView(context);
   1.107 +            input.setRawInputType(Configuration.KEYBOARD_12KEY);
   1.108 +            input.setInputType(InputType.TYPE_CLASS_NUMBER |
   1.109 +                               InputType.TYPE_NUMBER_FLAG_SIGNED);
   1.110 +            return input;
   1.111 +        }
   1.112 +    }
   1.113 +
   1.114 +    public static class PasswordInput extends EditInput {
   1.115 +        public static final String INPUT_TYPE = "password";
   1.116 +        public PasswordInput(JSONObject obj) {
   1.117 +            super(obj);
   1.118 +        }
   1.119 +
   1.120 +        public View getView(Context context) throws UnsupportedOperationException {
   1.121 +            EditText input = (EditText) super.getView(context);
   1.122 +            input.setInputType(InputType.TYPE_CLASS_TEXT |
   1.123 +                               InputType.TYPE_TEXT_VARIATION_PASSWORD |
   1.124 +                               InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
   1.125 +            return input;
   1.126 +        }
   1.127 +
   1.128 +        @Override
   1.129 +        public Object getValue() {
   1.130 +            EditText edit = (EditText)mView;
   1.131 +            return edit.getText();
   1.132 +        }
   1.133 +    }
   1.134 +
   1.135 +    public static class CheckboxInput extends PromptInput {
   1.136 +        public static final String INPUT_TYPE = "checkbox";
   1.137 +        private boolean mChecked;
   1.138 +
   1.139 +        public CheckboxInput(JSONObject obj) {
   1.140 +            super(obj);
   1.141 +            mChecked = obj.optBoolean("checked");
   1.142 +        }
   1.143 +
   1.144 +        public View getView(Context context) throws UnsupportedOperationException {
   1.145 +            CheckBox checkbox = new CheckBox(context);
   1.146 +            checkbox.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
   1.147 +            checkbox.setText(mLabel);
   1.148 +            checkbox.setChecked(mChecked);
   1.149 +            mView = (View)checkbox;
   1.150 +            return mView;
   1.151 +        }
   1.152 +
   1.153 +        @Override
   1.154 +        public Object getValue() {
   1.155 +            CheckBox checkbox = (CheckBox)mView;
   1.156 +            return checkbox.isChecked() ? Boolean.TRUE : Boolean.FALSE;
   1.157 +        }
   1.158 +    }
   1.159 +
   1.160 +    public static class DateTimeInput extends PromptInput {
   1.161 +        public static final String[] INPUT_TYPES = new String[] {
   1.162 +            "date",
   1.163 +            "week",
   1.164 +            "time",
   1.165 +            "datetime-local",
   1.166 +            "datetime",
   1.167 +            "month"
   1.168 +        };
   1.169 +
   1.170 +        public DateTimeInput(JSONObject obj) {
   1.171 +            super(obj);
   1.172 +        }
   1.173 +
   1.174 +        public View getView(Context context) throws UnsupportedOperationException {
   1.175 +            if (mType.equals("date")) {
   1.176 +                try {
   1.177 +                    DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd", mValue,
   1.178 +                                                              DateTimePicker.PickersState.DATE);
   1.179 +                    input.toggleCalendar(true);
   1.180 +                    mView = (View)input;
   1.181 +                } catch (UnsupportedOperationException ex) {
   1.182 +                    // We can't use our custom version of the DatePicker widget because the sdk is too old.
   1.183 +                    // But we can fallback on the native one.
   1.184 +                    DatePicker input = new DatePicker(context);
   1.185 +                    try {
   1.186 +                        if (!TextUtils.isEmpty(mValue)) {
   1.187 +                            GregorianCalendar calendar = new GregorianCalendar();
   1.188 +                            calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(mValue));
   1.189 +                            input.updateDate(calendar.get(Calendar.YEAR),
   1.190 +                                             calendar.get(Calendar.MONTH),
   1.191 +                                             calendar.get(Calendar.DAY_OF_MONTH));
   1.192 +                        }
   1.193 +                    } catch (Exception e) {
   1.194 +                        Log.e(LOGTAG, "error parsing format string: " + e);
   1.195 +                    }
   1.196 +                    mView = (View)input;
   1.197 +                }
   1.198 +            } else if (mType.equals("week")) {
   1.199 +                DateTimePicker input = new DateTimePicker(context, "yyyy-'W'ww", mValue,
   1.200 +                                                          DateTimePicker.PickersState.WEEK);
   1.201 +                mView = (View)input;
   1.202 +            } else if (mType.equals("time")) {
   1.203 +                TimePicker input = new TimePicker(context);
   1.204 +                input.setIs24HourView(DateFormat.is24HourFormat(context));
   1.205 +
   1.206 +                GregorianCalendar calendar = new GregorianCalendar();
   1.207 +                if (!TextUtils.isEmpty(mValue)) {
   1.208 +                    try {
   1.209 +                        calendar.setTime(new SimpleDateFormat("HH:mm").parse(mValue));
   1.210 +                    } catch (Exception e) { }
   1.211 +                }
   1.212 +                input.setCurrentHour(calendar.get(GregorianCalendar.HOUR_OF_DAY));
   1.213 +                input.setCurrentMinute(calendar.get(GregorianCalendar.MINUTE));
   1.214 +                mView = (View)input;
   1.215 +            } else if (mType.equals("datetime-local") || mType.equals("datetime")) {
   1.216 +                DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd HH:mm", mValue,
   1.217 +                                                          DateTimePicker.PickersState.DATETIME);
   1.218 +                input.toggleCalendar(true);
   1.219 +                mView = (View)input;
   1.220 +            } else if (mType.equals("month")) {
   1.221 +                DateTimePicker input = new DateTimePicker(context, "yyyy-MM", mValue,
   1.222 +                                                          DateTimePicker.PickersState.MONTH);
   1.223 +                mView = (View)input;
   1.224 +            }
   1.225 +            return mView;
   1.226 +        }
   1.227 +
   1.228 +        private static String formatDateString(String dateFormat, Calendar calendar) {
   1.229 +            return new SimpleDateFormat(dateFormat).format(calendar.getTime());
   1.230 +        }
   1.231 +
   1.232 +        @Override
   1.233 +        public Object getValue() {
   1.234 +            if (Build.VERSION.SDK_INT < 11 && mType.equals("date")) {
   1.235 +                // We can't use the custom DateTimePicker with a sdk older than 11.
   1.236 +                // Fallback on the native DatePicker.
   1.237 +                DatePicker dp = (DatePicker)mView;
   1.238 +                GregorianCalendar calendar =
   1.239 +                    new GregorianCalendar(dp.getYear(),dp.getMonth(),dp.getDayOfMonth());
   1.240 +                return formatDateString("yyyy-MM-dd",calendar);
   1.241 +            } else if (mType.equals("time")) {
   1.242 +                TimePicker tp = (TimePicker)mView;
   1.243 +                GregorianCalendar calendar =
   1.244 +                    new GregorianCalendar(0,0,0,tp.getCurrentHour(),tp.getCurrentMinute());
   1.245 +                return formatDateString("HH:mm",calendar);
   1.246 +            } else {
   1.247 +                DateTimePicker dp = (DateTimePicker)mView;
   1.248 +                GregorianCalendar calendar = new GregorianCalendar();
   1.249 +                calendar.setTimeInMillis(dp.getTimeInMillis());
   1.250 +                if (mType.equals("date")) {
   1.251 +                    return formatDateString("yyyy-MM-dd",calendar);
   1.252 +                } else if (mType.equals("week")) {
   1.253 +                    return formatDateString("yyyy-'W'ww",calendar);
   1.254 +                } else if (mType.equals("datetime-local")) {
   1.255 +                    return formatDateString("yyyy-MM-dd HH:mm",calendar);
   1.256 +                } else if (mType.equals("datetime")) {
   1.257 +                    calendar.set(GregorianCalendar.ZONE_OFFSET,0);
   1.258 +                    calendar.setTimeInMillis(dp.getTimeInMillis());
   1.259 +                    return formatDateString("yyyy-MM-dd HH:mm",calendar);
   1.260 +                } else if (mType.equals("month")) {
   1.261 +                    return formatDateString("yyyy-MM",calendar);
   1.262 +                }
   1.263 +            }
   1.264 +            return super.getValue();
   1.265 +        }
   1.266 +    }
   1.267 +
   1.268 +    public static class MenulistInput extends PromptInput {
   1.269 +        public static final String INPUT_TYPE = "menulist";
   1.270 +        private static String[] mListitems;
   1.271 +        private static int mSelected;
   1.272 +
   1.273 +        public Spinner spinner;
   1.274 +        public AllCapsTextView textView;
   1.275 +
   1.276 +        public MenulistInput(JSONObject obj) {
   1.277 +            super(obj);
   1.278 +            mListitems = Prompt.getStringArray(obj, "values");
   1.279 +            mSelected = obj.optInt("selected");
   1.280 +        }
   1.281 +
   1.282 +        public View getView(final Context context) throws UnsupportedOperationException {
   1.283 +            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
   1.284 +                spinner = new Spinner(context);
   1.285 +            } else {
   1.286 +                spinner = new Spinner(context, Spinner.MODE_DIALOG);
   1.287 +            }
   1.288 +            try {
   1.289 +                if (mListitems.length > 0) {
   1.290 +                    ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, mListitems);
   1.291 +                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
   1.292 +
   1.293 +                    spinner.setAdapter(adapter);
   1.294 +                    spinner.setSelection(mSelected);
   1.295 +                }
   1.296 +            } catch(Exception ex) { }
   1.297 +
   1.298 +            if (!TextUtils.isEmpty(mLabel)) {
   1.299 +                LinearLayout container = new LinearLayout(context);
   1.300 +                container.setOrientation(LinearLayout.VERTICAL);
   1.301 +
   1.302 +                textView = new AllCapsTextView(context, null);
   1.303 +                textView.setText(mLabel);
   1.304 +                container.addView(textView);
   1.305 +
   1.306 +                container.addView(spinner);
   1.307 +                return container;
   1.308 +            }
   1.309 +
   1.310 +            return spinner;
   1.311 +        }
   1.312 +
   1.313 +        @Override
   1.314 +        public Object getValue() {
   1.315 +            return new Integer(spinner.getSelectedItemPosition());
   1.316 +        }
   1.317 +    }
   1.318 +
   1.319 +    public static class LabelInput extends PromptInput {
   1.320 +        public static final String INPUT_TYPE = "label";
   1.321 +        public LabelInput(JSONObject obj) {
   1.322 +            super(obj);
   1.323 +        }
   1.324 +
   1.325 +        public View getView(Context context) throws UnsupportedOperationException {
   1.326 +            // not really an input, but a way to add labels and such to the dialog
   1.327 +            TextView view = new TextView(context);
   1.328 +            view.setText(Html.fromHtml(mLabel));
   1.329 +            mView = view;
   1.330 +            return mView;
   1.331 +        }
   1.332 +    }
   1.333 +
   1.334 +    public PromptInput(JSONObject obj) {
   1.335 +        mLabel = obj.optString("label");
   1.336 +        mType = obj.optString("type");
   1.337 +        String id = obj.optString("id");
   1.338 +        mId = TextUtils.isEmpty(id) ? mType : id;
   1.339 +        mValue = obj.optString("value");
   1.340 +    }
   1.341 +
   1.342 +    public static PromptInput getInput(JSONObject obj) {
   1.343 +        String type = obj.optString("type");
   1.344 +        if (EditInput.INPUT_TYPE.equals(type)) {
   1.345 +            return new EditInput(obj);
   1.346 +        } else if (NumberInput.INPUT_TYPE.equals(type)) {
   1.347 +            return new NumberInput(obj);
   1.348 +        } else if (PasswordInput.INPUT_TYPE.equals(type)) {
   1.349 +            return new PasswordInput(obj);
   1.350 +        } else if (CheckboxInput.INPUT_TYPE.equals(type)) {
   1.351 +            return new CheckboxInput(obj);
   1.352 +        } else if (MenulistInput.INPUT_TYPE.equals(type)) {
   1.353 +            return new MenulistInput(obj);
   1.354 +        } else if (LabelInput.INPUT_TYPE.equals(type)) {
   1.355 +            return new LabelInput(obj);
   1.356 +        } else if (IconGridInput.INPUT_TYPE.equals(type)) {
   1.357 +            return new IconGridInput(obj);
   1.358 +        } else if (ColorPickerInput.INPUT_TYPE.equals(type)) {
   1.359 +            return new ColorPickerInput(obj);
   1.360 +        } else if (TabInput.INPUT_TYPE.equals(type)) {
   1.361 +            return new TabInput(obj);
   1.362 +        } else {
   1.363 +            for (String dtType : DateTimeInput.INPUT_TYPES) {
   1.364 +                if (dtType.equals(type)) {
   1.365 +                    return new DateTimeInput(obj);
   1.366 +                }
   1.367 +            }
   1.368 +        }
   1.369 +        return null;
   1.370 +    }
   1.371 +
   1.372 +    public View getView(Context context) throws UnsupportedOperationException {
   1.373 +        return null;
   1.374 +    }
   1.375 +
   1.376 +    public String getId() {
   1.377 +        return mId;
   1.378 +    }
   1.379 +
   1.380 +    public Object getValue() {
   1.381 +        return null;
   1.382 +    }
   1.383 +
   1.384 +    public boolean getScrollable() {
   1.385 +        return false;
   1.386 +    }
   1.387 +
   1.388 +    public boolean canApplyInputStyle() {
   1.389 +        return true;
   1.390 +    }
   1.391 +
   1.392 +    protected void notifyListeners(String val) {
   1.393 +        if (mListener != null) {
   1.394 +            mListener.onChange(this);
   1.395 +        }
   1.396 +    }
   1.397 +}

mercurial