using com.sun.xml.@internal.bind.v2.runtime; using InABox.Core; using InABox.DynamicGrid; using InABox.WPF; using Microsoft.CodeAnalysis.CSharp.Syntax; using PRS.Shared.Events; using PRS.Shared.Grids.EventEditor; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Markup.Localizer; using System.Windows.Media; namespace PRS.Shared; public class EventTriggerContainer : BaseObject where TEvent : IEvent where TDataModel : IEventDataModel { public IEventTriggerParent? Parent { get; set; } public IEventTrigger Trigger { get; set; } public string TriggerType => Trigger.GetType().GetCaption(); public string Description => Trigger.Description; } public class EventTriggerGrid : DynamicItemsListGrid> where TEvent : IEvent where TDataModel : IEventDataModel { public IEnumerable> EventTriggers => Items.Where(x => x.Parent is null).Select(x => x.Trigger); public EventTriggerGrid(IEnumerable> items) { foreach(var item in items) { AddItem(item, null); } } private EventTriggerContainer GetContainer(IEventTrigger item) { return Items.First(x => x.Trigger == item); } private void AddItem(IEventTrigger item, IEventTriggerParent? parent) { Items.Add(new EventTriggerContainer { Trigger = item, Parent = parent }); if(item is IEventTriggerParent parentTrigger) { foreach(var child in parentTrigger.ChildTriggers) { AddItem(child, parentTrigger); } } } protected override IDynamicGridUIComponent CreateUIComponent() { var component = new DynamicGridTreeUIComponent, IEventTrigger?>( x => LoadItem(x).Trigger, x => LoadItem(x).Parent, null, (container, parent) => { if (parent is IEventTriggerParent parentTrigger) { parentTrigger.ChildTriggers.Add(container.Trigger); container.Parent = parentTrigger; } }) { Parent = this, }; component.OnContextMenuOpening += Component_OnContextMenuOpening; return component; } private enum OperatorType { And, Or } private void Component_OnContextMenuOpening(CoreTreeNode?>? node, ContextMenu menu) { if(node is null) { PopulateAddMenu(menu, null, null); } else { var andItem = menu.AddItem("And", null, null); PopulateAddMenu(andItem, node.ID, OperatorType.And); var orItem = menu.AddItem("Or", null, null); PopulateAddMenu(orItem, node.ID, OperatorType.Or); } } protected override void DoReconfigure(DynamicGridOptions options) { base.DoReconfigure(options); options.AddRows = true; options.EditRows = true; options.DeleteRows = true; options.MultiSelect = true; } public override DynamicGridColumns GenerateColumns() { var cols = new DynamicGridColumns>(); cols.Add(x => x.Description); return cols; } private void PopulateAddMenu(ItemsControl menu, IEventTrigger? trigger, OperatorType? op) { var types = EventUtils.GetEventTriggerTypes(typeof(TEvent)); foreach(var type in types) { menu.AddMenuItem(type.GetCaption(), null, (type, trigger, op), MenuAdd_Click); } } private void MenuAdd_Click((Type type, IEventTrigger? trigger, OperatorType? op) tuple) { if (tuple.type.IsGenericType) { tuple.type = tuple.type.MakeGenericType(typeof(TEvent).GenericTypeArguments); } var trigger = (Activator.CreateInstance(tuple.type) as IEventTrigger)!; if (!EventTriggerEditors.EditTrigger(trigger)) { return; } var container = new EventTriggerContainer { Trigger = trigger }; if(tuple.trigger is not null) { // Insert index of 'trigger' into 'parent' int? parentInsertIndex = null; IEventTriggerParent? parent = null; var triggerContainer = GetContainer(tuple.trigger); if(tuple.op == OperatorType.And && triggerContainer.Trigger is AndTrigger andTrigger) { parent = andTrigger; parentInsertIndex = null; } else if(tuple.op == OperatorType.Or && triggerContainer.Trigger is OrTrigger orTrigger) { parent = orTrigger; parentInsertIndex = null; } else if(tuple.op == OperatorType.And && triggerContainer.Parent is AndTrigger andTrigger2) { parent = andTrigger2; parentInsertIndex = triggerContainer.Parent.ChildTriggers.IndexOf(triggerContainer.Trigger) + 1; } else if(tuple.op == OperatorType.Or && triggerContainer.Parent is OrTrigger orTrigger2) { parent = orTrigger2; parentInsertIndex = triggerContainer.Parent.ChildTriggers.IndexOf(triggerContainer.Trigger) + 1; } if(parent is not null) { container.Parent = parent; if (parentInsertIndex.HasValue && parentInsertIndex < parent.ChildTriggers.Count) { parent.ChildTriggers.Insert(parentInsertIndex.Value, trigger); } else { parent.ChildTriggers.Add(trigger); } } else { if(tuple.op == OperatorType.And) { parent = new AndTrigger(); } else if(tuple.op == OperatorType.Or) { parent = new OrTrigger(); } if(parent is not null) { int? itemsInsertIndex = null; var parentContainer = new EventTriggerContainer() { Trigger = parent, Parent = triggerContainer.Parent }; if(triggerContainer.Parent is not null) { var index = triggerContainer.Parent.ChildTriggers.IndexOf(triggerContainer.Trigger); triggerContainer.Parent.ChildTriggers[index] = parent; } else { itemsInsertIndex = Items.IndexOf(triggerContainer); } triggerContainer.Parent = parent; container.Parent = parent; parent.ChildTriggers.Add(triggerContainer.Trigger); parent.ChildTriggers.Add(trigger); if (itemsInsertIndex.HasValue) { Items.Insert(itemsInsertIndex.Value, parentContainer); } else { Items.Add(parentContainer); } } } } Items.Add(container); RebuildItemsList(); Refresh(false, true); DoChanged(); } private void RebuildItemsList() { var triggers = Items.Where(x => x.Parent is null).Select(x => x.Trigger).ToArray(); Items.Clear(); foreach(var item in triggers) { AddItem(item, null); } } private IEnumerable> GetAllChildren(EventTriggerContainer item) { yield return item; if(item.Trigger is IEventTriggerParent parent) { foreach(var childItem in parent.ChildTriggers.SelectMany(x => GetAllChildren(GetContainer(x)))) { yield return childItem; } } } public override void DeleteItems(params CoreRow[] rows) { var toDelete = rows.SelectMany(x => GetAllChildren(LoadItem(x))).ToArray(); foreach(var item in toDelete) { item.Parent?.ChildTriggers.Remove(item.Trigger); Items.Remove(item); } } protected override void DoAdd(bool openEditorOnDirectEdit = false) { var menu = new ContextMenu(); PopulateAddMenu(menu, null, null); menu.IsOpen = true; } protected override void DoEdit() { if (SelectedRows.Length != 1) return; var row = SelectedRows.First(); var item = LoadItem(row); if (EventTriggerEditors.EditTrigger(item.Trigger)) { UpdateRow(row, item); DoChanged(); } } }