void Populate (object callbacks, object o, RootElement root)
{
MemberInfo last_radio_index = null;
var members = o.GetType ().GetMembers (BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
Section section = null;
foreach (var mi in members){
Type mType = GetTypeForMember (mi);
if (mType == null)
continue;
string caption = null;
object [] attrs = mi.GetCustomAttributes (false);
bool skip = false;
foreach (var attr in attrs){
if (attr is SkipAttribute)
skip = true;
if (attr is CaptionAttribute)
caption = ((CaptionAttribute) attr).Caption;
else if (attr is SectionAttribute){
if (section != null)
root.Add (section);
var sa = attr as SectionAttribute;
section = new Section (sa.Caption, sa.Footer);
}
}
if (skip)
continue;
if (caption == null)
caption = MakeCaption (mi.Name);
if (section == null)
section = new Section ();
Element element = null;
if (mType == typeof (string)){
PasswordAttribute pa = null;
AlignmentAttribute align = null;
EntryAttribute ea = null;
object html = null;
Action invoke = null;
bool multi = false;
foreach (object attr in attrs){
if (attr is PasswordAttribute)
pa = attr as PasswordAttribute;
else if (attr is EntryAttribute)
ea = attr as EntryAttribute;
else if (attr is MultilineAttribute)
multi = true;
else if (attr is HtmlAttribute)
html = attr;
else if (attr is AlignmentAttribute)
align = attr as AlignmentAttribute;
if (attr is OnTapAttribute){
string mname = ((OnTapAttribute) attr).Method;
if (callbacks == null){
throw new Exception ("Your class contains [OnTap] attributes, but you passed a null object for `context' in the constructor");
}
var method = callbacks.GetType ().GetMethod (mname);
if (method == null)
throw new Exception ("Did not find method " + mname);
invoke = delegate {
method.Invoke (method.IsStatic ? null : callbacks, new object [0]);
};
}
}
string value = (string) GetValue (mi, o);
if (pa != null)
element = new EntryElement (caption, pa.Placeholder, value, true);
else if (ea != null)
element = new EntryElement (caption, ea.Placeholder, value) { KeyboardType = ea.KeyboardType };
else if (multi)
element = new MultilineElement (caption, value);
else if (html != null)
element = new WebElement (caption, value);
else {
var selement = new StringElement (caption, value);
element = selement;
if (align != null)
selement.Alignment = align.Alignment;
}
if (invoke != null)
((StringElement) element).Tapped += invoke;
} else if (mType == typeof (float)){
var floatElement = new FloatElement (caption, (float) GetValue (mi, o));
element = floatElement;
foreach (object attr in attrs){
if (attr is RangeAttribute){
var ra = attr as RangeAttribute;
floatElement.MinValue = ra.Low;
floatElement.MaxValue = ra.High;
}
}
} else if (mType == typeof (bool)){
bool checkbox = false;
foreach (object attr in attrs){
if (attr is CheckboxAttribute)
checkbox = true;
}
if (checkbox)
element = new CheckboxElement (caption, (bool) GetValue (mi, o));
else
element = new iPhoneBooleanElement (caption, (bool) GetValue (mi, o));
} else if (mType == typeof (DateTime)){
var dateTime = (DateTime) GetValue (mi, o);
bool asDate = false, asTime = false;
foreach (object attr in attrs){
if (attr is DateAttribute)
asDate = true;
else if (attr is TimeAttribute)
asTime = true;
}
if (asDate)
element = new DateElement (caption, dateTime);
else if (asTime)
element = new TimeElement (caption, dateTime);
else
element = new DateTimeElement (caption, dateTime);
} else if (mType.IsEnum){
var csection = new Section ();
ulong evalue = Convert.ToUInt64 (GetValue (mi, o), null);
int idx = 0;
int selected = 0;
foreach (var fi in mType.GetFields (BindingFlags.Public | BindingFlags.Static)){
ulong v = Convert.ToUInt64 (GetValue (fi, null));
if (v == evalue)
selected = idx;
csection.Add (new RadioElement (MakeCaption (fi.Name)));
idx++;
}
element = new RootElement (caption, new RadioGroup (null, selected)) { csection };
} else if (mType == typeof (UIImage)){
element = new ImagePickerElement ((UIImage) GetValue (mi, o));
} else if (typeof (System.Collections.IEnumerable).IsAssignableFrom (mType)){
var csection = new Section ();
int count = 0;
if (last_radio_index == null)
throw new Exception ("IEnumerable found, but no previous int found");
foreach (var e in (IEnumerable) GetValue (mi, o)){
csection.Add (new RadioElement (e.ToString ()));
count++;
}
int selected = (int) GetValue (last_radio_index, o);
if (selected >= count || selected < 0)
selected = 0;
element = new RootElement (caption, new MemberRadioGroup (null, selected, last_radio_index)) { csection };
last_radio_index = null;
} else if (typeof (int) == mType){
foreach (object attr in attrs){
if (attr is RadioSelectionAttribute){
last_radio_index = mi;
break;
}
}
} else {
var nested = GetValue (mi, o);
if (nested != null){
var newRoot = new RootElement (caption);
Populate (callbacks, nested, newRoot);
element = newRoot;
}
}
if (element == null)
continue;
section.Add (element);
mappings [element] = new MemberAndInstance (mi, o);
}
root.Add (section);
}