private void UpdateNode(TreeNode node) { Array arrayValues; if (!string.IsNullOrEmpty(node.Name)) { switch (node.Name[0]) { case '*': // Node is a folder break; case '#': // Node is a checkbox arrayValues = (Array)GetPropertyValue(node.Parent.Name); string checkImage = "checkbox0"; for (int i = 0; i < arrayValues.Length; i++) { if (arrayValues.GetValue(i).ToString() == node.Name.Substring(1)) { checkImage = "checkbox1"; break; } } node.ImageKey = checkImage; node.SelectedImageKey = checkImage; break; default: // Node is a property if (GetPropertyInfo(node.Name).PropertyType.IsArray) // Property is an array { if (GetTreeViewPropertyAttribute(node.Name).DataSourceType.IsSubclassOf(typeof(ContextMenuExpandable))) { node.Nodes.Clear(); arrayValues = (Array)GetPropertyValue(node.Name); for (int i = 0; i < arrayValues.Length; i++) { TreeNode elementNode = node.Nodes.Add($"#{i}", arrayValues.GetValue(i).ToString()); elementNode.Tag = i; elementNode.ToolTipText = elementNode.Text.Replace(", ", "\r\n- "); } return; // Do not update subnodes } } else { TreeViewPropertyAttribute tvpa = GetTreeViewPropertyAttribute(node.Name); string valueText = GUITools.GetDisplayName(tvpa.DataSourceType, GetPropertyValue(node.Name)); if (tvpa.DataSourceType == typeof(int)) { TreeViewPropertyIntAttribute tvpia = GetPropertyAttribute <TreeViewPropertyIntAttribute>(node.Name); if (tvpia != null) { valueText = tvpia.FormatIntValue((int)GetPropertyValue(node.Name)); } } else if (string.IsNullOrEmpty(valueText) && tvpa.Flags.HasFlag(TreeViewPropertyAttributeFlags.EmptyIsRandom)) { valueText = "Random"; } node.Text = $"{tvpa.DisplayName}: {valueText}"; } break; } } foreach (TreeNode childNode in node.Nodes) { UpdateNode(childNode); } }
private void OnNodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node == null) { return; } EditorTreeView.SelectedNode = e.Node; if (e.Node.Nodes.Count > 0) { if (e.Node.IsExpanded) { e.Node.Collapse(); } else { e.Node.Expand(); } return; } if (string.IsNullOrEmpty(e.Node.Name)) { return; // Node has no name, nothing to do } if (e.Node.Name.StartsWith("*")) { return; // Node is a folder, nothing to do } if (e.Node.Name.StartsWith("#")) // Node is an array element { // Array of enums or DBEntries, treat as a checkbox if (GetTreeViewPropertyAttribute(e.Node.Parent.Name).DataSourceType.IsEnum || GetTreeViewPropertyAttribute(e.Node.Parent.Name).DataSourceType.IsSubclassOf(typeof(DBEntry))) { if (e.Button != MouseButtons.Left) { return; // Only left clicks can toggle checkboxes } string checkImage = (e.Node.ImageKey == "checkbox0") ? "checkbox1" : "checkbox0"; e.Node.ImageKey = checkImage; e.Node.SelectedImageKey = checkImage; object selectedValues = null; PropertyInfo propertyInfo = GetPropertyInfo(e.Node.Parent.Name); Type elementType = propertyInfo.PropertyType.GetElementType(); if (elementType == typeof(string)) { selectedValues = (from TreeNode n in e.Node.Parent.Nodes where n.ImageKey == "checkbox1" select n.Name.Substring(1)).ToArray(); } else if (elementType == typeof(RealismOption)) { selectedValues = (from TreeNode n in e.Node.Parent.Nodes where n.ImageKey == "checkbox1" select(RealismOption) Enum.Parse(elementType, n.Name.Substring(1))).ToArray(); } if (selectedValues != null) { propertyInfo.SetValue(SelectedObject, selectedValues); } UpdateNode(e.Node.Parent); // Update parent because sometimes enabling an option will disable others OnPropertyValueChanged?.Invoke(EditorTreeView, new EventArgs()); } else if (GetTreeViewPropertyAttribute(e.Node.Parent.Name).DataSourceType. IsSubclassOf(typeof(ContextMenuExpandable))) // Array of ContextMenuExpandables { ContextMenu.Items.Clear(); Array arrayValues = (Array)GetPropertyValue(e.Node.Parent.Name); int arrayIndex = (int)e.Node.Tag; ((ContextMenuExpandable)arrayValues.GetValue(arrayIndex)).CreateContextMenu(ContextMenu, OnContextMenuItemClicked); ContextMenu.Items.Add(new ToolStripSeparator()); if (GetTreeViewPropertyAttribute(e.Node.Parent.Name).DataSourceType == typeof(MissionTemplateFlightGroup)) { ContextMenu.Items.Add("Add another flight group").Tag = "*add"; if (e.Node.Parent.Nodes.Count > 1) { ContextMenu.Items.Add("Remove flight group").Tag = "*remove"; } } foreach (ToolStripItem item in ContextMenu.Items) { if ((item is ToolStripMenuItem) && (((ToolStripMenuItem)item).DropDownItems.Count > 0)) { ((ToolStripMenuItem)item).DropDownItemClicked += OnContextMenuItemClicked; } } ContextMenu.Show(EditorTreeView, e.Location); } return; } if (GetPropertyInfo(e.Node.Name).PropertyType.IsArray) { return; } ContextMenu.Items.Clear(); TreeViewPropertyAttribute tvpa = GetTreeViewPropertyAttribute(e.Node.Name); if (tvpa.DataSourceType.IsEnum) { foreach (object enumValue in Enum.GetValues(tvpa.DataSourceType)) { GUITools.GetDisplayStrings(tvpa.DataSourceType, enumValue, out string enumDisplayName, out string enumDescription); ToolStripMenuItem enumMenuItem = new ToolStripMenuItem { Tag = enumValue, Text = enumDisplayName, ToolTipText = enumDescription }; ContextMenu.Items.Add(enumMenuItem); } } else if (tvpa.DataSourceType == typeof(int)) { TreeViewPropertyIntAttribute tvpia = GetPropertyAttribute <TreeViewPropertyIntAttribute>(e.Node.Name); if (tvpia != null) { for (int i = tvpia.IntValueMin; i <= tvpia.IntValueMax; i += tvpia.IntValueIncrement) { ContextMenu.Items.Add(tvpia.FormatIntValue(i)).Tag = i; } } } else if (tvpa.DataSourceType.IsSubclassOf(typeof(DBEntry))) { GUITools.PopulateToolStripMenuWithDBEntries( ContextMenu.Items, tvpa.DataSourceType, OnContextMenuItemClicked, tvpa.Flags.HasFlag(TreeViewPropertyAttributeFlags.EmptyIsRandom)); } ContextMenu.Show(EditorTreeView, e.Location); }