using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core;
///
/// Provides extension methods for nodes.
///
public static class NodeExtension
{
#region Methods
///
/// Estimates a height of a node in the editor.
///
/// The node whose height to estimate.
/// The estimated height in pixels.
public static double EstimateHeight(this INode node)
{
const double PIN_HEIGHT = 26;
const double TITLE_HEIGHT = 46;
int inputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Input)
+ node.PinCollections.Where(x => x.Direction == PinDirection.Input).Sum(x => x.Count() + 1);
int outputPinCount = node.Pins.Count(x => x.Direction == PinDirection.Output)
+ node.PinCollections.Where(x => x.Direction == PinDirection.Output).Sum(x => x.Count() + 1);
return TITLE_HEIGHT + Math.Max(inputPinCount, outputPinCount) * PIN_HEIGHT;
}
///
/// Estimates a width a node in the editor.
///
/// The node whose width to estimate.
/// The estimated width in pixels.
public static double EstimateWidth(this INode node)
{
// DarthAffe 13.09.2022: For now just assume they are all the same size
return 120;
}
///
/// Determines whether the node is part of a loop when the provided pending connecting would be connected.
///
/// The node to check
/// The node to which a connection is pending
/// if there would be a loop; otherwise .
public static bool IsInLoop(this INode node, INode pendingConnection)
{
HashSet checkedNodes = new();
bool CheckNode(INode checkNode, INode? pending)
{
if (checkedNodes.Contains(checkNode)) return false;
checkedNodes.Add(checkNode);
List connectedNodes = checkNode.Pins
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node)
.Concat(checkNode.PinCollections
.Where(x => x.Direction == PinDirection.Input)
.SelectMany(x => x)
.SelectMany(x => x.ConnectedTo)
.Select(x => x.Node))
.Distinct()
.ToList();
if (pending != null)
connectedNodes.Add(pending);
foreach (INode connectedNode in connectedNodes)
{
if (connectedNode == node)
return true;
else if (CheckNode(connectedNode, null))
return true;
}
return false;
}
return CheckNode(node, pendingConnection);
}
#endregion
}