added FormWrapper and form field validation

This commit is contained in:
Daniel Gultsch 2016-01-23 20:32:00 +01:00
parent 0569a1e769
commit 8850a1fbe3
8 changed files with 160 additions and 4 deletions

View File

@ -2,6 +2,7 @@ package eu.siacs.conversations.ui.forms;
import android.content.Context; import android.content.Context;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -16,6 +17,13 @@ public class FormBooleanFieldWrapper extends FormFieldWrapper {
protected FormBooleanFieldWrapper(Context context, Field field) { protected FormBooleanFieldWrapper(Context context, Field field) {
super(context, field); super(context, field);
checkBox = (CheckBox) view.findViewById(R.id.field); checkBox = (CheckBox) view.findViewById(R.id.field);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkBox.setError(null);
invokeOnFormFieldValuesEdited();
}
});
} }
@Override @Override
@ -33,7 +41,22 @@ public class FormBooleanFieldWrapper extends FormFieldWrapper {
@Override @Override
public boolean validates() { public boolean validates() {
return checkBox.isChecked() || !field.isRequired(); if (checkBox.isChecked() || !field.isRequired()) {
return true;
} else {
checkBox.setError(context.getString(R.string.this_field_is_required));
checkBox.requestFocus();
return false;
}
}
@Override
public boolean edited() {
if (field.getValues().size() == 0) {
return checkBox.isChecked();
} else {
return super.edited();
}
} }
@Override @Override

View File

@ -20,7 +20,7 @@ public class FormFieldFactory {
typeTable.put("boolean", FormBooleanFieldWrapper.class); typeTable.put("boolean", FormBooleanFieldWrapper.class);
} }
public static FormFieldWrapper createFromField(Context context, Field field) { protected static FormFieldWrapper createFromField(Context context, Field field) {
Class clazz = typeTable.get(field.getType()); Class clazz = typeTable.get(field.getType());
if (clazz == null) { if (clazz == null) {
clazz = FormTextFieldWrapper.class; clazz = FormTextFieldWrapper.class;

View File

@ -4,11 +4,13 @@ import android.content.Context;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import java.util.List; import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R; import eu.siacs.conversations.R;
import eu.siacs.conversations.xmpp.forms.Field; import eu.siacs.conversations.xmpp.forms.Field;
@ -17,6 +19,7 @@ public abstract class FormFieldWrapper {
protected final Context context; protected final Context context;
protected final Field field; protected final Field field;
protected final View view; protected final View view;
protected OnFormFieldValuesEdited onFormFieldValuesEditedListener;
protected FormFieldWrapper(Context context, Field field) { protected FormFieldWrapper(Context context, Field field) {
this.context = context; this.context = context;
@ -57,6 +60,23 @@ public abstract class FormFieldWrapper {
return spannableString; return spannableString;
} }
protected void invokeOnFormFieldValuesEdited() {
Log.d(Config.LOGTAG, "invoke on form field values edited");
if (this.onFormFieldValuesEditedListener != null) {
this.onFormFieldValuesEditedListener.onFormFieldValuesEdited();
} else {
Log.d(Config.LOGTAG,"listener is null");
}
}
public boolean edited() {
return !field.getValues().equals(getValues());
}
public void setOnFormFieldValuesEditedListener(OnFormFieldValuesEdited listener) {
this.onFormFieldValuesEditedListener = listener;
}
protected static <F extends FormFieldWrapper> FormFieldWrapper createFromField(Class<F> c, Context context, Field field) { protected static <F extends FormFieldWrapper> FormFieldWrapper createFromField(Class<F> c, Context context, Field field) {
try { try {
return c.getDeclaredConstructor(Context.class, Field.class).newInstance(context,field); return c.getDeclaredConstructor(Context.class, Field.class).newInstance(context,field);
@ -65,4 +85,8 @@ public abstract class FormFieldWrapper {
return null; return null;
} }
} }
public interface OnFormFieldValuesEdited {
void onFormFieldValuesEdited();
}
} }

View File

@ -23,6 +23,8 @@ public class FormJidSingleFieldWrapper extends FormTextFieldWrapper {
try { try {
Jid.fromString(value); Jid.fromString(value);
} catch (InvalidJidException e) { } catch (InvalidJidException e) {
editText.setError(context.getString(R.string.invalid_jid));
editText.requestFocus();
return false; return false;
} }
} }

View File

@ -1,7 +1,9 @@
package eu.siacs.conversations.ui.forms; package eu.siacs.conversations.ui.forms;
import android.content.Context; import android.content.Context;
import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
@ -22,6 +24,21 @@ public class FormTextFieldWrapper extends FormFieldWrapper {
if ("text-private".equals(field.getType())) { if ("text-private".equals(field.getType())) {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
} }
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
editText.setError(null);
invokeOnFormFieldValuesEdited();
}
@Override
public void afterTextChanged(Editable s) {
}
});
} }
@Override @Override
@ -38,14 +55,22 @@ public class FormTextFieldWrapper extends FormFieldWrapper {
public List<String> getValues() { public List<String> getValues() {
List<String> values = new ArrayList<>(); List<String> values = new ArrayList<>();
for (String line : getValue().split("\\n")) { for (String line : getValue().split("\\n")) {
values.add(line); if (line.length() > 0) {
values.add(line);
}
} }
return values; return values;
} }
@Override @Override
public boolean validates() { public boolean validates() {
return getValue().trim().length() > 0 || !field.isRequired(); if (getValue().trim().length() > 0 || !field.isRequired()) {
return true;
} else {
editText.setError(context.getString(R.string.this_field_is_required));
editText.requestFocus();
return false;
}
} }
@Override @Override

View File

@ -0,0 +1,66 @@
package eu.siacs.conversations.ui.forms;
import android.content.Context;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.xmpp.forms.Data;
import eu.siacs.conversations.xmpp.forms.Field;
public class FormWrapper {
private final LinearLayout layout;
private final Data form;
private final List<FormFieldWrapper> fieldWrappers = new ArrayList<>();
private FormWrapper(Context context, LinearLayout linearLayout, Data form) {
this.form = form;
this.layout = linearLayout;
this.layout.removeAllViews();
for(Field field : form.getFields()) {
FormFieldWrapper fieldWrapper = FormFieldFactory.createFromField(context,field);
if (fieldWrapper != null) {
layout.addView(fieldWrapper.getView());
fieldWrappers.add(fieldWrapper);
}
}
}
public Data submit() {
for(FormFieldWrapper fieldWrapper : fieldWrappers) {
fieldWrapper.submit();
}
this.form.submit();
return this.form;
}
public boolean validates() {
boolean validates = true;
for(FormFieldWrapper fieldWrapper : fieldWrappers) {
validates &= fieldWrapper.validates();
}
return validates;
}
public void setOnFormFieldValuesEditedListener(FormFieldWrapper.OnFormFieldValuesEdited listener) {
for(FormFieldWrapper fieldWrapper : fieldWrappers) {
fieldWrapper.setOnFormFieldValuesEditedListener(listener);
}
}
public boolean edited() {
boolean edited = false;
for(FormFieldWrapper fieldWrapper : fieldWrappers) {
edited |= fieldWrapper.edited();
}
return edited;
}
public static FormWrapper createInLayout(Context context, LinearLayout layout, Data form) {
return new FormWrapper(context, layout, form);
}
}

View File

@ -1,7 +1,9 @@
package eu.siacs.conversations.xmpp.forms; package eu.siacs.conversations.xmpp.forms;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
@ -52,6 +54,19 @@ public class Field extends Element {
return findChildContent("value"); return findChildContent("value");
} }
public List<String> getValues() {
List<String> values = new ArrayList<>();
for(Element child : getChildren()) {
if ("value".equals(child.getName())) {
String content = child.getContent();
if (content != null) {
values.add(content);
}
}
}
return values;
}
public String getLabel() { public String getLabel() {
return getAttribute("label"); return getAttribute("label");
} }

View File

@ -581,4 +581,5 @@
<string name="disable">Disable</string> <string name="disable">Disable</string>
<string name="selection_too_large">The selected area is too large</string> <string name="selection_too_large">The selected area is too large</string>
<string name="no_accounts">(No activated accounts)</string> <string name="no_accounts">(No activated accounts)</string>
<string name="this_field_is_required">This field is required</string>
</resources> </resources>