public void TryOpenComms(Pawn negotiator) { if (!this.CanTradeNow) { return; } ModelPlaceOrder modelPlaceOrder = new ModelPlaceOrder(this); //maybe a grid or a dialog featuring my own flow components. Dictionary <string, PageRenderer> pages = new Dictionary <string, PageRenderer>(); pages.Add("menu", new PageRenderer((f => GetCallLabel()), null, null) .AddChild(new RowLayoutRenderer() .AddChild(new ColumnLayoutRenderer() .AddChild(new ButtonTextRenderer("Trade", (f => Find.WindowStack.Add(new Dialog_Trade(negotiator, this))))) //Placing an order requires selecting stuff for the item to make(could be a stuff category or fixed ingredients) more complicated things have filters //Maybe using the workbench interface to define the possible materials? But then we need to pick from storage etc.. simulating the whole chain. //Only allow recipes with category item. .AddChild(new ButtonTextRenderer("Place order", (f => { modelPlaceOrder.resources = ColonyThingsWillingToBuy(negotiator); f.navigate("placeOrder"); }))) //.AddChild(new ButtonTextRenderer("Claim order", (f => f.navigate("statistics")))) .AddChild(new ButtonTextRenderer("Statistics", (f => f.navigate("statistics")))) .AddChild(new ButtonTextRenderer("Rename colony", (f => f.navigate("renameColony")))) .AddChild(new ButtonTextRenderer("Remove colony", (f => Find.WindowStack.Add(new Dialog_MessageBox("This is irreversible! Are you sure?", "Remove", delegate { Find.WorldObjects.Remove(this); //TODO When removing a colony we have the option to remove the housed pawns for good(including their relations) or we keep them around. }, "Cancel", null, "Remove Remnant Colony", true))))) ))); pages.Add("statistics", new PageRenderer((f => "Statistics"), null, () => "menu") .AddChild(new RowLayoutRenderer() .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Inhabitants"))) .AddChild(new ColumnLayoutRenderer() .AddChild(new ListRenderer(pawnNames, 200f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 5) .AddChild(new LabelRenderer((f => ((string)((IterationItem)f.pageScope["curItem"]).curItem)), 200f)))) .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Max skill levels"))) .AddChild(new ColumnLayoutRenderer() .AddChild(new ListRenderer(maxSkillLevels, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 5) .AddChild(new LabelRenderer((f => ((SkillLevel)((IterationItem)f.pageScope["curItem"]).curItem).def.label), 200f)) .AddChild(new LabelRenderer((f => ((SkillLevel)((IterationItem)f.pageScope["curItem"]).curItem).level.ToString()), 200f)))))); pages.Add("renameColony", new PageRenderer((f => "Rename colony"), null, () => "menu") .AddChild(new RowLayoutRenderer() .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Name", 200f)) .AddChild(new EditTextRenderer((f => settlementName), (f, v) => settlementName = v, 200f))) )); pages.Add("placeOrder", new PageRenderer((f => "Place order"), null, () => "menu") .AddChild(new RowLayoutRenderer() .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Recipe", 200f)) .AddChild(new ButtonTextRenderer(f => modelPlaceOrder.recipe == null ? "Choose" : modelPlaceOrder.recipe.label, f => Find.WindowStack.Add( new Dialog_Select <RecipeDef>(def => { modelPlaceOrder.recipe = def; return(true); }, DefDatabase <RecipeDef> .AllDefsListForReading //only recipes that produce something and only recipes that can be crafted with the tradeable resources(e.g. chunks arent launchable and cannot be used) .Where(d => !d.products.NullOrEmpty() /*&&modelPlaceOrder.HasIngredients(d)*/) .OrderBy(d => d.label), d => d.label) ), GameFont.Small, 200f))) .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Ingredient", 200f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)) .AddChild(new LabelRenderer("Amount", 100f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)) .AddChild(new LabelRenderer("In Stock", 100f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter))) .AddChild(new ColumnLayoutRenderer() .AddChild(new ListRenderer(modelPlaceOrder.ingredients, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 5) .AddChild(new ButtonTextRenderer(f => ((Pair <ThingDef, IngredientCount>)((IterationItem)f.pageScope["curItem"]).curItem).Key.label, (f => { f.pageScope["selectItem"] = ((IterationItem)f.pageScope["curItem"]).curItem; Find.WindowStack.Add(new Dialog_SelectDef <ThingDef>(def => { ((Pair <ThingDef, IngredientCount>)f.pageScope["selectItem"]).Key = def; modelPlaceOrder.updateStuff(); return(true); }, ((Pair <ThingDef, IngredientCount>)f.pageScope["selectItem"]).Value.filter.AllowedThingDefs)); }), GameFont.Small, 200f)) .AddChild(new LabelRenderer((f => { Pair <ThingDef, IngredientCount> p = ((Pair <ThingDef, IngredientCount>)((IterationItem)f.pageScope["curItem"]).curItem); return(p.Value.CountRequiredOfFor(p.Key, modelPlaceOrder.recipe).ToString()); }), 100f, GameFont.Small, UnityEngine.TextAnchor.MiddleRight)) .AddChild(new LabelRenderer((f => modelPlaceOrder.stockCount(((Pair <ThingDef, IngredientCount>)((IterationItem)f.pageScope["curItem"]).curItem).Key).ToString()), 100f, GameFont.Small, UnityEngine.TextAnchor.MiddleRight)))) .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Quality", 100f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)) .AddChild(new LabelRenderer("Material", 150f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)) .AddChild(new LabelRenderer("Product", 150f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter))) .AddChild(new ColumnLayoutRenderer() .AddChild(new ListRenderer(modelPlaceOrder.products, 400f + QOLMod.VerticalScrollbarWidth(), QOLMod.LineHeight(GameFont.Small) * 5) .AddChild(new HideRenderer(f => !((ProductConfig)((IterationItem)f.pageScope["curItem"]).curItem).HasQuality(), new ButtonTextRenderer(f => ((ProductConfig)((IterationItem)f.pageScope["curItem"]).curItem).quality.GetLabel(), (f => { f.pageScope["selectItem"] = ((IterationItem)f.pageScope["curItem"]).curItem; Find.WindowStack.Add(new Dialog_Select <QualityCategory>(q => { ((ProductConfig)f.pageScope["selectItem"]).quality = q; modelPlaceOrder.updateStuff(); return(true); }, modelPlaceOrder.allowedQualityCategories, d => Enum.GetName(typeof(QualityCategory), d))); }), GameFont.Small, 100f))) .AddChild(new LabelRenderer(f => { ThingDef stuff = ((ProductConfig)((IterationItem)f.pageScope["curItem"]).curItem).stuff; return(stuff != null ? stuff.label : ""); }, 150f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)) .AddChild(new LabelRenderer((f => { ProductConfig p = ((ProductConfig)((IterationItem)f.pageScope["curItem"]).curItem); return(p.countClass.thingDef.label + (p.countClass.count > 1 ? "(" + p.countClass.count.ToString() + ")" : "")); }), 150f, GameFont.Small, UnityEngine.TextAnchor.MiddleCenter)))) //Display the currency count from the stock .AddChild(new ColumnLayoutRenderer() .AddChild(new LabelRenderer("Cost", 200f)) .AddChild(new LabelRenderer(f => ((ModelPlaceOrder)f.flowScope["model"]).cost().ToString() + " (" + modelPlaceOrder.stockCount(ThingDefOf.Silver) + ")", 200f))) .AddChild(new ColumnLayoutRenderer() .AddChild(new ButtonTextRenderer("Buy", f => modelPlaceOrder.buy(negotiator), GameFont.Small, 400f))) )); //A Button to place the order Flow flow = new Flow(pages, "menu"); Enum.GetValues(typeof(QualityCategory)); flow.flowScope["model"] = modelPlaceOrder; Find.WindowStack.Add(new Dialog_Flow(flow)); LessonAutoActivator.TeachOpportunity(ConceptDefOf.BuildOrbitalTradeBeacon, OpportunityType.Critical); TutorUtility.DoModalDialogIfNotKnown(ConceptDefOf.TradeGoodsMustBeNearBeacon); }
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))); }