protected PageRenderer editPage(SettingsProperties props, string backPage, Dictionary <string, PageRenderer> pages, Action <Flow> onBackHandler = null) { RowLayoutRenderer rows = new RowLayoutRenderer(); List <ISettingsFieldProperties> fis = props.fields; foreach (ISettingsFieldProperties p in fis) { if (!p.isList && p.isSelectable) { ISettingsFieldPropertiesSelectSingle pSelect = (ISettingsFieldPropertiesSelectSingle)p; rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(pSelect.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new ButtonTextRenderer(f => pSelect.labelProducer(((ISettingsInstance)f.flowScope["edit"]).get <object>(p.id)), f => Find.WindowStack.Add(new Dialog_Select <object>(pSelect.onSelectItem(f), pSelect.selectableItems(f), pSelect.labelProducer)), GameFont.Small, 200f))); } else if (p.type == typeof(bool)) { rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new CheckboxRenderer(f => ((ISettingsInstance)f.flowScope["edit"]).get <bool>(p.id), (f, v) => ((ISettingsInstance)f.flowScope["edit"]).set(p.id, v)))); } else if (p.type == typeof(int)) { rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new EditNumericRenderer <int>(f => ((ISettingsInstance)f.flowScope["edit"]).get <int>(p.id), (f, v) => ((ISettingsInstance)f.flowScope["edit"]).set(p.id, v), 200f, ((ISettingsFieldPropertiesPrimitiveInt)p).minValue, ((ISettingsFieldPropertiesPrimitiveInt)p).maxValue))); } else if (p.type == typeof(float)) { rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new EditNumericRenderer <float>(f => ((ISettingsInstance)f.flowScope["edit"]).get <float>(p.id), (f, v) => ((ISettingsInstance)f.flowScope["edit"]).set(p.id, v), 200f, ((ISettingsFieldPropertiesPrimitiveFloat)p).minValue, ((ISettingsFieldPropertiesPrimitiveFloat)p).maxValue))); } else if (p.type == typeof(string)) { rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new EditTextRenderer(f => ((ISettingsInstance)f.flowScope["edit"]).get <string>(p.id), (f, v) => ((ISettingsInstance)f.flowScope["edit"]).set(p.id, v), 200f, ((ISettingsFieldPropertiesPrimitiveString)p).maxNumOfChars, ((ISettingsFieldPropertiesPrimitiveString)p).inputValidator))); } else if (p.type == typeof(Color)) { rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 200f).attachTooltip(p.labelTooltip)) .AddChild(new EditColorRenderer(f => ((ISettingsInstance)f.flowScope["edit"]).get <Color>(p.id), (f, c) => ((ISettingsInstance)f.flowScope["edit"]).set <Color>(p.id, c), 200f))); } else if (p.isList && ((ISettingsFieldPropertiesList)p).isListSettings) { SettingsFieldPropertiesListSettings pList = (SettingsFieldPropertiesListSettings)p; SettingsProperties props2 = SettingsStorage.getSettingsProperties(pList.idEnclosedSettings); string deepEditPageId = backPage + "edit" + pList.id + props2.id; rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 400f, GameFont.Small, TextAnchor.MiddleCenter).attachTooltip(p.labelTooltip))); rows.AddChild(new ListRenderer(f => { List <SettingsInstance> lst = ((ISettingsInstance)f.flowScope["edit"]).get <List <SettingsInstance> >(pList.id); //avoiding nullpointer if the default value for a list is null or if a save state didnt contain the list if (lst == null) { lst = new List <SettingsInstance>(); ((ISettingsInstance)f.flowScope["edit"]).set <List <SettingsInstance> >(pList.id, lst); } return(lst); }, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 3) .AddChild(new ButtonTextRenderer(f => ((ISettingsInstance)((IterationItem)f.pageScope["curItem"]).curItem).getLabel(), f => { f.flowScope["edit"] = ((IterationItem)f.pageScope["curItem"]).curItem; f.navigate(deepEditPageId); }, GameFont.Small, pList.isRemovalAllowed ? 380f : 400f)) .AddChild(pList.isRemovalAllowed ? new ButtonTextRenderer("-", f => { ISettingsInstance setting = (ISettingsInstance)f.flowScope["edit"]; SettingsInstance lstItem = (SettingsInstance)((IterationItem)f.pageScope["curItem"]).curItem; f.addPostRenderCallback(fl => { if (setting.get <List <SettingsInstance> >(p.id).Remove(lstItem)) { setting.markAsChanged(); } }); }, GameFont.Small, 20f) : null)); rows.AddChild(pList.isAddingAllowed ? new ColumnLayoutRenderer() .AddChild(new ButtonTextRenderer("+", f => { SettingsInstance newItem = (SettingsInstance)pList.createNewEntry(); if (newItem != null) { ((ISettingsInstance)f.flowScope["edit"]).get <List <SettingsInstance> >(p.id).Add(newItem); newItem.attach(((ISettingsInstance)f.flowScope["edit"])); ((ISettingsInstance)f.flowScope["edit"]).markAsChanged(); } }, GameFont.Small, 400f)) : null); pages.Add(deepEditPageId, editPage(props2, "edit" + props.id, pages, f => { f.flowScope["edit"] = ((ISettingsInstance)f.flowScope["edit"]).getParentObject(); })); } else if (p.isList && ((ISettingsFieldPropertiesList)p).isListPrimitive) { SettingsFieldPropertiesListPrimitive pList = (SettingsFieldPropertiesListPrimitive)p; Type listItemType = pList.type.GetGenericArguments()[0]; rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 400f, GameFont.Small, TextAnchor.MiddleCenter).attachTooltip(p.labelTooltip))); ListRenderer lstRenderer = new ListRenderer(f => { IList lst = ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id); //avoiding nullpointer if the default value for a list is null or if a save state didnt contain the list if (lst == null) { lst = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(listItemType), null); ((ISettingsInstance)f.flowScope["edit"]).set <IList>(pList.id, lst); } return(lst); }, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 3); float editRendererWidth; if (pList.listLabelProducer != null) { lstRenderer.AddChild(new LabelRenderer(f => pList.listLabelProducer((ISettingsInstance)f.flowScope["edit"], f), 200f)); editRendererWidth = 200f; } else { editRendererWidth = 400f; } //Currently no min max etc for the list item type if (listItemType == typeof(float)) { lstRenderer.AddChild(new EditNumericRenderer <float>(f => (float)((IterationItem)f.pageScope["curItem"]).curItem, (f, v) => { ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id)[((IterationItem)f.pageScope["curItem"]).index] = v; ((ISettingsInstance)f.flowScope["edit"]).markAsChanged(); }, editRendererWidth /*,((ISettingsFieldPropertiesPrimitiveFloat)p).minValue,((ISettingsFieldPropertiesPrimitiveFloat)p).maxValue*/)); } else if (listItemType == typeof(int)) { lstRenderer.AddChild(new EditNumericRenderer <int>(f => (int)((IterationItem)f.pageScope["curItem"]).curItem, (f, v) => { ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id)[((IterationItem)f.pageScope["curItem"]).index] = v; ((ISettingsInstance)f.flowScope["edit"]).markAsChanged(); }, editRendererWidth /*,((ISettingsFieldPropertiesPrimitiveInt)p).minValue,((ISettingsFieldPropertiesPrimitiveInt)p).maxValue*/)); } else if (listItemType == typeof(bool)) { lstRenderer.AddChild(new CheckboxRenderer(f => (bool)((IterationItem)f.pageScope["curItem"]).curItem, (f, v) => { ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id)[((IterationItem)f.pageScope["curItem"]).index] = v; ((ISettingsInstance)f.flowScope["edit"]).markAsChanged(); })); } else if (listItemType == typeof(string)) { lstRenderer.AddChild(new EditTextRenderer(f => (string)((IterationItem)f.pageScope["curItem"]).curItem, (f, v) => { ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id)[((IterationItem)f.pageScope["curItem"]).index] = v; ((ISettingsInstance)f.flowScope["edit"]).markAsChanged(); }, editRendererWidth /*,((ISettingsFieldPropertiesPrimitiveString)p).maxNumOfChars,((ISettingsFieldPropertiesPrimitiveString)p).inputValidator*/)); } rows.AddChild(lstRenderer); } else if (p.isList && ((ISettingsFieldPropertiesList)p).isSelectable) { SettingsFieldPropertiesListSelectable pList = (SettingsFieldPropertiesListSelectable)p; Type listItemType = pList.type.GetGenericArguments()[0]; rows.AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer(p.label, 400f, GameFont.Small, TextAnchor.MiddleCenter).attachTooltip(p.labelTooltip))); ListRenderer lstRenderer = new ListRenderer(f => { IList lst = ((ISettingsInstance)f.flowScope["edit"]).get <IList>(pList.id); //avoiding nullpointer if the default value for a list is null or if a save state didnt contain the list if (lst == null) { lst = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(listItemType), null); ((ISettingsInstance)f.flowScope["edit"]).set <IList>(pList.id, lst); } return(lst); }, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 3); lstRenderer.AddChild(new ButtonTextRenderer(f => pList.labelProducer(((IterationItem)f.pageScope["curItem"]).curItem), f => Find.WindowStack.Add(new Dialog_Select <object>(pList.onSelectItem(f), pList.selectableItems(f), pList.labelProducer, null, pList.tooltipProducer)), GameFont.Small, pList.isRemovalAllowed ? 380f : 400f)); if (pList.tooltipProducer != null) { lstRenderer.childs[0].attachTooltip(f => pList.tooltipProducer(((IterationItem)f.pageScope["curItem"]).curItem)); } lstRenderer.AddChild(pList.isRemovalAllowed ? new ButtonTextRenderer("-", f => { ISettingsInstance setting = (ISettingsInstance)f.flowScope["edit"]; object lstItem = ((IterationItem)f.pageScope["curItem"]).curItem; f.addPostRenderCallback(fl => { IList lst = setting.get <IList>(p.id); if (lst.Contains(lstItem)) { lst.Remove(lstItem); setting.markAsChanged(); } }); }, GameFont.Small, 20f):null); rows.AddChild(lstRenderer); rows.AddChild(pList.isAddingAllowed ? new ColumnLayoutRenderer() .AddChild(new ButtonTextRenderer("+", f => { object newItem = pList.createNewEntry(); if (newItem != null) { ISettingsInstance currentSettings = ((ISettingsInstance)f.flowScope["edit"]); IList lst = currentSettings.get <IList>(p.id); f.addPostRenderCallback(fl => { lst.Add(newItem); if (pList.isSettings) { ((ISettingsInstance)newItem).attach(currentSettings); } currentSettings.markAsChanged(); }); } }, GameFont.Small, 400f)) : null); } } return(new PageRenderer(((ISettingsVisualizationEdit)props.visualization).getEditPageTitle, null, () => backPage, onBackHandler).AddChild(new VerticalScrollViewRenderer().AddChild(rows))); }