using System.Windows.Forms; using HeuristicLab.Core.Views; using HeuristicLab.MainForm; using System.Collections.Generic; using System.Linq; namespace HeuristicLab.Problems.ProgramSynthesis.Views { [View("Push Expression Selection Editor")] [Content(typeof(IExpressionsConfiguration), true)] public partial class ExpressionSelectionView : ItemView { public ExpressionSelectionView() { InitializeComponent(); InitEvents(); Name = "Push Expression Selection Editor"; } public new IExpressionsConfiguration Content { get { return (IExpressionsConfiguration)base.Content; } set { if (Content != null) Content.EnabledExpressionsChanged -= EnabledExpressionsChanged; base.Content = value; } } protected override void OnReadOnlyChanged() { base.OnReadOnlyChanged(); expressionsTreeView.Enabled = !ReadOnly; } private void InitEvents() { expressionsTreeView.AfterCheck += ExpressionsTreeViewAfterCheck; } private void ExpressionsTreeViewAfterCheck(object sender, TreeViewEventArgs e) { if (e.Action == TreeViewAction.Unknown) return; Content.EnabledExpressionsChanged -= EnabledExpressionsChanged; var stackType = (StackTypes)e.Node.Tag; if (e.Node.Parent == null) { Content.SetStack(stackType, e.Node.Checked); SetStackNodeText(e.Node); foreach (var subNode in e.Node.Nodes.OfType().Where(n => n.Checked != e.Node.Checked)) subNode.Checked = e.Node.Checked; } else { Content.SetExpression(e.Node.Text, e.Node.Checked); SetStackNodeText(e.Node.Parent); // enable/disable stack if no or at least one expression is enabled if ((e.Node.Checked && !e.Node.Parent.Checked) || (!e.Node.Checked && e.Node.Parent.Nodes.OfType().All(n => !n.Checked))) { e.Node.Parent.Checked = e.Node.Checked; } } Content.EnabledExpressionsChanged += EnabledExpressionsChanged; } protected override void OnContentChanged() { expressionsTreeView.Nodes.Clear(); if (Content == null) { return; } Content.EnabledExpressionsChanged += EnabledExpressionsChanged; UpdateNodes(); } private void EnabledExpressionsChanged(object sender, EnabledExpressionsChangedEventArgs e) { if (InvokeRequired) Invoke(new MethodInvoker(UpdateNodes)); else UpdateNodes(); } private void UpdateNodes() { expressionsTreeView.Nodes.Clear(); var treeNodes = GetTreeNodes(Content.EnabledExpressions) .OrderBy(x => x.Text) .ToArray(); expressionsTreeView.Nodes.AddRange(treeNodes); } private IEnumerable GetTreeNodes(IReadOnlyList enabledExpressions) { foreach (var stackType in ExpressionTable.StackTypeToNamesTable.Keys) { if (stackType == StackTypes.None) continue; var stackTreeNode = new TreeNode { Tag = stackType }; var stackExpressions = ExpressionTable.StackTypeToNamesTable[stackType]; var enabledStackExpressions = enabledExpressions.Intersect(stackExpressions).ToList(); SetStackNodeText(stackTreeNode); stackTreeNode.Checked = enabledStackExpressions.Any(); var expressionNodes = stackExpressions .Where(name => { var type = ExpressionTable.NameToTypeTable[name]; var attribute = ExpressionTable.TypeToAttributeTable[type]; return !attribute.IsHidden; }) .OrderBy(name => name) .Select(name => new TreeNode { Text = name, Tag = stackType, Checked = enabledStackExpressions.Contains(name), }).ToArray(); foreach (var node in expressionNodes) { var type = ExpressionTable.NameToTypeTable[node.Text]; var attribute = ExpressionTable.TypeToAttributeTable[type]; node.ToolTipText = attribute.Description; } stackTreeNode.Nodes.AddRange(expressionNodes); yield return stackTreeNode; } } private void SetStackNodeText(TreeNode node) { var stackTypes = (StackTypes)node.Tag; var stackExpressions = ExpressionTable.StackTypeToNamesTable[stackTypes]; var enabledStackExpressions = Content.EnabledExpressions.Intersect(stackExpressions).ToList(); var stackNames = string.Join(", ", stackTypes.ToValues().Select(type => type.ToString()).OrderBy(x => x)); node.Text = string.Format( "{0} ({1}/{2})", stackNames, enabledStackExpressions.Count, stackExpressions.Count); } } }