package dk.silverbullet.telemed.questionnaire.element; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; import android.text.InputType; import android.text.method.DigitsKeyListener; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.LinearLayout; import com.google.gson.annotations.Expose; import dk.silverbullet.telemed.questionnaire.expression.Constant; import dk.silverbullet.telemed.questionnaire.expression.Variable; import dk.silverbullet.telemed.questionnaire.expression.VariableLinkFailedException; import dk.silverbullet.telemed.questionnaire.node.IONode; import dk.silverbullet.telemed.questionnaire.node.Node; import java.util.Map; import java.util.regex.Pattern; import static dk.silverbullet.telemed.utils.Util.linkVariable; public class EditTextElement extends Element { private static Pattern floatPattern = Pattern.compile("^\\d{1,6}(\\.\\d+)?"); @Expose private Variable<?> outputVariable; private String popupTitle; private CharSequence[] popupItems; private String[] popupValues; private EditText editText; private boolean password; private boolean forMessageBody; private boolean lastElement; private Integer decimals; public EditTextElement(final IONode node) { super(node); } public void showPopup() { AlertDialog.Builder builder = new AlertDialog.Builder(getQuestionnaire().getContext()); builder.setTitle(popupTitle); builder.setItems(popupItems, new DialogInterface.OnClickListener() { @SuppressWarnings({ "unchecked", "rawtypes" }) public void onClick(DialogInterface dialog, int item) { editText.setText(popupItems[item]); outputVariable.setValue(new Constant(outputVariable.getType(), popupValues[item])); } }); AlertDialog alert = builder.create(); alert.show(); } @SuppressWarnings({ "unchecked", "rawtypes" }) public void setSelected(int item) { editText.setText(popupItems[item]); outputVariable.setValue(new Constant(outputVariable.getType(), popupValues[item])); } @Override public View getView() { if (editText == null) { editText = new EditText(getQuestionnaire().getContext().getApplicationContext()); editText.setTextColor(Color.parseColor("#777777")); editText.setBackgroundColor(Color.WHITE); editText.setBackgroundResource(android.R.drawable.edit_text); if (password) { editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); editText.setImeOptions(EditorInfo.IME_ACTION_DONE); } else if (forMessageBody) { editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE); } else { editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); if (lastElement) editText.setImeOptions(EditorInfo.IME_ACTION_DONE); else editText.setImeOptions(EditorInfo.IME_ACTION_NEXT); } editText.setTextSize(TEXTSIZE); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); editText.setLayoutParams(params); if (null != popupItems) { editText.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { showPopup(); } }); editText.setInputType(InputType.TYPE_NULL); editText.setFocusableInTouchMode(false); boolean found = false; if (null != outputVariable && null != outputVariable.getExpressionValue()) { for (int i = 0; i < popupValues.length; i++) { if (popupValues[i].equals(outputVariable.getExpressionValue().getValue())) { editText.setText(popupItems[i]); found = true; } } if (!found) { editText.setText(""); } } } else { if (Number.class.isAssignableFrom(outputVariable.getType())) { // No negative numbers are allowed, since currently no measurements in the system // can be negative boolean allowNegativeNumbers = false; // Double and Floats allow decimal points, but not Integer boolean allowDecimalPoint = !(Integer.class.isAssignableFrom(outputVariable.getType())); editText.setKeyListener(new DigitsKeyListener(allowNegativeNumbers, allowDecimalPoint)); } if (outputVariable.getExpressionValue() != null && outputVariable.getExpressionValue().getValue() != null) { editText.setText(outputVariable.getExpressionValue().toString()); } } } return editText; } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void leave() { String text = editText.getText().toString().trim(); if (null == popupItems) { if (validates()) { outputVariable.setValue(new Constant(outputVariable.getType(), text)); } else { outputVariable.setValue(new Constant(outputVariable.getType(), null)); } } // Remove keyboard after use.... InputMethodManager imm = (InputMethodManager) getQuestionnaire().getContext().getApplicationContext() .getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); } @Override public void linkNodes(Map<String, Node> map) { // Done } @Override public void linkVariables(Map<String, Variable<?>> variablePool) throws VariableLinkFailedException { outputVariable = linkVariable(variablePool, outputVariable); } @Override public boolean validates() { if (editText == null || editText.getText() == null) { return false; } return validates(editText.getText().toString(), outputVariable.getType(), decimals); } public static boolean validates(String text, Class<?> clazz, Integer decimals) { String trimmedText = text.trim(); if (trimmedText.equals("")) { return false; } if (Number.class.isAssignableFrom(clazz) && trimmedText.contains("-")) { return false; } if (Integer.class.isAssignableFrom(clazz) && trimmedText.contains(".")) { return false; } if (Integer.class.isAssignableFrom(clazz) && trimmedText.length() > 6) { return false; } if (decimals != null) { String[] textSplitBySeparator = trimmedText.split("\\."); boolean missesDecimalsBeforeComma = textSplitBySeparator[0].length() == 0; boolean hasTooManyDecimals = textSplitBySeparator.length == 2 && textSplitBySeparator[1].length() > decimals; if (missesDecimalsBeforeComma || hasTooManyDecimals) { return false; } } if (Float.class.isAssignableFrom(clazz) && !floatPattern.matcher(trimmedText).matches()) { return false; } return true; } public void setDecimals(Integer decimals) { this.decimals = decimals; } public void setOutputVariable(Variable<?> outputVariable) { this.outputVariable = outputVariable; } public void setForMessageBody(boolean forMessageBody) { this.forMessageBody = forMessageBody; } public void setLastElement(boolean lastElement) { this.lastElement = lastElement; } }