package org.commcare.views;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import org.commcare.activities.CommCareActivity;
import org.javarosa.core.services.locale.Localization;
import java.lang.reflect.Field;
/**
* Functions for managing the setup and persistence of activity fields with
* '@UiElement' annotations.
*
* @author Phillip Mates (pmates@dimagi.com).
*/
public class ManagedUiFramework {
public static boolean isManagedUi(Class c) {
return c.isAnnotationPresent(ManagedUi.class);
}
public static void setContentView(CommCareActivity activity) {
activity.setContentView(
activity.getUIManager().getClass().getAnnotation(ManagedUi.class).value());
}
/**
* Set text for activity's UiElement annotated fields
*/
public static void loadUiElements(CommCareActivity activity) {
Class classHoldingFields = activity.getUIManager().getClass();
for (Field f : classHoldingFields.getDeclaredFields()) {
if (f.isAnnotationPresent(UiElement.class)) {
UiElement element = f.getAnnotation(UiElement.class);
try {
f.setAccessible(true);
try {
View v = activity.findViewById(element.value());
f.set(activity.getUIManager(), v);
String localeString = element.locale();
if (!"".equals(localeString)) {
if (v instanceof EditText) {
((EditText)v).setHint(Localization.get(localeString));
} else if (v instanceof TextView) {
((TextView)v).setText(Localization.get(localeString));
} else {
throw new RuntimeException("Can't set the text for a " + v.getClass().getName() + " View!");
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new RuntimeException("Bad Object type for field " + f.getName());
} catch (IllegalAccessException e) {
throw new RuntimeException("Couldn't access the activity field for some reason");
}
} finally {
f.setAccessible(false);
}
}
}
}
/**
* Restore activity UiElement annotated fields with text, visibility, and
* enabled settings stored in bundle
*/
public static void restoreUiElements(CommCareActivity activity,
Bundle savedInstanceState) {
Class classHoldingFields = activity.getUIManager().getClass();
for (Field f : classHoldingFields.getDeclaredFields()) {
if (f.isAnnotationPresent(UiElement.class)) {
UiElement element = f.getAnnotation(UiElement.class);
try {
f.setAccessible(true);
try {
View v = activity.findViewById(element.value());
f.set(activity.getUIManager(), v);
restoredFromSaved(v, f, element, savedInstanceState);
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new RuntimeException("Bad Object type for field " + f.getName());
} catch (IllegalAccessException e) {
throw new RuntimeException("Couldn't access the activity field for some reason");
}
} finally {
f.setAccessible(false);
}
}
}
}
@SuppressWarnings("ResourceType")
private static void restoredFromSaved(View v, Field f, UiElement element, Bundle bundle) {
if (bundle != null) {
if (v != null) {
final String elementKey = getElementKey(element);
if (isFieldInBundle(elementKey, bundle)) {
v.setVisibility(bundle.getInt(elementKey + "_visibility"));
v.setEnabled(bundle.getBoolean(elementKey + "_enabled"));
if (v instanceof TextView) {
((TextView)v).setText(bundle.getString(elementKey + "_text"));
}
}
} else {
Log.d("loadFields", "NullPointerException when trying to find view with id: " +
element.value() + ", element is: " + f + " (" + f.getName() + ")");
}
}
}
private static String getElementKey(UiElement element) {
return String.valueOf(element.value());
}
private static boolean isFieldInBundle(String elementKey, Bundle bundle) {
return bundle.containsKey(elementKey + "_visibility");
}
/**
* Store the state of the activity's UiElement annotated fields.
*/
public static Bundle saveUiStateToBundle(CommCareActivity activity) {
Bundle bundle = new Bundle();
Object objectHoldingFields = activity.getUIManager();
for (Field f : objectHoldingFields.getClass().getDeclaredFields()) {
if (f.isAnnotationPresent(UiElement.class)) {
UiElement element = f.getAnnotation(UiElement.class);
try {
f.setAccessible(true);
try {
View v = (View)f.get(objectHoldingFields);
String elementKey = getElementKey(element);
int vis = v.getVisibility();
bundle.putInt(elementKey + "_visibility", vis);
boolean enabled = v.isEnabled();
bundle.putBoolean(elementKey + "_enabled", enabled);
if (v instanceof TextView) {
bundle.putString(elementKey + "_text", ((TextView)v).getText().toString());
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new RuntimeException("Bad Object type for field " + f.getName());
} catch (IllegalAccessException e) {
throw new RuntimeException("Couldn't access the activity field for some reason");
}
} finally {
f.setAccessible(false);
}
}
}
return bundle;
}
}