public static void CreateActorEditingControls(HeaderCommands.Actors.Entry ac, Controls.TableLayoutPanelEx tlpex, Action numberchanged, object tag = null, bool individual = false) { //TODO TODO TODO: more value types, more control types, etc, etc!!! /* No proper actor entry given? */ if (ac == null || ac.Definition == null) { tlpex.Controls.Clear(); return; } /* Get current definition */ Definition def = ac.Definition; /* No definition given? */ if (def == null) return; /* Begin layout creation */ tlpex.SuspendLayout(); tlpex.Controls.Clear(); /* Create description label */ Label desc = new Label() { Text = (ac.InternalName == string.Empty ? ac.Name : string.Format("{0} ({1})", ac.Name, ac.InternalName)), TextAlign = ContentAlignment.MiddleLeft, Dock = DockStyle.Fill }; tlpex.Controls.Add(desc, 0, 0); tlpex.SetColumnSpan(desc, 2); /* Parse items */ for (int i = 0; i < def.Items.Count; i++) { /* Get current item */ Definition.Item item = def.Items[i]; /* UGLY HACK -> for room number in transition actor with individual file mode... */ if (item.Usage == Definition.Item.Usages.NextRoomBack || item.Usage == Definition.Item.Usages.NextRoomFront) item.ControlType = (individual ? typeof(TextBox) : typeof(ComboBox)); /* Get value, create control */ object val = GetValueFromActor(item, ac); object ctrl = Activator.CreateInstance(item.ControlType); /* First ControlType check; ex. is label needed? */ if (item.ControlType == typeof(CheckBox)) { /* Add control alone */ tlpex.Controls.Add(ctrl as Control, 0, (i + 1)); } else { /* Add label and control */ Label lbl = new Label() { Text = string.Format("{0}:", item.Description), TextAlign = ContentAlignment.MiddleLeft, Dock = DockStyle.Fill }; tlpex.Controls.Add(lbl, 0, (i + 1)); tlpex.Controls.Add(ctrl as Control, 1, (i + 1)); } /* Set control properties */ item.ControlType.GetProperty("Dock").SetValue(ctrl, DockStyle.Fill, null); item.ControlType.GetProperty("Tag").SetValue(ctrl, item, null); item.ControlType.GetProperty("Name").SetValue(ctrl, item.Usage.ToString(), null); /* ControlType-specific settings */ if (item.ControlType == typeof(ComboBox)) { /* Set ComboBox */ item.ControlType.GetProperty("DropDownStyle").SetValue(ctrl, ComboBoxStyle.DropDownList, null); item.ControlType.GetProperty("DisplayMember").SetValue(ctrl, "Description", null); if (!individual && (item.Usage == Definition.Item.Usages.NextRoomBack || item.Usage == Definition.Item.Usages.NextRoomFront) && (tag is List<HeaderCommands.Rooms.RoomInfoClass>)) { /* Item usage is room number in transition actor; get room listing from function tag */ item.Options = new List<Definition.Item.Option>(); foreach (HeaderCommands.Rooms.RoomInfoClass ric in (tag as List<HeaderCommands.Rooms.RoomInfoClass>)) item.Options.Add(new Definition.Item.Option() { Description = ric.Description, Value = ric.Number }); } if (item.Options.Count > 0) { item.ControlType.GetProperty("DataSource").SetValue(ctrl, item.Options, null); item.ControlType.GetProperty("SelectedItem").SetValue(ctrl, item.Options.Find(x => x.Value == (Convert.ToUInt64(val) & item.Mask)), null); (ctrl as ComboBox).SelectedIndexChanged += new EventHandler((s, ex) => { SetValueInActor(item, ac, ((Definition.Item.Option)((ComboBox)s).SelectedItem).Value); }); } } else if (item.ControlType == typeof(CheckBox)) { /* Set CheckBox */ item.ControlType.GetProperty("Checked").SetValue(ctrl, Convert.ToBoolean(val), null); item.ControlType.GetProperty("Text").SetValue(ctrl, item.Description, null); tlpex.SetColumnSpan(ctrl as Control, 2); (ctrl as CheckBox).CheckedChanged += new EventHandler((s, ex) => { ChangeBitInActor(item, ac, item.Mask, ((CheckBox)s).Checked); }); } else { /* Fallback */ if (item.ControlType.GetProperty("Text") != null) { string fstr = "{0}"; switch (item.DisplayStyle) { case Definition.Item.DisplayStyles.Hexadecimal: fstr = "0x{0:X}"; break; case Definition.Item.DisplayStyles.Decimal: fstr = "{0:D}"; break; } item.ControlType.GetProperty("Text").SetValue(ctrl, string.Format(fstr, val), null); (ctrl as Control).TextChanged += new EventHandler((s, ex) => { object newval = Activator.CreateInstance(item.ValueType); System.Reflection.MethodInfo mi = item.ValueType.GetMethod("Parse", new Type[] { typeof(string), typeof(System.Globalization.NumberStyles) }); if (mi != null) { /* Determine NumberStyle to use */ System.Globalization.NumberStyles ns = (item.DisplayStyle == Definition.Item.DisplayStyles.Hexadecimal ? System.Globalization.NumberStyles.HexNumber : System.Globalization.NumberStyles.Integer); /* Hex number; is text long enough? */ if (ns == System.Globalization.NumberStyles.HexNumber && ((Control)s).Text.Length < 2) return; /* Get value string, depending on NumberStyle */ string valstr = (ns == System.Globalization.NumberStyles.HexNumber ? ((Control)s).Text.Substring(2) : ((Control)s).Text); /* Proper value string found? */ if (valstr != null && valstr != "") { try { /* Invoke Parse function and get parsed value */ newval = mi.Invoke(newval, new object[] { valstr, ns }); /* Set new value in actor; if usage is ActorNumber, also do callback */ SetValueInActor(item, ac, newval); if (item.Usage == Definition.Item.Usages.ActorNumber && numberchanged != null) numberchanged(); } catch (TargetInvocationException tiex) { if (tiex.InnerException is FormatException) { /* Ignore; happens with ex. malformed hex numbers (i.e. "0xx0") */ } } } } }); } } } /* Done */ tlpex.ResumeLayout(); }